1 /* tc-arm.c -- Assemble for the ARM
2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
3 Free Software Foundation, Inc.
4 Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
5 Modified by David Taylor (dtaylor@armltd.co.uk)
6 Cirrus coprocessor mods by Aldy Hernandez (aldyh@redhat.com)
8 This file is part of GAS, the GNU Assembler.
10 GAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
15 GAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with GAS; see the file COPYING. If not, write to the Free
22 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
28 #include "safe-ctype.h"
30 /* Need TARGET_CPU. */
39 #include "dwarf2dbg.h"
42 /* XXX Set this to 1 after the next binutils release */
43 #define WARN_DEPRECATED 0
45 /* The following bitmasks control CPU extensions: */
46 #define ARM_EXT_V1 0x00000001 /* All processors (core set). */
47 #define ARM_EXT_V2 0x00000002 /* Multiply instructions. */
48 #define ARM_EXT_V2S 0x00000004 /* SWP instructions. */
49 #define ARM_EXT_V3 0x00000008 /* MSR MRS. */
50 #define ARM_EXT_V3M 0x00000010 /* Allow long multiplies. */
51 #define ARM_EXT_V4 0x00000020 /* Allow half word loads. */
52 #define ARM_EXT_V4T 0x00000040 /* Thumb v1. */
53 #define ARM_EXT_V5 0x00000080 /* Allow CLZ, etc. */
54 #define ARM_EXT_V5T 0x00000100 /* Thumb v2. */
55 #define ARM_EXT_V5ExP 0x00000200 /* DSP core set. */
56 #define ARM_EXT_V5E 0x00000400 /* DSP Double transfers. */
57 #define ARM_EXT_V5J 0x00000800 /* Jazelle extension. */
59 /* Co-processor space extensions. */
60 #define ARM_CEXT_XSCALE 0x00800000 /* Allow MIA etc. */
61 #define ARM_CEXT_MAVERICK 0x00400000 /* Use Cirrus/DSP coprocessor. */
62 #define ARM_CEXT_IWMMXT 0x00200000 /* Intel Wireless MMX technology coprocessor. */
64 /* Architectures are the sum of the base and extensions. The ARM ARM (rev E)
65 defines the following: ARMv3, ARMv3M, ARMv4xM, ARMv4, ARMv4TxM, ARMv4T,
66 ARMv5xM, ARMv5, ARMv5TxM, ARMv5T, ARMv5TExP, ARMv5TE. To these we add
67 three more to cover cores prior to ARM6. Finally, there are cores which
68 implement further extensions in the co-processor space. */
69 #define ARM_ARCH_V1 ARM_EXT_V1
70 #define ARM_ARCH_V2 (ARM_ARCH_V1 | ARM_EXT_V2)
71 #define ARM_ARCH_V2S (ARM_ARCH_V2 | ARM_EXT_V2S)
72 #define ARM_ARCH_V3 (ARM_ARCH_V2S | ARM_EXT_V3)
73 #define ARM_ARCH_V3M (ARM_ARCH_V3 | ARM_EXT_V3M)
74 #define ARM_ARCH_V4xM (ARM_ARCH_V3 | ARM_EXT_V4)
75 #define ARM_ARCH_V4 (ARM_ARCH_V3M | ARM_EXT_V4)
76 #define ARM_ARCH_V4TxM (ARM_ARCH_V4xM | ARM_EXT_V4T)
77 #define ARM_ARCH_V4T (ARM_ARCH_V4 | ARM_EXT_V4T)
78 #define ARM_ARCH_V5xM (ARM_ARCH_V4xM | ARM_EXT_V5)
79 #define ARM_ARCH_V5 (ARM_ARCH_V4 | ARM_EXT_V5)
80 #define ARM_ARCH_V5TxM (ARM_ARCH_V5xM | ARM_EXT_V4T | ARM_EXT_V5T)
81 #define ARM_ARCH_V5T (ARM_ARCH_V5 | ARM_EXT_V4T | ARM_EXT_V5T)
82 #define ARM_ARCH_V5TExP (ARM_ARCH_V5T | ARM_EXT_V5ExP)
83 #define ARM_ARCH_V5TE (ARM_ARCH_V5TExP | ARM_EXT_V5E)
84 #define ARM_ARCH_V5TEJ (ARM_ARCH_V5TE | ARM_EXT_V5J)
86 /* Processors with specific extensions in the co-processor space. */
87 #define ARM_ARCH_XSCALE (ARM_ARCH_V5TE | ARM_CEXT_XSCALE)
88 #define ARM_ARCH_IWMMXT (ARM_ARCH_XSCALE | ARM_CEXT_IWMMXT)
90 /* Some useful combinations: */
91 #define ARM_ANY 0x0000ffff /* Any basic core. */
92 #define ARM_ALL 0x00ffffff /* Any core + co-processor */
93 #define CPROC_ANY 0x00ff0000 /* Any co-processor */
94 #define FPU_ANY 0xff000000 /* Note this is ~ARM_ALL. */
97 #define FPU_FPA_EXT_V1 0x80000000 /* Base FPA instruction set. */
98 #define FPU_FPA_EXT_V2 0x40000000 /* LFM/SFM. */
99 #define FPU_VFP_EXT_NONE 0x20000000 /* Use VFP word-ordering. */
100 #define FPU_VFP_EXT_V1xD 0x10000000 /* Base VFP instruction set. */
101 #define FPU_VFP_EXT_V1 0x08000000 /* Double-precision insns. */
102 #define FPU_VFP_EXT_V2 0x04000000 /* ARM10E VFPr1. */
105 #define FPU_ARCH_FPE FPU_FPA_EXT_V1
106 #define FPU_ARCH_FPA (FPU_ARCH_FPE | FPU_FPA_EXT_V2)
108 #define FPU_ARCH_VFP FPU_VFP_EXT_NONE
109 #define FPU_ARCH_VFP_V1xD (FPU_VFP_EXT_V1xD | FPU_VFP_EXT_NONE)
110 #define FPU_ARCH_VFP_V1 (FPU_ARCH_VFP_V1xD | FPU_VFP_EXT_V1)
111 #define FPU_ARCH_VFP_V2 (FPU_ARCH_VFP_V1 | FPU_VFP_EXT_V2)
113 /* Types of processor to assemble for. */
114 #define ARM_1 ARM_ARCH_V1
115 #define ARM_2 ARM_ARCH_V2
116 #define ARM_3 ARM_ARCH_V2S
117 #define ARM_250 ARM_ARCH_V2S
118 #define ARM_6 ARM_ARCH_V3
119 #define ARM_7 ARM_ARCH_V3
120 #define ARM_8 ARM_ARCH_V4
121 #define ARM_9 ARM_ARCH_V4T
122 #define ARM_STRONG ARM_ARCH_V4
123 #define ARM_CPU_MASK 0x0000000f /* XXX? */
126 #if defined __XSCALE__
127 #define CPU_DEFAULT (ARM_ARCH_XSCALE)
129 #if defined __thumb__
130 #define CPU_DEFAULT (ARM_ARCH_V5T)
132 #define CPU_DEFAULT ARM_ANY
138 #define FPU_DEFAULT FPU_ARCH_FPA
143 #define FPU_DEFAULT FPU_ARCH_VFP /* Soft-float, but VFP order. */
145 /* Legacy a.out format. */
146 #define FPU_DEFAULT FPU_ARCH_FPA /* Soft-float, but FPA order. */
150 /* For backwards compatibility we default to the FPA. */
152 #define FPU_DEFAULT FPU_ARCH_FPA
155 #define streq(a, b) (strcmp (a, b) == 0)
156 #define skip_whitespace(str) while (*(str) == ' ') ++(str)
158 static unsigned long cpu_variant
;
159 static int target_oabi
= 0;
161 /* Flags stored in private area of BFD structure. */
162 static int uses_apcs_26
= FALSE
;
163 static int atpcs
= FALSE
;
164 static int support_interwork
= FALSE
;
165 static int uses_apcs_float
= FALSE
;
166 static int pic_code
= FALSE
;
168 /* Variables that we set while parsing command-line options. Once all
169 options have been read we re-process these values to set the real
171 static int legacy_cpu
= -1;
172 static int legacy_fpu
= -1;
174 static int mcpu_cpu_opt
= -1;
175 static int mcpu_fpu_opt
= -1;
176 static int march_cpu_opt
= -1;
177 static int march_fpu_opt
= -1;
178 static int mfpu_opt
= -1;
180 /* This array holds the chars that always start a comment. If the
181 pre-processor is disabled, these aren't very useful. */
182 const char comment_chars
[] = "@";
184 /* This array holds the chars that only start a comment at the beginning of
185 a line. If the line seems to have the form '# 123 filename'
186 .line and .file directives will appear in the pre-processed output. */
187 /* Note that input_file.c hand checks for '#' at the beginning of the
188 first line of the input file. This is because the compiler outputs
189 #NO_APP at the beginning of its output. */
190 /* Also note that comments like this one will always work. */
191 const char line_comment_chars
[] = "#";
193 const char line_separator_chars
[] = ";";
195 /* Chars that can be used to separate mant
196 from exp in floating point numbers. */
197 const char EXP_CHARS
[] = "eE";
199 /* Chars that mean this number is a floating point constant. */
203 const char FLT_CHARS
[] = "rRsSfFdDxXeEpP";
205 /* Prefix characters that indicate the start of an immediate
207 #define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
210 /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
211 symbolS
* GOT_symbol
;
214 /* Size of relocation record. */
215 const int md_reloc_size
= 8;
217 /* 0: assemble for ARM,
218 1: assemble for Thumb,
219 2: assemble for Thumb even though target CPU does not support thumb
221 static int thumb_mode
= 0;
223 typedef struct arm_fix
231 unsigned long instruction
;
235 bfd_reloc_code_real_type type
;
252 struct asm_shift_properties
254 enum asm_shift_index index
;
255 unsigned long bit_field
;
256 unsigned int allows_0
: 1;
257 unsigned int allows_32
: 1;
260 static const struct asm_shift_properties shift_properties
[] =
262 { SHIFT_LSL
, 0, 1, 0},
263 { SHIFT_LSR
, 0x20, 0, 1},
264 { SHIFT_ASR
, 0x40, 0, 1},
265 { SHIFT_ROR
, 0x60, 0, 0},
266 { SHIFT_RRX
, 0x60, 0, 0}
269 struct asm_shift_name
272 const struct asm_shift_properties
* properties
;
275 static const struct asm_shift_name shift_names
[] =
277 { "asl", shift_properties
+ SHIFT_LSL
},
278 { "lsl", shift_properties
+ SHIFT_LSL
},
279 { "lsr", shift_properties
+ SHIFT_LSR
},
280 { "asr", shift_properties
+ SHIFT_ASR
},
281 { "ror", shift_properties
+ SHIFT_ROR
},
282 { "rrx", shift_properties
+ SHIFT_RRX
},
283 { "ASL", shift_properties
+ SHIFT_LSL
},
284 { "LSL", shift_properties
+ SHIFT_LSL
},
285 { "LSR", shift_properties
+ SHIFT_LSR
},
286 { "ASR", shift_properties
+ SHIFT_ASR
},
287 { "ROR", shift_properties
+ SHIFT_ROR
},
288 { "RRX", shift_properties
+ SHIFT_RRX
}
291 #define NO_SHIFT_RESTRICT 1
292 #define SHIFT_RESTRICT 0
294 #define NUM_FLOAT_VALS 8
296 const char * fp_const
[] =
298 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
301 /* Number of littlenums required to hold an extended precision number. */
302 #define MAX_LITTLENUMS 6
304 LITTLENUM_TYPE fp_values
[NUM_FLOAT_VALS
][MAX_LITTLENUMS
];
309 /* Whether a Co-processor load/store operation accepts write-back forms. */
318 #define CP_T_X 0x00008000
319 #define CP_T_Y 0x00400000
320 #define CP_T_Pre 0x01000000
321 #define CP_T_UD 0x00800000
322 #define CP_T_WB 0x00200000
324 #define CONDS_BIT 0x00100000
325 #define LOAD_BIT 0x00100000
327 #define DOUBLE_LOAD_FLAG 0x00000001
331 const char * template;
335 #define COND_ALWAYS 0xe0000000
336 #define COND_MASK 0xf0000000
338 static const struct asm_cond conds
[] =
342 {"cs", 0x20000000}, {"hs", 0x20000000},
343 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
360 const char *template;
365 /* The bit that distnguishes CPSR and SPSR. */
366 #define SPSR_BIT (1 << 22)
368 /* How many bits to shift the PSR_xxx bits up by. */
371 #define PSR_c (1 << 0)
372 #define PSR_x (1 << 1)
373 #define PSR_s (1 << 2)
374 #define PSR_f (1 << 3)
376 static const struct asm_psr psrs
[] =
378 {"CPSR", TRUE
, PSR_c
| PSR_f
},
379 {"CPSR_all", TRUE
, PSR_c
| PSR_f
},
380 {"SPSR", FALSE
, PSR_c
| PSR_f
},
381 {"SPSR_all", FALSE
, PSR_c
| PSR_f
},
382 {"CPSR_flg", TRUE
, PSR_f
},
383 {"CPSR_f", TRUE
, PSR_f
},
384 {"SPSR_flg", FALSE
, PSR_f
},
385 {"SPSR_f", FALSE
, PSR_f
},
386 {"CPSR_c", TRUE
, PSR_c
},
387 {"CPSR_ctl", TRUE
, PSR_c
},
388 {"SPSR_c", FALSE
, PSR_c
},
389 {"SPSR_ctl", FALSE
, PSR_c
},
390 {"CPSR_x", TRUE
, PSR_x
},
391 {"CPSR_s", TRUE
, PSR_s
},
392 {"SPSR_x", FALSE
, PSR_x
},
393 {"SPSR_s", FALSE
, PSR_s
},
394 /* Combinations of flags. */
395 {"CPSR_fs", TRUE
, PSR_f
| PSR_s
},
396 {"CPSR_fx", TRUE
, PSR_f
| PSR_x
},
397 {"CPSR_fc", TRUE
, PSR_f
| PSR_c
},
398 {"CPSR_sf", TRUE
, PSR_s
| PSR_f
},
399 {"CPSR_sx", TRUE
, PSR_s
| PSR_x
},
400 {"CPSR_sc", TRUE
, PSR_s
| PSR_c
},
401 {"CPSR_xf", TRUE
, PSR_x
| PSR_f
},
402 {"CPSR_xs", TRUE
, PSR_x
| PSR_s
},
403 {"CPSR_xc", TRUE
, PSR_x
| PSR_c
},
404 {"CPSR_cf", TRUE
, PSR_c
| PSR_f
},
405 {"CPSR_cs", TRUE
, PSR_c
| PSR_s
},
406 {"CPSR_cx", TRUE
, PSR_c
| PSR_x
},
407 {"CPSR_fsx", TRUE
, PSR_f
| PSR_s
| PSR_x
},
408 {"CPSR_fsc", TRUE
, PSR_f
| PSR_s
| PSR_c
},
409 {"CPSR_fxs", TRUE
, PSR_f
| PSR_x
| PSR_s
},
410 {"CPSR_fxc", TRUE
, PSR_f
| PSR_x
| PSR_c
},
411 {"CPSR_fcs", TRUE
, PSR_f
| PSR_c
| PSR_s
},
412 {"CPSR_fcx", TRUE
, PSR_f
| PSR_c
| PSR_x
},
413 {"CPSR_sfx", TRUE
, PSR_s
| PSR_f
| PSR_x
},
414 {"CPSR_sfc", TRUE
, PSR_s
| PSR_f
| PSR_c
},
415 {"CPSR_sxf", TRUE
, PSR_s
| PSR_x
| PSR_f
},
416 {"CPSR_sxc", TRUE
, PSR_s
| PSR_x
| PSR_c
},
417 {"CPSR_scf", TRUE
, PSR_s
| PSR_c
| PSR_f
},
418 {"CPSR_scx", TRUE
, PSR_s
| PSR_c
| PSR_x
},
419 {"CPSR_xfs", TRUE
, PSR_x
| PSR_f
| PSR_s
},
420 {"CPSR_xfc", TRUE
, PSR_x
| PSR_f
| PSR_c
},
421 {"CPSR_xsf", TRUE
, PSR_x
| PSR_s
| PSR_f
},
422 {"CPSR_xsc", TRUE
, PSR_x
| PSR_s
| PSR_c
},
423 {"CPSR_xcf", TRUE
, PSR_x
| PSR_c
| PSR_f
},
424 {"CPSR_xcs", TRUE
, PSR_x
| PSR_c
| PSR_s
},
425 {"CPSR_cfs", TRUE
, PSR_c
| PSR_f
| PSR_s
},
426 {"CPSR_cfx", TRUE
, PSR_c
| PSR_f
| PSR_x
},
427 {"CPSR_csf", TRUE
, PSR_c
| PSR_s
| PSR_f
},
428 {"CPSR_csx", TRUE
, PSR_c
| PSR_s
| PSR_x
},
429 {"CPSR_cxf", TRUE
, PSR_c
| PSR_x
| PSR_f
},
430 {"CPSR_cxs", TRUE
, PSR_c
| PSR_x
| PSR_s
},
431 {"CPSR_fsxc", TRUE
, PSR_f
| PSR_s
| PSR_x
| PSR_c
},
432 {"CPSR_fscx", TRUE
, PSR_f
| PSR_s
| PSR_c
| PSR_x
},
433 {"CPSR_fxsc", TRUE
, PSR_f
| PSR_x
| PSR_s
| PSR_c
},
434 {"CPSR_fxcs", TRUE
, PSR_f
| PSR_x
| PSR_c
| PSR_s
},
435 {"CPSR_fcsx", TRUE
, PSR_f
| PSR_c
| PSR_s
| PSR_x
},
436 {"CPSR_fcxs", TRUE
, PSR_f
| PSR_c
| PSR_x
| PSR_s
},
437 {"CPSR_sfxc", TRUE
, PSR_s
| PSR_f
| PSR_x
| PSR_c
},
438 {"CPSR_sfcx", TRUE
, PSR_s
| PSR_f
| PSR_c
| PSR_x
},
439 {"CPSR_sxfc", TRUE
, PSR_s
| PSR_x
| PSR_f
| PSR_c
},
440 {"CPSR_sxcf", TRUE
, PSR_s
| PSR_x
| PSR_c
| PSR_f
},
441 {"CPSR_scfx", TRUE
, PSR_s
| PSR_c
| PSR_f
| PSR_x
},
442 {"CPSR_scxf", TRUE
, PSR_s
| PSR_c
| PSR_x
| PSR_f
},
443 {"CPSR_xfsc", TRUE
, PSR_x
| PSR_f
| PSR_s
| PSR_c
},
444 {"CPSR_xfcs", TRUE
, PSR_x
| PSR_f
| PSR_c
| PSR_s
},
445 {"CPSR_xsfc", TRUE
, PSR_x
| PSR_s
| PSR_f
| PSR_c
},
446 {"CPSR_xscf", TRUE
, PSR_x
| PSR_s
| PSR_c
| PSR_f
},
447 {"CPSR_xcfs", TRUE
, PSR_x
| PSR_c
| PSR_f
| PSR_s
},
448 {"CPSR_xcsf", TRUE
, PSR_x
| PSR_c
| PSR_s
| PSR_f
},
449 {"CPSR_cfsx", TRUE
, PSR_c
| PSR_f
| PSR_s
| PSR_x
},
450 {"CPSR_cfxs", TRUE
, PSR_c
| PSR_f
| PSR_x
| PSR_s
},
451 {"CPSR_csfx", TRUE
, PSR_c
| PSR_s
| PSR_f
| PSR_x
},
452 {"CPSR_csxf", TRUE
, PSR_c
| PSR_s
| PSR_x
| PSR_f
},
453 {"CPSR_cxfs", TRUE
, PSR_c
| PSR_x
| PSR_f
| PSR_s
},
454 {"CPSR_cxsf", TRUE
, PSR_c
| PSR_x
| PSR_s
| PSR_f
},
455 {"SPSR_fs", FALSE
, PSR_f
| PSR_s
},
456 {"SPSR_fx", FALSE
, PSR_f
| PSR_x
},
457 {"SPSR_fc", FALSE
, PSR_f
| PSR_c
},
458 {"SPSR_sf", FALSE
, PSR_s
| PSR_f
},
459 {"SPSR_sx", FALSE
, PSR_s
| PSR_x
},
460 {"SPSR_sc", FALSE
, PSR_s
| PSR_c
},
461 {"SPSR_xf", FALSE
, PSR_x
| PSR_f
},
462 {"SPSR_xs", FALSE
, PSR_x
| PSR_s
},
463 {"SPSR_xc", FALSE
, PSR_x
| PSR_c
},
464 {"SPSR_cf", FALSE
, PSR_c
| PSR_f
},
465 {"SPSR_cs", FALSE
, PSR_c
| PSR_s
},
466 {"SPSR_cx", FALSE
, PSR_c
| PSR_x
},
467 {"SPSR_fsx", FALSE
, PSR_f
| PSR_s
| PSR_x
},
468 {"SPSR_fsc", FALSE
, PSR_f
| PSR_s
| PSR_c
},
469 {"SPSR_fxs", FALSE
, PSR_f
| PSR_x
| PSR_s
},
470 {"SPSR_fxc", FALSE
, PSR_f
| PSR_x
| PSR_c
},
471 {"SPSR_fcs", FALSE
, PSR_f
| PSR_c
| PSR_s
},
472 {"SPSR_fcx", FALSE
, PSR_f
| PSR_c
| PSR_x
},
473 {"SPSR_sfx", FALSE
, PSR_s
| PSR_f
| PSR_x
},
474 {"SPSR_sfc", FALSE
, PSR_s
| PSR_f
| PSR_c
},
475 {"SPSR_sxf", FALSE
, PSR_s
| PSR_x
| PSR_f
},
476 {"SPSR_sxc", FALSE
, PSR_s
| PSR_x
| PSR_c
},
477 {"SPSR_scf", FALSE
, PSR_s
| PSR_c
| PSR_f
},
478 {"SPSR_scx", FALSE
, PSR_s
| PSR_c
| PSR_x
},
479 {"SPSR_xfs", FALSE
, PSR_x
| PSR_f
| PSR_s
},
480 {"SPSR_xfc", FALSE
, PSR_x
| PSR_f
| PSR_c
},
481 {"SPSR_xsf", FALSE
, PSR_x
| PSR_s
| PSR_f
},
482 {"SPSR_xsc", FALSE
, PSR_x
| PSR_s
| PSR_c
},
483 {"SPSR_xcf", FALSE
, PSR_x
| PSR_c
| PSR_f
},
484 {"SPSR_xcs", FALSE
, PSR_x
| PSR_c
| PSR_s
},
485 {"SPSR_cfs", FALSE
, PSR_c
| PSR_f
| PSR_s
},
486 {"SPSR_cfx", FALSE
, PSR_c
| PSR_f
| PSR_x
},
487 {"SPSR_csf", FALSE
, PSR_c
| PSR_s
| PSR_f
},
488 {"SPSR_csx", FALSE
, PSR_c
| PSR_s
| PSR_x
},
489 {"SPSR_cxf", FALSE
, PSR_c
| PSR_x
| PSR_f
},
490 {"SPSR_cxs", FALSE
, PSR_c
| PSR_x
| PSR_s
},
491 {"SPSR_fsxc", FALSE
, PSR_f
| PSR_s
| PSR_x
| PSR_c
},
492 {"SPSR_fscx", FALSE
, PSR_f
| PSR_s
| PSR_c
| PSR_x
},
493 {"SPSR_fxsc", FALSE
, PSR_f
| PSR_x
| PSR_s
| PSR_c
},
494 {"SPSR_fxcs", FALSE
, PSR_f
| PSR_x
| PSR_c
| PSR_s
},
495 {"SPSR_fcsx", FALSE
, PSR_f
| PSR_c
| PSR_s
| PSR_x
},
496 {"SPSR_fcxs", FALSE
, PSR_f
| PSR_c
| PSR_x
| PSR_s
},
497 {"SPSR_sfxc", FALSE
, PSR_s
| PSR_f
| PSR_x
| PSR_c
},
498 {"SPSR_sfcx", FALSE
, PSR_s
| PSR_f
| PSR_c
| PSR_x
},
499 {"SPSR_sxfc", FALSE
, PSR_s
| PSR_x
| PSR_f
| PSR_c
},
500 {"SPSR_sxcf", FALSE
, PSR_s
| PSR_x
| PSR_c
| PSR_f
},
501 {"SPSR_scfx", FALSE
, PSR_s
| PSR_c
| PSR_f
| PSR_x
},
502 {"SPSR_scxf", FALSE
, PSR_s
| PSR_c
| PSR_x
| PSR_f
},
503 {"SPSR_xfsc", FALSE
, PSR_x
| PSR_f
| PSR_s
| PSR_c
},
504 {"SPSR_xfcs", FALSE
, PSR_x
| PSR_f
| PSR_c
| PSR_s
},
505 {"SPSR_xsfc", FALSE
, PSR_x
| PSR_s
| PSR_f
| PSR_c
},
506 {"SPSR_xscf", FALSE
, PSR_x
| PSR_s
| PSR_c
| PSR_f
},
507 {"SPSR_xcfs", FALSE
, PSR_x
| PSR_c
| PSR_f
| PSR_s
},
508 {"SPSR_xcsf", FALSE
, PSR_x
| PSR_c
| PSR_s
| PSR_f
},
509 {"SPSR_cfsx", FALSE
, PSR_c
| PSR_f
| PSR_s
| PSR_x
},
510 {"SPSR_cfxs", FALSE
, PSR_c
| PSR_f
| PSR_x
| PSR_s
},
511 {"SPSR_csfx", FALSE
, PSR_c
| PSR_s
| PSR_f
| PSR_x
},
512 {"SPSR_csxf", FALSE
, PSR_c
| PSR_s
| PSR_x
| PSR_f
},
513 {"SPSR_cxfs", FALSE
, PSR_c
| PSR_x
| PSR_f
| PSR_s
},
514 {"SPSR_cxsf", FALSE
, PSR_c
| PSR_x
| PSR_s
| PSR_f
},
521 IWMMXT_REG_WR_OR_WC
= 2,
525 enum iwmmxt_insn_type
548 VFP_REG_Dd
, VFP_REG_Dm
, VFP_REG_Dn
553 VFP_REG_Sd
, VFP_REG_Sm
, VFP_REG_Sn
558 VFP_LDSTMIA
, VFP_LDSTMDB
, VFP_LDSTMIAX
, VFP_LDSTMDBX
561 /* VFP system registers. */
568 static const struct vfp_reg vfp_regs
[] =
570 {"fpsid", 0x00000000},
571 {"FPSID", 0x00000000},
572 {"fpscr", 0x00010000},
573 {"FPSCR", 0x00010000},
574 {"fpexc", 0x00080000},
575 {"FPEXC", 0x00080000}
578 /* Structure for a hash table entry for a register. */
585 /* Some well known registers that we refer to directly elsewhere. */
590 #define wr_register(reg) ((reg ^ WR_PREFIX) >= 0 && (reg ^ WR_PREFIX) <= 15)
591 #define wc_register(reg) ((reg ^ WC_PREFIX) >= 0 && (reg ^ WC_PREFIX) <= 15)
592 #define wcg_register(reg) ((reg ^ WC_PREFIX) >= 8 && (reg ^ WC_PREFIX) <= 11)
594 /* These are the standard names. Users can add aliases with .req. */
595 /* Integer Register Numbers. */
596 static const struct reg_entry rn_table
[] =
598 {"r0", 0}, {"r1", 1}, {"r2", 2}, {"r3", 3},
599 {"r4", 4}, {"r5", 5}, {"r6", 6}, {"r7", 7},
600 {"r8", 8}, {"r9", 9}, {"r10", 10}, {"r11", 11},
601 {"r12", 12}, {"r13", REG_SP
}, {"r14", REG_LR
}, {"r15", REG_PC
},
602 /* ATPCS Synonyms. */
603 {"a1", 0}, {"a2", 1}, {"a3", 2}, {"a4", 3},
604 {"v1", 4}, {"v2", 5}, {"v3", 6}, {"v4", 7},
605 {"v5", 8}, {"v6", 9}, {"v7", 10}, {"v8", 11},
606 /* Well-known aliases. */
608 {"sb", 9}, {"sl", 10}, {"fp", 11},
609 {"ip", 12}, {"sp", REG_SP
}, {"lr", REG_LR
}, {"pc", REG_PC
},
613 #define WR_PREFIX 0x200
614 #define WC_PREFIX 0x400
616 static const struct reg_entry iwmmxt_table
[] =
618 /* Intel Wireless MMX technology register names. */
619 { "wr0", 0x0 | WR_PREFIX
}, {"wr1", 0x1 | WR_PREFIX
},
620 { "wr2", 0x2 | WR_PREFIX
}, {"wr3", 0x3 | WR_PREFIX
},
621 { "wr4", 0x4 | WR_PREFIX
}, {"wr5", 0x5 | WR_PREFIX
},
622 { "wr6", 0x6 | WR_PREFIX
}, {"wr7", 0x7 | WR_PREFIX
},
623 { "wr8", 0x8 | WR_PREFIX
}, {"wr9", 0x9 | WR_PREFIX
},
624 { "wr10", 0xa | WR_PREFIX
}, {"wr11", 0xb | WR_PREFIX
},
625 { "wr12", 0xc | WR_PREFIX
}, {"wr13", 0xd | WR_PREFIX
},
626 { "wr14", 0xe | WR_PREFIX
}, {"wr15", 0xf | WR_PREFIX
},
627 { "wcid", 0x0 | WC_PREFIX
}, {"wcon", 0x1 | WC_PREFIX
},
628 {"wcssf", 0x2 | WC_PREFIX
}, {"wcasf", 0x3 | WC_PREFIX
},
629 {"wcgr0", 0x8 | WC_PREFIX
}, {"wcgr1", 0x9 | WC_PREFIX
},
630 {"wcgr2", 0xa | WC_PREFIX
}, {"wcgr3", 0xb | WC_PREFIX
},
632 { "wR0", 0x0 | WR_PREFIX
}, {"wR1", 0x1 | WR_PREFIX
},
633 { "wR2", 0x2 | WR_PREFIX
}, {"wR3", 0x3 | WR_PREFIX
},
634 { "wR4", 0x4 | WR_PREFIX
}, {"wR5", 0x5 | WR_PREFIX
},
635 { "wR6", 0x6 | WR_PREFIX
}, {"wR7", 0x7 | WR_PREFIX
},
636 { "wR8", 0x8 | WR_PREFIX
}, {"wR9", 0x9 | WR_PREFIX
},
637 { "wR10", 0xa | WR_PREFIX
}, {"wR11", 0xb | WR_PREFIX
},
638 { "wR12", 0xc | WR_PREFIX
}, {"wR13", 0xd | WR_PREFIX
},
639 { "wR14", 0xe | WR_PREFIX
}, {"wR15", 0xf | WR_PREFIX
},
640 { "wCID", 0x0 | WC_PREFIX
}, {"wCon", 0x1 | WC_PREFIX
},
641 {"wCSSF", 0x2 | WC_PREFIX
}, {"wCASF", 0x3 | WC_PREFIX
},
642 {"wCGR0", 0x8 | WC_PREFIX
}, {"wCGR1", 0x9 | WC_PREFIX
},
643 {"wCGR2", 0xa | WC_PREFIX
}, {"wCGR3", 0xb | WC_PREFIX
},
647 /* Co-processor Numbers. */
648 static const struct reg_entry cp_table
[] =
650 {"p0", 0}, {"p1", 1}, {"p2", 2}, {"p3", 3},
651 {"p4", 4}, {"p5", 5}, {"p6", 6}, {"p7", 7},
652 {"p8", 8}, {"p9", 9}, {"p10", 10}, {"p11", 11},
653 {"p12", 12}, {"p13", 13}, {"p14", 14}, {"p15", 15},
657 /* Co-processor Register Numbers. */
658 static const struct reg_entry cn_table
[] =
660 {"c0", 0}, {"c1", 1}, {"c2", 2}, {"c3", 3},
661 {"c4", 4}, {"c5", 5}, {"c6", 6}, {"c7", 7},
662 {"c8", 8}, {"c9", 9}, {"c10", 10}, {"c11", 11},
663 {"c12", 12}, {"c13", 13}, {"c14", 14}, {"c15", 15},
664 /* Not really valid, but kept for back-wards compatibility. */
665 {"cr0", 0}, {"cr1", 1}, {"cr2", 2}, {"cr3", 3},
666 {"cr4", 4}, {"cr5", 5}, {"cr6", 6}, {"cr7", 7},
667 {"cr8", 8}, {"cr9", 9}, {"cr10", 10}, {"cr11", 11},
668 {"cr12", 12}, {"cr13", 13}, {"cr14", 14}, {"cr15", 15},
673 static const struct reg_entry fn_table
[] =
675 {"f0", 0}, {"f1", 1}, {"f2", 2}, {"f3", 3},
676 {"f4", 4}, {"f5", 5}, {"f6", 6}, {"f7", 7},
680 /* VFP SP Registers. */
681 static const struct reg_entry sn_table
[] =
683 {"s0", 0}, {"s1", 1}, {"s2", 2}, {"s3", 3},
684 {"s4", 4}, {"s5", 5}, {"s6", 6}, {"s7", 7},
685 {"s8", 8}, {"s9", 9}, {"s10", 10}, {"s11", 11},
686 {"s12", 12}, {"s13", 13}, {"s14", 14}, {"s15", 15},
687 {"s16", 16}, {"s17", 17}, {"s18", 18}, {"s19", 19},
688 {"s20", 20}, {"s21", 21}, {"s22", 22}, {"s23", 23},
689 {"s24", 24}, {"s25", 25}, {"s26", 26}, {"s27", 27},
690 {"s28", 28}, {"s29", 29}, {"s30", 30}, {"s31", 31},
694 /* VFP DP Registers. */
695 static const struct reg_entry dn_table
[] =
697 {"d0", 0}, {"d1", 1}, {"d2", 2}, {"d3", 3},
698 {"d4", 4}, {"d5", 5}, {"d6", 6}, {"d7", 7},
699 {"d8", 8}, {"d9", 9}, {"d10", 10}, {"d11", 11},
700 {"d12", 12}, {"d13", 13}, {"d14", 14}, {"d15", 15},
704 /* Maverick DSP coprocessor registers. */
705 static const struct reg_entry mav_mvf_table
[] =
707 {"mvf0", 0}, {"mvf1", 1}, {"mvf2", 2}, {"mvf3", 3},
708 {"mvf4", 4}, {"mvf5", 5}, {"mvf6", 6}, {"mvf7", 7},
709 {"mvf8", 8}, {"mvf9", 9}, {"mvf10", 10}, {"mvf11", 11},
710 {"mvf12", 12}, {"mvf13", 13}, {"mvf14", 14}, {"mvf15", 15},
714 static const struct reg_entry mav_mvd_table
[] =
716 {"mvd0", 0}, {"mvd1", 1}, {"mvd2", 2}, {"mvd3", 3},
717 {"mvd4", 4}, {"mvd5", 5}, {"mvd6", 6}, {"mvd7", 7},
718 {"mvd8", 8}, {"mvd9", 9}, {"mvd10", 10}, {"mvd11", 11},
719 {"mvd12", 12}, {"mvd13", 13}, {"mvd14", 14}, {"mvd15", 15},
723 static const struct reg_entry mav_mvfx_table
[] =
725 {"mvfx0", 0}, {"mvfx1", 1}, {"mvfx2", 2}, {"mvfx3", 3},
726 {"mvfx4", 4}, {"mvfx5", 5}, {"mvfx6", 6}, {"mvfx7", 7},
727 {"mvfx8", 8}, {"mvfx9", 9}, {"mvfx10", 10}, {"mvfx11", 11},
728 {"mvfx12", 12}, {"mvfx13", 13}, {"mvfx14", 14}, {"mvfx15", 15},
732 static const struct reg_entry mav_mvdx_table
[] =
734 {"mvdx0", 0}, {"mvdx1", 1}, {"mvdx2", 2}, {"mvdx3", 3},
735 {"mvdx4", 4}, {"mvdx5", 5}, {"mvdx6", 6}, {"mvdx7", 7},
736 {"mvdx8", 8}, {"mvdx9", 9}, {"mvdx10", 10}, {"mvdx11", 11},
737 {"mvdx12", 12}, {"mvdx13", 13}, {"mvdx14", 14}, {"mvdx15", 15},
741 static const struct reg_entry mav_mvax_table
[] =
743 {"mvax0", 0}, {"mvax1", 1}, {"mvax2", 2}, {"mvax3", 3},
747 static const struct reg_entry mav_dspsc_table
[] =
755 const struct reg_entry
*names
;
757 struct hash_control
*htab
;
758 const char *expected
;
761 struct reg_map all_reg_maps
[] =
763 {rn_table
, 15, NULL
, N_("ARM register expected")},
764 {cp_table
, 15, NULL
, N_("bad or missing co-processor number")},
765 {cn_table
, 15, NULL
, N_("co-processor register expected")},
766 {fn_table
, 7, NULL
, N_("FPA register expected")},
767 {sn_table
, 31, NULL
, N_("VFP single precision register expected")},
768 {dn_table
, 15, NULL
, N_("VFP double precision register expected")},
769 {mav_mvf_table
, 15, NULL
, N_("Maverick MVF register expected")},
770 {mav_mvd_table
, 15, NULL
, N_("Maverick MVD register expected")},
771 {mav_mvfx_table
, 15, NULL
, N_("Maverick MVFX register expected")},
772 {mav_mvdx_table
, 15, NULL
, N_("Maverick MVFX register expected")},
773 {mav_mvax_table
, 3, NULL
, N_("Maverick MVAX register expected")},
774 {mav_dspsc_table
, 0, NULL
, N_("Maverick DSPSC register expected")},
775 {iwmmxt_table
, 23, NULL
, N_("Intel Wireless MMX technology register expected")},
778 /* Enumeration matching entries in table above. */
782 #define REG_TYPE_FIRST REG_TYPE_RN
794 REG_TYPE_IWMMXT
= 12,
799 /* Functions called by parser. */
800 /* ARM instructions. */
801 static void do_arit
PARAMS ((char *));
802 static void do_cmp
PARAMS ((char *));
803 static void do_mov
PARAMS ((char *));
804 static void do_ldst
PARAMS ((char *));
805 static void do_ldstt
PARAMS ((char *));
806 static void do_ldmstm
PARAMS ((char *));
807 static void do_branch
PARAMS ((char *));
808 static void do_swi
PARAMS ((char *));
810 /* Pseudo Op codes. */
811 static void do_adr
PARAMS ((char *));
812 static void do_adrl
PARAMS ((char *));
813 static void do_empty
PARAMS ((char *));
816 static void do_mul
PARAMS ((char *));
817 static void do_mla
PARAMS ((char *));
820 static void do_swap
PARAMS ((char *));
823 static void do_msr
PARAMS ((char *));
824 static void do_mrs
PARAMS ((char *));
827 static void do_mull
PARAMS ((char *));
830 static void do_ldstv4
PARAMS ((char *));
833 static void do_bx
PARAMS ((char *));
836 static void do_blx
PARAMS ((char *));
837 static void do_bkpt
PARAMS ((char *));
838 static void do_clz
PARAMS ((char *));
839 static void do_lstc2
PARAMS ((char *));
840 static void do_cdp2
PARAMS ((char *));
841 static void do_co_reg2
PARAMS ((char *));
844 static void do_smla
PARAMS ((char *));
845 static void do_smlal
PARAMS ((char *));
846 static void do_smul
PARAMS ((char *));
847 static void do_qadd
PARAMS ((char *));
850 static void do_pld
PARAMS ((char *));
851 static void do_ldrd
PARAMS ((char *));
852 static void do_co_reg2c
PARAMS ((char *));
855 static void do_bxj
PARAMS ((char *));
857 /* Coprocessor Instructions. */
858 static void do_cdp
PARAMS ((char *));
859 static void do_lstc
PARAMS ((char *));
860 static void do_co_reg
PARAMS ((char *));
862 /* FPA instructions. */
863 static void do_fpa_ctrl
PARAMS ((char *));
864 static void do_fpa_ldst
PARAMS ((char *));
865 static void do_fpa_ldmstm
PARAMS ((char *));
866 static void do_fpa_dyadic
PARAMS ((char *));
867 static void do_fpa_monadic
PARAMS ((char *));
868 static void do_fpa_cmp
PARAMS ((char *));
869 static void do_fpa_from_reg
PARAMS ((char *));
870 static void do_fpa_to_reg
PARAMS ((char *));
872 /* VFP instructions. */
873 static void do_vfp_sp_monadic
PARAMS ((char *));
874 static void do_vfp_dp_monadic
PARAMS ((char *));
875 static void do_vfp_sp_dyadic
PARAMS ((char *));
876 static void do_vfp_dp_dyadic
PARAMS ((char *));
877 static void do_vfp_reg_from_sp
PARAMS ((char *));
878 static void do_vfp_sp_from_reg
PARAMS ((char *));
879 static void do_vfp_sp_reg2
PARAMS ((char *));
880 static void do_vfp_reg_from_dp
PARAMS ((char *));
881 static void do_vfp_reg2_from_dp
PARAMS ((char *));
882 static void do_vfp_dp_from_reg
PARAMS ((char *));
883 static void do_vfp_dp_from_reg2
PARAMS ((char *));
884 static void do_vfp_reg_from_ctrl
PARAMS ((char *));
885 static void do_vfp_ctrl_from_reg
PARAMS ((char *));
886 static void do_vfp_sp_ldst
PARAMS ((char *));
887 static void do_vfp_dp_ldst
PARAMS ((char *));
888 static void do_vfp_sp_ldstmia
PARAMS ((char *));
889 static void do_vfp_sp_ldstmdb
PARAMS ((char *));
890 static void do_vfp_dp_ldstmia
PARAMS ((char *));
891 static void do_vfp_dp_ldstmdb
PARAMS ((char *));
892 static void do_vfp_xp_ldstmia
PARAMS ((char *));
893 static void do_vfp_xp_ldstmdb
PARAMS ((char *));
894 static void do_vfp_sp_compare_z
PARAMS ((char *));
895 static void do_vfp_dp_compare_z
PARAMS ((char *));
896 static void do_vfp_dp_sp_cvt
PARAMS ((char *));
897 static void do_vfp_sp_dp_cvt
PARAMS ((char *));
900 static void do_xsc_mia
PARAMS ((char *));
901 static void do_xsc_mar
PARAMS ((char *));
902 static void do_xsc_mra
PARAMS ((char *));
905 static void do_mav_binops
PARAMS ((char *, int, enum arm_reg_type
,
907 static void do_mav_binops_1a
PARAMS ((char *));
908 static void do_mav_binops_1b
PARAMS ((char *));
909 static void do_mav_binops_1c
PARAMS ((char *));
910 static void do_mav_binops_1d
PARAMS ((char *));
911 static void do_mav_binops_1e
PARAMS ((char *));
912 static void do_mav_binops_1f
PARAMS ((char *));
913 static void do_mav_binops_1g
PARAMS ((char *));
914 static void do_mav_binops_1h
PARAMS ((char *));
915 static void do_mav_binops_1i
PARAMS ((char *));
916 static void do_mav_binops_1j
PARAMS ((char *));
917 static void do_mav_binops_1k
PARAMS ((char *));
918 static void do_mav_binops_1l
PARAMS ((char *));
919 static void do_mav_binops_1m
PARAMS ((char *));
920 static void do_mav_binops_1n
PARAMS ((char *));
921 static void do_mav_binops_1o
PARAMS ((char *));
922 static void do_mav_binops_2a
PARAMS ((char *));
923 static void do_mav_binops_2b
PARAMS ((char *));
924 static void do_mav_binops_2c
PARAMS ((char *));
925 static void do_mav_binops_3a
PARAMS ((char *));
926 static void do_mav_binops_3b
PARAMS ((char *));
927 static void do_mav_binops_3c
PARAMS ((char *));
928 static void do_mav_binops_3d
PARAMS ((char *));
929 static void do_mav_triple
PARAMS ((char *, int, enum arm_reg_type
,
932 static void do_mav_triple_4a
PARAMS ((char *));
933 static void do_mav_triple_4b
PARAMS ((char *));
934 static void do_mav_triple_5a
PARAMS ((char *));
935 static void do_mav_triple_5b
PARAMS ((char *));
936 static void do_mav_triple_5c
PARAMS ((char *));
937 static void do_mav_triple_5d
PARAMS ((char *));
938 static void do_mav_triple_5e
PARAMS ((char *));
939 static void do_mav_triple_5f
PARAMS ((char *));
940 static void do_mav_triple_5g
PARAMS ((char *));
941 static void do_mav_triple_5h
PARAMS ((char *));
942 static void do_mav_quad
PARAMS ((char *, int, enum arm_reg_type
,
946 static void do_mav_quad_6a
PARAMS ((char *));
947 static void do_mav_quad_6b
PARAMS ((char *));
948 static void do_mav_dspsc_1
PARAMS ((char *));
949 static void do_mav_dspsc_2
PARAMS ((char *));
950 static void do_mav_shift
PARAMS ((char *, enum arm_reg_type
,
952 static void do_mav_shift_1
PARAMS ((char *));
953 static void do_mav_shift_2
PARAMS ((char *));
954 static void do_mav_ldst
PARAMS ((char *, enum arm_reg_type
));
955 static void do_mav_ldst_1
PARAMS ((char *));
956 static void do_mav_ldst_2
PARAMS ((char *));
957 static void do_mav_ldst_3
PARAMS ((char *));
958 static void do_mav_ldst_4
PARAMS ((char *));
960 static int mav_reg_required_here
PARAMS ((char **, int,
962 static int mav_parse_offset
PARAMS ((char **, int *));
964 static void fix_new_arm
PARAMS ((fragS
*, int, short, expressionS
*,
966 static int arm_reg_parse
PARAMS ((char **, struct hash_control
*));
967 static enum arm_reg_type arm_reg_parse_any
PARAMS ((char *));
968 static const struct asm_psr
* arm_psr_parse
PARAMS ((char **));
969 static void symbol_locate
PARAMS ((symbolS
*, const char *, segT
, valueT
,
971 static int add_to_lit_pool
PARAMS ((void));
972 static unsigned validate_immediate
PARAMS ((unsigned));
973 static unsigned validate_immediate_twopart
PARAMS ((unsigned int,
975 static int validate_offset_imm
PARAMS ((unsigned int, int));
976 static void opcode_select
PARAMS ((int));
977 static void end_of_line
PARAMS ((char *));
978 static int reg_required_here
PARAMS ((char **, int));
979 static int psr_required_here
PARAMS ((char **));
980 static int co_proc_number
PARAMS ((char **));
981 static int cp_opc_expr
PARAMS ((char **, int, int));
982 static int cp_reg_required_here
PARAMS ((char **, int));
983 static int fp_reg_required_here
PARAMS ((char **, int));
984 static int vfp_sp_reg_required_here
PARAMS ((char **, enum vfp_sp_reg_pos
));
985 static int vfp_dp_reg_required_here
PARAMS ((char **, enum vfp_dp_reg_pos
));
986 static void vfp_sp_ldstm
PARAMS ((char *, enum vfp_ldstm_type
));
987 static void vfp_dp_ldstm
PARAMS ((char *, enum vfp_ldstm_type
));
988 static long vfp_sp_reg_list
PARAMS ((char **, enum vfp_sp_reg_pos
));
989 static long vfp_dp_reg_list
PARAMS ((char **));
990 static int vfp_psr_required_here
PARAMS ((char **str
));
991 static const struct vfp_reg
*vfp_psr_parse
PARAMS ((char **str
));
992 static int cp_address_offset
PARAMS ((char **));
993 static int cp_address_required_here
PARAMS ((char **, int));
994 static int my_get_float_expression
PARAMS ((char **));
995 static int skip_past_comma
PARAMS ((char **));
996 static int walk_no_bignums
PARAMS ((symbolS
*));
997 static int negate_data_op
PARAMS ((unsigned long *, unsigned long));
998 static int data_op2
PARAMS ((char **));
999 static int fp_op2
PARAMS ((char **));
1000 static long reg_list
PARAMS ((char **));
1001 static void thumb_load_store
PARAMS ((char *, int, int));
1002 static int decode_shift
PARAMS ((char **, int));
1003 static int ldst_extend
PARAMS ((char **));
1004 static int ldst_extend_v4
PARAMS ((char **));
1005 static void thumb_add_sub
PARAMS ((char *, int));
1006 static void insert_reg
PARAMS ((const struct reg_entry
*,
1007 struct hash_control
*));
1008 static void thumb_shift
PARAMS ((char *, int));
1009 static void thumb_mov_compare
PARAMS ((char *, int));
1010 static void build_arm_ops_hsh
PARAMS ((void));
1011 static void set_constant_flonums
PARAMS ((void));
1012 static valueT md_chars_to_number
PARAMS ((char *, int));
1013 static void build_reg_hsh
PARAMS ((struct reg_map
*));
1014 static void insert_reg_alias
PARAMS ((char *, int, struct hash_control
*));
1015 static int create_register_alias
PARAMS ((char *, char *));
1016 static void output_inst
PARAMS ((const char *));
1017 static int accum0_required_here
PARAMS ((char **));
1018 static int ld_mode_required_here
PARAMS ((char **));
1019 static void do_branch25
PARAMS ((char *));
1020 static symbolS
* find_real_start
PARAMS ((symbolS
*));
1022 static bfd_reloc_code_real_type arm_parse_reloc
PARAMS ((void));
1025 static int wreg_required_here
PARAMS ((char **, int, enum wreg_type
));
1026 static void do_iwmmxt_byte_addr
PARAMS ((char *));
1027 static void do_iwmmxt_tandc
PARAMS ((char *));
1028 static void do_iwmmxt_tbcst
PARAMS ((char *));
1029 static void do_iwmmxt_textrc
PARAMS ((char *));
1030 static void do_iwmmxt_textrm
PARAMS ((char *));
1031 static void do_iwmmxt_tinsr
PARAMS ((char *));
1032 static void do_iwmmxt_tmcr
PARAMS ((char *));
1033 static void do_iwmmxt_tmcrr
PARAMS ((char *));
1034 static void do_iwmmxt_tmia
PARAMS ((char *));
1035 static void do_iwmmxt_tmovmsk
PARAMS ((char *));
1036 static void do_iwmmxt_tmrc
PARAMS ((char *));
1037 static void do_iwmmxt_tmrrc
PARAMS ((char *));
1038 static void do_iwmmxt_torc
PARAMS ((char *));
1039 static void do_iwmmxt_waligni
PARAMS ((char *));
1040 static void do_iwmmxt_wmov
PARAMS ((char *));
1041 static void do_iwmmxt_word_addr
PARAMS ((char *));
1042 static void do_iwmmxt_wrwr
PARAMS ((char *));
1043 static void do_iwmmxt_wrwrwcg
PARAMS ((char *));
1044 static void do_iwmmxt_wrwrwr
PARAMS ((char *));
1045 static void do_iwmmxt_wshufh
PARAMS ((char *));
1046 static void do_iwmmxt_wzero
PARAMS ((char *));
1047 static int cp_byte_address_offset
PARAMS ((char **));
1048 static int cp_byte_address_required_here
PARAMS ((char **));
1050 /* ARM instructions take 4bytes in the object file, Thumb instructions
1054 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
1055 #define MAV_MODE1 0x100c
1057 /* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
1058 #define MAV_MODE2 0x0c10
1060 /* "INSN<cond> X,Y" where X:0, Y:bit16. */
1061 #define MAV_MODE3 0x1000
1063 /* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
1064 #define MAV_MODE4 0x0c0010
1066 /* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
1067 #define MAV_MODE5 0x00100c
1069 /* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
1070 #define MAV_MODE6 0x00100c05
1074 /* Basic string to match. */
1075 const char * template;
1077 /* Basic instruction code. */
1078 unsigned long value
;
1080 /* Offset into the template where the condition code (if any) will be.
1081 If zero, then the instruction is never conditional. */
1082 unsigned cond_offset
;
1084 /* Which architecture variant provides this instruction. */
1085 unsigned long variant
;
1087 /* Function to call to parse args. */
1088 void (* parms
) PARAMS ((char *));
1091 static const struct asm_opcode insns
[] =
1093 /* Core ARM Instructions. */
1094 {"and", 0xe0000000, 3, ARM_EXT_V1
, do_arit
},
1095 {"ands", 0xe0100000, 3, ARM_EXT_V1
, do_arit
},
1096 {"eor", 0xe0200000, 3, ARM_EXT_V1
, do_arit
},
1097 {"eors", 0xe0300000, 3, ARM_EXT_V1
, do_arit
},
1098 {"sub", 0xe0400000, 3, ARM_EXT_V1
, do_arit
},
1099 {"subs", 0xe0500000, 3, ARM_EXT_V1
, do_arit
},
1100 {"rsb", 0xe0600000, 3, ARM_EXT_V1
, do_arit
},
1101 {"rsbs", 0xe0700000, 3, ARM_EXT_V1
, do_arit
},
1102 {"add", 0xe0800000, 3, ARM_EXT_V1
, do_arit
},
1103 {"adds", 0xe0900000, 3, ARM_EXT_V1
, do_arit
},
1104 {"adc", 0xe0a00000, 3, ARM_EXT_V1
, do_arit
},
1105 {"adcs", 0xe0b00000, 3, ARM_EXT_V1
, do_arit
},
1106 {"sbc", 0xe0c00000, 3, ARM_EXT_V1
, do_arit
},
1107 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1
, do_arit
},
1108 {"rsc", 0xe0e00000, 3, ARM_EXT_V1
, do_arit
},
1109 {"rscs", 0xe0f00000, 3, ARM_EXT_V1
, do_arit
},
1110 {"orr", 0xe1800000, 3, ARM_EXT_V1
, do_arit
},
1111 {"orrs", 0xe1900000, 3, ARM_EXT_V1
, do_arit
},
1112 {"bic", 0xe1c00000, 3, ARM_EXT_V1
, do_arit
},
1113 {"bics", 0xe1d00000, 3, ARM_EXT_V1
, do_arit
},
1115 {"tst", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
1116 {"tsts", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
1117 {"tstp", 0xe110f000, 3, ARM_EXT_V1
, do_cmp
},
1118 {"teq", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
1119 {"teqs", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
1120 {"teqp", 0xe130f000, 3, ARM_EXT_V1
, do_cmp
},
1121 {"cmp", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
1122 {"cmps", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
1123 {"cmpp", 0xe150f000, 3, ARM_EXT_V1
, do_cmp
},
1124 {"cmn", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
1125 {"cmns", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
1126 {"cmnp", 0xe170f000, 3, ARM_EXT_V1
, do_cmp
},
1128 {"mov", 0xe1a00000, 3, ARM_EXT_V1
, do_mov
},
1129 {"movs", 0xe1b00000, 3, ARM_EXT_V1
, do_mov
},
1130 {"mvn", 0xe1e00000, 3, ARM_EXT_V1
, do_mov
},
1131 {"mvns", 0xe1f00000, 3, ARM_EXT_V1
, do_mov
},
1133 {"ldr", 0xe4100000, 3, ARM_EXT_V1
, do_ldst
},
1134 {"ldrb", 0xe4500000, 3, ARM_EXT_V1
, do_ldst
},
1135 {"ldrt", 0xe4300000, 3, ARM_EXT_V1
, do_ldstt
},
1136 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1
, do_ldstt
},
1137 {"str", 0xe4000000, 3, ARM_EXT_V1
, do_ldst
},
1138 {"strb", 0xe4400000, 3, ARM_EXT_V1
, do_ldst
},
1139 {"strt", 0xe4200000, 3, ARM_EXT_V1
, do_ldstt
},
1140 {"strbt", 0xe4600000, 3, ARM_EXT_V1
, do_ldstt
},
1142 {"stmia", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
1143 {"stmib", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
1144 {"stmda", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
1145 {"stmdb", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
1146 {"stmfd", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
1147 {"stmfa", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
1148 {"stmea", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
1149 {"stmed", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
1151 {"ldmia", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
1152 {"ldmib", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
1153 {"ldmda", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
1154 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
1155 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
1156 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
1157 {"ldmea", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
1158 {"ldmed", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
1160 {"swi", 0xef000000, 3, ARM_EXT_V1
, do_swi
},
1162 /* XXX This is the wrong place to do this. Think multi-arch. */
1163 {"bl", 0xeb000000, 2, ARM_EXT_V1
, do_branch
},
1164 {"b", 0xea000000, 1, ARM_EXT_V1
, do_branch
},
1166 {"bl", 0xebfffffe, 2, ARM_EXT_V1
, do_branch
},
1167 {"b", 0xeafffffe, 1, ARM_EXT_V1
, do_branch
},
1171 {"adr", 0xe28f0000, 3, ARM_EXT_V1
, do_adr
},
1172 {"adrl", 0xe28f0000, 3, ARM_EXT_V1
, do_adrl
},
1173 {"nop", 0xe1a00000, 3, ARM_EXT_V1
, do_empty
},
1175 /* ARM 2 multiplies. */
1176 {"mul", 0xe0000090, 3, ARM_EXT_V2
, do_mul
},
1177 {"muls", 0xe0100090, 3, ARM_EXT_V2
, do_mul
},
1178 {"mla", 0xe0200090, 3, ARM_EXT_V2
, do_mla
},
1179 {"mlas", 0xe0300090, 3, ARM_EXT_V2
, do_mla
},
1181 /* Generic copressor instructions. */
1182 {"cdp", 0xee000000, 3, ARM_EXT_V2
, do_cdp
},
1183 {"ldc", 0xec100000, 3, ARM_EXT_V2
, do_lstc
},
1184 {"ldcl", 0xec500000, 3, ARM_EXT_V2
, do_lstc
},
1185 {"stc", 0xec000000, 3, ARM_EXT_V2
, do_lstc
},
1186 {"stcl", 0xec400000, 3, ARM_EXT_V2
, do_lstc
},
1187 {"mcr", 0xee000010, 3, ARM_EXT_V2
, do_co_reg
},
1188 {"mrc", 0xee100010, 3, ARM_EXT_V2
, do_co_reg
},
1190 /* ARM 3 - swp instructions. */
1191 {"swp", 0xe1000090, 3, ARM_EXT_V2S
, do_swap
},
1192 {"swpb", 0xe1400090, 3, ARM_EXT_V2S
, do_swap
},
1194 /* ARM 6 Status register instructions. */
1195 {"mrs", 0xe10f0000, 3, ARM_EXT_V3
, do_mrs
},
1196 {"msr", 0xe120f000, 3, ARM_EXT_V3
, do_msr
},
1197 /* ScottB: our code uses 0xe128f000 for msr.
1198 NickC: but this is wrong because the bits 16 through 19 are
1199 handled by the PSR_xxx defines above. */
1201 /* ARM 7M long multiplies. */
1202 {"smull", 0xe0c00090, 5, ARM_EXT_V3M
, do_mull
},
1203 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M
, do_mull
},
1204 {"umull", 0xe0800090, 5, ARM_EXT_V3M
, do_mull
},
1205 {"umulls", 0xe0900090, 5, ARM_EXT_V3M
, do_mull
},
1206 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M
, do_mull
},
1207 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M
, do_mull
},
1208 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M
, do_mull
},
1209 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M
, do_mull
},
1211 /* ARM Architecture 4. */
1212 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4
, do_ldstv4
},
1213 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4
, do_ldstv4
},
1214 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4
, do_ldstv4
},
1215 {"strh", 0xe00000b0, 3, ARM_EXT_V4
, do_ldstv4
},
1217 /* ARM Architecture 4T. */
1218 /* Note: bx (and blx) are required on V5, even if the processor does
1219 not support Thumb. */
1220 {"bx", 0xe12fff10, 2, ARM_EXT_V4T
| ARM_EXT_V5
, do_bx
},
1222 /* ARM Architecture 5T. */
1223 /* Note: blx has 2 variants, so the .value is set dynamically.
1224 Only one of the variants has conditional execution. */
1225 {"blx", 0xe0000000, 3, ARM_EXT_V5
, do_blx
},
1226 {"clz", 0xe16f0f10, 3, ARM_EXT_V5
, do_clz
},
1227 {"bkpt", 0xe1200070, 0, ARM_EXT_V5
, do_bkpt
},
1228 {"ldc2", 0xfc100000, 0, ARM_EXT_V5
, do_lstc2
},
1229 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5
, do_lstc2
},
1230 {"stc2", 0xfc000000, 0, ARM_EXT_V5
, do_lstc2
},
1231 {"stc2l", 0xfc400000, 0, ARM_EXT_V5
, do_lstc2
},
1232 {"cdp2", 0xfe000000, 0, ARM_EXT_V5
, do_cdp2
},
1233 {"mcr2", 0xfe000010, 0, ARM_EXT_V5
, do_co_reg2
},
1234 {"mrc2", 0xfe100010, 0, ARM_EXT_V5
, do_co_reg2
},
1236 /* ARM Architecture 5TExP. */
1237 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP
, do_smla
},
1238 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP
, do_smla
},
1239 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP
, do_smla
},
1240 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP
, do_smla
},
1242 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP
, do_smla
},
1243 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP
, do_smla
},
1245 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP
, do_smlal
},
1246 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP
, do_smlal
},
1247 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP
, do_smlal
},
1248 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP
, do_smlal
},
1250 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP
, do_smul
},
1251 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP
, do_smul
},
1252 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP
, do_smul
},
1253 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP
, do_smul
},
1255 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP
, do_smul
},
1256 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP
, do_smul
},
1258 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP
, do_qadd
},
1259 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP
, do_qadd
},
1260 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP
, do_qadd
},
1261 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP
, do_qadd
},
1263 /* ARM Architecture 5TE. */
1264 {"pld", 0xf450f000, 0, ARM_EXT_V5E
, do_pld
},
1265 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E
, do_ldrd
},
1266 {"strd", 0xe00000f0, 3, ARM_EXT_V5E
, do_ldrd
},
1268 {"mcrr", 0xec400000, 4, ARM_EXT_V5E
, do_co_reg2c
},
1269 {"mrrc", 0xec500000, 4, ARM_EXT_V5E
, do_co_reg2c
},
1271 /* ARM Architecture 5TEJ. */
1272 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J
, do_bxj
},
1274 /* Core FPA instruction set (V1). */
1275 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1276 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1277 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1278 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1280 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1281 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1282 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1283 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1285 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1286 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1287 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1288 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1290 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1291 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1292 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1293 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1294 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1295 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1296 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1297 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1298 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1299 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1300 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1301 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1303 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1304 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1305 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1306 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1307 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1308 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1309 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1310 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1311 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1312 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1313 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1314 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1316 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1317 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1318 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1319 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1320 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1321 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1322 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1323 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1324 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1325 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1326 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1327 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1329 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1330 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1331 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1332 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1333 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1334 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1335 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1336 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1337 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1338 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1339 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1340 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1342 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1343 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1344 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1345 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1346 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1347 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1348 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1349 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1350 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1351 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1352 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1353 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1355 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1356 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1357 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1358 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1359 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1360 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1361 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1362 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1363 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1364 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1365 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1366 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1368 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1369 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1370 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1371 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1372 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1373 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1374 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1375 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1376 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1377 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1378 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1379 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1381 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1382 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1383 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1384 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1385 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1386 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1387 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1388 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1389 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1390 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1391 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1392 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1394 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1395 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1396 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1397 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1398 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1399 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1400 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1401 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1402 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1403 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1404 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1405 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1407 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1408 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1409 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1410 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1411 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1412 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1413 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1414 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1415 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1416 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1417 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1418 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1420 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1421 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1422 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1423 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1424 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1425 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1426 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1427 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1428 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1429 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1430 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1431 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1433 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1434 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1435 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1436 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1437 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1438 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1439 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1440 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1441 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1442 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1443 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1444 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1446 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1447 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1448 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1449 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1450 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1451 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1452 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1453 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1454 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1455 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1456 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1457 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1459 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1460 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1461 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1462 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1463 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1464 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1465 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1466 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1467 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1468 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1469 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1470 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1472 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1473 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1474 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1475 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1476 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1477 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1478 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1479 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1480 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1481 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1482 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1483 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1485 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1486 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1487 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1488 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1489 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1490 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1491 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1492 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1493 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1494 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1495 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1496 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1498 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1499 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1500 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1501 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1502 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1503 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1504 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1505 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1506 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1507 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1508 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1509 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1511 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1512 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1513 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1514 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1515 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1516 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1517 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1518 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1519 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1520 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1521 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1522 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1524 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1525 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1526 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1527 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1528 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1529 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1530 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1531 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1532 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1533 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1534 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1535 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1537 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1538 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1539 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1540 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1541 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1542 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1543 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1544 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1545 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1546 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1547 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1548 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1550 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1551 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1552 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1553 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1554 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1555 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1556 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1557 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1558 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1559 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1560 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1561 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1563 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1564 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1565 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1566 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1567 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1568 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1569 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1570 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1571 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1572 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1573 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1574 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1576 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1577 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1578 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1579 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1580 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1581 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1582 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1583 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1584 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1585 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1586 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1587 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1589 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1590 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1591 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1592 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1593 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1594 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1595 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1596 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1597 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1598 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1599 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1600 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1602 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1603 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1604 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1605 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1606 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1607 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1608 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1609 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1610 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1611 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1612 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1613 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1615 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1616 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1617 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1618 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1619 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1620 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1621 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1622 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1623 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1624 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1625 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1626 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1628 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1629 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1630 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1631 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1632 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1633 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1634 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1635 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1636 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1637 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1638 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1639 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1641 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1642 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1643 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1644 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1645 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1646 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1647 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1648 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1649 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1650 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1651 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1652 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1654 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1655 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1656 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1657 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1658 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1659 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1660 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1661 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1662 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1663 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1664 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1665 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1667 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1668 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1669 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1670 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1671 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
1672 not be an optional suffix, but part of the instruction. To be
1673 compatible, we accept either. */
1674 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1675 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1677 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1678 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1679 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1680 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1681 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1682 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1683 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1684 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1685 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1686 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1687 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1688 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1690 /* The implementation of the FIX instruction is broken on some
1691 assemblers, in that it accepts a precision specifier as well as a
1692 rounding specifier, despite the fact that this is meaningless.
1693 To be more compatible, we accept it as well, though of course it
1694 does not set any bits. */
1695 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1696 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1697 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1698 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1699 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1700 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1701 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1702 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1703 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1704 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1705 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1706 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1707 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1709 /* Instructions that were new with the real FPA, call them V2. */
1710 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1711 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1712 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1713 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1714 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1715 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1717 /* VFP V1xD (single precision). */
1718 /* Moves and type conversions. */
1719 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1720 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_reg_from_sp
},
1721 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_from_reg
},
1722 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD
, do_empty
},
1723 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1724 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1725 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1726 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1727 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1728 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1729 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_reg_from_ctrl
},
1730 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_ctrl_from_reg
},
1732 /* Memory operations. */
1733 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldst
},
1734 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldst
},
1735 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1736 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1737 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1738 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1739 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1740 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1741 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1742 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1743 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1744 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1745 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1746 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1747 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1748 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1749 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1750 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1752 /* Monadic operations. */
1753 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1754 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1755 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1757 /* Dyadic operations. */
1758 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1759 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1760 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1761 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1762 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1763 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1764 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1765 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1766 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1769 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1770 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_compare_z
},
1771 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1772 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_compare_z
},
1774 /* VFP V1 (Double precision). */
1775 /* Moves and type conversions. */
1776 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1777 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
1778 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1779 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1
, do_vfp_dp_from_reg
},
1780 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1
, do_vfp_dp_from_reg
},
1781 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1
, do_vfp_reg_from_dp
},
1782 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1
, do_vfp_reg_from_dp
},
1783 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
1784 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
1785 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1786 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1787 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1788 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1790 /* Memory operations. */
1791 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1
, do_vfp_dp_ldst
},
1792 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1
, do_vfp_dp_ldst
},
1793 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1794 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1795 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1796 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1797 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1798 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1799 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1800 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1802 /* Monadic operations. */
1803 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1804 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1805 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1807 /* Dyadic operations. */
1808 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1809 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1810 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1811 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1812 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1813 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1814 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1815 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1816 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1819 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1820 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_compare_z
},
1821 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1822 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1
, do_vfp_dp_compare_z
},
1825 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2
, do_vfp_sp_reg2
},
1826 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2
, do_vfp_sp_reg2
},
1827 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2
, do_vfp_dp_from_reg2
},
1828 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2
, do_vfp_reg2_from_dp
},
1830 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
1831 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE
, do_xsc_mia
},
1832 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1833 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1834 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1835 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1836 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1837 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE
, do_xsc_mar
},
1838 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE
, do_xsc_mra
},
1840 /* Intel Wireless MMX technology instructions. */
1841 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
1842 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
1843 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
1844 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
1845 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
1846 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
1847 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
1848 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
1849 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
1850 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
1851 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
1852 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
1853 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
1854 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
1855 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
1856 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
1857 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
1858 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
1859 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmcr
},
1860 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_tmcrr
},
1861 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
1862 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
1863 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
1864 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
1865 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
1866 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
1867 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
1868 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
1869 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
1870 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmrc
},
1871 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_tmrrc
},
1872 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
1873 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
1874 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
1875 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1876 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1877 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1878 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1879 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1880 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1881 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1882 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1883 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1884 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1885 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1886 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1887 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_waligni
},
1888 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1889 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1890 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1891 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1892 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1893 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1894 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1895 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1896 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1897 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1898 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1899 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1900 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1901 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1902 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1903 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1904 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1905 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1906 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1907 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
1908 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
1909 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
1910 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
1911 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1912 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1913 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1914 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1915 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1916 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1917 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1918 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1919 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1920 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1921 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1922 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1923 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1924 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1925 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1926 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1927 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1928 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1929 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wmov
},
1930 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1931 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1932 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1933 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1934 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1935 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1936 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1937 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1938 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1939 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1940 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1941 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1942 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1943 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1944 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1945 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1946 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1947 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1948 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1949 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1950 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1951 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wshufh
},
1952 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1953 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1954 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1955 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1956 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1957 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1958 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1959 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1960 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1961 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1962 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1963 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1964 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1965 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1966 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1967 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1968 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1969 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1970 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
1971 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
1972 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
1973 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
1974 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1975 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1976 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1977 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1978 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1979 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1980 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1981 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1982 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1983 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1984 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1985 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1986 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1987 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1988 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1989 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1990 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1991 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1992 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1993 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1994 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1995 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1996 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1997 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1998 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1999 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2000 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2001 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2002 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wzero
},
2004 /* Cirrus Maverick instructions. */
2005 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_1
},
2006 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_2
},
2007 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_3
},
2008 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_4
},
2009 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_1
},
2010 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_2
},
2011 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_3
},
2012 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_4
},
2013 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK
, do_mav_binops_2a
},
2014 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1a
},
2015 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK
, do_mav_binops_2b
},
2016 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1b
},
2017 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK
, do_mav_binops_2b
},
2018 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1b
},
2019 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK
, do_mav_binops_2c
},
2020 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1c
},
2021 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK
, do_mav_binops_2c
},
2022 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1c
},
2023 {"cfmval32", 0xee100610, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
2024 {"cfmv32al", 0xee000610, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
2025 {"cfmvam32", 0xee100630, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
2026 {"cfmv32am", 0xee000630, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
2027 {"cfmvah32", 0xee100650, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
2028 {"cfmv32ah", 0xee000650, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
2029 {"cfmva32", 0xee100670, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
2030 {"cfmv32a", 0xee000670, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
2031 {"cfmva64", 0xee100690, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3c
},
2032 {"cfmv64a", 0xee000690, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3d
},
2033 {"cfmvsc32", 0xee1006b0, 8, ARM_CEXT_MAVERICK
, do_mav_dspsc_1
},
2034 {"cfmv32sc", 0xee0006b0, 8, ARM_CEXT_MAVERICK
, do_mav_dspsc_2
},
2035 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
2036 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
2037 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1f
},
2038 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1g
},
2039 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1h
},
2040 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1i
},
2041 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1j
},
2042 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1k
},
2043 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1l
},
2044 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1m
},
2045 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK
, do_mav_binops_1l
},
2046 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK
, do_mav_binops_1m
},
2047 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK
, do_mav_triple_4a
},
2048 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK
, do_mav_triple_4b
},
2049 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK
, do_mav_shift_1
},
2050 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK
, do_mav_shift_2
},
2051 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5a
},
2052 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5b
},
2053 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5c
},
2054 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5d
},
2055 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
2056 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
2057 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
2058 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
2059 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
2060 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
2061 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
2062 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
2063 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
2064 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
2065 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1n
},
2066 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1o
},
2067 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1n
},
2068 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1o
},
2069 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2070 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
2071 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2072 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
2073 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2074 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
2075 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2076 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2077 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK
, do_mav_quad_6a
},
2078 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK
, do_mav_quad_6a
},
2079 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK
, do_mav_quad_6b
},
2080 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK
, do_mav_quad_6b
},
2083 /* Defines for various bits that we will want to toggle. */
2084 #define INST_IMMEDIATE 0x02000000
2085 #define OFFSET_REG 0x02000000
2086 #define HWOFFSET_IMM 0x00400000
2087 #define SHIFT_BY_REG 0x00000010
2088 #define PRE_INDEX 0x01000000
2089 #define INDEX_UP 0x00800000
2090 #define WRITE_BACK 0x00200000
2091 #define LDM_TYPE_2_OR_3 0x00400000
2093 #define LITERAL_MASK 0xf000f000
2094 #define OPCODE_MASK 0xfe1fffff
2095 #define V4_STR_BIT 0x00000020
2097 #define DATA_OP_SHIFT 21
2099 /* Codes to distinguish the arithmetic instructions. */
2100 #define OPCODE_AND 0
2101 #define OPCODE_EOR 1
2102 #define OPCODE_SUB 2
2103 #define OPCODE_RSB 3
2104 #define OPCODE_ADD 4
2105 #define OPCODE_ADC 5
2106 #define OPCODE_SBC 6
2107 #define OPCODE_RSC 7
2108 #define OPCODE_TST 8
2109 #define OPCODE_TEQ 9
2110 #define OPCODE_CMP 10
2111 #define OPCODE_CMN 11
2112 #define OPCODE_ORR 12
2113 #define OPCODE_MOV 13
2114 #define OPCODE_BIC 14
2115 #define OPCODE_MVN 15
2117 /* Thumb v1 (ARMv4T). */
2118 static void do_t_nop
PARAMS ((char *));
2119 static void do_t_arit
PARAMS ((char *));
2120 static void do_t_add
PARAMS ((char *));
2121 static void do_t_asr
PARAMS ((char *));
2122 static void do_t_branch9
PARAMS ((char *));
2123 static void do_t_branch12
PARAMS ((char *));
2124 static void do_t_branch23
PARAMS ((char *));
2125 static void do_t_bx
PARAMS ((char *));
2126 static void do_t_compare
PARAMS ((char *));
2127 static void do_t_ldmstm
PARAMS ((char *));
2128 static void do_t_ldr
PARAMS ((char *));
2129 static void do_t_ldrb
PARAMS ((char *));
2130 static void do_t_ldrh
PARAMS ((char *));
2131 static void do_t_lds
PARAMS ((char *));
2132 static void do_t_lsl
PARAMS ((char *));
2133 static void do_t_lsr
PARAMS ((char *));
2134 static void do_t_mov
PARAMS ((char *));
2135 static void do_t_push_pop
PARAMS ((char *));
2136 static void do_t_str
PARAMS ((char *));
2137 static void do_t_strb
PARAMS ((char *));
2138 static void do_t_strh
PARAMS ((char *));
2139 static void do_t_sub
PARAMS ((char *));
2140 static void do_t_swi
PARAMS ((char *));
2141 static void do_t_adr
PARAMS ((char *));
2143 /* Thumb v2 (ARMv5T). */
2144 static void do_t_blx
PARAMS ((char *));
2145 static void do_t_bkpt
PARAMS ((char *));
2147 #define T_OPCODE_MUL 0x4340
2148 #define T_OPCODE_TST 0x4200
2149 #define T_OPCODE_CMN 0x42c0
2150 #define T_OPCODE_NEG 0x4240
2151 #define T_OPCODE_MVN 0x43c0
2153 #define T_OPCODE_ADD_R3 0x1800
2154 #define T_OPCODE_SUB_R3 0x1a00
2155 #define T_OPCODE_ADD_HI 0x4400
2156 #define T_OPCODE_ADD_ST 0xb000
2157 #define T_OPCODE_SUB_ST 0xb080
2158 #define T_OPCODE_ADD_SP 0xa800
2159 #define T_OPCODE_ADD_PC 0xa000
2160 #define T_OPCODE_ADD_I8 0x3000
2161 #define T_OPCODE_SUB_I8 0x3800
2162 #define T_OPCODE_ADD_I3 0x1c00
2163 #define T_OPCODE_SUB_I3 0x1e00
2165 #define T_OPCODE_ASR_R 0x4100
2166 #define T_OPCODE_LSL_R 0x4080
2167 #define T_OPCODE_LSR_R 0x40c0
2168 #define T_OPCODE_ASR_I 0x1000
2169 #define T_OPCODE_LSL_I 0x0000
2170 #define T_OPCODE_LSR_I 0x0800
2172 #define T_OPCODE_MOV_I8 0x2000
2173 #define T_OPCODE_CMP_I8 0x2800
2174 #define T_OPCODE_CMP_LR 0x4280
2175 #define T_OPCODE_MOV_HR 0x4600
2176 #define T_OPCODE_CMP_HR 0x4500
2178 #define T_OPCODE_LDR_PC 0x4800
2179 #define T_OPCODE_LDR_SP 0x9800
2180 #define T_OPCODE_STR_SP 0x9000
2181 #define T_OPCODE_LDR_IW 0x6800
2182 #define T_OPCODE_STR_IW 0x6000
2183 #define T_OPCODE_LDR_IH 0x8800
2184 #define T_OPCODE_STR_IH 0x8000
2185 #define T_OPCODE_LDR_IB 0x7800
2186 #define T_OPCODE_STR_IB 0x7000
2187 #define T_OPCODE_LDR_RW 0x5800
2188 #define T_OPCODE_STR_RW 0x5000
2189 #define T_OPCODE_LDR_RH 0x5a00
2190 #define T_OPCODE_STR_RH 0x5200
2191 #define T_OPCODE_LDR_RB 0x5c00
2192 #define T_OPCODE_STR_RB 0x5400
2194 #define T_OPCODE_PUSH 0xb400
2195 #define T_OPCODE_POP 0xbc00
2197 #define T_OPCODE_BRANCH 0xe7fe
2199 static int thumb_reg
PARAMS ((char ** str
, int hi_lo
));
2201 #define THUMB_SIZE 2 /* Size of thumb instruction. */
2202 #define THUMB_REG_LO 0x1
2203 #define THUMB_REG_HI 0x2
2204 #define THUMB_REG_ANY 0x3
2206 #define THUMB_H1 0x0080
2207 #define THUMB_H2 0x0040
2213 #define THUMB_MOVE 0
2214 #define THUMB_COMPARE 1
2216 #define THUMB_LOAD 0
2217 #define THUMB_STORE 1
2219 #define THUMB_PP_PC_LR 0x0100
2221 /* These three are used for immediate shifts, do not alter. */
2222 #define THUMB_WORD 2
2223 #define THUMB_HALFWORD 1
2224 #define THUMB_BYTE 0
2228 /* Basic string to match. */
2229 const char * template;
2231 /* Basic instruction code. */
2232 unsigned long value
;
2236 /* Which CPU variants this exists for. */
2237 unsigned long variant
;
2239 /* Function to call to parse args. */
2240 void (* parms
) PARAMS ((char *));
2243 static const struct thumb_opcode tinsns
[] =
2245 /* Thumb v1 (ARMv4T). */
2246 {"adc", 0x4140, 2, ARM_EXT_V4T
, do_t_arit
},
2247 {"add", 0x0000, 2, ARM_EXT_V4T
, do_t_add
},
2248 {"and", 0x4000, 2, ARM_EXT_V4T
, do_t_arit
},
2249 {"asr", 0x0000, 2, ARM_EXT_V4T
, do_t_asr
},
2250 {"b", T_OPCODE_BRANCH
, 2, ARM_EXT_V4T
, do_t_branch12
},
2251 {"beq", 0xd0fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2252 {"bne", 0xd1fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2253 {"bcs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2254 {"bhs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2255 {"bcc", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2256 {"bul", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2257 {"blo", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2258 {"bmi", 0xd4fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2259 {"bpl", 0xd5fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2260 {"bvs", 0xd6fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2261 {"bvc", 0xd7fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2262 {"bhi", 0xd8fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2263 {"bls", 0xd9fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2264 {"bge", 0xdafe, 2, ARM_EXT_V4T
, do_t_branch9
},
2265 {"blt", 0xdbfe, 2, ARM_EXT_V4T
, do_t_branch9
},
2266 {"bgt", 0xdcfe, 2, ARM_EXT_V4T
, do_t_branch9
},
2267 {"ble", 0xddfe, 2, ARM_EXT_V4T
, do_t_branch9
},
2268 {"bal", 0xdefe, 2, ARM_EXT_V4T
, do_t_branch9
},
2269 {"bic", 0x4380, 2, ARM_EXT_V4T
, do_t_arit
},
2270 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T
, do_t_branch23
},
2271 {"bx", 0x4700, 2, ARM_EXT_V4T
, do_t_bx
},
2272 {"cmn", T_OPCODE_CMN
, 2, ARM_EXT_V4T
, do_t_arit
},
2273 {"cmp", 0x0000, 2, ARM_EXT_V4T
, do_t_compare
},
2274 {"eor", 0x4040, 2, ARM_EXT_V4T
, do_t_arit
},
2275 {"ldmia", 0xc800, 2, ARM_EXT_V4T
, do_t_ldmstm
},
2276 {"ldr", 0x0000, 2, ARM_EXT_V4T
, do_t_ldr
},
2277 {"ldrb", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrb
},
2278 {"ldrh", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrh
},
2279 {"ldrsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
2280 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
2281 {"ldsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
2282 {"ldsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
2283 {"lsl", 0x0000, 2, ARM_EXT_V4T
, do_t_lsl
},
2284 {"lsr", 0x0000, 2, ARM_EXT_V4T
, do_t_lsr
},
2285 {"mov", 0x0000, 2, ARM_EXT_V4T
, do_t_mov
},
2286 {"mul", T_OPCODE_MUL
, 2, ARM_EXT_V4T
, do_t_arit
},
2287 {"mvn", T_OPCODE_MVN
, 2, ARM_EXT_V4T
, do_t_arit
},
2288 {"neg", T_OPCODE_NEG
, 2, ARM_EXT_V4T
, do_t_arit
},
2289 {"orr", 0x4300, 2, ARM_EXT_V4T
, do_t_arit
},
2290 {"pop", 0xbc00, 2, ARM_EXT_V4T
, do_t_push_pop
},
2291 {"push", 0xb400, 2, ARM_EXT_V4T
, do_t_push_pop
},
2292 {"ror", 0x41c0, 2, ARM_EXT_V4T
, do_t_arit
},
2293 {"sbc", 0x4180, 2, ARM_EXT_V4T
, do_t_arit
},
2294 {"stmia", 0xc000, 2, ARM_EXT_V4T
, do_t_ldmstm
},
2295 {"str", 0x0000, 2, ARM_EXT_V4T
, do_t_str
},
2296 {"strb", 0x0000, 2, ARM_EXT_V4T
, do_t_strb
},
2297 {"strh", 0x0000, 2, ARM_EXT_V4T
, do_t_strh
},
2298 {"swi", 0xdf00, 2, ARM_EXT_V4T
, do_t_swi
},
2299 {"sub", 0x0000, 2, ARM_EXT_V4T
, do_t_sub
},
2300 {"tst", T_OPCODE_TST
, 2, ARM_EXT_V4T
, do_t_arit
},
2302 {"adr", 0x0000, 2, ARM_EXT_V4T
, do_t_adr
},
2303 {"nop", 0x46C0, 2, ARM_EXT_V4T
, do_t_nop
}, /* mov r8,r8 */
2304 /* Thumb v2 (ARMv5T). */
2305 {"blx", 0, 0, ARM_EXT_V5T
, do_t_blx
},
2306 {"bkpt", 0xbe00, 2, ARM_EXT_V5T
, do_t_bkpt
},
2309 #define BAD_ARGS _("bad arguments to instruction")
2310 #define BAD_PC _("r15 not allowed here")
2311 #define BAD_COND _("instruction is not conditional")
2312 #define ERR_NO_ACCUM _("acc0 expected")
2314 static struct hash_control
* arm_ops_hsh
= NULL
;
2315 static struct hash_control
* arm_tops_hsh
= NULL
;
2316 static struct hash_control
* arm_cond_hsh
= NULL
;
2317 static struct hash_control
* arm_shift_hsh
= NULL
;
2318 static struct hash_control
* arm_psr_hsh
= NULL
;
2320 /* This table describes all the machine specific pseudo-ops the assembler
2321 has to support. The fields are:
2322 pseudo-op name without dot
2323 function to call to execute this pseudo-op
2324 Integer arg to pass to the function. */
2326 static void s_req
PARAMS ((int));
2327 static void s_align
PARAMS ((int));
2328 static void s_bss
PARAMS ((int));
2329 static void s_even
PARAMS ((int));
2330 static void s_ltorg
PARAMS ((int));
2331 static void s_arm
PARAMS ((int));
2332 static void s_thumb
PARAMS ((int));
2333 static void s_code
PARAMS ((int));
2334 static void s_force_thumb
PARAMS ((int));
2335 static void s_thumb_func
PARAMS ((int));
2336 static void s_thumb_set
PARAMS ((int));
2338 static void s_arm_elf_cons
PARAMS ((int));
2341 static int my_get_expression
PARAMS ((expressionS
*, char **));
2343 const pseudo_typeS md_pseudo_table
[] =
2345 /* Never called becasue '.req' does not start line. */
2346 { "req", s_req
, 0 },
2347 { "bss", s_bss
, 0 },
2348 { "align", s_align
, 0 },
2349 { "arm", s_arm
, 0 },
2350 { "thumb", s_thumb
, 0 },
2351 { "code", s_code
, 0 },
2352 { "force_thumb", s_force_thumb
, 0 },
2353 { "thumb_func", s_thumb_func
, 0 },
2354 { "thumb_set", s_thumb_set
, 0 },
2355 { "even", s_even
, 0 },
2356 { "ltorg", s_ltorg
, 0 },
2357 { "pool", s_ltorg
, 0 },
2359 { "word", s_arm_elf_cons
, 4 },
2360 { "long", s_arm_elf_cons
, 4 },
2364 { "extend", float_cons
, 'x' },
2365 { "ldouble", float_cons
, 'x' },
2366 { "packed", float_cons
, 'p' },
2370 /* Other internal functions. */
2371 static int arm_parse_extension
PARAMS ((char *, int *));
2372 static int arm_parse_cpu
PARAMS ((char *));
2373 static int arm_parse_arch
PARAMS ((char *));
2374 static int arm_parse_fpu
PARAMS ((char *));
2375 #if defined OBJ_COFF || defined OBJ_ELF
2376 static void arm_add_note
PARAMS ((const char *, const char *, unsigned int));
2379 /* Stuff needed to resolve the label ambiguity
2389 symbolS
* last_label_seen
;
2390 static int label_is_thumb_function_name
= FALSE
;
2392 /* Literal Pool stuff. */
2394 #define MAX_LITERAL_POOL_SIZE 1024
2396 /* Literal pool structure. Held on a per-section
2397 and per-sub-section basis. */
2398 typedef struct literal_pool
2400 expressionS literals
[MAX_LITERAL_POOL_SIZE
];
2401 unsigned int next_free_entry
;
2405 subsegT sub_section
;
2406 struct literal_pool
* next
;
2409 /* Pointer to a linked list of literal pools. */
2410 literal_pool
* list_of_pools
= NULL
;
2412 static literal_pool
* find_literal_pool
PARAMS ((void));
2413 static literal_pool
* find_or_make_literal_pool
PARAMS ((void));
2415 static literal_pool
*
2416 find_literal_pool ()
2418 literal_pool
* pool
;
2420 for (pool
= list_of_pools
; pool
!= NULL
; pool
= pool
->next
)
2422 if (pool
->section
== now_seg
2423 && pool
->sub_section
== now_subseg
)
2430 static literal_pool
*
2431 find_or_make_literal_pool ()
2433 /* Next literal pool ID number. */
2434 static unsigned int latest_pool_num
= 1;
2435 literal_pool
* pool
;
2437 pool
= find_literal_pool ();
2441 /* Create a new pool. */
2442 pool
= (literal_pool
*) xmalloc (sizeof (* pool
));
2446 pool
->next_free_entry
= 0;
2447 pool
->section
= now_seg
;
2448 pool
->sub_section
= now_subseg
;
2449 pool
->next
= list_of_pools
;
2450 pool
->symbol
= NULL
;
2452 /* Add it to the list. */
2453 list_of_pools
= pool
;
2456 /* New pools, and emptied pools, will have a NULL symbol. */
2457 if (pool
->symbol
== NULL
)
2459 pool
->symbol
= symbol_create (FAKE_LABEL_NAME
, undefined_section
,
2460 (valueT
) 0, &zero_address_frag
);
2461 pool
->id
= latest_pool_num
++;
2468 /* Add the literal in the global 'inst'
2469 structure to the relevent literal pool. */
2473 literal_pool
* pool
;
2476 pool
= find_or_make_literal_pool ();
2478 /* Check if this literal value is already in the pool. */
2479 for (entry
= 0; entry
< pool
->next_free_entry
; entry
++)
2481 if ((pool
->literals
[entry
].X_op
== inst
.reloc
.exp
.X_op
)
2482 && (inst
.reloc
.exp
.X_op
== O_constant
)
2483 && (pool
->literals
[entry
].X_add_number
2484 == inst
.reloc
.exp
.X_add_number
)
2485 && (pool
->literals
[entry
].X_unsigned
2486 == inst
.reloc
.exp
.X_unsigned
))
2489 if ((pool
->literals
[entry
].X_op
== inst
.reloc
.exp
.X_op
)
2490 && (inst
.reloc
.exp
.X_op
== O_symbol
)
2491 && (pool
->literals
[entry
].X_add_number
2492 == inst
.reloc
.exp
.X_add_number
)
2493 && (pool
->literals
[entry
].X_add_symbol
2494 == inst
.reloc
.exp
.X_add_symbol
)
2495 && (pool
->literals
[entry
].X_op_symbol
2496 == inst
.reloc
.exp
.X_op_symbol
))
2500 /* Do we need to create a new entry? */
2501 if (entry
== pool
->next_free_entry
)
2503 if (entry
>= MAX_LITERAL_POOL_SIZE
)
2505 inst
.error
= _("literal pool overflow");
2509 pool
->literals
[entry
] = inst
.reloc
.exp
;
2510 pool
->next_free_entry
+= 1;
2513 inst
.reloc
.exp
.X_op
= O_symbol
;
2514 inst
.reloc
.exp
.X_add_number
= ((int) entry
) * 4 - 8;
2515 inst
.reloc
.exp
.X_add_symbol
= pool
->symbol
;
2520 /* Can't use symbol_new here, so have to create a symbol and then at
2521 a later date assign it a value. Thats what these functions do. */
2524 symbol_locate (symbolP
, name
, segment
, valu
, frag
)
2526 const char * name
; /* It is copied, the caller can modify. */
2527 segT segment
; /* Segment identifier (SEG_<something>). */
2528 valueT valu
; /* Symbol value. */
2529 fragS
* frag
; /* Associated fragment. */
2531 unsigned int name_length
;
2532 char * preserved_copy_of_name
;
2534 name_length
= strlen (name
) + 1; /* +1 for \0. */
2535 obstack_grow (¬es
, name
, name_length
);
2536 preserved_copy_of_name
= obstack_finish (¬es
);
2537 #ifdef STRIP_UNDERSCORE
2538 if (preserved_copy_of_name
[0] == '_')
2539 preserved_copy_of_name
++;
2542 #ifdef tc_canonicalize_symbol_name
2543 preserved_copy_of_name
=
2544 tc_canonicalize_symbol_name (preserved_copy_of_name
);
2547 S_SET_NAME (symbolP
, preserved_copy_of_name
);
2549 S_SET_SEGMENT (symbolP
, segment
);
2550 S_SET_VALUE (symbolP
, valu
);
2551 symbol_clear_list_pointers (symbolP
);
2553 symbol_set_frag (symbolP
, frag
);
2555 /* Link to end of symbol chain. */
2557 extern int symbol_table_frozen
;
2558 if (symbol_table_frozen
)
2562 symbol_append (symbolP
, symbol_lastP
, & symbol_rootP
, & symbol_lastP
);
2564 obj_symbol_new_hook (symbolP
);
2566 #ifdef tc_symbol_new_hook
2567 tc_symbol_new_hook (symbolP
);
2571 verify_symbol_chain (symbol_rootP
, symbol_lastP
);
2572 #endif /* DEBUG_SYMS */
2575 /* Check that an immediate is valid.
2576 If so, convert it to the right format. */
2579 validate_immediate (val
)
2585 #define rotate_left(v, n) (v << n | v >> (32 - n))
2587 for (i
= 0; i
< 32; i
+= 2)
2588 if ((a
= rotate_left (val
, i
)) <= 0xff)
2589 return a
| (i
<< 7); /* 12-bit pack: [shift-cnt,const]. */
2594 /* Check to see if an immediate can be computed as two seperate immediate
2595 values, added together. We already know that this value cannot be
2596 computed by just one ARM instruction. */
2599 validate_immediate_twopart (val
, highpart
)
2601 unsigned int * highpart
;
2606 for (i
= 0; i
< 32; i
+= 2)
2607 if (((a
= rotate_left (val
, i
)) & 0xff) != 0)
2613 * highpart
= (a
>> 8) | ((i
+ 24) << 7);
2615 else if (a
& 0xff0000)
2619 * highpart
= (a
>> 16) | ((i
+ 16) << 7);
2623 assert (a
& 0xff000000);
2624 * highpart
= (a
>> 24) | ((i
+ 8) << 7);
2627 return (a
& 0xff) | (i
<< 7);
2634 validate_offset_imm (val
, hwse
)
2638 if ((hwse
&& val
> 255) || val
> 4095)
2645 int a ATTRIBUTE_UNUSED
;
2647 as_bad (_("invalid syntax for .req directive"));
2652 int ignore ATTRIBUTE_UNUSED
;
2654 /* We don't support putting frags in the BSS segment, we fake it by
2655 marking in_bss, then looking at s_skip for clues. */
2656 subseg_set (bss_section
, 0);
2657 demand_empty_rest_of_line ();
2662 int ignore ATTRIBUTE_UNUSED
;
2664 /* Never make frag if expect extra pass. */
2666 frag_align (1, 0, 0);
2668 record_alignment (now_seg
, 1);
2670 demand_empty_rest_of_line ();
2675 int ignored ATTRIBUTE_UNUSED
;
2678 literal_pool
* pool
;
2681 pool
= find_literal_pool ();
2683 || pool
->symbol
== NULL
2684 || pool
->next_free_entry
== 0)
2687 /* Align pool as you have word accesses.
2688 Only make a frag if we have to. */
2690 frag_align (2, 0, 0);
2692 record_alignment (now_seg
, 2);
2694 sprintf (sym_name
, "$$lit_\002%x", pool
->id
);
2696 symbol_locate (pool
->symbol
, sym_name
, now_seg
,
2697 (valueT
) frag_now_fix (), frag_now
);
2698 symbol_table_insert (pool
->symbol
);
2700 ARM_SET_THUMB (pool
->symbol
, thumb_mode
);
2702 #if defined OBJ_COFF || defined OBJ_ELF
2703 ARM_SET_INTERWORK (pool
->symbol
, support_interwork
);
2706 for (entry
= 0; entry
< pool
->next_free_entry
; entry
++)
2707 /* First output the expression in the instruction to the pool. */
2708 emit_expr (&(pool
->literals
[entry
]), 4); /* .word */
2710 /* Mark the pool as empty. */
2711 pool
->next_free_entry
= 0;
2712 pool
->symbol
= NULL
;
2715 /* Same as s_align_ptwo but align 0 => align 2. */
2719 int unused ATTRIBUTE_UNUSED
;
2722 register long temp_fill
;
2723 long max_alignment
= 15;
2725 temp
= get_absolute_expression ();
2726 if (temp
> max_alignment
)
2727 as_bad (_("alignment too large: %d assumed"), temp
= max_alignment
);
2730 as_bad (_("alignment negative. 0 assumed."));
2734 if (*input_line_pointer
== ',')
2736 input_line_pointer
++;
2737 temp_fill
= get_absolute_expression ();
2745 /* Only make a frag if we HAVE to. */
2746 if (temp
&& !need_pass_2
)
2747 frag_align (temp
, (int) temp_fill
, 0);
2748 demand_empty_rest_of_line ();
2750 record_alignment (now_seg
, temp
);
2754 s_force_thumb (ignore
)
2755 int ignore ATTRIBUTE_UNUSED
;
2757 /* If we are not already in thumb mode go into it, EVEN if
2758 the target processor does not support thumb instructions.
2759 This is used by gcc/config/arm/lib1funcs.asm for example
2760 to compile interworking support functions even if the
2761 target processor should not support interworking. */
2766 record_alignment (now_seg
, 1);
2769 demand_empty_rest_of_line ();
2773 s_thumb_func (ignore
)
2774 int ignore ATTRIBUTE_UNUSED
;
2779 /* The following label is the name/address of the start of a Thumb function.
2780 We need to know this for the interworking support. */
2781 label_is_thumb_function_name
= TRUE
;
2783 demand_empty_rest_of_line ();
2786 /* Perform a .set directive, but also mark the alias as
2787 being a thumb function. */
2793 /* XXX the following is a duplicate of the code for s_set() in read.c
2794 We cannot just call that code as we need to get at the symbol that
2796 register char * name
;
2797 register char delim
;
2798 register char * end_name
;
2799 register symbolS
* symbolP
;
2801 /* Especial apologies for the random logic:
2802 This just grew, and could be parsed much more simply!
2804 name
= input_line_pointer
;
2805 delim
= get_symbol_end ();
2806 end_name
= input_line_pointer
;
2811 if (*input_line_pointer
!= ',')
2814 as_bad (_("expected comma after name \"%s\""), name
);
2816 ignore_rest_of_line ();
2820 input_line_pointer
++;
2823 if (name
[0] == '.' && name
[1] == '\0')
2825 /* XXX - this should not happen to .thumb_set. */
2829 if ((symbolP
= symbol_find (name
)) == NULL
2830 && (symbolP
= md_undefined_symbol (name
)) == NULL
)
2833 /* When doing symbol listings, play games with dummy fragments living
2834 outside the normal fragment chain to record the file and line info
2836 if (listing
& LISTING_SYMBOLS
)
2838 extern struct list_info_struct
* listing_tail
;
2839 fragS
* dummy_frag
= (fragS
*) xmalloc (sizeof (fragS
));
2841 memset (dummy_frag
, 0, sizeof (fragS
));
2842 dummy_frag
->fr_type
= rs_fill
;
2843 dummy_frag
->line
= listing_tail
;
2844 symbolP
= symbol_new (name
, undefined_section
, 0, dummy_frag
);
2845 dummy_frag
->fr_symbol
= symbolP
;
2849 symbolP
= symbol_new (name
, undefined_section
, 0, &zero_address_frag
);
2852 /* "set" symbols are local unless otherwise specified. */
2853 SF_SET_LOCAL (symbolP
);
2854 #endif /* OBJ_COFF */
2855 } /* Make a new symbol. */
2857 symbol_table_insert (symbolP
);
2862 && S_IS_DEFINED (symbolP
)
2863 && S_GET_SEGMENT (symbolP
) != reg_section
)
2864 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP
));
2866 pseudo_set (symbolP
);
2868 demand_empty_rest_of_line ();
2870 /* XXX Now we come to the Thumb specific bit of code. */
2872 THUMB_SET_FUNC (symbolP
, 1);
2873 ARM_SET_THUMB (symbolP
, 1);
2874 #if defined OBJ_ELF || defined OBJ_COFF
2875 ARM_SET_INTERWORK (symbolP
, support_interwork
);
2880 opcode_select (width
)
2888 if (! (cpu_variant
& ARM_EXT_V4T
))
2889 as_bad (_("selected processor does not support THUMB opcodes"));
2892 /* No need to force the alignment, since we will have been
2893 coming from ARM mode, which is word-aligned. */
2894 record_alignment (now_seg
, 1);
2901 if ((cpu_variant
& ARM_ALL
) == ARM_EXT_V4T
)
2902 as_bad (_("selected processor does not support ARM opcodes"));
2907 frag_align (2, 0, 0);
2909 record_alignment (now_seg
, 1);
2914 as_bad (_("invalid instruction size selected (%d)"), width
);
2920 int ignore ATTRIBUTE_UNUSED
;
2923 demand_empty_rest_of_line ();
2928 int ignore ATTRIBUTE_UNUSED
;
2931 demand_empty_rest_of_line ();
2936 int unused ATTRIBUTE_UNUSED
;
2940 temp
= get_absolute_expression ();
2945 opcode_select (temp
);
2949 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp
);
2957 skip_whitespace (str
);
2959 if (*str
!= '\0' && !inst
.error
)
2960 inst
.error
= _("garbage following instruction");
2964 skip_past_comma (str
)
2967 char * p
= * str
, c
;
2970 while ((c
= *p
) == ' ' || c
== ',')
2973 if (c
== ',' && comma
++)
2981 return comma
? SUCCESS
: FAIL
;
2984 /* A standard register must be given at this point.
2985 SHIFT is the place to put it in inst.instruction.
2986 Restores input start point on error.
2987 Returns the reg#, or FAIL. */
2990 reg_required_here (str
, shift
)
2994 static char buff
[128]; /* XXX */
2996 char * start
= * str
;
2998 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_RN
].htab
)) != FAIL
)
3001 inst
.instruction
|= reg
<< shift
;
3005 /* Restore the start point, we may have got a reg of the wrong class. */
3008 /* In the few cases where we might be able to accept something else
3009 this error can be overridden. */
3010 sprintf (buff
, _("register expected, not '%.100s'"), start
);
3016 /* A Intel Wireless MMX technology register
3017 must be given at this point.
3018 Shift is the place to put it in inst.instruction.
3019 Restores input start point on err.
3020 Returns the reg#, or FAIL. */
3023 wreg_required_here (str
, shift
, reg_type
)
3026 enum wreg_type reg_type
;
3028 static char buff
[128];
3030 char * start
= *str
;
3032 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_IWMMXT
].htab
)) != FAIL
)
3034 if (wr_register (reg
)
3035 && (reg_type
== IWMMXT_REG_WR
|| reg_type
== IWMMXT_REG_WR_OR_WC
))
3038 inst
.instruction
|= (reg
^ WR_PREFIX
) << shift
;
3041 else if (wc_register (reg
)
3042 && (reg_type
== IWMMXT_REG_WC
|| reg_type
== IWMMXT_REG_WR_OR_WC
))
3045 inst
.instruction
|= (reg
^ WC_PREFIX
) << shift
;
3048 else if ((wcg_register (reg
) && reg_type
== IWMMXT_REG_WCG
))
3051 inst
.instruction
|= ((reg
^ WC_PREFIX
) - 8) << shift
;
3056 /* Restore the start point, we may have got a reg of the wrong class. */
3059 /* In the few cases where we might be able to accept
3060 something else this error can be overridden. */
3061 sprintf (buff
, _("Intel Wireless MMX technology register expected, not '%.100s'"), start
);
3067 static const struct asm_psr
*
3069 register char ** ccp
;
3071 char * start
= * ccp
;
3074 const struct asm_psr
* psr
;
3078 /* Skip to the end of the next word in the input stream. */
3083 while (ISALPHA (c
) || c
== '_');
3085 /* Terminate the word. */
3088 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
3089 feature for ease of use and backwards compatibility. */
3090 if (!strncmp (start
, "cpsr", 4))
3091 strncpy (start
, "CPSR", 4);
3092 else if (!strncmp (start
, "spsr", 4))
3093 strncpy (start
, "SPSR", 4);
3095 /* Now locate the word in the psr hash table. */
3096 psr
= (const struct asm_psr
*) hash_find (arm_psr_hsh
, start
);
3098 /* Restore the input stream. */
3101 /* If we found a valid match, advance the
3102 stream pointer past the end of the word. */
3108 /* Parse the input looking for a PSR flag. */
3111 psr_required_here (str
)
3114 char * start
= * str
;
3115 const struct asm_psr
* psr
;
3117 psr
= arm_psr_parse (str
);
3121 /* If this is the SPSR that is being modified, set the R bit. */
3123 inst
.instruction
|= SPSR_BIT
;
3125 /* Set the psr flags in the MSR instruction. */
3126 inst
.instruction
|= psr
->field
<< PSR_SHIFT
;
3131 /* In the few cases where we might be able to accept
3132 something else this error can be overridden. */
3133 inst
.error
= _("flag for {c}psr instruction expected");
3135 /* Restore the start point. */
3141 co_proc_number (str
)
3144 int processor
, pchar
;
3147 skip_whitespace (*str
);
3150 /* The data sheet seems to imply that just a number on its own is valid
3151 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
3153 if ((processor
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CP
].htab
))
3159 if (pchar
>= '0' && pchar
<= '9')
3161 processor
= pchar
- '0';
3162 if (**str
>= '0' && **str
<= '9')
3164 processor
= processor
* 10 + *(*str
)++ - '0';
3167 inst
.error
= _("illegal co-processor number");
3174 inst
.error
= _("bad or missing co-processor number");
3179 inst
.instruction
|= processor
<< 8;
3184 cp_opc_expr (str
, where
, length
)
3191 skip_whitespace (* str
);
3193 memset (&expr
, '\0', sizeof (expr
));
3195 if (my_get_expression (&expr
, str
))
3197 if (expr
.X_op
!= O_constant
)
3199 inst
.error
= _("bad or missing expression");
3203 if ((expr
.X_add_number
& ((1 << length
) - 1)) != expr
.X_add_number
)
3205 inst
.error
= _("immediate co-processor expression too large");
3209 inst
.instruction
|= expr
.X_add_number
<< where
;
3214 cp_reg_required_here (str
, where
)
3219 char * start
= *str
;
3221 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CN
].htab
)) != FAIL
)
3223 inst
.instruction
|= reg
<< where
;
3227 /* In the few cases where we might be able to accept something else
3228 this error can be overridden. */
3229 inst
.error
= _("co-processor register expected");
3231 /* Restore the start point. */
3237 fp_reg_required_here (str
, where
)
3242 char * start
= * str
;
3244 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_FN
].htab
)) != FAIL
)
3246 inst
.instruction
|= reg
<< where
;
3250 /* In the few cases where we might be able to accept something else
3251 this error can be overridden. */
3252 inst
.error
= _("floating point register expected");
3254 /* Restore the start point. */
3260 cp_address_offset (str
)
3265 skip_whitespace (* str
);
3267 if (! is_immediate_prefix (**str
))
3269 inst
.error
= _("immediate expression expected");
3275 if (my_get_expression (& inst
.reloc
.exp
, str
))
3278 if (inst
.reloc
.exp
.X_op
== O_constant
)
3280 offset
= inst
.reloc
.exp
.X_add_number
;
3284 inst
.error
= _("co-processor address must be word aligned");
3288 if (offset
> 1023 || offset
< -1023)
3290 inst
.error
= _("offset too large");
3295 inst
.instruction
|= INDEX_UP
;
3299 inst
.instruction
|= offset
>> 2;
3302 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
3308 cp_address_required_here (str
, wb_ok
)
3321 skip_whitespace (p
);
3323 if ((reg
= reg_required_here (& p
, 16)) == FAIL
)
3326 skip_whitespace (p
);
3332 skip_whitespace (p
);
3336 /* As an extension to the official ARM syntax we allow:
3340 as a short hand for:
3343 inst
.instruction
|= PRE_INDEX
| INDEX_UP
;
3348 if (skip_past_comma (& p
) == FAIL
)
3350 inst
.error
= _("comma expected after closing square bracket");
3354 skip_whitespace (p
);
3361 write_back
= WRITE_BACK
;
3365 inst
.error
= _("pc may not be used in post-increment");
3369 if (cp_address_offset (& p
) == FAIL
)
3373 pre_inc
= PRE_INDEX
| INDEX_UP
;
3379 /* [Rn], {<expr>} */
3382 skip_whitespace (p
);
3384 if (my_get_expression (& inst
.reloc
.exp
, & p
))
3387 if (inst
.reloc
.exp
.X_op
== O_constant
)
3389 option
= inst
.reloc
.exp
.X_add_number
;
3391 if (option
> 255 || option
< 0)
3393 inst
.error
= _("'option' field too large");
3397 skip_whitespace (p
);
3401 inst
.error
= _("'}' expected at end of 'option' field");
3407 inst
.instruction
|= option
;
3408 inst
.instruction
|= INDEX_UP
;
3413 inst
.error
= _("non-constant expressions for 'option' field not supported");
3419 inst
.error
= _("# or { expected after comma");
3425 /* '['Rn, #expr']'[!] */
3427 if (skip_past_comma (& p
) == FAIL
)
3429 inst
.error
= _("pre-indexed expression expected");
3433 pre_inc
= PRE_INDEX
;
3435 if (cp_address_offset (& p
) == FAIL
)
3438 skip_whitespace (p
);
3442 inst
.error
= _("missing ]");
3446 skip_whitespace (p
);
3448 if (wb_ok
&& *p
== '!')
3452 inst
.error
= _("pc may not be used with write-back");
3457 write_back
= WRITE_BACK
;
3463 if (my_get_expression (&inst
.reloc
.exp
, &p
))
3466 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
3467 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
3468 inst
.reloc
.pc_rel
= 1;
3469 inst
.instruction
|= (REG_PC
<< 16);
3470 pre_inc
= PRE_INDEX
;
3473 inst
.instruction
|= write_back
| pre_inc
;
3479 cp_byte_address_offset (str
)
3484 skip_whitespace (* str
);
3486 if (! is_immediate_prefix (**str
))
3488 inst
.error
= _("immediate expression expected");
3494 if (my_get_expression (& inst
.reloc
.exp
, str
))
3497 if (inst
.reloc
.exp
.X_op
== O_constant
)
3499 offset
= inst
.reloc
.exp
.X_add_number
;
3501 if (offset
> 255 || offset
< -255)
3503 inst
.error
= _("offset too large");
3508 inst
.instruction
|= INDEX_UP
;
3512 inst
.instruction
|= offset
;
3515 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM_S2
;
3521 cp_byte_address_required_here (str
)
3533 skip_whitespace (p
);
3535 if ((reg
= reg_required_here (& p
, 16)) == FAIL
)
3538 skip_whitespace (p
);
3544 if (skip_past_comma (& p
) == SUCCESS
)
3547 write_back
= WRITE_BACK
;
3551 inst
.error
= _("pc may not be used in post-increment");
3555 if (cp_byte_address_offset (& p
) == FAIL
)
3559 pre_inc
= PRE_INDEX
| INDEX_UP
;
3563 /* '['Rn, #expr']'[!] */
3565 if (skip_past_comma (& p
) == FAIL
)
3567 inst
.error
= _("pre-indexed expression expected");
3571 pre_inc
= PRE_INDEX
;
3573 if (cp_byte_address_offset (& p
) == FAIL
)
3576 skip_whitespace (p
);
3580 inst
.error
= _("missing ]");
3584 skip_whitespace (p
);
3590 inst
.error
= _("pc may not be used with write-back");
3595 write_back
= WRITE_BACK
;
3601 if (my_get_expression (&inst
.reloc
.exp
, &p
))
3604 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM_S2
;
3605 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
3606 inst
.reloc
.pc_rel
= 1;
3607 inst
.instruction
|= (REG_PC
<< 16);
3608 pre_inc
= PRE_INDEX
;
3611 inst
.instruction
|= write_back
| pre_inc
;
3620 /* Do nothing really. */
3631 /* Only one syntax. */
3632 skip_whitespace (str
);
3634 if (reg_required_here (&str
, 12) == FAIL
)
3636 inst
.error
= BAD_ARGS
;
3640 if (skip_past_comma (&str
) == FAIL
)
3642 inst
.error
= _("comma expected after register name");
3646 skip_whitespace (str
);
3648 if ( strcmp (str
, "CPSR") == 0
3649 || strcmp (str
, "SPSR") == 0
3650 /* Lower case versions for backwards compatability. */
3651 || strcmp (str
, "cpsr") == 0
3652 || strcmp (str
, "spsr") == 0)
3655 /* This is for backwards compatability with older toolchains. */
3656 else if ( strcmp (str
, "cpsr_all") == 0
3657 || strcmp (str
, "spsr_all") == 0)
3661 inst
.error
= _("CPSR or SPSR expected");
3665 if (* str
== 's' || * str
== 'S')
3666 inst
.instruction
|= SPSR_BIT
;
3672 /* Two possible forms:
3673 "{C|S}PSR_<field>, Rm",
3674 "{C|S}PSR_f, #expression". */
3680 skip_whitespace (str
);
3682 if (psr_required_here (& str
) == FAIL
)
3685 if (skip_past_comma (& str
) == FAIL
)
3687 inst
.error
= _("comma missing after psr flags");
3691 skip_whitespace (str
);
3693 if (reg_required_here (& str
, 0) != FAIL
)
3700 if (! is_immediate_prefix (* str
))
3703 _("only a register or immediate value can follow a psr flag");
3710 if (my_get_expression (& inst
.reloc
.exp
, & str
))
3713 _("only a register or immediate value can follow a psr flag");
3717 #if 0 /* The first edition of the ARM architecture manual stated that
3718 writing anything other than the flags with an immediate operation
3719 had UNPREDICTABLE effects. This constraint was removed in the
3720 second edition of the specification. */
3721 if ((cpu_variant
& ARM_EXT_V5
) != ARM_EXT_V5
3722 && inst
.instruction
& ((PSR_c
| PSR_x
| PSR_s
) << PSR_SHIFT
))
3724 inst
.error
= _("immediate value cannot be used to set this field");
3729 inst
.instruction
|= INST_IMMEDIATE
;
3731 if (inst
.reloc
.exp
.X_add_symbol
)
3733 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
3734 inst
.reloc
.pc_rel
= 0;
3738 unsigned value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
3740 if (value
== (unsigned) FAIL
)
3742 inst
.error
= _("invalid constant");
3746 inst
.instruction
|= value
;
3753 /* Long Multiply Parser
3754 UMULL RdLo, RdHi, Rm, Rs
3755 SMULL RdLo, RdHi, Rm, Rs
3756 UMLAL RdLo, RdHi, Rm, Rs
3757 SMLAL RdLo, RdHi, Rm, Rs. */
3763 int rdlo
, rdhi
, rm
, rs
;
3765 /* Only one format "rdlo, rdhi, rm, rs". */
3766 skip_whitespace (str
);
3768 if ((rdlo
= reg_required_here (&str
, 12)) == FAIL
)
3770 inst
.error
= BAD_ARGS
;
3774 if (skip_past_comma (&str
) == FAIL
3775 || (rdhi
= reg_required_here (&str
, 16)) == FAIL
)
3777 inst
.error
= BAD_ARGS
;
3781 if (skip_past_comma (&str
) == FAIL
3782 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
3784 inst
.error
= BAD_ARGS
;
3788 /* rdhi, rdlo and rm must all be different. */
3789 if (rdlo
== rdhi
|| rdlo
== rm
|| rdhi
== rm
)
3790 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
3792 if (skip_past_comma (&str
) == FAIL
3793 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
3795 inst
.error
= BAD_ARGS
;
3799 if (rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
)
3801 inst
.error
= BAD_PC
;
3815 /* Only one format "rd, rm, rs". */
3816 skip_whitespace (str
);
3818 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
3820 inst
.error
= BAD_ARGS
;
3826 inst
.error
= BAD_PC
;
3830 if (skip_past_comma (&str
) == FAIL
3831 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
3833 inst
.error
= BAD_ARGS
;
3839 inst
.error
= BAD_PC
;
3844 as_tsktsk (_("rd and rm should be different in mul"));
3846 if (skip_past_comma (&str
) == FAIL
3847 || (rm
= reg_required_here (&str
, 8)) == FAIL
)
3849 inst
.error
= BAD_ARGS
;
3855 inst
.error
= BAD_PC
;
3869 /* Only one format "rd, rm, rs, rn". */
3870 skip_whitespace (str
);
3872 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
3874 inst
.error
= BAD_ARGS
;
3880 inst
.error
= BAD_PC
;
3884 if (skip_past_comma (&str
) == FAIL
3885 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
3887 inst
.error
= BAD_ARGS
;
3893 inst
.error
= BAD_PC
;
3898 as_tsktsk (_("rd and rm should be different in mla"));
3900 if (skip_past_comma (&str
) == FAIL
3901 || (rd
= reg_required_here (&str
, 8)) == FAIL
3902 || skip_past_comma (&str
) == FAIL
3903 || (rm
= reg_required_here (&str
, 12)) == FAIL
)
3905 inst
.error
= BAD_ARGS
;
3909 if (rd
== REG_PC
|| rm
== REG_PC
)
3911 inst
.error
= BAD_PC
;
3919 /* Expects *str -> the characters "acc0", possibly with leading blanks.
3920 Advances *str to the next non-alphanumeric.
3921 Returns 0, or else FAIL (in which case sets inst.error).
3923 (In a future XScale, there may be accumulators other than zero.
3924 At that time this routine and its callers can be upgraded to suit.) */
3927 accum0_required_here (str
)
3930 static char buff
[128]; /* Note the address is taken. Hence, static. */
3933 int result
= 0; /* The accum number. */
3935 skip_whitespace (p
);
3937 *str
= p
; /* Advance caller's string pointer too. */
3942 *--p
= 0; /* Aap nul into input buffer at non-alnum. */
3944 if (! ( streq (*str
, "acc0") || streq (*str
, "ACC0")))
3946 sprintf (buff
, _("acc0 expected, not '%.100s'"), *str
);
3951 *p
= c
; /* Unzap. */
3952 *str
= p
; /* Caller's string pointer to after match. */
3956 /* Expects **str -> after a comma. May be leading blanks.
3957 Advances *str, recognizing a load mode, and setting inst.instruction.
3958 Returns rn, or else FAIL (in which case may set inst.error
3959 and not advance str)
3961 Note: doesn't know Rd, so no err checks that require such knowledge. */
3964 ld_mode_required_here (string
)
3967 char * str
= * string
;
3971 skip_whitespace (str
);
3977 skip_whitespace (str
);
3979 if ((rn
= reg_required_here (& str
, 16)) == FAIL
)
3982 skip_whitespace (str
);
3988 if (skip_past_comma (& str
) == SUCCESS
)
3990 /* [Rn],... (post inc) */
3991 if (ldst_extend_v4 (&str
) == FAIL
)
3996 skip_whitespace (str
);
4001 inst
.instruction
|= WRITE_BACK
;
4004 inst
.instruction
|= INDEX_UP
| HWOFFSET_IMM
;
4010 if (skip_past_comma (& str
) == FAIL
)
4012 inst
.error
= _("pre-indexed expression expected");
4018 if (ldst_extend_v4 (&str
) == FAIL
)
4021 skip_whitespace (str
);
4023 if (* str
++ != ']')
4025 inst
.error
= _("missing ]");
4029 skip_whitespace (str
);
4034 inst
.instruction
|= WRITE_BACK
;
4038 else if (* str
== '=') /* ldr's "r,=label" syntax */
4039 /* We should never reach here, because <text> = <expression> is
4040 caught gas/read.c read_a_source_file() as a .set operation. */
4042 else /* PC +- 8 bit immediate offset. */
4044 if (my_get_expression (& inst
.reloc
.exp
, & str
))
4047 inst
.instruction
|= HWOFFSET_IMM
; /* The I bit. */
4048 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
4049 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
4050 inst
.reloc
.pc_rel
= 1;
4051 inst
.instruction
|= (REG_PC
<< 16);
4057 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
4063 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
4064 SMLAxy{cond} Rd,Rm,Rs,Rn
4065 SMLAWy{cond} Rd,Rm,Rs,Rn
4066 Error if any register is R15. */
4074 skip_whitespace (str
);
4076 if ((rd
= reg_required_here (& str
, 16)) == FAIL
4077 || skip_past_comma (& str
) == FAIL
4078 || (rm
= reg_required_here (& str
, 0)) == FAIL
4079 || skip_past_comma (& str
) == FAIL
4080 || (rs
= reg_required_here (& str
, 8)) == FAIL
4081 || skip_past_comma (& str
) == FAIL
4082 || (rn
= reg_required_here (& str
, 12)) == FAIL
)
4083 inst
.error
= BAD_ARGS
;
4085 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
|| rn
== REG_PC
)
4086 inst
.error
= BAD_PC
;
4092 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
4093 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
4094 Error if any register is R15.
4095 Warning if Rdlo == Rdhi. */
4101 int rdlo
, rdhi
, rm
, rs
;
4103 skip_whitespace (str
);
4105 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
4106 || skip_past_comma (& str
) == FAIL
4107 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
4108 || skip_past_comma (& str
) == FAIL
4109 || (rm
= reg_required_here (& str
, 0)) == FAIL
4110 || skip_past_comma (& str
) == FAIL
4111 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
4113 inst
.error
= BAD_ARGS
;
4117 if (rdlo
== REG_PC
|| rdhi
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
4119 inst
.error
= BAD_PC
;
4124 as_tsktsk (_("rdhi and rdlo must be different"));
4129 /* ARM V5E (El Segundo) signed-multiply (argument parse)
4130 SMULxy{cond} Rd,Rm,Rs
4131 Error if any register is R15. */
4139 skip_whitespace (str
);
4141 if ((rd
= reg_required_here (& str
, 16)) == FAIL
4142 || skip_past_comma (& str
) == FAIL
4143 || (rm
= reg_required_here (& str
, 0)) == FAIL
4144 || skip_past_comma (& str
) == FAIL
4145 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
4146 inst
.error
= BAD_ARGS
;
4148 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
4149 inst
.error
= BAD_PC
;
4155 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
4156 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
4157 Error if any register is R15. */
4165 skip_whitespace (str
);
4167 if ((rd
= reg_required_here (& str
, 12)) == FAIL
4168 || skip_past_comma (& str
) == FAIL
4169 || (rm
= reg_required_here (& str
, 0)) == FAIL
4170 || skip_past_comma (& str
) == FAIL
4171 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
4172 inst
.error
= BAD_ARGS
;
4174 else if (rd
== REG_PC
|| rm
== REG_PC
|| rn
== REG_PC
)
4175 inst
.error
= BAD_PC
;
4181 /* ARM V5E (el Segundo)
4182 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4183 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4185 These are equivalent to the XScale instructions MAR and MRA,
4186 respectively, when coproc == 0, opcode == 0, and CRm == 0.
4188 Result unpredicatable if Rd or Rn is R15. */
4196 skip_whitespace (str
);
4198 if (co_proc_number (& str
) == FAIL
)
4201 inst
.error
= BAD_ARGS
;
4205 if (skip_past_comma (& str
) == FAIL
4206 || cp_opc_expr (& str
, 4, 4) == FAIL
)
4209 inst
.error
= BAD_ARGS
;
4213 if (skip_past_comma (& str
) == FAIL
4214 || (rd
= reg_required_here (& str
, 12)) == FAIL
)
4217 inst
.error
= BAD_ARGS
;
4221 if (skip_past_comma (& str
) == FAIL
4222 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
4225 inst
.error
= BAD_ARGS
;
4229 /* Unpredictable result if rd or rn is R15. */
4230 if (rd
== REG_PC
|| rn
== REG_PC
)
4232 (_("Warning: instruction unpredictable when using r15"));
4234 if (skip_past_comma (& str
) == FAIL
4235 || cp_reg_required_here (& str
, 0) == FAIL
)
4238 inst
.error
= BAD_ARGS
;
4245 /* ARM V5 count-leading-zeroes instruction (argument parse)
4246 CLZ{<cond>} <Rd>, <Rm>
4247 Condition defaults to COND_ALWAYS.
4248 Error if Rd or Rm are R15. */
4256 skip_whitespace (str
);
4258 if (((rd
= reg_required_here (& str
, 12)) == FAIL
)
4259 || (skip_past_comma (& str
) == FAIL
)
4260 || ((rm
= reg_required_here (& str
, 0)) == FAIL
))
4261 inst
.error
= BAD_ARGS
;
4263 else if (rd
== REG_PC
|| rm
== REG_PC
)
4264 inst
.error
= BAD_PC
;
4270 /* ARM V5 (argument parse)
4271 LDC2{L} <coproc>, <CRd>, <addressing mode>
4272 STC2{L} <coproc>, <CRd>, <addressing mode>
4273 Instruction is not conditional, and has 0xf in the codition field.
4274 Otherwise, it's the same as LDC/STC. */
4280 skip_whitespace (str
);
4282 if (co_proc_number (& str
) == FAIL
)
4285 inst
.error
= BAD_ARGS
;
4287 else if (skip_past_comma (& str
) == FAIL
4288 || cp_reg_required_here (& str
, 12) == FAIL
)
4291 inst
.error
= BAD_ARGS
;
4293 else if (skip_past_comma (& str
) == FAIL
4294 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
4297 inst
.error
= BAD_ARGS
;
4303 /* ARM V5 (argument parse)
4304 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
4305 Instruction is not conditional, and has 0xf in the condition field.
4306 Otherwise, it's the same as CDP. */
4312 skip_whitespace (str
);
4314 if (co_proc_number (& str
) == FAIL
)
4317 inst
.error
= BAD_ARGS
;
4321 if (skip_past_comma (& str
) == FAIL
4322 || cp_opc_expr (& str
, 20,4) == FAIL
)
4325 inst
.error
= BAD_ARGS
;
4329 if (skip_past_comma (& str
) == FAIL
4330 || cp_reg_required_here (& str
, 12) == FAIL
)
4333 inst
.error
= BAD_ARGS
;
4337 if (skip_past_comma (& str
) == FAIL
4338 || cp_reg_required_here (& str
, 16) == FAIL
)
4341 inst
.error
= BAD_ARGS
;
4345 if (skip_past_comma (& str
) == FAIL
4346 || cp_reg_required_here (& str
, 0) == FAIL
)
4349 inst
.error
= BAD_ARGS
;
4353 if (skip_past_comma (& str
) == SUCCESS
)
4355 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
4358 inst
.error
= BAD_ARGS
;
4366 /* ARM V5 (argument parse)
4367 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4368 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4369 Instruction is not conditional, and has 0xf in the condition field.
4370 Otherwise, it's the same as MCR/MRC. */
4376 skip_whitespace (str
);
4378 if (co_proc_number (& str
) == FAIL
)
4381 inst
.error
= BAD_ARGS
;
4385 if (skip_past_comma (& str
) == FAIL
4386 || cp_opc_expr (& str
, 21, 3) == FAIL
)
4389 inst
.error
= BAD_ARGS
;
4393 if (skip_past_comma (& str
) == FAIL
4394 || reg_required_here (& str
, 12) == FAIL
)
4397 inst
.error
= BAD_ARGS
;
4401 if (skip_past_comma (& str
) == FAIL
4402 || cp_reg_required_here (& str
, 16) == FAIL
)
4405 inst
.error
= BAD_ARGS
;
4409 if (skip_past_comma (& str
) == FAIL
4410 || cp_reg_required_here (& str
, 0) == FAIL
)
4413 inst
.error
= BAD_ARGS
;
4417 if (skip_past_comma (& str
) == SUCCESS
)
4419 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
4422 inst
.error
= BAD_ARGS
;
4430 /* ARM v5TEJ. Jump to Jazelle code. */
4437 skip_whitespace (str
);
4439 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
4441 inst
.error
= BAD_ARGS
;
4445 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
4447 as_tsktsk (_("use of r15 in bxj is not really useful"));
4452 /* THUMB V5 breakpoint instruction (argument parse)
4460 unsigned long number
;
4462 skip_whitespace (str
);
4464 /* Allow optional leading '#'. */
4465 if (is_immediate_prefix (*str
))
4468 memset (& expr
, '\0', sizeof (expr
));
4469 if (my_get_expression (& expr
, & str
)
4470 || (expr
.X_op
!= O_constant
4471 /* As a convenience we allow 'bkpt' without an operand. */
4472 && expr
.X_op
!= O_absent
))
4474 inst
.error
= _("bad expression");
4478 number
= expr
.X_add_number
;
4480 /* Check it fits an 8 bit unsigned. */
4481 if (number
!= (number
& 0xff))
4483 inst
.error
= _("immediate value out of range");
4487 inst
.instruction
|= number
;
4492 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
4493 Expects inst.instruction is set for BLX(1).
4494 Note: this is cloned from do_branch, and the reloc changed to be a
4495 new one that can cope with setting one extra bit (the H bit). */
4501 if (my_get_expression (& inst
.reloc
.exp
, & str
))
4508 /* ScottB: February 5, 1998 */
4509 /* Check to see of PLT32 reloc required for the instruction. */
4511 /* arm_parse_reloc() works on input_line_pointer.
4512 We actually want to parse the operands to the branch instruction
4513 passed in 'str'. Save the input pointer and restore it later. */
4514 save_in
= input_line_pointer
;
4515 input_line_pointer
= str
;
4517 if (inst
.reloc
.exp
.X_op
== O_symbol
4519 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
4521 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
4522 inst
.reloc
.pc_rel
= 0;
4523 /* Modify str to point to after parsed operands, otherwise
4524 end_of_line() will complain about the (PLT) left in str. */
4525 str
= input_line_pointer
;
4529 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
4530 inst
.reloc
.pc_rel
= 1;
4533 input_line_pointer
= save_in
;
4536 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
4537 inst
.reloc
.pc_rel
= 1;
4538 #endif /* OBJ_ELF */
4543 /* ARM V5 branch-link-exchange instruction (argument parse)
4544 BLX <target_addr> ie BLX(1)
4545 BLX{<condition>} <Rm> ie BLX(2)
4546 Unfortunately, there are two different opcodes for this mnemonic.
4547 So, the insns[].value is not used, and the code here zaps values
4548 into inst.instruction.
4549 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
4558 skip_whitespace (mystr
);
4559 rm
= reg_required_here (& mystr
, 0);
4561 /* The above may set inst.error. Ignore his opinion. */
4566 /* Arg is a register.
4567 Use the condition code our caller put in inst.instruction.
4568 Pass ourselves off as a BX with a funny opcode. */
4569 inst
.instruction
|= 0x012fff30;
4574 /* This must be is BLX <target address>, no condition allowed. */
4575 if (inst
.instruction
!= COND_ALWAYS
)
4577 inst
.error
= BAD_COND
;
4581 inst
.instruction
= 0xfafffffe;
4583 /* Process like a B/BL, but with a different reloc.
4584 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
4589 /* ARM V5 Thumb BLX (argument parse)
4590 BLX <target_addr> which is BLX(1)
4591 BLX <Rm> which is BLX(2)
4592 Unfortunately, there are two different opcodes for this mnemonic.
4593 So, the tinsns[].value is not used, and the code here zaps values
4594 into inst.instruction. */
4603 skip_whitespace (mystr
);
4604 inst
.instruction
= 0x4780;
4606 /* Note that this call is to the ARM register recognizer. BLX(2)
4607 uses the ARM register space, not the Thumb one, so a call to
4608 thumb_reg() would be wrong. */
4609 rm
= reg_required_here (& mystr
, 3);
4614 /* It's BLX(2). The .instruction was zapped with rm & is final. */
4619 /* No ARM register. This must be BLX(1). Change the .instruction. */
4620 inst
.instruction
= 0xf7ffeffe;
4623 if (my_get_expression (& inst
.reloc
.exp
, & mystr
))
4626 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BLX
;
4627 inst
.reloc
.pc_rel
= 1;
4630 end_of_line (mystr
);
4633 /* ARM V5 breakpoint instruction (argument parse)
4634 BKPT <16 bit unsigned immediate>
4635 Instruction is not conditional.
4636 The bit pattern given in insns[] has the COND_ALWAYS condition,
4637 and it is an error if the caller tried to override that. */
4644 unsigned long number
;
4646 skip_whitespace (str
);
4648 /* Allow optional leading '#'. */
4649 if (is_immediate_prefix (* str
))
4652 memset (& expr
, '\0', sizeof (expr
));
4654 if (my_get_expression (& expr
, & str
)
4655 || (expr
.X_op
!= O_constant
4656 /* As a convenience we allow 'bkpt' without an operand. */
4657 && expr
.X_op
!= O_absent
))
4659 inst
.error
= _("bad expression");
4663 number
= expr
.X_add_number
;
4665 /* Check it fits a 16 bit unsigned. */
4666 if (number
!= (number
& 0xffff))
4668 inst
.error
= _("immediate value out of range");
4672 /* Top 12 of 16 bits to bits 19:8. */
4673 inst
.instruction
|= (number
& 0xfff0) << 4;
4675 /* Bottom 4 of 16 bits to bits 3:0. */
4676 inst
.instruction
|= number
& 0xf;
4681 static unsigned long check_iwmmxt_insn
PARAMS ((char *, enum iwmmxt_insn_type
, int));
4683 /* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
4685 static unsigned long
4686 check_iwmmxt_insn (str
, insn_type
, immediate_size
)
4688 enum iwmmxt_insn_type insn_type
;
4692 const char * inst_error
;
4694 unsigned long number
;
4696 inst_error
= inst
.error
;
4698 inst
.error
= BAD_ARGS
;
4699 skip_whitespace (str
);
4704 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
4709 if ((wreg_required_here (&str
, 0, IWMMXT_REG_WR
)) == FAIL
)
4714 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
4715 || skip_past_comma (&str
) == FAIL
4716 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
))
4721 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
4722 || skip_past_comma (&str
) == FAIL
4723 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4724 || skip_past_comma (&str
) == FAIL
4725 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
))
4730 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
4731 || skip_past_comma (&str
) == FAIL
4732 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4733 || skip_past_comma (&str
) == FAIL
4734 || wreg_required_here (&str
, 0, IWMMXT_REG_WCG
) == FAIL
))
4739 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4740 || skip_past_comma (&str
) == FAIL
4741 || reg_required_here (&str
, 12) == FAIL
))
4746 if ((reg_required_here (&str
, 12) == FAIL
4747 || skip_past_comma (&str
) == FAIL
4748 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
))
4753 if ((wreg_required_here (&str
, 5, IWMMXT_REG_WR
) == FAIL
4754 || skip_past_comma (&str
) == FAIL
4755 || reg_required_here (&str
, 0) == FAIL
4756 || skip_past_comma (&str
) == FAIL
4757 || reg_required_here (&str
, 12) == FAIL
))
4762 if ((wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
4763 || skip_past_comma (&str
) == FAIL
4764 || reg_required_here (&str
, 12) == FAIL
4765 || skip_past_comma (&str
) == FAIL
4766 || reg_required_here (&str
, 16) == FAIL
))
4771 if ((reg_required_here (&str
, 12) == FAIL
4772 || skip_past_comma (&str
) == FAIL
4773 || reg_required_here (&str
, 16) == FAIL
4774 || skip_past_comma (&str
) == FAIL
4775 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
))
4780 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WC
) == FAIL
4781 || skip_past_comma (&str
) == FAIL
4782 || reg_required_here (&str
, 12) == FAIL
))
4787 if ((reg_required_here (&str
, 12) == FAIL
4788 || skip_past_comma (&str
) == FAIL
4789 || wreg_required_here (&str
, 16, IWMMXT_REG_WC
) == FAIL
))
4794 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4795 || skip_past_comma (&str
) == FAIL
4796 || reg_required_here (&str
, 12) == FAIL
4797 || skip_past_comma (&str
) == FAIL
))
4802 if ((reg_required_here (&str
, 12) == FAIL
4803 || skip_past_comma (&str
) == FAIL
))
4808 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
4809 || skip_past_comma (&str
) == FAIL
4810 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4811 || skip_past_comma (&str
) == FAIL
4812 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
4813 || skip_past_comma (&str
) == FAIL
))
4818 if ((reg_required_here (&str
, 12) == FAIL
4819 || skip_past_comma (&str
) == FAIL
4820 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4821 || skip_past_comma (&str
) == FAIL
))
4826 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
4827 || skip_past_comma (&str
) == FAIL
4828 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4829 || skip_past_comma (&str
) == FAIL
))
4834 if (immediate_size
== 0)
4837 inst
.error
= inst_error
;
4842 skip_whitespace (str
);
4844 /* Allow optional leading '#'. */
4845 if (is_immediate_prefix (* str
))
4848 memset (& expr
, '\0', sizeof (expr
));
4850 if (my_get_expression (& expr
, & str
) || (expr
.X_op
!= O_constant
))
4852 inst
.error
= _("bad or missing expression");
4856 number
= expr
.X_add_number
;
4858 if (number
!= (number
& immediate_size
))
4860 inst
.error
= _("immediate value out of range");
4864 inst
.error
= inst_error
;
4870 do_iwmmxt_byte_addr (str
)
4873 int op
= (inst
.instruction
& 0x300) >> 8;
4876 inst
.instruction
&= ~0x300;
4877 inst
.instruction
|= (op
& 1) << 22 | (op
& 2) << 7;
4879 skip_whitespace (str
);
4881 if ((reg
= wreg_required_here (&str
, 12, IWMMXT_REG_WR_OR_WC
)) == FAIL
4882 || skip_past_comma (& str
) == FAIL
4883 || cp_byte_address_required_here (&str
) == FAIL
)
4886 inst
.error
= BAD_ARGS
;
4891 if (wc_register (reg
))
4893 inst
.instruction
|= 0xf0000100;
4894 inst
.instruction
&= ~0x00400000;
4899 do_iwmmxt_tandc (str
)
4904 reg
= check_iwmmxt_insn (str
, check_rd
, 0);
4906 if (reg
!= REG_PC
&& !inst
.error
)
4907 inst
.error
= _("only r15 allowed here");
4912 do_iwmmxt_tbcst (str
)
4915 check_iwmmxt_insn (str
, check_tbcst
, 0);
4921 do_iwmmxt_textrc (str
)
4924 unsigned long number
;
4926 if ((number
= check_iwmmxt_insn (str
, check_textrc
, 7)) == (unsigned long) FAIL
)
4929 inst
.instruction
|= number
& 0x7;
4934 do_iwmmxt_textrm (str
)
4937 unsigned long number
;
4939 if ((number
= check_iwmmxt_insn (str
, check_textrm
, 7)) == (unsigned long) FAIL
)
4942 inst
.instruction
|= number
& 0x7;
4946 do_iwmmxt_tinsr (str
)
4949 unsigned long number
;
4951 if ((number
= check_iwmmxt_insn (str
, check_tinsr
, 7)) == (unsigned long) FAIL
)
4954 inst
.instruction
|= number
& 0x7;
4959 do_iwmmxt_tmcr (str
)
4962 check_iwmmxt_insn (str
, check_tmcr
, 0);
4968 do_iwmmxt_tmcrr (str
)
4971 check_iwmmxt_insn (str
, check_tmcrr
, 0);
4977 do_iwmmxt_tmia (str
)
4980 check_iwmmxt_insn (str
, check_tmia
, 0);
4986 do_iwmmxt_tmovmsk (str
)
4989 check_iwmmxt_insn (str
, check_tmovmsk
, 0);
4995 do_iwmmxt_tmrc (str
)
4998 check_iwmmxt_insn (str
, check_tmrc
, 0);
5004 do_iwmmxt_tmrrc (str
)
5007 check_iwmmxt_insn (str
, check_tmrrc
, 0);
5013 do_iwmmxt_torc (str
)
5016 check_iwmmxt_insn (str
, check_rd
, 0);
5021 do_iwmmxt_waligni (str
)
5024 unsigned long number
;
5026 if ((number
= check_iwmmxt_insn (str
, check_waligni
, 7)) == (unsigned long) FAIL
)
5029 inst
.instruction
|= ((number
& 0x7) << 20);
5034 do_iwmmxt_wmov (str
)
5037 if (check_iwmmxt_insn (str
, check_wrwr
, 0) == (unsigned long) FAIL
)
5040 inst
.instruction
|= ((inst
.instruction
>> 16) & 0xf);
5045 do_iwmmxt_word_addr (str
)
5048 int op
= (inst
.instruction
& 0x300) >> 8;
5051 inst
.instruction
&= ~0x300;
5052 inst
.instruction
|= (op
& 1) << 22 | (op
& 2) << 7;
5054 skip_whitespace (str
);
5056 if ((reg
= wreg_required_here (&str
, 12, IWMMXT_REG_WR_OR_WC
)) == FAIL
5057 || skip_past_comma (& str
) == FAIL
5058 || cp_address_required_here (& str
, CP_WB_OK
) == FAIL
)
5061 inst
.error
= BAD_ARGS
;
5066 if (wc_register (reg
))
5068 inst
.instruction
|= 0xf0000100;
5069 inst
.instruction
&= ~0x00400000;
5074 do_iwmmxt_wrwr (str
)
5077 check_iwmmxt_insn (str
, check_wrwr
, 0);
5083 do_iwmmxt_wrwrwcg (str
)
5086 check_iwmmxt_insn (str
, check_wrwrwcg
, 0);
5092 do_iwmmxt_wrwrwr (str
)
5095 check_iwmmxt_insn (str
, check_wrwrwr
, 0);
5101 do_iwmmxt_wshufh (str
)
5104 unsigned long number
;
5106 if ((number
= check_iwmmxt_insn (str
, check_wshufh
, 0xff)) == (unsigned long) FAIL
)
5109 inst
.instruction
|= ((number
& 0xf0) << 16) | (number
& 0xf);
5114 do_iwmmxt_wzero (str
)
5117 if (check_iwmmxt_insn (str
, check_wr
, 0) == (unsigned long) FAIL
)
5120 inst
.instruction
|= ((inst
.instruction
& 0xf) << 12) | ((inst
.instruction
& 0xf) << 16);
5124 /* Xscale multiply-accumulate (argument parse)
5127 MIAxycc acc0,Rm,Rs. */
5136 if (accum0_required_here (& str
) == FAIL
)
5137 inst
.error
= ERR_NO_ACCUM
;
5139 else if (skip_past_comma (& str
) == FAIL
5140 || (rm
= reg_required_here (& str
, 0)) == FAIL
)
5141 inst
.error
= BAD_ARGS
;
5143 else if (skip_past_comma (& str
) == FAIL
5144 || (rs
= reg_required_here (& str
, 12)) == FAIL
)
5145 inst
.error
= BAD_ARGS
;
5147 /* inst.instruction has now been zapped with both rm and rs. */
5148 else if (rm
== REG_PC
|| rs
== REG_PC
)
5149 inst
.error
= BAD_PC
; /* Undefined result if rm or rs is R15. */
5155 /* Xscale move-accumulator-register (argument parse)
5157 MARcc acc0,RdLo,RdHi. */
5165 if (accum0_required_here (& str
) == FAIL
)
5166 inst
.error
= ERR_NO_ACCUM
;
5168 else if (skip_past_comma (& str
) == FAIL
5169 || (rdlo
= reg_required_here (& str
, 12)) == FAIL
)
5170 inst
.error
= BAD_ARGS
;
5172 else if (skip_past_comma (& str
) == FAIL
5173 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
5174 inst
.error
= BAD_ARGS
;
5176 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5177 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
5178 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
5184 /* Xscale move-register-accumulator (argument parse)
5186 MRAcc RdLo,RdHi,acc0. */
5195 skip_whitespace (str
);
5197 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
)
5198 inst
.error
= BAD_ARGS
;
5200 else if (skip_past_comma (& str
) == FAIL
5201 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
5202 inst
.error
= BAD_ARGS
;
5204 else if (skip_past_comma (& str
) == FAIL
5205 || accum0_required_here (& str
) == FAIL
)
5206 inst
.error
= ERR_NO_ACCUM
;
5208 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5209 else if (rdlo
== rdhi
)
5210 inst
.error
= BAD_ARGS
; /* Undefined result if 2 writes to same reg. */
5212 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
5213 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
5218 /* ARMv5TE: Preload-Cache
5222 Syntactically, like LDR with B=1, W=0, L=1. */
5230 skip_whitespace (str
);
5234 inst
.error
= _("'[' expected after PLD mnemonic");
5239 skip_whitespace (str
);
5241 if ((rd
= reg_required_here (& str
, 16)) == FAIL
)
5244 skip_whitespace (str
);
5250 skip_whitespace (str
);
5252 /* Post-indexed addressing is not allowed with PLD. */
5253 if (skip_past_comma (&str
) == SUCCESS
)
5256 = _("post-indexed expression used in preload instruction");
5259 else if (*str
== '!') /* [Rn]! */
5261 inst
.error
= _("writeback used in preload instruction");
5265 inst
.instruction
|= INDEX_UP
| PRE_INDEX
;
5267 else /* [Rn, ...] */
5269 if (skip_past_comma (& str
) == FAIL
)
5271 inst
.error
= _("pre-indexed expression expected");
5275 if (ldst_extend (&str
) == FAIL
)
5278 skip_whitespace (str
);
5282 inst
.error
= _("missing ]");
5287 skip_whitespace (str
);
5289 if (* str
== '!') /* [Rn]! */
5291 inst
.error
= _("writeback used in preload instruction");
5295 inst
.instruction
|= PRE_INDEX
;
5301 /* ARMv5TE load-consecutive (argument parse)
5314 skip_whitespace (str
);
5316 if ((rd
= reg_required_here (& str
, 12)) == FAIL
)
5318 inst
.error
= BAD_ARGS
;
5322 if (skip_past_comma (& str
) == FAIL
5323 || (rn
= ld_mode_required_here (& str
)) == FAIL
)
5326 inst
.error
= BAD_ARGS
;
5330 /* inst.instruction has now been zapped with Rd and the addressing mode. */
5331 if (rd
& 1) /* Unpredictable result if Rd is odd. */
5333 inst
.error
= _("destination register must be even");
5339 inst
.error
= _("r14 not allowed here");
5343 if (((rd
== rn
) || (rd
+ 1 == rn
))
5344 && ((inst
.instruction
& WRITE_BACK
)
5345 || (!(inst
.instruction
& PRE_INDEX
))))
5346 as_warn (_("pre/post-indexing used when modified address register is destination"));
5348 /* For an index-register load, the index register must not overlap the
5349 destination (even if not write-back). */
5350 if ((inst
.instruction
& V4_STR_BIT
) == 0
5351 && (inst
.instruction
& HWOFFSET_IMM
) == 0)
5353 int rm
= inst
.instruction
& 0x0000000f;
5355 if (rm
== rd
|| (rm
== rd
+ 1))
5356 as_warn (_("ldrd destination registers must not overlap index register"));
5362 /* Returns the index into fp_values of a floating point number,
5363 or -1 if not in the table. */
5366 my_get_float_expression (str
)
5369 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
5375 memset (words
, 0, MAX_LITTLENUMS
* sizeof (LITTLENUM_TYPE
));
5377 /* Look for a raw floating point number. */
5378 if ((save_in
= atof_ieee (*str
, 'x', words
)) != NULL
5379 && is_end_of_line
[(unsigned char) *save_in
])
5381 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
5383 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
5385 if (words
[j
] != fp_values
[i
][j
])
5389 if (j
== MAX_LITTLENUMS
)
5397 /* Try and parse a more complex expression, this will probably fail
5398 unless the code uses a floating point prefix (eg "0f"). */
5399 save_in
= input_line_pointer
;
5400 input_line_pointer
= *str
;
5401 if (expression (&exp
) == absolute_section
5402 && exp
.X_op
== O_big
5403 && exp
.X_add_number
< 0)
5405 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
5407 if (gen_to_words (words
, 5, (long) 15) == 0)
5409 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
5411 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
5413 if (words
[j
] != fp_values
[i
][j
])
5417 if (j
== MAX_LITTLENUMS
)
5419 *str
= input_line_pointer
;
5420 input_line_pointer
= save_in
;
5427 *str
= input_line_pointer
;
5428 input_line_pointer
= save_in
;
5432 /* Return TRUE if anything in the expression is a bignum. */
5435 walk_no_bignums (sp
)
5438 if (symbol_get_value_expression (sp
)->X_op
== O_big
)
5441 if (symbol_get_value_expression (sp
)->X_add_symbol
)
5443 return (walk_no_bignums (symbol_get_value_expression (sp
)->X_add_symbol
)
5444 || (symbol_get_value_expression (sp
)->X_op_symbol
5445 && walk_no_bignums (symbol_get_value_expression (sp
)->X_op_symbol
)));
5451 static int in_my_get_expression
= 0;
5454 my_get_expression (ep
, str
)
5461 save_in
= input_line_pointer
;
5462 input_line_pointer
= *str
;
5463 in_my_get_expression
= 1;
5464 seg
= expression (ep
);
5465 in_my_get_expression
= 0;
5467 if (ep
->X_op
== O_illegal
)
5469 /* We found a bad expression in md_operand(). */
5470 *str
= input_line_pointer
;
5471 input_line_pointer
= save_in
;
5476 if (seg
!= absolute_section
5477 && seg
!= text_section
5478 && seg
!= data_section
5479 && seg
!= bss_section
5480 && seg
!= undefined_section
)
5482 inst
.error
= _("bad_segment");
5483 *str
= input_line_pointer
;
5484 input_line_pointer
= save_in
;
5489 /* Get rid of any bignums now, so that we don't generate an error for which
5490 we can't establish a line number later on. Big numbers are never valid
5491 in instructions, which is where this routine is always called. */
5492 if (ep
->X_op
== O_big
5493 || (ep
->X_add_symbol
5494 && (walk_no_bignums (ep
->X_add_symbol
)
5496 && walk_no_bignums (ep
->X_op_symbol
)))))
5498 inst
.error
= _("invalid constant");
5499 *str
= input_line_pointer
;
5500 input_line_pointer
= save_in
;
5504 *str
= input_line_pointer
;
5505 input_line_pointer
= save_in
;
5509 /* We handle all bad expressions here, so that we can report the faulty
5510 instruction in the error message. */
5515 if (in_my_get_expression
)
5517 expr
->X_op
= O_illegal
;
5518 if (inst
.error
== NULL
)
5519 inst
.error
= _("bad expression");
5523 /* UNRESTRICT should be one if <shift> <register> is permitted for this
5527 decode_shift (str
, unrestrict
)
5531 const struct asm_shift_name
* shift
;
5535 skip_whitespace (* str
);
5537 for (p
= * str
; ISALPHA (* p
); p
++)
5542 inst
.error
= _("shift expression expected");
5548 shift
= (const struct asm_shift_name
*) hash_find (arm_shift_hsh
, * str
);
5553 inst
.error
= _("shift expression expected");
5557 assert (shift
->properties
->index
== shift_properties
[shift
->properties
->index
].index
);
5559 if (shift
->properties
->index
== SHIFT_RRX
)
5562 inst
.instruction
|= shift
->properties
->bit_field
;
5566 skip_whitespace (p
);
5568 if (unrestrict
&& reg_required_here (& p
, 8) != FAIL
)
5570 inst
.instruction
|= shift
->properties
->bit_field
| SHIFT_BY_REG
;
5574 else if (! is_immediate_prefix (* p
))
5576 inst
.error
= (unrestrict
5577 ? _("shift requires register or #expression")
5578 : _("shift requires #expression"));
5586 if (my_get_expression (& inst
.reloc
.exp
, & p
))
5589 /* Validate some simple #expressions. */
5590 if (inst
.reloc
.exp
.X_op
== O_constant
)
5592 unsigned num
= inst
.reloc
.exp
.X_add_number
;
5594 /* Reject operations greater than 32. */
5596 /* Reject a shift of 0 unless the mode allows it. */
5597 || (num
== 0 && shift
->properties
->allows_0
== 0)
5598 /* Reject a shift of 32 unless the mode allows it. */
5599 || (num
== 32 && shift
->properties
->allows_32
== 0)
5602 /* As a special case we allow a shift of zero for
5603 modes that do not support it to be recoded as an
5604 logical shift left of zero (ie nothing). We warn
5605 about this though. */
5608 as_warn (_("shift of 0 ignored."));
5609 shift
= & shift_names
[0];
5610 assert (shift
->properties
->index
== SHIFT_LSL
);
5614 inst
.error
= _("invalid immediate shift");
5619 /* Shifts of 32 are encoded as 0, for those shifts that
5624 inst
.instruction
|= (num
<< 7) | shift
->properties
->bit_field
;
5628 inst
.reloc
.type
= BFD_RELOC_ARM_SHIFT_IMM
;
5629 inst
.reloc
.pc_rel
= 0;
5630 inst
.instruction
|= shift
->properties
->bit_field
;
5637 /* Do those data_ops which can take a negative immediate constant
5638 by altering the instuction. A bit of a hack really.
5642 by inverting the second operand, and
5645 by negating the second operand. */
5648 negate_data_op (instruction
, value
)
5649 unsigned long * instruction
;
5650 unsigned long value
;
5653 unsigned long negated
, inverted
;
5655 negated
= validate_immediate (-value
);
5656 inverted
= validate_immediate (~value
);
5658 op
= (*instruction
>> DATA_OP_SHIFT
) & 0xf;
5661 /* First negates. */
5662 case OPCODE_SUB
: /* ADD <-> SUB */
5663 new_inst
= OPCODE_ADD
;
5668 new_inst
= OPCODE_SUB
;
5672 case OPCODE_CMP
: /* CMP <-> CMN */
5673 new_inst
= OPCODE_CMN
;
5678 new_inst
= OPCODE_CMP
;
5682 /* Now Inverted ops. */
5683 case OPCODE_MOV
: /* MOV <-> MVN */
5684 new_inst
= OPCODE_MVN
;
5689 new_inst
= OPCODE_MOV
;
5693 case OPCODE_AND
: /* AND <-> BIC */
5694 new_inst
= OPCODE_BIC
;
5699 new_inst
= OPCODE_AND
;
5703 case OPCODE_ADC
: /* ADC <-> SBC */
5704 new_inst
= OPCODE_SBC
;
5709 new_inst
= OPCODE_ADC
;
5713 /* We cannot do anything. */
5718 if (value
== (unsigned) FAIL
)
5721 *instruction
&= OPCODE_MASK
;
5722 *instruction
|= new_inst
<< DATA_OP_SHIFT
;
5733 skip_whitespace (* str
);
5735 if (reg_required_here (str
, 0) != FAIL
)
5737 if (skip_past_comma (str
) == SUCCESS
)
5738 /* Shift operation on register. */
5739 return decode_shift (str
, NO_SHIFT_RESTRICT
);
5745 /* Immediate expression. */
5746 if (is_immediate_prefix (**str
))
5751 if (my_get_expression (&inst
.reloc
.exp
, str
))
5754 if (inst
.reloc
.exp
.X_add_symbol
)
5756 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
5757 inst
.reloc
.pc_rel
= 0;
5761 if (skip_past_comma (str
) == SUCCESS
)
5763 /* #x, y -- ie explicit rotation by Y. */
5764 if (my_get_expression (&expr
, str
))
5767 if (expr
.X_op
!= O_constant
)
5769 inst
.error
= _("constant expression expected");
5773 /* Rotate must be a multiple of 2. */
5774 if (((unsigned) expr
.X_add_number
) > 30
5775 || (expr
.X_add_number
& 1) != 0
5776 || ((unsigned) inst
.reloc
.exp
.X_add_number
) > 255)
5778 inst
.error
= _("invalid constant");
5781 inst
.instruction
|= INST_IMMEDIATE
;
5782 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
5783 inst
.instruction
|= expr
.X_add_number
<< 7;
5787 /* Implicit rotation, select a suitable one. */
5788 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
5792 /* Can't be done. Perhaps the code reads something like
5793 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
5794 if ((value
= negate_data_op (&inst
.instruction
,
5795 inst
.reloc
.exp
.X_add_number
))
5798 inst
.error
= _("invalid constant");
5803 inst
.instruction
|= value
;
5806 inst
.instruction
|= INST_IMMEDIATE
;
5811 inst
.error
= _("register or shift expression expected");
5820 skip_whitespace (* str
);
5822 if (fp_reg_required_here (str
, 0) != FAIL
)
5826 /* Immediate expression. */
5827 if (*((*str
)++) == '#')
5833 skip_whitespace (* str
);
5835 /* First try and match exact strings, this is to guarantee
5836 that some formats will work even for cross assembly. */
5838 for (i
= 0; fp_const
[i
]; i
++)
5840 if (strncmp (*str
, fp_const
[i
], strlen (fp_const
[i
])) == 0)
5844 *str
+= strlen (fp_const
[i
]);
5845 if (is_end_of_line
[(unsigned char) **str
])
5847 inst
.instruction
|= i
+ 8;
5854 /* Just because we didn't get a match doesn't mean that the
5855 constant isn't valid, just that it is in a format that we
5856 don't automatically recognize. Try parsing it with
5857 the standard expression routines. */
5858 if ((i
= my_get_float_expression (str
)) >= 0)
5860 inst
.instruction
|= i
+ 8;
5864 inst
.error
= _("invalid floating point immediate expression");
5868 _("floating point register or immediate expression expected");
5877 skip_whitespace (str
);
5879 if (reg_required_here (&str
, 12) == FAIL
5880 || skip_past_comma (&str
) == FAIL
5881 || reg_required_here (&str
, 16) == FAIL
5882 || skip_past_comma (&str
) == FAIL
5883 || data_op2 (&str
) == FAIL
)
5886 inst
.error
= BAD_ARGS
;
5898 /* This is a pseudo-op of the form "adr rd, label" to be converted
5899 into a relative address of the form "add rd, pc, #label-.-8". */
5900 skip_whitespace (str
);
5902 if (reg_required_here (&str
, 12) == FAIL
5903 || skip_past_comma (&str
) == FAIL
5904 || my_get_expression (&inst
.reloc
.exp
, &str
))
5907 inst
.error
= BAD_ARGS
;
5911 /* Frag hacking will turn this into a sub instruction if the offset turns
5912 out to be negative. */
5913 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
5914 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust. */
5915 inst
.reloc
.pc_rel
= 1;
5924 /* This is a pseudo-op of the form "adrl rd, label" to be converted
5925 into a relative address of the form:
5926 add rd, pc, #low(label-.-8)"
5927 add rd, rd, #high(label-.-8)" */
5929 skip_whitespace (str
);
5931 if (reg_required_here (&str
, 12) == FAIL
5932 || skip_past_comma (&str
) == FAIL
5933 || my_get_expression (&inst
.reloc
.exp
, &str
))
5936 inst
.error
= BAD_ARGS
;
5942 /* Frag hacking will turn this into a sub instruction if the offset turns
5943 out to be negative. */
5944 inst
.reloc
.type
= BFD_RELOC_ARM_ADRL_IMMEDIATE
;
5945 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust */
5946 inst
.reloc
.pc_rel
= 1;
5947 inst
.size
= INSN_SIZE
* 2;
5956 skip_whitespace (str
);
5958 if (reg_required_here (&str
, 16) == FAIL
)
5961 inst
.error
= BAD_ARGS
;
5965 if (skip_past_comma (&str
) == FAIL
5966 || data_op2 (&str
) == FAIL
)
5969 inst
.error
= BAD_ARGS
;
5981 skip_whitespace (str
);
5983 if (reg_required_here (&str
, 12) == FAIL
)
5986 inst
.error
= BAD_ARGS
;
5990 if (skip_past_comma (&str
) == FAIL
5991 || data_op2 (&str
) == FAIL
)
5994 inst
.error
= BAD_ARGS
;
6013 if (my_get_expression (& inst
.reloc
.exp
, str
))
6016 if (inst
.reloc
.exp
.X_op
== O_constant
)
6018 int value
= inst
.reloc
.exp
.X_add_number
;
6020 if (value
< -4095 || value
> 4095)
6022 inst
.error
= _("address offset too large");
6032 inst
.instruction
|= add
| value
;
6036 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
6037 inst
.reloc
.pc_rel
= 0;
6050 if (reg_required_here (str
, 0) == FAIL
)
6053 inst
.instruction
|= add
| OFFSET_REG
;
6054 if (skip_past_comma (str
) == SUCCESS
)
6055 return decode_shift (str
, SHIFT_RESTRICT
);
6069 skip_whitespace (str
);
6071 if ((conflict_reg
= reg_required_here (&str
, 12)) == FAIL
)
6074 inst
.error
= BAD_ARGS
;
6078 if (skip_past_comma (&str
) == FAIL
)
6080 inst
.error
= _("address expected");
6090 skip_whitespace (str
);
6092 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6095 /* Conflicts can occur on stores as well as loads. */
6096 conflict_reg
= (conflict_reg
== reg
);
6098 skip_whitespace (str
);
6104 if (skip_past_comma (&str
) == SUCCESS
)
6106 /* [Rn],... (post inc) */
6107 if (ldst_extend (&str
) == FAIL
)
6110 as_warn (_("%s register same as write-back base"),
6111 ((inst
.instruction
& LOAD_BIT
)
6112 ? _("destination") : _("source")));
6117 skip_whitespace (str
);
6122 as_warn (_("%s register same as write-back base"),
6123 ((inst
.instruction
& LOAD_BIT
)
6124 ? _("destination") : _("source")));
6126 inst
.instruction
|= WRITE_BACK
;
6129 inst
.instruction
|= INDEX_UP
;
6136 if (skip_past_comma (&str
) == FAIL
)
6138 inst
.error
= _("pre-indexed expression expected");
6143 if (ldst_extend (&str
) == FAIL
)
6146 skip_whitespace (str
);
6150 inst
.error
= _("missing ]");
6154 skip_whitespace (str
);
6159 as_warn (_("%s register same as write-back base"),
6160 ((inst
.instruction
& LOAD_BIT
)
6161 ? _("destination") : _("source")));
6163 inst
.instruction
|= WRITE_BACK
;
6167 else if (*str
== '=')
6169 if ((inst
.instruction
& LOAD_BIT
) == 0)
6171 inst
.error
= _("invalid pseudo operation");
6175 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6178 skip_whitespace (str
);
6180 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6183 if (inst
.reloc
.exp
.X_op
!= O_constant
6184 && inst
.reloc
.exp
.X_op
!= O_symbol
)
6186 inst
.error
= _("constant expression expected");
6190 if (inst
.reloc
.exp
.X_op
== O_constant
)
6192 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
6196 /* This can be done with a mov instruction. */
6197 inst
.instruction
&= LITERAL_MASK
;
6198 inst
.instruction
|= (INST_IMMEDIATE
6199 | (OPCODE_MOV
<< DATA_OP_SHIFT
));
6200 inst
.instruction
|= value
& 0xfff;
6205 value
= validate_immediate (~inst
.reloc
.exp
.X_add_number
);
6209 /* This can be done with a mvn instruction. */
6210 inst
.instruction
&= LITERAL_MASK
;
6211 inst
.instruction
|= (INST_IMMEDIATE
6212 | (OPCODE_MVN
<< DATA_OP_SHIFT
));
6213 inst
.instruction
|= value
& 0xfff;
6219 /* Insert into literal pool. */
6220 if (add_to_lit_pool () == FAIL
)
6223 inst
.error
= _("literal pool insertion failed");
6227 /* Change the instruction exp to point to the pool. */
6228 inst
.reloc
.type
= BFD_RELOC_ARM_LITERAL
;
6229 inst
.reloc
.pc_rel
= 1;
6230 inst
.instruction
|= (REG_PC
<< 16);
6235 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6238 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
6240 /* PC rel adjust. */
6241 inst
.reloc
.exp
.X_add_number
-= 8;
6243 inst
.reloc
.pc_rel
= 1;
6244 inst
.instruction
|= (REG_PC
<< 16);
6248 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
6259 skip_whitespace (str
);
6261 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
6264 inst
.error
= BAD_ARGS
;
6268 if (skip_past_comma (& str
) == FAIL
)
6270 inst
.error
= _("address expected");
6280 skip_whitespace (str
);
6282 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6285 /* ldrt/strt always use post-indexed addressing, so if the base is
6286 the same as Rd, we warn. */
6287 if (conflict_reg
== reg
)
6288 as_warn (_("%s register same as write-back base"),
6289 ((inst
.instruction
& LOAD_BIT
)
6290 ? _("destination") : _("source")));
6292 skip_whitespace (str
);
6298 if (skip_past_comma (&str
) == SUCCESS
)
6300 /* [Rn],... (post inc) */
6301 if (ldst_extend (&str
) == FAIL
)
6307 skip_whitespace (str
);
6309 /* Skip a write-back '!'. */
6313 inst
.instruction
|= INDEX_UP
;
6318 inst
.error
= _("post-indexed expression expected");
6324 inst
.error
= _("post-indexed expression expected");
6333 ldst_extend_v4 (str
)
6343 if (my_get_expression (& inst
.reloc
.exp
, str
))
6346 if (inst
.reloc
.exp
.X_op
== O_constant
)
6348 int value
= inst
.reloc
.exp
.X_add_number
;
6350 if (value
< -255 || value
> 255)
6352 inst
.error
= _("address offset too large");
6362 /* Halfword and signextension instructions have the
6363 immediate value split across bits 11..8 and bits 3..0. */
6364 inst
.instruction
|= (add
| HWOFFSET_IMM
6365 | ((value
>> 4) << 8) | (value
& 0xF));
6369 inst
.instruction
|= HWOFFSET_IMM
;
6370 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
6371 inst
.reloc
.pc_rel
= 0;
6384 if (reg_required_here (str
, 0) == FAIL
)
6387 inst
.instruction
|= add
;
6392 /* Halfword and signed-byte load/store operations. */
6401 skip_whitespace (str
);
6403 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
6406 inst
.error
= BAD_ARGS
;
6410 if (skip_past_comma (& str
) == FAIL
)
6412 inst
.error
= _("address expected");
6422 skip_whitespace (str
);
6424 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6427 /* Conflicts can occur on stores as well as loads. */
6428 conflict_reg
= (conflict_reg
== reg
);
6430 skip_whitespace (str
);
6436 if (skip_past_comma (&str
) == SUCCESS
)
6438 /* [Rn],... (post inc) */
6439 if (ldst_extend_v4 (&str
) == FAIL
)
6442 as_warn (_("%s register same as write-back base"),
6443 ((inst
.instruction
& LOAD_BIT
)
6444 ? _("destination") : _("source")));
6449 inst
.instruction
|= HWOFFSET_IMM
;
6451 skip_whitespace (str
);
6456 as_warn (_("%s register same as write-back base"),
6457 ((inst
.instruction
& LOAD_BIT
)
6458 ? _("destination") : _("source")));
6460 inst
.instruction
|= WRITE_BACK
;
6463 inst
.instruction
|= INDEX_UP
;
6470 if (skip_past_comma (&str
) == FAIL
)
6472 inst
.error
= _("pre-indexed expression expected");
6477 if (ldst_extend_v4 (&str
) == FAIL
)
6480 skip_whitespace (str
);
6484 inst
.error
= _("missing ]");
6488 skip_whitespace (str
);
6493 as_warn (_("%s register same as write-back base"),
6494 ((inst
.instruction
& LOAD_BIT
)
6495 ? _("destination") : _("source")));
6497 inst
.instruction
|= WRITE_BACK
;
6501 else if (*str
== '=')
6503 if ((inst
.instruction
& LOAD_BIT
) == 0)
6505 inst
.error
= _("invalid pseudo operation");
6509 /* XXX Does this work correctly for half-word/byte ops? */
6510 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6513 skip_whitespace (str
);
6515 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6518 if (inst
.reloc
.exp
.X_op
!= O_constant
6519 && inst
.reloc
.exp
.X_op
!= O_symbol
)
6521 inst
.error
= _("constant expression expected");
6525 if (inst
.reloc
.exp
.X_op
== O_constant
)
6527 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
6531 /* This can be done with a mov instruction. */
6532 inst
.instruction
&= LITERAL_MASK
;
6533 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MOV
<< DATA_OP_SHIFT
);
6534 inst
.instruction
|= value
& 0xfff;
6539 value
= validate_immediate (~ inst
.reloc
.exp
.X_add_number
);
6543 /* This can be done with a mvn instruction. */
6544 inst
.instruction
&= LITERAL_MASK
;
6545 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MVN
<< DATA_OP_SHIFT
);
6546 inst
.instruction
|= value
& 0xfff;
6552 /* Insert into literal pool. */
6553 if (add_to_lit_pool () == FAIL
)
6556 inst
.error
= _("literal pool insertion failed");
6560 /* Change the instruction exp to point to the pool. */
6561 inst
.instruction
|= HWOFFSET_IMM
;
6562 inst
.reloc
.type
= BFD_RELOC_ARM_HWLITERAL
;
6563 inst
.reloc
.pc_rel
= 1;
6564 inst
.instruction
|= (REG_PC
<< 16);
6569 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6572 inst
.instruction
|= HWOFFSET_IMM
;
6573 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
6575 /* PC rel adjust. */
6576 inst
.reloc
.exp
.X_add_number
-= 8;
6578 inst
.reloc
.pc_rel
= 1;
6579 inst
.instruction
|= (REG_PC
<< 16);
6583 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
6592 char * str
= * strp
;
6596 /* We come back here if we get ranges concatenated by '+' or '|'. */
6611 skip_whitespace (str
);
6613 if ((reg
= reg_required_here (& str
, -1)) == FAIL
)
6622 inst
.error
= _("bad range in register list");
6626 for (i
= cur_reg
+ 1; i
< reg
; i
++)
6628 if (range
& (1 << i
))
6630 (_("Warning: duplicated register (r%d) in register list"),
6638 if (range
& (1 << reg
))
6639 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
6641 else if (reg
<= cur_reg
)
6642 as_tsktsk (_("Warning: register range not in ascending order"));
6647 while (skip_past_comma (&str
) != FAIL
6648 || (in_range
= 1, *str
++ == '-'));
6650 skip_whitespace (str
);
6654 inst
.error
= _("missing `}'");
6662 if (my_get_expression (&expr
, &str
))
6665 if (expr
.X_op
== O_constant
)
6667 if (expr
.X_add_number
6668 != (expr
.X_add_number
& 0x0000ffff))
6670 inst
.error
= _("invalid register mask");
6674 if ((range
& expr
.X_add_number
) != 0)
6676 int regno
= range
& expr
.X_add_number
;
6679 regno
= (1 << regno
) - 1;
6681 (_("Warning: duplicated register (r%d) in register list"),
6685 range
|= expr
.X_add_number
;
6689 if (inst
.reloc
.type
!= 0)
6691 inst
.error
= _("expression too complex");
6695 memcpy (&inst
.reloc
.exp
, &expr
, sizeof (expressionS
));
6696 inst
.reloc
.type
= BFD_RELOC_ARM_MULTI
;
6697 inst
.reloc
.pc_rel
= 0;
6701 skip_whitespace (str
);
6703 if (*str
== '|' || *str
== '+')
6709 while (another_range
);
6722 skip_whitespace (str
);
6724 if ((base_reg
= reg_required_here (&str
, 16)) == FAIL
)
6727 if (base_reg
== REG_PC
)
6729 inst
.error
= _("r15 not allowed as base register");
6733 skip_whitespace (str
);
6737 inst
.instruction
|= WRITE_BACK
;
6741 if (skip_past_comma (&str
) == FAIL
6742 || (range
= reg_list (&str
)) == FAIL
)
6745 inst
.error
= BAD_ARGS
;
6752 inst
.instruction
|= LDM_TYPE_2_OR_3
;
6755 if (inst
.instruction
& WRITE_BACK
)
6757 /* Check for unpredictable uses of writeback. */
6758 if (inst
.instruction
& LOAD_BIT
)
6760 /* Not allowed in LDM type 2. */
6761 if ((inst
.instruction
& LDM_TYPE_2_OR_3
)
6762 && ((range
& (1 << REG_PC
)) == 0))
6763 as_warn (_("writeback of base register is UNPREDICTABLE"));
6764 /* Only allowed if base reg not in list for other types. */
6765 else if (range
& (1 << base_reg
))
6766 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
6770 /* Not allowed for type 2. */
6771 if (inst
.instruction
& LDM_TYPE_2_OR_3
)
6772 as_warn (_("writeback of base register is UNPREDICTABLE"));
6773 /* Only allowed if base reg not in list, or first in list. */
6774 else if ((range
& (1 << base_reg
))
6775 && (range
& ((1 << base_reg
) - 1)))
6776 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
6780 inst
.instruction
|= range
;
6789 skip_whitespace (str
);
6791 /* Allow optional leading '#'. */
6792 if (is_immediate_prefix (*str
))
6795 if (my_get_expression (& inst
.reloc
.exp
, & str
))
6798 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
6799 inst
.reloc
.pc_rel
= 0;
6811 skip_whitespace (str
);
6813 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
6818 inst
.error
= _("r15 not allowed in swap");
6822 if (skip_past_comma (&str
) == FAIL
6823 || (reg
= reg_required_here (&str
, 0)) == FAIL
)
6826 inst
.error
= BAD_ARGS
;
6832 inst
.error
= _("r15 not allowed in swap");
6836 if (skip_past_comma (&str
) == FAIL
6839 inst
.error
= BAD_ARGS
;
6843 skip_whitespace (str
);
6845 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6850 inst
.error
= BAD_PC
;
6854 skip_whitespace (str
);
6858 inst
.error
= _("missing ]");
6870 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6877 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
6878 required for the instruction. */
6880 /* arm_parse_reloc () works on input_line_pointer.
6881 We actually want to parse the operands to the branch instruction
6882 passed in 'str'. Save the input pointer and restore it later. */
6883 save_in
= input_line_pointer
;
6884 input_line_pointer
= str
;
6885 if (inst
.reloc
.exp
.X_op
== O_symbol
6887 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
6889 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
6890 inst
.reloc
.pc_rel
= 0;
6891 /* Modify str to point to after parsed operands, otherwise
6892 end_of_line() will complain about the (PLT) left in str. */
6893 str
= input_line_pointer
;
6897 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
6898 inst
.reloc
.pc_rel
= 1;
6900 input_line_pointer
= save_in
;
6903 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
6904 inst
.reloc
.pc_rel
= 1;
6905 #endif /* OBJ_ELF */
6917 skip_whitespace (str
);
6919 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
6921 inst
.error
= BAD_ARGS
;
6925 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
6927 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
6936 /* Co-processor data operation.
6937 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
6938 skip_whitespace (str
);
6940 if (co_proc_number (&str
) == FAIL
)
6943 inst
.error
= BAD_ARGS
;
6947 if (skip_past_comma (&str
) == FAIL
6948 || cp_opc_expr (&str
, 20,4) == FAIL
)
6951 inst
.error
= BAD_ARGS
;
6955 if (skip_past_comma (&str
) == FAIL
6956 || cp_reg_required_here (&str
, 12) == FAIL
)
6959 inst
.error
= BAD_ARGS
;
6963 if (skip_past_comma (&str
) == FAIL
6964 || cp_reg_required_here (&str
, 16) == FAIL
)
6967 inst
.error
= BAD_ARGS
;
6971 if (skip_past_comma (&str
) == FAIL
6972 || cp_reg_required_here (&str
, 0) == FAIL
)
6975 inst
.error
= BAD_ARGS
;
6979 if (skip_past_comma (&str
) == SUCCESS
)
6981 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
6984 inst
.error
= BAD_ARGS
;
6997 /* Co-processor register load/store.
6998 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
7000 skip_whitespace (str
);
7002 if (co_proc_number (&str
) == FAIL
)
7005 inst
.error
= BAD_ARGS
;
7009 if (skip_past_comma (&str
) == FAIL
7010 || cp_reg_required_here (&str
, 12) == FAIL
)
7013 inst
.error
= BAD_ARGS
;
7017 if (skip_past_comma (&str
) == FAIL
7018 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
7021 inst
.error
= BAD_ARGS
;
7033 /* Co-processor register transfer.
7034 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
7036 skip_whitespace (str
);
7038 if (co_proc_number (&str
) == FAIL
)
7041 inst
.error
= BAD_ARGS
;
7045 if (skip_past_comma (&str
) == FAIL
7046 || cp_opc_expr (&str
, 21, 3) == FAIL
)
7049 inst
.error
= BAD_ARGS
;
7053 if (skip_past_comma (&str
) == FAIL
7054 || reg_required_here (&str
, 12) == FAIL
)
7057 inst
.error
= BAD_ARGS
;
7061 if (skip_past_comma (&str
) == FAIL
7062 || cp_reg_required_here (&str
, 16) == FAIL
)
7065 inst
.error
= BAD_ARGS
;
7069 if (skip_past_comma (&str
) == FAIL
7070 || cp_reg_required_here (&str
, 0) == FAIL
)
7073 inst
.error
= BAD_ARGS
;
7077 if (skip_past_comma (&str
) == SUCCESS
)
7079 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
7082 inst
.error
= BAD_ARGS
;
7095 /* FP control registers.
7096 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
7098 skip_whitespace (str
);
7100 if (reg_required_here (&str
, 12) == FAIL
)
7103 inst
.error
= BAD_ARGS
;
7115 skip_whitespace (str
);
7117 if (fp_reg_required_here (&str
, 12) == FAIL
)
7120 inst
.error
= BAD_ARGS
;
7124 if (skip_past_comma (&str
) == FAIL
7125 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
7128 inst
.error
= BAD_ARGS
;
7141 skip_whitespace (str
);
7143 if (fp_reg_required_here (&str
, 12) == FAIL
)
7146 inst
.error
= BAD_ARGS
;
7150 /* Get Number of registers to transfer. */
7151 if (skip_past_comma (&str
) == FAIL
7152 || my_get_expression (&inst
.reloc
.exp
, &str
))
7155 inst
.error
= _("constant expression expected");
7159 if (inst
.reloc
.exp
.X_op
!= O_constant
)
7161 inst
.error
= _("constant value required for number of registers");
7165 num_regs
= inst
.reloc
.exp
.X_add_number
;
7167 if (num_regs
< 1 || num_regs
> 4)
7169 inst
.error
= _("number of registers must be in the range [1:4]");
7176 inst
.instruction
|= CP_T_X
;
7179 inst
.instruction
|= CP_T_Y
;
7182 inst
.instruction
|= CP_T_Y
| CP_T_X
;
7190 if (inst
.instruction
& (CP_T_Pre
| CP_T_UD
)) /* ea/fd format. */
7196 /* The instruction specified "ea" or "fd", so we can only accept
7197 [Rn]{!}. The instruction does not really support stacking or
7198 unstacking, so we have to emulate these by setting appropriate
7199 bits and offsets. */
7200 if (skip_past_comma (&str
) == FAIL
7204 inst
.error
= BAD_ARGS
;
7209 skip_whitespace (str
);
7211 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
7214 skip_whitespace (str
);
7218 inst
.error
= BAD_ARGS
;
7230 _("r15 not allowed as base register with write-back");
7237 if (inst
.instruction
& CP_T_Pre
)
7239 /* Pre-decrement. */
7240 offset
= 3 * num_regs
;
7242 inst
.instruction
|= CP_T_WB
;
7246 /* Post-increment. */
7249 inst
.instruction
|= CP_T_WB
;
7250 offset
= 3 * num_regs
;
7254 /* No write-back, so convert this into a standard pre-increment
7255 instruction -- aesthetically more pleasing. */
7256 inst
.instruction
|= CP_T_Pre
| CP_T_UD
;
7261 inst
.instruction
|= offset
;
7263 else if (skip_past_comma (&str
) == FAIL
7264 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
7267 inst
.error
= BAD_ARGS
;
7278 skip_whitespace (str
);
7280 if (fp_reg_required_here (&str
, 12) == FAIL
)
7283 inst
.error
= BAD_ARGS
;
7287 if (skip_past_comma (&str
) == FAIL
7288 || fp_reg_required_here (&str
, 16) == FAIL
)
7291 inst
.error
= BAD_ARGS
;
7295 if (skip_past_comma (&str
) == FAIL
7296 || fp_op2 (&str
) == FAIL
)
7299 inst
.error
= BAD_ARGS
;
7308 do_fpa_monadic (str
)
7311 skip_whitespace (str
);
7313 if (fp_reg_required_here (&str
, 12) == FAIL
)
7316 inst
.error
= BAD_ARGS
;
7320 if (skip_past_comma (&str
) == FAIL
7321 || fp_op2 (&str
) == FAIL
)
7324 inst
.error
= BAD_ARGS
;
7336 skip_whitespace (str
);
7338 if (fp_reg_required_here (&str
, 16) == FAIL
)
7341 inst
.error
= BAD_ARGS
;
7345 if (skip_past_comma (&str
) == FAIL
7346 || fp_op2 (&str
) == FAIL
)
7349 inst
.error
= BAD_ARGS
;
7358 do_fpa_from_reg (str
)
7361 skip_whitespace (str
);
7363 if (fp_reg_required_here (&str
, 16) == FAIL
)
7366 inst
.error
= BAD_ARGS
;
7370 if (skip_past_comma (&str
) == FAIL
7371 || reg_required_here (&str
, 12) == FAIL
)
7374 inst
.error
= BAD_ARGS
;
7386 skip_whitespace (str
);
7388 if (reg_required_here (&str
, 12) == FAIL
)
7391 if (skip_past_comma (&str
) == FAIL
7392 || fp_reg_required_here (&str
, 0) == FAIL
)
7395 inst
.error
= BAD_ARGS
;
7404 vfp_sp_reg_required_here (str
, pos
)
7406 enum vfp_sp_reg_pos pos
;
7411 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_SN
].htab
)) != FAIL
)
7416 inst
.instruction
|= ((reg
>> 1) << 12) | ((reg
& 1) << 22);
7420 inst
.instruction
|= ((reg
>> 1) << 16) | ((reg
& 1) << 7);
7424 inst
.instruction
|= ((reg
>> 1) << 0) | ((reg
& 1) << 5);
7433 /* In the few cases where we might be able to accept something else
7434 this error can be overridden. */
7435 inst
.error
= _(all_reg_maps
[REG_TYPE_SN
].expected
);
7437 /* Restore the start point. */
7443 vfp_dp_reg_required_here (str
, pos
)
7445 enum vfp_dp_reg_pos pos
;
7450 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_DN
].htab
)) != FAIL
)
7455 inst
.instruction
|= reg
<< 12;
7459 inst
.instruction
|= reg
<< 16;
7463 inst
.instruction
|= reg
<< 0;
7472 /* In the few cases where we might be able to accept something else
7473 this error can be overridden. */
7474 inst
.error
= _(all_reg_maps
[REG_TYPE_DN
].expected
);
7476 /* Restore the start point. */
7482 do_vfp_sp_monadic (str
)
7485 skip_whitespace (str
);
7487 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7490 if (skip_past_comma (&str
) == FAIL
7491 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
7494 inst
.error
= BAD_ARGS
;
7503 do_vfp_dp_monadic (str
)
7506 skip_whitespace (str
);
7508 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7511 if (skip_past_comma (&str
) == FAIL
7512 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7515 inst
.error
= BAD_ARGS
;
7524 do_vfp_sp_dyadic (str
)
7527 skip_whitespace (str
);
7529 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7532 if (skip_past_comma (&str
) == FAIL
7533 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
7534 || skip_past_comma (&str
) == FAIL
7535 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
7538 inst
.error
= BAD_ARGS
;
7547 do_vfp_dp_dyadic (str
)
7550 skip_whitespace (str
);
7552 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7555 if (skip_past_comma (&str
) == FAIL
7556 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
7557 || skip_past_comma (&str
) == FAIL
7558 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7561 inst
.error
= BAD_ARGS
;
7570 do_vfp_reg_from_sp (str
)
7573 skip_whitespace (str
);
7575 if (reg_required_here (&str
, 12) == FAIL
)
7578 if (skip_past_comma (&str
) == FAIL
7579 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
7582 inst
.error
= BAD_ARGS
;
7591 do_vfp_sp_reg2 (str
)
7594 skip_whitespace (str
);
7596 if (reg_required_here (&str
, 12) == FAIL
)
7599 if (skip_past_comma (&str
) == FAIL
7600 || reg_required_here (&str
, 16) == FAIL
7601 || skip_past_comma (&str
) == FAIL
)
7604 inst
.error
= BAD_ARGS
;
7608 /* We require exactly two consecutive SP registers. */
7609 if (vfp_sp_reg_list (&str
, VFP_REG_Sm
) != 2)
7612 inst
.error
= _("only two consecutive VFP SP registers allowed here");
7620 do_vfp_sp_from_reg (str
)
7623 skip_whitespace (str
);
7625 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
7628 if (skip_past_comma (&str
) == FAIL
7629 || reg_required_here (&str
, 12) == FAIL
)
7632 inst
.error
= BAD_ARGS
;
7641 do_vfp_reg_from_dp (str
)
7644 skip_whitespace (str
);
7646 if (reg_required_here (&str
, 12) == FAIL
)
7649 if (skip_past_comma (&str
) == FAIL
7650 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
7653 inst
.error
= BAD_ARGS
;
7662 do_vfp_reg2_from_dp (str
)
7665 skip_whitespace (str
);
7667 if (reg_required_here (&str
, 12) == FAIL
)
7670 if (skip_past_comma (&str
) == FAIL
7671 || reg_required_here (&str
, 16) == FAIL
7672 || skip_past_comma (&str
) == FAIL
7673 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7676 inst
.error
= BAD_ARGS
;
7685 do_vfp_dp_from_reg (str
)
7688 skip_whitespace (str
);
7690 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
7693 if (skip_past_comma (&str
) == FAIL
7694 || reg_required_here (&str
, 12) == FAIL
)
7697 inst
.error
= BAD_ARGS
;
7706 do_vfp_dp_from_reg2 (str
)
7709 skip_whitespace (str
);
7711 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7714 if (skip_past_comma (&str
) == FAIL
7715 || reg_required_here (&str
, 12) == FAIL
7716 || skip_past_comma (&str
) == FAIL
7717 || reg_required_here (&str
, 16))
7720 inst
.error
= BAD_ARGS
;
7728 static const struct vfp_reg
*
7735 const struct vfp_reg
*vreg
;
7739 /* Find the end of the current token. */
7744 while (ISALPHA (c
));
7749 for (vreg
= vfp_regs
+ 0;
7750 vreg
< vfp_regs
+ sizeof (vfp_regs
) / sizeof (struct vfp_reg
);
7753 if (strcmp (start
, vreg
->name
) == 0)
7766 vfp_psr_required_here (str
)
7770 const struct vfp_reg
*vreg
;
7772 vreg
= vfp_psr_parse (str
);
7776 inst
.instruction
|= vreg
->regno
;
7780 inst
.error
= _("VFP system register expected");
7787 do_vfp_reg_from_ctrl (str
)
7790 skip_whitespace (str
);
7792 if (reg_required_here (&str
, 12) == FAIL
)
7795 if (skip_past_comma (&str
) == FAIL
7796 || vfp_psr_required_here (&str
) == FAIL
)
7799 inst
.error
= BAD_ARGS
;
7808 do_vfp_ctrl_from_reg (str
)
7811 skip_whitespace (str
);
7813 if (vfp_psr_required_here (&str
) == FAIL
)
7816 if (skip_past_comma (&str
) == FAIL
7817 || reg_required_here (&str
, 12) == FAIL
)
7820 inst
.error
= BAD_ARGS
;
7829 do_vfp_sp_ldst (str
)
7832 skip_whitespace (str
);
7834 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7837 inst
.error
= BAD_ARGS
;
7841 if (skip_past_comma (&str
) == FAIL
7842 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
7845 inst
.error
= BAD_ARGS
;
7854 do_vfp_dp_ldst (str
)
7857 skip_whitespace (str
);
7859 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7862 inst
.error
= BAD_ARGS
;
7866 if (skip_past_comma (&str
) == FAIL
7867 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
7870 inst
.error
= BAD_ARGS
;
7878 /* Parse and encode a VFP SP register list, storing the initial
7879 register in position POS and returning the range as the result. If
7880 the string is invalid return FAIL (an invalid range). */
7882 vfp_sp_reg_list (str
, pos
)
7884 enum vfp_sp_reg_pos pos
;
7892 unsigned long mask
= 0;
7899 skip_whitespace (*str
);
7901 tempinst
= inst
.instruction
;
7905 inst
.instruction
= 0;
7907 if ((new_base
= vfp_sp_reg_required_here (str
, pos
)) == FAIL
)
7910 if (count
== 0 || base_reg
> new_base
)
7912 base_reg
= new_base
;
7913 base_bits
= inst
.instruction
;
7916 if (mask
& (1 << new_base
))
7918 inst
.error
= _("invalid register list");
7922 if ((mask
>> new_base
) != 0 && ! warned
)
7924 as_tsktsk (_("register list not in ascending order"));
7928 mask
|= 1 << new_base
;
7931 skip_whitespace (*str
);
7933 if (**str
== '-') /* We have the start of a range expression */
7940 = arm_reg_parse (str
, all_reg_maps
[REG_TYPE_SN
].htab
))
7943 inst
.error
= _(all_reg_maps
[REG_TYPE_SN
].expected
);
7947 if (high_range
<= new_base
)
7949 inst
.error
= _("register range not in ascending order");
7953 for (new_base
++; new_base
<= high_range
; new_base
++)
7955 if (mask
& (1 << new_base
))
7957 inst
.error
= _("invalid register list");
7961 mask
|= 1 << new_base
;
7966 while (skip_past_comma (str
) != FAIL
);
7970 inst
.error
= _("invalid register list");
7978 /* Sanity check -- should have raised a parse error above. */
7979 if (count
== 0 || count
> 32)
7982 /* Final test -- the registers must be consecutive. */
7985 if ((mask
& (1 << base_reg
++)) == 0)
7987 inst
.error
= _("non-contiguous register range");
7992 inst
.instruction
= tempinst
| base_bits
;
7997 vfp_dp_reg_list (str
)
8005 unsigned long mask
= 0;
8012 skip_whitespace (*str
);
8014 tempinst
= inst
.instruction
;
8018 inst
.instruction
= 0;
8020 if ((new_base
= vfp_dp_reg_required_here (str
, VFP_REG_Dd
)) == FAIL
)
8023 if (count
== 0 || base_reg
> new_base
)
8025 base_reg
= new_base
;
8026 range
= inst
.instruction
;
8029 if (mask
& (1 << new_base
))
8031 inst
.error
= _("invalid register list");
8035 if ((mask
>> new_base
) != 0 && ! warned
)
8037 as_tsktsk (_("register list not in ascending order"));
8041 mask
|= 1 << new_base
;
8044 skip_whitespace (*str
);
8046 if (**str
== '-') /* We have the start of a range expression */
8053 = arm_reg_parse (str
, all_reg_maps
[REG_TYPE_DN
].htab
))
8056 inst
.error
= _(all_reg_maps
[REG_TYPE_DN
].expected
);
8060 if (high_range
<= new_base
)
8062 inst
.error
= _("register range not in ascending order");
8066 for (new_base
++; new_base
<= high_range
; new_base
++)
8068 if (mask
& (1 << new_base
))
8070 inst
.error
= _("invalid register list");
8074 mask
|= 1 << new_base
;
8079 while (skip_past_comma (str
) != FAIL
);
8083 inst
.error
= _("invalid register list");
8091 /* Sanity check -- should have raised a parse error above. */
8092 if (count
== 0 || count
> 16)
8095 /* Final test -- the registers must be consecutive. */
8098 if ((mask
& (1 << base_reg
++)) == 0)
8100 inst
.error
= _("non-contiguous register range");
8105 inst
.instruction
= tempinst
;
8110 vfp_sp_ldstm (str
, ldstm_type
)
8112 enum vfp_ldstm_type ldstm_type
;
8116 skip_whitespace (str
);
8118 if (reg_required_here (&str
, 16) == FAIL
)
8121 skip_whitespace (str
);
8125 inst
.instruction
|= WRITE_BACK
;
8128 else if (ldstm_type
!= VFP_LDSTMIA
)
8130 inst
.error
= _("this addressing mode requires base-register writeback");
8134 if (skip_past_comma (&str
) == FAIL
8135 || (range
= vfp_sp_reg_list (&str
, VFP_REG_Sd
)) == FAIL
)
8138 inst
.error
= BAD_ARGS
;
8142 inst
.instruction
|= range
;
8147 vfp_dp_ldstm (str
, ldstm_type
)
8149 enum vfp_ldstm_type ldstm_type
;
8153 skip_whitespace (str
);
8155 if (reg_required_here (&str
, 16) == FAIL
)
8158 skip_whitespace (str
);
8162 inst
.instruction
|= WRITE_BACK
;
8165 else if (ldstm_type
!= VFP_LDSTMIA
&& ldstm_type
!= VFP_LDSTMIAX
)
8167 inst
.error
= _("this addressing mode requires base-register writeback");
8171 if (skip_past_comma (&str
) == FAIL
8172 || (range
= vfp_dp_reg_list (&str
)) == FAIL
)
8175 inst
.error
= BAD_ARGS
;
8179 if (ldstm_type
== VFP_LDSTMIAX
|| ldstm_type
== VFP_LDSTMDBX
)
8182 inst
.instruction
|= range
;
8187 do_vfp_sp_ldstmia (str
)
8190 vfp_sp_ldstm (str
, VFP_LDSTMIA
);
8194 do_vfp_sp_ldstmdb (str
)
8197 vfp_sp_ldstm (str
, VFP_LDSTMDB
);
8201 do_vfp_dp_ldstmia (str
)
8204 vfp_dp_ldstm (str
, VFP_LDSTMIA
);
8208 do_vfp_dp_ldstmdb (str
)
8211 vfp_dp_ldstm (str
, VFP_LDSTMDB
);
8215 do_vfp_xp_ldstmia (str
)
8218 vfp_dp_ldstm (str
, VFP_LDSTMIAX
);
8222 do_vfp_xp_ldstmdb (str
)
8225 vfp_dp_ldstm (str
, VFP_LDSTMDBX
);
8229 do_vfp_sp_compare_z (str
)
8232 skip_whitespace (str
);
8234 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8237 inst
.error
= BAD_ARGS
;
8246 do_vfp_dp_compare_z (str
)
8249 skip_whitespace (str
);
8251 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8254 inst
.error
= BAD_ARGS
;
8263 do_vfp_dp_sp_cvt (str
)
8266 skip_whitespace (str
);
8268 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8271 if (skip_past_comma (&str
) == FAIL
8272 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
8275 inst
.error
= BAD_ARGS
;
8284 do_vfp_sp_dp_cvt (str
)
8287 skip_whitespace (str
);
8289 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8292 if (skip_past_comma (&str
) == FAIL
8293 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
8296 inst
.error
= BAD_ARGS
;
8304 /* Thumb specific routines. */
8306 /* Parse and validate that a register is of the right form, this saves
8307 repeated checking of this information in many similar cases.
8308 Unlike the 32-bit case we do not insert the register into the opcode
8309 here, since the position is often unknown until the full instruction
8313 thumb_reg (strp
, hi_lo
)
8319 if ((reg
= reg_required_here (strp
, -1)) == FAIL
)
8327 inst
.error
= _("lo register required");
8335 inst
.error
= _("hi register required");
8347 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
8351 thumb_add_sub (str
, subtract
)
8355 int Rd
, Rs
, Rn
= FAIL
;
8357 skip_whitespace (str
);
8359 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
8360 || skip_past_comma (&str
) == FAIL
)
8363 inst
.error
= BAD_ARGS
;
8367 if (is_immediate_prefix (*str
))
8371 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8376 if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8379 if (skip_past_comma (&str
) == FAIL
)
8381 /* Two operand format, shuffle the registers
8382 and pretend there are 3. */
8386 else if (is_immediate_prefix (*str
))
8389 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8392 else if ((Rn
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8396 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8397 for the latter case, EXPR contains the immediate that was found. */
8400 /* All register format. */
8401 if (Rd
> 7 || Rs
> 7 || Rn
> 7)
8405 inst
.error
= _("dest and source1 must be the same register");
8409 /* Can't do this for SUB. */
8412 inst
.error
= _("subtract valid only on lo regs");
8416 inst
.instruction
= (T_OPCODE_ADD_HI
8417 | (Rd
> 7 ? THUMB_H1
: 0)
8418 | (Rn
> 7 ? THUMB_H2
: 0));
8419 inst
.instruction
|= (Rd
& 7) | ((Rn
& 7) << 3);
8423 inst
.instruction
= subtract
? T_OPCODE_SUB_R3
: T_OPCODE_ADD_R3
;
8424 inst
.instruction
|= Rd
| (Rs
<< 3) | (Rn
<< 6);
8429 /* Immediate expression, now things start to get nasty. */
8431 /* First deal with HI regs, only very restricted cases allowed:
8432 Adjusting SP, and using PC or SP to get an address. */
8433 if ((Rd
> 7 && (Rd
!= REG_SP
|| Rs
!= REG_SP
))
8434 || (Rs
> 7 && Rs
!= REG_SP
&& Rs
!= REG_PC
))
8436 inst
.error
= _("invalid Hi register with immediate");
8440 if (inst
.reloc
.exp
.X_op
!= O_constant
)
8442 /* Value isn't known yet, all we can do is store all the fragments
8443 we know about in the instruction and let the reloc hacking
8445 inst
.instruction
= (subtract
? 0x8000 : 0) | (Rd
<< 4) | Rs
;
8446 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
8450 int offset
= inst
.reloc
.exp
.X_add_number
;
8460 /* Quick check, in case offset is MIN_INT. */
8463 inst
.error
= _("immediate value out of range");
8467 /* Note - you cannot convert a subtract of 0 into an
8468 add of 0 because the carry flag is set differently. */
8469 else if (offset
> 0)
8474 if (offset
& ~0x1fc)
8476 inst
.error
= _("invalid immediate value for stack adjust");
8479 inst
.instruction
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
8480 inst
.instruction
|= offset
>> 2;
8482 else if (Rs
== REG_PC
|| Rs
== REG_SP
)
8485 || (offset
& ~0x3fc))
8487 inst
.error
= _("invalid immediate for address calculation");
8490 inst
.instruction
= (Rs
== REG_PC
? T_OPCODE_ADD_PC
8492 inst
.instruction
|= (Rd
<< 8) | (offset
>> 2);
8498 inst
.error
= _("immediate value out of range");
8501 inst
.instruction
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
8502 inst
.instruction
|= (Rd
<< 8) | offset
;
8508 inst
.error
= _("immediate value out of range");
8511 inst
.instruction
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
8512 inst
.instruction
|= Rd
| (Rs
<< 3) | (offset
<< 6);
8521 thumb_shift (str
, shift
)
8525 int Rd
, Rs
, Rn
= FAIL
;
8527 skip_whitespace (str
);
8529 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
8530 || skip_past_comma (&str
) == FAIL
)
8533 inst
.error
= BAD_ARGS
;
8537 if (is_immediate_prefix (*str
))
8539 /* Two operand immediate format, set Rs to Rd. */
8542 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8547 if ((Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8550 if (skip_past_comma (&str
) == FAIL
)
8552 /* Two operand format, shuffle the registers
8553 and pretend there are 3. */
8557 else if (is_immediate_prefix (*str
))
8560 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8563 else if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8567 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8568 for the latter case, EXPR contains the immediate that was found. */
8574 inst
.error
= _("source1 and dest must be same register");
8580 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_R
; break;
8581 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_R
; break;
8582 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_R
; break;
8585 inst
.instruction
|= Rd
| (Rn
<< 3);
8591 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_I
; break;
8592 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_I
; break;
8593 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_I
; break;
8596 if (inst
.reloc
.exp
.X_op
!= O_constant
)
8598 /* Value isn't known yet, create a dummy reloc and let reloc
8599 hacking fix it up. */
8600 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_SHIFT
;
8604 unsigned shift_value
= inst
.reloc
.exp
.X_add_number
;
8606 if (shift_value
> 32 || (shift_value
== 32 && shift
== THUMB_LSL
))
8608 inst
.error
= _("invalid immediate for shift");
8612 /* Shifts of zero are handled by converting to LSL. */
8613 if (shift_value
== 0)
8614 inst
.instruction
= T_OPCODE_LSL_I
;
8616 /* Shifts of 32 are encoded as a shift of zero. */
8617 if (shift_value
== 32)
8620 inst
.instruction
|= shift_value
<< 6;
8623 inst
.instruction
|= Rd
| (Rs
<< 3);
8630 thumb_mov_compare (str
, move
)
8636 skip_whitespace (str
);
8638 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
8639 || skip_past_comma (&str
) == FAIL
)
8642 inst
.error
= BAD_ARGS
;
8646 if (is_immediate_prefix (*str
))
8649 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8652 else if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8657 if (Rs
< 8 && Rd
< 8)
8659 if (move
== THUMB_MOVE
)
8660 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
8661 since a MOV instruction produces unpredictable results. */
8662 inst
.instruction
= T_OPCODE_ADD_I3
;
8664 inst
.instruction
= T_OPCODE_CMP_LR
;
8665 inst
.instruction
|= Rd
| (Rs
<< 3);
8669 if (move
== THUMB_MOVE
)
8670 inst
.instruction
= T_OPCODE_MOV_HR
;
8672 inst
.instruction
= T_OPCODE_CMP_HR
;
8675 inst
.instruction
|= THUMB_H1
;
8678 inst
.instruction
|= THUMB_H2
;
8680 inst
.instruction
|= (Rd
& 7) | ((Rs
& 7) << 3);
8687 inst
.error
= _("only lo regs allowed with immediate");
8691 if (move
== THUMB_MOVE
)
8692 inst
.instruction
= T_OPCODE_MOV_I8
;
8694 inst
.instruction
= T_OPCODE_CMP_I8
;
8696 inst
.instruction
|= Rd
<< 8;
8698 if (inst
.reloc
.exp
.X_op
!= O_constant
)
8699 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_IMM
;
8702 unsigned value
= inst
.reloc
.exp
.X_add_number
;
8706 inst
.error
= _("invalid immediate");
8710 inst
.instruction
|= value
;
8718 thumb_load_store (str
, load_store
, size
)
8723 int Rd
, Rb
, Ro
= FAIL
;
8725 skip_whitespace (str
);
8727 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
8728 || skip_past_comma (&str
) == FAIL
)
8731 inst
.error
= BAD_ARGS
;
8738 if ((Rb
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8741 if (skip_past_comma (&str
) != FAIL
)
8743 if (is_immediate_prefix (*str
))
8746 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8749 else if ((Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8754 inst
.reloc
.exp
.X_op
= O_constant
;
8755 inst
.reloc
.exp
.X_add_number
= 0;
8760 inst
.error
= _("expected ']'");
8765 else if (*str
== '=')
8767 if (load_store
!= THUMB_LOAD
)
8769 inst
.error
= _("invalid pseudo operation");
8773 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
8776 skip_whitespace (str
);
8778 if (my_get_expression (& inst
.reloc
.exp
, & str
))
8783 if ( inst
.reloc
.exp
.X_op
!= O_constant
8784 && inst
.reloc
.exp
.X_op
!= O_symbol
)
8786 inst
.error
= "Constant expression expected";
8790 if (inst
.reloc
.exp
.X_op
== O_constant
8791 && ((inst
.reloc
.exp
.X_add_number
& ~0xFF) == 0))
8793 /* This can be done with a mov instruction. */
8795 inst
.instruction
= T_OPCODE_MOV_I8
| (Rd
<< 8);
8796 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
8800 /* Insert into literal pool. */
8801 if (add_to_lit_pool () == FAIL
)
8804 inst
.error
= "literal pool insertion failed";
8808 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8809 inst
.reloc
.pc_rel
= 1;
8810 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
8811 /* Adjust ARM pipeline offset to Thumb. */
8812 inst
.reloc
.exp
.X_add_number
+= 4;
8818 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8821 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
8822 inst
.reloc
.pc_rel
= 1;
8823 inst
.reloc
.exp
.X_add_number
-= 4; /* Pipeline offset. */
8824 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8829 if (Rb
== REG_PC
|| Rb
== REG_SP
)
8831 if (size
!= THUMB_WORD
)
8833 inst
.error
= _("byte or halfword not valid for base register");
8836 else if (Rb
== REG_PC
&& load_store
!= THUMB_LOAD
)
8838 inst
.error
= _("r15 based store not allowed");
8841 else if (Ro
!= FAIL
)
8843 inst
.error
= _("invalid base register for register offset");
8848 inst
.instruction
= T_OPCODE_LDR_PC
;
8849 else if (load_store
== THUMB_LOAD
)
8850 inst
.instruction
= T_OPCODE_LDR_SP
;
8852 inst
.instruction
= T_OPCODE_STR_SP
;
8854 inst
.instruction
|= Rd
<< 8;
8855 if (inst
.reloc
.exp
.X_op
== O_constant
)
8857 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
8859 if (offset
& ~0x3fc)
8861 inst
.error
= _("invalid offset");
8865 inst
.instruction
|= offset
>> 2;
8868 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8872 inst
.error
= _("invalid base register in load/store");
8875 else if (Ro
== FAIL
)
8877 /* Immediate offset. */
8878 if (size
== THUMB_WORD
)
8879 inst
.instruction
= (load_store
== THUMB_LOAD
8880 ? T_OPCODE_LDR_IW
: T_OPCODE_STR_IW
);
8881 else if (size
== THUMB_HALFWORD
)
8882 inst
.instruction
= (load_store
== THUMB_LOAD
8883 ? T_OPCODE_LDR_IH
: T_OPCODE_STR_IH
);
8885 inst
.instruction
= (load_store
== THUMB_LOAD
8886 ? T_OPCODE_LDR_IB
: T_OPCODE_STR_IB
);
8888 inst
.instruction
|= Rd
| (Rb
<< 3);
8890 if (inst
.reloc
.exp
.X_op
== O_constant
)
8892 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
8894 if (offset
& ~(0x1f << size
))
8896 inst
.error
= _("invalid offset");
8899 inst
.instruction
|= (offset
>> size
) << 6;
8902 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8906 /* Register offset. */
8907 if (size
== THUMB_WORD
)
8908 inst
.instruction
= (load_store
== THUMB_LOAD
8909 ? T_OPCODE_LDR_RW
: T_OPCODE_STR_RW
);
8910 else if (size
== THUMB_HALFWORD
)
8911 inst
.instruction
= (load_store
== THUMB_LOAD
8912 ? T_OPCODE_LDR_RH
: T_OPCODE_STR_RH
);
8914 inst
.instruction
= (load_store
== THUMB_LOAD
8915 ? T_OPCODE_LDR_RB
: T_OPCODE_STR_RB
);
8917 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
8923 /* A register must be given at this point.
8925 Shift is the place to put it in inst.instruction.
8927 Restores input start point on err.
8928 Returns the reg#, or FAIL. */
8931 mav_reg_required_here (str
, shift
, regtype
)
8934 enum arm_reg_type regtype
;
8939 if ((reg
= arm_reg_parse (str
, all_reg_maps
[regtype
].htab
)) != FAIL
)
8942 inst
.instruction
|= reg
<< shift
;
8947 /* Restore the start point. */
8950 /* In the few cases where we might be able to accept something else
8951 this error can be overridden. */
8952 inst
.error
= _(all_reg_maps
[regtype
].expected
);
8957 /* Cirrus Maverick Instructions. */
8959 /* Wrapper functions. */
8962 do_mav_binops_1a (str
)
8965 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVF
);
8969 do_mav_binops_1b (str
)
8972 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVD
);
8976 do_mav_binops_1c (str
)
8979 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVDX
);
8983 do_mav_binops_1d (str
)
8986 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVF
);
8990 do_mav_binops_1e (str
)
8993 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVD
);
8997 do_mav_binops_1f (str
)
9000 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVF
);
9004 do_mav_binops_1g (str
)
9007 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVD
);
9011 do_mav_binops_1h (str
)
9014 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVFX
);
9018 do_mav_binops_1i (str
)
9021 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVFX
);
9025 do_mav_binops_1j (str
)
9028 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVDX
);
9032 do_mav_binops_1k (str
)
9035 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVDX
);
9039 do_mav_binops_1l (str
)
9042 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVF
);
9046 do_mav_binops_1m (str
)
9049 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVD
);
9053 do_mav_binops_1n (str
)
9056 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
9060 do_mav_binops_1o (str
)
9063 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
9067 do_mav_binops_2a (str
)
9070 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVF
, REG_TYPE_RN
);
9074 do_mav_binops_2b (str
)
9077 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVD
, REG_TYPE_RN
);
9081 do_mav_binops_2c (str
)
9084 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVDX
, REG_TYPE_RN
);
9088 do_mav_binops_3a (str
)
9091 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVFX
);
9095 do_mav_binops_3b (str
)
9098 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVFX
, REG_TYPE_MVAX
);
9102 do_mav_binops_3c (str
)
9105 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVDX
);
9109 do_mav_binops_3d (str
)
9112 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVDX
, REG_TYPE_MVAX
);
9116 do_mav_triple_4a (str
)
9119 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_RN
);
9123 do_mav_triple_4b (str
)
9126 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_RN
);
9130 do_mav_triple_5a (str
)
9133 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVF
, REG_TYPE_MVF
);
9137 do_mav_triple_5b (str
)
9140 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVD
, REG_TYPE_MVD
);
9144 do_mav_triple_5c (str
)
9147 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
9151 do_mav_triple_5d (str
)
9154 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
9158 do_mav_triple_5e (str
)
9161 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVF
, REG_TYPE_MVF
, REG_TYPE_MVF
);
9165 do_mav_triple_5f (str
)
9168 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVD
, REG_TYPE_MVD
, REG_TYPE_MVD
);
9172 do_mav_triple_5g (str
)
9175 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
9179 do_mav_triple_5h (str
)
9182 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
9186 do_mav_quad_6a (str
)
9189 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
,
9194 do_mav_quad_6b (str
)
9197 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVAX
, REG_TYPE_MVFX
,
9201 /* cfmvsc32<cond> DSPSC,MVFX[15:0]. */
9203 do_mav_dspsc_1 (str
)
9206 skip_whitespace (str
);
9209 if (mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
9210 || skip_past_comma (&str
) == FAIL
9211 || mav_reg_required_here (&str
, 16, REG_TYPE_MVFX
) == FAIL
)
9214 inst
.error
= BAD_ARGS
;
9222 /* cfmv32sc<cond> MVFX[15:0],DSPSC. */
9224 do_mav_dspsc_2 (str
)
9227 skip_whitespace (str
);
9230 if (mav_reg_required_here (&str
, 0, REG_TYPE_MVFX
) == FAIL
9231 || skip_past_comma (&str
) == FAIL
9232 || mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
)
9235 inst
.error
= BAD_ARGS
;
9244 do_mav_shift_1 (str
)
9247 do_mav_shift (str
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
9251 do_mav_shift_2 (str
)
9254 do_mav_shift (str
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
9261 do_mav_ldst (str
, REG_TYPE_MVF
);
9268 do_mav_ldst (str
, REG_TYPE_MVD
);
9275 do_mav_ldst (str
, REG_TYPE_MVFX
);
9282 do_mav_ldst (str
, REG_TYPE_MVDX
);
9285 /* Isnsn like "foo X,Y". */
9288 do_mav_binops (str
, mode
, reg0
, reg1
)
9291 enum arm_reg_type reg0
;
9292 enum arm_reg_type reg1
;
9296 shift0
= mode
& 0xff;
9297 shift1
= (mode
>> 8) & 0xff;
9299 skip_whitespace (str
);
9301 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
9302 || skip_past_comma (&str
) == FAIL
9303 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
)
9306 inst
.error
= BAD_ARGS
;
9312 /* Isnsn like "foo X,Y,Z". */
9315 do_mav_triple (str
, mode
, reg0
, reg1
, reg2
)
9318 enum arm_reg_type reg0
;
9319 enum arm_reg_type reg1
;
9320 enum arm_reg_type reg2
;
9322 int shift0
, shift1
, shift2
;
9324 shift0
= mode
& 0xff;
9325 shift1
= (mode
>> 8) & 0xff;
9326 shift2
= (mode
>> 16) & 0xff;
9328 skip_whitespace (str
);
9330 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
9331 || skip_past_comma (&str
) == FAIL
9332 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
9333 || skip_past_comma (&str
) == FAIL
9334 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
)
9337 inst
.error
= BAD_ARGS
;
9343 /* Isnsn like "foo W,X,Y,Z".
9344 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
9347 do_mav_quad (str
, mode
, reg0
, reg1
, reg2
, reg3
)
9350 enum arm_reg_type reg0
;
9351 enum arm_reg_type reg1
;
9352 enum arm_reg_type reg2
;
9353 enum arm_reg_type reg3
;
9355 int shift0
, shift1
, shift2
, shift3
;
9357 shift0
= mode
& 0xff;
9358 shift1
= (mode
>> 8) & 0xff;
9359 shift2
= (mode
>> 16) & 0xff;
9360 shift3
= (mode
>> 24) & 0xff;
9362 skip_whitespace (str
);
9364 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
9365 || skip_past_comma (&str
) == FAIL
9366 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
9367 || skip_past_comma (&str
) == FAIL
9368 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
9369 || skip_past_comma (&str
) == FAIL
9370 || mav_reg_required_here (&str
, shift3
, reg3
) == FAIL
)
9373 inst
.error
= BAD_ARGS
;
9379 /* Maverick shift immediate instructions.
9380 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
9381 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
9384 do_mav_shift (str
, reg0
, reg1
)
9386 enum arm_reg_type reg0
;
9387 enum arm_reg_type reg1
;
9392 skip_whitespace (str
);
9396 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
9397 || skip_past_comma (&str
) == FAIL
9398 || mav_reg_required_here (&str
, 16, reg1
) == FAIL
9399 || skip_past_comma (&str
) == FAIL
)
9402 inst
.error
= BAD_ARGS
;
9406 /* Calculate the immediate operand.
9407 The operand is a 7bit signed number. */
9408 skip_whitespace (str
);
9413 if (!ISDIGIT (*str
) && *str
!= '-')
9415 inst
.error
= _("expecting immediate, 7bit operand");
9425 for (imm
= 0; *str
&& ISDIGIT (*str
); ++str
)
9426 imm
= imm
* 10 + *str
- '0';
9430 inst
.error
= _("immediate out of range");
9434 /* Make negative imm's into 7bit signed numbers. */
9441 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
9442 Bits 5-7 of the insn should have bits 4-6 of the immediate.
9443 Bit 4 should be 0. */
9444 imm
= (imm
& 0xf) | ((imm
& 0x70) << 1);
9446 inst
.instruction
|= imm
;
9451 mav_parse_offset (str
, negative
)
9460 skip_whitespace (p
);
9473 inst
.error
= _("offset expected");
9477 for (offset
= 0; *p
&& ISDIGIT (*p
); ++p
)
9478 offset
= offset
* 10 + *p
- '0';
9482 inst
.error
= _("offset out of range");
9488 return *negative
? -offset
: offset
;
9491 /* Maverick load/store instructions.
9492 <insn><cond> CRd,[Rn,<offset>]{!}.
9493 <insn><cond> CRd,[Rn],<offset>. */
9496 do_mav_ldst (str
, reg0
)
9498 enum arm_reg_type reg0
;
9500 int offset
, negative
;
9502 skip_whitespace (str
);
9504 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
9505 || skip_past_comma (&str
) == FAIL
9507 || reg_required_here (&str
, 16) == FAIL
)
9510 if (skip_past_comma (&str
) == SUCCESS
)
9512 /* You are here: "<offset>]{!}". */
9513 inst
.instruction
|= PRE_INDEX
;
9515 offset
= mav_parse_offset (&str
, &negative
);
9522 inst
.error
= _("missing ]");
9528 inst
.instruction
|= WRITE_BACK
;
9534 /* You are here: "], <offset>". */
9537 inst
.error
= _("missing ]");
9541 if (skip_past_comma (&str
) == FAIL
9542 || (offset
= mav_parse_offset (&str
, &negative
), inst
.error
))
9545 inst
.instruction
|= CP_T_WB
; /* Post indexed, set bit W. */
9551 inst
.instruction
|= CP_T_UD
; /* Postive, so set bit U. */
9553 inst
.instruction
|= offset
>> 2;
9559 inst
.error
= BAD_ARGS
;
9572 /* Handle the Format 4 instructions that do not have equivalents in other
9573 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
9582 skip_whitespace (str
);
9584 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9585 || skip_past_comma (&str
) == FAIL
9586 || (Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9588 inst
.error
= BAD_ARGS
;
9592 if (skip_past_comma (&str
) != FAIL
)
9594 /* Three operand format not allowed for TST, CMN, NEG and MVN.
9595 (It isn't allowed for CMP either, but that isn't handled by this
9597 if (inst
.instruction
== T_OPCODE_TST
9598 || inst
.instruction
== T_OPCODE_CMN
9599 || inst
.instruction
== T_OPCODE_NEG
9600 || inst
.instruction
== T_OPCODE_MVN
)
9602 inst
.error
= BAD_ARGS
;
9606 if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9611 inst
.error
= _("dest and source1 must be the same register");
9617 if (inst
.instruction
== T_OPCODE_MUL
9619 as_tsktsk (_("Rs and Rd must be different in MUL"));
9621 inst
.instruction
|= Rd
| (Rs
<< 3);
9629 thumb_add_sub (str
, 0);
9636 thumb_shift (str
, THUMB_ASR
);
9643 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9645 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH9
;
9646 inst
.reloc
.pc_rel
= 1;
9654 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9656 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH12
;
9657 inst
.reloc
.pc_rel
= 1;
9661 /* Find the real, Thumb encoded start of a Thumb function. */
9664 find_real_start (symbolP
)
9668 const char * name
= S_GET_NAME (symbolP
);
9669 symbolS
* new_target
;
9671 /* This definiton must agree with the one in gcc/config/arm/thumb.c. */
9672 #define STUB_NAME ".real_start_of"
9677 /* Names that start with '.' are local labels, not function entry points.
9678 The compiler may generate BL instructions to these labels because it
9679 needs to perform a branch to a far away location. */
9683 real_start
= malloc (strlen (name
) + strlen (STUB_NAME
) + 1);
9684 sprintf (real_start
, "%s%s", STUB_NAME
, name
);
9686 new_target
= symbol_find (real_start
);
9688 if (new_target
== NULL
)
9690 as_warn ("Failed to find real start of function: %s\n", name
);
9691 new_target
= symbolP
;
9703 if (my_get_expression (& inst
.reloc
.exp
, & str
))
9706 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH23
;
9707 inst
.reloc
.pc_rel
= 1;
9710 /* If the destination of the branch is a defined symbol which does not have
9711 the THUMB_FUNC attribute, then we must be calling a function which has
9712 the (interfacearm) attribute. We look for the Thumb entry point to that
9713 function and change the branch to refer to that function instead. */
9714 if ( inst
.reloc
.exp
.X_op
== O_symbol
9715 && inst
.reloc
.exp
.X_add_symbol
!= NULL
9716 && S_IS_DEFINED (inst
.reloc
.exp
.X_add_symbol
)
9717 && ! THUMB_IS_FUNC (inst
.reloc
.exp
.X_add_symbol
))
9718 inst
.reloc
.exp
.X_add_symbol
=
9719 find_real_start (inst
.reloc
.exp
.X_add_symbol
);
9728 skip_whitespace (str
);
9730 if ((reg
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
9733 /* This sets THUMB_H2 from the top bit of reg. */
9734 inst
.instruction
|= reg
<< 3;
9736 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
9737 should cause the alignment to be checked once it is known. This is
9738 because BX PC only works if the instruction is word aligned. */
9747 thumb_mov_compare (str
, THUMB_COMPARE
);
9757 skip_whitespace (str
);
9759 if ((Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9763 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
9767 if (skip_past_comma (&str
) == FAIL
9768 || (range
= reg_list (&str
)) == FAIL
)
9771 inst
.error
= BAD_ARGS
;
9775 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
9777 /* This really doesn't seem worth it. */
9778 inst
.reloc
.type
= BFD_RELOC_NONE
;
9779 inst
.error
= _("expression too complex");
9785 inst
.error
= _("only lo-regs valid in load/store multiple");
9789 inst
.instruction
|= (Rb
<< 8) | range
;
9797 thumb_load_store (str
, THUMB_LOAD
, THUMB_WORD
);
9804 thumb_load_store (str
, THUMB_LOAD
, THUMB_BYTE
);
9811 thumb_load_store (str
, THUMB_LOAD
, THUMB_HALFWORD
);
9820 skip_whitespace (str
);
9822 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9823 || skip_past_comma (&str
) == FAIL
9825 || (Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9826 || skip_past_comma (&str
) == FAIL
9827 || (Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9831 inst
.error
= _("syntax: ldrs[b] Rd, [Rb, Ro]");
9835 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
9843 thumb_shift (str
, THUMB_LSL
);
9850 thumb_shift (str
, THUMB_LSR
);
9857 thumb_mov_compare (str
, THUMB_MOVE
);
9866 skip_whitespace (str
);
9868 if ((range
= reg_list (&str
)) == FAIL
)
9871 inst
.error
= BAD_ARGS
;
9875 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
9877 /* This really doesn't seem worth it. */
9878 inst
.reloc
.type
= BFD_RELOC_NONE
;
9879 inst
.error
= _("expression too complex");
9885 if ((inst
.instruction
== T_OPCODE_PUSH
9886 && (range
& ~0xff) == 1 << REG_LR
)
9887 || (inst
.instruction
== T_OPCODE_POP
9888 && (range
& ~0xff) == 1 << REG_PC
))
9890 inst
.instruction
|= THUMB_PP_PC_LR
;
9895 inst
.error
= _("invalid register list to push/pop instruction");
9900 inst
.instruction
|= range
;
9908 thumb_load_store (str
, THUMB_STORE
, THUMB_WORD
);
9915 thumb_load_store (str
, THUMB_STORE
, THUMB_BYTE
);
9922 thumb_load_store (str
, THUMB_STORE
, THUMB_HALFWORD
);
9929 thumb_add_sub (str
, 1);
9936 skip_whitespace (str
);
9938 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9941 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
9952 /* This is a pseudo-op of the form "adr rd, label" to be converted
9953 into a relative address of the form "add rd, pc, #label-.-4". */
9954 skip_whitespace (str
);
9956 /* Store Rd in temporary location inside instruction. */
9957 if ((reg
= reg_required_here (&str
, 4)) == FAIL
9958 || (reg
> 7) /* For Thumb reg must be r0..r7. */
9959 || skip_past_comma (&str
) == FAIL
9960 || my_get_expression (&inst
.reloc
.exp
, &str
))
9963 inst
.error
= BAD_ARGS
;
9967 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
9968 inst
.reloc
.exp
.X_add_number
-= 4; /* PC relative adjust. */
9969 inst
.reloc
.pc_rel
= 1;
9970 inst
.instruction
|= REG_PC
; /* Rd is already placed into the instruction. */
9976 insert_reg (r
, htab
)
9977 const struct reg_entry
*r
;
9978 struct hash_control
*htab
;
9980 int len
= strlen (r
->name
) + 2;
9981 char * buf
= (char *) xmalloc (len
);
9982 char * buf2
= (char *) xmalloc (len
);
9985 #ifdef REGISTER_PREFIX
9986 buf
[i
++] = REGISTER_PREFIX
;
9989 strcpy (buf
+ i
, r
->name
);
9991 for (i
= 0; buf
[i
]; i
++)
9992 buf2
[i
] = TOUPPER (buf
[i
]);
9996 hash_insert (htab
, buf
, (PTR
) r
);
9997 hash_insert (htab
, buf2
, (PTR
) r
);
10001 build_reg_hsh (map
)
10002 struct reg_map
*map
;
10004 const struct reg_entry
*r
;
10006 if ((map
->htab
= hash_new ()) == NULL
)
10007 as_fatal (_("virtual memory exhausted"));
10009 for (r
= map
->names
; r
->name
!= NULL
; r
++)
10010 insert_reg (r
, map
->htab
);
10014 insert_reg_alias (str
, regnum
, htab
)
10017 struct hash_control
*htab
;
10019 struct reg_entry
*new =
10020 (struct reg_entry
*) xmalloc (sizeof (struct reg_entry
));
10021 char *name
= xmalloc (strlen (str
) + 1);
10022 strcpy (name
, str
);
10025 new->number
= regnum
;
10027 hash_insert (htab
, name
, (PTR
) new);
10030 /* Look for the .req directive. This is of the form:
10032 newname .req existing_name
10034 If we find one, or if it looks sufficiently like one that we want to
10035 handle any error here, return non-zero. Otherwise return zero. */
10037 create_register_alias (newname
, p
)
10045 skip_whitespace (q
);
10050 if (*q
&& !strncmp (q
, ".req ", 5))
10055 #ifdef IGNORE_OPCODE_CASE
10056 newname
= original_case_string
;
10058 copy_of_str
= newname
;
10061 skip_whitespace (q
);
10063 for (r
= q
; *r
!= '\0'; r
++)
10069 enum arm_reg_type new_type
, old_type
;
10074 old_type
= arm_reg_parse_any (q
);
10077 new_type
= arm_reg_parse_any (newname
);
10079 if (new_type
== REG_TYPE_MAX
)
10081 if (old_type
!= REG_TYPE_MAX
)
10083 old_regno
= arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
);
10084 insert_reg_alias (newname
, old_regno
,
10085 all_reg_maps
[old_type
].htab
);
10088 as_warn (_("register '%s' does not exist\n"), q
);
10090 else if (old_type
== REG_TYPE_MAX
)
10092 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
10097 /* Do not warn about redefinitions to the same alias. */
10098 if (new_type
!= old_type
10099 || (arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
)
10100 != arm_reg_parse (&q
, all_reg_maps
[new_type
].htab
)))
10101 as_warn (_("ignoring redefinition of register alias '%s'"),
10107 as_warn (_("ignoring incomplete .req pseuso op"));
10117 set_constant_flonums ()
10121 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
10122 if (atof_ieee ((char *) fp_const
[i
], 'x', fp_values
[i
]) == NULL
)
10126 /* Iterate over the base tables to create the instruction patterns. */
10128 build_arm_ops_hsh ()
10132 static struct obstack insn_obstack
;
10134 obstack_begin (&insn_obstack
, 4000);
10136 for (i
= 0; i
< sizeof (insns
) / sizeof (struct asm_opcode
); i
++)
10138 const struct asm_opcode
*insn
= insns
+ i
;
10140 if (insn
->cond_offset
!= 0)
10142 /* Insn supports conditional execution. Build the varaints
10143 and insert them in the hash table. */
10144 for (j
= 0; j
< sizeof (conds
) / sizeof (struct asm_cond
); j
++)
10146 unsigned len
= strlen (insn
->template);
10147 struct asm_opcode
*new;
10150 new = obstack_alloc (&insn_obstack
, sizeof (struct asm_opcode
));
10151 /* All condition codes are two characters. */
10152 template = obstack_alloc (&insn_obstack
, len
+ 3);
10154 strncpy (template, insn
->template, insn
->cond_offset
);
10155 strcpy (template + insn
->cond_offset
, conds
[j
].template);
10156 if (len
> insn
->cond_offset
)
10157 strcpy (template + insn
->cond_offset
+ 2,
10158 insn
->template + insn
->cond_offset
);
10159 new->template = template;
10160 new->cond_offset
= 0;
10161 new->variant
= insn
->variant
;
10162 new->parms
= insn
->parms
;
10163 new->value
= (insn
->value
& ~COND_MASK
) | conds
[j
].value
;
10165 hash_insert (arm_ops_hsh
, new->template, (PTR
) new);
10168 /* Finally, insert the unconditional insn in the table directly;
10169 no need to build a copy. */
10170 hash_insert (arm_ops_hsh
, insn
->template, (PTR
) insn
);
10174 #if defined OBJ_ELF || defined OBJ_COFF
10177 #define arm_Note Elf_External_Note
10181 unsigned char namesz
[4]; /* Size of entry's owner string. */
10182 unsigned char descsz
[4]; /* Size of the note descriptor. */
10183 unsigned char type
[4]; /* Interpretation of the descriptor. */
10184 char name
[1]; /* Start of the name+desc data. */
10188 /* The description is kept to a fix sized in order to make updating
10189 it and merging it easier. */
10190 #define ARM_NOTE_DESCRIPTION_LENGTH 8
10193 arm_add_note (name
, description
, type
)
10195 const char * description
;
10198 arm_Note note ATTRIBUTE_UNUSED
;
10200 unsigned int name_len
;
10202 name_len
= (strlen (name
) + 1 + 3) & ~3;
10204 p
= frag_more (sizeof (note
.namesz
));
10205 md_number_to_chars (p
, (valueT
) name_len
, sizeof (note
.namesz
));
10207 p
= frag_more (sizeof (note
.descsz
));
10208 md_number_to_chars (p
, (valueT
) ARM_NOTE_DESCRIPTION_LENGTH
, sizeof (note
.descsz
));
10210 p
= frag_more (sizeof (note
.type
));
10211 md_number_to_chars (p
, (valueT
) type
, sizeof (note
.type
));
10213 p
= frag_more (name_len
);
10216 p
= frag_more (ARM_NOTE_DESCRIPTION_LENGTH
);
10217 strncpy (p
, description
, ARM_NOTE_DESCRIPTION_LENGTH
);
10218 frag_align (2, 0, 0);
10228 if ( (arm_ops_hsh
= hash_new ()) == NULL
10229 || (arm_tops_hsh
= hash_new ()) == NULL
10230 || (arm_cond_hsh
= hash_new ()) == NULL
10231 || (arm_shift_hsh
= hash_new ()) == NULL
10232 || (arm_psr_hsh
= hash_new ()) == NULL
)
10233 as_fatal (_("virtual memory exhausted"));
10235 build_arm_ops_hsh ();
10236 for (i
= 0; i
< sizeof (tinsns
) / sizeof (struct thumb_opcode
); i
++)
10237 hash_insert (arm_tops_hsh
, tinsns
[i
].template, (PTR
) (tinsns
+ i
));
10238 for (i
= 0; i
< sizeof (conds
) / sizeof (struct asm_cond
); i
++)
10239 hash_insert (arm_cond_hsh
, conds
[i
].template, (PTR
) (conds
+ i
));
10240 for (i
= 0; i
< sizeof (shift_names
) / sizeof (struct asm_shift_name
); i
++)
10241 hash_insert (arm_shift_hsh
, shift_names
[i
].name
, (PTR
) (shift_names
+ i
));
10242 for (i
= 0; i
< sizeof (psrs
) / sizeof (struct asm_psr
); i
++)
10243 hash_insert (arm_psr_hsh
, psrs
[i
].template, (PTR
) (psrs
+ i
));
10245 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
10246 build_reg_hsh (all_reg_maps
+ i
);
10248 set_constant_flonums ();
10250 /* Set the cpu variant based on the command-line options. We prefer
10251 -mcpu= over -march= if both are set (as for GCC); and we prefer
10252 -mfpu= over any other way of setting the floating point unit.
10253 Use of legacy options with new options are faulted. */
10254 if (legacy_cpu
!= -1)
10256 if (mcpu_cpu_opt
!= -1 || march_cpu_opt
!= -1)
10257 as_bad (_("use of old and new-style options to set CPU type"));
10259 mcpu_cpu_opt
= legacy_cpu
;
10261 else if (mcpu_cpu_opt
== -1)
10262 mcpu_cpu_opt
= march_cpu_opt
;
10264 if (legacy_fpu
!= -1)
10266 if (mfpu_opt
!= -1)
10267 as_bad (_("use of old and new-style options to set FPU type"));
10269 mfpu_opt
= legacy_fpu
;
10271 else if (mfpu_opt
== -1)
10273 #if !(defined (TE_LINUX) || defined (TE_NetBSD))
10274 /* Some environments specify a default FPU. If they don't, infer it
10275 from the processor. */
10276 if (mcpu_fpu_opt
!= -1)
10277 mfpu_opt
= mcpu_fpu_opt
;
10279 mfpu_opt
= march_fpu_opt
;
10281 mfpu_opt
= FPU_DEFAULT
;
10285 if (mfpu_opt
== -1)
10287 if (mcpu_cpu_opt
== -1)
10288 mfpu_opt
= FPU_DEFAULT
;
10289 else if (mcpu_cpu_opt
& ARM_EXT_V5
)
10290 mfpu_opt
= FPU_ARCH_VFP_V2
;
10292 mfpu_opt
= FPU_ARCH_FPA
;
10295 if (mcpu_cpu_opt
== -1)
10296 mcpu_cpu_opt
= CPU_DEFAULT
;
10298 cpu_variant
= mcpu_cpu_opt
| mfpu_opt
;
10300 #if defined OBJ_COFF || defined OBJ_ELF
10302 unsigned int flags
= 0;
10304 /* Set the flags in the private structure. */
10305 if (uses_apcs_26
) flags
|= F_APCS26
;
10306 if (support_interwork
) flags
|= F_INTERWORK
;
10307 if (uses_apcs_float
) flags
|= F_APCS_FLOAT
;
10308 if (pic_code
) flags
|= F_PIC
;
10309 if ((cpu_variant
& FPU_ANY
) == FPU_NONE
10310 || (cpu_variant
& FPU_ANY
) == FPU_ARCH_VFP
) /* VFP layout only. */
10311 flags
|= F_SOFT_FLOAT
;
10312 /* Using VFP conventions (even if soft-float). */
10313 if (cpu_variant
& FPU_VFP_EXT_NONE
) flags
|= F_VFP_FLOAT
;
10315 #if defined OBJ_ELF
10316 if (cpu_variant
& ARM_CEXT_MAVERICK
)
10318 flags
^= F_SOFT_FLOAT
;
10319 flags
|= EF_ARM_MAVERICK_FLOAT
;
10323 bfd_set_private_flags (stdoutput
, flags
);
10325 /* We have run out flags in the COFF header to encode the
10326 status of ATPCS support, so instead we create a dummy,
10327 empty, debug section called .arm.atpcs. */
10332 sec
= bfd_make_section (stdoutput
, ".arm.atpcs");
10336 bfd_set_section_flags
10337 (stdoutput
, sec
, SEC_READONLY
| SEC_DEBUGGING
/* | SEC_HAS_CONTENTS */);
10338 bfd_set_section_size (stdoutput
, sec
, 0);
10339 bfd_set_section_contents (stdoutput
, sec
, NULL
, 0, 0);
10345 /* Record the CPU type as well. */
10346 switch (cpu_variant
& ARM_CPU_MASK
)
10349 mach
= bfd_mach_arm_2
;
10352 case ARM_3
: /* Also ARM_250. */
10353 mach
= bfd_mach_arm_2a
;
10356 case ARM_6
: /* Also ARM_7. */
10357 mach
= bfd_mach_arm_3
;
10361 mach
= bfd_mach_arm_unknown
;
10365 /* Catch special cases. */
10366 if (cpu_variant
& ARM_CEXT_IWMMXT
)
10367 mach
= bfd_mach_arm_iWMMXt
;
10368 else if (cpu_variant
& ARM_CEXT_XSCALE
)
10369 mach
= bfd_mach_arm_XScale
;
10370 else if (cpu_variant
& ARM_CEXT_MAVERICK
)
10371 mach
= bfd_mach_arm_ep9312
;
10372 else if (cpu_variant
& ARM_EXT_V5E
)
10373 mach
= bfd_mach_arm_5TE
;
10374 else if (cpu_variant
& ARM_EXT_V5
)
10376 if (cpu_variant
& ARM_EXT_V4T
)
10377 mach
= bfd_mach_arm_5T
;
10379 mach
= bfd_mach_arm_5
;
10381 else if (cpu_variant
& ARM_EXT_V4
)
10383 if (cpu_variant
& ARM_EXT_V4T
)
10384 mach
= bfd_mach_arm_4T
;
10386 mach
= bfd_mach_arm_4
;
10388 else if (cpu_variant
& ARM_EXT_V3M
)
10389 mach
= bfd_mach_arm_3M
;
10391 #if 0 /* Suppressed - for now. */
10392 #if defined (OBJ_ELF) || defined (OBJ_COFF)
10394 /* Create a .note section to fully identify this arm binary. */
10396 #define NOTE_ARCH_STRING "arch: "
10398 #if defined OBJ_COFF && ! defined NT_VERSION
10399 #define NT_VERSION 1
10404 segT current_seg
= now_seg
;
10405 subsegT current_subseg
= now_subseg
;
10406 asection
* arm_arch
;
10407 const char * arch_string
;
10409 arm_arch
= bfd_make_section_old_way (stdoutput
, ARM_NOTE_SECTION
);
10412 bfd_set_section_flags (stdoutput
, arm_arch
,
10413 SEC_DATA
| SEC_ALLOC
| SEC_LOAD
| SEC_LINK_ONCE \
10414 | SEC_HAS_CONTENTS
);
10416 arm_arch
->output_section
= arm_arch
;
10417 subseg_set (arm_arch
, 0);
10422 case bfd_mach_arm_unknown
: arch_string
= "unknown"; break;
10423 case bfd_mach_arm_2
: arch_string
= "armv2"; break;
10424 case bfd_mach_arm_2a
: arch_string
= "armv2a"; break;
10425 case bfd_mach_arm_3
: arch_string
= "armv3"; break;
10426 case bfd_mach_arm_3M
: arch_string
= "armv3M"; break;
10427 case bfd_mach_arm_4
: arch_string
= "armv4"; break;
10428 case bfd_mach_arm_4T
: arch_string
= "armv4t"; break;
10429 case bfd_mach_arm_5
: arch_string
= "armv5"; break;
10430 case bfd_mach_arm_5T
: arch_string
= "armv5t"; break;
10431 case bfd_mach_arm_5TE
: arch_string
= "armv5te"; break;
10432 case bfd_mach_arm_XScale
: arch_string
= "XScale"; break;
10433 case bfd_mach_arm_ep9312
: arch_string
= "ep9312"; break;
10434 case bfd_mach_arm_iWMMXt
: arch_string
= "iWMMXt"; break;
10437 arm_add_note (NOTE_ARCH_STRING
, arch_string
, NT_ARCH
);
10439 subseg_set (current_seg
, current_subseg
);
10442 #endif /* Suppressed code. */
10444 bfd_set_arch_mach (stdoutput
, TARGET_ARCH
, mach
);
10447 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
10448 for use in the a.out file, and stores them in the array pointed to by buf.
10449 This knows about the endian-ness of the target machine and does
10450 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
10451 2 (short) and 4 (long) Floating numbers are put out as a series of
10452 LITTLENUMS (shorts, here at least). */
10455 md_number_to_chars (buf
, val
, n
)
10460 if (target_big_endian
)
10461 number_to_chars_bigendian (buf
, val
, n
);
10463 number_to_chars_littleendian (buf
, val
, n
);
10467 md_chars_to_number (buf
, n
)
10472 unsigned char * where
= (unsigned char *) buf
;
10474 if (target_big_endian
)
10479 result
|= (*where
++ & 255);
10487 result
|= (where
[n
] & 255);
10494 /* Turn a string in input_line_pointer into a floating point constant
10495 of type TYPE, and store the appropriate bytes in *LITP. The number
10496 of LITTLENUMS emitted is stored in *SIZEP. An error message is
10497 returned, or NULL on OK.
10499 Note that fp constants aren't represent in the normal way on the ARM.
10500 In big endian mode, things are as expected. However, in little endian
10501 mode fp constants are big-endian word-wise, and little-endian byte-wise
10502 within the words. For example, (double) 1.1 in big endian mode is
10503 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
10504 the byte sequence 99 99 f1 3f 9a 99 99 99.
10506 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
10509 md_atof (type
, litP
, sizeP
)
10515 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
10547 return _("bad call to MD_ATOF()");
10550 t
= atof_ieee (input_line_pointer
, type
, words
);
10552 input_line_pointer
= t
;
10555 if (target_big_endian
)
10557 for (i
= 0; i
< prec
; i
++)
10559 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
10565 if (cpu_variant
& FPU_ARCH_VFP
)
10566 for (i
= prec
- 1; i
>= 0; i
--)
10568 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
10572 /* For a 4 byte float the order of elements in `words' is 1 0.
10573 For an 8 byte float the order is 1 0 3 2. */
10574 for (i
= 0; i
< prec
; i
+= 2)
10576 md_number_to_chars (litP
, (valueT
) words
[i
+ 1], 2);
10577 md_number_to_chars (litP
+ 2, (valueT
) words
[i
], 2);
10585 /* The knowledge of the PC's pipeline offset is built into the insns
10589 md_pcrel_from (fixP
)
10593 && S_GET_SEGMENT (fixP
->fx_addsy
) == undefined_section
10594 && fixP
->fx_subsy
== NULL
)
10597 if (fixP
->fx_pcrel
&& (fixP
->fx_r_type
== BFD_RELOC_ARM_THUMB_ADD
))
10599 /* PC relative addressing on the Thumb is slightly odd
10600 as the bottom two bits of the PC are forced to zero
10601 for the calculation. */
10602 return (fixP
->fx_where
+ fixP
->fx_frag
->fr_address
) & ~3;
10606 /* The pattern was adjusted to accomodate CE's off-by-one fixups,
10607 so we un-adjust here to compensate for the accomodation. */
10608 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
+ 8;
10610 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
10614 /* Round up a section size to the appropriate boundary. */
10617 md_section_align (segment
, size
)
10618 segT segment ATTRIBUTE_UNUSED
;
10624 /* Round all sects to multiple of 4. */
10625 return (size
+ 3) & ~3;
10629 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
10630 Otherwise we have no need to default values of symbols. */
10633 md_undefined_symbol (name
)
10634 char * name ATTRIBUTE_UNUSED
;
10637 if (name
[0] == '_' && name
[1] == 'G'
10638 && streq (name
, GLOBAL_OFFSET_TABLE_NAME
))
10642 if (symbol_find (name
))
10643 as_bad ("GOT already in the symbol table");
10645 GOT_symbol
= symbol_new (name
, undefined_section
,
10646 (valueT
) 0, & zero_address_frag
);
10656 /* arm_reg_parse () := if it looks like a register, return its token and
10657 advance the pointer. */
10660 arm_reg_parse (ccp
, htab
)
10661 register char ** ccp
;
10662 struct hash_control
*htab
;
10664 char * start
= * ccp
;
10667 struct reg_entry
* reg
;
10669 #ifdef REGISTER_PREFIX
10670 if (*start
!= REGISTER_PREFIX
)
10675 #ifdef OPTIONAL_REGISTER_PREFIX
10676 if (*p
== OPTIONAL_REGISTER_PREFIX
)
10680 if (!ISALPHA (*p
) || !is_name_beginner (*p
))
10684 while (ISALPHA (c
) || ISDIGIT (c
) || c
== '_')
10688 reg
= (struct reg_entry
*) hash_find (htab
, start
);
10694 return reg
->number
;
10700 /* Search for the following register name in each of the possible reg name
10701 tables. Return the classification if found, or REG_TYPE_MAX if not
10703 static enum arm_reg_type
10704 arm_reg_parse_any (cp
)
10709 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
10710 if (arm_reg_parse (&cp
, all_reg_maps
[i
].htab
) != FAIL
)
10711 return (enum arm_reg_type
) i
;
10713 return REG_TYPE_MAX
;
10717 md_apply_fix3 (fixP
, valP
, seg
)
10722 offsetT value
= * valP
;
10724 unsigned int newimm
;
10725 unsigned long temp
;
10727 char * buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
10728 arm_fix_data
* arm_data
= (arm_fix_data
*) fixP
->tc_fix_data
;
10730 assert (fixP
->fx_r_type
< BFD_RELOC_UNUSED
);
10732 /* Note whether this will delete the relocation. */
10734 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
10735 doesn't work fully.) */
10736 if ((fixP
->fx_addsy
== 0 || symbol_constant_p (fixP
->fx_addsy
))
10737 && !fixP
->fx_pcrel
)
10739 if (fixP
->fx_addsy
== 0 && !fixP
->fx_pcrel
)
10743 /* If this symbol is in a different section then we need to leave it for
10744 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
10745 so we have to undo it's effects here. */
10746 if (fixP
->fx_pcrel
)
10748 if (fixP
->fx_addsy
!= NULL
10749 && S_IS_DEFINED (fixP
->fx_addsy
)
10750 && S_GET_SEGMENT (fixP
->fx_addsy
) != seg
)
10753 && (fixP
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
10754 || fixP
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
10758 value
+= md_pcrel_from (fixP
);
10762 /* Remember value for emit_reloc. */
10763 fixP
->fx_addnumber
= value
;
10765 switch (fixP
->fx_r_type
)
10767 case BFD_RELOC_ARM_IMMEDIATE
:
10768 newimm
= validate_immediate (value
);
10769 temp
= md_chars_to_number (buf
, INSN_SIZE
);
10771 /* If the instruction will fail, see if we can fix things up by
10772 changing the opcode. */
10773 if (newimm
== (unsigned int) FAIL
10774 && (newimm
= negate_data_op (&temp
, value
)) == (unsigned int) FAIL
)
10776 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10777 _("invalid constant (%lx) after fixup"),
10778 (unsigned long) value
);
10782 newimm
|= (temp
& 0xfffff000);
10783 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
10787 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
10789 unsigned int highpart
= 0;
10790 unsigned int newinsn
= 0xe1a00000; /* nop. */
10792 newimm
= validate_immediate (value
);
10793 temp
= md_chars_to_number (buf
, INSN_SIZE
);
10795 /* If the instruction will fail, see if we can fix things up by
10796 changing the opcode. */
10797 if (newimm
== (unsigned int) FAIL
10798 && (newimm
= negate_data_op (& temp
, value
)) == (unsigned int) FAIL
)
10800 /* No ? OK - try using two ADD instructions to generate
10802 newimm
= validate_immediate_twopart (value
, & highpart
);
10804 /* Yes - then make sure that the second instruction is
10806 if (newimm
!= (unsigned int) FAIL
)
10808 /* Still No ? Try using a negated value. */
10809 else if ((newimm
= validate_immediate_twopart (- value
, & highpart
)) != (unsigned int) FAIL
)
10810 temp
= newinsn
= (temp
& OPCODE_MASK
) | OPCODE_SUB
<< DATA_OP_SHIFT
;
10811 /* Otherwise - give up. */
10814 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10815 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
10820 /* Replace the first operand in the 2nd instruction (which
10821 is the PC) with the destination register. We have
10822 already added in the PC in the first instruction and we
10823 do not want to do it again. */
10824 newinsn
&= ~ 0xf0000;
10825 newinsn
|= ((newinsn
& 0x0f000) << 4);
10828 newimm
|= (temp
& 0xfffff000);
10829 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
10831 highpart
|= (newinsn
& 0xfffff000);
10832 md_number_to_chars (buf
+ INSN_SIZE
, (valueT
) highpart
, INSN_SIZE
);
10836 case BFD_RELOC_ARM_OFFSET_IMM
:
10842 if (validate_offset_imm (value
, 0) == FAIL
)
10844 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10845 _("bad immediate value for offset (%ld)"),
10850 newval
= md_chars_to_number (buf
, INSN_SIZE
);
10851 newval
&= 0xff7ff000;
10852 newval
|= value
| (sign
? INDEX_UP
: 0);
10853 md_number_to_chars (buf
, newval
, INSN_SIZE
);
10856 case BFD_RELOC_ARM_OFFSET_IMM8
:
10857 case BFD_RELOC_ARM_HWLITERAL
:
10863 if (validate_offset_imm (value
, 1) == FAIL
)
10865 if (fixP
->fx_r_type
== BFD_RELOC_ARM_HWLITERAL
)
10866 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10867 _("invalid literal constant: pool needs to be closer"));
10869 as_bad (_("bad immediate value for half-word offset (%ld)"),
10874 newval
= md_chars_to_number (buf
, INSN_SIZE
);
10875 newval
&= 0xff7ff0f0;
10876 newval
|= ((value
>> 4) << 8) | (value
& 0xf) | (sign
? INDEX_UP
: 0);
10877 md_number_to_chars (buf
, newval
, INSN_SIZE
);
10880 case BFD_RELOC_ARM_LITERAL
:
10886 if (validate_offset_imm (value
, 0) == FAIL
)
10888 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10889 _("invalid literal constant: pool needs to be closer"));
10893 newval
= md_chars_to_number (buf
, INSN_SIZE
);
10894 newval
&= 0xff7ff000;
10895 newval
|= value
| (sign
? INDEX_UP
: 0);
10896 md_number_to_chars (buf
, newval
, INSN_SIZE
);
10899 case BFD_RELOC_ARM_SHIFT_IMM
:
10900 newval
= md_chars_to_number (buf
, INSN_SIZE
);
10901 if (((unsigned long) value
) > 32
10903 && (((newval
& 0x60) == 0) || (newval
& 0x60) == 0x60)))
10905 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10906 _("shift expression is too large"));
10911 /* Shifts of zero must be done as lsl. */
10913 else if (value
== 32)
10915 newval
&= 0xfffff07f;
10916 newval
|= (value
& 0x1f) << 7;
10917 md_number_to_chars (buf
, newval
, INSN_SIZE
);
10920 case BFD_RELOC_ARM_SWI
:
10921 if (arm_data
->thumb_mode
)
10923 if (((unsigned long) value
) > 0xff)
10924 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10925 _("invalid swi expression"));
10926 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xff00;
10928 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
10932 if (((unsigned long) value
) > 0x00ffffff)
10933 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10934 _("invalid swi expression"));
10935 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff000000;
10937 md_number_to_chars (buf
, newval
, INSN_SIZE
);
10941 case BFD_RELOC_ARM_MULTI
:
10942 if (((unsigned long) value
) > 0xffff)
10943 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10944 _("invalid expression in load/store multiple"));
10945 newval
= value
| md_chars_to_number (buf
, INSN_SIZE
);
10946 md_number_to_chars (buf
, newval
, INSN_SIZE
);
10949 case BFD_RELOC_ARM_PCREL_BRANCH
:
10950 newval
= md_chars_to_number (buf
, INSN_SIZE
);
10952 /* Sign-extend a 24-bit number. */
10953 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
10957 value
= fixP
->fx_offset
;
10960 /* We are going to store value (shifted right by two) in the
10961 instruction, in a 24 bit, signed field. Thus we need to check
10962 that none of the top 8 bits of the shifted value (top 7 bits of
10963 the unshifted, unsigned value) are set, or that they are all set. */
10964 if ((value
& ~ ((offsetT
) 0x1ffffff)) != 0
10965 && ((value
& ~ ((offsetT
) 0x1ffffff)) != ~ ((offsetT
) 0x1ffffff)))
10968 /* Normally we would be stuck at this point, since we cannot store
10969 the absolute address that is the destination of the branch in the
10970 24 bits of the branch instruction. If however, we happen to know
10971 that the destination of the branch is in the same section as the
10972 branch instruciton itself, then we can compute the relocation for
10973 ourselves and not have to bother the linker with it.
10975 FIXME: The tests for OBJ_ELF and ! target_oabi are only here
10976 because I have not worked out how to do this for OBJ_COFF or
10979 && fixP
->fx_addsy
!= NULL
10980 && S_IS_DEFINED (fixP
->fx_addsy
)
10981 && S_GET_SEGMENT (fixP
->fx_addsy
) == seg
)
10983 /* Get pc relative value to go into the branch. */
10986 /* Permit a backward branch provided that enough bits
10987 are set. Allow a forwards branch, provided that
10988 enough bits are clear. */
10989 if ( (value
& ~ ((offsetT
) 0x1ffffff)) == ~ ((offsetT
) 0x1ffffff)
10990 || (value
& ~ ((offsetT
) 0x1ffffff)) == 0)
10994 if (! fixP
->fx_done
)
10996 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10997 _("GAS can't handle same-section branch dest >= 0x04000000"));
11001 value
+= SEXT24 (newval
);
11003 if ( (value
& ~ ((offsetT
) 0xffffff)) != 0
11004 && ((value
& ~ ((offsetT
) 0xffffff)) != ~ ((offsetT
) 0xffffff)))
11005 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11006 _("out of range branch"));
11008 newval
= (value
& 0x00ffffff) | (newval
& 0xff000000);
11009 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11012 case BFD_RELOC_ARM_PCREL_BLX
:
11015 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11019 value
= fixP
->fx_offset
;
11021 hbit
= (value
>> 1) & 1;
11022 value
= (value
>> 2) & 0x00ffffff;
11023 value
= (value
+ (newval
& 0x00ffffff)) & 0x00ffffff;
11024 newval
= value
| (newval
& 0xfe000000) | (hbit
<< 24);
11025 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11029 case BFD_RELOC_THUMB_PCREL_BRANCH9
: /* Conditional branch. */
11030 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11032 addressT diff
= (newval
& 0xff) << 1;
11037 if ((value
& ~0xff) && ((value
& ~0xff) != ~0xff))
11038 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11039 _("branch out of range"));
11040 newval
= (newval
& 0xff00) | ((value
& 0x1ff) >> 1);
11042 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11045 case BFD_RELOC_THUMB_PCREL_BRANCH12
: /* Unconditional branch. */
11046 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11048 addressT diff
= (newval
& 0x7ff) << 1;
11053 if ((value
& ~0x7ff) && ((value
& ~0x7ff) != ~0x7ff))
11054 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11055 _("branch out of range"));
11056 newval
= (newval
& 0xf800) | ((value
& 0xfff) >> 1);
11058 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11061 case BFD_RELOC_THUMB_PCREL_BLX
:
11062 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
11067 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11068 newval2
= md_chars_to_number (buf
+ THUMB_SIZE
, THUMB_SIZE
);
11069 diff
= ((newval
& 0x7ff) << 12) | ((newval2
& 0x7ff) << 1);
11070 if (diff
& 0x400000)
11073 value
= fixP
->fx_offset
;
11077 if ((value
& ~0x3fffff) && ((value
& ~0x3fffff) != ~0x3fffff))
11078 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11079 _("branch with link out of range"));
11081 newval
= (newval
& 0xf800) | ((value
& 0x7fffff) >> 12);
11082 newval2
= (newval2
& 0xf800) | ((value
& 0xfff) >> 1);
11083 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
)
11084 /* For a BLX instruction, make sure that the relocation is rounded up
11085 to a word boundary. This follows the semantics of the instruction
11086 which specifies that bit 1 of the target address will come from bit
11087 1 of the base address. */
11088 newval2
= (newval2
+ 1) & ~ 1;
11089 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11090 md_number_to_chars (buf
+ THUMB_SIZE
, newval2
, THUMB_SIZE
);
11095 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11096 md_number_to_chars (buf
, value
, 1);
11098 else if (!target_oabi
)
11100 value
= fixP
->fx_offset
;
11101 md_number_to_chars (buf
, value
, 1);
11107 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11108 md_number_to_chars (buf
, value
, 2);
11110 else if (!target_oabi
)
11112 value
= fixP
->fx_offset
;
11113 md_number_to_chars (buf
, value
, 2);
11119 case BFD_RELOC_ARM_GOT32
:
11120 case BFD_RELOC_ARM_GOTOFF
:
11121 md_number_to_chars (buf
, 0, 4);
11125 case BFD_RELOC_RVA
:
11127 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11128 md_number_to_chars (buf
, value
, 4);
11130 else if (!target_oabi
)
11132 value
= fixP
->fx_offset
;
11133 md_number_to_chars (buf
, value
, 4);
11139 case BFD_RELOC_ARM_PLT32
:
11140 /* It appears the instruction is fully prepared at this point. */
11144 case BFD_RELOC_ARM_CP_OFF_IMM
:
11146 if (value
< -1023 || value
> 1023 || (value
& 3))
11147 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11148 _("illegal value for co-processor offset"));
11151 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
11152 newval
|= (value
>> 2) | (sign
? INDEX_UP
: 0);
11153 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11156 case BFD_RELOC_ARM_CP_OFF_IMM_S2
:
11158 if (value
< -255 || value
> 255)
11159 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11160 _("Illegal value for co-processor offset"));
11163 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
11164 newval
|= value
| (sign
? INDEX_UP
: 0);
11165 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11168 case BFD_RELOC_ARM_THUMB_OFFSET
:
11169 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11170 /* Exactly what ranges, and where the offset is inserted depends
11171 on the type of instruction, we can establish this from the
11173 switch (newval
>> 12)
11175 case 4: /* PC load. */
11176 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
11177 forced to zero for these loads, so we will need to round
11178 up the offset if the instruction address is not word
11179 aligned (since the final address produced must be, and
11180 we can only describe word-aligned immediate offsets). */
11182 if ((fixP
->fx_frag
->fr_address
+ fixP
->fx_where
+ value
) & 3)
11183 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11184 _("invalid offset, target not word aligned (0x%08X)"),
11185 (unsigned int) (fixP
->fx_frag
->fr_address
11186 + fixP
->fx_where
+ value
));
11188 if ((value
+ 2) & ~0x3fe)
11189 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11190 _("invalid offset, value too big (0x%08lX)"),
11193 /* Round up, since pc will be rounded down. */
11194 newval
|= (value
+ 2) >> 2;
11197 case 9: /* SP load/store. */
11198 if (value
& ~0x3fc)
11199 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11200 _("invalid offset, value too big (0x%08lX)"),
11202 newval
|= value
>> 2;
11205 case 6: /* Word load/store. */
11207 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11208 _("invalid offset, value too big (0x%08lX)"),
11210 newval
|= value
<< 4; /* 6 - 2. */
11213 case 7: /* Byte load/store. */
11215 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11216 _("invalid offset, value too big (0x%08lX)"),
11218 newval
|= value
<< 6;
11221 case 8: /* Halfword load/store. */
11223 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11224 _("invalid offset, value too big (0x%08lX)"),
11226 newval
|= value
<< 5; /* 6 - 1. */
11230 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11231 "Unable to process relocation for thumb opcode: %lx",
11232 (unsigned long) newval
);
11235 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11238 case BFD_RELOC_ARM_THUMB_ADD
:
11239 /* This is a complicated relocation, since we use it for all of
11240 the following immediate relocations:
11244 9bit ADD/SUB SP word-aligned
11245 10bit ADD PC/SP word-aligned
11247 The type of instruction being processed is encoded in the
11254 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11256 int rd
= (newval
>> 4) & 0xf;
11257 int rs
= newval
& 0xf;
11258 int subtract
= newval
& 0x8000;
11262 if (value
& ~0x1fc)
11263 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11264 _("invalid immediate for stack address calculation"));
11265 newval
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
11266 newval
|= value
>> 2;
11268 else if (rs
== REG_PC
|| rs
== REG_SP
)
11272 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11273 _("invalid immediate for address calculation (value = 0x%08lX)"),
11274 (unsigned long) value
);
11275 newval
= (rs
== REG_PC
? T_OPCODE_ADD_PC
: T_OPCODE_ADD_SP
);
11277 newval
|= value
>> 2;
11282 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11283 _("invalid 8bit immediate"));
11284 newval
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
11285 newval
|= (rd
<< 8) | value
;
11290 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11291 _("invalid 3bit immediate"));
11292 newval
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
11293 newval
|= rd
| (rs
<< 3) | (value
<< 6);
11296 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11299 case BFD_RELOC_ARM_THUMB_IMM
:
11300 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11301 switch (newval
>> 11)
11303 case 0x04: /* 8bit immediate MOV. */
11304 case 0x05: /* 8bit immediate CMP. */
11305 if (value
< 0 || value
> 255)
11306 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11307 _("invalid immediate: %ld is too large"),
11315 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11318 case BFD_RELOC_ARM_THUMB_SHIFT
:
11319 /* 5bit shift value (0..31). */
11320 if (value
< 0 || value
> 31)
11321 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11322 _("illegal Thumb shift value: %ld"), (long) value
);
11323 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xf03f;
11324 newval
|= value
<< 6;
11325 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11328 case BFD_RELOC_VTABLE_INHERIT
:
11329 case BFD_RELOC_VTABLE_ENTRY
:
11333 case BFD_RELOC_NONE
:
11335 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11336 _("bad relocation fixup type (%d)"), fixP
->fx_r_type
);
11340 /* Translate internal representation of relocation info to BFD target
11344 tc_gen_reloc (section
, fixp
)
11345 asection
* section ATTRIBUTE_UNUSED
;
11349 bfd_reloc_code_real_type code
;
11351 reloc
= (arelent
*) xmalloc (sizeof (arelent
));
11353 reloc
->sym_ptr_ptr
= (asymbol
**) xmalloc (sizeof (asymbol
*));
11354 *reloc
->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
11355 reloc
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
11357 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
11359 if (fixp
->fx_pcrel
== 0)
11360 reloc
->addend
= fixp
->fx_offset
;
11362 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
11363 #else /* OBJ_ELF */
11364 reloc
->addend
= fixp
->fx_offset
;
11367 switch (fixp
->fx_r_type
)
11370 if (fixp
->fx_pcrel
)
11372 code
= BFD_RELOC_8_PCREL
;
11377 if (fixp
->fx_pcrel
)
11379 code
= BFD_RELOC_16_PCREL
;
11384 if (fixp
->fx_pcrel
)
11386 code
= BFD_RELOC_32_PCREL
;
11390 case BFD_RELOC_ARM_PCREL_BRANCH
:
11391 case BFD_RELOC_ARM_PCREL_BLX
:
11392 case BFD_RELOC_RVA
:
11393 case BFD_RELOC_THUMB_PCREL_BRANCH9
:
11394 case BFD_RELOC_THUMB_PCREL_BRANCH12
:
11395 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
11396 case BFD_RELOC_THUMB_PCREL_BLX
:
11397 case BFD_RELOC_VTABLE_ENTRY
:
11398 case BFD_RELOC_VTABLE_INHERIT
:
11399 code
= fixp
->fx_r_type
;
11402 case BFD_RELOC_ARM_LITERAL
:
11403 case BFD_RELOC_ARM_HWLITERAL
:
11404 /* If this is called then the a literal has
11405 been referenced across a section boundary. */
11406 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
11407 _("literal referenced across section boundary"));
11411 case BFD_RELOC_ARM_GOT32
:
11412 case BFD_RELOC_ARM_GOTOFF
:
11413 case BFD_RELOC_ARM_PLT32
:
11414 code
= fixp
->fx_r_type
;
11418 case BFD_RELOC_ARM_IMMEDIATE
:
11419 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
11420 _("internal relocation (type: IMMEDIATE) not fixed up"));
11423 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
11424 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
11425 _("ADRL used for a symbol not defined in the same file"));
11428 case BFD_RELOC_ARM_OFFSET_IMM
:
11429 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
11430 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
11437 switch (fixp
->fx_r_type
)
11439 case BFD_RELOC_ARM_OFFSET_IMM8
: type
= "OFFSET_IMM8"; break;
11440 case BFD_RELOC_ARM_SHIFT_IMM
: type
= "SHIFT_IMM"; break;
11441 case BFD_RELOC_ARM_SWI
: type
= "SWI"; break;
11442 case BFD_RELOC_ARM_MULTI
: type
= "MULTI"; break;
11443 case BFD_RELOC_ARM_CP_OFF_IMM
: type
= "CP_OFF_IMM"; break;
11444 case BFD_RELOC_ARM_THUMB_ADD
: type
= "THUMB_ADD"; break;
11445 case BFD_RELOC_ARM_THUMB_SHIFT
: type
= "THUMB_SHIFT"; break;
11446 case BFD_RELOC_ARM_THUMB_IMM
: type
= "THUMB_IMM"; break;
11447 case BFD_RELOC_ARM_THUMB_OFFSET
: type
= "THUMB_OFFSET"; break;
11448 default: type
= _("<unknown>"); break;
11450 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
11451 _("cannot represent %s relocation in this object file format"),
11458 if ((code
== BFD_RELOC_32_PCREL
|| code
== BFD_RELOC_32
)
11460 && fixp
->fx_addsy
== GOT_symbol
)
11462 code
= BFD_RELOC_ARM_GOTPC
;
11463 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
11467 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, code
);
11469 if (reloc
->howto
== NULL
)
11471 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
11472 _("cannot represent %s relocation in this object file format"),
11473 bfd_get_reloc_code_name (code
));
11477 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
11478 vtable entry to be used in the relocation's section offset. */
11479 if (fixp
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
11480 reloc
->address
= fixp
->fx_offset
;
11486 md_estimate_size_before_relax (fragP
, segtype
)
11487 fragS
* fragP ATTRIBUTE_UNUSED
;
11488 segT segtype ATTRIBUTE_UNUSED
;
11490 as_fatal (_("md_estimate_size_before_relax\n"));
11502 as_bad ("%s -- `%s'", inst
.error
, str
);
11506 to
= frag_more (inst
.size
);
11508 if (thumb_mode
&& (inst
.size
> THUMB_SIZE
))
11510 assert (inst
.size
== (2 * THUMB_SIZE
));
11511 md_number_to_chars (to
, inst
.instruction
>> 16, THUMB_SIZE
);
11512 md_number_to_chars (to
+ THUMB_SIZE
, inst
.instruction
, THUMB_SIZE
);
11514 else if (inst
.size
> INSN_SIZE
)
11516 assert (inst
.size
== (2 * INSN_SIZE
));
11517 md_number_to_chars (to
, inst
.instruction
, INSN_SIZE
);
11518 md_number_to_chars (to
+ INSN_SIZE
, inst
.instruction
, INSN_SIZE
);
11521 md_number_to_chars (to
, inst
.instruction
, inst
.size
);
11523 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
11524 fix_new_arm (frag_now
, to
- frag_now
->fr_literal
,
11525 inst
.size
, & inst
.reloc
.exp
, inst
.reloc
.pc_rel
,
11529 dwarf2_emit_insn (inst
.size
);
11541 /* Align the instruction.
11542 This may not be the right thing to do but ... */
11547 /* Align the previous label if needed. */
11548 if (last_label_seen
!= NULL
)
11550 symbol_set_frag (last_label_seen
, frag_now
);
11551 S_SET_VALUE (last_label_seen
, (valueT
) frag_now_fix ());
11552 S_SET_SEGMENT (last_label_seen
, now_seg
);
11555 memset (&inst
, '\0', sizeof (inst
));
11556 inst
.reloc
.type
= BFD_RELOC_NONE
;
11558 skip_whitespace (str
);
11560 /* Scan up to the end of the op-code, which must end in white space or
11562 for (start
= p
= str
; *p
!= '\0'; p
++)
11568 as_bad (_("no operator -- statement `%s'\n"), str
);
11574 const struct thumb_opcode
* opcode
;
11578 opcode
= (const struct thumb_opcode
*) hash_find (arm_tops_hsh
, str
);
11583 /* Check that this instruction is supported for this CPU. */
11584 if (thumb_mode
== 1 && (opcode
->variant
& cpu_variant
) == 0)
11586 as_bad (_("selected processor does not support `%s'"), str
);
11590 inst
.instruction
= opcode
->value
;
11591 inst
.size
= opcode
->size
;
11592 (*opcode
->parms
) (p
);
11599 const struct asm_opcode
* opcode
;
11603 opcode
= (const struct asm_opcode
*) hash_find (arm_ops_hsh
, str
);
11608 /* Check that this instruction is supported for this CPU. */
11609 if ((opcode
->variant
& cpu_variant
) == 0)
11611 as_bad (_("selected processor does not support `%s'"), str
);
11615 inst
.instruction
= opcode
->value
;
11616 inst
.size
= INSN_SIZE
;
11617 (*opcode
->parms
) (p
);
11623 /* It wasn't an instruction, but it might be a register alias of the form
11625 if (create_register_alias (str
, p
))
11628 as_bad (_("bad instruction `%s'"), start
);
11632 Invocation line includes a switch not recognized by the base assembler.
11633 See if it's a processor-specific option.
11635 This routine is somewhat complicated by the need for backwards
11636 compatibility (since older releases of gcc can't be changed).
11637 The new options try to make the interface as compatible as
11640 New options (supported) are:
11642 -mcpu=<cpu name> Assemble for selected processor
11643 -march=<architecture name> Assemble for selected architecture
11644 -mfpu=<fpu architecture> Assemble for selected FPU.
11645 -EB/-mbig-endian Big-endian
11646 -EL/-mlittle-endian Little-endian
11647 -k Generate PIC code
11648 -mthumb Start in Thumb mode
11649 -mthumb-interwork Code supports ARM/Thumb interworking
11651 For now we will also provide support for:
11653 -mapcs-32 32-bit Program counter
11654 -mapcs-26 26-bit Program counter
11655 -macps-float Floats passed in FP registers
11656 -mapcs-reentrant Reentrant code
11658 (sometime these will probably be replaced with -mapcs=<list of options>
11659 and -matpcs=<list of options>)
11661 The remaining options are only supported for back-wards compatibility.
11662 Cpu variants, the arm part is optional:
11663 -m[arm]1 Currently not supported.
11664 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
11665 -m[arm]3 Arm 3 processor
11666 -m[arm]6[xx], Arm 6 processors
11667 -m[arm]7[xx][t][[d]m] Arm 7 processors
11668 -m[arm]8[10] Arm 8 processors
11669 -m[arm]9[20][tdmi] Arm 9 processors
11670 -mstrongarm[110[0]] StrongARM processors
11671 -mxscale XScale processors
11672 -m[arm]v[2345[t[e]]] Arm architectures
11673 -mall All (except the ARM1)
11675 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
11676 -mfpe-old (No float load/store multiples)
11677 -mvfpxd VFP Single precision
11679 -mno-fpu Disable all floating point instructions
11681 The following CPU names are recognized:
11682 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
11683 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
11684 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
11685 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
11686 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
11687 arm10t arm10e, arm1020t, arm1020e, arm10200e,
11688 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
11692 const char * md_shortopts
= "m:k";
11694 #ifdef ARM_BI_ENDIAN
11695 #define OPTION_EB (OPTION_MD_BASE + 0)
11696 #define OPTION_EL (OPTION_MD_BASE + 1)
11698 #if TARGET_BYTES_BIG_ENDIAN
11699 #define OPTION_EB (OPTION_MD_BASE + 0)
11701 #define OPTION_EL (OPTION_MD_BASE + 1)
11705 struct option md_longopts
[] =
11708 {"EB", no_argument
, NULL
, OPTION_EB
},
11711 {"EL", no_argument
, NULL
, OPTION_EL
},
11713 {NULL
, no_argument
, NULL
, 0}
11716 size_t md_longopts_size
= sizeof (md_longopts
);
11718 struct arm_option_table
11720 char *option
; /* Option name to match. */
11721 char *help
; /* Help information. */
11722 int *var
; /* Variable to change. */
11723 int value
; /* What to change it to. */
11724 char *deprecated
; /* If non-null, print this message. */
11727 struct arm_option_table arm_opts
[] =
11729 {"k", N_("generate PIC code"), &pic_code
, 1, NULL
},
11730 {"mthumb", N_("assemble Thumb code"), &thumb_mode
, 1, NULL
},
11731 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
11732 &support_interwork
, 1, NULL
},
11733 {"moabi", N_("use old ABI (ELF only)"), &target_oabi
, 1, NULL
},
11734 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26
, 0, NULL
},
11735 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26
, 1, NULL
},
11736 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float
,
11738 {"mapcs-reentrant", N_("re-entrant code"), &pic_code
, 1, NULL
},
11739 {"matpcs", N_("code is ATPCS conformant"), &atpcs
, 1, NULL
},
11740 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian
, 1, NULL
},
11741 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian
, 1,
11744 /* These are recognized by the assembler, but have no affect on code. */
11745 {"mapcs-frame", N_("use frame pointer"), NULL
, 0, NULL
},
11746 {"mapcs-stack-check", N_("use stack size checking"), NULL
, 0, NULL
},
11748 /* DON'T add any new processors to this list -- we want the whole list
11749 to go away... Add them to the processors table instead. */
11750 {"marm1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
11751 {"m1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
11752 {"marm2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
11753 {"m2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
11754 {"marm250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
11755 {"m250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
11756 {"marm3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
11757 {"m3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
11758 {"marm6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
11759 {"m6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
11760 {"marm600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
11761 {"m600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
11762 {"marm610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
11763 {"m610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
11764 {"marm620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
11765 {"m620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
11766 {"marm7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
11767 {"m7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
11768 {"marm70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
11769 {"m70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
11770 {"marm700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
11771 {"m700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
11772 {"marm700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
11773 {"m700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
11774 {"marm710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
11775 {"m710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
11776 {"marm710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
11777 {"m710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
11778 {"marm720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
11779 {"m720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
11780 {"marm7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
11781 {"m7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
11782 {"marm7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
11783 {"m7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
11784 {"marm7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
11785 {"m7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
11786 {"marm7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
11787 {"m7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
11788 {"marm7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
11789 {"m7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
11790 {"marm7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
11791 {"m7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
11792 {"marm7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
11793 {"m7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
11794 {"marm7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
11795 {"m7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
11796 {"marm7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
11797 {"m7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
11798 {"marm7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
11799 {"m7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
11800 {"marm710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
11801 {"m710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
11802 {"marm720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
11803 {"m720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
11804 {"marm740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
11805 {"m740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
11806 {"marm8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
11807 {"m8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
11808 {"marm810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
11809 {"m810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
11810 {"marm9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
11811 {"m9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
11812 {"marm9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
11813 {"m9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
11814 {"marm920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
11815 {"m920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
11816 {"marm940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
11817 {"m940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
11818 {"mstrongarm", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=strongarm")},
11819 {"mstrongarm110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
11820 N_("use -mcpu=strongarm110")},
11821 {"mstrongarm1100", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
11822 N_("use -mcpu=strongarm1100")},
11823 {"mstrongarm1110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
11824 N_("use -mcpu=strongarm1110")},
11825 {"mxscale", NULL
, &legacy_cpu
, ARM_ARCH_XSCALE
, N_("use -mcpu=xscale")},
11826 {"miwmmxt", NULL
, &legacy_cpu
, ARM_ARCH_IWMMXT
, N_("use -mcpu=iwmmxt")},
11827 {"mall", NULL
, &legacy_cpu
, ARM_ANY
, N_("use -mcpu=all")},
11829 /* Architecture variants -- don't add any more to this list either. */
11830 {"mv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
11831 {"marmv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
11832 {"mv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
11833 {"marmv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
11834 {"mv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
11835 {"marmv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
11836 {"mv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
11837 {"marmv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
11838 {"mv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
11839 {"marmv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
11840 {"mv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
11841 {"marmv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
11842 {"mv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
11843 {"marmv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
11844 {"mv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
11845 {"marmv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
11846 {"mv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
11847 {"marmv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
11849 /* Floating point variants -- don't add any more to this list either. */
11850 {"mfpe-old", NULL
, &legacy_fpu
, FPU_ARCH_FPE
, N_("use -mfpu=fpe")},
11851 {"mfpa10", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa10")},
11852 {"mfpa11", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa11")},
11853 {"mno-fpu", NULL
, &legacy_fpu
, 0,
11854 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
11856 {NULL
, NULL
, NULL
, 0, NULL
}
11859 struct arm_cpu_option_table
11863 /* For some CPUs we assume an FPU unless the user explicitly sets
11868 /* This list should, at a minimum, contain all the cpu names
11869 recognized by GCC. */
11870 static struct arm_cpu_option_table arm_cpus
[] =
11872 {"all", ARM_ANY
, FPU_ARCH_FPA
},
11873 {"arm1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
11874 {"arm2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
11875 {"arm250", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
11876 {"arm3", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
11877 {"arm6", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11878 {"arm60", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11879 {"arm600", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11880 {"arm610", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11881 {"arm620", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11882 {"arm7", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11883 {"arm7m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
11884 {"arm7d", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11885 {"arm7dm", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
11886 {"arm7di", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11887 {"arm7dmi", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
11888 {"arm70", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11889 {"arm700", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11890 {"arm700i", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11891 {"arm710", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11892 {"arm710t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
11893 {"arm720", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11894 {"arm720t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
11895 {"arm740t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
11896 {"arm710c", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11897 {"arm7100", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11898 {"arm7500", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11899 {"arm7500fe", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11900 {"arm7t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
11901 {"arm7tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
11902 {"arm8", ARM_ARCH_V4
, FPU_ARCH_FPA
},
11903 {"arm810", ARM_ARCH_V4
, FPU_ARCH_FPA
},
11904 {"strongarm", ARM_ARCH_V4
, FPU_ARCH_FPA
},
11905 {"strongarm1", ARM_ARCH_V4
, FPU_ARCH_FPA
},
11906 {"strongarm110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
11907 {"strongarm1100", ARM_ARCH_V4
, FPU_ARCH_FPA
},
11908 {"strongarm1110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
11909 {"arm9", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
11910 {"arm920", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
11911 {"arm920t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
11912 {"arm922t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
11913 {"arm940t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
11914 {"arm9tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
11915 /* For V5 or later processors we default to using VFP; but the user
11916 should really set the FPU type explicitly. */
11917 {"arm9e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
11918 {"arm9e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
11919 {"arm926ej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
11920 {"arm946e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
11921 {"arm946e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
11922 {"arm966e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
11923 {"arm966e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
11924 {"arm10t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
11925 {"arm10e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
11926 {"arm1020", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
11927 {"arm1020t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
11928 {"arm1020e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
11929 /* ??? XSCALE is really an architecture. */
11930 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
11931 /* ??? iwmmxt is not a processor. */
11932 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP_V2
},
11933 {"i80200", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
11935 {"ep9312", ARM_ARCH_V4T
| ARM_CEXT_MAVERICK
, FPU_NONE
},
11939 struct arm_arch_option_table
11946 /* This list should, at a minimum, contain all the architecture names
11947 recognized by GCC. */
11948 static struct arm_arch_option_table arm_archs
[] =
11950 {"all", ARM_ANY
, FPU_ARCH_FPA
},
11951 {"armv1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
11952 {"armv2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
11953 {"armv2a", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
11954 {"armv2s", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
11955 {"armv3", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11956 {"armv3m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
11957 {"armv4", ARM_ARCH_V4
, FPU_ARCH_FPA
},
11958 {"armv4xm", ARM_ARCH_V4xM
, FPU_ARCH_FPA
},
11959 {"armv4t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
11960 {"armv4txm", ARM_ARCH_V4TxM
, FPU_ARCH_FPA
},
11961 {"armv5", ARM_ARCH_V5
, FPU_ARCH_VFP
},
11962 {"armv5t", ARM_ARCH_V5T
, FPU_ARCH_VFP
},
11963 {"armv5txm", ARM_ARCH_V5TxM
, FPU_ARCH_VFP
},
11964 {"armv5te", ARM_ARCH_V5TE
, FPU_ARCH_VFP
},
11965 {"armv5texp", ARM_ARCH_V5TExP
, FPU_ARCH_VFP
},
11966 {"armv5tej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP
},
11967 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP
},
11968 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP
},
11972 /* ISA extensions in the co-processor space. */
11973 struct arm_arch_extension_table
11979 static struct arm_arch_extension_table arm_extensions
[] =
11981 {"maverick", ARM_CEXT_MAVERICK
},
11982 {"xscale", ARM_CEXT_XSCALE
},
11983 {"iwmmxt", ARM_CEXT_IWMMXT
},
11987 struct arm_fpu_option_table
11993 /* This list should, at a minimum, contain all the fpu names
11994 recognized by GCC. */
11995 static struct arm_fpu_option_table arm_fpus
[] =
11997 {"softfpa", FPU_NONE
},
11998 {"fpe", FPU_ARCH_FPE
},
11999 {"fpe2", FPU_ARCH_FPE
},
12000 {"fpe3", FPU_ARCH_FPA
}, /* Third release supports LFM/SFM. */
12001 {"fpa", FPU_ARCH_FPA
},
12002 {"fpa10", FPU_ARCH_FPA
},
12003 {"fpa11", FPU_ARCH_FPA
},
12004 {"arm7500fe", FPU_ARCH_FPA
},
12005 {"softvfp", FPU_ARCH_VFP
},
12006 {"softvfp+vfp", FPU_ARCH_VFP_V2
},
12007 {"vfp", FPU_ARCH_VFP_V2
},
12008 {"vfp9", FPU_ARCH_VFP_V2
},
12009 {"vfp10", FPU_ARCH_VFP_V2
},
12010 {"vfp10-r0", FPU_ARCH_VFP_V1
},
12011 {"vfpxd", FPU_ARCH_VFP_V1xD
},
12012 {"arm1020t", FPU_ARCH_VFP_V1
},
12013 {"arm1020e", FPU_ARCH_VFP_V2
},
12017 struct arm_long_option_table
12019 char *option
; /* Substring to match. */
12020 char *help
; /* Help information. */
12021 int (*func
) PARAMS ((char *subopt
)); /* Function to decode sub-option. */
12022 char *deprecated
; /* If non-null, print this message. */
12026 arm_parse_extension (str
, opt_p
)
12030 while (str
!= NULL
&& *str
!= 0)
12032 struct arm_arch_extension_table
*opt
;
12038 as_bad (_("invalid architectural extension"));
12043 ext
= strchr (str
, '+');
12046 optlen
= ext
- str
;
12048 optlen
= strlen (str
);
12052 as_bad (_("missing architectural extension"));
12056 for (opt
= arm_extensions
; opt
->name
!= NULL
; opt
++)
12057 if (strncmp (opt
->name
, str
, optlen
) == 0)
12059 *opt_p
|= opt
->value
;
12063 if (opt
->name
== NULL
)
12065 as_bad (_("unknown architectural extnsion `%s'"), str
);
12076 arm_parse_cpu (str
)
12079 struct arm_cpu_option_table
*opt
;
12080 char *ext
= strchr (str
, '+');
12084 optlen
= ext
- str
;
12086 optlen
= strlen (str
);
12090 as_bad (_("missing cpu name `%s'"), str
);
12094 for (opt
= arm_cpus
; opt
->name
!= NULL
; opt
++)
12095 if (strncmp (opt
->name
, str
, optlen
) == 0)
12097 mcpu_cpu_opt
= opt
->value
;
12098 mcpu_fpu_opt
= opt
->default_fpu
;
12101 return arm_parse_extension (ext
, &mcpu_cpu_opt
);
12106 as_bad (_("unknown cpu `%s'"), str
);
12111 arm_parse_arch (str
)
12114 struct arm_arch_option_table
*opt
;
12115 char *ext
= strchr (str
, '+');
12119 optlen
= ext
- str
;
12121 optlen
= strlen (str
);
12125 as_bad (_("missing architecture name `%s'"), str
);
12130 for (opt
= arm_archs
; opt
->name
!= NULL
; opt
++)
12131 if (strcmp (opt
->name
, str
) == 0)
12133 march_cpu_opt
= opt
->value
;
12134 march_fpu_opt
= opt
->default_fpu
;
12137 return arm_parse_extension (ext
, &march_cpu_opt
);
12142 as_bad (_("unknown architecture `%s'\n"), str
);
12147 arm_parse_fpu (str
)
12150 struct arm_fpu_option_table
*opt
;
12152 for (opt
= arm_fpus
; opt
->name
!= NULL
; opt
++)
12153 if (strcmp (opt
->name
, str
) == 0)
12155 mfpu_opt
= opt
->value
;
12159 as_bad (_("unknown floating point format `%s'\n"), str
);
12163 struct arm_long_option_table arm_long_opts
[] =
12165 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
12166 arm_parse_cpu
, NULL
},
12167 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
12168 arm_parse_arch
, NULL
},
12169 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
12170 arm_parse_fpu
, NULL
},
12171 {NULL
, NULL
, 0, NULL
}
12175 md_parse_option (c
, arg
)
12179 struct arm_option_table
*opt
;
12180 struct arm_long_option_table
*lopt
;
12186 target_big_endian
= 1;
12192 target_big_endian
= 0;
12197 /* Listing option. Just ignore these, we don't support additional
12202 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
12204 if (c
== opt
->option
[0]
12205 && ((arg
== NULL
&& opt
->option
[1] == 0)
12206 || strcmp (arg
, opt
->option
+ 1) == 0))
12208 #if WARN_DEPRECATED
12209 /* If the option is deprecated, tell the user. */
12210 if (opt
->deprecated
!= NULL
)
12211 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
,
12212 arg
? arg
: "", _(opt
->deprecated
));
12215 if (opt
->var
!= NULL
)
12216 *opt
->var
= opt
->value
;
12222 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
12224 /* These options are expected to have an argument. */
12225 if (c
== lopt
->option
[0]
12227 && strncmp (arg
, lopt
->option
+ 1,
12228 strlen (lopt
->option
+ 1)) == 0)
12230 #if WARN_DEPRECATED
12231 /* If the option is deprecated, tell the user. */
12232 if (lopt
->deprecated
!= NULL
)
12233 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
, arg
,
12234 _(lopt
->deprecated
));
12237 /* Call the sup-option parser. */
12238 return (*lopt
->func
)(arg
+ strlen (lopt
->option
) - 1);
12242 as_bad (_("unrecognized option `-%c%s'"), c
, arg
? arg
: "");
12253 struct arm_option_table
*opt
;
12254 struct arm_long_option_table
*lopt
;
12256 fprintf (fp
, _(" ARM-specific assembler options:\n"));
12258 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
12259 if (opt
->help
!= NULL
)
12260 fprintf (fp
, " -%-23s%s\n", opt
->option
, _(opt
->help
));
12262 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
12263 if (lopt
->help
!= NULL
)
12264 fprintf (fp
, " -%s%s\n", lopt
->option
, _(lopt
->help
));
12268 -EB assemble code for a big-endian cpu\n"));
12273 -EL assemble code for a little-endian cpu\n"));
12277 /* We need to be able to fix up arbitrary expressions in some statements.
12278 This is so that we can handle symbols that are an arbitrary distance from
12279 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
12280 which returns part of an address in a form which will be valid for
12281 a data instruction. We do this by pushing the expression into a symbol
12282 in the expr_section, and creating a fix for that. */
12285 fix_new_arm (frag
, where
, size
, exp
, pc_rel
, reloc
)
12294 arm_fix_data
* arm_data
;
12302 new_fix
= fix_new_exp (frag
, where
, size
, exp
, pc_rel
, reloc
);
12306 new_fix
= fix_new (frag
, where
, size
, make_expr_symbol (exp
), 0,
12311 /* Mark whether the fix is to a THUMB instruction, or an ARM
12313 arm_data
= (arm_fix_data
*) obstack_alloc (& notes
, sizeof (arm_fix_data
));
12314 new_fix
->tc_fix_data
= (PTR
) arm_data
;
12315 arm_data
->thumb_mode
= thumb_mode
;
12320 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
12323 cons_fix_new_arm (frag
, where
, size
, exp
)
12329 bfd_reloc_code_real_type type
;
12333 FIXME: @@ Should look at CPU word size. */
12337 type
= BFD_RELOC_8
;
12340 type
= BFD_RELOC_16
;
12344 type
= BFD_RELOC_32
;
12347 type
= BFD_RELOC_64
;
12351 fix_new_exp (frag
, where
, (int) size
, exp
, pcrel
, type
);
12354 /* A good place to do this, although this was probably not intended
12355 for this kind of use. We need to dump the literal pool before
12356 references are made to a null symbol pointer. */
12361 literal_pool
* pool
;
12363 for (pool
= list_of_pools
; pool
; pool
= pool
->next
)
12365 /* Put it at the end of the relevent section. */
12366 subseg_set (pool
->section
, pool
->sub_section
);
12372 arm_start_line_hook ()
12374 last_label_seen
= NULL
;
12378 arm_frob_label (sym
)
12381 last_label_seen
= sym
;
12383 ARM_SET_THUMB (sym
, thumb_mode
);
12385 #if defined OBJ_COFF || defined OBJ_ELF
12386 ARM_SET_INTERWORK (sym
, support_interwork
);
12389 /* Note - do not allow local symbols (.Lxxx) to be labeled
12390 as Thumb functions. This is because these labels, whilst
12391 they exist inside Thumb code, are not the entry points for
12392 possible ARM->Thumb calls. Also, these labels can be used
12393 as part of a computed goto or switch statement. eg gcc
12394 can generate code that looks like this:
12396 ldr r2, [pc, .Laaa]
12406 The first instruction loads the address of the jump table.
12407 The second instruction converts a table index into a byte offset.
12408 The third instruction gets the jump address out of the table.
12409 The fourth instruction performs the jump.
12411 If the address stored at .Laaa is that of a symbol which has the
12412 Thumb_Func bit set, then the linker will arrange for this address
12413 to have the bottom bit set, which in turn would mean that the
12414 address computation performed by the third instruction would end
12415 up with the bottom bit set. Since the ARM is capable of unaligned
12416 word loads, the instruction would then load the incorrect address
12417 out of the jump table, and chaos would ensue. */
12418 if (label_is_thumb_function_name
12419 && (S_GET_NAME (sym
)[0] != '.' || S_GET_NAME (sym
)[1] != 'L')
12420 && (bfd_get_section_flags (stdoutput
, now_seg
) & SEC_CODE
) != 0)
12422 /* When the address of a Thumb function is taken the bottom
12423 bit of that address should be set. This will allow
12424 interworking between Arm and Thumb functions to work
12427 THUMB_SET_FUNC (sym
, 1);
12429 label_is_thumb_function_name
= FALSE
;
12433 /* Adjust the symbol table. This marks Thumb symbols as distinct from
12437 arm_adjust_symtab ()
12442 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
12444 if (ARM_IS_THUMB (sym
))
12446 if (THUMB_IS_FUNC (sym
))
12448 /* Mark the symbol as a Thumb function. */
12449 if ( S_GET_STORAGE_CLASS (sym
) == C_STAT
12450 || S_GET_STORAGE_CLASS (sym
) == C_LABEL
) /* This can happen! */
12451 S_SET_STORAGE_CLASS (sym
, C_THUMBSTATFUNC
);
12453 else if (S_GET_STORAGE_CLASS (sym
) == C_EXT
)
12454 S_SET_STORAGE_CLASS (sym
, C_THUMBEXTFUNC
);
12456 as_bad (_("%s: unexpected function type: %d"),
12457 S_GET_NAME (sym
), S_GET_STORAGE_CLASS (sym
));
12459 else switch (S_GET_STORAGE_CLASS (sym
))
12462 S_SET_STORAGE_CLASS (sym
, C_THUMBEXT
);
12465 S_SET_STORAGE_CLASS (sym
, C_THUMBSTAT
);
12468 S_SET_STORAGE_CLASS (sym
, C_THUMBLABEL
);
12476 if (ARM_IS_INTERWORK (sym
))
12477 coffsymbol (symbol_get_bfdsym (sym
))->native
->u
.syment
.n_flags
= 0xFF;
12484 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
12486 if (ARM_IS_THUMB (sym
))
12488 elf_symbol_type
* elf_sym
;
12490 elf_sym
= elf_symbol (symbol_get_bfdsym (sym
));
12491 bind
= ELF_ST_BIND (elf_sym
);
12493 /* If it's a .thumb_func, declare it as so,
12494 otherwise tag label as .code 16. */
12495 if (THUMB_IS_FUNC (sym
))
12496 elf_sym
->internal_elf_sym
.st_info
=
12497 ELF_ST_INFO (bind
, STT_ARM_TFUNC
);
12499 elf_sym
->internal_elf_sym
.st_info
=
12500 ELF_ST_INFO (bind
, STT_ARM_16BIT
);
12507 arm_data_in_code ()
12509 if (thumb_mode
&& ! strncmp (input_line_pointer
+ 1, "data:", 5))
12511 *input_line_pointer
= '/';
12512 input_line_pointer
+= 5;
12513 *input_line_pointer
= 0;
12521 arm_canonicalize_symbol_name (name
)
12526 if (thumb_mode
&& (len
= strlen (name
)) > 5
12527 && streq (name
+ len
- 5, "/data"))
12528 *(name
+ len
- 5) = 0;
12533 #if defined OBJ_COFF || defined OBJ_ELF
12535 arm_validate_fix (fixP
)
12538 /* If the destination of the branch is a defined symbol which does not have
12539 the THUMB_FUNC attribute, then we must be calling a function which has
12540 the (interfacearm) attribute. We look for the Thumb entry point to that
12541 function and change the branch to refer to that function instead. */
12542 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
12543 && fixP
->fx_addsy
!= NULL
12544 && S_IS_DEFINED (fixP
->fx_addsy
)
12545 && ! THUMB_IS_FUNC (fixP
->fx_addsy
))
12547 fixP
->fx_addsy
= find_real_start (fixP
->fx_addsy
);
12553 arm_force_relocation (fixp
)
12556 #if defined (OBJ_COFF) && defined (TE_PE)
12557 if (fixp
->fx_r_type
== BFD_RELOC_RVA
)
12561 if (fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
12562 || fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
12563 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
12564 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
)
12568 /* Resolve these relocations even if the symbol is extern or weak. */
12569 if (fixp
->fx_r_type
== BFD_RELOC_ARM_IMMEDIATE
12570 || fixp
->fx_r_type
== BFD_RELOC_ARM_OFFSET_IMM
12571 || fixp
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
12574 return generic_force_reloc (fixp
);
12578 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
12579 local labels from being added to the output symbol table when they
12580 are used with the ADRL pseudo op. The ADRL relocation should always
12581 be resolved before the binbary is emitted, so it is safe to say that
12582 it is adjustable. */
12585 arm_fix_adjustable (fixP
)
12588 if (fixP
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
12595 /* Relocations against Thumb function names must be left unadjusted,
12596 so that the linker can use this information to correctly set the
12597 bottom bit of their addresses. The MIPS version of this function
12598 also prevents relocations that are mips-16 specific, but I do not
12599 know why it does this.
12602 There is one other problem that ought to be addressed here, but
12603 which currently is not: Taking the address of a label (rather
12604 than a function) and then later jumping to that address. Such
12605 addresses also ought to have their bottom bit set (assuming that
12606 they reside in Thumb code), but at the moment they will not. */
12609 arm_fix_adjustable (fixP
)
12612 if (fixP
->fx_addsy
== NULL
)
12615 if (THUMB_IS_FUNC (fixP
->fx_addsy
)
12616 && fixP
->fx_subsy
== NULL
)
12619 /* We need the symbol name for the VTABLE entries. */
12620 if ( fixP
->fx_r_type
== BFD_RELOC_VTABLE_INHERIT
12621 || fixP
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
12624 /* Don't allow symbols to be discarded on GOT related relocs. */
12625 if (fixP
->fx_r_type
== BFD_RELOC_ARM_PLT32
12626 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOT32
12627 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOTOFF
)
12634 elf32_arm_target_format ()
12636 if (target_big_endian
)
12639 return "elf32-bigarm-oabi";
12641 return "elf32-bigarm";
12646 return "elf32-littlearm-oabi";
12648 return "elf32-littlearm";
12653 armelf_frob_symbol (symp
, puntp
)
12657 elf_frob_symbol (symp
, puntp
);
12660 static bfd_reloc_code_real_type
12670 bfd_reloc_code_real_type reloc
;
12674 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
12675 MAP ("(got)", BFD_RELOC_ARM_GOT32
),
12676 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF
),
12677 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
12678 branch instructions generated by GCC for PLT relocs. */
12679 MAP ("(plt)", BFD_RELOC_ARM_PLT32
),
12680 { NULL
, 0, BFD_RELOC_UNUSED
}
12684 for (i
= 0, ip
= input_line_pointer
;
12685 i
< sizeof (id
) && (ISALNUM (*ip
) || ISPUNCT (*ip
));
12687 id
[i
] = TOLOWER (*ip
);
12689 for (i
= 0; reloc_map
[i
].str
; i
++)
12690 if (strncmp (id
, reloc_map
[i
].str
, reloc_map
[i
].len
) == 0)
12693 input_line_pointer
+= reloc_map
[i
].len
;
12695 return reloc_map
[i
].reloc
;
12699 s_arm_elf_cons (nbytes
)
12704 #ifdef md_flush_pending_output
12705 md_flush_pending_output ();
12708 if (is_it_end_of_statement ())
12710 demand_empty_rest_of_line ();
12714 #ifdef md_cons_align
12715 md_cons_align (nbytes
);
12720 bfd_reloc_code_real_type reloc
;
12722 expression (& exp
);
12724 if (exp
.X_op
== O_symbol
12725 && * input_line_pointer
== '('
12726 && (reloc
= arm_parse_reloc ()) != BFD_RELOC_UNUSED
)
12728 reloc_howto_type
*howto
= bfd_reloc_type_lookup (stdoutput
, reloc
);
12729 int size
= bfd_get_reloc_size (howto
);
12732 as_bad ("%s relocations do not fit in %d bytes",
12733 howto
->name
, nbytes
);
12736 register char *p
= frag_more ((int) nbytes
);
12737 int offset
= nbytes
- size
;
12739 fix_new_exp (frag_now
, p
- frag_now
->fr_literal
+ offset
, size
,
12744 emit_expr (&exp
, (unsigned int) nbytes
);
12746 while (*input_line_pointer
++ == ',');
12748 /* Put terminator back into stream. */
12749 input_line_pointer
--;
12750 demand_empty_rest_of_line ();
12753 #endif /* OBJ_ELF */
12755 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
12756 of an rs_align_code fragment. */
12759 arm_handle_align (fragP
)
12762 static char const arm_noop
[4] = { 0x00, 0x00, 0xa0, 0xe1 };
12763 static char const thumb_noop
[2] = { 0xc0, 0x46 };
12764 static char const arm_bigend_noop
[4] = { 0xe1, 0xa0, 0x00, 0x00 };
12765 static char const thumb_bigend_noop
[2] = { 0x46, 0xc0 };
12767 int bytes
, fix
, noop_size
;
12771 if (fragP
->fr_type
!= rs_align_code
)
12774 bytes
= fragP
->fr_next
->fr_address
- fragP
->fr_address
- fragP
->fr_fix
;
12775 p
= fragP
->fr_literal
+ fragP
->fr_fix
;
12778 if (bytes
> MAX_MEM_FOR_RS_ALIGN_CODE
)
12779 bytes
&= MAX_MEM_FOR_RS_ALIGN_CODE
;
12781 if (fragP
->tc_frag_data
)
12783 if (target_big_endian
)
12784 noop
= thumb_bigend_noop
;
12787 noop_size
= sizeof (thumb_noop
);
12791 if (target_big_endian
)
12792 noop
= arm_bigend_noop
;
12795 noop_size
= sizeof (arm_noop
);
12798 if (bytes
& (noop_size
- 1))
12800 fix
= bytes
& (noop_size
- 1);
12801 memset (p
, 0, fix
);
12806 while (bytes
>= noop_size
)
12808 memcpy (p
, noop
, noop_size
);
12810 bytes
-= noop_size
;
12814 fragP
->fr_fix
+= fix
;
12815 fragP
->fr_var
= noop_size
;
12818 /* Called from md_do_align. Used to create an alignment
12819 frag in a code section. */
12822 arm_frag_align_code (n
, max
)
12828 /* We assume that there will never be a requirment
12829 to support alignments greater than 32 bytes. */
12830 if (max
> MAX_MEM_FOR_RS_ALIGN_CODE
)
12831 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
12833 p
= frag_var (rs_align_code
,
12834 MAX_MEM_FOR_RS_ALIGN_CODE
,
12836 (relax_substateT
) max
,
12844 /* Perform target specific initialisation of a frag. */
12847 arm_init_frag (fragP
)
12850 /* Record whether this frag is in an ARM or a THUMB area. */
12851 fragP
->tc_frag_data
= thumb_mode
;