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. */
58 #define ARM_EXT_V6 0x00001000 /* ARM V6. */
60 /* Co-processor space extensions. */
61 #define ARM_CEXT_XSCALE 0x00800000 /* Allow MIA etc. */
62 #define ARM_CEXT_MAVERICK 0x00400000 /* Use Cirrus/DSP coprocessor. */
63 #define ARM_CEXT_IWMMXT 0x00200000 /* Intel Wireless MMX technology coprocessor. */
65 /* Architectures are the sum of the base and extensions. The ARM ARM (rev E)
66 defines the following: ARMv3, ARMv3M, ARMv4xM, ARMv4, ARMv4TxM, ARMv4T,
67 ARMv5xM, ARMv5, ARMv5TxM, ARMv5T, ARMv5TExP, ARMv5TE. To these we add
68 three more to cover cores prior to ARM6. Finally, there are cores which
69 implement further extensions in the co-processor space. */
70 #define ARM_ARCH_V1 ARM_EXT_V1
71 #define ARM_ARCH_V2 (ARM_ARCH_V1 | ARM_EXT_V2)
72 #define ARM_ARCH_V2S (ARM_ARCH_V2 | ARM_EXT_V2S)
73 #define ARM_ARCH_V3 (ARM_ARCH_V2S | ARM_EXT_V3)
74 #define ARM_ARCH_V3M (ARM_ARCH_V3 | ARM_EXT_V3M)
75 #define ARM_ARCH_V4xM (ARM_ARCH_V3 | ARM_EXT_V4)
76 #define ARM_ARCH_V4 (ARM_ARCH_V3M | ARM_EXT_V4)
77 #define ARM_ARCH_V4TxM (ARM_ARCH_V4xM | ARM_EXT_V4T)
78 #define ARM_ARCH_V4T (ARM_ARCH_V4 | ARM_EXT_V4T)
79 #define ARM_ARCH_V5xM (ARM_ARCH_V4xM | ARM_EXT_V5)
80 #define ARM_ARCH_V5 (ARM_ARCH_V4 | ARM_EXT_V5)
81 #define ARM_ARCH_V5TxM (ARM_ARCH_V5xM | ARM_EXT_V4T | ARM_EXT_V5T)
82 #define ARM_ARCH_V5T (ARM_ARCH_V5 | ARM_EXT_V4T | ARM_EXT_V5T)
83 #define ARM_ARCH_V5TExP (ARM_ARCH_V5T | ARM_EXT_V5ExP)
84 #define ARM_ARCH_V5TE (ARM_ARCH_V5TExP | ARM_EXT_V5E)
85 #define ARM_ARCH_V5TEJ (ARM_ARCH_V5TE | ARM_EXT_V5J)
86 #define ARM_ARCH_V6 (ARM_ARCH_V5TEJ | ARM_EXT_V6)
88 /* Processors with specific extensions in the co-processor space. */
89 #define ARM_ARCH_XSCALE (ARM_ARCH_V5TE | ARM_CEXT_XSCALE)
90 #define ARM_ARCH_IWMMXT (ARM_ARCH_XSCALE | ARM_CEXT_IWMMXT)
92 /* Some useful combinations: */
93 #define ARM_ANY 0x0000ffff /* Any basic core. */
94 #define ARM_ALL 0x00ffffff /* Any core + co-processor */
95 #define CPROC_ANY 0x00ff0000 /* Any co-processor */
96 #define FPU_ANY 0xff000000 /* Note this is ~ARM_ALL. */
99 #define FPU_FPA_EXT_V1 0x80000000 /* Base FPA instruction set. */
100 #define FPU_FPA_EXT_V2 0x40000000 /* LFM/SFM. */
101 #define FPU_VFP_EXT_NONE 0x20000000 /* Use VFP word-ordering. */
102 #define FPU_VFP_EXT_V1xD 0x10000000 /* Base VFP instruction set. */
103 #define FPU_VFP_EXT_V1 0x08000000 /* Double-precision insns. */
104 #define FPU_VFP_EXT_V2 0x04000000 /* ARM10E VFPr1. */
107 #define FPU_ARCH_FPE FPU_FPA_EXT_V1
108 #define FPU_ARCH_FPA (FPU_ARCH_FPE | FPU_FPA_EXT_V2)
110 #define FPU_ARCH_VFP FPU_VFP_EXT_NONE
111 #define FPU_ARCH_VFP_V1xD (FPU_VFP_EXT_V1xD | FPU_VFP_EXT_NONE)
112 #define FPU_ARCH_VFP_V1 (FPU_ARCH_VFP_V1xD | FPU_VFP_EXT_V1)
113 #define FPU_ARCH_VFP_V2 (FPU_ARCH_VFP_V1 | FPU_VFP_EXT_V2)
115 /* Types of processor to assemble for. */
116 #define ARM_1 ARM_ARCH_V1
117 #define ARM_2 ARM_ARCH_V2
118 #define ARM_3 ARM_ARCH_V2S
119 #define ARM_250 ARM_ARCH_V2S
120 #define ARM_6 ARM_ARCH_V3
121 #define ARM_7 ARM_ARCH_V3
122 #define ARM_8 ARM_ARCH_V4
123 #define ARM_9 ARM_ARCH_V4T
124 #define ARM_STRONG ARM_ARCH_V4
125 #define ARM_CPU_MASK 0x0000000f /* XXX? */
128 #if defined __XSCALE__
129 #define CPU_DEFAULT (ARM_ARCH_XSCALE)
131 #if defined __thumb__
132 #define CPU_DEFAULT (ARM_ARCH_V5T)
134 #define CPU_DEFAULT ARM_ANY
140 #define FPU_DEFAULT FPU_ARCH_FPA
145 #define FPU_DEFAULT FPU_ARCH_VFP /* Soft-float, but VFP order. */
147 /* Legacy a.out format. */
148 #define FPU_DEFAULT FPU_ARCH_FPA /* Soft-float, but FPA order. */
152 /* For backwards compatibility we default to the FPA. */
154 #define FPU_DEFAULT FPU_ARCH_FPA
157 #define streq(a, b) (strcmp (a, b) == 0)
158 #define skip_whitespace(str) while (*(str) == ' ') ++(str)
160 static unsigned long cpu_variant
;
161 static int target_oabi
= 0;
163 /* Flags stored in private area of BFD structure. */
164 static int uses_apcs_26
= FALSE
;
165 static int atpcs
= FALSE
;
166 static int support_interwork
= FALSE
;
167 static int uses_apcs_float
= FALSE
;
168 static int pic_code
= FALSE
;
170 /* Variables that we set while parsing command-line options. Once all
171 options have been read we re-process these values to set the real
173 static int legacy_cpu
= -1;
174 static int legacy_fpu
= -1;
176 static int mcpu_cpu_opt
= -1;
177 static int mcpu_fpu_opt
= -1;
178 static int march_cpu_opt
= -1;
179 static int march_fpu_opt
= -1;
180 static int mfpu_opt
= -1;
182 /* This array holds the chars that always start a comment. If the
183 pre-processor is disabled, these aren't very useful. */
184 const char comment_chars
[] = "@";
186 /* This array holds the chars that only start a comment at the beginning of
187 a line. If the line seems to have the form '# 123 filename'
188 .line and .file directives will appear in the pre-processed output. */
189 /* Note that input_file.c hand checks for '#' at the beginning of the
190 first line of the input file. This is because the compiler outputs
191 #NO_APP at the beginning of its output. */
192 /* Also note that comments like this one will always work. */
193 const char line_comment_chars
[] = "#";
195 const char line_separator_chars
[] = ";";
197 /* Chars that can be used to separate mant
198 from exp in floating point numbers. */
199 const char EXP_CHARS
[] = "eE";
201 /* Chars that mean this number is a floating point constant. */
205 const char FLT_CHARS
[] = "rRsSfFdDxXeEpP";
207 /* Prefix characters that indicate the start of an immediate
209 #define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
212 /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
213 symbolS
* GOT_symbol
;
216 /* Size of relocation record. */
217 const int md_reloc_size
= 8;
219 /* 0: assemble for ARM,
220 1: assemble for Thumb,
221 2: assemble for Thumb even though target CPU does not support thumb
223 static int thumb_mode
= 0;
225 typedef struct arm_fix
233 unsigned long instruction
;
237 bfd_reloc_code_real_type type
;
254 struct asm_shift_properties
256 enum asm_shift_index index
;
257 unsigned long bit_field
;
258 unsigned int allows_0
: 1;
259 unsigned int allows_32
: 1;
262 static const struct asm_shift_properties shift_properties
[] =
264 { SHIFT_LSL
, 0, 1, 0},
265 { SHIFT_LSR
, 0x20, 0, 1},
266 { SHIFT_ASR
, 0x40, 0, 1},
267 { SHIFT_ROR
, 0x60, 0, 0},
268 { SHIFT_RRX
, 0x60, 0, 0}
271 struct asm_shift_name
274 const struct asm_shift_properties
* properties
;
277 static const struct asm_shift_name shift_names
[] =
279 { "asl", shift_properties
+ SHIFT_LSL
},
280 { "lsl", shift_properties
+ SHIFT_LSL
},
281 { "lsr", shift_properties
+ SHIFT_LSR
},
282 { "asr", shift_properties
+ SHIFT_ASR
},
283 { "ror", shift_properties
+ SHIFT_ROR
},
284 { "rrx", shift_properties
+ SHIFT_RRX
},
285 { "ASL", shift_properties
+ SHIFT_LSL
},
286 { "LSL", shift_properties
+ SHIFT_LSL
},
287 { "LSR", shift_properties
+ SHIFT_LSR
},
288 { "ASR", shift_properties
+ SHIFT_ASR
},
289 { "ROR", shift_properties
+ SHIFT_ROR
},
290 { "RRX", shift_properties
+ SHIFT_RRX
}
293 /* Any kind of shift is accepted. */
294 #define NO_SHIFT_RESTRICT 1
295 /* The shift operand must be an immediate value, not a register. */
296 #define SHIFT_IMMEDIATE 0
297 /* The shift must be LSL or ASR and the operand must be an immediate. */
298 #define SHIFT_LSL_OR_ASR_IMMEDIATE 2
299 /* The shift must be ASR and the operand must be an immediate. */
300 #define SHIFT_ASR_IMMEDIATE 3
301 /* The shift must be LSL and the operand must be an immediate. */
302 #define SHIFT_LSL_IMMEDIATE 4
304 #define NUM_FLOAT_VALS 8
306 const char * fp_const
[] =
308 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
311 /* Number of littlenums required to hold an extended precision number. */
312 #define MAX_LITTLENUMS 6
314 LITTLENUM_TYPE fp_values
[NUM_FLOAT_VALS
][MAX_LITTLENUMS
];
319 /* Whether a Co-processor load/store operation accepts write-back forms. */
328 #define CP_T_X 0x00008000
329 #define CP_T_Y 0x00400000
330 #define CP_T_Pre 0x01000000
331 #define CP_T_UD 0x00800000
332 #define CP_T_WB 0x00200000
334 #define CONDS_BIT 0x00100000
335 #define LOAD_BIT 0x00100000
337 #define DOUBLE_LOAD_FLAG 0x00000001
341 const char * template;
345 #define COND_ALWAYS 0xe0000000
346 #define COND_MASK 0xf0000000
348 static const struct asm_cond conds
[] =
352 {"cs", 0x20000000}, {"hs", 0x20000000},
353 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
370 const char *template;
375 /* The bit that distinguishes CPSR and SPSR. */
376 #define SPSR_BIT (1 << 22)
378 /* How many bits to shift the PSR_xxx bits up by. */
381 #define PSR_c (1 << 0)
382 #define PSR_x (1 << 1)
383 #define PSR_s (1 << 2)
384 #define PSR_f (1 << 3)
386 static const struct asm_psr psrs
[] =
388 {"CPSR", TRUE
, PSR_c
| PSR_f
},
389 {"CPSR_all", TRUE
, PSR_c
| PSR_f
},
390 {"SPSR", FALSE
, PSR_c
| PSR_f
},
391 {"SPSR_all", FALSE
, PSR_c
| PSR_f
},
392 {"CPSR_flg", TRUE
, PSR_f
},
393 {"CPSR_f", TRUE
, PSR_f
},
394 {"SPSR_flg", FALSE
, PSR_f
},
395 {"SPSR_f", FALSE
, PSR_f
},
396 {"CPSR_c", TRUE
, PSR_c
},
397 {"CPSR_ctl", TRUE
, PSR_c
},
398 {"SPSR_c", FALSE
, PSR_c
},
399 {"SPSR_ctl", FALSE
, PSR_c
},
400 {"CPSR_x", TRUE
, PSR_x
},
401 {"CPSR_s", TRUE
, PSR_s
},
402 {"SPSR_x", FALSE
, PSR_x
},
403 {"SPSR_s", FALSE
, PSR_s
},
404 /* Combinations of flags. */
405 {"CPSR_fs", TRUE
, PSR_f
| PSR_s
},
406 {"CPSR_fx", TRUE
, PSR_f
| PSR_x
},
407 {"CPSR_fc", TRUE
, PSR_f
| PSR_c
},
408 {"CPSR_sf", TRUE
, PSR_s
| PSR_f
},
409 {"CPSR_sx", TRUE
, PSR_s
| PSR_x
},
410 {"CPSR_sc", TRUE
, PSR_s
| PSR_c
},
411 {"CPSR_xf", TRUE
, PSR_x
| PSR_f
},
412 {"CPSR_xs", TRUE
, PSR_x
| PSR_s
},
413 {"CPSR_xc", TRUE
, PSR_x
| PSR_c
},
414 {"CPSR_cf", TRUE
, PSR_c
| PSR_f
},
415 {"CPSR_cs", TRUE
, PSR_c
| PSR_s
},
416 {"CPSR_cx", TRUE
, PSR_c
| PSR_x
},
417 {"CPSR_fsx", TRUE
, PSR_f
| PSR_s
| PSR_x
},
418 {"CPSR_fsc", TRUE
, PSR_f
| PSR_s
| PSR_c
},
419 {"CPSR_fxs", TRUE
, PSR_f
| PSR_x
| PSR_s
},
420 {"CPSR_fxc", TRUE
, PSR_f
| PSR_x
| PSR_c
},
421 {"CPSR_fcs", TRUE
, PSR_f
| PSR_c
| PSR_s
},
422 {"CPSR_fcx", TRUE
, PSR_f
| PSR_c
| PSR_x
},
423 {"CPSR_sfx", TRUE
, PSR_s
| PSR_f
| PSR_x
},
424 {"CPSR_sfc", TRUE
, PSR_s
| PSR_f
| PSR_c
},
425 {"CPSR_sxf", TRUE
, PSR_s
| PSR_x
| PSR_f
},
426 {"CPSR_sxc", TRUE
, PSR_s
| PSR_x
| PSR_c
},
427 {"CPSR_scf", TRUE
, PSR_s
| PSR_c
| PSR_f
},
428 {"CPSR_scx", TRUE
, PSR_s
| PSR_c
| PSR_x
},
429 {"CPSR_xfs", TRUE
, PSR_x
| PSR_f
| PSR_s
},
430 {"CPSR_xfc", TRUE
, PSR_x
| PSR_f
| PSR_c
},
431 {"CPSR_xsf", TRUE
, PSR_x
| PSR_s
| PSR_f
},
432 {"CPSR_xsc", TRUE
, PSR_x
| PSR_s
| PSR_c
},
433 {"CPSR_xcf", TRUE
, PSR_x
| PSR_c
| PSR_f
},
434 {"CPSR_xcs", TRUE
, PSR_x
| PSR_c
| PSR_s
},
435 {"CPSR_cfs", TRUE
, PSR_c
| PSR_f
| PSR_s
},
436 {"CPSR_cfx", TRUE
, PSR_c
| PSR_f
| PSR_x
},
437 {"CPSR_csf", TRUE
, PSR_c
| PSR_s
| PSR_f
},
438 {"CPSR_csx", TRUE
, PSR_c
| PSR_s
| PSR_x
},
439 {"CPSR_cxf", TRUE
, PSR_c
| PSR_x
| PSR_f
},
440 {"CPSR_cxs", TRUE
, PSR_c
| PSR_x
| PSR_s
},
441 {"CPSR_fsxc", TRUE
, PSR_f
| PSR_s
| PSR_x
| PSR_c
},
442 {"CPSR_fscx", TRUE
, PSR_f
| PSR_s
| PSR_c
| PSR_x
},
443 {"CPSR_fxsc", TRUE
, PSR_f
| PSR_x
| PSR_s
| PSR_c
},
444 {"CPSR_fxcs", TRUE
, PSR_f
| PSR_x
| PSR_c
| PSR_s
},
445 {"CPSR_fcsx", TRUE
, PSR_f
| PSR_c
| PSR_s
| PSR_x
},
446 {"CPSR_fcxs", TRUE
, PSR_f
| PSR_c
| PSR_x
| PSR_s
},
447 {"CPSR_sfxc", TRUE
, PSR_s
| PSR_f
| PSR_x
| PSR_c
},
448 {"CPSR_sfcx", TRUE
, PSR_s
| PSR_f
| PSR_c
| PSR_x
},
449 {"CPSR_sxfc", TRUE
, PSR_s
| PSR_x
| PSR_f
| PSR_c
},
450 {"CPSR_sxcf", TRUE
, PSR_s
| PSR_x
| PSR_c
| PSR_f
},
451 {"CPSR_scfx", TRUE
, PSR_s
| PSR_c
| PSR_f
| PSR_x
},
452 {"CPSR_scxf", TRUE
, PSR_s
| PSR_c
| PSR_x
| PSR_f
},
453 {"CPSR_xfsc", TRUE
, PSR_x
| PSR_f
| PSR_s
| PSR_c
},
454 {"CPSR_xfcs", TRUE
, PSR_x
| PSR_f
| PSR_c
| PSR_s
},
455 {"CPSR_xsfc", TRUE
, PSR_x
| PSR_s
| PSR_f
| PSR_c
},
456 {"CPSR_xscf", TRUE
, PSR_x
| PSR_s
| PSR_c
| PSR_f
},
457 {"CPSR_xcfs", TRUE
, PSR_x
| PSR_c
| PSR_f
| PSR_s
},
458 {"CPSR_xcsf", TRUE
, PSR_x
| PSR_c
| PSR_s
| PSR_f
},
459 {"CPSR_cfsx", TRUE
, PSR_c
| PSR_f
| PSR_s
| PSR_x
},
460 {"CPSR_cfxs", TRUE
, PSR_c
| PSR_f
| PSR_x
| PSR_s
},
461 {"CPSR_csfx", TRUE
, PSR_c
| PSR_s
| PSR_f
| PSR_x
},
462 {"CPSR_csxf", TRUE
, PSR_c
| PSR_s
| PSR_x
| PSR_f
},
463 {"CPSR_cxfs", TRUE
, PSR_c
| PSR_x
| PSR_f
| PSR_s
},
464 {"CPSR_cxsf", TRUE
, PSR_c
| PSR_x
| PSR_s
| PSR_f
},
465 {"SPSR_fs", FALSE
, PSR_f
| PSR_s
},
466 {"SPSR_fx", FALSE
, PSR_f
| PSR_x
},
467 {"SPSR_fc", FALSE
, PSR_f
| PSR_c
},
468 {"SPSR_sf", FALSE
, PSR_s
| PSR_f
},
469 {"SPSR_sx", FALSE
, PSR_s
| PSR_x
},
470 {"SPSR_sc", FALSE
, PSR_s
| PSR_c
},
471 {"SPSR_xf", FALSE
, PSR_x
| PSR_f
},
472 {"SPSR_xs", FALSE
, PSR_x
| PSR_s
},
473 {"SPSR_xc", FALSE
, PSR_x
| PSR_c
},
474 {"SPSR_cf", FALSE
, PSR_c
| PSR_f
},
475 {"SPSR_cs", FALSE
, PSR_c
| PSR_s
},
476 {"SPSR_cx", FALSE
, PSR_c
| PSR_x
},
477 {"SPSR_fsx", FALSE
, PSR_f
| PSR_s
| PSR_x
},
478 {"SPSR_fsc", FALSE
, PSR_f
| PSR_s
| PSR_c
},
479 {"SPSR_fxs", FALSE
, PSR_f
| PSR_x
| PSR_s
},
480 {"SPSR_fxc", FALSE
, PSR_f
| PSR_x
| PSR_c
},
481 {"SPSR_fcs", FALSE
, PSR_f
| PSR_c
| PSR_s
},
482 {"SPSR_fcx", FALSE
, PSR_f
| PSR_c
| PSR_x
},
483 {"SPSR_sfx", FALSE
, PSR_s
| PSR_f
| PSR_x
},
484 {"SPSR_sfc", FALSE
, PSR_s
| PSR_f
| PSR_c
},
485 {"SPSR_sxf", FALSE
, PSR_s
| PSR_x
| PSR_f
},
486 {"SPSR_sxc", FALSE
, PSR_s
| PSR_x
| PSR_c
},
487 {"SPSR_scf", FALSE
, PSR_s
| PSR_c
| PSR_f
},
488 {"SPSR_scx", FALSE
, PSR_s
| PSR_c
| PSR_x
},
489 {"SPSR_xfs", FALSE
, PSR_x
| PSR_f
| PSR_s
},
490 {"SPSR_xfc", FALSE
, PSR_x
| PSR_f
| PSR_c
},
491 {"SPSR_xsf", FALSE
, PSR_x
| PSR_s
| PSR_f
},
492 {"SPSR_xsc", FALSE
, PSR_x
| PSR_s
| PSR_c
},
493 {"SPSR_xcf", FALSE
, PSR_x
| PSR_c
| PSR_f
},
494 {"SPSR_xcs", FALSE
, PSR_x
| PSR_c
| PSR_s
},
495 {"SPSR_cfs", FALSE
, PSR_c
| PSR_f
| PSR_s
},
496 {"SPSR_cfx", FALSE
, PSR_c
| PSR_f
| PSR_x
},
497 {"SPSR_csf", FALSE
, PSR_c
| PSR_s
| PSR_f
},
498 {"SPSR_csx", FALSE
, PSR_c
| PSR_s
| PSR_x
},
499 {"SPSR_cxf", FALSE
, PSR_c
| PSR_x
| PSR_f
},
500 {"SPSR_cxs", FALSE
, PSR_c
| PSR_x
| PSR_s
},
501 {"SPSR_fsxc", FALSE
, PSR_f
| PSR_s
| PSR_x
| PSR_c
},
502 {"SPSR_fscx", FALSE
, PSR_f
| PSR_s
| PSR_c
| PSR_x
},
503 {"SPSR_fxsc", FALSE
, PSR_f
| PSR_x
| PSR_s
| PSR_c
},
504 {"SPSR_fxcs", FALSE
, PSR_f
| PSR_x
| PSR_c
| PSR_s
},
505 {"SPSR_fcsx", FALSE
, PSR_f
| PSR_c
| PSR_s
| PSR_x
},
506 {"SPSR_fcxs", FALSE
, PSR_f
| PSR_c
| PSR_x
| PSR_s
},
507 {"SPSR_sfxc", FALSE
, PSR_s
| PSR_f
| PSR_x
| PSR_c
},
508 {"SPSR_sfcx", FALSE
, PSR_s
| PSR_f
| PSR_c
| PSR_x
},
509 {"SPSR_sxfc", FALSE
, PSR_s
| PSR_x
| PSR_f
| PSR_c
},
510 {"SPSR_sxcf", FALSE
, PSR_s
| PSR_x
| PSR_c
| PSR_f
},
511 {"SPSR_scfx", FALSE
, PSR_s
| PSR_c
| PSR_f
| PSR_x
},
512 {"SPSR_scxf", FALSE
, PSR_s
| PSR_c
| PSR_x
| PSR_f
},
513 {"SPSR_xfsc", FALSE
, PSR_x
| PSR_f
| PSR_s
| PSR_c
},
514 {"SPSR_xfcs", FALSE
, PSR_x
| PSR_f
| PSR_c
| PSR_s
},
515 {"SPSR_xsfc", FALSE
, PSR_x
| PSR_s
| PSR_f
| PSR_c
},
516 {"SPSR_xscf", FALSE
, PSR_x
| PSR_s
| PSR_c
| PSR_f
},
517 {"SPSR_xcfs", FALSE
, PSR_x
| PSR_c
| PSR_f
| PSR_s
},
518 {"SPSR_xcsf", FALSE
, PSR_x
| PSR_c
| PSR_s
| PSR_f
},
519 {"SPSR_cfsx", FALSE
, PSR_c
| PSR_f
| PSR_s
| PSR_x
},
520 {"SPSR_cfxs", FALSE
, PSR_c
| PSR_f
| PSR_x
| PSR_s
},
521 {"SPSR_csfx", FALSE
, PSR_c
| PSR_s
| PSR_f
| PSR_x
},
522 {"SPSR_csxf", FALSE
, PSR_c
| PSR_s
| PSR_x
| PSR_f
},
523 {"SPSR_cxfs", FALSE
, PSR_c
| PSR_x
| PSR_f
| PSR_s
},
524 {"SPSR_cxsf", FALSE
, PSR_c
| PSR_x
| PSR_s
| PSR_f
},
531 IWMMXT_REG_WR_OR_WC
= 2,
535 enum iwmmxt_insn_type
558 VFP_REG_Dd
, VFP_REG_Dm
, VFP_REG_Dn
563 VFP_REG_Sd
, VFP_REG_Sm
, VFP_REG_Sn
568 VFP_LDSTMIA
, VFP_LDSTMDB
, VFP_LDSTMIAX
, VFP_LDSTMDBX
571 /* VFP system registers. */
578 static const struct vfp_reg vfp_regs
[] =
580 {"fpsid", 0x00000000},
581 {"FPSID", 0x00000000},
582 {"fpscr", 0x00010000},
583 {"FPSCR", 0x00010000},
584 {"fpexc", 0x00080000},
585 {"FPEXC", 0x00080000}
588 /* Structure for a hash table entry for a register. */
596 /* Some well known registers that we refer to directly elsewhere. */
601 #define wr_register(reg) ((reg ^ WR_PREFIX) >= 0 && (reg ^ WR_PREFIX) <= 15)
602 #define wc_register(reg) ((reg ^ WC_PREFIX) >= 0 && (reg ^ WC_PREFIX) <= 15)
603 #define wcg_register(reg) ((reg ^ WC_PREFIX) >= 8 && (reg ^ WC_PREFIX) <= 11)
605 /* These are the standard names. Users can add aliases with .req.
606 and delete them with .unreq. */
608 /* Integer Register Numbers. */
609 static const struct reg_entry rn_table
[] =
611 {"r0", 0, TRUE
}, {"r1", 1, TRUE
}, {"r2", 2, TRUE
}, {"r3", 3, TRUE
},
612 {"r4", 4, TRUE
}, {"r5", 5, TRUE
}, {"r6", 6, TRUE
}, {"r7", 7, TRUE
},
613 {"r8", 8, TRUE
}, {"r9", 9, TRUE
}, {"r10", 10, TRUE
}, {"r11", 11, TRUE
},
614 {"r12", 12, TRUE
}, {"r13", REG_SP
, TRUE
}, {"r14", REG_LR
, TRUE
}, {"r15", REG_PC
, TRUE
},
615 /* ATPCS Synonyms. */
616 {"a1", 0, TRUE
}, {"a2", 1, TRUE
}, {"a3", 2, TRUE
}, {"a4", 3, TRUE
},
617 {"v1", 4, TRUE
}, {"v2", 5, TRUE
}, {"v3", 6, TRUE
}, {"v4", 7, TRUE
},
618 {"v5", 8, TRUE
}, {"v6", 9, TRUE
}, {"v7", 10, TRUE
}, {"v8", 11, TRUE
},
619 /* Well-known aliases. */
620 {"wr", 7, TRUE
}, {"sb", 9, TRUE
}, {"sl", 10, TRUE
}, {"fp", 11, TRUE
},
621 {"ip", 12, TRUE
}, {"sp", REG_SP
, TRUE
}, {"lr", REG_LR
, TRUE
}, {"pc", REG_PC
, TRUE
},
625 #define WR_PREFIX 0x200
626 #define WC_PREFIX 0x400
628 static const struct reg_entry iwmmxt_table
[] =
630 /* Intel Wireless MMX technology register names. */
631 { "wr0", 0x0 | WR_PREFIX
, TRUE
}, {"wr1", 0x1 | WR_PREFIX
, TRUE
},
632 { "wr2", 0x2 | WR_PREFIX
, TRUE
}, {"wr3", 0x3 | WR_PREFIX
, TRUE
},
633 { "wr4", 0x4 | WR_PREFIX
, TRUE
}, {"wr5", 0x5 | WR_PREFIX
, TRUE
},
634 { "wr6", 0x6 | WR_PREFIX
, TRUE
}, {"wr7", 0x7 | WR_PREFIX
, TRUE
},
635 { "wr8", 0x8 | WR_PREFIX
, TRUE
}, {"wr9", 0x9 | WR_PREFIX
, TRUE
},
636 { "wr10", 0xa | WR_PREFIX
, TRUE
}, {"wr11", 0xb | WR_PREFIX
, TRUE
},
637 { "wr12", 0xc | WR_PREFIX
, TRUE
}, {"wr13", 0xd | WR_PREFIX
, TRUE
},
638 { "wr14", 0xe | WR_PREFIX
, TRUE
}, {"wr15", 0xf | WR_PREFIX
, TRUE
},
639 { "wcid", 0x0 | WC_PREFIX
, TRUE
}, {"wcon", 0x1 | WC_PREFIX
, TRUE
},
640 {"wcssf", 0x2 | WC_PREFIX
, TRUE
}, {"wcasf", 0x3 | WC_PREFIX
, TRUE
},
641 {"wcgr0", 0x8 | WC_PREFIX
, TRUE
}, {"wcgr1", 0x9 | WC_PREFIX
, TRUE
},
642 {"wcgr2", 0xa | WC_PREFIX
, TRUE
}, {"wcgr3", 0xb | WC_PREFIX
, TRUE
},
644 { "wR0", 0x0 | WR_PREFIX
, TRUE
}, {"wR1", 0x1 | WR_PREFIX
, TRUE
},
645 { "wR2", 0x2 | WR_PREFIX
, TRUE
}, {"wR3", 0x3 | WR_PREFIX
, TRUE
},
646 { "wR4", 0x4 | WR_PREFIX
, TRUE
}, {"wR5", 0x5 | WR_PREFIX
, TRUE
},
647 { "wR6", 0x6 | WR_PREFIX
, TRUE
}, {"wR7", 0x7 | WR_PREFIX
, TRUE
},
648 { "wR8", 0x8 | WR_PREFIX
, TRUE
}, {"wR9", 0x9 | WR_PREFIX
, TRUE
},
649 { "wR10", 0xa | WR_PREFIX
, TRUE
}, {"wR11", 0xb | WR_PREFIX
, TRUE
},
650 { "wR12", 0xc | WR_PREFIX
, TRUE
}, {"wR13", 0xd | WR_PREFIX
, TRUE
},
651 { "wR14", 0xe | WR_PREFIX
, TRUE
}, {"wR15", 0xf | WR_PREFIX
, TRUE
},
652 { "wCID", 0x0 | WC_PREFIX
, TRUE
}, {"wCon", 0x1 | WC_PREFIX
, TRUE
},
653 {"wCSSF", 0x2 | WC_PREFIX
, TRUE
}, {"wCASF", 0x3 | WC_PREFIX
, TRUE
},
654 {"wCGR0", 0x8 | WC_PREFIX
, TRUE
}, {"wCGR1", 0x9 | WC_PREFIX
, TRUE
},
655 {"wCGR2", 0xa | WC_PREFIX
, TRUE
}, {"wCGR3", 0xb | WC_PREFIX
, TRUE
},
659 /* Co-processor Numbers. */
660 static const struct reg_entry cp_table
[] =
662 {"p0", 0, TRUE
}, {"p1", 1, TRUE
}, {"p2", 2, TRUE
}, {"p3", 3, TRUE
},
663 {"p4", 4, TRUE
}, {"p5", 5, TRUE
}, {"p6", 6, TRUE
}, {"p7", 7, TRUE
},
664 {"p8", 8, TRUE
}, {"p9", 9, TRUE
}, {"p10", 10, TRUE
}, {"p11", 11, TRUE
},
665 {"p12", 12, TRUE
}, {"p13", 13, TRUE
}, {"p14", 14, TRUE
}, {"p15", 15, TRUE
},
669 /* Co-processor Register Numbers. */
670 static const struct reg_entry cn_table
[] =
672 {"c0", 0, TRUE
}, {"c1", 1, TRUE
}, {"c2", 2, TRUE
}, {"c3", 3, TRUE
},
673 {"c4", 4, TRUE
}, {"c5", 5, TRUE
}, {"c6", 6, TRUE
}, {"c7", 7, TRUE
},
674 {"c8", 8, TRUE
}, {"c9", 9, TRUE
}, {"c10", 10, TRUE
}, {"c11", 11, TRUE
},
675 {"c12", 12, TRUE
}, {"c13", 13, TRUE
}, {"c14", 14, TRUE
}, {"c15", 15, TRUE
},
676 /* Not really valid, but kept for back-wards compatibility. */
677 {"cr0", 0, TRUE
}, {"cr1", 1, TRUE
}, {"cr2", 2, TRUE
}, {"cr3", 3, TRUE
},
678 {"cr4", 4, TRUE
}, {"cr5", 5, TRUE
}, {"cr6", 6, TRUE
}, {"cr7", 7, TRUE
},
679 {"cr8", 8, TRUE
}, {"cr9", 9, TRUE
}, {"cr10", 10, TRUE
}, {"cr11", 11, TRUE
},
680 {"cr12", 12, TRUE
}, {"cr13", 13, TRUE
}, {"cr14", 14, TRUE
}, {"cr15", 15, TRUE
},
685 static const struct reg_entry fn_table
[] =
687 {"f0", 0, TRUE
}, {"f1", 1, TRUE
}, {"f2", 2, TRUE
}, {"f3", 3, TRUE
},
688 {"f4", 4, TRUE
}, {"f5", 5, TRUE
}, {"f6", 6, TRUE
}, {"f7", 7, TRUE
},
692 /* VFP SP Registers. */
693 static const struct reg_entry sn_table
[] =
695 {"s0", 0, TRUE
}, {"s1", 1, TRUE
}, {"s2", 2, TRUE
}, {"s3", 3, TRUE
},
696 {"s4", 4, TRUE
}, {"s5", 5, TRUE
}, {"s6", 6, TRUE
}, {"s7", 7, TRUE
},
697 {"s8", 8, TRUE
}, {"s9", 9, TRUE
}, {"s10", 10, TRUE
}, {"s11", 11, TRUE
},
698 {"s12", 12, TRUE
}, {"s13", 13, TRUE
}, {"s14", 14, TRUE
}, {"s15", 15, TRUE
},
699 {"s16", 16, TRUE
}, {"s17", 17, TRUE
}, {"s18", 18, TRUE
}, {"s19", 19, TRUE
},
700 {"s20", 20, TRUE
}, {"s21", 21, TRUE
}, {"s22", 22, TRUE
}, {"s23", 23, TRUE
},
701 {"s24", 24, TRUE
}, {"s25", 25, TRUE
}, {"s26", 26, TRUE
}, {"s27", 27, TRUE
},
702 {"s28", 28, TRUE
}, {"s29", 29, TRUE
}, {"s30", 30, TRUE
}, {"s31", 31, TRUE
},
706 /* VFP DP Registers. */
707 static const struct reg_entry dn_table
[] =
709 {"d0", 0, TRUE
}, {"d1", 1, TRUE
}, {"d2", 2, TRUE
}, {"d3", 3, TRUE
},
710 {"d4", 4, TRUE
}, {"d5", 5, TRUE
}, {"d6", 6, TRUE
}, {"d7", 7, TRUE
},
711 {"d8", 8, TRUE
}, {"d9", 9, TRUE
}, {"d10", 10, TRUE
}, {"d11", 11, TRUE
},
712 {"d12", 12, TRUE
}, {"d13", 13, TRUE
}, {"d14", 14, TRUE
}, {"d15", 15, TRUE
},
716 /* Maverick DSP coprocessor registers. */
717 static const struct reg_entry mav_mvf_table
[] =
719 {"mvf0", 0, TRUE
}, {"mvf1", 1, TRUE
}, {"mvf2", 2, TRUE
}, {"mvf3", 3, TRUE
},
720 {"mvf4", 4, TRUE
}, {"mvf5", 5, TRUE
}, {"mvf6", 6, TRUE
}, {"mvf7", 7, TRUE
},
721 {"mvf8", 8, TRUE
}, {"mvf9", 9, TRUE
}, {"mvf10", 10, TRUE
}, {"mvf11", 11, TRUE
},
722 {"mvf12", 12, TRUE
}, {"mvf13", 13, TRUE
}, {"mvf14", 14, TRUE
}, {"mvf15", 15, TRUE
},
726 static const struct reg_entry mav_mvd_table
[] =
728 {"mvd0", 0, TRUE
}, {"mvd1", 1, TRUE
}, {"mvd2", 2, TRUE
}, {"mvd3", 3, TRUE
},
729 {"mvd4", 4, TRUE
}, {"mvd5", 5, TRUE
}, {"mvd6", 6, TRUE
}, {"mvd7", 7, TRUE
},
730 {"mvd8", 8, TRUE
}, {"mvd9", 9, TRUE
}, {"mvd10", 10, TRUE
}, {"mvd11", 11, TRUE
},
731 {"mvd12", 12, TRUE
}, {"mvd13", 13, TRUE
}, {"mvd14", 14, TRUE
}, {"mvd15", 15, TRUE
},
735 static const struct reg_entry mav_mvfx_table
[] =
737 {"mvfx0", 0, TRUE
}, {"mvfx1", 1, TRUE
}, {"mvfx2", 2, TRUE
}, {"mvfx3", 3, TRUE
},
738 {"mvfx4", 4, TRUE
}, {"mvfx5", 5, TRUE
}, {"mvfx6", 6, TRUE
}, {"mvfx7", 7, TRUE
},
739 {"mvfx8", 8, TRUE
}, {"mvfx9", 9, TRUE
}, {"mvfx10", 10, TRUE
}, {"mvfx11", 11, TRUE
},
740 {"mvfx12", 12, TRUE
}, {"mvfx13", 13, TRUE
}, {"mvfx14", 14, TRUE
}, {"mvfx15", 15, TRUE
},
744 static const struct reg_entry mav_mvdx_table
[] =
746 {"mvdx0", 0, TRUE
}, {"mvdx1", 1, TRUE
}, {"mvdx2", 2, TRUE
}, {"mvdx3", 3, TRUE
},
747 {"mvdx4", 4, TRUE
}, {"mvdx5", 5, TRUE
}, {"mvdx6", 6, TRUE
}, {"mvdx7", 7, TRUE
},
748 {"mvdx8", 8, TRUE
}, {"mvdx9", 9, TRUE
}, {"mvdx10", 10, TRUE
}, {"mvdx11", 11, TRUE
},
749 {"mvdx12", 12, TRUE
}, {"mvdx13", 13, TRUE
}, {"mvdx14", 14, TRUE
}, {"mvdx15", 15, TRUE
},
753 static const struct reg_entry mav_mvax_table
[] =
755 {"mvax0", 0, TRUE
}, {"mvax1", 1, TRUE
}, {"mvax2", 2, TRUE
}, {"mvax3", 3, TRUE
},
759 static const struct reg_entry mav_dspsc_table
[] =
767 const struct reg_entry
*names
;
769 struct hash_control
*htab
;
770 const char *expected
;
773 struct reg_map all_reg_maps
[] =
775 {rn_table
, 15, NULL
, N_("ARM register expected")},
776 {cp_table
, 15, NULL
, N_("bad or missing co-processor number")},
777 {cn_table
, 15, NULL
, N_("co-processor register expected")},
778 {fn_table
, 7, NULL
, N_("FPA register expected")},
779 {sn_table
, 31, NULL
, N_("VFP single precision register expected")},
780 {dn_table
, 15, NULL
, N_("VFP double precision register expected")},
781 {mav_mvf_table
, 15, NULL
, N_("Maverick MVF register expected")},
782 {mav_mvd_table
, 15, NULL
, N_("Maverick MVD register expected")},
783 {mav_mvfx_table
, 15, NULL
, N_("Maverick MVFX register expected")},
784 {mav_mvdx_table
, 15, NULL
, N_("Maverick MVDX register expected")},
785 {mav_mvax_table
, 3, NULL
, N_("Maverick MVAX register expected")},
786 {mav_dspsc_table
, 0, NULL
, N_("Maverick DSPSC register expected")},
787 {iwmmxt_table
, 23, NULL
, N_("Intel Wireless MMX technology register expected")},
790 /* Enumeration matching entries in table above. */
794 #define REG_TYPE_FIRST REG_TYPE_RN
806 REG_TYPE_IWMMXT
= 12,
811 /* Functions called by parser. */
812 /* ARM instructions. */
813 static void do_arit
PARAMS ((char *));
814 static void do_cmp
PARAMS ((char *));
815 static void do_mov
PARAMS ((char *));
816 static void do_ldst
PARAMS ((char *));
817 static void do_ldstt
PARAMS ((char *));
818 static void do_ldmstm
PARAMS ((char *));
819 static void do_branch
PARAMS ((char *));
820 static void do_swi
PARAMS ((char *));
822 /* Pseudo Op codes. */
823 static void do_adr
PARAMS ((char *));
824 static void do_adrl
PARAMS ((char *));
825 static void do_empty
PARAMS ((char *));
828 static void do_mul
PARAMS ((char *));
829 static void do_mla
PARAMS ((char *));
832 static void do_swap
PARAMS ((char *));
835 static void do_msr
PARAMS ((char *));
836 static void do_mrs
PARAMS ((char *));
839 static void do_mull
PARAMS ((char *));
842 static void do_ldstv4
PARAMS ((char *));
845 static void do_bx
PARAMS ((char *));
848 static void do_blx
PARAMS ((char *));
849 static void do_bkpt
PARAMS ((char *));
850 static void do_clz
PARAMS ((char *));
851 static void do_lstc2
PARAMS ((char *));
852 static void do_cdp2
PARAMS ((char *));
853 static void do_co_reg2
PARAMS ((char *));
856 static void do_smla
PARAMS ((char *));
857 static void do_smlal
PARAMS ((char *));
858 static void do_smul
PARAMS ((char *));
859 static void do_qadd
PARAMS ((char *));
862 static void do_pld
PARAMS ((char *));
863 static void do_ldrd
PARAMS ((char *));
864 static void do_co_reg2c
PARAMS ((char *));
867 static void do_bxj
PARAMS ((char *));
870 static void do_cps
PARAMS ((char *));
871 static void do_cpsi
PARAMS ((char *));
872 static void do_ldrex
PARAMS ((char *));
873 static void do_pkhbt
PARAMS ((char *));
874 static void do_pkhtb
PARAMS ((char *));
875 static void do_qadd16
PARAMS ((char *));
876 static void do_rev
PARAMS ((char *));
877 static void do_rfe
PARAMS ((char *));
878 static void do_sxtah
PARAMS ((char *));
879 static void do_sxth
PARAMS ((char *));
880 static void do_setend
PARAMS ((char *));
881 static void do_smlad
PARAMS ((char *));
882 static void do_smlald
PARAMS ((char *));
883 static void do_smmul
PARAMS ((char *));
884 static void do_ssat
PARAMS ((char *));
885 static void do_usat
PARAMS ((char *));
886 static void do_srs
PARAMS ((char *));
887 static void do_ssat16
PARAMS ((char *));
888 static void do_usat16
PARAMS ((char *));
889 static void do_strex
PARAMS ((char *));
890 static void do_umaal
PARAMS ((char *));
892 static void do_cps_mode
PARAMS ((char **));
893 static void do_cps_flags
PARAMS ((char **, int));
894 static int do_endian_specifier
PARAMS ((char *));
895 static void do_pkh_core
PARAMS ((char *, int));
896 static void do_sat
PARAMS ((char **, int));
897 static void do_sat16
PARAMS ((char **, int));
899 /* Coprocessor Instructions. */
900 static void do_cdp
PARAMS ((char *));
901 static void do_lstc
PARAMS ((char *));
902 static void do_co_reg
PARAMS ((char *));
904 /* FPA instructions. */
905 static void do_fpa_ctrl
PARAMS ((char *));
906 static void do_fpa_ldst
PARAMS ((char *));
907 static void do_fpa_ldmstm
PARAMS ((char *));
908 static void do_fpa_dyadic
PARAMS ((char *));
909 static void do_fpa_monadic
PARAMS ((char *));
910 static void do_fpa_cmp
PARAMS ((char *));
911 static void do_fpa_from_reg
PARAMS ((char *));
912 static void do_fpa_to_reg
PARAMS ((char *));
914 /* VFP instructions. */
915 static void do_vfp_sp_monadic
PARAMS ((char *));
916 static void do_vfp_dp_monadic
PARAMS ((char *));
917 static void do_vfp_sp_dyadic
PARAMS ((char *));
918 static void do_vfp_dp_dyadic
PARAMS ((char *));
919 static void do_vfp_reg_from_sp
PARAMS ((char *));
920 static void do_vfp_sp_from_reg
PARAMS ((char *));
921 static void do_vfp_sp_reg2
PARAMS ((char *));
922 static void do_vfp_reg_from_dp
PARAMS ((char *));
923 static void do_vfp_reg2_from_dp
PARAMS ((char *));
924 static void do_vfp_dp_from_reg
PARAMS ((char *));
925 static void do_vfp_dp_from_reg2
PARAMS ((char *));
926 static void do_vfp_reg_from_ctrl
PARAMS ((char *));
927 static void do_vfp_ctrl_from_reg
PARAMS ((char *));
928 static void do_vfp_sp_ldst
PARAMS ((char *));
929 static void do_vfp_dp_ldst
PARAMS ((char *));
930 static void do_vfp_sp_ldstmia
PARAMS ((char *));
931 static void do_vfp_sp_ldstmdb
PARAMS ((char *));
932 static void do_vfp_dp_ldstmia
PARAMS ((char *));
933 static void do_vfp_dp_ldstmdb
PARAMS ((char *));
934 static void do_vfp_xp_ldstmia
PARAMS ((char *));
935 static void do_vfp_xp_ldstmdb
PARAMS ((char *));
936 static void do_vfp_sp_compare_z
PARAMS ((char *));
937 static void do_vfp_dp_compare_z
PARAMS ((char *));
938 static void do_vfp_dp_sp_cvt
PARAMS ((char *));
939 static void do_vfp_sp_dp_cvt
PARAMS ((char *));
942 static void do_xsc_mia
PARAMS ((char *));
943 static void do_xsc_mar
PARAMS ((char *));
944 static void do_xsc_mra
PARAMS ((char *));
947 static void do_mav_binops
PARAMS ((char *, int, enum arm_reg_type
,
949 static void do_mav_binops_1a
PARAMS ((char *));
950 static void do_mav_binops_1b
PARAMS ((char *));
951 static void do_mav_binops_1c
PARAMS ((char *));
952 static void do_mav_binops_1d
PARAMS ((char *));
953 static void do_mav_binops_1e
PARAMS ((char *));
954 static void do_mav_binops_1f
PARAMS ((char *));
955 static void do_mav_binops_1g
PARAMS ((char *));
956 static void do_mav_binops_1h
PARAMS ((char *));
957 static void do_mav_binops_1i
PARAMS ((char *));
958 static void do_mav_binops_1j
PARAMS ((char *));
959 static void do_mav_binops_1k
PARAMS ((char *));
960 static void do_mav_binops_1l
PARAMS ((char *));
961 static void do_mav_binops_1m
PARAMS ((char *));
962 static void do_mav_binops_1n
PARAMS ((char *));
963 static void do_mav_binops_1o
PARAMS ((char *));
964 static void do_mav_binops_2a
PARAMS ((char *));
965 static void do_mav_binops_2b
PARAMS ((char *));
966 static void do_mav_binops_2c
PARAMS ((char *));
967 static void do_mav_binops_3a
PARAMS ((char *));
968 static void do_mav_binops_3b
PARAMS ((char *));
969 static void do_mav_binops_3c
PARAMS ((char *));
970 static void do_mav_binops_3d
PARAMS ((char *));
971 static void do_mav_triple
PARAMS ((char *, int, enum arm_reg_type
,
974 static void do_mav_triple_4a
PARAMS ((char *));
975 static void do_mav_triple_4b
PARAMS ((char *));
976 static void do_mav_triple_5a
PARAMS ((char *));
977 static void do_mav_triple_5b
PARAMS ((char *));
978 static void do_mav_triple_5c
PARAMS ((char *));
979 static void do_mav_triple_5d
PARAMS ((char *));
980 static void do_mav_triple_5e
PARAMS ((char *));
981 static void do_mav_triple_5f
PARAMS ((char *));
982 static void do_mav_triple_5g
PARAMS ((char *));
983 static void do_mav_triple_5h
PARAMS ((char *));
984 static void do_mav_quad
PARAMS ((char *, int, enum arm_reg_type
,
988 static void do_mav_quad_6a
PARAMS ((char *));
989 static void do_mav_quad_6b
PARAMS ((char *));
990 static void do_mav_dspsc_1
PARAMS ((char *));
991 static void do_mav_dspsc_2
PARAMS ((char *));
992 static void do_mav_shift
PARAMS ((char *, enum arm_reg_type
,
994 static void do_mav_shift_1
PARAMS ((char *));
995 static void do_mav_shift_2
PARAMS ((char *));
996 static void do_mav_ldst
PARAMS ((char *, enum arm_reg_type
));
997 static void do_mav_ldst_1
PARAMS ((char *));
998 static void do_mav_ldst_2
PARAMS ((char *));
999 static void do_mav_ldst_3
PARAMS ((char *));
1000 static void do_mav_ldst_4
PARAMS ((char *));
1002 static int mav_reg_required_here
PARAMS ((char **, int,
1003 enum arm_reg_type
));
1004 static int mav_parse_offset
PARAMS ((char **, int *));
1006 static void fix_new_arm
PARAMS ((fragS
*, int, short, expressionS
*,
1008 static int arm_reg_parse
PARAMS ((char **, struct hash_control
*));
1009 static enum arm_reg_type arm_reg_parse_any
PARAMS ((char *));
1010 static const struct asm_psr
* arm_psr_parse
PARAMS ((char **));
1011 static void symbol_locate
PARAMS ((symbolS
*, const char *, segT
, valueT
,
1013 static int add_to_lit_pool
PARAMS ((void));
1014 static unsigned validate_immediate
PARAMS ((unsigned));
1015 static unsigned validate_immediate_twopart
PARAMS ((unsigned int,
1017 static int validate_offset_imm
PARAMS ((unsigned int, int));
1018 static void opcode_select
PARAMS ((int));
1019 static void end_of_line
PARAMS ((char *));
1020 static int reg_required_here
PARAMS ((char **, int));
1021 static int psr_required_here
PARAMS ((char **));
1022 static int co_proc_number
PARAMS ((char **));
1023 static int cp_opc_expr
PARAMS ((char **, int, int));
1024 static int cp_reg_required_here
PARAMS ((char **, int));
1025 static int fp_reg_required_here
PARAMS ((char **, int));
1026 static int vfp_sp_reg_required_here
PARAMS ((char **, enum vfp_sp_reg_pos
));
1027 static int vfp_dp_reg_required_here
PARAMS ((char **, enum vfp_dp_reg_pos
));
1028 static void vfp_sp_ldstm
PARAMS ((char *, enum vfp_ldstm_type
));
1029 static void vfp_dp_ldstm
PARAMS ((char *, enum vfp_ldstm_type
));
1030 static long vfp_sp_reg_list
PARAMS ((char **, enum vfp_sp_reg_pos
));
1031 static long vfp_dp_reg_list
PARAMS ((char **));
1032 static int vfp_psr_required_here
PARAMS ((char **str
));
1033 static const struct vfp_reg
*vfp_psr_parse
PARAMS ((char **str
));
1034 static int cp_address_offset
PARAMS ((char **));
1035 static int cp_address_required_here
PARAMS ((char **, int));
1036 static int my_get_float_expression
PARAMS ((char **));
1037 static int skip_past_comma
PARAMS ((char **));
1038 static int walk_no_bignums
PARAMS ((symbolS
*));
1039 static int negate_data_op
PARAMS ((unsigned long *, unsigned long));
1040 static int data_op2
PARAMS ((char **));
1041 static int fp_op2
PARAMS ((char **));
1042 static long reg_list
PARAMS ((char **));
1043 static void thumb_load_store
PARAMS ((char *, int, int));
1044 static int decode_shift
PARAMS ((char **, int));
1045 static int ldst_extend
PARAMS ((char **));
1046 static int ldst_extend_v4
PARAMS ((char **));
1047 static void thumb_add_sub
PARAMS ((char *, int));
1048 static void insert_reg
PARAMS ((const struct reg_entry
*,
1049 struct hash_control
*));
1050 static void thumb_shift
PARAMS ((char *, int));
1051 static void thumb_mov_compare
PARAMS ((char *, int));
1052 static void build_arm_ops_hsh
PARAMS ((void));
1053 static void set_constant_flonums
PARAMS ((void));
1054 static valueT md_chars_to_number
PARAMS ((char *, int));
1055 static void build_reg_hsh
PARAMS ((struct reg_map
*));
1056 static void insert_reg_alias
PARAMS ((char *, int, struct hash_control
*));
1057 static int create_register_alias
PARAMS ((char *, char *));
1058 static void output_inst
PARAMS ((const char *));
1059 static int accum0_required_here
PARAMS ((char **));
1060 static int ld_mode_required_here
PARAMS ((char **));
1061 static void do_branch25
PARAMS ((char *));
1062 static symbolS
* find_real_start
PARAMS ((symbolS
*));
1064 static bfd_reloc_code_real_type arm_parse_reloc
PARAMS ((void));
1067 static int wreg_required_here
PARAMS ((char **, int, enum wreg_type
));
1068 static void do_iwmmxt_byte_addr
PARAMS ((char *));
1069 static void do_iwmmxt_tandc
PARAMS ((char *));
1070 static void do_iwmmxt_tbcst
PARAMS ((char *));
1071 static void do_iwmmxt_textrc
PARAMS ((char *));
1072 static void do_iwmmxt_textrm
PARAMS ((char *));
1073 static void do_iwmmxt_tinsr
PARAMS ((char *));
1074 static void do_iwmmxt_tmcr
PARAMS ((char *));
1075 static void do_iwmmxt_tmcrr
PARAMS ((char *));
1076 static void do_iwmmxt_tmia
PARAMS ((char *));
1077 static void do_iwmmxt_tmovmsk
PARAMS ((char *));
1078 static void do_iwmmxt_tmrc
PARAMS ((char *));
1079 static void do_iwmmxt_tmrrc
PARAMS ((char *));
1080 static void do_iwmmxt_torc
PARAMS ((char *));
1081 static void do_iwmmxt_waligni
PARAMS ((char *));
1082 static void do_iwmmxt_wmov
PARAMS ((char *));
1083 static void do_iwmmxt_word_addr
PARAMS ((char *));
1084 static void do_iwmmxt_wrwr
PARAMS ((char *));
1085 static void do_iwmmxt_wrwrwcg
PARAMS ((char *));
1086 static void do_iwmmxt_wrwrwr
PARAMS ((char *));
1087 static void do_iwmmxt_wshufh
PARAMS ((char *));
1088 static void do_iwmmxt_wzero
PARAMS ((char *));
1089 static int cp_byte_address_offset
PARAMS ((char **));
1090 static int cp_byte_address_required_here
PARAMS ((char **));
1092 /* ARM instructions take 4bytes in the object file, Thumb instructions
1096 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
1097 #define MAV_MODE1 0x100c
1099 /* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
1100 #define MAV_MODE2 0x0c10
1102 /* "INSN<cond> X,Y" where X:0, Y:bit16. */
1103 #define MAV_MODE3 0x1000
1105 /* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
1106 #define MAV_MODE4 0x0c0010
1108 /* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
1109 #define MAV_MODE5 0x00100c
1111 /* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
1112 #define MAV_MODE6 0x00100c05
1116 /* Basic string to match. */
1117 const char * template;
1119 /* Basic instruction code. */
1120 unsigned long value
;
1122 /* Offset into the template where the condition code (if any) will be.
1123 If zero, then the instruction is never conditional. */
1124 unsigned cond_offset
;
1126 /* Which architecture variant provides this instruction. */
1127 unsigned long variant
;
1129 /* Function to call to parse args. */
1130 void (* parms
) PARAMS ((char *));
1133 static const struct asm_opcode insns
[] =
1135 /* Core ARM Instructions. */
1136 {"and", 0xe0000000, 3, ARM_EXT_V1
, do_arit
},
1137 {"ands", 0xe0100000, 3, ARM_EXT_V1
, do_arit
},
1138 {"eor", 0xe0200000, 3, ARM_EXT_V1
, do_arit
},
1139 {"eors", 0xe0300000, 3, ARM_EXT_V1
, do_arit
},
1140 {"sub", 0xe0400000, 3, ARM_EXT_V1
, do_arit
},
1141 {"subs", 0xe0500000, 3, ARM_EXT_V1
, do_arit
},
1142 {"rsb", 0xe0600000, 3, ARM_EXT_V1
, do_arit
},
1143 {"rsbs", 0xe0700000, 3, ARM_EXT_V1
, do_arit
},
1144 {"add", 0xe0800000, 3, ARM_EXT_V1
, do_arit
},
1145 {"adds", 0xe0900000, 3, ARM_EXT_V1
, do_arit
},
1146 {"adc", 0xe0a00000, 3, ARM_EXT_V1
, do_arit
},
1147 {"adcs", 0xe0b00000, 3, ARM_EXT_V1
, do_arit
},
1148 {"sbc", 0xe0c00000, 3, ARM_EXT_V1
, do_arit
},
1149 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1
, do_arit
},
1150 {"rsc", 0xe0e00000, 3, ARM_EXT_V1
, do_arit
},
1151 {"rscs", 0xe0f00000, 3, ARM_EXT_V1
, do_arit
},
1152 {"orr", 0xe1800000, 3, ARM_EXT_V1
, do_arit
},
1153 {"orrs", 0xe1900000, 3, ARM_EXT_V1
, do_arit
},
1154 {"bic", 0xe1c00000, 3, ARM_EXT_V1
, do_arit
},
1155 {"bics", 0xe1d00000, 3, ARM_EXT_V1
, do_arit
},
1157 {"tst", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
1158 {"tsts", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
1159 {"tstp", 0xe110f000, 3, ARM_EXT_V1
, do_cmp
},
1160 {"teq", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
1161 {"teqs", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
1162 {"teqp", 0xe130f000, 3, ARM_EXT_V1
, do_cmp
},
1163 {"cmp", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
1164 {"cmps", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
1165 {"cmpp", 0xe150f000, 3, ARM_EXT_V1
, do_cmp
},
1166 {"cmn", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
1167 {"cmns", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
1168 {"cmnp", 0xe170f000, 3, ARM_EXT_V1
, do_cmp
},
1170 {"mov", 0xe1a00000, 3, ARM_EXT_V1
, do_mov
},
1171 {"movs", 0xe1b00000, 3, ARM_EXT_V1
, do_mov
},
1172 {"mvn", 0xe1e00000, 3, ARM_EXT_V1
, do_mov
},
1173 {"mvns", 0xe1f00000, 3, ARM_EXT_V1
, do_mov
},
1175 {"ldr", 0xe4100000, 3, ARM_EXT_V1
, do_ldst
},
1176 {"ldrb", 0xe4500000, 3, ARM_EXT_V1
, do_ldst
},
1177 {"ldrt", 0xe4300000, 3, ARM_EXT_V1
, do_ldstt
},
1178 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1
, do_ldstt
},
1179 {"str", 0xe4000000, 3, ARM_EXT_V1
, do_ldst
},
1180 {"strb", 0xe4400000, 3, ARM_EXT_V1
, do_ldst
},
1181 {"strt", 0xe4200000, 3, ARM_EXT_V1
, do_ldstt
},
1182 {"strbt", 0xe4600000, 3, ARM_EXT_V1
, do_ldstt
},
1184 {"stmia", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
1185 {"stmib", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
1186 {"stmda", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
1187 {"stmdb", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
1188 {"stmfd", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
1189 {"stmfa", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
1190 {"stmea", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
1191 {"stmed", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
1193 {"ldmia", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
1194 {"ldmib", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
1195 {"ldmda", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
1196 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
1197 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
1198 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
1199 {"ldmea", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
1200 {"ldmed", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
1202 {"swi", 0xef000000, 3, ARM_EXT_V1
, do_swi
},
1204 /* XXX This is the wrong place to do this. Think multi-arch. */
1205 {"bl", 0xeb000000, 2, ARM_EXT_V1
, do_branch
},
1206 {"b", 0xea000000, 1, ARM_EXT_V1
, do_branch
},
1208 {"bl", 0xebfffffe, 2, ARM_EXT_V1
, do_branch
},
1209 {"b", 0xeafffffe, 1, ARM_EXT_V1
, do_branch
},
1213 {"adr", 0xe28f0000, 3, ARM_EXT_V1
, do_adr
},
1214 {"adrl", 0xe28f0000, 3, ARM_EXT_V1
, do_adrl
},
1215 {"nop", 0xe1a00000, 3, ARM_EXT_V1
, do_empty
},
1217 /* ARM 2 multiplies. */
1218 {"mul", 0xe0000090, 3, ARM_EXT_V2
, do_mul
},
1219 {"muls", 0xe0100090, 3, ARM_EXT_V2
, do_mul
},
1220 {"mla", 0xe0200090, 3, ARM_EXT_V2
, do_mla
},
1221 {"mlas", 0xe0300090, 3, ARM_EXT_V2
, do_mla
},
1223 /* Generic coprocessor instructions. */
1224 {"cdp", 0xee000000, 3, ARM_EXT_V2
, do_cdp
},
1225 {"ldc", 0xec100000, 3, ARM_EXT_V2
, do_lstc
},
1226 {"ldcl", 0xec500000, 3, ARM_EXT_V2
, do_lstc
},
1227 {"stc", 0xec000000, 3, ARM_EXT_V2
, do_lstc
},
1228 {"stcl", 0xec400000, 3, ARM_EXT_V2
, do_lstc
},
1229 {"mcr", 0xee000010, 3, ARM_EXT_V2
, do_co_reg
},
1230 {"mrc", 0xee100010, 3, ARM_EXT_V2
, do_co_reg
},
1232 /* ARM 3 - swp instructions. */
1233 {"swp", 0xe1000090, 3, ARM_EXT_V2S
, do_swap
},
1234 {"swpb", 0xe1400090, 3, ARM_EXT_V2S
, do_swap
},
1236 /* ARM 6 Status register instructions. */
1237 {"mrs", 0xe10f0000, 3, ARM_EXT_V3
, do_mrs
},
1238 {"msr", 0xe120f000, 3, ARM_EXT_V3
, do_msr
},
1239 /* ScottB: our code uses 0xe128f000 for msr.
1240 NickC: but this is wrong because the bits 16 through 19 are
1241 handled by the PSR_xxx defines above. */
1243 /* ARM 7M long multiplies. */
1244 {"smull", 0xe0c00090, 5, ARM_EXT_V3M
, do_mull
},
1245 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M
, do_mull
},
1246 {"umull", 0xe0800090, 5, ARM_EXT_V3M
, do_mull
},
1247 {"umulls", 0xe0900090, 5, ARM_EXT_V3M
, do_mull
},
1248 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M
, do_mull
},
1249 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M
, do_mull
},
1250 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M
, do_mull
},
1251 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M
, do_mull
},
1253 /* ARM Architecture 4. */
1254 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4
, do_ldstv4
},
1255 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4
, do_ldstv4
},
1256 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4
, do_ldstv4
},
1257 {"strh", 0xe00000b0, 3, ARM_EXT_V4
, do_ldstv4
},
1259 /* ARM Architecture 4T. */
1260 /* Note: bx (and blx) are required on V5, even if the processor does
1261 not support Thumb. */
1262 {"bx", 0xe12fff10, 2, ARM_EXT_V4T
| ARM_EXT_V5
, do_bx
},
1264 /* ARM Architecture 5T. */
1265 /* Note: blx has 2 variants, so the .value is set dynamically.
1266 Only one of the variants has conditional execution. */
1267 {"blx", 0xe0000000, 3, ARM_EXT_V5
, do_blx
},
1268 {"clz", 0xe16f0f10, 3, ARM_EXT_V5
, do_clz
},
1269 {"bkpt", 0xe1200070, 0, ARM_EXT_V5
, do_bkpt
},
1270 {"ldc2", 0xfc100000, 0, ARM_EXT_V5
, do_lstc2
},
1271 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5
, do_lstc2
},
1272 {"stc2", 0xfc000000, 0, ARM_EXT_V5
, do_lstc2
},
1273 {"stc2l", 0xfc400000, 0, ARM_EXT_V5
, do_lstc2
},
1274 {"cdp2", 0xfe000000, 0, ARM_EXT_V5
, do_cdp2
},
1275 {"mcr2", 0xfe000010, 0, ARM_EXT_V5
, do_co_reg2
},
1276 {"mrc2", 0xfe100010, 0, ARM_EXT_V5
, do_co_reg2
},
1278 /* ARM Architecture 5TExP. */
1279 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP
, do_smla
},
1280 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP
, do_smla
},
1281 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP
, do_smla
},
1282 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP
, do_smla
},
1284 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP
, do_smla
},
1285 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP
, do_smla
},
1287 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP
, do_smlal
},
1288 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP
, do_smlal
},
1289 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP
, do_smlal
},
1290 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP
, do_smlal
},
1292 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP
, do_smul
},
1293 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP
, do_smul
},
1294 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP
, do_smul
},
1295 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP
, do_smul
},
1297 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP
, do_smul
},
1298 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP
, do_smul
},
1300 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP
, do_qadd
},
1301 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP
, do_qadd
},
1302 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP
, do_qadd
},
1303 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP
, do_qadd
},
1305 /* ARM Architecture 5TE. */
1306 {"pld", 0xf450f000, 0, ARM_EXT_V5E
, do_pld
},
1307 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E
, do_ldrd
},
1308 {"strd", 0xe00000f0, 3, ARM_EXT_V5E
, do_ldrd
},
1310 {"mcrr", 0xec400000, 4, ARM_EXT_V5E
, do_co_reg2c
},
1311 {"mrrc", 0xec500000, 4, ARM_EXT_V5E
, do_co_reg2c
},
1313 /* ARM Architecture 5TEJ. */
1314 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J
, do_bxj
},
1317 { "cps", 0xf1020000, 0, ARM_EXT_V6
, do_cps
},
1318 { "cpsie", 0xf1080000, 0, ARM_EXT_V6
, do_cpsi
},
1319 { "cpsid", 0xf10C0000, 0, ARM_EXT_V6
, do_cpsi
},
1320 { "ldrex", 0xe1900f9f, 5, ARM_EXT_V6
, do_ldrex
},
1321 { "mcrr2", 0xfc400000, 0, ARM_EXT_V6
, do_co_reg2c
},
1322 { "mrrc2", 0xfc500000, 0, ARM_EXT_V6
, do_co_reg2c
},
1323 { "pkhbt", 0xe6800010, 5, ARM_EXT_V6
, do_pkhbt
},
1324 { "pkhtb", 0xe6800050, 5, ARM_EXT_V6
, do_pkhtb
},
1325 { "qadd16", 0xe6200f10, 6, ARM_EXT_V6
, do_qadd16
},
1326 { "qadd8", 0xe6200f90, 5, ARM_EXT_V6
, do_qadd16
},
1327 { "qaddsubx", 0xe6200f30, 8, ARM_EXT_V6
, do_qadd16
},
1328 { "qsub16", 0xe6200f70, 6, ARM_EXT_V6
, do_qadd16
},
1329 { "qsub8", 0xe6200ff0, 5, ARM_EXT_V6
, do_qadd16
},
1330 { "qsubaddx", 0xe6200f50, 8, ARM_EXT_V6
, do_qadd16
},
1331 { "sadd16", 0xe6100f10, 6, ARM_EXT_V6
, do_qadd16
},
1332 { "sadd8", 0xe6100f90, 5, ARM_EXT_V6
, do_qadd16
},
1333 { "saddsubx", 0xe6100f30, 8, ARM_EXT_V6
, do_qadd16
},
1334 { "shadd16", 0xe6300f10, 7, ARM_EXT_V6
, do_qadd16
},
1335 { "shadd8", 0xe6300f90, 6, ARM_EXT_V6
, do_qadd16
},
1336 { "shaddsubx", 0xe6300f30, 9, ARM_EXT_V6
, do_qadd16
},
1337 { "shsub16", 0xe6300f70, 7, ARM_EXT_V6
, do_qadd16
},
1338 { "shsub8", 0xe6300ff0, 6, ARM_EXT_V6
, do_qadd16
},
1339 { "shsubaddx", 0xe6300f50, 9, ARM_EXT_V6
, do_qadd16
},
1340 { "ssub16", 0xe6100f70, 6, ARM_EXT_V6
, do_qadd16
},
1341 { "ssub8", 0xe6100ff0, 5, ARM_EXT_V6
, do_qadd16
},
1342 { "ssubaddx", 0xe6100f50, 8, ARM_EXT_V6
, do_qadd16
},
1343 { "uadd16", 0xe6500f10, 6, ARM_EXT_V6
, do_qadd16
},
1344 { "uadd8", 0xe6500f90, 5, ARM_EXT_V6
, do_qadd16
},
1345 { "uaddsubx", 0xe6500f30, 8, ARM_EXT_V6
, do_qadd16
},
1346 { "uhadd16", 0xe6700f10, 7, ARM_EXT_V6
, do_qadd16
},
1347 { "uhadd8", 0xe6700f90, 6, ARM_EXT_V6
, do_qadd16
},
1348 { "uhaddsubx", 0xe6700f30, 9, ARM_EXT_V6
, do_qadd16
},
1349 { "uhsub16", 0xe6700f70, 7, ARM_EXT_V6
, do_qadd16
},
1350 { "uhsub8", 0xe6700ff0, 6, ARM_EXT_V6
, do_qadd16
},
1351 { "uhsubaddx", 0xe6700f50, 9, ARM_EXT_V6
, do_qadd16
},
1352 { "uqadd16", 0xe6600f10, 7, ARM_EXT_V6
, do_qadd16
},
1353 { "uqadd8", 0xe6600f90, 6, ARM_EXT_V6
, do_qadd16
},
1354 { "uqaddsubx", 0xe6600f30, 9, ARM_EXT_V6
, do_qadd16
},
1355 { "uqsub16", 0xe6600f70, 7, ARM_EXT_V6
, do_qadd16
},
1356 { "uqsub8", 0xe6600ff0, 6, ARM_EXT_V6
, do_qadd16
},
1357 { "uqsubaddx", 0xe6600f50, 9, ARM_EXT_V6
, do_qadd16
},
1358 { "usub16", 0xe6500f70, 6, ARM_EXT_V6
, do_qadd16
},
1359 { "usub8", 0xe6500ff0, 5, ARM_EXT_V6
, do_qadd16
},
1360 { "usubaddx", 0xe6500f50, 8, ARM_EXT_V6
, do_qadd16
},
1361 { "rev", 0xe6bf0f30, 3, ARM_EXT_V6
, do_rev
},
1362 { "rev16", 0xe6bf0fb0, 5, ARM_EXT_V6
, do_rev
},
1363 { "revsh", 0xe6ff0fb0, 5, ARM_EXT_V6
, do_rev
},
1364 { "rfeia", 0xf8900a00, 0, ARM_EXT_V6
, do_rfe
},
1365 { "rfeib", 0xf9900a00, 0, ARM_EXT_V6
, do_rfe
},
1366 { "rfeda", 0xf8100a00, 0, ARM_EXT_V6
, do_rfe
},
1367 { "rfedb", 0xf9100a00, 0, ARM_EXT_V6
, do_rfe
},
1368 { "rfefd", 0xf8900a00, 0, ARM_EXT_V6
, do_rfe
},
1369 { "rfefa", 0xf9900a00, 0, ARM_EXT_V6
, do_rfe
},
1370 { "rfeea", 0xf8100a00, 0, ARM_EXT_V6
, do_rfe
},
1371 { "rfeed", 0xf9100a00, 0, ARM_EXT_V6
, do_rfe
},
1372 { "sxtah", 0xe6b00070, 5, ARM_EXT_V6
, do_sxtah
},
1373 { "sxtab16", 0xe6800070, 7, ARM_EXT_V6
, do_sxtah
},
1374 { "sxtab", 0xe6a00070, 5, ARM_EXT_V6
, do_sxtah
},
1375 { "sxth", 0xe6bf0070, 4, ARM_EXT_V6
, do_sxth
},
1376 { "sxtb16", 0xe68f0070, 6, ARM_EXT_V6
, do_sxth
},
1377 { "sxtb", 0xe6af0070, 4, ARM_EXT_V6
, do_sxth
},
1378 { "uxtah", 0xe6f00070, 5, ARM_EXT_V6
, do_sxtah
},
1379 { "uxtab16", 0xe6c00070, 7, ARM_EXT_V6
, do_sxtah
},
1380 { "uxtab", 0xe6e00070, 5, ARM_EXT_V6
, do_sxtah
},
1381 { "uxth", 0xe6ff0070, 4, ARM_EXT_V6
, do_sxth
},
1382 { "uxtb16", 0xe6cf0070, 6, ARM_EXT_V6
, do_sxth
},
1383 { "uxtb", 0xe6ef0070, 4, ARM_EXT_V6
, do_sxth
},
1384 { "sel", 0xe68000b0, 3, ARM_EXT_V6
, do_qadd16
},
1385 { "setend", 0xf1010000, 0, ARM_EXT_V6
, do_setend
},
1386 { "smlad", 0xe7000010, 5, ARM_EXT_V6
, do_smlad
},
1387 { "smladx", 0xe7000030, 6, ARM_EXT_V6
, do_smlad
},
1388 { "smlald", 0xe7400010, 6, ARM_EXT_V6
, do_smlald
},
1389 { "smlaldx", 0xe7400030, 7, ARM_EXT_V6
, do_smlald
},
1390 { "smlsd", 0xe7000050, 5, ARM_EXT_V6
, do_smlad
},
1391 { "smlsdx", 0xe7000070, 6, ARM_EXT_V6
, do_smlad
},
1392 { "smlsld", 0xe7400050, 6, ARM_EXT_V6
, do_smlald
},
1393 { "smlsldx", 0xe7400070, 7, ARM_EXT_V6
, do_smlald
},
1394 { "smmla", 0xe7500010, 5, ARM_EXT_V6
, do_smlad
},
1395 { "smmlar", 0xe7500030, 6, ARM_EXT_V6
, do_smlad
},
1396 { "smmls", 0xe75000d0, 5, ARM_EXT_V6
, do_smlad
},
1397 { "smmlsr", 0xe75000f0, 6, ARM_EXT_V6
, do_smlad
},
1398 { "smmul", 0xe750f010, 5, ARM_EXT_V6
, do_smmul
},
1399 { "smmulr", 0xe750f030, 6, ARM_EXT_V6
, do_smmul
},
1400 { "smuad", 0xe700f010, 5, ARM_EXT_V6
, do_smmul
},
1401 { "smuadx", 0xe700f030, 6, ARM_EXT_V6
, do_smmul
},
1402 { "smusd", 0xe700f050, 5, ARM_EXT_V6
, do_smmul
},
1403 { "smusdx", 0xe700f070, 6, ARM_EXT_V6
, do_smmul
},
1404 { "srsia", 0xf8cd0500, 0, ARM_EXT_V6
, do_srs
},
1405 { "srsib", 0xf9cd0500, 0, ARM_EXT_V6
, do_srs
},
1406 { "srsda", 0xf84d0500, 0, ARM_EXT_V6
, do_srs
},
1407 { "srsdb", 0xf94d0500, 0, ARM_EXT_V6
, do_srs
},
1408 { "ssat", 0xe6a00010, 4, ARM_EXT_V6
, do_ssat
},
1409 { "ssat16", 0xe6a00f30, 6, ARM_EXT_V6
, do_ssat16
},
1410 { "strex", 0xe1800f90, 5, ARM_EXT_V6
, do_strex
},
1411 { "umaal", 0xe0400090, 5, ARM_EXT_V6
, do_umaal
},
1412 { "usad8", 0xe780f010, 5, ARM_EXT_V6
, do_smmul
},
1413 { "usada8", 0xe7800010, 6, ARM_EXT_V6
, do_smlad
},
1414 { "usat", 0xe6e00010, 4, ARM_EXT_V6
, do_usat
},
1415 { "usat16", 0xe6e00f30, 6, ARM_EXT_V6
, do_usat16
},
1417 /* Core FPA instruction set (V1). */
1418 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1419 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1420 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1421 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1423 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1424 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1425 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1426 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1428 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1429 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1430 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1431 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1433 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1434 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1435 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1436 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1437 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1438 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1439 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1440 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1441 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1442 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1443 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1444 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1446 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1447 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1448 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1449 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1450 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1451 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1452 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1453 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1454 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1455 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1456 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1457 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1459 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1460 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1461 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1462 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1463 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1464 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1465 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1466 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1467 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1468 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1469 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1470 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1472 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1473 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1474 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1475 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1476 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1477 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1478 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1479 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1480 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1481 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1482 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1483 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1485 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1486 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1487 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1488 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1489 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1490 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1491 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1492 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1493 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1494 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1495 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1496 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1498 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1499 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1500 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1501 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1502 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1503 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1504 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1505 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1506 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1507 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1508 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1509 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1511 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1512 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1513 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1514 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1515 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1516 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1517 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1518 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1519 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1520 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1521 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1522 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1524 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1525 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1526 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1527 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1528 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1529 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1530 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1531 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1532 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1533 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1534 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1535 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1537 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1538 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1539 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1540 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1541 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1542 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1543 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1544 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1545 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1546 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1547 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1548 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1550 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1551 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1552 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1553 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1554 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1555 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1556 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1557 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1558 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1559 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1560 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1561 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1563 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1564 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1565 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1566 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1567 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1568 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1569 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1570 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1571 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1572 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1573 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1574 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1576 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1577 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1578 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1579 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1580 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1581 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1582 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1583 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1584 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1585 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1586 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1587 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1589 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1590 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1591 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1592 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1593 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1594 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1595 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1596 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1597 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1598 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1599 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1600 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1602 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1603 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1604 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1605 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1606 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1607 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1608 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1609 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1610 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1611 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1612 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1613 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1615 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1616 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1617 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1618 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1619 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1620 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1621 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1622 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1623 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1624 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1625 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1626 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1628 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1629 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1630 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1631 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1632 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1633 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1634 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1635 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1636 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1637 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1638 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1639 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1641 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1642 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1643 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1644 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1645 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1646 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1647 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1648 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1649 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1650 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1651 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1652 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1654 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1655 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1656 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1657 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1658 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1659 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1660 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1661 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1662 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1663 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1664 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1665 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1667 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1668 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1669 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1670 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1671 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1672 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1673 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1674 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1675 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1676 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1677 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1678 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1680 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1681 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1682 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1683 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1684 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1685 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1686 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1687 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1688 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1689 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1690 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1691 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1693 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1694 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1695 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1696 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1697 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1698 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1699 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1700 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1701 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1702 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1703 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1704 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1706 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1707 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1708 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1709 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1710 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1711 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1712 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1713 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1714 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1715 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1716 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1717 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1719 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1720 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1721 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1722 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1723 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1724 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1725 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1726 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1727 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1728 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1729 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1730 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1732 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1733 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1734 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1735 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1736 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1737 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1738 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1739 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1740 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1741 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1742 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1743 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1745 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1746 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1747 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1748 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1749 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1750 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1751 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1752 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1753 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1754 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1755 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1756 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1758 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1759 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1760 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1761 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1762 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1763 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1764 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1765 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1766 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1767 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1768 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1769 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1771 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1772 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1773 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1774 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1775 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1776 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1777 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1778 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1779 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1780 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1781 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1782 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1784 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1785 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1786 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1787 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1788 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1789 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1790 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1791 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1792 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1793 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1794 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1795 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1797 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1798 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1799 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1800 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1801 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1802 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1803 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1804 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1805 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1806 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1807 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1808 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1810 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1811 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1812 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1813 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1814 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
1815 not be an optional suffix, but part of the instruction. To be
1816 compatible, we accept either. */
1817 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1818 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1820 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1821 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1822 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1823 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1824 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1825 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1826 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1827 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1828 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1829 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1830 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1831 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1833 /* The implementation of the FIX instruction is broken on some
1834 assemblers, in that it accepts a precision specifier as well as a
1835 rounding specifier, despite the fact that this is meaningless.
1836 To be more compatible, we accept it as well, though of course it
1837 does not set any bits. */
1838 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1839 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1840 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1841 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1842 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1843 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1844 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1845 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1846 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1847 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1848 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1849 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1850 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1852 /* Instructions that were new with the real FPA, call them V2. */
1853 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1854 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1855 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1856 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1857 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1858 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1860 /* VFP V1xD (single precision). */
1861 /* Moves and type conversions. */
1862 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1863 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_reg_from_sp
},
1864 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_from_reg
},
1865 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD
, do_empty
},
1866 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1867 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1868 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1869 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1870 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1871 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1872 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_reg_from_ctrl
},
1873 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_ctrl_from_reg
},
1875 /* Memory operations. */
1876 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldst
},
1877 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldst
},
1878 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1879 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1880 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1881 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1882 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1883 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1884 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1885 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1886 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1887 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1888 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1889 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1890 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1891 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1892 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1893 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1895 /* Monadic operations. */
1896 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1897 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1898 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1900 /* Dyadic operations. */
1901 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1902 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1903 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1904 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1905 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1906 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1907 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1908 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1909 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1912 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1913 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_compare_z
},
1914 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1915 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_compare_z
},
1917 /* VFP V1 (Double precision). */
1918 /* Moves and type conversions. */
1919 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1920 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
1921 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1922 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1
, do_vfp_dp_from_reg
},
1923 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1
, do_vfp_dp_from_reg
},
1924 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1
, do_vfp_reg_from_dp
},
1925 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1
, do_vfp_reg_from_dp
},
1926 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
1927 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
1928 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1929 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1930 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1931 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1933 /* Memory operations. */
1934 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1
, do_vfp_dp_ldst
},
1935 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1
, do_vfp_dp_ldst
},
1936 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1937 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1938 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1939 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1940 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1941 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1942 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1943 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1945 /* Monadic operations. */
1946 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1947 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1948 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1950 /* Dyadic operations. */
1951 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1952 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1953 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1954 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1955 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1956 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1957 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1958 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1959 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1962 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1963 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_compare_z
},
1964 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1965 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1
, do_vfp_dp_compare_z
},
1968 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2
, do_vfp_sp_reg2
},
1969 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2
, do_vfp_sp_reg2
},
1970 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2
, do_vfp_dp_from_reg2
},
1971 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2
, do_vfp_reg2_from_dp
},
1973 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
1974 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE
, do_xsc_mia
},
1975 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1976 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1977 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1978 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1979 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1980 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE
, do_xsc_mar
},
1981 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE
, do_xsc_mra
},
1983 /* Intel Wireless MMX technology instructions. */
1984 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
1985 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
1986 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
1987 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
1988 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
1989 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
1990 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
1991 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
1992 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
1993 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
1994 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
1995 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
1996 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
1997 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
1998 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
1999 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
2000 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
2001 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
2002 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmcr
},
2003 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_tmcrr
},
2004 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
2005 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
2006 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
2007 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
2008 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
2009 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
2010 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
2011 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
2012 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
2013 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmrc
},
2014 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_tmrrc
},
2015 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
2016 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
2017 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
2018 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2019 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2020 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2021 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2022 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2023 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2024 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2025 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2026 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2027 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2028 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2029 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2030 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_waligni
},
2031 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2032 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2033 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2034 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2035 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2036 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2037 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2038 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2039 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2040 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2041 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2042 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2043 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2044 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2045 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2046 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2047 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2048 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2049 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2050 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
2051 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
2052 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
2053 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
2054 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2055 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2056 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2057 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2058 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2059 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2060 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2061 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2062 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2063 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2064 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2065 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2066 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2067 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2068 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2069 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2070 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2071 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2072 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wmov
},
2073 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2074 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2075 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2076 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2077 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2078 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2079 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2080 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2081 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2082 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2083 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2084 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2085 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2086 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2087 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2088 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2089 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2090 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2091 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2092 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2093 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2094 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wshufh
},
2095 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2096 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2097 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2098 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2099 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2100 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2101 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2102 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2103 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2104 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2105 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2106 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2107 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2108 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2109 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2110 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2111 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2112 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2113 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
2114 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
2115 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
2116 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
2117 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2118 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2119 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2120 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2121 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2122 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2123 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2124 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2125 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2126 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2127 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2128 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2129 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2130 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2131 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2132 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2133 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2134 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2135 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2136 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2137 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2138 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2139 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2140 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2141 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2142 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2143 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2144 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2145 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wzero
},
2147 /* Cirrus Maverick instructions. */
2148 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_1
},
2149 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_2
},
2150 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_3
},
2151 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_4
},
2152 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_1
},
2153 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_2
},
2154 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_3
},
2155 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_4
},
2156 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK
, do_mav_binops_2a
},
2157 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1a
},
2158 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK
, do_mav_binops_2b
},
2159 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1b
},
2160 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK
, do_mav_binops_2b
},
2161 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1b
},
2162 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK
, do_mav_binops_2c
},
2163 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1c
},
2164 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK
, do_mav_binops_2c
},
2165 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1c
},
2166 {"cfmval32", 0xee100610, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
2167 {"cfmv32al", 0xee000610, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
2168 {"cfmvam32", 0xee100630, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
2169 {"cfmv32am", 0xee000630, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
2170 {"cfmvah32", 0xee100650, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
2171 {"cfmv32ah", 0xee000650, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
2172 {"cfmva32", 0xee100670, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
2173 {"cfmv32a", 0xee000670, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
2174 {"cfmva64", 0xee100690, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3c
},
2175 {"cfmv64a", 0xee000690, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3d
},
2176 {"cfmvsc32", 0xee1006b0, 8, ARM_CEXT_MAVERICK
, do_mav_dspsc_1
},
2177 {"cfmv32sc", 0xee0006b0, 8, ARM_CEXT_MAVERICK
, do_mav_dspsc_2
},
2178 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
2179 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
2180 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1f
},
2181 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1g
},
2182 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1h
},
2183 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1i
},
2184 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1j
},
2185 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1k
},
2186 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1l
},
2187 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1m
},
2188 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK
, do_mav_binops_1l
},
2189 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK
, do_mav_binops_1m
},
2190 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK
, do_mav_triple_4a
},
2191 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK
, do_mav_triple_4b
},
2192 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK
, do_mav_shift_1
},
2193 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK
, do_mav_shift_2
},
2194 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5a
},
2195 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5b
},
2196 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5c
},
2197 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5d
},
2198 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
2199 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
2200 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
2201 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
2202 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
2203 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
2204 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
2205 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
2206 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
2207 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
2208 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1n
},
2209 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1o
},
2210 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1n
},
2211 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1o
},
2212 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2213 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
2214 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2215 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
2216 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2217 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
2218 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2219 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2220 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK
, do_mav_quad_6a
},
2221 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK
, do_mav_quad_6a
},
2222 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK
, do_mav_quad_6b
},
2223 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK
, do_mav_quad_6b
},
2226 /* Defines for various bits that we will want to toggle. */
2227 #define INST_IMMEDIATE 0x02000000
2228 #define OFFSET_REG 0x02000000
2229 #define HWOFFSET_IMM 0x00400000
2230 #define SHIFT_BY_REG 0x00000010
2231 #define PRE_INDEX 0x01000000
2232 #define INDEX_UP 0x00800000
2233 #define WRITE_BACK 0x00200000
2234 #define LDM_TYPE_2_OR_3 0x00400000
2236 #define LITERAL_MASK 0xf000f000
2237 #define OPCODE_MASK 0xfe1fffff
2238 #define V4_STR_BIT 0x00000020
2240 #define DATA_OP_SHIFT 21
2242 /* Codes to distinguish the arithmetic instructions. */
2243 #define OPCODE_AND 0
2244 #define OPCODE_EOR 1
2245 #define OPCODE_SUB 2
2246 #define OPCODE_RSB 3
2247 #define OPCODE_ADD 4
2248 #define OPCODE_ADC 5
2249 #define OPCODE_SBC 6
2250 #define OPCODE_RSC 7
2251 #define OPCODE_TST 8
2252 #define OPCODE_TEQ 9
2253 #define OPCODE_CMP 10
2254 #define OPCODE_CMN 11
2255 #define OPCODE_ORR 12
2256 #define OPCODE_MOV 13
2257 #define OPCODE_BIC 14
2258 #define OPCODE_MVN 15
2260 /* Thumb v1 (ARMv4T). */
2261 static void do_t_nop
PARAMS ((char *));
2262 static void do_t_arit
PARAMS ((char *));
2263 static void do_t_add
PARAMS ((char *));
2264 static void do_t_asr
PARAMS ((char *));
2265 static void do_t_branch9
PARAMS ((char *));
2266 static void do_t_branch12
PARAMS ((char *));
2267 static void do_t_branch23
PARAMS ((char *));
2268 static void do_t_bx
PARAMS ((char *));
2269 static void do_t_compare
PARAMS ((char *));
2270 static void do_t_ldmstm
PARAMS ((char *));
2271 static void do_t_ldr
PARAMS ((char *));
2272 static void do_t_ldrb
PARAMS ((char *));
2273 static void do_t_ldrh
PARAMS ((char *));
2274 static void do_t_lds
PARAMS ((char *));
2275 static void do_t_lsl
PARAMS ((char *));
2276 static void do_t_lsr
PARAMS ((char *));
2277 static void do_t_mov
PARAMS ((char *));
2278 static void do_t_push_pop
PARAMS ((char *));
2279 static void do_t_str
PARAMS ((char *));
2280 static void do_t_strb
PARAMS ((char *));
2281 static void do_t_strh
PARAMS ((char *));
2282 static void do_t_sub
PARAMS ((char *));
2283 static void do_t_swi
PARAMS ((char *));
2284 static void do_t_adr
PARAMS ((char *));
2286 /* Thumb v2 (ARMv5T). */
2287 static void do_t_blx
PARAMS ((char *));
2288 static void do_t_bkpt
PARAMS ((char *));
2291 static void do_t_cps
PARAMS ((char *));
2292 static void do_t_cpy
PARAMS ((char *));
2293 static void do_t_setend
PARAMS ((char *));;
2295 #define T_OPCODE_MUL 0x4340
2296 #define T_OPCODE_TST 0x4200
2297 #define T_OPCODE_CMN 0x42c0
2298 #define T_OPCODE_NEG 0x4240
2299 #define T_OPCODE_MVN 0x43c0
2301 #define T_OPCODE_ADD_R3 0x1800
2302 #define T_OPCODE_SUB_R3 0x1a00
2303 #define T_OPCODE_ADD_HI 0x4400
2304 #define T_OPCODE_ADD_ST 0xb000
2305 #define T_OPCODE_SUB_ST 0xb080
2306 #define T_OPCODE_ADD_SP 0xa800
2307 #define T_OPCODE_ADD_PC 0xa000
2308 #define T_OPCODE_ADD_I8 0x3000
2309 #define T_OPCODE_SUB_I8 0x3800
2310 #define T_OPCODE_ADD_I3 0x1c00
2311 #define T_OPCODE_SUB_I3 0x1e00
2313 #define T_OPCODE_ASR_R 0x4100
2314 #define T_OPCODE_LSL_R 0x4080
2315 #define T_OPCODE_LSR_R 0x40c0
2316 #define T_OPCODE_ASR_I 0x1000
2317 #define T_OPCODE_LSL_I 0x0000
2318 #define T_OPCODE_LSR_I 0x0800
2320 #define T_OPCODE_MOV_I8 0x2000
2321 #define T_OPCODE_CMP_I8 0x2800
2322 #define T_OPCODE_CMP_LR 0x4280
2323 #define T_OPCODE_MOV_HR 0x4600
2324 #define T_OPCODE_CMP_HR 0x4500
2326 #define T_OPCODE_LDR_PC 0x4800
2327 #define T_OPCODE_LDR_SP 0x9800
2328 #define T_OPCODE_STR_SP 0x9000
2329 #define T_OPCODE_LDR_IW 0x6800
2330 #define T_OPCODE_STR_IW 0x6000
2331 #define T_OPCODE_LDR_IH 0x8800
2332 #define T_OPCODE_STR_IH 0x8000
2333 #define T_OPCODE_LDR_IB 0x7800
2334 #define T_OPCODE_STR_IB 0x7000
2335 #define T_OPCODE_LDR_RW 0x5800
2336 #define T_OPCODE_STR_RW 0x5000
2337 #define T_OPCODE_LDR_RH 0x5a00
2338 #define T_OPCODE_STR_RH 0x5200
2339 #define T_OPCODE_LDR_RB 0x5c00
2340 #define T_OPCODE_STR_RB 0x5400
2342 #define T_OPCODE_PUSH 0xb400
2343 #define T_OPCODE_POP 0xbc00
2345 #define T_OPCODE_BRANCH 0xe7fe
2347 static int thumb_reg
PARAMS ((char ** str
, int hi_lo
));
2349 #define THUMB_SIZE 2 /* Size of thumb instruction. */
2350 #define THUMB_REG_LO 0x1
2351 #define THUMB_REG_HI 0x2
2352 #define THUMB_REG_ANY 0x3
2354 #define THUMB_H1 0x0080
2355 #define THUMB_H2 0x0040
2361 #define THUMB_MOVE 0
2362 #define THUMB_COMPARE 1
2365 #define THUMB_LOAD 0
2366 #define THUMB_STORE 1
2368 #define THUMB_PP_PC_LR 0x0100
2370 /* These three are used for immediate shifts, do not alter. */
2371 #define THUMB_WORD 2
2372 #define THUMB_HALFWORD 1
2373 #define THUMB_BYTE 0
2377 /* Basic string to match. */
2378 const char * template;
2380 /* Basic instruction code. */
2381 unsigned long value
;
2385 /* Which CPU variants this exists for. */
2386 unsigned long variant
;
2388 /* Function to call to parse args. */
2389 void (* parms
) PARAMS ((char *));
2392 static const struct thumb_opcode tinsns
[] =
2394 /* Thumb v1 (ARMv4T). */
2395 {"adc", 0x4140, 2, ARM_EXT_V4T
, do_t_arit
},
2396 {"add", 0x0000, 2, ARM_EXT_V4T
, do_t_add
},
2397 {"and", 0x4000, 2, ARM_EXT_V4T
, do_t_arit
},
2398 {"asr", 0x0000, 2, ARM_EXT_V4T
, do_t_asr
},
2399 {"b", T_OPCODE_BRANCH
, 2, ARM_EXT_V4T
, do_t_branch12
},
2400 {"beq", 0xd0fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2401 {"bne", 0xd1fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2402 {"bcs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2403 {"bhs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2404 {"bcc", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2405 {"bul", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2406 {"blo", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2407 {"bmi", 0xd4fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2408 {"bpl", 0xd5fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2409 {"bvs", 0xd6fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2410 {"bvc", 0xd7fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2411 {"bhi", 0xd8fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2412 {"bls", 0xd9fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2413 {"bge", 0xdafe, 2, ARM_EXT_V4T
, do_t_branch9
},
2414 {"blt", 0xdbfe, 2, ARM_EXT_V4T
, do_t_branch9
},
2415 {"bgt", 0xdcfe, 2, ARM_EXT_V4T
, do_t_branch9
},
2416 {"ble", 0xddfe, 2, ARM_EXT_V4T
, do_t_branch9
},
2417 {"bal", 0xdefe, 2, ARM_EXT_V4T
, do_t_branch9
},
2418 {"bic", 0x4380, 2, ARM_EXT_V4T
, do_t_arit
},
2419 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T
, do_t_branch23
},
2420 {"bx", 0x4700, 2, ARM_EXT_V4T
, do_t_bx
},
2421 {"cmn", T_OPCODE_CMN
, 2, ARM_EXT_V4T
, do_t_arit
},
2422 {"cmp", 0x0000, 2, ARM_EXT_V4T
, do_t_compare
},
2423 {"eor", 0x4040, 2, ARM_EXT_V4T
, do_t_arit
},
2424 {"ldmia", 0xc800, 2, ARM_EXT_V4T
, do_t_ldmstm
},
2425 {"ldr", 0x0000, 2, ARM_EXT_V4T
, do_t_ldr
},
2426 {"ldrb", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrb
},
2427 {"ldrh", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrh
},
2428 {"ldrsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
2429 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
2430 {"ldsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
2431 {"ldsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
2432 {"lsl", 0x0000, 2, ARM_EXT_V4T
, do_t_lsl
},
2433 {"lsr", 0x0000, 2, ARM_EXT_V4T
, do_t_lsr
},
2434 {"mov", 0x0000, 2, ARM_EXT_V4T
, do_t_mov
},
2435 {"mul", T_OPCODE_MUL
, 2, ARM_EXT_V4T
, do_t_arit
},
2436 {"mvn", T_OPCODE_MVN
, 2, ARM_EXT_V4T
, do_t_arit
},
2437 {"neg", T_OPCODE_NEG
, 2, ARM_EXT_V4T
, do_t_arit
},
2438 {"orr", 0x4300, 2, ARM_EXT_V4T
, do_t_arit
},
2439 {"pop", 0xbc00, 2, ARM_EXT_V4T
, do_t_push_pop
},
2440 {"push", 0xb400, 2, ARM_EXT_V4T
, do_t_push_pop
},
2441 {"ror", 0x41c0, 2, ARM_EXT_V4T
, do_t_arit
},
2442 {"sbc", 0x4180, 2, ARM_EXT_V4T
, do_t_arit
},
2443 {"stmia", 0xc000, 2, ARM_EXT_V4T
, do_t_ldmstm
},
2444 {"str", 0x0000, 2, ARM_EXT_V4T
, do_t_str
},
2445 {"strb", 0x0000, 2, ARM_EXT_V4T
, do_t_strb
},
2446 {"strh", 0x0000, 2, ARM_EXT_V4T
, do_t_strh
},
2447 {"swi", 0xdf00, 2, ARM_EXT_V4T
, do_t_swi
},
2448 {"sub", 0x0000, 2, ARM_EXT_V4T
, do_t_sub
},
2449 {"tst", T_OPCODE_TST
, 2, ARM_EXT_V4T
, do_t_arit
},
2451 {"adr", 0x0000, 2, ARM_EXT_V4T
, do_t_adr
},
2452 {"nop", 0x46C0, 2, ARM_EXT_V4T
, do_t_nop
}, /* mov r8,r8 */
2453 /* Thumb v2 (ARMv5T). */
2454 {"blx", 0, 0, ARM_EXT_V5T
, do_t_blx
},
2455 {"bkpt", 0xbe00, 2, ARM_EXT_V5T
, do_t_bkpt
},
2458 {"cpsie", 0xb660, 2, ARM_EXT_V6
, do_t_cps
},
2459 {"cpsid", 0xb670, 2, ARM_EXT_V6
, do_t_cps
},
2460 {"cpy", 0x4600, 2, ARM_EXT_V6
, do_t_cpy
},
2461 {"rev", 0xba00, 2, ARM_EXT_V6
, do_t_arit
},
2462 {"rev16", 0xba40, 2, ARM_EXT_V6
, do_t_arit
},
2463 {"revsh", 0xbac0, 2, ARM_EXT_V6
, do_t_arit
},
2464 {"setend", 0xb650, 2, ARM_EXT_V6
, do_t_setend
},
2465 {"sxth", 0xb200, 2, ARM_EXT_V6
, do_t_arit
},
2466 {"sxtb", 0xb240, 2, ARM_EXT_V6
, do_t_arit
},
2467 {"uxth", 0xb280, 2, ARM_EXT_V6
, do_t_arit
},
2468 {"uxtb", 0xb2c0, 2, ARM_EXT_V6
, do_t_arit
},
2471 #define BAD_ARGS _("bad arguments to instruction")
2472 #define BAD_PC _("r15 not allowed here")
2473 #define BAD_COND _("instruction is not conditional")
2474 #define ERR_NO_ACCUM _("acc0 expected")
2476 static struct hash_control
* arm_ops_hsh
= NULL
;
2477 static struct hash_control
* arm_tops_hsh
= NULL
;
2478 static struct hash_control
* arm_cond_hsh
= NULL
;
2479 static struct hash_control
* arm_shift_hsh
= NULL
;
2480 static struct hash_control
* arm_psr_hsh
= NULL
;
2482 /* This table describes all the machine specific pseudo-ops the assembler
2483 has to support. The fields are:
2484 pseudo-op name without dot
2485 function to call to execute this pseudo-op
2486 Integer arg to pass to the function. */
2488 static void s_req
PARAMS ((int));
2489 static void s_unreq
PARAMS ((int));
2490 static void s_align
PARAMS ((int));
2491 static void s_bss
PARAMS ((int));
2492 static void s_even
PARAMS ((int));
2493 static void s_ltorg
PARAMS ((int));
2494 static void s_arm
PARAMS ((int));
2495 static void s_thumb
PARAMS ((int));
2496 static void s_code
PARAMS ((int));
2497 static void s_force_thumb
PARAMS ((int));
2498 static void s_thumb_func
PARAMS ((int));
2499 static void s_thumb_set
PARAMS ((int));
2501 static void s_arm_elf_cons
PARAMS ((int));
2504 static int my_get_expression
PARAMS ((expressionS
*, char **));
2506 const pseudo_typeS md_pseudo_table
[] =
2508 /* Never called because '.req' does not start a line. */
2509 { "req", s_req
, 0 },
2510 { "unreq", s_unreq
, 0 },
2511 { "bss", s_bss
, 0 },
2512 { "align", s_align
, 0 },
2513 { "arm", s_arm
, 0 },
2514 { "thumb", s_thumb
, 0 },
2515 { "code", s_code
, 0 },
2516 { "force_thumb", s_force_thumb
, 0 },
2517 { "thumb_func", s_thumb_func
, 0 },
2518 { "thumb_set", s_thumb_set
, 0 },
2519 { "even", s_even
, 0 },
2520 { "ltorg", s_ltorg
, 0 },
2521 { "pool", s_ltorg
, 0 },
2523 { "word", s_arm_elf_cons
, 4 },
2524 { "long", s_arm_elf_cons
, 4 },
2528 { "extend", float_cons
, 'x' },
2529 { "ldouble", float_cons
, 'x' },
2530 { "packed", float_cons
, 'p' },
2534 /* Other internal functions. */
2535 static int arm_parse_extension
PARAMS ((char *, int *));
2536 static int arm_parse_cpu
PARAMS ((char *));
2537 static int arm_parse_arch
PARAMS ((char *));
2538 static int arm_parse_fpu
PARAMS ((char *));
2539 #if 0 /* Suppressed - for now. */
2540 #if defined OBJ_COFF || defined OBJ_ELF
2541 static void arm_add_note
PARAMS ((const char *, const char *, unsigned int));
2545 /* Stuff needed to resolve the label ambiguity
2555 symbolS
* last_label_seen
;
2556 static int label_is_thumb_function_name
= FALSE
;
2558 /* Literal Pool stuff. */
2560 #define MAX_LITERAL_POOL_SIZE 1024
2562 /* Literal pool structure. Held on a per-section
2563 and per-sub-section basis. */
2564 typedef struct literal_pool
2566 expressionS literals
[MAX_LITERAL_POOL_SIZE
];
2567 unsigned int next_free_entry
;
2571 subsegT sub_section
;
2572 struct literal_pool
* next
;
2575 /* Pointer to a linked list of literal pools. */
2576 literal_pool
* list_of_pools
= NULL
;
2578 static literal_pool
* find_literal_pool
PARAMS ((void));
2579 static literal_pool
* find_or_make_literal_pool
PARAMS ((void));
2581 static literal_pool
*
2582 find_literal_pool ()
2584 literal_pool
* pool
;
2586 for (pool
= list_of_pools
; pool
!= NULL
; pool
= pool
->next
)
2588 if (pool
->section
== now_seg
2589 && pool
->sub_section
== now_subseg
)
2596 static literal_pool
*
2597 find_or_make_literal_pool ()
2599 /* Next literal pool ID number. */
2600 static unsigned int latest_pool_num
= 1;
2601 literal_pool
* pool
;
2603 pool
= find_literal_pool ();
2607 /* Create a new pool. */
2608 pool
= (literal_pool
*) xmalloc (sizeof (* pool
));
2612 pool
->next_free_entry
= 0;
2613 pool
->section
= now_seg
;
2614 pool
->sub_section
= now_subseg
;
2615 pool
->next
= list_of_pools
;
2616 pool
->symbol
= NULL
;
2618 /* Add it to the list. */
2619 list_of_pools
= pool
;
2622 /* New pools, and emptied pools, will have a NULL symbol. */
2623 if (pool
->symbol
== NULL
)
2625 pool
->symbol
= symbol_create (FAKE_LABEL_NAME
, undefined_section
,
2626 (valueT
) 0, &zero_address_frag
);
2627 pool
->id
= latest_pool_num
++;
2634 /* Add the literal in the global 'inst'
2635 structure to the relevent literal pool. */
2639 literal_pool
* pool
;
2642 pool
= find_or_make_literal_pool ();
2644 /* Check if this literal value is already in the pool. */
2645 for (entry
= 0; entry
< pool
->next_free_entry
; entry
++)
2647 if ((pool
->literals
[entry
].X_op
== inst
.reloc
.exp
.X_op
)
2648 && (inst
.reloc
.exp
.X_op
== O_constant
)
2649 && (pool
->literals
[entry
].X_add_number
2650 == inst
.reloc
.exp
.X_add_number
)
2651 && (pool
->literals
[entry
].X_unsigned
2652 == inst
.reloc
.exp
.X_unsigned
))
2655 if ((pool
->literals
[entry
].X_op
== inst
.reloc
.exp
.X_op
)
2656 && (inst
.reloc
.exp
.X_op
== O_symbol
)
2657 && (pool
->literals
[entry
].X_add_number
2658 == inst
.reloc
.exp
.X_add_number
)
2659 && (pool
->literals
[entry
].X_add_symbol
2660 == inst
.reloc
.exp
.X_add_symbol
)
2661 && (pool
->literals
[entry
].X_op_symbol
2662 == inst
.reloc
.exp
.X_op_symbol
))
2666 /* Do we need to create a new entry? */
2667 if (entry
== pool
->next_free_entry
)
2669 if (entry
>= MAX_LITERAL_POOL_SIZE
)
2671 inst
.error
= _("literal pool overflow");
2675 pool
->literals
[entry
] = inst
.reloc
.exp
;
2676 pool
->next_free_entry
+= 1;
2679 inst
.reloc
.exp
.X_op
= O_symbol
;
2680 inst
.reloc
.exp
.X_add_number
= ((int) entry
) * 4 - 8;
2681 inst
.reloc
.exp
.X_add_symbol
= pool
->symbol
;
2686 /* Can't use symbol_new here, so have to create a symbol and then at
2687 a later date assign it a value. Thats what these functions do. */
2690 symbol_locate (symbolP
, name
, segment
, valu
, frag
)
2692 const char * name
; /* It is copied, the caller can modify. */
2693 segT segment
; /* Segment identifier (SEG_<something>). */
2694 valueT valu
; /* Symbol value. */
2695 fragS
* frag
; /* Associated fragment. */
2697 unsigned int name_length
;
2698 char * preserved_copy_of_name
;
2700 name_length
= strlen (name
) + 1; /* +1 for \0. */
2701 obstack_grow (¬es
, name
, name_length
);
2702 preserved_copy_of_name
= obstack_finish (¬es
);
2703 #ifdef STRIP_UNDERSCORE
2704 if (preserved_copy_of_name
[0] == '_')
2705 preserved_copy_of_name
++;
2708 #ifdef tc_canonicalize_symbol_name
2709 preserved_copy_of_name
=
2710 tc_canonicalize_symbol_name (preserved_copy_of_name
);
2713 S_SET_NAME (symbolP
, preserved_copy_of_name
);
2715 S_SET_SEGMENT (symbolP
, segment
);
2716 S_SET_VALUE (symbolP
, valu
);
2717 symbol_clear_list_pointers (symbolP
);
2719 symbol_set_frag (symbolP
, frag
);
2721 /* Link to end of symbol chain. */
2723 extern int symbol_table_frozen
;
2724 if (symbol_table_frozen
)
2728 symbol_append (symbolP
, symbol_lastP
, & symbol_rootP
, & symbol_lastP
);
2730 obj_symbol_new_hook (symbolP
);
2732 #ifdef tc_symbol_new_hook
2733 tc_symbol_new_hook (symbolP
);
2737 verify_symbol_chain (symbol_rootP
, symbol_lastP
);
2738 #endif /* DEBUG_SYMS */
2741 /* Check that an immediate is valid.
2742 If so, convert it to the right format. */
2745 validate_immediate (val
)
2751 #define rotate_left(v, n) (v << n | v >> (32 - n))
2753 for (i
= 0; i
< 32; i
+= 2)
2754 if ((a
= rotate_left (val
, i
)) <= 0xff)
2755 return a
| (i
<< 7); /* 12-bit pack: [shift-cnt,const]. */
2760 /* Check to see if an immediate can be computed as two separate immediate
2761 values, added together. We already know that this value cannot be
2762 computed by just one ARM instruction. */
2765 validate_immediate_twopart (val
, highpart
)
2767 unsigned int * highpart
;
2772 for (i
= 0; i
< 32; i
+= 2)
2773 if (((a
= rotate_left (val
, i
)) & 0xff) != 0)
2779 * highpart
= (a
>> 8) | ((i
+ 24) << 7);
2781 else if (a
& 0xff0000)
2785 * highpart
= (a
>> 16) | ((i
+ 16) << 7);
2789 assert (a
& 0xff000000);
2790 * highpart
= (a
>> 24) | ((i
+ 8) << 7);
2793 return (a
& 0xff) | (i
<< 7);
2800 validate_offset_imm (val
, hwse
)
2804 if ((hwse
&& val
> 255) || val
> 4095)
2818 /* This code is to handle mapping symbols as defined in the ARM ELF spec.
2819 (This text is taken from version B-02 of the spec):
2821 4.4.7 Mapping and tagging symbols
2823 A section of an ARM ELF file can contain a mixture of ARM code,
2824 Thumb code, and data. There are inline transitions between code
2825 and data at literal pool boundaries. There can also be inline
2826 transitions between ARM code and Thumb code, for example in
2827 ARM-Thumb inter-working veneers. Linkers, machine-level
2828 debuggers, profiling tools, and disassembly tools need to map
2829 images accurately. For example, setting an ARM breakpoint on a
2830 Thumb location, or in a literal pool, can crash the program
2831 being debugged, ruining the debugging session.
2833 ARM ELF entities are mapped (see section 4.4.7.1 below) and
2834 tagged (see section 4.4.7.2 below) using local symbols (with
2835 binding STB_LOCAL). To assist consumers, mapping and tagging
2836 symbols should be collated first in the symbol table, before
2837 other symbols with binding STB_LOCAL.
2839 To allow properly collated mapping and tagging symbols to be
2840 skipped by consumers that have no interest in them, the first
2841 such symbol should have the name $m and its st_value field equal
2842 to the total number of mapping and tagging symbols (including
2843 the $m) in the symbol table.
2845 4.4.7.1 Mapping symbols
2847 $a Labels the first byte of a sequence of ARM instructions.
2848 Its type is STT_FUNC.
2850 $d Labels the first byte of a sequence of data items.
2851 Its type is STT_OBJECT.
2853 $t Labels the first byte of a sequence of Thumb instructions.
2854 Its type is STT_FUNC.
2856 This list of mapping symbols may be extended in the future.
2858 Section-relative mapping symbols
2860 Mapping symbols defined in a section define a sequence of
2861 half-open address intervals that cover the address range of the
2862 section. Each interval starts at the address defined by a
2863 mapping symbol, and continues up to, but not including, the
2864 address defined by the next (in address order) mapping symbol or
2865 the end of the section. A corollary is that there must be a
2866 mapping symbol defined at the beginning of each section.
2867 Consumers can ignore the size of a section-relative mapping
2868 symbol. Producers can set it to 0.
2870 Absolute mapping symbols
2872 Because of the need to crystallize a Thumb address with the
2873 Thumb-bit set, absolute symbol of type STT_FUNC (symbols of type
2874 STT_FUNC defined in section SHN_ABS) need to be mapped with $a
2877 The extent of a mapping symbol defined in SHN_ABS is [st_value,
2878 st_value + st_size), or [st_value, st_value + 1) if st_size = 0,
2879 where [x, y) denotes the half-open address range from x,
2880 inclusive, to y, exclusive.
2882 In the absence of a mapping symbol, a consumer can interpret a
2883 function symbol with an odd value as the Thumb code address
2884 obtained by clearing the least significant bit of the
2885 value. This interpretation is deprecated, and it may not work in
2888 Note - the Tagging symbols ($b, $f, $p $m) have been dropped from
2889 the EABI (which is still under development), so they are not
2890 implemented here. */
2893 mapping_state (enum mstate state
)
2895 static enum mstate mapstate
= MAP_DATA
;
2897 const char * symname
;
2900 if (mapstate
== state
)
2901 /* The mapping symbol has already been emitted.
2902 There is nothing else to do. */
2915 type
= BSF_FUNCTION
;
2919 type
= BSF_FUNCTION
;
2925 symbolP
= symbol_new (symname
, now_seg
, (valueT
) frag_now_fix (), frag_now
);
2926 symbol_table_insert (symbolP
);
2927 symbol_get_bfdsym (symbolP
)->flags
|= type
| BSF_LOCAL
;
2932 THUMB_SET_FUNC (symbolP
, 0);
2933 ARM_SET_THUMB (symbolP
, 0);
2934 ARM_SET_INTERWORK (symbolP
, support_interwork
);
2938 THUMB_SET_FUNC (symbolP
, 1);
2939 ARM_SET_THUMB (symbolP
, 1);
2940 ARM_SET_INTERWORK (symbolP
, support_interwork
);
2949 /* When we change sections we need to issue a new mapping symbol. */
2952 arm_elf_change_section (void)
2956 if (!SEG_NORMAL (now_seg
))
2959 flags
= bfd_get_section_flags (stdoutput
, now_seg
);
2961 /* We can ignore sections that only contain debug info. */
2962 if ((flags
& SEC_ALLOC
) == 0)
2965 if (flags
& SEC_CODE
)
2968 mapping_state (MAP_THUMB
);
2970 mapping_state (MAP_ARM
);
2973 /* This section does not contain code. Therefore it must contain data. */
2974 mapping_state (MAP_DATA
);
2977 #define mapping_state(a)
2978 #endif /* OBJ_ELF */
2983 int a ATTRIBUTE_UNUSED
;
2985 as_bad (_("invalid syntax for .req directive"));
2988 /* The .unreq directive deletes an alias which was previously defined
2989 by .req. For example:
2995 s_unreq (int a ATTRIBUTE_UNUSED
)
3000 skip_whitespace (input_line_pointer
);
3001 name
= input_line_pointer
;
3003 while (*input_line_pointer
!= 0
3004 && *input_line_pointer
!= ' '
3005 && *input_line_pointer
!= '\n')
3006 ++input_line_pointer
;
3008 saved_char
= *input_line_pointer
;
3009 *input_line_pointer
= 0;
3013 enum arm_reg_type req_type
= arm_reg_parse_any (name
);
3015 if (req_type
!= REG_TYPE_MAX
)
3017 char *temp_name
= name
;
3018 int req_no
= arm_reg_parse (&temp_name
, all_reg_maps
[req_type
].htab
);
3022 struct reg_entry
*req_entry
;
3024 /* Check to see if this alias is a builtin one. */
3025 req_entry
= hash_delete (all_reg_maps
[req_type
].htab
, name
);
3028 as_bad (_("unreq: missing hash entry for \"%s\""), name
);
3029 else if (req_entry
->builtin
)
3030 /* FIXME: We are deleting a built in register alias which
3031 points to a const data structure, so we only need to
3032 free up the memory used by the key in the hash table.
3033 Unfortunately we have not recorded this value, so this
3034 is a memory leak. */
3035 /* FIXME: Should we issue a warning message ? */
3039 /* Deleting a user defined alias. We need to free the
3040 key and the value, but fortunately the key is the same
3041 as the value->name field. */
3042 free ((char *) req_entry
->name
);
3047 as_bad (_(".unreq: unrecognized symbol \"%s\""), name
);
3050 as_bad (_(".unreq: unrecognized symbol \"%s\""), name
);
3053 as_bad (_("invalid syntax for .unreq directive"));
3055 *input_line_pointer
= saved_char
;
3056 demand_empty_rest_of_line ();
3061 int ignore ATTRIBUTE_UNUSED
;
3063 /* We don't support putting frags in the BSS segment, we fake it by
3064 marking in_bss, then looking at s_skip for clues. */
3065 subseg_set (bss_section
, 0);
3066 demand_empty_rest_of_line ();
3067 mapping_state (MAP_DATA
);
3072 int ignore ATTRIBUTE_UNUSED
;
3074 /* Never make frag if expect extra pass. */
3076 frag_align (1, 0, 0);
3078 record_alignment (now_seg
, 1);
3080 demand_empty_rest_of_line ();
3085 int ignored ATTRIBUTE_UNUSED
;
3088 literal_pool
* pool
;
3091 pool
= find_literal_pool ();
3093 || pool
->symbol
== NULL
3094 || pool
->next_free_entry
== 0)
3097 /* Align pool as you have word accesses.
3098 Only make a frag if we have to. */
3100 frag_align (2, 0, 0);
3102 record_alignment (now_seg
, 2);
3104 sprintf (sym_name
, "$$lit_\002%x", pool
->id
);
3106 symbol_locate (pool
->symbol
, sym_name
, now_seg
,
3107 (valueT
) frag_now_fix (), frag_now
);
3108 symbol_table_insert (pool
->symbol
);
3110 ARM_SET_THUMB (pool
->symbol
, thumb_mode
);
3112 #if defined OBJ_COFF || defined OBJ_ELF
3113 ARM_SET_INTERWORK (pool
->symbol
, support_interwork
);
3116 for (entry
= 0; entry
< pool
->next_free_entry
; entry
++)
3117 /* First output the expression in the instruction to the pool. */
3118 emit_expr (&(pool
->literals
[entry
]), 4); /* .word */
3120 /* Mark the pool as empty. */
3121 pool
->next_free_entry
= 0;
3122 pool
->symbol
= NULL
;
3125 /* Same as s_align_ptwo but align 0 => align 2. */
3129 int unused ATTRIBUTE_UNUSED
;
3132 register long temp_fill
;
3133 long max_alignment
= 15;
3135 temp
= get_absolute_expression ();
3136 if (temp
> max_alignment
)
3137 as_bad (_("alignment too large: %d assumed"), temp
= max_alignment
);
3140 as_bad (_("alignment negative. 0 assumed."));
3144 if (*input_line_pointer
== ',')
3146 input_line_pointer
++;
3147 temp_fill
= get_absolute_expression ();
3155 /* Only make a frag if we HAVE to. */
3156 if (temp
&& !need_pass_2
)
3157 frag_align (temp
, (int) temp_fill
, 0);
3158 demand_empty_rest_of_line ();
3160 record_alignment (now_seg
, temp
);
3164 s_force_thumb (ignore
)
3165 int ignore ATTRIBUTE_UNUSED
;
3167 /* If we are not already in thumb mode go into it, EVEN if
3168 the target processor does not support thumb instructions.
3169 This is used by gcc/config/arm/lib1funcs.asm for example
3170 to compile interworking support functions even if the
3171 target processor should not support interworking. */
3176 record_alignment (now_seg
, 1);
3179 demand_empty_rest_of_line ();
3183 s_thumb_func (ignore
)
3184 int ignore ATTRIBUTE_UNUSED
;
3189 /* The following label is the name/address of the start of a Thumb function.
3190 We need to know this for the interworking support. */
3191 label_is_thumb_function_name
= TRUE
;
3193 demand_empty_rest_of_line ();
3196 /* Perform a .set directive, but also mark the alias as
3197 being a thumb function. */
3203 /* XXX the following is a duplicate of the code for s_set() in read.c
3204 We cannot just call that code as we need to get at the symbol that
3206 register char * name
;
3207 register char delim
;
3208 register char * end_name
;
3209 register symbolS
* symbolP
;
3211 /* Especial apologies for the random logic:
3212 This just grew, and could be parsed much more simply!
3214 name
= input_line_pointer
;
3215 delim
= get_symbol_end ();
3216 end_name
= input_line_pointer
;
3221 if (*input_line_pointer
!= ',')
3224 as_bad (_("expected comma after name \"%s\""), name
);
3226 ignore_rest_of_line ();
3230 input_line_pointer
++;
3233 if (name
[0] == '.' && name
[1] == '\0')
3235 /* XXX - this should not happen to .thumb_set. */
3239 if ((symbolP
= symbol_find (name
)) == NULL
3240 && (symbolP
= md_undefined_symbol (name
)) == NULL
)
3243 /* When doing symbol listings, play games with dummy fragments living
3244 outside the normal fragment chain to record the file and line info
3246 if (listing
& LISTING_SYMBOLS
)
3248 extern struct list_info_struct
* listing_tail
;
3249 fragS
* dummy_frag
= (fragS
*) xmalloc (sizeof (fragS
));
3251 memset (dummy_frag
, 0, sizeof (fragS
));
3252 dummy_frag
->fr_type
= rs_fill
;
3253 dummy_frag
->line
= listing_tail
;
3254 symbolP
= symbol_new (name
, undefined_section
, 0, dummy_frag
);
3255 dummy_frag
->fr_symbol
= symbolP
;
3259 symbolP
= symbol_new (name
, undefined_section
, 0, &zero_address_frag
);
3262 /* "set" symbols are local unless otherwise specified. */
3263 SF_SET_LOCAL (symbolP
);
3264 #endif /* OBJ_COFF */
3265 } /* Make a new symbol. */
3267 symbol_table_insert (symbolP
);
3272 && S_IS_DEFINED (symbolP
)
3273 && S_GET_SEGMENT (symbolP
) != reg_section
)
3274 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP
));
3276 pseudo_set (symbolP
);
3278 demand_empty_rest_of_line ();
3280 /* XXX Now we come to the Thumb specific bit of code. */
3282 THUMB_SET_FUNC (symbolP
, 1);
3283 ARM_SET_THUMB (symbolP
, 1);
3284 #if defined OBJ_ELF || defined OBJ_COFF
3285 ARM_SET_INTERWORK (symbolP
, support_interwork
);
3290 opcode_select (width
)
3298 if (! (cpu_variant
& ARM_EXT_V4T
))
3299 as_bad (_("selected processor does not support THUMB opcodes"));
3302 /* No need to force the alignment, since we will have been
3303 coming from ARM mode, which is word-aligned. */
3304 record_alignment (now_seg
, 1);
3306 mapping_state (MAP_THUMB
);
3312 if ((cpu_variant
& ARM_ALL
) == ARM_EXT_V4T
)
3313 as_bad (_("selected processor does not support ARM opcodes"));
3318 frag_align (2, 0, 0);
3320 record_alignment (now_seg
, 1);
3322 mapping_state (MAP_ARM
);
3326 as_bad (_("invalid instruction size selected (%d)"), width
);
3332 int ignore ATTRIBUTE_UNUSED
;
3335 demand_empty_rest_of_line ();
3340 int ignore ATTRIBUTE_UNUSED
;
3343 demand_empty_rest_of_line ();
3348 int unused ATTRIBUTE_UNUSED
;
3352 temp
= get_absolute_expression ();
3357 opcode_select (temp
);
3361 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp
);
3369 skip_whitespace (str
);
3371 if (*str
!= '\0' && !inst
.error
)
3372 inst
.error
= _("garbage following instruction");
3376 skip_past_comma (str
)
3379 char * p
= * str
, c
;
3382 while ((c
= *p
) == ' ' || c
== ',')
3385 if (c
== ',' && comma
++)
3393 return comma
? SUCCESS
: FAIL
;
3396 /* A standard register must be given at this point.
3397 SHIFT is the place to put it in inst.instruction.
3398 Restores input start point on error.
3399 Returns the reg#, or FAIL. */
3402 reg_required_here (str
, shift
)
3406 static char buff
[128]; /* XXX */
3408 char * start
= * str
;
3410 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_RN
].htab
)) != FAIL
)
3413 inst
.instruction
|= reg
<< shift
;
3417 /* Restore the start point, we may have got a reg of the wrong class. */
3420 /* In the few cases where we might be able to accept something else
3421 this error can be overridden. */
3422 sprintf (buff
, _("register expected, not '%.100s'"), start
);
3428 /* A Intel Wireless MMX technology register
3429 must be given at this point.
3430 Shift is the place to put it in inst.instruction.
3431 Restores input start point on err.
3432 Returns the reg#, or FAIL. */
3435 wreg_required_here (str
, shift
, reg_type
)
3438 enum wreg_type reg_type
;
3440 static char buff
[128];
3442 char * start
= *str
;
3444 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_IWMMXT
].htab
)) != FAIL
)
3446 if (wr_register (reg
)
3447 && (reg_type
== IWMMXT_REG_WR
|| reg_type
== IWMMXT_REG_WR_OR_WC
))
3450 inst
.instruction
|= (reg
^ WR_PREFIX
) << shift
;
3453 else if (wc_register (reg
)
3454 && (reg_type
== IWMMXT_REG_WC
|| reg_type
== IWMMXT_REG_WR_OR_WC
))
3457 inst
.instruction
|= (reg
^ WC_PREFIX
) << shift
;
3460 else if ((wcg_register (reg
) && reg_type
== IWMMXT_REG_WCG
))
3463 inst
.instruction
|= ((reg
^ WC_PREFIX
) - 8) << shift
;
3468 /* Restore the start point, we may have got a reg of the wrong class. */
3471 /* In the few cases where we might be able to accept
3472 something else this error can be overridden. */
3473 sprintf (buff
, _("Intel Wireless MMX technology register expected, not '%.100s'"), start
);
3479 static const struct asm_psr
*
3481 register char ** ccp
;
3483 char * start
= * ccp
;
3486 const struct asm_psr
* psr
;
3490 /* Skip to the end of the next word in the input stream. */
3495 while (ISALPHA (c
) || c
== '_');
3497 /* Terminate the word. */
3500 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
3501 feature for ease of use and backwards compatibility. */
3502 if (!strncmp (start
, "cpsr", 4))
3503 strncpy (start
, "CPSR", 4);
3504 else if (!strncmp (start
, "spsr", 4))
3505 strncpy (start
, "SPSR", 4);
3507 /* Now locate the word in the psr hash table. */
3508 psr
= (const struct asm_psr
*) hash_find (arm_psr_hsh
, start
);
3510 /* Restore the input stream. */
3513 /* If we found a valid match, advance the
3514 stream pointer past the end of the word. */
3520 /* Parse the input looking for a PSR flag. */
3523 psr_required_here (str
)
3526 char * start
= * str
;
3527 const struct asm_psr
* psr
;
3529 psr
= arm_psr_parse (str
);
3533 /* If this is the SPSR that is being modified, set the R bit. */
3535 inst
.instruction
|= SPSR_BIT
;
3537 /* Set the psr flags in the MSR instruction. */
3538 inst
.instruction
|= psr
->field
<< PSR_SHIFT
;
3543 /* In the few cases where we might be able to accept
3544 something else this error can be overridden. */
3545 inst
.error
= _("flag for {c}psr instruction expected");
3547 /* Restore the start point. */
3553 co_proc_number (str
)
3556 int processor
, pchar
;
3559 skip_whitespace (*str
);
3562 /* The data sheet seems to imply that just a number on its own is valid
3563 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
3565 if ((processor
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CP
].htab
))
3571 if (pchar
>= '0' && pchar
<= '9')
3573 processor
= pchar
- '0';
3574 if (**str
>= '0' && **str
<= '9')
3576 processor
= processor
* 10 + *(*str
)++ - '0';
3579 inst
.error
= _("illegal co-processor number");
3586 inst
.error
= _("bad or missing co-processor number");
3591 inst
.instruction
|= processor
<< 8;
3596 cp_opc_expr (str
, where
, length
)
3603 skip_whitespace (* str
);
3605 memset (&expr
, '\0', sizeof (expr
));
3607 if (my_get_expression (&expr
, str
))
3609 if (expr
.X_op
!= O_constant
)
3611 inst
.error
= _("bad or missing expression");
3615 if ((expr
.X_add_number
& ((1 << length
) - 1)) != expr
.X_add_number
)
3617 inst
.error
= _("immediate co-processor expression too large");
3621 inst
.instruction
|= expr
.X_add_number
<< where
;
3626 cp_reg_required_here (str
, where
)
3631 char * start
= *str
;
3633 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CN
].htab
)) != FAIL
)
3635 inst
.instruction
|= reg
<< where
;
3639 /* In the few cases where we might be able to accept something else
3640 this error can be overridden. */
3641 inst
.error
= _("co-processor register expected");
3643 /* Restore the start point. */
3649 fp_reg_required_here (str
, where
)
3654 char * start
= * str
;
3656 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_FN
].htab
)) != FAIL
)
3658 inst
.instruction
|= reg
<< where
;
3662 /* In the few cases where we might be able to accept something else
3663 this error can be overridden. */
3664 inst
.error
= _("floating point register expected");
3666 /* Restore the start point. */
3672 cp_address_offset (str
)
3677 skip_whitespace (* str
);
3679 if (! is_immediate_prefix (**str
))
3681 inst
.error
= _("immediate expression expected");
3687 if (my_get_expression (& inst
.reloc
.exp
, str
))
3690 if (inst
.reloc
.exp
.X_op
== O_constant
)
3692 offset
= inst
.reloc
.exp
.X_add_number
;
3696 inst
.error
= _("co-processor address must be word aligned");
3700 if (offset
> 1023 || offset
< -1023)
3702 inst
.error
= _("offset too large");
3707 inst
.instruction
|= INDEX_UP
;
3711 inst
.instruction
|= offset
>> 2;
3714 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
3720 cp_address_required_here (str
, wb_ok
)
3733 skip_whitespace (p
);
3735 if ((reg
= reg_required_here (& p
, 16)) == FAIL
)
3738 skip_whitespace (p
);
3744 skip_whitespace (p
);
3748 /* As an extension to the official ARM syntax we allow:
3752 as a short hand for:
3755 inst
.instruction
|= PRE_INDEX
| INDEX_UP
;
3760 if (skip_past_comma (& p
) == FAIL
)
3762 inst
.error
= _("comma expected after closing square bracket");
3766 skip_whitespace (p
);
3773 write_back
= WRITE_BACK
;
3777 inst
.error
= _("pc may not be used in post-increment");
3781 if (cp_address_offset (& p
) == FAIL
)
3785 pre_inc
= PRE_INDEX
| INDEX_UP
;
3791 /* [Rn], {<expr>} */
3794 skip_whitespace (p
);
3796 if (my_get_expression (& inst
.reloc
.exp
, & p
))
3799 if (inst
.reloc
.exp
.X_op
== O_constant
)
3801 option
= inst
.reloc
.exp
.X_add_number
;
3803 if (option
> 255 || option
< 0)
3805 inst
.error
= _("'option' field too large");
3809 skip_whitespace (p
);
3813 inst
.error
= _("'}' expected at end of 'option' field");
3819 inst
.instruction
|= option
;
3820 inst
.instruction
|= INDEX_UP
;
3825 inst
.error
= _("non-constant expressions for 'option' field not supported");
3831 inst
.error
= _("# or { expected after comma");
3837 /* '['Rn, #expr']'[!] */
3839 if (skip_past_comma (& p
) == FAIL
)
3841 inst
.error
= _("pre-indexed expression expected");
3845 pre_inc
= PRE_INDEX
;
3847 if (cp_address_offset (& p
) == FAIL
)
3850 skip_whitespace (p
);
3854 inst
.error
= _("missing ]");
3858 skip_whitespace (p
);
3860 if (wb_ok
&& *p
== '!')
3864 inst
.error
= _("pc may not be used with write-back");
3869 write_back
= WRITE_BACK
;
3875 if (my_get_expression (&inst
.reloc
.exp
, &p
))
3878 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
3879 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
3880 inst
.reloc
.pc_rel
= 1;
3881 inst
.instruction
|= (REG_PC
<< 16);
3882 pre_inc
= PRE_INDEX
;
3885 inst
.instruction
|= write_back
| pre_inc
;
3891 cp_byte_address_offset (str
)
3896 skip_whitespace (* str
);
3898 if (! is_immediate_prefix (**str
))
3900 inst
.error
= _("immediate expression expected");
3906 if (my_get_expression (& inst
.reloc
.exp
, str
))
3909 if (inst
.reloc
.exp
.X_op
== O_constant
)
3911 offset
= inst
.reloc
.exp
.X_add_number
;
3913 if (offset
> 255 || offset
< -255)
3915 inst
.error
= _("offset too large");
3920 inst
.instruction
|= INDEX_UP
;
3924 inst
.instruction
|= offset
;
3927 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM_S2
;
3933 cp_byte_address_required_here (str
)
3945 skip_whitespace (p
);
3947 if ((reg
= reg_required_here (& p
, 16)) == FAIL
)
3950 skip_whitespace (p
);
3956 if (skip_past_comma (& p
) == SUCCESS
)
3959 write_back
= WRITE_BACK
;
3963 inst
.error
= _("pc may not be used in post-increment");
3967 if (cp_byte_address_offset (& p
) == FAIL
)
3971 pre_inc
= PRE_INDEX
| INDEX_UP
;
3975 /* '['Rn, #expr']'[!] */
3977 if (skip_past_comma (& p
) == FAIL
)
3979 inst
.error
= _("pre-indexed expression expected");
3983 pre_inc
= PRE_INDEX
;
3985 if (cp_byte_address_offset (& p
) == FAIL
)
3988 skip_whitespace (p
);
3992 inst
.error
= _("missing ]");
3996 skip_whitespace (p
);
4002 inst
.error
= _("pc may not be used with write-back");
4007 write_back
= WRITE_BACK
;
4013 if (my_get_expression (&inst
.reloc
.exp
, &p
))
4016 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM_S2
;
4017 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
4018 inst
.reloc
.pc_rel
= 1;
4019 inst
.instruction
|= (REG_PC
<< 16);
4020 pre_inc
= PRE_INDEX
;
4023 inst
.instruction
|= write_back
| pre_inc
;
4032 /* Do nothing really. */
4043 /* Only one syntax. */
4044 skip_whitespace (str
);
4046 if (reg_required_here (&str
, 12) == FAIL
)
4048 inst
.error
= BAD_ARGS
;
4052 if (skip_past_comma (&str
) == FAIL
)
4054 inst
.error
= _("comma expected after register name");
4058 skip_whitespace (str
);
4060 if ( strcmp (str
, "CPSR") == 0
4061 || strcmp (str
, "SPSR") == 0
4062 /* Lower case versions for backwards compatibility. */
4063 || strcmp (str
, "cpsr") == 0
4064 || strcmp (str
, "spsr") == 0)
4067 /* This is for backwards compatibility with older toolchains. */
4068 else if ( strcmp (str
, "cpsr_all") == 0
4069 || strcmp (str
, "spsr_all") == 0)
4073 inst
.error
= _("CPSR or SPSR expected");
4077 if (* str
== 's' || * str
== 'S')
4078 inst
.instruction
|= SPSR_BIT
;
4084 /* Two possible forms:
4085 "{C|S}PSR_<field>, Rm",
4086 "{C|S}PSR_f, #expression". */
4092 skip_whitespace (str
);
4094 if (psr_required_here (& str
) == FAIL
)
4097 if (skip_past_comma (& str
) == FAIL
)
4099 inst
.error
= _("comma missing after psr flags");
4103 skip_whitespace (str
);
4105 if (reg_required_here (& str
, 0) != FAIL
)
4112 if (! is_immediate_prefix (* str
))
4115 _("only a register or immediate value can follow a psr flag");
4122 if (my_get_expression (& inst
.reloc
.exp
, & str
))
4125 _("only a register or immediate value can follow a psr flag");
4129 #if 0 /* The first edition of the ARM architecture manual stated that
4130 writing anything other than the flags with an immediate operation
4131 had UNPREDICTABLE effects. This constraint was removed in the
4132 second edition of the specification. */
4133 if ((cpu_variant
& ARM_EXT_V5
) != ARM_EXT_V5
4134 && inst
.instruction
& ((PSR_c
| PSR_x
| PSR_s
) << PSR_SHIFT
))
4136 inst
.error
= _("immediate value cannot be used to set this field");
4141 inst
.instruction
|= INST_IMMEDIATE
;
4143 if (inst
.reloc
.exp
.X_add_symbol
)
4145 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
4146 inst
.reloc
.pc_rel
= 0;
4150 unsigned value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
4152 if (value
== (unsigned) FAIL
)
4154 inst
.error
= _("invalid constant");
4158 inst
.instruction
|= value
;
4165 /* Long Multiply Parser
4166 UMULL RdLo, RdHi, Rm, Rs
4167 SMULL RdLo, RdHi, Rm, Rs
4168 UMLAL RdLo, RdHi, Rm, Rs
4169 SMLAL RdLo, RdHi, Rm, Rs. */
4175 int rdlo
, rdhi
, rm
, rs
;
4177 /* Only one format "rdlo, rdhi, rm, rs". */
4178 skip_whitespace (str
);
4180 if ((rdlo
= reg_required_here (&str
, 12)) == FAIL
)
4182 inst
.error
= BAD_ARGS
;
4186 if (skip_past_comma (&str
) == FAIL
4187 || (rdhi
= reg_required_here (&str
, 16)) == FAIL
)
4189 inst
.error
= BAD_ARGS
;
4193 if (skip_past_comma (&str
) == FAIL
4194 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4196 inst
.error
= BAD_ARGS
;
4200 /* rdhi, rdlo and rm must all be different. */
4201 if (rdlo
== rdhi
|| rdlo
== rm
|| rdhi
== rm
)
4202 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
4204 if (skip_past_comma (&str
) == FAIL
4205 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
4207 inst
.error
= BAD_ARGS
;
4211 if (rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
)
4213 inst
.error
= BAD_PC
;
4227 /* Only one format "rd, rm, rs". */
4228 skip_whitespace (str
);
4230 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
4232 inst
.error
= BAD_ARGS
;
4238 inst
.error
= BAD_PC
;
4242 if (skip_past_comma (&str
) == FAIL
4243 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4245 inst
.error
= BAD_ARGS
;
4251 inst
.error
= BAD_PC
;
4256 as_tsktsk (_("rd and rm should be different in mul"));
4258 if (skip_past_comma (&str
) == FAIL
4259 || (rm
= reg_required_here (&str
, 8)) == FAIL
)
4261 inst
.error
= BAD_ARGS
;
4267 inst
.error
= BAD_PC
;
4281 /* Only one format "rd, rm, rs, rn". */
4282 skip_whitespace (str
);
4284 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
4286 inst
.error
= BAD_ARGS
;
4292 inst
.error
= BAD_PC
;
4296 if (skip_past_comma (&str
) == FAIL
4297 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4299 inst
.error
= BAD_ARGS
;
4305 inst
.error
= BAD_PC
;
4310 as_tsktsk (_("rd and rm should be different in mla"));
4312 if (skip_past_comma (&str
) == FAIL
4313 || (rd
= reg_required_here (&str
, 8)) == FAIL
4314 || skip_past_comma (&str
) == FAIL
4315 || (rm
= reg_required_here (&str
, 12)) == FAIL
)
4317 inst
.error
= BAD_ARGS
;
4321 if (rd
== REG_PC
|| rm
== REG_PC
)
4323 inst
.error
= BAD_PC
;
4331 /* Expects *str -> the characters "acc0", possibly with leading blanks.
4332 Advances *str to the next non-alphanumeric.
4333 Returns 0, or else FAIL (in which case sets inst.error).
4335 (In a future XScale, there may be accumulators other than zero.
4336 At that time this routine and its callers can be upgraded to suit.) */
4339 accum0_required_here (str
)
4342 static char buff
[128]; /* Note the address is taken. Hence, static. */
4345 int result
= 0; /* The accum number. */
4347 skip_whitespace (p
);
4349 *str
= p
; /* Advance caller's string pointer too. */
4354 *--p
= 0; /* Aap nul into input buffer at non-alnum. */
4356 if (! ( streq (*str
, "acc0") || streq (*str
, "ACC0")))
4358 sprintf (buff
, _("acc0 expected, not '%.100s'"), *str
);
4363 *p
= c
; /* Unzap. */
4364 *str
= p
; /* Caller's string pointer to after match. */
4368 /* Expects **str -> after a comma. May be leading blanks.
4369 Advances *str, recognizing a load mode, and setting inst.instruction.
4370 Returns rn, or else FAIL (in which case may set inst.error
4371 and not advance str)
4373 Note: doesn't know Rd, so no err checks that require such knowledge. */
4376 ld_mode_required_here (string
)
4379 char * str
= * string
;
4383 skip_whitespace (str
);
4389 skip_whitespace (str
);
4391 if ((rn
= reg_required_here (& str
, 16)) == FAIL
)
4394 skip_whitespace (str
);
4400 if (skip_past_comma (& str
) == SUCCESS
)
4402 /* [Rn],... (post inc) */
4403 if (ldst_extend_v4 (&str
) == FAIL
)
4408 skip_whitespace (str
);
4413 inst
.instruction
|= WRITE_BACK
;
4416 inst
.instruction
|= INDEX_UP
| HWOFFSET_IMM
;
4422 if (skip_past_comma (& str
) == FAIL
)
4424 inst
.error
= _("pre-indexed expression expected");
4430 if (ldst_extend_v4 (&str
) == FAIL
)
4433 skip_whitespace (str
);
4435 if (* str
++ != ']')
4437 inst
.error
= _("missing ]");
4441 skip_whitespace (str
);
4446 inst
.instruction
|= WRITE_BACK
;
4450 else if (* str
== '=') /* ldr's "r,=label" syntax */
4451 /* We should never reach here, because <text> = <expression> is
4452 caught gas/read.c read_a_source_file() as a .set operation. */
4454 else /* PC +- 8 bit immediate offset. */
4456 if (my_get_expression (& inst
.reloc
.exp
, & str
))
4459 inst
.instruction
|= HWOFFSET_IMM
; /* The I bit. */
4460 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
4461 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
4462 inst
.reloc
.pc_rel
= 1;
4463 inst
.instruction
|= (REG_PC
<< 16);
4469 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
4475 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
4476 SMLAxy{cond} Rd,Rm,Rs,Rn
4477 SMLAWy{cond} Rd,Rm,Rs,Rn
4478 Error if any register is R15. */
4486 skip_whitespace (str
);
4488 if ((rd
= reg_required_here (& str
, 16)) == FAIL
4489 || skip_past_comma (& str
) == FAIL
4490 || (rm
= reg_required_here (& str
, 0)) == FAIL
4491 || skip_past_comma (& str
) == FAIL
4492 || (rs
= reg_required_here (& str
, 8)) == FAIL
4493 || skip_past_comma (& str
) == FAIL
4494 || (rn
= reg_required_here (& str
, 12)) == FAIL
)
4495 inst
.error
= BAD_ARGS
;
4497 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
|| rn
== REG_PC
)
4498 inst
.error
= BAD_PC
;
4504 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
4505 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
4506 Error if any register is R15.
4507 Warning if Rdlo == Rdhi. */
4513 int rdlo
, rdhi
, rm
, rs
;
4515 skip_whitespace (str
);
4517 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
4518 || skip_past_comma (& str
) == FAIL
4519 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
4520 || skip_past_comma (& str
) == FAIL
4521 || (rm
= reg_required_here (& str
, 0)) == FAIL
4522 || skip_past_comma (& str
) == FAIL
4523 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
4525 inst
.error
= BAD_ARGS
;
4529 if (rdlo
== REG_PC
|| rdhi
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
4531 inst
.error
= BAD_PC
;
4536 as_tsktsk (_("rdhi and rdlo must be different"));
4541 /* ARM V5E (El Segundo) signed-multiply (argument parse)
4542 SMULxy{cond} Rd,Rm,Rs
4543 Error if any register is R15. */
4551 skip_whitespace (str
);
4553 if ((rd
= reg_required_here (& str
, 16)) == FAIL
4554 || skip_past_comma (& str
) == FAIL
4555 || (rm
= reg_required_here (& str
, 0)) == FAIL
4556 || skip_past_comma (& str
) == FAIL
4557 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
4558 inst
.error
= BAD_ARGS
;
4560 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
4561 inst
.error
= BAD_PC
;
4567 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
4568 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
4569 Error if any register is R15. */
4577 skip_whitespace (str
);
4579 if ((rd
= reg_required_here (& str
, 12)) == FAIL
4580 || skip_past_comma (& str
) == FAIL
4581 || (rm
= reg_required_here (& str
, 0)) == FAIL
4582 || skip_past_comma (& str
) == FAIL
4583 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
4584 inst
.error
= BAD_ARGS
;
4586 else if (rd
== REG_PC
|| rm
== REG_PC
|| rn
== REG_PC
)
4587 inst
.error
= BAD_PC
;
4593 /* ARM V5E (el Segundo)
4594 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4595 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4597 These are equivalent to the XScale instructions MAR and MRA,
4598 respectively, when coproc == 0, opcode == 0, and CRm == 0.
4600 Result unpredicatable if Rd or Rn is R15. */
4608 skip_whitespace (str
);
4610 if (co_proc_number (& str
) == FAIL
)
4613 inst
.error
= BAD_ARGS
;
4617 if (skip_past_comma (& str
) == FAIL
4618 || cp_opc_expr (& str
, 4, 4) == FAIL
)
4621 inst
.error
= BAD_ARGS
;
4625 if (skip_past_comma (& str
) == FAIL
4626 || (rd
= reg_required_here (& str
, 12)) == FAIL
)
4629 inst
.error
= BAD_ARGS
;
4633 if (skip_past_comma (& str
) == FAIL
4634 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
4637 inst
.error
= BAD_ARGS
;
4641 /* Unpredictable result if rd or rn is R15. */
4642 if (rd
== REG_PC
|| rn
== REG_PC
)
4644 (_("Warning: instruction unpredictable when using r15"));
4646 if (skip_past_comma (& str
) == FAIL
4647 || cp_reg_required_here (& str
, 0) == FAIL
)
4650 inst
.error
= BAD_ARGS
;
4657 /* ARM V5 count-leading-zeroes instruction (argument parse)
4658 CLZ{<cond>} <Rd>, <Rm>
4659 Condition defaults to COND_ALWAYS.
4660 Error if Rd or Rm are R15. */
4668 skip_whitespace (str
);
4670 if (((rd
= reg_required_here (& str
, 12)) == FAIL
)
4671 || (skip_past_comma (& str
) == FAIL
)
4672 || ((rm
= reg_required_here (& str
, 0)) == FAIL
))
4673 inst
.error
= BAD_ARGS
;
4675 else if (rd
== REG_PC
|| rm
== REG_PC
)
4676 inst
.error
= BAD_PC
;
4682 /* ARM V5 (argument parse)
4683 LDC2{L} <coproc>, <CRd>, <addressing mode>
4684 STC2{L} <coproc>, <CRd>, <addressing mode>
4685 Instruction is not conditional, and has 0xf in the condition field.
4686 Otherwise, it's the same as LDC/STC. */
4692 skip_whitespace (str
);
4694 if (co_proc_number (& str
) == FAIL
)
4697 inst
.error
= BAD_ARGS
;
4699 else if (skip_past_comma (& str
) == FAIL
4700 || cp_reg_required_here (& str
, 12) == FAIL
)
4703 inst
.error
= BAD_ARGS
;
4705 else if (skip_past_comma (& str
) == FAIL
4706 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
4709 inst
.error
= BAD_ARGS
;
4715 /* ARM V5 (argument parse)
4716 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
4717 Instruction is not conditional, and has 0xf in the condition field.
4718 Otherwise, it's the same as CDP. */
4724 skip_whitespace (str
);
4726 if (co_proc_number (& str
) == FAIL
)
4729 inst
.error
= BAD_ARGS
;
4733 if (skip_past_comma (& str
) == FAIL
4734 || cp_opc_expr (& str
, 20,4) == FAIL
)
4737 inst
.error
= BAD_ARGS
;
4741 if (skip_past_comma (& str
) == FAIL
4742 || cp_reg_required_here (& str
, 12) == FAIL
)
4745 inst
.error
= BAD_ARGS
;
4749 if (skip_past_comma (& str
) == FAIL
4750 || cp_reg_required_here (& str
, 16) == FAIL
)
4753 inst
.error
= BAD_ARGS
;
4757 if (skip_past_comma (& str
) == FAIL
4758 || cp_reg_required_here (& str
, 0) == FAIL
)
4761 inst
.error
= BAD_ARGS
;
4765 if (skip_past_comma (& str
) == SUCCESS
)
4767 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
4770 inst
.error
= BAD_ARGS
;
4778 /* ARM V5 (argument parse)
4779 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4780 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4781 Instruction is not conditional, and has 0xf in the condition field.
4782 Otherwise, it's the same as MCR/MRC. */
4788 skip_whitespace (str
);
4790 if (co_proc_number (& str
) == FAIL
)
4793 inst
.error
= BAD_ARGS
;
4797 if (skip_past_comma (& str
) == FAIL
4798 || cp_opc_expr (& str
, 21, 3) == FAIL
)
4801 inst
.error
= BAD_ARGS
;
4805 if (skip_past_comma (& str
) == FAIL
4806 || reg_required_here (& str
, 12) == FAIL
)
4809 inst
.error
= BAD_ARGS
;
4813 if (skip_past_comma (& str
) == FAIL
4814 || cp_reg_required_here (& str
, 16) == FAIL
)
4817 inst
.error
= BAD_ARGS
;
4821 if (skip_past_comma (& str
) == FAIL
4822 || cp_reg_required_here (& str
, 0) == FAIL
)
4825 inst
.error
= BAD_ARGS
;
4829 if (skip_past_comma (& str
) == SUCCESS
)
4831 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
4834 inst
.error
= BAD_ARGS
;
4842 /* ARM v5TEJ. Jump to Jazelle code. */
4849 skip_whitespace (str
);
4851 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
4853 inst
.error
= BAD_ARGS
;
4857 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
4859 as_tsktsk (_("use of r15 in bxj is not really useful"));
4864 /* ARM V6 umaal (argument parse). */
4871 int rdlo
, rdhi
, rm
, rs
;
4873 skip_whitespace (str
);
4874 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
4875 || skip_past_comma (& str
) == FAIL
4876 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
4877 || skip_past_comma (& str
) == FAIL
4878 || (rm
= reg_required_here (& str
, 0)) == FAIL
4879 || skip_past_comma (& str
) == FAIL
4880 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
4882 inst
.error
= BAD_ARGS
;
4886 if (rdlo
== REG_PC
|| rdhi
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
4888 inst
.error
= BAD_PC
;
4895 /* ARM V6 strex (argument parse). */
4903 /* Parse Rd, Rm,. */
4904 skip_whitespace (str
);
4905 if ((rd
= reg_required_here (& str
, 12)) == FAIL
4906 || skip_past_comma (& str
) == FAIL
4907 || (rm
= reg_required_here (& str
, 0)) == FAIL
4908 || skip_past_comma (& str
) == FAIL
)
4910 inst
.error
= BAD_ARGS
;
4913 if (rd
== REG_PC
|| rm
== REG_PC
)
4915 inst
.error
= BAD_PC
;
4920 inst
.error
= _("Rd equal to Rm or Rn yields unpredictable results");
4924 /* Skip past '['. */
4925 if ((strlen (str
) >= 1)
4926 && strncmp (str
, "[", 1) == 0)
4928 skip_whitespace (str
);
4931 if ((rn
= reg_required_here (& str
, 16)) == FAIL
)
4933 inst
.error
= BAD_ARGS
;
4936 else if (rn
== REG_PC
)
4938 inst
.error
= BAD_PC
;
4943 inst
.error
= _("Rd equal to Rm or Rn yields unpredictable results");
4946 skip_whitespace (str
);
4948 /* Skip past ']'. */
4949 if ((strlen (str
) >= 1)
4950 && strncmp (str
, "]", 1) == 0)
4956 /* ARM V6 ssat (argument parse). */
4962 do_sat (&str
, /*bias=*/-1);
4966 /* ARM V6 usat (argument parse). */
4972 do_sat (&str
, /*bias=*/0);
4984 skip_whitespace (*str
);
4986 /* Parse <Rd>, field. */
4987 if ((rd
= reg_required_here (str
, 12)) == FAIL
4988 || skip_past_comma (str
) == FAIL
)
4990 inst
.error
= BAD_ARGS
;
4995 inst
.error
= BAD_PC
;
4999 /* Parse #<immed>, field. */
5000 if (is_immediate_prefix (**str
))
5004 inst
.error
= _("immediate expression expected");
5007 if (my_get_expression (&expr
, str
))
5009 inst
.error
= _("bad expression");
5012 if (expr
.X_op
!= O_constant
)
5014 inst
.error
= _("constant expression expected");
5017 if (expr
.X_add_number
+ bias
< 0
5018 || expr
.X_add_number
+ bias
> 31)
5020 inst
.error
= _("immediate value out of range");
5023 inst
.instruction
|= (expr
.X_add_number
+ bias
) << 16;
5024 if (skip_past_comma (str
) == FAIL
)
5026 inst
.error
= BAD_ARGS
;
5030 /* Parse <Rm> field. */
5031 if ((rm
= reg_required_here (str
, 0)) == FAIL
)
5033 inst
.error
= BAD_ARGS
;
5038 inst
.error
= BAD_PC
;
5042 if (skip_past_comma (str
) == SUCCESS
)
5043 decode_shift (str
, SHIFT_LSL_OR_ASR_IMMEDIATE
);
5046 /* ARM V6 ssat16 (argument parse). */
5052 do_sat16 (&str
, /*bias=*/-1);
5060 do_sat16 (&str
, /*bias=*/0);
5065 do_sat16 (str
, bias
)
5072 skip_whitespace (*str
);
5074 /* Parse the <Rd> field. */
5075 if ((rd
= reg_required_here (str
, 12)) == FAIL
5076 || skip_past_comma (str
) == FAIL
)
5078 inst
.error
= BAD_ARGS
;
5083 inst
.error
= BAD_PC
;
5087 /* Parse #<immed>, field. */
5088 if (is_immediate_prefix (**str
))
5092 inst
.error
= _("immediate expression expected");
5095 if (my_get_expression (&expr
, str
))
5097 inst
.error
= _("bad expression");
5100 if (expr
.X_op
!= O_constant
)
5102 inst
.error
= _("constant expression expected");
5105 if (expr
.X_add_number
+ bias
< 0
5106 || expr
.X_add_number
+ bias
> 15)
5108 inst
.error
= _("immediate value out of range");
5111 inst
.instruction
|= (expr
.X_add_number
+ bias
) << 16;
5112 if (skip_past_comma (str
) == FAIL
)
5114 inst
.error
= BAD_ARGS
;
5118 /* Parse <Rm> field. */
5119 if ((rm
= reg_required_here (str
, 0)) == FAIL
)
5121 inst
.error
= BAD_ARGS
;
5126 inst
.error
= BAD_PC
;
5131 /* ARM V6 srs (argument parse). */
5138 skip_whitespace (str
);
5139 exclam
= strchr (str
, '!');
5147 inst
.instruction
|= WRITE_BACK
;
5153 /* ARM V6 SMMUL (argument parse). */
5161 skip_whitespace (str
);
5162 if ((rd
= reg_required_here (&str
, 16)) == FAIL
5163 || skip_past_comma (&str
) == FAIL
5164 || (rm
= reg_required_here (&str
, 0)) == FAIL
5165 || skip_past_comma (&str
) == FAIL
5166 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
5168 inst
.error
= BAD_ARGS
;
5176 inst
.error
= BAD_PC
;
5184 /* ARM V6 SMLALD (argument parse). */
5190 int rdlo
, rdhi
, rm
, rs
;
5191 skip_whitespace (str
);
5192 if ((rdlo
= reg_required_here (&str
, 12)) == FAIL
5193 || skip_past_comma (&str
) == FAIL
5194 || (rdhi
= reg_required_here (&str
, 16)) == FAIL
5195 || skip_past_comma (&str
) == FAIL
5196 || (rm
= reg_required_here (&str
, 0)) == FAIL
5197 || skip_past_comma (&str
) == FAIL
5198 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
5200 inst
.error
= BAD_ARGS
;
5209 inst
.error
= BAD_PC
;
5216 /* ARM V6 SMLAD (argument parse). Signed multiply accumulate dual.
5217 smlad{x}{<cond>} Rd, Rm, Rs, Rn */
5225 skip_whitespace (str
);
5226 if ((rd
= reg_required_here (&str
, 16)) == FAIL
5227 || skip_past_comma (&str
) == FAIL
5228 || (rm
= reg_required_here (&str
, 0)) == FAIL
5229 || skip_past_comma (&str
) == FAIL
5230 || (rs
= reg_required_here (&str
, 8)) == FAIL
5231 || skip_past_comma (&str
) == FAIL
5232 || (rn
= reg_required_here (&str
, 12)) == FAIL
)
5234 inst
.error
= BAD_ARGS
;
5243 inst
.error
= BAD_PC
;
5250 /* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
5251 preserving the other bits.
5253 setend <endian_specifier>, where <endian_specifier> is either
5260 if (do_endian_specifier (str
))
5261 inst
.instruction
|= 0x200;
5264 /* Returns true if the endian-specifier indicates big-endianness. */
5267 do_endian_specifier (str
)
5272 skip_whitespace (str
);
5273 if (strlen (str
) < 2)
5274 inst
.error
= _("missing endian specifier");
5275 else if (strncasecmp (str
, "BE", 2) == 0)
5280 else if (strncasecmp (str
, "LE", 2) == 0)
5283 inst
.error
= _("valid endian specifiers are be or le");
5292 SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
5293 Condition defaults to COND_ALWAYS.
5294 Error if any register uses R15. */
5302 int rotation_clear_mask
= 0xfffff3ff;
5303 int rotation_eight_mask
= 0x00000400;
5304 int rotation_sixteen_mask
= 0x00000800;
5305 int rotation_twenty_four_mask
= 0x00000c00;
5307 skip_whitespace (str
);
5308 if ((rd
= reg_required_here (&str
, 12)) == FAIL
5309 || skip_past_comma (&str
) == FAIL
5310 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
5312 inst
.error
= BAD_ARGS
;
5316 else if (rd
== REG_PC
|| rm
== REG_PC
)
5318 inst
.error
= BAD_PC
;
5322 /* Zero out the rotation field. */
5323 inst
.instruction
&= rotation_clear_mask
;
5325 /* Check for lack of optional rotation field. */
5326 if (skip_past_comma (&str
) == FAIL
)
5332 /* Move past 'ROR'. */
5333 skip_whitespace (str
);
5334 if (strncasecmp (str
, "ROR", 3) == 0)
5338 inst
.error
= _("missing rotation field after comma");
5342 /* Get the immediate constant. */
5343 skip_whitespace (str
);
5344 if (is_immediate_prefix (* str
))
5348 inst
.error
= _("immediate expression expected");
5352 if (my_get_expression (&expr
, &str
))
5354 inst
.error
= _("bad expression");
5358 if (expr
.X_op
!= O_constant
)
5360 inst
.error
= _("constant expression expected");
5364 switch (expr
.X_add_number
)
5367 /* Rotation field has already been zeroed. */
5370 inst
.instruction
|= rotation_eight_mask
;
5374 inst
.instruction
|= rotation_sixteen_mask
;
5378 inst
.instruction
|= rotation_twenty_four_mask
;
5382 inst
.error
= _("rotation can be 8, 16, 24 or 0 when field is ommited");
5390 /* ARM V6 SXTAH extracts a 16-bit value from a register, sign
5391 extends it to 32-bits, and adds the result to a value in another
5392 register. You can specify a rotation by 0, 8, 16, or 24 bits
5393 before extracting the 16-bit value.
5394 SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
5395 Condition defaults to COND_ALWAYS.
5396 Error if any register uses R15. */
5404 int rotation_clear_mask
= 0xfffff3ff;
5405 int rotation_eight_mask
= 0x00000400;
5406 int rotation_sixteen_mask
= 0x00000800;
5407 int rotation_twenty_four_mask
= 0x00000c00;
5409 skip_whitespace (str
);
5410 if ((rd
= reg_required_here (&str
, 12)) == FAIL
5411 || skip_past_comma (&str
) == FAIL
5412 || (rn
= reg_required_here (&str
, 16)) == FAIL
5413 || skip_past_comma (&str
) == FAIL
5414 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
5416 inst
.error
= BAD_ARGS
;
5420 else if (rd
== REG_PC
|| rn
== REG_PC
|| rm
== REG_PC
)
5422 inst
.error
= BAD_PC
;
5426 /* Zero out the rotation field. */
5427 inst
.instruction
&= rotation_clear_mask
;
5429 /* Check for lack of optional rotation field. */
5430 if (skip_past_comma (&str
) == FAIL
)
5436 /* Move past 'ROR'. */
5437 skip_whitespace (str
);
5438 if (strncasecmp (str
, "ROR", 3) == 0)
5442 inst
.error
= _("missing rotation field after comma");
5446 /* Get the immediate constant. */
5447 skip_whitespace (str
);
5448 if (is_immediate_prefix (* str
))
5452 inst
.error
= _("immediate expression expected");
5456 if (my_get_expression (&expr
, &str
))
5458 inst
.error
= _("bad expression");
5462 if (expr
.X_op
!= O_constant
)
5464 inst
.error
= _("constant expression expected");
5468 switch (expr
.X_add_number
)
5471 /* Rotation field has already been zeroed. */
5475 inst
.instruction
|= rotation_eight_mask
;
5479 inst
.instruction
|= rotation_sixteen_mask
;
5483 inst
.instruction
|= rotation_twenty_four_mask
;
5487 inst
.error
= _("rotation can be 8, 16, 24 or 0 when field is ommited");
5496 /* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
5497 word at the specified address and the following word
5499 Unconditionally executed.
5509 skip_whitespace (str
);
5511 if ((rn
= reg_required_here (&str
, 16)) == FAIL
)
5516 inst
.error
= BAD_PC
;
5520 skip_whitespace (str
);
5524 inst
.instruction
|= WRITE_BACK
;
5530 /* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
5531 register (argument parse).
5533 Condition defaults to COND_ALWAYS.
5534 Error if Rd or Rm are R15. */
5542 skip_whitespace (str
);
5544 if ((rd
= reg_required_here (&str
, 12)) == FAIL
5545 || skip_past_comma (&str
) == FAIL
5546 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
5547 inst
.error
= BAD_ARGS
;
5549 else if (rd
== REG_PC
|| rm
== REG_PC
)
5550 inst
.error
= BAD_PC
;
5556 /* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
5557 QADD16{<cond>} <Rd>, <Rn>, <Rm>
5558 Condition defaults to COND_ALWAYS.
5559 Error if Rd, Rn or Rm are R15. */
5567 skip_whitespace (str
);
5569 if ((rd
= reg_required_here (&str
, 12)) == FAIL
5570 || skip_past_comma (&str
) == FAIL
5571 || (rn
= reg_required_here (&str
, 16)) == FAIL
5572 || skip_past_comma (&str
) == FAIL
5573 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
5574 inst
.error
= BAD_ARGS
;
5576 else if (rd
== REG_PC
|| rm
== REG_PC
|| rn
== REG_PC
)
5577 inst
.error
= BAD_PC
;
5583 /* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
5584 PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
5585 Condition defaults to COND_ALWAYS.
5586 Error if Rd, Rn or Rm are R15. */
5592 do_pkh_core (str
, SHIFT_LSL_IMMEDIATE
);
5595 /* ARM V6 PKHTB (Argument Parse). */
5601 do_pkh_core (str
, SHIFT_ASR_IMMEDIATE
);
5605 do_pkh_core (str
, shift
)
5611 skip_whitespace (str
);
5612 if (((rd
= reg_required_here (&str
, 12)) == FAIL
)
5613 || (skip_past_comma (&str
) == FAIL
)
5614 || ((rn
= reg_required_here (&str
, 16)) == FAIL
)
5615 || (skip_past_comma (&str
) == FAIL
)
5616 || ((rm
= reg_required_here (&str
, 0)) == FAIL
))
5618 inst
.error
= BAD_ARGS
;
5622 else if (rd
== REG_PC
|| rn
== REG_PC
|| rm
== REG_PC
)
5624 inst
.error
= BAD_PC
;
5628 /* Check for optional shift immediate constant. */
5629 if (skip_past_comma (&str
) == FAIL
)
5631 if (shift
== SHIFT_ASR_IMMEDIATE
)
5633 /* If the shift specifier is ommited, turn the instruction
5634 into pkhbt rd, rm, rn. First, switch the instruction
5635 code, and clear the rn and rm fields. */
5636 inst
.instruction
&= 0xfff0f010;
5637 /* Now, re-encode the registers. */
5638 inst
.instruction
|= (rm
<< 16) | rn
;
5643 decode_shift (&str
, shift
);
5646 /* ARM V6 Load Register Exclusive instruction (argument parse).
5647 LDREX{<cond>} <Rd, [<Rn>]
5648 Condition defaults to COND_ALWAYS.
5649 Error if Rd or Rn are R15.
5650 See ARMARMv6 A4.1.27: LDREX. */
5659 skip_whitespace (str
);
5662 if (((rd
= reg_required_here (&str
, 12)) == FAIL
)
5663 || (skip_past_comma (&str
) == FAIL
))
5665 inst
.error
= BAD_ARGS
;
5668 else if (rd
== REG_PC
)
5670 inst
.error
= BAD_PC
;
5673 skip_whitespace (str
);
5675 /* Skip past '['. */
5676 if ((strlen (str
) >= 1)
5677 &&strncmp (str
, "[", 1) == 0)
5679 skip_whitespace (str
);
5682 if ((rn
= reg_required_here (&str
, 16)) == FAIL
)
5684 inst
.error
= BAD_ARGS
;
5687 else if (rn
== REG_PC
)
5689 inst
.error
= BAD_PC
;
5692 skip_whitespace (str
);
5694 /* Skip past ']'. */
5695 if ((strlen (str
) >= 1)
5696 && strncmp (str
, "]", 1) == 0)
5702 /* ARM V6 change processor state instruction (argument parse)
5703 CPS, CPSIE, CSPID . */
5717 do_cps_flags (&str
, /*thumb_p=*/0);
5719 if (skip_past_comma (&str
) == SUCCESS
)
5721 skip_whitespace (str
);
5733 skip_whitespace (*str
);
5735 if (! is_immediate_prefix (**str
))
5737 inst
.error
= _("immediate expression expected");
5741 (*str
)++; /* Strip off the immediate signifier. */
5742 if (my_get_expression (&expr
, str
))
5744 inst
.error
= _("bad expression");
5748 if (expr
.X_op
!= O_constant
)
5750 inst
.error
= _("constant expression expected");
5754 /* The mode is a 5 bit field. Valid values are 0-31. */
5755 if (((unsigned) expr
.X_add_number
) > 31
5756 || (inst
.reloc
.exp
.X_add_number
) < 0)
5758 inst
.error
= _("invalid constant");
5762 inst
.instruction
|= expr
.X_add_number
;
5767 do_cps_flags (str
, thumb_p
)
5773 unsigned long arm_value
;
5774 unsigned long thumb_value
;
5776 static struct cps_flag flag_table
[] = {
5784 skip_whitespace (*str
);
5786 /* Get the a, f and i flags. */
5787 while (**str
&& **str
!= ',')
5790 struct cps_flag
*q
= flag_table
+ sizeof (flag_table
)/sizeof (*p
);
5791 for (p
= flag_table
; p
< q
; ++p
)
5792 if (strncasecmp (*str
, &p
->character
, 1) == 0)
5794 inst
.instruction
|= (thumb_p
? p
->thumb_value
: p
->arm_value
);
5800 inst
.error
= _("unrecognized flag");
5806 inst
.error
= _("no 'a', 'i', or 'f' flags for 'cps'");
5809 /* THUMB V5 breakpoint instruction (argument parse)
5817 unsigned long number
;
5819 skip_whitespace (str
);
5821 /* Allow optional leading '#'. */
5822 if (is_immediate_prefix (*str
))
5825 memset (& expr
, '\0', sizeof (expr
));
5826 if (my_get_expression (& expr
, & str
)
5827 || (expr
.X_op
!= O_constant
5828 /* As a convenience we allow 'bkpt' without an operand. */
5829 && expr
.X_op
!= O_absent
))
5831 inst
.error
= _("bad expression");
5835 number
= expr
.X_add_number
;
5837 /* Check it fits an 8 bit unsigned. */
5838 if (number
!= (number
& 0xff))
5840 inst
.error
= _("immediate value out of range");
5844 inst
.instruction
|= number
;
5849 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
5850 Expects inst.instruction is set for BLX(1).
5851 Note: this is cloned from do_branch, and the reloc changed to be a
5852 new one that can cope with setting one extra bit (the H bit). */
5858 if (my_get_expression (& inst
.reloc
.exp
, & str
))
5865 /* ScottB: February 5, 1998 */
5866 /* Check to see of PLT32 reloc required for the instruction. */
5868 /* arm_parse_reloc() works on input_line_pointer.
5869 We actually want to parse the operands to the branch instruction
5870 passed in 'str'. Save the input pointer and restore it later. */
5871 save_in
= input_line_pointer
;
5872 input_line_pointer
= str
;
5874 if (inst
.reloc
.exp
.X_op
== O_symbol
5876 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
5878 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
5879 inst
.reloc
.pc_rel
= 0;
5880 /* Modify str to point to after parsed operands, otherwise
5881 end_of_line() will complain about the (PLT) left in str. */
5882 str
= input_line_pointer
;
5886 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
5887 inst
.reloc
.pc_rel
= 1;
5890 input_line_pointer
= save_in
;
5893 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
5894 inst
.reloc
.pc_rel
= 1;
5895 #endif /* OBJ_ELF */
5900 /* ARM V5 branch-link-exchange instruction (argument parse)
5901 BLX <target_addr> ie BLX(1)
5902 BLX{<condition>} <Rm> ie BLX(2)
5903 Unfortunately, there are two different opcodes for this mnemonic.
5904 So, the insns[].value is not used, and the code here zaps values
5905 into inst.instruction.
5906 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
5915 skip_whitespace (mystr
);
5916 rm
= reg_required_here (& mystr
, 0);
5918 /* The above may set inst.error. Ignore his opinion. */
5923 /* Arg is a register.
5924 Use the condition code our caller put in inst.instruction.
5925 Pass ourselves off as a BX with a funny opcode. */
5926 inst
.instruction
|= 0x012fff30;
5931 /* This must be is BLX <target address>, no condition allowed. */
5932 if (inst
.instruction
!= COND_ALWAYS
)
5934 inst
.error
= BAD_COND
;
5938 inst
.instruction
= 0xfafffffe;
5940 /* Process like a B/BL, but with a different reloc.
5941 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
5946 /* ARM V5 Thumb BLX (argument parse)
5947 BLX <target_addr> which is BLX(1)
5948 BLX <Rm> which is BLX(2)
5949 Unfortunately, there are two different opcodes for this mnemonic.
5950 So, the tinsns[].value is not used, and the code here zaps values
5951 into inst.instruction. */
5960 skip_whitespace (mystr
);
5961 inst
.instruction
= 0x4780;
5963 /* Note that this call is to the ARM register recognizer. BLX(2)
5964 uses the ARM register space, not the Thumb one, so a call to
5965 thumb_reg() would be wrong. */
5966 rm
= reg_required_here (& mystr
, 3);
5971 /* It's BLX(2). The .instruction was zapped with rm & is final. */
5976 /* No ARM register. This must be BLX(1). Change the .instruction. */
5977 inst
.instruction
= 0xf7ffeffe;
5980 if (my_get_expression (& inst
.reloc
.exp
, & mystr
))
5983 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BLX
;
5984 inst
.reloc
.pc_rel
= 1;
5987 end_of_line (mystr
);
5990 /* ARM V5 breakpoint instruction (argument parse)
5991 BKPT <16 bit unsigned immediate>
5992 Instruction is not conditional.
5993 The bit pattern given in insns[] has the COND_ALWAYS condition,
5994 and it is an error if the caller tried to override that. */
6001 unsigned long number
;
6003 skip_whitespace (str
);
6005 /* Allow optional leading '#'. */
6006 if (is_immediate_prefix (* str
))
6009 memset (& expr
, '\0', sizeof (expr
));
6011 if (my_get_expression (& expr
, & str
)
6012 || (expr
.X_op
!= O_constant
6013 /* As a convenience we allow 'bkpt' without an operand. */
6014 && expr
.X_op
!= O_absent
))
6016 inst
.error
= _("bad expression");
6020 number
= expr
.X_add_number
;
6022 /* Check it fits a 16 bit unsigned. */
6023 if (number
!= (number
& 0xffff))
6025 inst
.error
= _("immediate value out of range");
6029 /* Top 12 of 16 bits to bits 19:8. */
6030 inst
.instruction
|= (number
& 0xfff0) << 4;
6032 /* Bottom 4 of 16 bits to bits 3:0. */
6033 inst
.instruction
|= number
& 0xf;
6038 /* THUMB CPS instruction (argument parse). */
6044 do_cps_flags (&str
, /*thumb_p=*/1);
6048 /* THUMB CPY instruction (argument parse). */
6054 thumb_mov_compare (str
, THUMB_CPY
);
6057 /* THUMB SETEND instruction (argument parse). */
6063 if (do_endian_specifier (str
))
6064 inst
.instruction
|= 0x8;
6067 static unsigned long check_iwmmxt_insn
PARAMS ((char *, enum iwmmxt_insn_type
, int));
6069 /* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
6071 static unsigned long
6072 check_iwmmxt_insn (str
, insn_type
, immediate_size
)
6074 enum iwmmxt_insn_type insn_type
;
6078 const char * inst_error
;
6080 unsigned long number
;
6082 inst_error
= inst
.error
;
6084 inst
.error
= BAD_ARGS
;
6085 skip_whitespace (str
);
6090 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
6095 if ((wreg_required_here (&str
, 0, IWMMXT_REG_WR
)) == FAIL
)
6100 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
6101 || skip_past_comma (&str
) == FAIL
6102 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
))
6107 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
6108 || skip_past_comma (&str
) == FAIL
6109 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6110 || skip_past_comma (&str
) == FAIL
6111 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
))
6116 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
6117 || skip_past_comma (&str
) == FAIL
6118 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6119 || skip_past_comma (&str
) == FAIL
6120 || wreg_required_here (&str
, 0, IWMMXT_REG_WCG
) == FAIL
))
6125 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6126 || skip_past_comma (&str
) == FAIL
6127 || reg_required_here (&str
, 12) == FAIL
))
6132 if ((reg_required_here (&str
, 12) == FAIL
6133 || skip_past_comma (&str
) == FAIL
6134 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
))
6139 if ((wreg_required_here (&str
, 5, IWMMXT_REG_WR
) == FAIL
6140 || skip_past_comma (&str
) == FAIL
6141 || reg_required_here (&str
, 0) == FAIL
6142 || skip_past_comma (&str
) == FAIL
6143 || reg_required_here (&str
, 12) == FAIL
))
6148 if ((wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
6149 || skip_past_comma (&str
) == FAIL
6150 || reg_required_here (&str
, 12) == FAIL
6151 || skip_past_comma (&str
) == FAIL
6152 || reg_required_here (&str
, 16) == FAIL
))
6157 if ((reg_required_here (&str
, 12) == FAIL
6158 || skip_past_comma (&str
) == FAIL
6159 || reg_required_here (&str
, 16) == FAIL
6160 || skip_past_comma (&str
) == FAIL
6161 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
))
6166 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WC
) == FAIL
6167 || skip_past_comma (&str
) == FAIL
6168 || reg_required_here (&str
, 12) == FAIL
))
6173 if ((reg_required_here (&str
, 12) == FAIL
6174 || skip_past_comma (&str
) == FAIL
6175 || wreg_required_here (&str
, 16, IWMMXT_REG_WC
) == FAIL
))
6180 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6181 || skip_past_comma (&str
) == FAIL
6182 || reg_required_here (&str
, 12) == FAIL
6183 || skip_past_comma (&str
) == FAIL
))
6188 if ((reg_required_here (&str
, 12) == FAIL
6189 || skip_past_comma (&str
) == FAIL
))
6194 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
6195 || skip_past_comma (&str
) == FAIL
6196 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6197 || skip_past_comma (&str
) == FAIL
6198 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
6199 || skip_past_comma (&str
) == FAIL
))
6204 if ((reg_required_here (&str
, 12) == FAIL
6205 || skip_past_comma (&str
) == FAIL
6206 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6207 || skip_past_comma (&str
) == FAIL
))
6212 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
6213 || skip_past_comma (&str
) == FAIL
6214 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6215 || skip_past_comma (&str
) == FAIL
))
6220 if (immediate_size
== 0)
6223 inst
.error
= inst_error
;
6228 skip_whitespace (str
);
6230 /* Allow optional leading '#'. */
6231 if (is_immediate_prefix (* str
))
6234 memset (& expr
, '\0', sizeof (expr
));
6236 if (my_get_expression (& expr
, & str
) || (expr
.X_op
!= O_constant
))
6238 inst
.error
= _("bad or missing expression");
6242 number
= expr
.X_add_number
;
6244 if (number
!= (number
& immediate_size
))
6246 inst
.error
= _("immediate value out of range");
6250 inst
.error
= inst_error
;
6256 do_iwmmxt_byte_addr (str
)
6259 int op
= (inst
.instruction
& 0x300) >> 8;
6262 inst
.instruction
&= ~0x300;
6263 inst
.instruction
|= (op
& 1) << 22 | (op
& 2) << 7;
6265 skip_whitespace (str
);
6267 if ((reg
= wreg_required_here (&str
, 12, IWMMXT_REG_WR_OR_WC
)) == FAIL
6268 || skip_past_comma (& str
) == FAIL
6269 || cp_byte_address_required_here (&str
) == FAIL
)
6272 inst
.error
= BAD_ARGS
;
6277 if (wc_register (reg
))
6279 as_bad (_("non-word size not supported with control register"));
6280 inst
.instruction
|= 0xf0000100;
6281 inst
.instruction
&= ~0x00400000;
6286 do_iwmmxt_tandc (str
)
6291 reg
= check_iwmmxt_insn (str
, check_rd
, 0);
6293 if (reg
!= REG_PC
&& !inst
.error
)
6294 inst
.error
= _("only r15 allowed here");
6299 do_iwmmxt_tbcst (str
)
6302 check_iwmmxt_insn (str
, check_tbcst
, 0);
6308 do_iwmmxt_textrc (str
)
6311 unsigned long number
;
6313 if ((number
= check_iwmmxt_insn (str
, check_textrc
, 7)) == (unsigned long) FAIL
)
6316 inst
.instruction
|= number
& 0x7;
6321 do_iwmmxt_textrm (str
)
6324 unsigned long number
;
6326 if ((number
= check_iwmmxt_insn (str
, check_textrm
, 7)) == (unsigned long) FAIL
)
6329 inst
.instruction
|= number
& 0x7;
6333 do_iwmmxt_tinsr (str
)
6336 unsigned long number
;
6338 if ((number
= check_iwmmxt_insn (str
, check_tinsr
, 7)) == (unsigned long) FAIL
)
6341 inst
.instruction
|= number
& 0x7;
6346 do_iwmmxt_tmcr (str
)
6349 check_iwmmxt_insn (str
, check_tmcr
, 0);
6355 do_iwmmxt_tmcrr (str
)
6358 check_iwmmxt_insn (str
, check_tmcrr
, 0);
6364 do_iwmmxt_tmia (str
)
6367 check_iwmmxt_insn (str
, check_tmia
, 0);
6373 do_iwmmxt_tmovmsk (str
)
6376 check_iwmmxt_insn (str
, check_tmovmsk
, 0);
6382 do_iwmmxt_tmrc (str
)
6385 check_iwmmxt_insn (str
, check_tmrc
, 0);
6391 do_iwmmxt_tmrrc (str
)
6394 check_iwmmxt_insn (str
, check_tmrrc
, 0);
6400 do_iwmmxt_torc (str
)
6403 check_iwmmxt_insn (str
, check_rd
, 0);
6408 do_iwmmxt_waligni (str
)
6411 unsigned long number
;
6413 if ((number
= check_iwmmxt_insn (str
, check_waligni
, 7)) == (unsigned long) FAIL
)
6416 inst
.instruction
|= ((number
& 0x7) << 20);
6421 do_iwmmxt_wmov (str
)
6424 if (check_iwmmxt_insn (str
, check_wrwr
, 0) == (unsigned long) FAIL
)
6427 inst
.instruction
|= ((inst
.instruction
>> 16) & 0xf);
6432 do_iwmmxt_word_addr (str
)
6435 int op
= (inst
.instruction
& 0x300) >> 8;
6438 inst
.instruction
&= ~0x300;
6439 inst
.instruction
|= (op
& 1) << 22 | (op
& 2) << 7;
6441 skip_whitespace (str
);
6443 if ((reg
= wreg_required_here (&str
, 12, IWMMXT_REG_WR_OR_WC
)) == FAIL
6444 || skip_past_comma (& str
) == FAIL
6445 || cp_address_required_here (& str
, CP_WB_OK
) == FAIL
)
6448 inst
.error
= BAD_ARGS
;
6453 if (wc_register (reg
))
6455 if ((inst
.instruction
& COND_MASK
) != COND_ALWAYS
)
6456 as_bad (_("conditional execution not supported with control register"));
6458 as_bad (_("non-word size not supported with control register"));
6459 inst
.instruction
|= 0xf0000100;
6460 inst
.instruction
&= ~0x00400000;
6465 do_iwmmxt_wrwr (str
)
6468 check_iwmmxt_insn (str
, check_wrwr
, 0);
6474 do_iwmmxt_wrwrwcg (str
)
6477 check_iwmmxt_insn (str
, check_wrwrwcg
, 0);
6483 do_iwmmxt_wrwrwr (str
)
6486 check_iwmmxt_insn (str
, check_wrwrwr
, 0);
6492 do_iwmmxt_wshufh (str
)
6495 unsigned long number
;
6497 if ((number
= check_iwmmxt_insn (str
, check_wshufh
, 0xff)) == (unsigned long) FAIL
)
6500 inst
.instruction
|= ((number
& 0xf0) << 16) | (number
& 0xf);
6505 do_iwmmxt_wzero (str
)
6508 if (check_iwmmxt_insn (str
, check_wr
, 0) == (unsigned long) FAIL
)
6511 inst
.instruction
|= ((inst
.instruction
& 0xf) << 12) | ((inst
.instruction
& 0xf) << 16);
6515 /* Xscale multiply-accumulate (argument parse)
6518 MIAxycc acc0,Rm,Rs. */
6527 if (accum0_required_here (& str
) == FAIL
)
6528 inst
.error
= ERR_NO_ACCUM
;
6530 else if (skip_past_comma (& str
) == FAIL
6531 || (rm
= reg_required_here (& str
, 0)) == FAIL
)
6532 inst
.error
= BAD_ARGS
;
6534 else if (skip_past_comma (& str
) == FAIL
6535 || (rs
= reg_required_here (& str
, 12)) == FAIL
)
6536 inst
.error
= BAD_ARGS
;
6538 /* inst.instruction has now been zapped with both rm and rs. */
6539 else if (rm
== REG_PC
|| rs
== REG_PC
)
6540 inst
.error
= BAD_PC
; /* Undefined result if rm or rs is R15. */
6546 /* Xscale move-accumulator-register (argument parse)
6548 MARcc acc0,RdLo,RdHi. */
6556 if (accum0_required_here (& str
) == FAIL
)
6557 inst
.error
= ERR_NO_ACCUM
;
6559 else if (skip_past_comma (& str
) == FAIL
6560 || (rdlo
= reg_required_here (& str
, 12)) == FAIL
)
6561 inst
.error
= BAD_ARGS
;
6563 else if (skip_past_comma (& str
) == FAIL
6564 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
6565 inst
.error
= BAD_ARGS
;
6567 /* inst.instruction has now been zapped with both rdlo and rdhi. */
6568 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
6569 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
6575 /* Xscale move-register-accumulator (argument parse)
6577 MRAcc RdLo,RdHi,acc0. */
6586 skip_whitespace (str
);
6588 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
)
6589 inst
.error
= BAD_ARGS
;
6591 else if (skip_past_comma (& str
) == FAIL
6592 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
6593 inst
.error
= BAD_ARGS
;
6595 else if (skip_past_comma (& str
) == FAIL
6596 || accum0_required_here (& str
) == FAIL
)
6597 inst
.error
= ERR_NO_ACCUM
;
6599 /* inst.instruction has now been zapped with both rdlo and rdhi. */
6600 else if (rdlo
== rdhi
)
6601 inst
.error
= BAD_ARGS
; /* Undefined result if 2 writes to same reg. */
6603 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
6604 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
6609 /* ARMv5TE: Preload-Cache
6613 Syntactically, like LDR with B=1, W=0, L=1. */
6621 skip_whitespace (str
);
6625 inst
.error
= _("'[' expected after PLD mnemonic");
6630 skip_whitespace (str
);
6632 if ((rd
= reg_required_here (& str
, 16)) == FAIL
)
6635 skip_whitespace (str
);
6641 skip_whitespace (str
);
6643 /* Post-indexed addressing is not allowed with PLD. */
6644 if (skip_past_comma (&str
) == SUCCESS
)
6647 = _("post-indexed expression used in preload instruction");
6650 else if (*str
== '!') /* [Rn]! */
6652 inst
.error
= _("writeback used in preload instruction");
6656 inst
.instruction
|= INDEX_UP
| PRE_INDEX
;
6658 else /* [Rn, ...] */
6660 if (skip_past_comma (& str
) == FAIL
)
6662 inst
.error
= _("pre-indexed expression expected");
6666 if (ldst_extend (&str
) == FAIL
)
6669 skip_whitespace (str
);
6673 inst
.error
= _("missing ]");
6678 skip_whitespace (str
);
6680 if (* str
== '!') /* [Rn]! */
6682 inst
.error
= _("writeback used in preload instruction");
6686 inst
.instruction
|= PRE_INDEX
;
6692 /* ARMv5TE load-consecutive (argument parse)
6705 skip_whitespace (str
);
6707 if ((rd
= reg_required_here (& str
, 12)) == FAIL
)
6709 inst
.error
= BAD_ARGS
;
6713 if (skip_past_comma (& str
) == FAIL
6714 || (rn
= ld_mode_required_here (& str
)) == FAIL
)
6717 inst
.error
= BAD_ARGS
;
6721 /* inst.instruction has now been zapped with Rd and the addressing mode. */
6722 if (rd
& 1) /* Unpredictable result if Rd is odd. */
6724 inst
.error
= _("destination register must be even");
6730 inst
.error
= _("r14 not allowed here");
6734 if (((rd
== rn
) || (rd
+ 1 == rn
))
6735 && ((inst
.instruction
& WRITE_BACK
)
6736 || (!(inst
.instruction
& PRE_INDEX
))))
6737 as_warn (_("pre/post-indexing used when modified address register is destination"));
6739 /* For an index-register load, the index register must not overlap the
6740 destination (even if not write-back). */
6741 if ((inst
.instruction
& V4_STR_BIT
) == 0
6742 && (inst
.instruction
& HWOFFSET_IMM
) == 0)
6744 int rm
= inst
.instruction
& 0x0000000f;
6746 if (rm
== rd
|| (rm
== rd
+ 1))
6747 as_warn (_("ldrd destination registers must not overlap index register"));
6753 /* Returns the index into fp_values of a floating point number,
6754 or -1 if not in the table. */
6757 my_get_float_expression (str
)
6760 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
6766 memset (words
, 0, MAX_LITTLENUMS
* sizeof (LITTLENUM_TYPE
));
6768 /* Look for a raw floating point number. */
6769 if ((save_in
= atof_ieee (*str
, 'x', words
)) != NULL
6770 && is_end_of_line
[(unsigned char) *save_in
])
6772 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
6774 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
6776 if (words
[j
] != fp_values
[i
][j
])
6780 if (j
== MAX_LITTLENUMS
)
6788 /* Try and parse a more complex expression, this will probably fail
6789 unless the code uses a floating point prefix (eg "0f"). */
6790 save_in
= input_line_pointer
;
6791 input_line_pointer
= *str
;
6792 if (expression (&exp
) == absolute_section
6793 && exp
.X_op
== O_big
6794 && exp
.X_add_number
< 0)
6796 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
6798 if (gen_to_words (words
, 5, (long) 15) == 0)
6800 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
6802 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
6804 if (words
[j
] != fp_values
[i
][j
])
6808 if (j
== MAX_LITTLENUMS
)
6810 *str
= input_line_pointer
;
6811 input_line_pointer
= save_in
;
6818 *str
= input_line_pointer
;
6819 input_line_pointer
= save_in
;
6823 /* Return TRUE if anything in the expression is a bignum. */
6826 walk_no_bignums (sp
)
6829 if (symbol_get_value_expression (sp
)->X_op
== O_big
)
6832 if (symbol_get_value_expression (sp
)->X_add_symbol
)
6834 return (walk_no_bignums (symbol_get_value_expression (sp
)->X_add_symbol
)
6835 || (symbol_get_value_expression (sp
)->X_op_symbol
6836 && walk_no_bignums (symbol_get_value_expression (sp
)->X_op_symbol
)));
6842 static int in_my_get_expression
= 0;
6845 my_get_expression (ep
, str
)
6852 save_in
= input_line_pointer
;
6853 input_line_pointer
= *str
;
6854 in_my_get_expression
= 1;
6855 seg
= expression (ep
);
6856 in_my_get_expression
= 0;
6858 if (ep
->X_op
== O_illegal
)
6860 /* We found a bad expression in md_operand(). */
6861 *str
= input_line_pointer
;
6862 input_line_pointer
= save_in
;
6867 if (seg
!= absolute_section
6868 && seg
!= text_section
6869 && seg
!= data_section
6870 && seg
!= bss_section
6871 && seg
!= undefined_section
)
6873 inst
.error
= _("bad_segment");
6874 *str
= input_line_pointer
;
6875 input_line_pointer
= save_in
;
6880 /* Get rid of any bignums now, so that we don't generate an error for which
6881 we can't establish a line number later on. Big numbers are never valid
6882 in instructions, which is where this routine is always called. */
6883 if (ep
->X_op
== O_big
6884 || (ep
->X_add_symbol
6885 && (walk_no_bignums (ep
->X_add_symbol
)
6887 && walk_no_bignums (ep
->X_op_symbol
)))))
6889 inst
.error
= _("invalid constant");
6890 *str
= input_line_pointer
;
6891 input_line_pointer
= save_in
;
6895 *str
= input_line_pointer
;
6896 input_line_pointer
= save_in
;
6900 /* We handle all bad expressions here, so that we can report the faulty
6901 instruction in the error message. */
6906 if (in_my_get_expression
)
6908 expr
->X_op
= O_illegal
;
6909 if (inst
.error
== NULL
)
6910 inst
.error
= _("bad expression");
6914 /* KIND indicates what kind of shifts are accepted. */
6917 decode_shift (str
, kind
)
6921 const struct asm_shift_name
* shift
;
6925 skip_whitespace (* str
);
6927 for (p
= * str
; ISALPHA (* p
); p
++)
6932 inst
.error
= _("shift expression expected");
6938 shift
= (const struct asm_shift_name
*) hash_find (arm_shift_hsh
, * str
);
6943 inst
.error
= _("shift expression expected");
6947 assert (shift
->properties
->index
== shift_properties
[shift
->properties
->index
].index
);
6949 if (kind
== SHIFT_LSL_OR_ASR_IMMEDIATE
6950 && shift
->properties
->index
!= SHIFT_LSL
6951 && shift
->properties
->index
!= SHIFT_ASR
)
6953 inst
.error
= _("'LSL' or 'ASR' required");
6956 else if (kind
== SHIFT_LSL_IMMEDIATE
6957 && shift
->properties
->index
!= SHIFT_LSL
)
6959 inst
.error
= _("'LSL' required");
6962 else if (kind
== SHIFT_ASR_IMMEDIATE
6963 && shift
->properties
->index
!= SHIFT_ASR
)
6965 inst
.error
= _("'ASR' required");
6969 if (shift
->properties
->index
== SHIFT_RRX
)
6972 inst
.instruction
|= shift
->properties
->bit_field
;
6976 skip_whitespace (p
);
6978 if (kind
== NO_SHIFT_RESTRICT
&& reg_required_here (& p
, 8) != FAIL
)
6980 inst
.instruction
|= shift
->properties
->bit_field
| SHIFT_BY_REG
;
6984 else if (! is_immediate_prefix (* p
))
6986 inst
.error
= (NO_SHIFT_RESTRICT
6987 ? _("shift requires register or #expression")
6988 : _("shift requires #expression"));
6996 if (my_get_expression (& inst
.reloc
.exp
, & p
))
6999 /* Validate some simple #expressions. */
7000 if (inst
.reloc
.exp
.X_op
== O_constant
)
7002 unsigned num
= inst
.reloc
.exp
.X_add_number
;
7004 /* Reject operations greater than 32. */
7006 /* Reject a shift of 0 unless the mode allows it. */
7007 || (num
== 0 && shift
->properties
->allows_0
== 0)
7008 /* Reject a shift of 32 unless the mode allows it. */
7009 || (num
== 32 && shift
->properties
->allows_32
== 0)
7012 /* As a special case we allow a shift of zero for
7013 modes that do not support it to be recoded as an
7014 logical shift left of zero (ie nothing). We warn
7015 about this though. */
7018 as_warn (_("shift of 0 ignored."));
7019 shift
= & shift_names
[0];
7020 assert (shift
->properties
->index
== SHIFT_LSL
);
7024 inst
.error
= _("invalid immediate shift");
7029 /* Shifts of 32 are encoded as 0, for those shifts that
7034 inst
.instruction
|= (num
<< 7) | shift
->properties
->bit_field
;
7038 inst
.reloc
.type
= BFD_RELOC_ARM_SHIFT_IMM
;
7039 inst
.reloc
.pc_rel
= 0;
7040 inst
.instruction
|= shift
->properties
->bit_field
;
7047 /* Do those data_ops which can take a negative immediate constant
7048 by altering the instruction. A bit of a hack really.
7052 by inverting the second operand, and
7055 by negating the second operand. */
7058 negate_data_op (instruction
, value
)
7059 unsigned long * instruction
;
7060 unsigned long value
;
7063 unsigned long negated
, inverted
;
7065 negated
= validate_immediate (-value
);
7066 inverted
= validate_immediate (~value
);
7068 op
= (*instruction
>> DATA_OP_SHIFT
) & 0xf;
7071 /* First negates. */
7072 case OPCODE_SUB
: /* ADD <-> SUB */
7073 new_inst
= OPCODE_ADD
;
7078 new_inst
= OPCODE_SUB
;
7082 case OPCODE_CMP
: /* CMP <-> CMN */
7083 new_inst
= OPCODE_CMN
;
7088 new_inst
= OPCODE_CMP
;
7092 /* Now Inverted ops. */
7093 case OPCODE_MOV
: /* MOV <-> MVN */
7094 new_inst
= OPCODE_MVN
;
7099 new_inst
= OPCODE_MOV
;
7103 case OPCODE_AND
: /* AND <-> BIC */
7104 new_inst
= OPCODE_BIC
;
7109 new_inst
= OPCODE_AND
;
7113 case OPCODE_ADC
: /* ADC <-> SBC */
7114 new_inst
= OPCODE_SBC
;
7119 new_inst
= OPCODE_ADC
;
7123 /* We cannot do anything. */
7128 if (value
== (unsigned) FAIL
)
7131 *instruction
&= OPCODE_MASK
;
7132 *instruction
|= new_inst
<< DATA_OP_SHIFT
;
7143 skip_whitespace (* str
);
7145 if (reg_required_here (str
, 0) != FAIL
)
7147 if (skip_past_comma (str
) == SUCCESS
)
7148 /* Shift operation on register. */
7149 return decode_shift (str
, NO_SHIFT_RESTRICT
);
7155 /* Immediate expression. */
7156 if (is_immediate_prefix (**str
))
7161 if (my_get_expression (&inst
.reloc
.exp
, str
))
7164 if (inst
.reloc
.exp
.X_add_symbol
)
7166 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
7167 inst
.reloc
.pc_rel
= 0;
7171 if (skip_past_comma (str
) == SUCCESS
)
7173 /* #x, y -- ie explicit rotation by Y. */
7174 if (my_get_expression (&expr
, str
))
7177 if (expr
.X_op
!= O_constant
)
7179 inst
.error
= _("constant expression expected");
7183 /* Rotate must be a multiple of 2. */
7184 if (((unsigned) expr
.X_add_number
) > 30
7185 || (expr
.X_add_number
& 1) != 0
7186 || ((unsigned) inst
.reloc
.exp
.X_add_number
) > 255)
7188 inst
.error
= _("invalid constant");
7191 inst
.instruction
|= INST_IMMEDIATE
;
7192 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
7193 inst
.instruction
|= expr
.X_add_number
<< 7;
7197 /* Implicit rotation, select a suitable one. */
7198 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
7202 /* Can't be done. Perhaps the code reads something like
7203 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
7204 if ((value
= negate_data_op (&inst
.instruction
,
7205 inst
.reloc
.exp
.X_add_number
))
7208 inst
.error
= _("invalid constant");
7213 inst
.instruction
|= value
;
7216 inst
.instruction
|= INST_IMMEDIATE
;
7221 inst
.error
= _("register or shift expression expected");
7230 skip_whitespace (* str
);
7232 if (fp_reg_required_here (str
, 0) != FAIL
)
7236 /* Immediate expression. */
7237 if (*((*str
)++) == '#')
7243 skip_whitespace (* str
);
7245 /* First try and match exact strings, this is to guarantee
7246 that some formats will work even for cross assembly. */
7248 for (i
= 0; fp_const
[i
]; i
++)
7250 if (strncmp (*str
, fp_const
[i
], strlen (fp_const
[i
])) == 0)
7254 *str
+= strlen (fp_const
[i
]);
7255 if (is_end_of_line
[(unsigned char) **str
])
7257 inst
.instruction
|= i
+ 8;
7264 /* Just because we didn't get a match doesn't mean that the
7265 constant isn't valid, just that it is in a format that we
7266 don't automatically recognize. Try parsing it with
7267 the standard expression routines. */
7268 if ((i
= my_get_float_expression (str
)) >= 0)
7270 inst
.instruction
|= i
+ 8;
7274 inst
.error
= _("invalid floating point immediate expression");
7278 _("floating point register or immediate expression expected");
7287 skip_whitespace (str
);
7289 if (reg_required_here (&str
, 12) == FAIL
7290 || skip_past_comma (&str
) == FAIL
7291 || reg_required_here (&str
, 16) == FAIL
7292 || skip_past_comma (&str
) == FAIL
7293 || data_op2 (&str
) == FAIL
)
7296 inst
.error
= BAD_ARGS
;
7308 /* This is a pseudo-op of the form "adr rd, label" to be converted
7309 into a relative address of the form "add rd, pc, #label-.-8". */
7310 skip_whitespace (str
);
7312 if (reg_required_here (&str
, 12) == FAIL
7313 || skip_past_comma (&str
) == FAIL
7314 || my_get_expression (&inst
.reloc
.exp
, &str
))
7317 inst
.error
= BAD_ARGS
;
7321 /* Frag hacking will turn this into a sub instruction if the offset turns
7322 out to be negative. */
7323 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
7324 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust. */
7325 inst
.reloc
.pc_rel
= 1;
7334 /* This is a pseudo-op of the form "adrl rd, label" to be converted
7335 into a relative address of the form:
7336 add rd, pc, #low(label-.-8)"
7337 add rd, rd, #high(label-.-8)" */
7339 skip_whitespace (str
);
7341 if (reg_required_here (&str
, 12) == FAIL
7342 || skip_past_comma (&str
) == FAIL
7343 || my_get_expression (&inst
.reloc
.exp
, &str
))
7346 inst
.error
= BAD_ARGS
;
7352 /* Frag hacking will turn this into a sub instruction if the offset turns
7353 out to be negative. */
7354 inst
.reloc
.type
= BFD_RELOC_ARM_ADRL_IMMEDIATE
;
7355 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust */
7356 inst
.reloc
.pc_rel
= 1;
7357 inst
.size
= INSN_SIZE
* 2;
7366 skip_whitespace (str
);
7368 if (reg_required_here (&str
, 16) == FAIL
)
7371 inst
.error
= BAD_ARGS
;
7375 if (skip_past_comma (&str
) == FAIL
7376 || data_op2 (&str
) == FAIL
)
7379 inst
.error
= BAD_ARGS
;
7391 skip_whitespace (str
);
7393 if (reg_required_here (&str
, 12) == FAIL
)
7396 inst
.error
= BAD_ARGS
;
7400 if (skip_past_comma (&str
) == FAIL
7401 || data_op2 (&str
) == FAIL
)
7404 inst
.error
= BAD_ARGS
;
7423 if (my_get_expression (& inst
.reloc
.exp
, str
))
7426 if (inst
.reloc
.exp
.X_op
== O_constant
)
7428 int value
= inst
.reloc
.exp
.X_add_number
;
7430 if (value
< -4095 || value
> 4095)
7432 inst
.error
= _("address offset too large");
7442 inst
.instruction
|= add
| value
;
7446 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
7447 inst
.reloc
.pc_rel
= 0;
7460 if (reg_required_here (str
, 0) == FAIL
)
7463 inst
.instruction
|= add
| OFFSET_REG
;
7464 if (skip_past_comma (str
) == SUCCESS
)
7465 return decode_shift (str
, SHIFT_IMMEDIATE
);
7479 skip_whitespace (str
);
7481 if ((conflict_reg
= reg_required_here (&str
, 12)) == FAIL
)
7484 inst
.error
= BAD_ARGS
;
7488 if (skip_past_comma (&str
) == FAIL
)
7490 inst
.error
= _("address expected");
7500 skip_whitespace (str
);
7502 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
7505 /* Conflicts can occur on stores as well as loads. */
7506 conflict_reg
= (conflict_reg
== reg
);
7508 skip_whitespace (str
);
7514 if (skip_past_comma (&str
) == SUCCESS
)
7516 /* [Rn],... (post inc) */
7517 if (ldst_extend (&str
) == FAIL
)
7520 as_warn (_("%s register same as write-back base"),
7521 ((inst
.instruction
& LOAD_BIT
)
7522 ? _("destination") : _("source")));
7527 skip_whitespace (str
);
7532 as_warn (_("%s register same as write-back base"),
7533 ((inst
.instruction
& LOAD_BIT
)
7534 ? _("destination") : _("source")));
7536 inst
.instruction
|= WRITE_BACK
;
7539 inst
.instruction
|= INDEX_UP
;
7546 if (skip_past_comma (&str
) == FAIL
)
7548 inst
.error
= _("pre-indexed expression expected");
7553 if (ldst_extend (&str
) == FAIL
)
7556 skip_whitespace (str
);
7560 inst
.error
= _("missing ]");
7564 skip_whitespace (str
);
7569 as_warn (_("%s register same as write-back base"),
7570 ((inst
.instruction
& LOAD_BIT
)
7571 ? _("destination") : _("source")));
7573 inst
.instruction
|= WRITE_BACK
;
7577 else if (*str
== '=')
7579 if ((inst
.instruction
& LOAD_BIT
) == 0)
7581 inst
.error
= _("invalid pseudo operation");
7585 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
7588 skip_whitespace (str
);
7590 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7593 if (inst
.reloc
.exp
.X_op
!= O_constant
7594 && inst
.reloc
.exp
.X_op
!= O_symbol
)
7596 inst
.error
= _("constant expression expected");
7600 if (inst
.reloc
.exp
.X_op
== O_constant
)
7602 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
7606 /* This can be done with a mov instruction. */
7607 inst
.instruction
&= LITERAL_MASK
;
7608 inst
.instruction
|= (INST_IMMEDIATE
7609 | (OPCODE_MOV
<< DATA_OP_SHIFT
));
7610 inst
.instruction
|= value
& 0xfff;
7615 value
= validate_immediate (~inst
.reloc
.exp
.X_add_number
);
7619 /* This can be done with a mvn instruction. */
7620 inst
.instruction
&= LITERAL_MASK
;
7621 inst
.instruction
|= (INST_IMMEDIATE
7622 | (OPCODE_MVN
<< DATA_OP_SHIFT
));
7623 inst
.instruction
|= value
& 0xfff;
7629 /* Insert into literal pool. */
7630 if (add_to_lit_pool () == FAIL
)
7633 inst
.error
= _("literal pool insertion failed");
7637 /* Change the instruction exp to point to the pool. */
7638 inst
.reloc
.type
= BFD_RELOC_ARM_LITERAL
;
7639 inst
.reloc
.pc_rel
= 1;
7640 inst
.instruction
|= (REG_PC
<< 16);
7645 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7648 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
7650 /* PC rel adjust. */
7651 inst
.reloc
.exp
.X_add_number
-= 8;
7653 inst
.reloc
.pc_rel
= 1;
7654 inst
.instruction
|= (REG_PC
<< 16);
7658 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
7669 skip_whitespace (str
);
7671 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
7674 inst
.error
= BAD_ARGS
;
7678 if (skip_past_comma (& str
) == FAIL
)
7680 inst
.error
= _("address expected");
7690 skip_whitespace (str
);
7692 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
7695 /* ldrt/strt always use post-indexed addressing, so if the base is
7696 the same as Rd, we warn. */
7697 if (conflict_reg
== reg
)
7698 as_warn (_("%s register same as write-back base"),
7699 ((inst
.instruction
& LOAD_BIT
)
7700 ? _("destination") : _("source")));
7702 skip_whitespace (str
);
7708 if (skip_past_comma (&str
) == SUCCESS
)
7710 /* [Rn],... (post inc) */
7711 if (ldst_extend (&str
) == FAIL
)
7717 skip_whitespace (str
);
7719 /* Skip a write-back '!'. */
7723 inst
.instruction
|= INDEX_UP
;
7728 inst
.error
= _("post-indexed expression expected");
7734 inst
.error
= _("post-indexed expression expected");
7743 ldst_extend_v4 (str
)
7753 if (my_get_expression (& inst
.reloc
.exp
, str
))
7756 if (inst
.reloc
.exp
.X_op
== O_constant
)
7758 int value
= inst
.reloc
.exp
.X_add_number
;
7760 if (value
< -255 || value
> 255)
7762 inst
.error
= _("address offset too large");
7772 /* Halfword and signextension instructions have the
7773 immediate value split across bits 11..8 and bits 3..0. */
7774 inst
.instruction
|= (add
| HWOFFSET_IMM
7775 | ((value
>> 4) << 8) | (value
& 0xF));
7779 inst
.instruction
|= HWOFFSET_IMM
;
7780 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
7781 inst
.reloc
.pc_rel
= 0;
7794 if (reg_required_here (str
, 0) == FAIL
)
7797 inst
.instruction
|= add
;
7802 /* Halfword and signed-byte load/store operations. */
7811 skip_whitespace (str
);
7813 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
7816 inst
.error
= BAD_ARGS
;
7820 if (skip_past_comma (& str
) == FAIL
)
7822 inst
.error
= _("address expected");
7832 skip_whitespace (str
);
7834 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
7837 /* Conflicts can occur on stores as well as loads. */
7838 conflict_reg
= (conflict_reg
== reg
);
7840 skip_whitespace (str
);
7846 if (skip_past_comma (&str
) == SUCCESS
)
7848 /* [Rn],... (post inc) */
7849 if (ldst_extend_v4 (&str
) == FAIL
)
7852 as_warn (_("%s register same as write-back base"),
7853 ((inst
.instruction
& LOAD_BIT
)
7854 ? _("destination") : _("source")));
7859 inst
.instruction
|= HWOFFSET_IMM
;
7861 skip_whitespace (str
);
7866 as_warn (_("%s register same as write-back base"),
7867 ((inst
.instruction
& LOAD_BIT
)
7868 ? _("destination") : _("source")));
7870 inst
.instruction
|= WRITE_BACK
;
7873 inst
.instruction
|= INDEX_UP
;
7880 if (skip_past_comma (&str
) == FAIL
)
7882 inst
.error
= _("pre-indexed expression expected");
7887 if (ldst_extend_v4 (&str
) == FAIL
)
7890 skip_whitespace (str
);
7894 inst
.error
= _("missing ]");
7898 skip_whitespace (str
);
7903 as_warn (_("%s register same as write-back base"),
7904 ((inst
.instruction
& LOAD_BIT
)
7905 ? _("destination") : _("source")));
7907 inst
.instruction
|= WRITE_BACK
;
7911 else if (*str
== '=')
7913 if ((inst
.instruction
& LOAD_BIT
) == 0)
7915 inst
.error
= _("invalid pseudo operation");
7919 /* XXX Does this work correctly for half-word/byte ops? */
7920 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
7923 skip_whitespace (str
);
7925 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7928 if (inst
.reloc
.exp
.X_op
!= O_constant
7929 && inst
.reloc
.exp
.X_op
!= O_symbol
)
7931 inst
.error
= _("constant expression expected");
7935 if (inst
.reloc
.exp
.X_op
== O_constant
)
7937 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
7941 /* This can be done with a mov instruction. */
7942 inst
.instruction
&= LITERAL_MASK
;
7943 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MOV
<< DATA_OP_SHIFT
);
7944 inst
.instruction
|= value
& 0xfff;
7949 value
= validate_immediate (~ inst
.reloc
.exp
.X_add_number
);
7953 /* This can be done with a mvn instruction. */
7954 inst
.instruction
&= LITERAL_MASK
;
7955 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MVN
<< DATA_OP_SHIFT
);
7956 inst
.instruction
|= value
& 0xfff;
7962 /* Insert into literal pool. */
7963 if (add_to_lit_pool () == FAIL
)
7966 inst
.error
= _("literal pool insertion failed");
7970 /* Change the instruction exp to point to the pool. */
7971 inst
.instruction
|= HWOFFSET_IMM
;
7972 inst
.reloc
.type
= BFD_RELOC_ARM_HWLITERAL
;
7973 inst
.reloc
.pc_rel
= 1;
7974 inst
.instruction
|= (REG_PC
<< 16);
7979 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7982 inst
.instruction
|= HWOFFSET_IMM
;
7983 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
7985 /* PC rel adjust. */
7986 inst
.reloc
.exp
.X_add_number
-= 8;
7988 inst
.reloc
.pc_rel
= 1;
7989 inst
.instruction
|= (REG_PC
<< 16);
7993 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
8002 char * str
= * strp
;
8006 /* We come back here if we get ranges concatenated by '+' or '|'. */
8021 skip_whitespace (str
);
8023 if ((reg
= reg_required_here (& str
, -1)) == FAIL
)
8032 inst
.error
= _("bad range in register list");
8036 for (i
= cur_reg
+ 1; i
< reg
; i
++)
8038 if (range
& (1 << i
))
8040 (_("Warning: duplicated register (r%d) in register list"),
8048 if (range
& (1 << reg
))
8049 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
8051 else if (reg
<= cur_reg
)
8052 as_tsktsk (_("Warning: register range not in ascending order"));
8057 while (skip_past_comma (&str
) != FAIL
8058 || (in_range
= 1, *str
++ == '-'));
8060 skip_whitespace (str
);
8064 inst
.error
= _("missing `}'");
8072 if (my_get_expression (&expr
, &str
))
8075 if (expr
.X_op
== O_constant
)
8077 if (expr
.X_add_number
8078 != (expr
.X_add_number
& 0x0000ffff))
8080 inst
.error
= _("invalid register mask");
8084 if ((range
& expr
.X_add_number
) != 0)
8086 int regno
= range
& expr
.X_add_number
;
8089 regno
= (1 << regno
) - 1;
8091 (_("Warning: duplicated register (r%d) in register list"),
8095 range
|= expr
.X_add_number
;
8099 if (inst
.reloc
.type
!= 0)
8101 inst
.error
= _("expression too complex");
8105 memcpy (&inst
.reloc
.exp
, &expr
, sizeof (expressionS
));
8106 inst
.reloc
.type
= BFD_RELOC_ARM_MULTI
;
8107 inst
.reloc
.pc_rel
= 0;
8111 skip_whitespace (str
);
8113 if (*str
== '|' || *str
== '+')
8119 while (another_range
);
8132 skip_whitespace (str
);
8134 if ((base_reg
= reg_required_here (&str
, 16)) == FAIL
)
8137 if (base_reg
== REG_PC
)
8139 inst
.error
= _("r15 not allowed as base register");
8143 skip_whitespace (str
);
8147 inst
.instruction
|= WRITE_BACK
;
8151 if (skip_past_comma (&str
) == FAIL
8152 || (range
= reg_list (&str
)) == FAIL
)
8155 inst
.error
= BAD_ARGS
;
8162 inst
.instruction
|= LDM_TYPE_2_OR_3
;
8165 if (inst
.instruction
& WRITE_BACK
)
8167 /* Check for unpredictable uses of writeback. */
8168 if (inst
.instruction
& LOAD_BIT
)
8170 /* Not allowed in LDM type 2. */
8171 if ((inst
.instruction
& LDM_TYPE_2_OR_3
)
8172 && ((range
& (1 << REG_PC
)) == 0))
8173 as_warn (_("writeback of base register is UNPREDICTABLE"));
8174 /* Only allowed if base reg not in list for other types. */
8175 else if (range
& (1 << base_reg
))
8176 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
8180 /* Not allowed for type 2. */
8181 if (inst
.instruction
& LDM_TYPE_2_OR_3
)
8182 as_warn (_("writeback of base register is UNPREDICTABLE"));
8183 /* Only allowed if base reg not in list, or first in list. */
8184 else if ((range
& (1 << base_reg
))
8185 && (range
& ((1 << base_reg
) - 1)))
8186 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
8190 inst
.instruction
|= range
;
8199 skip_whitespace (str
);
8201 /* Allow optional leading '#'. */
8202 if (is_immediate_prefix (*str
))
8205 if (my_get_expression (& inst
.reloc
.exp
, & str
))
8208 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
8209 inst
.reloc
.pc_rel
= 0;
8221 skip_whitespace (str
);
8223 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
8228 inst
.error
= _("r15 not allowed in swap");
8232 if (skip_past_comma (&str
) == FAIL
8233 || (reg
= reg_required_here (&str
, 0)) == FAIL
)
8236 inst
.error
= BAD_ARGS
;
8242 inst
.error
= _("r15 not allowed in swap");
8246 if (skip_past_comma (&str
) == FAIL
8249 inst
.error
= BAD_ARGS
;
8253 skip_whitespace (str
);
8255 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
8260 inst
.error
= BAD_PC
;
8264 skip_whitespace (str
);
8268 inst
.error
= _("missing ]");
8280 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8287 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
8288 required for the instruction. */
8290 /* arm_parse_reloc () works on input_line_pointer.
8291 We actually want to parse the operands to the branch instruction
8292 passed in 'str'. Save the input pointer and restore it later. */
8293 save_in
= input_line_pointer
;
8294 input_line_pointer
= str
;
8295 if (inst
.reloc
.exp
.X_op
== O_symbol
8297 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
8299 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
8300 inst
.reloc
.pc_rel
= 0;
8301 /* Modify str to point to after parsed operands, otherwise
8302 end_of_line() will complain about the (PLT) left in str. */
8303 str
= input_line_pointer
;
8307 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
8308 inst
.reloc
.pc_rel
= 1;
8310 input_line_pointer
= save_in
;
8313 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
8314 inst
.reloc
.pc_rel
= 1;
8315 #endif /* OBJ_ELF */
8327 skip_whitespace (str
);
8329 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
8331 inst
.error
= BAD_ARGS
;
8335 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
8337 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
8346 /* Co-processor data operation.
8347 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
8348 skip_whitespace (str
);
8350 if (co_proc_number (&str
) == FAIL
)
8353 inst
.error
= BAD_ARGS
;
8357 if (skip_past_comma (&str
) == FAIL
8358 || cp_opc_expr (&str
, 20,4) == FAIL
)
8361 inst
.error
= BAD_ARGS
;
8365 if (skip_past_comma (&str
) == FAIL
8366 || cp_reg_required_here (&str
, 12) == FAIL
)
8369 inst
.error
= BAD_ARGS
;
8373 if (skip_past_comma (&str
) == FAIL
8374 || cp_reg_required_here (&str
, 16) == FAIL
)
8377 inst
.error
= BAD_ARGS
;
8381 if (skip_past_comma (&str
) == FAIL
8382 || cp_reg_required_here (&str
, 0) == FAIL
)
8385 inst
.error
= BAD_ARGS
;
8389 if (skip_past_comma (&str
) == SUCCESS
)
8391 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
8394 inst
.error
= BAD_ARGS
;
8407 /* Co-processor register load/store.
8408 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
8410 skip_whitespace (str
);
8412 if (co_proc_number (&str
) == FAIL
)
8415 inst
.error
= BAD_ARGS
;
8419 if (skip_past_comma (&str
) == FAIL
8420 || cp_reg_required_here (&str
, 12) == FAIL
)
8423 inst
.error
= BAD_ARGS
;
8427 if (skip_past_comma (&str
) == FAIL
8428 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
8431 inst
.error
= BAD_ARGS
;
8443 /* Co-processor register transfer.
8444 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
8446 skip_whitespace (str
);
8448 if (co_proc_number (&str
) == FAIL
)
8451 inst
.error
= BAD_ARGS
;
8455 if (skip_past_comma (&str
) == FAIL
8456 || cp_opc_expr (&str
, 21, 3) == FAIL
)
8459 inst
.error
= BAD_ARGS
;
8463 if (skip_past_comma (&str
) == FAIL
8464 || reg_required_here (&str
, 12) == FAIL
)
8467 inst
.error
= BAD_ARGS
;
8471 if (skip_past_comma (&str
) == FAIL
8472 || cp_reg_required_here (&str
, 16) == FAIL
)
8475 inst
.error
= BAD_ARGS
;
8479 if (skip_past_comma (&str
) == FAIL
8480 || cp_reg_required_here (&str
, 0) == FAIL
)
8483 inst
.error
= BAD_ARGS
;
8487 if (skip_past_comma (&str
) == SUCCESS
)
8489 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
8492 inst
.error
= BAD_ARGS
;
8505 /* FP control registers.
8506 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
8508 skip_whitespace (str
);
8510 if (reg_required_here (&str
, 12) == FAIL
)
8513 inst
.error
= BAD_ARGS
;
8525 skip_whitespace (str
);
8527 if (fp_reg_required_here (&str
, 12) == FAIL
)
8530 inst
.error
= BAD_ARGS
;
8534 if (skip_past_comma (&str
) == FAIL
8535 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
8538 inst
.error
= BAD_ARGS
;
8551 skip_whitespace (str
);
8553 if (fp_reg_required_here (&str
, 12) == FAIL
)
8556 inst
.error
= BAD_ARGS
;
8560 /* Get Number of registers to transfer. */
8561 if (skip_past_comma (&str
) == FAIL
8562 || my_get_expression (&inst
.reloc
.exp
, &str
))
8565 inst
.error
= _("constant expression expected");
8569 if (inst
.reloc
.exp
.X_op
!= O_constant
)
8571 inst
.error
= _("constant value required for number of registers");
8575 num_regs
= inst
.reloc
.exp
.X_add_number
;
8577 if (num_regs
< 1 || num_regs
> 4)
8579 inst
.error
= _("number of registers must be in the range [1:4]");
8586 inst
.instruction
|= CP_T_X
;
8589 inst
.instruction
|= CP_T_Y
;
8592 inst
.instruction
|= CP_T_Y
| CP_T_X
;
8600 if (inst
.instruction
& (CP_T_Pre
| CP_T_UD
)) /* ea/fd format. */
8606 /* The instruction specified "ea" or "fd", so we can only accept
8607 [Rn]{!}. The instruction does not really support stacking or
8608 unstacking, so we have to emulate these by setting appropriate
8609 bits and offsets. */
8610 if (skip_past_comma (&str
) == FAIL
8614 inst
.error
= BAD_ARGS
;
8619 skip_whitespace (str
);
8621 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
8624 skip_whitespace (str
);
8628 inst
.error
= BAD_ARGS
;
8640 _("r15 not allowed as base register with write-back");
8647 if (inst
.instruction
& CP_T_Pre
)
8649 /* Pre-decrement. */
8650 offset
= 3 * num_regs
;
8652 inst
.instruction
|= CP_T_WB
;
8656 /* Post-increment. */
8659 inst
.instruction
|= CP_T_WB
;
8660 offset
= 3 * num_regs
;
8664 /* No write-back, so convert this into a standard pre-increment
8665 instruction -- aesthetically more pleasing. */
8666 inst
.instruction
|= CP_T_Pre
| CP_T_UD
;
8671 inst
.instruction
|= offset
;
8673 else if (skip_past_comma (&str
) == FAIL
8674 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
8677 inst
.error
= BAD_ARGS
;
8688 skip_whitespace (str
);
8690 if (fp_reg_required_here (&str
, 12) == FAIL
)
8693 inst
.error
= BAD_ARGS
;
8697 if (skip_past_comma (&str
) == FAIL
8698 || fp_reg_required_here (&str
, 16) == FAIL
)
8701 inst
.error
= BAD_ARGS
;
8705 if (skip_past_comma (&str
) == FAIL
8706 || fp_op2 (&str
) == FAIL
)
8709 inst
.error
= BAD_ARGS
;
8718 do_fpa_monadic (str
)
8721 skip_whitespace (str
);
8723 if (fp_reg_required_here (&str
, 12) == FAIL
)
8726 inst
.error
= BAD_ARGS
;
8730 if (skip_past_comma (&str
) == FAIL
8731 || fp_op2 (&str
) == FAIL
)
8734 inst
.error
= BAD_ARGS
;
8746 skip_whitespace (str
);
8748 if (fp_reg_required_here (&str
, 16) == FAIL
)
8751 inst
.error
= BAD_ARGS
;
8755 if (skip_past_comma (&str
) == FAIL
8756 || fp_op2 (&str
) == FAIL
)
8759 inst
.error
= BAD_ARGS
;
8768 do_fpa_from_reg (str
)
8771 skip_whitespace (str
);
8773 if (fp_reg_required_here (&str
, 16) == FAIL
)
8776 inst
.error
= BAD_ARGS
;
8780 if (skip_past_comma (&str
) == FAIL
8781 || reg_required_here (&str
, 12) == FAIL
)
8784 inst
.error
= BAD_ARGS
;
8796 skip_whitespace (str
);
8798 if (reg_required_here (&str
, 12) == FAIL
)
8801 if (skip_past_comma (&str
) == FAIL
8802 || fp_reg_required_here (&str
, 0) == FAIL
)
8805 inst
.error
= BAD_ARGS
;
8814 vfp_sp_reg_required_here (str
, pos
)
8816 enum vfp_sp_reg_pos pos
;
8821 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_SN
].htab
)) != FAIL
)
8826 inst
.instruction
|= ((reg
>> 1) << 12) | ((reg
& 1) << 22);
8830 inst
.instruction
|= ((reg
>> 1) << 16) | ((reg
& 1) << 7);
8834 inst
.instruction
|= ((reg
>> 1) << 0) | ((reg
& 1) << 5);
8843 /* In the few cases where we might be able to accept something else
8844 this error can be overridden. */
8845 inst
.error
= _(all_reg_maps
[REG_TYPE_SN
].expected
);
8847 /* Restore the start point. */
8853 vfp_dp_reg_required_here (str
, pos
)
8855 enum vfp_dp_reg_pos pos
;
8860 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_DN
].htab
)) != FAIL
)
8865 inst
.instruction
|= reg
<< 12;
8869 inst
.instruction
|= reg
<< 16;
8873 inst
.instruction
|= reg
<< 0;
8882 /* In the few cases where we might be able to accept something else
8883 this error can be overridden. */
8884 inst
.error
= _(all_reg_maps
[REG_TYPE_DN
].expected
);
8886 /* Restore the start point. */
8892 do_vfp_sp_monadic (str
)
8895 skip_whitespace (str
);
8897 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8900 if (skip_past_comma (&str
) == FAIL
8901 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
8904 inst
.error
= BAD_ARGS
;
8913 do_vfp_dp_monadic (str
)
8916 skip_whitespace (str
);
8918 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8921 if (skip_past_comma (&str
) == FAIL
8922 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
8925 inst
.error
= BAD_ARGS
;
8934 do_vfp_sp_dyadic (str
)
8937 skip_whitespace (str
);
8939 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8942 if (skip_past_comma (&str
) == FAIL
8943 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
8944 || skip_past_comma (&str
) == FAIL
8945 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
8948 inst
.error
= BAD_ARGS
;
8957 do_vfp_dp_dyadic (str
)
8960 skip_whitespace (str
);
8962 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8965 if (skip_past_comma (&str
) == FAIL
8966 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
8967 || skip_past_comma (&str
) == FAIL
8968 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
8971 inst
.error
= BAD_ARGS
;
8980 do_vfp_reg_from_sp (str
)
8983 skip_whitespace (str
);
8985 if (reg_required_here (&str
, 12) == FAIL
)
8988 if (skip_past_comma (&str
) == FAIL
8989 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
8992 inst
.error
= BAD_ARGS
;
9001 do_vfp_sp_reg2 (str
)
9004 skip_whitespace (str
);
9006 if (reg_required_here (&str
, 12) == FAIL
)
9009 if (skip_past_comma (&str
) == FAIL
9010 || reg_required_here (&str
, 16) == FAIL
9011 || skip_past_comma (&str
) == FAIL
)
9014 inst
.error
= BAD_ARGS
;
9018 /* We require exactly two consecutive SP registers. */
9019 if (vfp_sp_reg_list (&str
, VFP_REG_Sm
) != 2)
9022 inst
.error
= _("only two consecutive VFP SP registers allowed here");
9030 do_vfp_sp_from_reg (str
)
9033 skip_whitespace (str
);
9035 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
9038 if (skip_past_comma (&str
) == FAIL
9039 || reg_required_here (&str
, 12) == FAIL
)
9042 inst
.error
= BAD_ARGS
;
9051 do_vfp_reg_from_dp (str
)
9054 skip_whitespace (str
);
9056 if (reg_required_here (&str
, 12) == FAIL
)
9059 if (skip_past_comma (&str
) == FAIL
9060 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
9063 inst
.error
= BAD_ARGS
;
9072 do_vfp_reg2_from_dp (str
)
9075 skip_whitespace (str
);
9077 if (reg_required_here (&str
, 12) == FAIL
)
9080 if (skip_past_comma (&str
) == FAIL
9081 || reg_required_here (&str
, 16) == FAIL
9082 || skip_past_comma (&str
) == FAIL
9083 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
9086 inst
.error
= BAD_ARGS
;
9095 do_vfp_dp_from_reg (str
)
9098 skip_whitespace (str
);
9100 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
9103 if (skip_past_comma (&str
) == FAIL
9104 || reg_required_here (&str
, 12) == FAIL
)
9107 inst
.error
= BAD_ARGS
;
9116 do_vfp_dp_from_reg2 (str
)
9119 skip_whitespace (str
);
9121 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
9124 if (skip_past_comma (&str
) == FAIL
9125 || reg_required_here (&str
, 12) == FAIL
9126 || skip_past_comma (&str
) == FAIL
9127 || reg_required_here (&str
, 16))
9130 inst
.error
= BAD_ARGS
;
9138 static const struct vfp_reg
*
9145 const struct vfp_reg
*vreg
;
9149 /* Find the end of the current token. */
9154 while (ISALPHA (c
));
9159 for (vreg
= vfp_regs
+ 0;
9160 vreg
< vfp_regs
+ sizeof (vfp_regs
) / sizeof (struct vfp_reg
);
9163 if (strcmp (start
, vreg
->name
) == 0)
9176 vfp_psr_required_here (str
)
9180 const struct vfp_reg
*vreg
;
9182 vreg
= vfp_psr_parse (str
);
9186 inst
.instruction
|= vreg
->regno
;
9190 inst
.error
= _("VFP system register expected");
9197 do_vfp_reg_from_ctrl (str
)
9200 skip_whitespace (str
);
9202 if (reg_required_here (&str
, 12) == FAIL
)
9205 if (skip_past_comma (&str
) == FAIL
9206 || vfp_psr_required_here (&str
) == FAIL
)
9209 inst
.error
= BAD_ARGS
;
9218 do_vfp_ctrl_from_reg (str
)
9221 skip_whitespace (str
);
9223 if (vfp_psr_required_here (&str
) == FAIL
)
9226 if (skip_past_comma (&str
) == FAIL
9227 || reg_required_here (&str
, 12) == FAIL
)
9230 inst
.error
= BAD_ARGS
;
9239 do_vfp_sp_ldst (str
)
9242 skip_whitespace (str
);
9244 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
9247 inst
.error
= BAD_ARGS
;
9251 if (skip_past_comma (&str
) == FAIL
9252 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
9255 inst
.error
= BAD_ARGS
;
9264 do_vfp_dp_ldst (str
)
9267 skip_whitespace (str
);
9269 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
9272 inst
.error
= BAD_ARGS
;
9276 if (skip_past_comma (&str
) == FAIL
9277 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
9280 inst
.error
= BAD_ARGS
;
9288 /* Parse and encode a VFP SP register list, storing the initial
9289 register in position POS and returning the range as the result. If
9290 the string is invalid return FAIL (an invalid range). */
9292 vfp_sp_reg_list (str
, pos
)
9294 enum vfp_sp_reg_pos pos
;
9302 unsigned long mask
= 0;
9309 skip_whitespace (*str
);
9311 tempinst
= inst
.instruction
;
9315 inst
.instruction
= 0;
9317 if ((new_base
= vfp_sp_reg_required_here (str
, pos
)) == FAIL
)
9320 if (count
== 0 || base_reg
> new_base
)
9322 base_reg
= new_base
;
9323 base_bits
= inst
.instruction
;
9326 if (mask
& (1 << new_base
))
9328 inst
.error
= _("invalid register list");
9332 if ((mask
>> new_base
) != 0 && ! warned
)
9334 as_tsktsk (_("register list not in ascending order"));
9338 mask
|= 1 << new_base
;
9341 skip_whitespace (*str
);
9343 if (**str
== '-') /* We have the start of a range expression */
9350 = arm_reg_parse (str
, all_reg_maps
[REG_TYPE_SN
].htab
))
9353 inst
.error
= _(all_reg_maps
[REG_TYPE_SN
].expected
);
9357 if (high_range
<= new_base
)
9359 inst
.error
= _("register range not in ascending order");
9363 for (new_base
++; new_base
<= high_range
; new_base
++)
9365 if (mask
& (1 << new_base
))
9367 inst
.error
= _("invalid register list");
9371 mask
|= 1 << new_base
;
9376 while (skip_past_comma (str
) != FAIL
);
9380 inst
.error
= _("invalid register list");
9388 /* Sanity check -- should have raised a parse error above. */
9389 if (count
== 0 || count
> 32)
9392 /* Final test -- the registers must be consecutive. */
9395 if ((mask
& (1 << base_reg
++)) == 0)
9397 inst
.error
= _("non-contiguous register range");
9402 inst
.instruction
= tempinst
| base_bits
;
9407 vfp_dp_reg_list (str
)
9415 unsigned long mask
= 0;
9422 skip_whitespace (*str
);
9424 tempinst
= inst
.instruction
;
9428 inst
.instruction
= 0;
9430 if ((new_base
= vfp_dp_reg_required_here (str
, VFP_REG_Dd
)) == FAIL
)
9433 if (count
== 0 || base_reg
> new_base
)
9435 base_reg
= new_base
;
9436 range
= inst
.instruction
;
9439 if (mask
& (1 << new_base
))
9441 inst
.error
= _("invalid register list");
9445 if ((mask
>> new_base
) != 0 && ! warned
)
9447 as_tsktsk (_("register list not in ascending order"));
9451 mask
|= 1 << new_base
;
9454 skip_whitespace (*str
);
9456 if (**str
== '-') /* We have the start of a range expression */
9463 = arm_reg_parse (str
, all_reg_maps
[REG_TYPE_DN
].htab
))
9466 inst
.error
= _(all_reg_maps
[REG_TYPE_DN
].expected
);
9470 if (high_range
<= new_base
)
9472 inst
.error
= _("register range not in ascending order");
9476 for (new_base
++; new_base
<= high_range
; new_base
++)
9478 if (mask
& (1 << new_base
))
9480 inst
.error
= _("invalid register list");
9484 mask
|= 1 << new_base
;
9489 while (skip_past_comma (str
) != FAIL
);
9493 inst
.error
= _("invalid register list");
9501 /* Sanity check -- should have raised a parse error above. */
9502 if (count
== 0 || count
> 16)
9505 /* Final test -- the registers must be consecutive. */
9508 if ((mask
& (1 << base_reg
++)) == 0)
9510 inst
.error
= _("non-contiguous register range");
9515 inst
.instruction
= tempinst
;
9520 vfp_sp_ldstm (str
, ldstm_type
)
9522 enum vfp_ldstm_type ldstm_type
;
9526 skip_whitespace (str
);
9528 if (reg_required_here (&str
, 16) == FAIL
)
9531 skip_whitespace (str
);
9535 inst
.instruction
|= WRITE_BACK
;
9538 else if (ldstm_type
!= VFP_LDSTMIA
)
9540 inst
.error
= _("this addressing mode requires base-register writeback");
9544 if (skip_past_comma (&str
) == FAIL
9545 || (range
= vfp_sp_reg_list (&str
, VFP_REG_Sd
)) == FAIL
)
9548 inst
.error
= BAD_ARGS
;
9552 inst
.instruction
|= range
;
9557 vfp_dp_ldstm (str
, ldstm_type
)
9559 enum vfp_ldstm_type ldstm_type
;
9563 skip_whitespace (str
);
9565 if (reg_required_here (&str
, 16) == FAIL
)
9568 skip_whitespace (str
);
9572 inst
.instruction
|= WRITE_BACK
;
9575 else if (ldstm_type
!= VFP_LDSTMIA
&& ldstm_type
!= VFP_LDSTMIAX
)
9577 inst
.error
= _("this addressing mode requires base-register writeback");
9581 if (skip_past_comma (&str
) == FAIL
9582 || (range
= vfp_dp_reg_list (&str
)) == FAIL
)
9585 inst
.error
= BAD_ARGS
;
9589 if (ldstm_type
== VFP_LDSTMIAX
|| ldstm_type
== VFP_LDSTMDBX
)
9592 inst
.instruction
|= range
;
9597 do_vfp_sp_ldstmia (str
)
9600 vfp_sp_ldstm (str
, VFP_LDSTMIA
);
9604 do_vfp_sp_ldstmdb (str
)
9607 vfp_sp_ldstm (str
, VFP_LDSTMDB
);
9611 do_vfp_dp_ldstmia (str
)
9614 vfp_dp_ldstm (str
, VFP_LDSTMIA
);
9618 do_vfp_dp_ldstmdb (str
)
9621 vfp_dp_ldstm (str
, VFP_LDSTMDB
);
9625 do_vfp_xp_ldstmia (str
)
9628 vfp_dp_ldstm (str
, VFP_LDSTMIAX
);
9632 do_vfp_xp_ldstmdb (str
)
9635 vfp_dp_ldstm (str
, VFP_LDSTMDBX
);
9639 do_vfp_sp_compare_z (str
)
9642 skip_whitespace (str
);
9644 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
9647 inst
.error
= BAD_ARGS
;
9656 do_vfp_dp_compare_z (str
)
9659 skip_whitespace (str
);
9661 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
9664 inst
.error
= BAD_ARGS
;
9673 do_vfp_dp_sp_cvt (str
)
9676 skip_whitespace (str
);
9678 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
9681 if (skip_past_comma (&str
) == FAIL
9682 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
9685 inst
.error
= BAD_ARGS
;
9694 do_vfp_sp_dp_cvt (str
)
9697 skip_whitespace (str
);
9699 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
9702 if (skip_past_comma (&str
) == FAIL
9703 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
9706 inst
.error
= BAD_ARGS
;
9714 /* Thumb specific routines. */
9716 /* Parse and validate that a register is of the right form, this saves
9717 repeated checking of this information in many similar cases.
9718 Unlike the 32-bit case we do not insert the register into the opcode
9719 here, since the position is often unknown until the full instruction
9723 thumb_reg (strp
, hi_lo
)
9729 if ((reg
= reg_required_here (strp
, -1)) == FAIL
)
9737 inst
.error
= _("lo register required");
9745 inst
.error
= _("hi register required");
9757 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
9761 thumb_add_sub (str
, subtract
)
9765 int Rd
, Rs
, Rn
= FAIL
;
9767 skip_whitespace (str
);
9769 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
9770 || skip_past_comma (&str
) == FAIL
)
9773 inst
.error
= BAD_ARGS
;
9777 if (is_immediate_prefix (*str
))
9781 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9786 if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
9789 if (skip_past_comma (&str
) == FAIL
)
9791 /* Two operand format, shuffle the registers
9792 and pretend there are 3. */
9796 else if (is_immediate_prefix (*str
))
9799 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9802 else if ((Rn
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
9806 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
9807 for the latter case, EXPR contains the immediate that was found. */
9810 /* All register format. */
9811 if (Rd
> 7 || Rs
> 7 || Rn
> 7)
9815 inst
.error
= _("dest and source1 must be the same register");
9819 /* Can't do this for SUB. */
9822 inst
.error
= _("subtract valid only on lo regs");
9826 inst
.instruction
= (T_OPCODE_ADD_HI
9827 | (Rd
> 7 ? THUMB_H1
: 0)
9828 | (Rn
> 7 ? THUMB_H2
: 0));
9829 inst
.instruction
|= (Rd
& 7) | ((Rn
& 7) << 3);
9833 inst
.instruction
= subtract
? T_OPCODE_SUB_R3
: T_OPCODE_ADD_R3
;
9834 inst
.instruction
|= Rd
| (Rs
<< 3) | (Rn
<< 6);
9839 /* Immediate expression, now things start to get nasty. */
9841 /* First deal with HI regs, only very restricted cases allowed:
9842 Adjusting SP, and using PC or SP to get an address. */
9843 if ((Rd
> 7 && (Rd
!= REG_SP
|| Rs
!= REG_SP
))
9844 || (Rs
> 7 && Rs
!= REG_SP
&& Rs
!= REG_PC
))
9846 inst
.error
= _("invalid Hi register with immediate");
9850 if (inst
.reloc
.exp
.X_op
!= O_constant
)
9852 /* Value isn't known yet, all we can do is store all the fragments
9853 we know about in the instruction and let the reloc hacking
9855 inst
.instruction
= (subtract
? 0x8000 : 0) | (Rd
<< 4) | Rs
;
9856 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
9860 int offset
= inst
.reloc
.exp
.X_add_number
;
9870 /* Quick check, in case offset is MIN_INT. */
9873 inst
.error
= _("immediate value out of range");
9877 /* Note - you cannot convert a subtract of 0 into an
9878 add of 0 because the carry flag is set differently. */
9879 else if (offset
> 0)
9884 if (offset
& ~0x1fc)
9886 inst
.error
= _("invalid immediate value for stack adjust");
9889 inst
.instruction
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
9890 inst
.instruction
|= offset
>> 2;
9892 else if (Rs
== REG_PC
|| Rs
== REG_SP
)
9895 || (offset
& ~0x3fc))
9897 inst
.error
= _("invalid immediate for address calculation");
9900 inst
.instruction
= (Rs
== REG_PC
? T_OPCODE_ADD_PC
9902 inst
.instruction
|= (Rd
<< 8) | (offset
>> 2);
9908 inst
.error
= _("immediate value out of range");
9911 inst
.instruction
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
9912 inst
.instruction
|= (Rd
<< 8) | offset
;
9918 inst
.error
= _("immediate value out of range");
9921 inst
.instruction
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
9922 inst
.instruction
|= Rd
| (Rs
<< 3) | (offset
<< 6);
9931 thumb_shift (str
, shift
)
9935 int Rd
, Rs
, Rn
= FAIL
;
9937 skip_whitespace (str
);
9939 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9940 || skip_past_comma (&str
) == FAIL
)
9943 inst
.error
= BAD_ARGS
;
9947 if (is_immediate_prefix (*str
))
9949 /* Two operand immediate format, set Rs to Rd. */
9952 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9957 if ((Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9960 if (skip_past_comma (&str
) == FAIL
)
9962 /* Two operand format, shuffle the registers
9963 and pretend there are 3. */
9967 else if (is_immediate_prefix (*str
))
9970 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9973 else if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9977 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
9978 for the latter case, EXPR contains the immediate that was found. */
9984 inst
.error
= _("source1 and dest must be same register");
9990 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_R
; break;
9991 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_R
; break;
9992 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_R
; break;
9995 inst
.instruction
|= Rd
| (Rn
<< 3);
10001 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_I
; break;
10002 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_I
; break;
10003 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_I
; break;
10006 if (inst
.reloc
.exp
.X_op
!= O_constant
)
10008 /* Value isn't known yet, create a dummy reloc and let reloc
10009 hacking fix it up. */
10010 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_SHIFT
;
10014 unsigned shift_value
= inst
.reloc
.exp
.X_add_number
;
10016 if (shift_value
> 32 || (shift_value
== 32 && shift
== THUMB_LSL
))
10018 inst
.error
= _("invalid immediate for shift");
10022 /* Shifts of zero are handled by converting to LSL. */
10023 if (shift_value
== 0)
10024 inst
.instruction
= T_OPCODE_LSL_I
;
10026 /* Shifts of 32 are encoded as a shift of zero. */
10027 if (shift_value
== 32)
10030 inst
.instruction
|= shift_value
<< 6;
10033 inst
.instruction
|= Rd
| (Rs
<< 3);
10040 thumb_mov_compare (str
, move
)
10046 skip_whitespace (str
);
10048 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
10049 || skip_past_comma (&str
) == FAIL
)
10052 inst
.error
= BAD_ARGS
;
10056 if (move
!= THUMB_CPY
&& is_immediate_prefix (*str
))
10059 if (my_get_expression (&inst
.reloc
.exp
, &str
))
10062 else if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
10067 if (move
!= THUMB_CPY
&& Rs
< 8 && Rd
< 8)
10069 if (move
== THUMB_MOVE
)
10070 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
10071 since a MOV instruction produces unpredictable results. */
10072 inst
.instruction
= T_OPCODE_ADD_I3
;
10074 inst
.instruction
= T_OPCODE_CMP_LR
;
10075 inst
.instruction
|= Rd
| (Rs
<< 3);
10079 if (move
== THUMB_MOVE
)
10080 inst
.instruction
= T_OPCODE_MOV_HR
;
10081 else if (move
!= THUMB_CPY
)
10082 inst
.instruction
= T_OPCODE_CMP_HR
;
10085 inst
.instruction
|= THUMB_H1
;
10088 inst
.instruction
|= THUMB_H2
;
10090 inst
.instruction
|= (Rd
& 7) | ((Rs
& 7) << 3);
10097 inst
.error
= _("only lo regs allowed with immediate");
10101 if (move
== THUMB_MOVE
)
10102 inst
.instruction
= T_OPCODE_MOV_I8
;
10104 inst
.instruction
= T_OPCODE_CMP_I8
;
10106 inst
.instruction
|= Rd
<< 8;
10108 if (inst
.reloc
.exp
.X_op
!= O_constant
)
10109 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_IMM
;
10112 unsigned value
= inst
.reloc
.exp
.X_add_number
;
10116 inst
.error
= _("invalid immediate");
10120 inst
.instruction
|= value
;
10128 thumb_load_store (str
, load_store
, size
)
10133 int Rd
, Rb
, Ro
= FAIL
;
10135 skip_whitespace (str
);
10137 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
10138 || skip_past_comma (&str
) == FAIL
)
10141 inst
.error
= BAD_ARGS
;
10148 if ((Rb
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
10151 if (skip_past_comma (&str
) != FAIL
)
10153 if (is_immediate_prefix (*str
))
10156 if (my_get_expression (&inst
.reloc
.exp
, &str
))
10159 else if ((Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
10164 inst
.reloc
.exp
.X_op
= O_constant
;
10165 inst
.reloc
.exp
.X_add_number
= 0;
10170 inst
.error
= _("expected ']'");
10175 else if (*str
== '=')
10177 if (load_store
!= THUMB_LOAD
)
10179 inst
.error
= _("invalid pseudo operation");
10183 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
10186 skip_whitespace (str
);
10188 if (my_get_expression (& inst
.reloc
.exp
, & str
))
10193 if ( inst
.reloc
.exp
.X_op
!= O_constant
10194 && inst
.reloc
.exp
.X_op
!= O_symbol
)
10196 inst
.error
= "Constant expression expected";
10200 if (inst
.reloc
.exp
.X_op
== O_constant
10201 && ((inst
.reloc
.exp
.X_add_number
& ~0xFF) == 0))
10203 /* This can be done with a mov instruction. */
10205 inst
.instruction
= T_OPCODE_MOV_I8
| (Rd
<< 8);
10206 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
10210 /* Insert into literal pool. */
10211 if (add_to_lit_pool () == FAIL
)
10214 inst
.error
= "literal pool insertion failed";
10218 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
10219 inst
.reloc
.pc_rel
= 1;
10220 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
10221 /* Adjust ARM pipeline offset to Thumb. */
10222 inst
.reloc
.exp
.X_add_number
+= 4;
10228 if (my_get_expression (&inst
.reloc
.exp
, &str
))
10231 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
10232 inst
.reloc
.pc_rel
= 1;
10233 inst
.reloc
.exp
.X_add_number
-= 4; /* Pipeline offset. */
10234 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
10239 if (Rb
== REG_PC
|| Rb
== REG_SP
)
10241 if (size
!= THUMB_WORD
)
10243 inst
.error
= _("byte or halfword not valid for base register");
10246 else if (Rb
== REG_PC
&& load_store
!= THUMB_LOAD
)
10248 inst
.error
= _("r15 based store not allowed");
10251 else if (Ro
!= FAIL
)
10253 inst
.error
= _("invalid base register for register offset");
10258 inst
.instruction
= T_OPCODE_LDR_PC
;
10259 else if (load_store
== THUMB_LOAD
)
10260 inst
.instruction
= T_OPCODE_LDR_SP
;
10262 inst
.instruction
= T_OPCODE_STR_SP
;
10264 inst
.instruction
|= Rd
<< 8;
10265 if (inst
.reloc
.exp
.X_op
== O_constant
)
10267 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
10269 if (offset
& ~0x3fc)
10271 inst
.error
= _("invalid offset");
10275 inst
.instruction
|= offset
>> 2;
10278 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
10282 inst
.error
= _("invalid base register in load/store");
10285 else if (Ro
== FAIL
)
10287 /* Immediate offset. */
10288 if (size
== THUMB_WORD
)
10289 inst
.instruction
= (load_store
== THUMB_LOAD
10290 ? T_OPCODE_LDR_IW
: T_OPCODE_STR_IW
);
10291 else if (size
== THUMB_HALFWORD
)
10292 inst
.instruction
= (load_store
== THUMB_LOAD
10293 ? T_OPCODE_LDR_IH
: T_OPCODE_STR_IH
);
10295 inst
.instruction
= (load_store
== THUMB_LOAD
10296 ? T_OPCODE_LDR_IB
: T_OPCODE_STR_IB
);
10298 inst
.instruction
|= Rd
| (Rb
<< 3);
10300 if (inst
.reloc
.exp
.X_op
== O_constant
)
10302 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
10304 if (offset
& ~(0x1f << size
))
10306 inst
.error
= _("invalid offset");
10309 inst
.instruction
|= (offset
>> size
) << 6;
10312 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
10316 /* Register offset. */
10317 if (size
== THUMB_WORD
)
10318 inst
.instruction
= (load_store
== THUMB_LOAD
10319 ? T_OPCODE_LDR_RW
: T_OPCODE_STR_RW
);
10320 else if (size
== THUMB_HALFWORD
)
10321 inst
.instruction
= (load_store
== THUMB_LOAD
10322 ? T_OPCODE_LDR_RH
: T_OPCODE_STR_RH
);
10324 inst
.instruction
= (load_store
== THUMB_LOAD
10325 ? T_OPCODE_LDR_RB
: T_OPCODE_STR_RB
);
10327 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
10333 /* A register must be given at this point.
10335 Shift is the place to put it in inst.instruction.
10337 Restores input start point on err.
10338 Returns the reg#, or FAIL. */
10341 mav_reg_required_here (str
, shift
, regtype
)
10344 enum arm_reg_type regtype
;
10347 char *start
= *str
;
10349 if ((reg
= arm_reg_parse (str
, all_reg_maps
[regtype
].htab
)) != FAIL
)
10352 inst
.instruction
|= reg
<< shift
;
10357 /* Restore the start point. */
10360 /* In the few cases where we might be able to accept something else
10361 this error can be overridden. */
10362 inst
.error
= _(all_reg_maps
[regtype
].expected
);
10367 /* Cirrus Maverick Instructions. */
10369 /* Wrapper functions. */
10372 do_mav_binops_1a (str
)
10375 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVF
);
10379 do_mav_binops_1b (str
)
10382 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVD
);
10386 do_mav_binops_1c (str
)
10389 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVDX
);
10393 do_mav_binops_1d (str
)
10396 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVF
);
10400 do_mav_binops_1e (str
)
10403 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVD
);
10407 do_mav_binops_1f (str
)
10410 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVF
);
10414 do_mav_binops_1g (str
)
10417 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVD
);
10421 do_mav_binops_1h (str
)
10424 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVFX
);
10428 do_mav_binops_1i (str
)
10431 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVFX
);
10435 do_mav_binops_1j (str
)
10438 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVDX
);
10442 do_mav_binops_1k (str
)
10445 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVDX
);
10449 do_mav_binops_1l (str
)
10452 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVF
);
10456 do_mav_binops_1m (str
)
10459 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVD
);
10463 do_mav_binops_1n (str
)
10466 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
10470 do_mav_binops_1o (str
)
10473 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
10477 do_mav_binops_2a (str
)
10480 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVF
, REG_TYPE_RN
);
10484 do_mav_binops_2b (str
)
10487 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVD
, REG_TYPE_RN
);
10491 do_mav_binops_2c (str
)
10494 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVDX
, REG_TYPE_RN
);
10498 do_mav_binops_3a (str
)
10501 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVFX
);
10505 do_mav_binops_3b (str
)
10508 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVFX
, REG_TYPE_MVAX
);
10512 do_mav_binops_3c (str
)
10515 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVDX
);
10519 do_mav_binops_3d (str
)
10522 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVDX
, REG_TYPE_MVAX
);
10526 do_mav_triple_4a (str
)
10529 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_RN
);
10533 do_mav_triple_4b (str
)
10536 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_RN
);
10540 do_mav_triple_5a (str
)
10543 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVF
, REG_TYPE_MVF
);
10547 do_mav_triple_5b (str
)
10550 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVD
, REG_TYPE_MVD
);
10554 do_mav_triple_5c (str
)
10557 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
10561 do_mav_triple_5d (str
)
10564 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
10568 do_mav_triple_5e (str
)
10571 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVF
, REG_TYPE_MVF
, REG_TYPE_MVF
);
10575 do_mav_triple_5f (str
)
10578 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVD
, REG_TYPE_MVD
, REG_TYPE_MVD
);
10582 do_mav_triple_5g (str
)
10585 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
10589 do_mav_triple_5h (str
)
10592 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
10596 do_mav_quad_6a (str
)
10599 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
,
10604 do_mav_quad_6b (str
)
10607 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVAX
, REG_TYPE_MVFX
,
10611 /* cfmvsc32<cond> DSPSC,MVFX[15:0]. */
10613 do_mav_dspsc_1 (str
)
10616 skip_whitespace (str
);
10619 if (mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
10620 || skip_past_comma (&str
) == FAIL
10621 || mav_reg_required_here (&str
, 16, REG_TYPE_MVFX
) == FAIL
)
10624 inst
.error
= BAD_ARGS
;
10632 /* cfmv32sc<cond> MVFX[15:0],DSPSC. */
10634 do_mav_dspsc_2 (str
)
10637 skip_whitespace (str
);
10640 if (mav_reg_required_here (&str
, 0, REG_TYPE_MVFX
) == FAIL
10641 || skip_past_comma (&str
) == FAIL
10642 || mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
)
10645 inst
.error
= BAD_ARGS
;
10654 do_mav_shift_1 (str
)
10657 do_mav_shift (str
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
10661 do_mav_shift_2 (str
)
10664 do_mav_shift (str
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
10668 do_mav_ldst_1 (str
)
10671 do_mav_ldst (str
, REG_TYPE_MVF
);
10675 do_mav_ldst_2 (str
)
10678 do_mav_ldst (str
, REG_TYPE_MVD
);
10682 do_mav_ldst_3 (str
)
10685 do_mav_ldst (str
, REG_TYPE_MVFX
);
10689 do_mav_ldst_4 (str
)
10692 do_mav_ldst (str
, REG_TYPE_MVDX
);
10695 /* Isnsn like "foo X,Y". */
10698 do_mav_binops (str
, mode
, reg0
, reg1
)
10701 enum arm_reg_type reg0
;
10702 enum arm_reg_type reg1
;
10704 int shift0
, shift1
;
10706 shift0
= mode
& 0xff;
10707 shift1
= (mode
>> 8) & 0xff;
10709 skip_whitespace (str
);
10711 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
10712 || skip_past_comma (&str
) == FAIL
10713 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
)
10716 inst
.error
= BAD_ARGS
;
10722 /* Isnsn like "foo X,Y,Z". */
10725 do_mav_triple (str
, mode
, reg0
, reg1
, reg2
)
10728 enum arm_reg_type reg0
;
10729 enum arm_reg_type reg1
;
10730 enum arm_reg_type reg2
;
10732 int shift0
, shift1
, shift2
;
10734 shift0
= mode
& 0xff;
10735 shift1
= (mode
>> 8) & 0xff;
10736 shift2
= (mode
>> 16) & 0xff;
10738 skip_whitespace (str
);
10740 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
10741 || skip_past_comma (&str
) == FAIL
10742 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
10743 || skip_past_comma (&str
) == FAIL
10744 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
)
10747 inst
.error
= BAD_ARGS
;
10753 /* Isnsn like "foo W,X,Y,Z".
10754 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
10757 do_mav_quad (str
, mode
, reg0
, reg1
, reg2
, reg3
)
10760 enum arm_reg_type reg0
;
10761 enum arm_reg_type reg1
;
10762 enum arm_reg_type reg2
;
10763 enum arm_reg_type reg3
;
10765 int shift0
, shift1
, shift2
, shift3
;
10767 shift0
= mode
& 0xff;
10768 shift1
= (mode
>> 8) & 0xff;
10769 shift2
= (mode
>> 16) & 0xff;
10770 shift3
= (mode
>> 24) & 0xff;
10772 skip_whitespace (str
);
10774 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
10775 || skip_past_comma (&str
) == FAIL
10776 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
10777 || skip_past_comma (&str
) == FAIL
10778 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
10779 || skip_past_comma (&str
) == FAIL
10780 || mav_reg_required_here (&str
, shift3
, reg3
) == FAIL
)
10783 inst
.error
= BAD_ARGS
;
10789 /* Maverick shift immediate instructions.
10790 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
10791 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
10794 do_mav_shift (str
, reg0
, reg1
)
10796 enum arm_reg_type reg0
;
10797 enum arm_reg_type reg1
;
10802 skip_whitespace (str
);
10806 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
10807 || skip_past_comma (&str
) == FAIL
10808 || mav_reg_required_here (&str
, 16, reg1
) == FAIL
10809 || skip_past_comma (&str
) == FAIL
)
10812 inst
.error
= BAD_ARGS
;
10816 /* Calculate the immediate operand.
10817 The operand is a 7bit signed number. */
10818 skip_whitespace (str
);
10823 if (!ISDIGIT (*str
) && *str
!= '-')
10825 inst
.error
= _("expecting immediate, 7bit operand");
10835 for (imm
= 0; *str
&& ISDIGIT (*str
); ++str
)
10836 imm
= imm
* 10 + *str
- '0';
10840 inst
.error
= _("immediate out of range");
10844 /* Make negative imm's into 7bit signed numbers. */
10851 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
10852 Bits 5-7 of the insn should have bits 4-6 of the immediate.
10853 Bit 4 should be 0. */
10854 imm
= (imm
& 0xf) | ((imm
& 0x70) << 1);
10856 inst
.instruction
|= imm
;
10861 mav_parse_offset (str
, negative
)
10870 skip_whitespace (p
);
10883 inst
.error
= _("offset expected");
10887 for (offset
= 0; *p
&& ISDIGIT (*p
); ++p
)
10888 offset
= offset
* 10 + *p
- '0';
10892 inst
.error
= _("offset out of range");
10898 return *negative
? -offset
: offset
;
10901 /* Maverick load/store instructions.
10902 <insn><cond> CRd,[Rn,<offset>]{!}.
10903 <insn><cond> CRd,[Rn],<offset>. */
10906 do_mav_ldst (str
, reg0
)
10908 enum arm_reg_type reg0
;
10910 int offset
, negative
;
10912 skip_whitespace (str
);
10914 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
10915 || skip_past_comma (&str
) == FAIL
10917 || reg_required_here (&str
, 16) == FAIL
)
10920 if (skip_past_comma (&str
) == SUCCESS
)
10922 /* You are here: "<offset>]{!}". */
10923 inst
.instruction
|= PRE_INDEX
;
10925 offset
= mav_parse_offset (&str
, &negative
);
10932 inst
.error
= _("missing ]");
10938 inst
.instruction
|= WRITE_BACK
;
10944 /* You are here: "], <offset>". */
10947 inst
.error
= _("missing ]");
10951 if (skip_past_comma (&str
) == FAIL
10952 || (offset
= mav_parse_offset (&str
, &negative
), inst
.error
))
10955 inst
.instruction
|= CP_T_WB
; /* Post indexed, set bit W. */
10961 inst
.instruction
|= CP_T_UD
; /* Positive, so set bit U. */
10963 inst
.instruction
|= offset
>> 2;
10969 inst
.error
= BAD_ARGS
;
10982 /* Handle the Format 4 instructions that do not have equivalents in other
10983 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
10992 skip_whitespace (str
);
10994 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
10995 || skip_past_comma (&str
) == FAIL
10996 || (Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
10998 inst
.error
= BAD_ARGS
;
11002 if (skip_past_comma (&str
) != FAIL
)
11004 /* Three operand format not allowed for TST, CMN, NEG and MVN.
11005 (It isn't allowed for CMP either, but that isn't handled by this
11007 if (inst
.instruction
== T_OPCODE_TST
11008 || inst
.instruction
== T_OPCODE_CMN
11009 || inst
.instruction
== T_OPCODE_NEG
11010 || inst
.instruction
== T_OPCODE_MVN
)
11012 inst
.error
= BAD_ARGS
;
11016 if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
11021 inst
.error
= _("dest and source1 must be the same register");
11027 if (inst
.instruction
== T_OPCODE_MUL
11029 as_tsktsk (_("Rs and Rd must be different in MUL"));
11031 inst
.instruction
|= Rd
| (Rs
<< 3);
11039 thumb_add_sub (str
, 0);
11046 thumb_shift (str
, THUMB_ASR
);
11053 if (my_get_expression (&inst
.reloc
.exp
, &str
))
11055 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH9
;
11056 inst
.reloc
.pc_rel
= 1;
11061 do_t_branch12 (str
)
11064 if (my_get_expression (&inst
.reloc
.exp
, &str
))
11066 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH12
;
11067 inst
.reloc
.pc_rel
= 1;
11071 /* Find the real, Thumb encoded start of a Thumb function. */
11074 find_real_start (symbolP
)
11078 const char * name
= S_GET_NAME (symbolP
);
11079 symbolS
* new_target
;
11081 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
11082 #define STUB_NAME ".real_start_of"
11087 /* Names that start with '.' are local labels, not function entry points.
11088 The compiler may generate BL instructions to these labels because it
11089 needs to perform a branch to a far away location. */
11090 if (name
[0] == '.')
11093 real_start
= malloc (strlen (name
) + strlen (STUB_NAME
) + 1);
11094 sprintf (real_start
, "%s%s", STUB_NAME
, name
);
11096 new_target
= symbol_find (real_start
);
11098 if (new_target
== NULL
)
11100 as_warn ("Failed to find real start of function: %s\n", name
);
11101 new_target
= symbolP
;
11110 do_t_branch23 (str
)
11113 if (my_get_expression (& inst
.reloc
.exp
, & str
))
11116 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH23
;
11117 inst
.reloc
.pc_rel
= 1;
11120 /* If the destination of the branch is a defined symbol which does not have
11121 the THUMB_FUNC attribute, then we must be calling a function which has
11122 the (interfacearm) attribute. We look for the Thumb entry point to that
11123 function and change the branch to refer to that function instead. */
11124 if ( inst
.reloc
.exp
.X_op
== O_symbol
11125 && inst
.reloc
.exp
.X_add_symbol
!= NULL
11126 && S_IS_DEFINED (inst
.reloc
.exp
.X_add_symbol
)
11127 && ! THUMB_IS_FUNC (inst
.reloc
.exp
.X_add_symbol
))
11128 inst
.reloc
.exp
.X_add_symbol
=
11129 find_real_start (inst
.reloc
.exp
.X_add_symbol
);
11138 skip_whitespace (str
);
11140 if ((reg
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
11143 /* This sets THUMB_H2 from the top bit of reg. */
11144 inst
.instruction
|= reg
<< 3;
11146 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
11147 should cause the alignment to be checked once it is known. This is
11148 because BX PC only works if the instruction is word aligned. */
11157 thumb_mov_compare (str
, THUMB_COMPARE
);
11167 skip_whitespace (str
);
11169 if ((Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
11173 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
11177 if (skip_past_comma (&str
) == FAIL
11178 || (range
= reg_list (&str
)) == FAIL
)
11181 inst
.error
= BAD_ARGS
;
11185 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
11187 /* This really doesn't seem worth it. */
11188 inst
.reloc
.type
= BFD_RELOC_NONE
;
11189 inst
.error
= _("expression too complex");
11195 inst
.error
= _("only lo-regs valid in load/store multiple");
11199 inst
.instruction
|= (Rb
<< 8) | range
;
11207 thumb_load_store (str
, THUMB_LOAD
, THUMB_WORD
);
11214 thumb_load_store (str
, THUMB_LOAD
, THUMB_BYTE
);
11221 thumb_load_store (str
, THUMB_LOAD
, THUMB_HALFWORD
);
11230 skip_whitespace (str
);
11232 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
11233 || skip_past_comma (&str
) == FAIL
11235 || (Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
11236 || skip_past_comma (&str
) == FAIL
11237 || (Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
11241 inst
.error
= _("syntax: ldrs[b] Rd, [Rb, Ro]");
11245 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
11253 thumb_shift (str
, THUMB_LSL
);
11260 thumb_shift (str
, THUMB_LSR
);
11267 thumb_mov_compare (str
, THUMB_MOVE
);
11271 do_t_push_pop (str
)
11276 skip_whitespace (str
);
11278 if ((range
= reg_list (&str
)) == FAIL
)
11281 inst
.error
= BAD_ARGS
;
11285 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
11287 /* This really doesn't seem worth it. */
11288 inst
.reloc
.type
= BFD_RELOC_NONE
;
11289 inst
.error
= _("expression too complex");
11295 if ((inst
.instruction
== T_OPCODE_PUSH
11296 && (range
& ~0xff) == 1 << REG_LR
)
11297 || (inst
.instruction
== T_OPCODE_POP
11298 && (range
& ~0xff) == 1 << REG_PC
))
11300 inst
.instruction
|= THUMB_PP_PC_LR
;
11305 inst
.error
= _("invalid register list to push/pop instruction");
11310 inst
.instruction
|= range
;
11318 thumb_load_store (str
, THUMB_STORE
, THUMB_WORD
);
11325 thumb_load_store (str
, THUMB_STORE
, THUMB_BYTE
);
11332 thumb_load_store (str
, THUMB_STORE
, THUMB_HALFWORD
);
11339 thumb_add_sub (str
, 1);
11346 skip_whitespace (str
);
11348 if (my_get_expression (&inst
.reloc
.exp
, &str
))
11351 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
11362 /* This is a pseudo-op of the form "adr rd, label" to be converted
11363 into a relative address of the form "add rd, pc, #label-.-4". */
11364 skip_whitespace (str
);
11366 /* Store Rd in temporary location inside instruction. */
11367 if ((reg
= reg_required_here (&str
, 4)) == FAIL
11368 || (reg
> 7) /* For Thumb reg must be r0..r7. */
11369 || skip_past_comma (&str
) == FAIL
11370 || my_get_expression (&inst
.reloc
.exp
, &str
))
11373 inst
.error
= BAD_ARGS
;
11377 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
11378 inst
.reloc
.exp
.X_add_number
-= 4; /* PC relative adjust. */
11379 inst
.reloc
.pc_rel
= 1;
11380 inst
.instruction
|= REG_PC
; /* Rd is already placed into the instruction. */
11386 insert_reg (r
, htab
)
11387 const struct reg_entry
*r
;
11388 struct hash_control
*htab
;
11390 int len
= strlen (r
->name
) + 2;
11391 char * buf
= (char *) xmalloc (len
);
11392 char * buf2
= (char *) xmalloc (len
);
11395 #ifdef REGISTER_PREFIX
11396 buf
[i
++] = REGISTER_PREFIX
;
11399 strcpy (buf
+ i
, r
->name
);
11401 for (i
= 0; buf
[i
]; i
++)
11402 buf2
[i
] = TOUPPER (buf
[i
]);
11406 hash_insert (htab
, buf
, (PTR
) r
);
11407 hash_insert (htab
, buf2
, (PTR
) r
);
11411 build_reg_hsh (map
)
11412 struct reg_map
*map
;
11414 const struct reg_entry
*r
;
11416 if ((map
->htab
= hash_new ()) == NULL
)
11417 as_fatal (_("virtual memory exhausted"));
11419 for (r
= map
->names
; r
->name
!= NULL
; r
++)
11420 insert_reg (r
, map
->htab
);
11424 insert_reg_alias (str
, regnum
, htab
)
11427 struct hash_control
*htab
;
11430 struct reg_entry
*new = xmalloc (sizeof (struct reg_entry
));
11431 const char *name
= xmalloc (strlen (str
) + 1);
11433 strcpy ((char *) name
, str
);
11436 new->number
= regnum
;
11437 new->builtin
= FALSE
;
11439 error
= hash_insert (htab
, name
, (PTR
) new);
11442 as_bad (_("failed to create an alias for %s, reason: %s"),
11444 free ((char *) name
);
11449 /* Look for the .req directive. This is of the form:
11451 new_register_name .req existing_register_name
11453 If we find one, or if it looks sufficiently like one that we want to
11454 handle any error here, return non-zero. Otherwise return zero. */
11456 create_register_alias (newname
, p
)
11464 skip_whitespace (q
);
11469 if (*q
&& !strncmp (q
, ".req ", 5))
11474 #ifdef IGNORE_OPCODE_CASE
11475 newname
= original_case_string
;
11477 copy_of_str
= newname
;
11480 skip_whitespace (q
);
11482 for (r
= q
; *r
!= '\0'; r
++)
11488 enum arm_reg_type new_type
, old_type
;
11493 old_type
= arm_reg_parse_any (q
);
11496 new_type
= arm_reg_parse_any (newname
);
11498 if (new_type
== REG_TYPE_MAX
)
11500 if (old_type
!= REG_TYPE_MAX
)
11502 old_regno
= arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
);
11503 insert_reg_alias (newname
, old_regno
,
11504 all_reg_maps
[old_type
].htab
);
11507 as_warn (_("register '%s' does not exist\n"), q
);
11509 else if (old_type
== REG_TYPE_MAX
)
11511 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
11516 /* Do not warn about redefinitions to the same alias. */
11517 if (new_type
!= old_type
11518 || (arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
)
11519 != arm_reg_parse (&q
, all_reg_maps
[new_type
].htab
)))
11520 as_warn (_("ignoring redefinition of register alias '%s'"),
11526 as_warn (_("ignoring incomplete .req pseuso op"));
11537 set_constant_flonums ()
11541 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
11542 if (atof_ieee ((char *) fp_const
[i
], 'x', fp_values
[i
]) == NULL
)
11546 /* Iterate over the base tables to create the instruction patterns. */
11548 build_arm_ops_hsh ()
11552 static struct obstack insn_obstack
;
11554 obstack_begin (&insn_obstack
, 4000);
11556 for (i
= 0; i
< sizeof (insns
) / sizeof (struct asm_opcode
); i
++)
11558 const struct asm_opcode
*insn
= insns
+ i
;
11560 if (insn
->cond_offset
!= 0)
11562 /* Insn supports conditional execution. Build the varaints
11563 and insert them in the hash table. */
11564 for (j
= 0; j
< sizeof (conds
) / sizeof (struct asm_cond
); j
++)
11566 unsigned len
= strlen (insn
->template);
11567 struct asm_opcode
*new;
11570 new = obstack_alloc (&insn_obstack
, sizeof (struct asm_opcode
));
11571 /* All condition codes are two characters. */
11572 template = obstack_alloc (&insn_obstack
, len
+ 3);
11574 strncpy (template, insn
->template, insn
->cond_offset
);
11575 strcpy (template + insn
->cond_offset
, conds
[j
].template);
11576 if (len
> insn
->cond_offset
)
11577 strcpy (template + insn
->cond_offset
+ 2,
11578 insn
->template + insn
->cond_offset
);
11579 new->template = template;
11580 new->cond_offset
= 0;
11581 new->variant
= insn
->variant
;
11582 new->parms
= insn
->parms
;
11583 new->value
= (insn
->value
& ~COND_MASK
) | conds
[j
].value
;
11585 hash_insert (arm_ops_hsh
, new->template, (PTR
) new);
11588 /* Finally, insert the unconditional insn in the table directly;
11589 no need to build a copy. */
11590 hash_insert (arm_ops_hsh
, insn
->template, (PTR
) insn
);
11594 #if 0 /* Suppressed - for now. */
11595 #if defined OBJ_ELF || defined OBJ_COFF
11598 #define arm_Note Elf_External_Note
11602 unsigned char namesz
[4]; /* Size of entry's owner string. */
11603 unsigned char descsz
[4]; /* Size of the note descriptor. */
11604 unsigned char type
[4]; /* Interpretation of the descriptor. */
11605 char name
[1]; /* Start of the name+desc data. */
11609 /* The description is kept to a fix sized in order to make updating
11610 it and merging it easier. */
11611 #define ARM_NOTE_DESCRIPTION_LENGTH 8
11614 arm_add_note (name
, description
, type
)
11616 const char * description
;
11619 arm_Note note ATTRIBUTE_UNUSED
;
11621 unsigned int name_len
;
11623 name_len
= (strlen (name
) + 1 + 3) & ~3;
11625 p
= frag_more (sizeof (note
.namesz
));
11626 md_number_to_chars (p
, (valueT
) name_len
, sizeof (note
.namesz
));
11628 p
= frag_more (sizeof (note
.descsz
));
11629 md_number_to_chars (p
, (valueT
) ARM_NOTE_DESCRIPTION_LENGTH
, sizeof (note
.descsz
));
11631 p
= frag_more (sizeof (note
.type
));
11632 md_number_to_chars (p
, (valueT
) type
, sizeof (note
.type
));
11634 p
= frag_more (name_len
);
11637 p
= frag_more (ARM_NOTE_DESCRIPTION_LENGTH
);
11638 strncpy (p
, description
, ARM_NOTE_DESCRIPTION_LENGTH
);
11639 frag_align (2, 0, 0);
11650 if ( (arm_ops_hsh
= hash_new ()) == NULL
11651 || (arm_tops_hsh
= hash_new ()) == NULL
11652 || (arm_cond_hsh
= hash_new ()) == NULL
11653 || (arm_shift_hsh
= hash_new ()) == NULL
11654 || (arm_psr_hsh
= hash_new ()) == NULL
)
11655 as_fatal (_("virtual memory exhausted"));
11657 build_arm_ops_hsh ();
11658 for (i
= 0; i
< sizeof (tinsns
) / sizeof (struct thumb_opcode
); i
++)
11659 hash_insert (arm_tops_hsh
, tinsns
[i
].template, (PTR
) (tinsns
+ i
));
11660 for (i
= 0; i
< sizeof (conds
) / sizeof (struct asm_cond
); i
++)
11661 hash_insert (arm_cond_hsh
, conds
[i
].template, (PTR
) (conds
+ i
));
11662 for (i
= 0; i
< sizeof (shift_names
) / sizeof (struct asm_shift_name
); i
++)
11663 hash_insert (arm_shift_hsh
, shift_names
[i
].name
, (PTR
) (shift_names
+ i
));
11664 for (i
= 0; i
< sizeof (psrs
) / sizeof (struct asm_psr
); i
++)
11665 hash_insert (arm_psr_hsh
, psrs
[i
].template, (PTR
) (psrs
+ i
));
11667 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
11668 build_reg_hsh (all_reg_maps
+ i
);
11670 set_constant_flonums ();
11672 /* Set the cpu variant based on the command-line options. We prefer
11673 -mcpu= over -march= if both are set (as for GCC); and we prefer
11674 -mfpu= over any other way of setting the floating point unit.
11675 Use of legacy options with new options are faulted. */
11676 if (legacy_cpu
!= -1)
11678 if (mcpu_cpu_opt
!= -1 || march_cpu_opt
!= -1)
11679 as_bad (_("use of old and new-style options to set CPU type"));
11681 mcpu_cpu_opt
= legacy_cpu
;
11683 else if (mcpu_cpu_opt
== -1)
11684 mcpu_cpu_opt
= march_cpu_opt
;
11686 if (legacy_fpu
!= -1)
11688 if (mfpu_opt
!= -1)
11689 as_bad (_("use of old and new-style options to set FPU type"));
11691 mfpu_opt
= legacy_fpu
;
11693 else if (mfpu_opt
== -1)
11695 #if !(defined (TE_LINUX) || defined (TE_NetBSD))
11696 /* Some environments specify a default FPU. If they don't, infer it
11697 from the processor. */
11698 if (mcpu_fpu_opt
!= -1)
11699 mfpu_opt
= mcpu_fpu_opt
;
11701 mfpu_opt
= march_fpu_opt
;
11703 mfpu_opt
= FPU_DEFAULT
;
11707 if (mfpu_opt
== -1)
11709 if (mcpu_cpu_opt
== -1)
11710 mfpu_opt
= FPU_DEFAULT
;
11711 else if (mcpu_cpu_opt
& ARM_EXT_V5
)
11712 mfpu_opt
= FPU_ARCH_VFP_V2
;
11714 mfpu_opt
= FPU_ARCH_FPA
;
11717 if (mcpu_cpu_opt
== -1)
11718 mcpu_cpu_opt
= CPU_DEFAULT
;
11720 cpu_variant
= mcpu_cpu_opt
| mfpu_opt
;
11722 #if defined OBJ_COFF || defined OBJ_ELF
11724 unsigned int flags
= 0;
11726 /* Set the flags in the private structure. */
11727 if (uses_apcs_26
) flags
|= F_APCS26
;
11728 if (support_interwork
) flags
|= F_INTERWORK
;
11729 if (uses_apcs_float
) flags
|= F_APCS_FLOAT
;
11730 if (pic_code
) flags
|= F_PIC
;
11731 if ((cpu_variant
& FPU_ANY
) == FPU_NONE
11732 || (cpu_variant
& FPU_ANY
) == FPU_ARCH_VFP
) /* VFP layout only. */
11733 flags
|= F_SOFT_FLOAT
;
11734 /* Using VFP conventions (even if soft-float). */
11735 if (cpu_variant
& FPU_VFP_EXT_NONE
) flags
|= F_VFP_FLOAT
;
11737 #if defined OBJ_ELF
11738 if (cpu_variant
& ARM_CEXT_MAVERICK
)
11740 flags
&= ~ F_SOFT_FLOAT
;
11741 flags
|= EF_ARM_MAVERICK_FLOAT
;
11745 bfd_set_private_flags (stdoutput
, flags
);
11747 /* We have run out flags in the COFF header to encode the
11748 status of ATPCS support, so instead we create a dummy,
11749 empty, debug section called .arm.atpcs. */
11754 sec
= bfd_make_section (stdoutput
, ".arm.atpcs");
11758 bfd_set_section_flags
11759 (stdoutput
, sec
, SEC_READONLY
| SEC_DEBUGGING
/* | SEC_HAS_CONTENTS */);
11760 bfd_set_section_size (stdoutput
, sec
, 0);
11761 bfd_set_section_contents (stdoutput
, sec
, NULL
, 0, 0);
11767 /* Record the CPU type as well. */
11768 switch (cpu_variant
& ARM_CPU_MASK
)
11771 mach
= bfd_mach_arm_2
;
11774 case ARM_3
: /* Also ARM_250. */
11775 mach
= bfd_mach_arm_2a
;
11778 case ARM_6
: /* Also ARM_7. */
11779 mach
= bfd_mach_arm_3
;
11783 mach
= bfd_mach_arm_unknown
;
11787 /* Catch special cases. */
11788 if (cpu_variant
& ARM_CEXT_IWMMXT
)
11789 mach
= bfd_mach_arm_iWMMXt
;
11790 else if (cpu_variant
& ARM_CEXT_XSCALE
)
11791 mach
= bfd_mach_arm_XScale
;
11792 else if (cpu_variant
& ARM_CEXT_MAVERICK
)
11793 mach
= bfd_mach_arm_ep9312
;
11794 else if (cpu_variant
& ARM_EXT_V5E
)
11795 mach
= bfd_mach_arm_5TE
;
11796 else if (cpu_variant
& ARM_EXT_V5
)
11798 if (cpu_variant
& ARM_EXT_V4T
)
11799 mach
= bfd_mach_arm_5T
;
11801 mach
= bfd_mach_arm_5
;
11803 else if (cpu_variant
& ARM_EXT_V4
)
11805 if (cpu_variant
& ARM_EXT_V4T
)
11806 mach
= bfd_mach_arm_4T
;
11808 mach
= bfd_mach_arm_4
;
11810 else if (cpu_variant
& ARM_EXT_V3M
)
11811 mach
= bfd_mach_arm_3M
;
11813 #if 0 /* Suppressed - for now. */
11814 #if defined (OBJ_ELF) || defined (OBJ_COFF)
11816 /* Create a .note section to fully identify this arm binary. */
11818 #define NOTE_ARCH_STRING "arch: "
11820 #if defined OBJ_COFF && ! defined NT_VERSION
11821 #define NT_VERSION 1
11826 segT current_seg
= now_seg
;
11827 subsegT current_subseg
= now_subseg
;
11828 asection
* arm_arch
;
11829 const char * arch_string
;
11831 arm_arch
= bfd_make_section_old_way (stdoutput
, ARM_NOTE_SECTION
);
11834 bfd_set_section_flags (stdoutput
, arm_arch
,
11835 SEC_DATA
| SEC_ALLOC
| SEC_LOAD
| SEC_LINK_ONCE \
11836 | SEC_HAS_CONTENTS
);
11838 arm_arch
->output_section
= arm_arch
;
11839 subseg_set (arm_arch
, 0);
11844 case bfd_mach_arm_unknown
: arch_string
= "unknown"; break;
11845 case bfd_mach_arm_2
: arch_string
= "armv2"; break;
11846 case bfd_mach_arm_2a
: arch_string
= "armv2a"; break;
11847 case bfd_mach_arm_3
: arch_string
= "armv3"; break;
11848 case bfd_mach_arm_3M
: arch_string
= "armv3M"; break;
11849 case bfd_mach_arm_4
: arch_string
= "armv4"; break;
11850 case bfd_mach_arm_4T
: arch_string
= "armv4t"; break;
11851 case bfd_mach_arm_5
: arch_string
= "armv5"; break;
11852 case bfd_mach_arm_5T
: arch_string
= "armv5t"; break;
11853 case bfd_mach_arm_5TE
: arch_string
= "armv5te"; break;
11854 case bfd_mach_arm_XScale
: arch_string
= "XScale"; break;
11855 case bfd_mach_arm_ep9312
: arch_string
= "ep9312"; break;
11856 case bfd_mach_arm_iWMMXt
: arch_string
= "iWMMXt"; break;
11859 arm_add_note (NOTE_ARCH_STRING
, arch_string
, NT_ARCH
);
11861 subseg_set (current_seg
, current_subseg
);
11864 #endif /* Suppressed code. */
11866 bfd_set_arch_mach (stdoutput
, TARGET_ARCH
, mach
);
11869 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11870 for use in the a.out file, and stores them in the array pointed to by buf.
11871 This knows about the endian-ness of the target machine and does
11872 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11873 2 (short) and 4 (long) Floating numbers are put out as a series of
11874 LITTLENUMS (shorts, here at least). */
11877 md_number_to_chars (buf
, val
, n
)
11882 if (target_big_endian
)
11883 number_to_chars_bigendian (buf
, val
, n
);
11885 number_to_chars_littleendian (buf
, val
, n
);
11889 md_chars_to_number (buf
, n
)
11894 unsigned char * where
= (unsigned char *) buf
;
11896 if (target_big_endian
)
11901 result
|= (*where
++ & 255);
11909 result
|= (where
[n
] & 255);
11916 /* Turn a string in input_line_pointer into a floating point constant
11917 of type TYPE, and store the appropriate bytes in *LITP. The number
11918 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11919 returned, or NULL on OK.
11921 Note that fp constants aren't represent in the normal way on the ARM.
11922 In big endian mode, things are as expected. However, in little endian
11923 mode fp constants are big-endian word-wise, and little-endian byte-wise
11924 within the words. For example, (double) 1.1 in big endian mode is
11925 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11926 the byte sequence 99 99 f1 3f 9a 99 99 99.
11928 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11931 md_atof (type
, litP
, sizeP
)
11937 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
11969 return _("bad call to MD_ATOF()");
11972 t
= atof_ieee (input_line_pointer
, type
, words
);
11974 input_line_pointer
= t
;
11977 if (target_big_endian
)
11979 for (i
= 0; i
< prec
; i
++)
11981 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
11987 if (cpu_variant
& FPU_ARCH_VFP
)
11988 for (i
= prec
- 1; i
>= 0; i
--)
11990 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
11994 /* For a 4 byte float the order of elements in `words' is 1 0.
11995 For an 8 byte float the order is 1 0 3 2. */
11996 for (i
= 0; i
< prec
; i
+= 2)
11998 md_number_to_chars (litP
, (valueT
) words
[i
+ 1], 2);
11999 md_number_to_chars (litP
+ 2, (valueT
) words
[i
], 2);
12007 /* The knowledge of the PC's pipeline offset is built into the insns
12011 md_pcrel_from (fixP
)
12015 && S_GET_SEGMENT (fixP
->fx_addsy
) == undefined_section
12016 && fixP
->fx_subsy
== NULL
)
12019 if (fixP
->fx_pcrel
&& (fixP
->fx_r_type
== BFD_RELOC_ARM_THUMB_ADD
))
12021 /* PC relative addressing on the Thumb is slightly odd
12022 as the bottom two bits of the PC are forced to zero
12023 for the calculation. */
12024 return (fixP
->fx_where
+ fixP
->fx_frag
->fr_address
) & ~3;
12028 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
12029 so we un-adjust here to compensate for the accommodation. */
12030 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
+ 8;
12032 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
12036 /* Round up a section size to the appropriate boundary. */
12039 md_section_align (segment
, size
)
12040 segT segment ATTRIBUTE_UNUSED
;
12046 /* Round all sects to multiple of 4. */
12047 return (size
+ 3) & ~3;
12051 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
12052 Otherwise we have no need to default values of symbols. */
12055 md_undefined_symbol (name
)
12056 char * name ATTRIBUTE_UNUSED
;
12059 if (name
[0] == '_' && name
[1] == 'G'
12060 && streq (name
, GLOBAL_OFFSET_TABLE_NAME
))
12064 if (symbol_find (name
))
12065 as_bad ("GOT already in the symbol table");
12067 GOT_symbol
= symbol_new (name
, undefined_section
,
12068 (valueT
) 0, & zero_address_frag
);
12078 /* arm_reg_parse () := if it looks like a register, return its token and
12079 advance the pointer. */
12082 arm_reg_parse (ccp
, htab
)
12083 register char ** ccp
;
12084 struct hash_control
*htab
;
12086 char * start
= * ccp
;
12089 struct reg_entry
* reg
;
12091 #ifdef REGISTER_PREFIX
12092 if (*start
!= REGISTER_PREFIX
)
12097 #ifdef OPTIONAL_REGISTER_PREFIX
12098 if (*p
== OPTIONAL_REGISTER_PREFIX
)
12102 if (!ISALPHA (*p
) || !is_name_beginner (*p
))
12106 while (ISALPHA (c
) || ISDIGIT (c
) || c
== '_')
12110 reg
= (struct reg_entry
*) hash_find (htab
, start
);
12116 return reg
->number
;
12122 /* Search for the following register name in each of the possible reg name
12123 tables. Return the classification if found, or REG_TYPE_MAX if not
12125 static enum arm_reg_type
12126 arm_reg_parse_any (cp
)
12131 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
12132 if (arm_reg_parse (&cp
, all_reg_maps
[i
].htab
) != FAIL
)
12133 return (enum arm_reg_type
) i
;
12135 return REG_TYPE_MAX
;
12139 md_apply_fix3 (fixP
, valP
, seg
)
12144 offsetT value
= * valP
;
12146 unsigned int newimm
;
12147 unsigned long temp
;
12149 char * buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
12150 arm_fix_data
* arm_data
= (arm_fix_data
*) fixP
->tc_fix_data
;
12152 assert (fixP
->fx_r_type
< BFD_RELOC_UNUSED
);
12154 /* Note whether this will delete the relocation. */
12156 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
12157 doesn't work fully.) */
12158 if ((fixP
->fx_addsy
== 0 || symbol_constant_p (fixP
->fx_addsy
))
12159 && !fixP
->fx_pcrel
)
12161 if (fixP
->fx_addsy
== 0 && !fixP
->fx_pcrel
)
12165 /* If this symbol is in a different section then we need to leave it for
12166 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
12167 so we have to undo it's effects here. */
12168 if (fixP
->fx_pcrel
)
12170 if (fixP
->fx_addsy
!= NULL
12171 && S_IS_DEFINED (fixP
->fx_addsy
)
12172 && S_GET_SEGMENT (fixP
->fx_addsy
) != seg
)
12175 && (fixP
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
12176 || fixP
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
12180 value
+= md_pcrel_from (fixP
);
12184 /* Remember value for emit_reloc. */
12185 fixP
->fx_addnumber
= value
;
12187 switch (fixP
->fx_r_type
)
12189 case BFD_RELOC_ARM_IMMEDIATE
:
12190 newimm
= validate_immediate (value
);
12191 temp
= md_chars_to_number (buf
, INSN_SIZE
);
12193 /* If the instruction will fail, see if we can fix things up by
12194 changing the opcode. */
12195 if (newimm
== (unsigned int) FAIL
12196 && (newimm
= negate_data_op (&temp
, value
)) == (unsigned int) FAIL
)
12198 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12199 _("invalid constant (%lx) after fixup"),
12200 (unsigned long) value
);
12204 newimm
|= (temp
& 0xfffff000);
12205 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
12209 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
12211 unsigned int highpart
= 0;
12212 unsigned int newinsn
= 0xe1a00000; /* nop. */
12214 newimm
= validate_immediate (value
);
12215 temp
= md_chars_to_number (buf
, INSN_SIZE
);
12217 /* If the instruction will fail, see if we can fix things up by
12218 changing the opcode. */
12219 if (newimm
== (unsigned int) FAIL
12220 && (newimm
= negate_data_op (& temp
, value
)) == (unsigned int) FAIL
)
12222 /* No ? OK - try using two ADD instructions to generate
12224 newimm
= validate_immediate_twopart (value
, & highpart
);
12226 /* Yes - then make sure that the second instruction is
12228 if (newimm
!= (unsigned int) FAIL
)
12230 /* Still No ? Try using a negated value. */
12231 else if ((newimm
= validate_immediate_twopart (- value
, & highpart
)) != (unsigned int) FAIL
)
12232 temp
= newinsn
= (temp
& OPCODE_MASK
) | OPCODE_SUB
<< DATA_OP_SHIFT
;
12233 /* Otherwise - give up. */
12236 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12237 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
12242 /* Replace the first operand in the 2nd instruction (which
12243 is the PC) with the destination register. We have
12244 already added in the PC in the first instruction and we
12245 do not want to do it again. */
12246 newinsn
&= ~ 0xf0000;
12247 newinsn
|= ((newinsn
& 0x0f000) << 4);
12250 newimm
|= (temp
& 0xfffff000);
12251 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
12253 highpart
|= (newinsn
& 0xfffff000);
12254 md_number_to_chars (buf
+ INSN_SIZE
, (valueT
) highpart
, INSN_SIZE
);
12258 case BFD_RELOC_ARM_OFFSET_IMM
:
12264 if (validate_offset_imm (value
, 0) == FAIL
)
12266 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12267 _("bad immediate value for offset (%ld)"),
12272 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12273 newval
&= 0xff7ff000;
12274 newval
|= value
| (sign
? INDEX_UP
: 0);
12275 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12278 case BFD_RELOC_ARM_OFFSET_IMM8
:
12279 case BFD_RELOC_ARM_HWLITERAL
:
12285 if (validate_offset_imm (value
, 1) == FAIL
)
12287 if (fixP
->fx_r_type
== BFD_RELOC_ARM_HWLITERAL
)
12288 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12289 _("invalid literal constant: pool needs to be closer"));
12291 as_bad (_("bad immediate value for half-word offset (%ld)"),
12296 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12297 newval
&= 0xff7ff0f0;
12298 newval
|= ((value
>> 4) << 8) | (value
& 0xf) | (sign
? INDEX_UP
: 0);
12299 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12302 case BFD_RELOC_ARM_LITERAL
:
12308 if (validate_offset_imm (value
, 0) == FAIL
)
12310 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12311 _("invalid literal constant: pool needs to be closer"));
12315 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12316 newval
&= 0xff7ff000;
12317 newval
|= value
| (sign
? INDEX_UP
: 0);
12318 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12321 case BFD_RELOC_ARM_SHIFT_IMM
:
12322 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12323 if (((unsigned long) value
) > 32
12325 && (((newval
& 0x60) == 0) || (newval
& 0x60) == 0x60)))
12327 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12328 _("shift expression is too large"));
12333 /* Shifts of zero must be done as lsl. */
12335 else if (value
== 32)
12337 newval
&= 0xfffff07f;
12338 newval
|= (value
& 0x1f) << 7;
12339 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12342 case BFD_RELOC_ARM_SWI
:
12343 if (arm_data
->thumb_mode
)
12345 if (((unsigned long) value
) > 0xff)
12346 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12347 _("invalid swi expression"));
12348 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xff00;
12350 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12354 if (((unsigned long) value
) > 0x00ffffff)
12355 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12356 _("invalid swi expression"));
12357 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff000000;
12359 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12363 case BFD_RELOC_ARM_MULTI
:
12364 if (((unsigned long) value
) > 0xffff)
12365 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12366 _("invalid expression in load/store multiple"));
12367 newval
= value
| md_chars_to_number (buf
, INSN_SIZE
);
12368 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12371 case BFD_RELOC_ARM_PCREL_BRANCH
:
12372 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12374 /* Sign-extend a 24-bit number. */
12375 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
12379 value
= fixP
->fx_offset
;
12382 /* We are going to store value (shifted right by two) in the
12383 instruction, in a 24 bit, signed field. Thus we need to check
12384 that none of the top 8 bits of the shifted value (top 7 bits of
12385 the unshifted, unsigned value) are set, or that they are all set. */
12386 if ((value
& ~ ((offsetT
) 0x1ffffff)) != 0
12387 && ((value
& ~ ((offsetT
) 0x1ffffff)) != ~ ((offsetT
) 0x1ffffff)))
12390 /* Normally we would be stuck at this point, since we cannot store
12391 the absolute address that is the destination of the branch in the
12392 24 bits of the branch instruction. If however, we happen to know
12393 that the destination of the branch is in the same section as the
12394 branch instruction itself, then we can compute the relocation for
12395 ourselves and not have to bother the linker with it.
12397 FIXME: The tests for OBJ_ELF and ! target_oabi are only here
12398 because I have not worked out how to do this for OBJ_COFF or
12401 && fixP
->fx_addsy
!= NULL
12402 && S_IS_DEFINED (fixP
->fx_addsy
)
12403 && S_GET_SEGMENT (fixP
->fx_addsy
) == seg
)
12405 /* Get pc relative value to go into the branch. */
12408 /* Permit a backward branch provided that enough bits
12409 are set. Allow a forwards branch, provided that
12410 enough bits are clear. */
12411 if ( (value
& ~ ((offsetT
) 0x1ffffff)) == ~ ((offsetT
) 0x1ffffff)
12412 || (value
& ~ ((offsetT
) 0x1ffffff)) == 0)
12416 if (! fixP
->fx_done
)
12418 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12419 _("GAS can't handle same-section branch dest >= 0x04000000"));
12423 value
+= SEXT24 (newval
);
12425 if ( (value
& ~ ((offsetT
) 0xffffff)) != 0
12426 && ((value
& ~ ((offsetT
) 0xffffff)) != ~ ((offsetT
) 0xffffff)))
12427 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12428 _("out of range branch"));
12430 newval
= (value
& 0x00ffffff) | (newval
& 0xff000000);
12431 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12434 case BFD_RELOC_ARM_PCREL_BLX
:
12437 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12441 value
= fixP
->fx_offset
;
12443 hbit
= (value
>> 1) & 1;
12444 value
= (value
>> 2) & 0x00ffffff;
12445 value
= (value
+ (newval
& 0x00ffffff)) & 0x00ffffff;
12446 newval
= value
| (newval
& 0xfe000000) | (hbit
<< 24);
12447 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12451 case BFD_RELOC_THUMB_PCREL_BRANCH9
: /* Conditional branch. */
12452 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12454 addressT diff
= (newval
& 0xff) << 1;
12459 if ((value
& ~0xff) && ((value
& ~0xff) != ~0xff))
12460 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12461 _("branch out of range"));
12462 newval
= (newval
& 0xff00) | ((value
& 0x1ff) >> 1);
12464 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12467 case BFD_RELOC_THUMB_PCREL_BRANCH12
: /* Unconditional branch. */
12468 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12470 addressT diff
= (newval
& 0x7ff) << 1;
12475 if ((value
& ~0x7ff) && ((value
& ~0x7ff) != ~0x7ff))
12476 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12477 _("branch out of range"));
12478 newval
= (newval
& 0xf800) | ((value
& 0xfff) >> 1);
12480 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12483 case BFD_RELOC_THUMB_PCREL_BLX
:
12484 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
12489 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12490 newval2
= md_chars_to_number (buf
+ THUMB_SIZE
, THUMB_SIZE
);
12491 diff
= ((newval
& 0x7ff) << 12) | ((newval2
& 0x7ff) << 1);
12492 if (diff
& 0x400000)
12495 value
= fixP
->fx_offset
;
12499 if ((value
& ~0x3fffff) && ((value
& ~0x3fffff) != ~0x3fffff))
12500 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12501 _("branch with link out of range"));
12503 newval
= (newval
& 0xf800) | ((value
& 0x7fffff) >> 12);
12504 newval2
= (newval2
& 0xf800) | ((value
& 0xfff) >> 1);
12505 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
)
12506 /* For a BLX instruction, make sure that the relocation is rounded up
12507 to a word boundary. This follows the semantics of the instruction
12508 which specifies that bit 1 of the target address will come from bit
12509 1 of the base address. */
12510 newval2
= (newval2
+ 1) & ~ 1;
12511 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12512 md_number_to_chars (buf
+ THUMB_SIZE
, newval2
, THUMB_SIZE
);
12517 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
12518 md_number_to_chars (buf
, value
, 1);
12520 else if (!target_oabi
)
12522 value
= fixP
->fx_offset
;
12523 md_number_to_chars (buf
, value
, 1);
12529 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
12530 md_number_to_chars (buf
, value
, 2);
12532 else if (!target_oabi
)
12534 value
= fixP
->fx_offset
;
12535 md_number_to_chars (buf
, value
, 2);
12541 case BFD_RELOC_ARM_GOT32
:
12542 case BFD_RELOC_ARM_GOTOFF
:
12543 md_number_to_chars (buf
, 0, 4);
12547 case BFD_RELOC_RVA
:
12549 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
12550 md_number_to_chars (buf
, value
, 4);
12552 else if (!target_oabi
)
12554 value
= fixP
->fx_offset
;
12555 md_number_to_chars (buf
, value
, 4);
12561 case BFD_RELOC_ARM_PLT32
:
12562 /* It appears the instruction is fully prepared at this point. */
12566 case BFD_RELOC_ARM_CP_OFF_IMM
:
12568 if (value
< -1023 || value
> 1023 || (value
& 3))
12569 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12570 _("illegal value for co-processor offset"));
12573 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
12574 newval
|= (value
>> 2) | (sign
? INDEX_UP
: 0);
12575 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12578 case BFD_RELOC_ARM_CP_OFF_IMM_S2
:
12580 if (value
< -255 || value
> 255)
12581 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12582 _("Illegal value for co-processor offset"));
12585 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
12586 newval
|= value
| (sign
? INDEX_UP
: 0);
12587 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12590 case BFD_RELOC_ARM_THUMB_OFFSET
:
12591 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12592 /* Exactly what ranges, and where the offset is inserted depends
12593 on the type of instruction, we can establish this from the
12595 switch (newval
>> 12)
12597 case 4: /* PC load. */
12598 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
12599 forced to zero for these loads, so we will need to round
12600 up the offset if the instruction address is not word
12601 aligned (since the final address produced must be, and
12602 we can only describe word-aligned immediate offsets). */
12604 if ((fixP
->fx_frag
->fr_address
+ fixP
->fx_where
+ value
) & 3)
12605 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12606 _("invalid offset, target not word aligned (0x%08X)"),
12607 (unsigned int) (fixP
->fx_frag
->fr_address
12608 + fixP
->fx_where
+ value
));
12610 if ((value
+ 2) & ~0x3fe)
12611 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12612 _("invalid offset, value too big (0x%08lX)"),
12615 /* Round up, since pc will be rounded down. */
12616 newval
|= (value
+ 2) >> 2;
12619 case 9: /* SP load/store. */
12620 if (value
& ~0x3fc)
12621 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12622 _("invalid offset, value too big (0x%08lX)"),
12624 newval
|= value
>> 2;
12627 case 6: /* Word load/store. */
12629 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12630 _("invalid offset, value too big (0x%08lX)"),
12632 newval
|= value
<< 4; /* 6 - 2. */
12635 case 7: /* Byte load/store. */
12637 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12638 _("invalid offset, value too big (0x%08lX)"),
12640 newval
|= value
<< 6;
12643 case 8: /* Halfword load/store. */
12645 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12646 _("invalid offset, value too big (0x%08lX)"),
12648 newval
|= value
<< 5; /* 6 - 1. */
12652 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12653 "Unable to process relocation for thumb opcode: %lx",
12654 (unsigned long) newval
);
12657 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12660 case BFD_RELOC_ARM_THUMB_ADD
:
12661 /* This is a complicated relocation, since we use it for all of
12662 the following immediate relocations:
12666 9bit ADD/SUB SP word-aligned
12667 10bit ADD PC/SP word-aligned
12669 The type of instruction being processed is encoded in the
12676 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12678 int rd
= (newval
>> 4) & 0xf;
12679 int rs
= newval
& 0xf;
12680 int subtract
= newval
& 0x8000;
12684 if (value
& ~0x1fc)
12685 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12686 _("invalid immediate for stack address calculation"));
12687 newval
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
12688 newval
|= value
>> 2;
12690 else if (rs
== REG_PC
|| rs
== REG_SP
)
12694 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12695 _("invalid immediate for address calculation (value = 0x%08lX)"),
12696 (unsigned long) value
);
12697 newval
= (rs
== REG_PC
? T_OPCODE_ADD_PC
: T_OPCODE_ADD_SP
);
12699 newval
|= value
>> 2;
12704 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12705 _("invalid 8bit immediate"));
12706 newval
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
12707 newval
|= (rd
<< 8) | value
;
12712 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12713 _("invalid 3bit immediate"));
12714 newval
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
12715 newval
|= rd
| (rs
<< 3) | (value
<< 6);
12718 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12721 case BFD_RELOC_ARM_THUMB_IMM
:
12722 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12723 switch (newval
>> 11)
12725 case 0x04: /* 8bit immediate MOV. */
12726 case 0x05: /* 8bit immediate CMP. */
12727 if (value
< 0 || value
> 255)
12728 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12729 _("invalid immediate: %ld is too large"),
12737 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12740 case BFD_RELOC_ARM_THUMB_SHIFT
:
12741 /* 5bit shift value (0..31). */
12742 if (value
< 0 || value
> 31)
12743 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12744 _("illegal Thumb shift value: %ld"), (long) value
);
12745 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xf03f;
12746 newval
|= value
<< 6;
12747 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12750 case BFD_RELOC_VTABLE_INHERIT
:
12751 case BFD_RELOC_VTABLE_ENTRY
:
12755 case BFD_RELOC_NONE
:
12757 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12758 _("bad relocation fixup type (%d)"), fixP
->fx_r_type
);
12762 /* Translate internal representation of relocation info to BFD target
12766 tc_gen_reloc (section
, fixp
)
12767 asection
* section ATTRIBUTE_UNUSED
;
12771 bfd_reloc_code_real_type code
;
12773 reloc
= (arelent
*) xmalloc (sizeof (arelent
));
12775 reloc
->sym_ptr_ptr
= (asymbol
**) xmalloc (sizeof (asymbol
*));
12776 *reloc
->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
12777 reloc
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
12779 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12781 if (fixp
->fx_pcrel
== 0)
12782 reloc
->addend
= fixp
->fx_offset
;
12784 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
12785 #else /* OBJ_ELF */
12786 reloc
->addend
= fixp
->fx_offset
;
12789 switch (fixp
->fx_r_type
)
12792 if (fixp
->fx_pcrel
)
12794 code
= BFD_RELOC_8_PCREL
;
12799 if (fixp
->fx_pcrel
)
12801 code
= BFD_RELOC_16_PCREL
;
12806 if (fixp
->fx_pcrel
)
12808 code
= BFD_RELOC_32_PCREL
;
12812 case BFD_RELOC_ARM_PCREL_BRANCH
:
12813 case BFD_RELOC_ARM_PCREL_BLX
:
12814 case BFD_RELOC_RVA
:
12815 case BFD_RELOC_THUMB_PCREL_BRANCH9
:
12816 case BFD_RELOC_THUMB_PCREL_BRANCH12
:
12817 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
12818 case BFD_RELOC_THUMB_PCREL_BLX
:
12819 case BFD_RELOC_VTABLE_ENTRY
:
12820 case BFD_RELOC_VTABLE_INHERIT
:
12821 code
= fixp
->fx_r_type
;
12824 case BFD_RELOC_ARM_LITERAL
:
12825 case BFD_RELOC_ARM_HWLITERAL
:
12826 /* If this is called then the a literal has
12827 been referenced across a section boundary. */
12828 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12829 _("literal referenced across section boundary"));
12833 case BFD_RELOC_ARM_GOT32
:
12834 case BFD_RELOC_ARM_GOTOFF
:
12835 case BFD_RELOC_ARM_PLT32
:
12836 code
= fixp
->fx_r_type
;
12840 case BFD_RELOC_ARM_IMMEDIATE
:
12841 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12842 _("internal relocation (type: IMMEDIATE) not fixed up"));
12845 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
12846 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12847 _("ADRL used for a symbol not defined in the same file"));
12850 case BFD_RELOC_ARM_OFFSET_IMM
:
12851 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12852 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
12859 switch (fixp
->fx_r_type
)
12861 case BFD_RELOC_ARM_OFFSET_IMM8
: type
= "OFFSET_IMM8"; break;
12862 case BFD_RELOC_ARM_SHIFT_IMM
: type
= "SHIFT_IMM"; break;
12863 case BFD_RELOC_ARM_SWI
: type
= "SWI"; break;
12864 case BFD_RELOC_ARM_MULTI
: type
= "MULTI"; break;
12865 case BFD_RELOC_ARM_CP_OFF_IMM
: type
= "CP_OFF_IMM"; break;
12866 case BFD_RELOC_ARM_THUMB_ADD
: type
= "THUMB_ADD"; break;
12867 case BFD_RELOC_ARM_THUMB_SHIFT
: type
= "THUMB_SHIFT"; break;
12868 case BFD_RELOC_ARM_THUMB_IMM
: type
= "THUMB_IMM"; break;
12869 case BFD_RELOC_ARM_THUMB_OFFSET
: type
= "THUMB_OFFSET"; break;
12870 default: type
= _("<unknown>"); break;
12872 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12873 _("cannot represent %s relocation in this object file format"),
12880 if ((code
== BFD_RELOC_32_PCREL
|| code
== BFD_RELOC_32
)
12882 && fixp
->fx_addsy
== GOT_symbol
)
12884 code
= BFD_RELOC_ARM_GOTPC
;
12885 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
12889 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, code
);
12891 if (reloc
->howto
== NULL
)
12893 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12894 _("cannot represent %s relocation in this object file format"),
12895 bfd_get_reloc_code_name (code
));
12899 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12900 vtable entry to be used in the relocation's section offset. */
12901 if (fixp
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
12902 reloc
->address
= fixp
->fx_offset
;
12908 md_estimate_size_before_relax (fragP
, segtype
)
12909 fragS
* fragP ATTRIBUTE_UNUSED
;
12910 segT segtype ATTRIBUTE_UNUSED
;
12912 as_fatal (_("md_estimate_size_before_relax\n"));
12924 as_bad ("%s -- `%s'", inst
.error
, str
);
12928 to
= frag_more (inst
.size
);
12930 if (thumb_mode
&& (inst
.size
> THUMB_SIZE
))
12932 assert (inst
.size
== (2 * THUMB_SIZE
));
12933 md_number_to_chars (to
, inst
.instruction
>> 16, THUMB_SIZE
);
12934 md_number_to_chars (to
+ THUMB_SIZE
, inst
.instruction
, THUMB_SIZE
);
12936 else if (inst
.size
> INSN_SIZE
)
12938 assert (inst
.size
== (2 * INSN_SIZE
));
12939 md_number_to_chars (to
, inst
.instruction
, INSN_SIZE
);
12940 md_number_to_chars (to
+ INSN_SIZE
, inst
.instruction
, INSN_SIZE
);
12943 md_number_to_chars (to
, inst
.instruction
, inst
.size
);
12945 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
12946 fix_new_arm (frag_now
, to
- frag_now
->fr_literal
,
12947 inst
.size
, & inst
.reloc
.exp
, inst
.reloc
.pc_rel
,
12951 dwarf2_emit_insn (inst
.size
);
12963 /* Align the instruction.
12964 This may not be the right thing to do but ... */
12969 /* Align the previous label if needed. */
12970 if (last_label_seen
!= NULL
)
12972 symbol_set_frag (last_label_seen
, frag_now
);
12973 S_SET_VALUE (last_label_seen
, (valueT
) frag_now_fix ());
12974 S_SET_SEGMENT (last_label_seen
, now_seg
);
12977 memset (&inst
, '\0', sizeof (inst
));
12978 inst
.reloc
.type
= BFD_RELOC_NONE
;
12980 skip_whitespace (str
);
12982 /* Scan up to the end of the op-code, which must end in white space or
12984 for (start
= p
= str
; *p
!= '\0'; p
++)
12990 as_bad (_("no operator -- statement `%s'\n"), str
);
12996 const struct thumb_opcode
* opcode
;
13000 opcode
= (const struct thumb_opcode
*) hash_find (arm_tops_hsh
, str
);
13005 /* Check that this instruction is supported for this CPU. */
13006 if (thumb_mode
== 1 && (opcode
->variant
& cpu_variant
) == 0)
13008 as_bad (_("selected processor does not support `%s'"), str
);
13012 mapping_state (MAP_THUMB
);
13013 inst
.instruction
= opcode
->value
;
13014 inst
.size
= opcode
->size
;
13015 (*opcode
->parms
) (p
);
13022 const struct asm_opcode
* opcode
;
13026 opcode
= (const struct asm_opcode
*) hash_find (arm_ops_hsh
, str
);
13031 /* Check that this instruction is supported for this CPU. */
13032 if ((opcode
->variant
& cpu_variant
) == 0)
13034 as_bad (_("selected processor does not support `%s'"), str
);
13038 mapping_state (MAP_ARM
);
13039 inst
.instruction
= opcode
->value
;
13040 inst
.size
= INSN_SIZE
;
13041 (*opcode
->parms
) (p
);
13047 /* It wasn't an instruction, but it might be a register alias of the form
13049 if (create_register_alias (str
, p
))
13052 as_bad (_("bad instruction `%s'"), start
);
13056 Invocation line includes a switch not recognized by the base assembler.
13057 See if it's a processor-specific option.
13059 This routine is somewhat complicated by the need for backwards
13060 compatibility (since older releases of gcc can't be changed).
13061 The new options try to make the interface as compatible as
13064 New options (supported) are:
13066 -mcpu=<cpu name> Assemble for selected processor
13067 -march=<architecture name> Assemble for selected architecture
13068 -mfpu=<fpu architecture> Assemble for selected FPU.
13069 -EB/-mbig-endian Big-endian
13070 -EL/-mlittle-endian Little-endian
13071 -k Generate PIC code
13072 -mthumb Start in Thumb mode
13073 -mthumb-interwork Code supports ARM/Thumb interworking
13075 For now we will also provide support for:
13077 -mapcs-32 32-bit Program counter
13078 -mapcs-26 26-bit Program counter
13079 -macps-float Floats passed in FP registers
13080 -mapcs-reentrant Reentrant code
13082 (sometime these will probably be replaced with -mapcs=<list of options>
13083 and -matpcs=<list of options>)
13085 The remaining options are only supported for back-wards compatibility.
13086 Cpu variants, the arm part is optional:
13087 -m[arm]1 Currently not supported.
13088 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
13089 -m[arm]3 Arm 3 processor
13090 -m[arm]6[xx], Arm 6 processors
13091 -m[arm]7[xx][t][[d]m] Arm 7 processors
13092 -m[arm]8[10] Arm 8 processors
13093 -m[arm]9[20][tdmi] Arm 9 processors
13094 -mstrongarm[110[0]] StrongARM processors
13095 -mxscale XScale processors
13096 -m[arm]v[2345[t[e]]] Arm architectures
13097 -mall All (except the ARM1)
13099 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
13100 -mfpe-old (No float load/store multiples)
13101 -mvfpxd VFP Single precision
13103 -mno-fpu Disable all floating point instructions
13105 The following CPU names are recognized:
13106 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
13107 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
13108 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
13109 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
13110 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
13111 arm10t arm10e, arm1020t, arm1020e, arm10200e,
13112 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
13116 const char * md_shortopts
= "m:k";
13118 #ifdef ARM_BI_ENDIAN
13119 #define OPTION_EB (OPTION_MD_BASE + 0)
13120 #define OPTION_EL (OPTION_MD_BASE + 1)
13122 #if TARGET_BYTES_BIG_ENDIAN
13123 #define OPTION_EB (OPTION_MD_BASE + 0)
13125 #define OPTION_EL (OPTION_MD_BASE + 1)
13129 struct option md_longopts
[] =
13132 {"EB", no_argument
, NULL
, OPTION_EB
},
13135 {"EL", no_argument
, NULL
, OPTION_EL
},
13137 {NULL
, no_argument
, NULL
, 0}
13140 size_t md_longopts_size
= sizeof (md_longopts
);
13142 struct arm_option_table
13144 char *option
; /* Option name to match. */
13145 char *help
; /* Help information. */
13146 int *var
; /* Variable to change. */
13147 int value
; /* What to change it to. */
13148 char *deprecated
; /* If non-null, print this message. */
13151 struct arm_option_table arm_opts
[] =
13153 {"k", N_("generate PIC code"), &pic_code
, 1, NULL
},
13154 {"mthumb", N_("assemble Thumb code"), &thumb_mode
, 1, NULL
},
13155 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
13156 &support_interwork
, 1, NULL
},
13157 {"moabi", N_("use old ABI (ELF only)"), &target_oabi
, 1, NULL
},
13158 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26
, 0, NULL
},
13159 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26
, 1, NULL
},
13160 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float
,
13162 {"mapcs-reentrant", N_("re-entrant code"), &pic_code
, 1, NULL
},
13163 {"matpcs", N_("code is ATPCS conformant"), &atpcs
, 1, NULL
},
13164 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian
, 1, NULL
},
13165 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian
, 1,
13168 /* These are recognized by the assembler, but have no affect on code. */
13169 {"mapcs-frame", N_("use frame pointer"), NULL
, 0, NULL
},
13170 {"mapcs-stack-check", N_("use stack size checking"), NULL
, 0, NULL
},
13172 /* DON'T add any new processors to this list -- we want the whole list
13173 to go away... Add them to the processors table instead. */
13174 {"marm1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
13175 {"m1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
13176 {"marm2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
13177 {"m2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
13178 {"marm250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
13179 {"m250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
13180 {"marm3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
13181 {"m3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
13182 {"marm6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
13183 {"m6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
13184 {"marm600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
13185 {"m600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
13186 {"marm610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
13187 {"m610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
13188 {"marm620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
13189 {"m620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
13190 {"marm7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
13191 {"m7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
13192 {"marm70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
13193 {"m70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
13194 {"marm700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
13195 {"m700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
13196 {"marm700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
13197 {"m700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
13198 {"marm710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
13199 {"m710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
13200 {"marm710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
13201 {"m710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
13202 {"marm720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
13203 {"m720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
13204 {"marm7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
13205 {"m7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
13206 {"marm7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
13207 {"m7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
13208 {"marm7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
13209 {"m7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
13210 {"marm7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
13211 {"m7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
13212 {"marm7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
13213 {"m7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
13214 {"marm7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
13215 {"m7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
13216 {"marm7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
13217 {"m7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
13218 {"marm7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
13219 {"m7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
13220 {"marm7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
13221 {"m7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
13222 {"marm7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
13223 {"m7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
13224 {"marm710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
13225 {"m710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
13226 {"marm720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
13227 {"m720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
13228 {"marm740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
13229 {"m740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
13230 {"marm8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
13231 {"m8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
13232 {"marm810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
13233 {"m810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
13234 {"marm9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
13235 {"m9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
13236 {"marm9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
13237 {"m9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
13238 {"marm920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
13239 {"m920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
13240 {"marm940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
13241 {"m940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
13242 {"mstrongarm", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=strongarm")},
13243 {"mstrongarm110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
13244 N_("use -mcpu=strongarm110")},
13245 {"mstrongarm1100", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
13246 N_("use -mcpu=strongarm1100")},
13247 {"mstrongarm1110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
13248 N_("use -mcpu=strongarm1110")},
13249 {"mxscale", NULL
, &legacy_cpu
, ARM_ARCH_XSCALE
, N_("use -mcpu=xscale")},
13250 {"miwmmxt", NULL
, &legacy_cpu
, ARM_ARCH_IWMMXT
, N_("use -mcpu=iwmmxt")},
13251 {"mall", NULL
, &legacy_cpu
, ARM_ANY
, N_("use -mcpu=all")},
13253 /* Architecture variants -- don't add any more to this list either. */
13254 {"mv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
13255 {"marmv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
13256 {"mv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
13257 {"marmv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
13258 {"mv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
13259 {"marmv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
13260 {"mv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
13261 {"marmv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
13262 {"mv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
13263 {"marmv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
13264 {"mv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
13265 {"marmv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
13266 {"mv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
13267 {"marmv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
13268 {"mv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
13269 {"marmv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
13270 {"mv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
13271 {"marmv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
13273 /* Floating point variants -- don't add any more to this list either. */
13274 {"mfpe-old", NULL
, &legacy_fpu
, FPU_ARCH_FPE
, N_("use -mfpu=fpe")},
13275 {"mfpa10", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa10")},
13276 {"mfpa11", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa11")},
13277 {"mno-fpu", NULL
, &legacy_fpu
, 0,
13278 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
13280 {NULL
, NULL
, NULL
, 0, NULL
}
13283 struct arm_cpu_option_table
13287 /* For some CPUs we assume an FPU unless the user explicitly sets
13292 /* This list should, at a minimum, contain all the cpu names
13293 recognized by GCC. */
13294 static struct arm_cpu_option_table arm_cpus
[] =
13296 {"all", ARM_ANY
, FPU_ARCH_FPA
},
13297 {"arm1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
13298 {"arm2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
13299 {"arm250", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
13300 {"arm3", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
13301 {"arm6", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13302 {"arm60", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13303 {"arm600", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13304 {"arm610", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13305 {"arm620", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13306 {"arm7", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13307 {"arm7m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
13308 {"arm7d", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13309 {"arm7dm", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
13310 {"arm7di", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13311 {"arm7dmi", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
13312 {"arm70", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13313 {"arm700", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13314 {"arm700i", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13315 {"arm710", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13316 {"arm710t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13317 {"arm720", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13318 {"arm720t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13319 {"arm740t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13320 {"arm710c", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13321 {"arm7100", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13322 {"arm7500", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13323 {"arm7500fe", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13324 {"arm7t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13325 {"arm7tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13326 {"arm8", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13327 {"arm810", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13328 {"strongarm", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13329 {"strongarm1", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13330 {"strongarm110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13331 {"strongarm1100", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13332 {"strongarm1110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13333 {"arm9", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13334 {"arm920", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13335 {"arm920t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13336 {"arm922t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13337 {"arm940t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13338 {"arm9tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13339 /* For V5 or later processors we default to using VFP; but the user
13340 should really set the FPU type explicitly. */
13341 {"arm9e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
13342 {"arm9e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13343 {"arm926ej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
13344 {"arm946e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
13345 {"arm946e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13346 {"arm966e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
13347 {"arm966e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13348 {"arm10t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
13349 {"arm10e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13350 {"arm1020", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13351 {"arm1020t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
13352 {"arm1020e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13353 {"arm1136js", ARM_ARCH_V6
, FPU_NONE
},
13354 {"arm1136jfs", ARM_ARCH_V6
, FPU_ARCH_VFP_V2
},
13355 /* ??? XSCALE is really an architecture. */
13356 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
13357 /* ??? iwmmxt is not a processor. */
13358 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP_V2
},
13359 {"i80200", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
13361 {"ep9312", ARM_ARCH_V4T
| ARM_CEXT_MAVERICK
, FPU_NONE
},
13365 struct arm_arch_option_table
13372 /* This list should, at a minimum, contain all the architecture names
13373 recognized by GCC. */
13374 static struct arm_arch_option_table arm_archs
[] =
13376 {"all", ARM_ANY
, FPU_ARCH_FPA
},
13377 {"armv1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
13378 {"armv2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
13379 {"armv2a", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
13380 {"armv2s", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
13381 {"armv3", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13382 {"armv3m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
13383 {"armv4", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13384 {"armv4xm", ARM_ARCH_V4xM
, FPU_ARCH_FPA
},
13385 {"armv4t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13386 {"armv4txm", ARM_ARCH_V4TxM
, FPU_ARCH_FPA
},
13387 {"armv5", ARM_ARCH_V5
, FPU_ARCH_VFP
},
13388 {"armv5t", ARM_ARCH_V5T
, FPU_ARCH_VFP
},
13389 {"armv5txm", ARM_ARCH_V5TxM
, FPU_ARCH_VFP
},
13390 {"armv5te", ARM_ARCH_V5TE
, FPU_ARCH_VFP
},
13391 {"armv5texp", ARM_ARCH_V5TExP
, FPU_ARCH_VFP
},
13392 {"armv5tej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP
},
13393 {"armv6", ARM_ARCH_V6
, FPU_ARCH_VFP
},
13394 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP
},
13395 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP
},
13399 /* ISA extensions in the co-processor space. */
13400 struct arm_arch_extension_table
13406 static struct arm_arch_extension_table arm_extensions
[] =
13408 {"maverick", ARM_CEXT_MAVERICK
},
13409 {"xscale", ARM_CEXT_XSCALE
},
13410 {"iwmmxt", ARM_CEXT_IWMMXT
},
13414 struct arm_fpu_option_table
13420 /* This list should, at a minimum, contain all the fpu names
13421 recognized by GCC. */
13422 static struct arm_fpu_option_table arm_fpus
[] =
13424 {"softfpa", FPU_NONE
},
13425 {"fpe", FPU_ARCH_FPE
},
13426 {"fpe2", FPU_ARCH_FPE
},
13427 {"fpe3", FPU_ARCH_FPA
}, /* Third release supports LFM/SFM. */
13428 {"fpa", FPU_ARCH_FPA
},
13429 {"fpa10", FPU_ARCH_FPA
},
13430 {"fpa11", FPU_ARCH_FPA
},
13431 {"arm7500fe", FPU_ARCH_FPA
},
13432 {"softvfp", FPU_ARCH_VFP
},
13433 {"softvfp+vfp", FPU_ARCH_VFP_V2
},
13434 {"vfp", FPU_ARCH_VFP_V2
},
13435 {"vfp9", FPU_ARCH_VFP_V2
},
13436 {"vfp10", FPU_ARCH_VFP_V2
},
13437 {"vfp10-r0", FPU_ARCH_VFP_V1
},
13438 {"vfpxd", FPU_ARCH_VFP_V1xD
},
13439 {"arm1020t", FPU_ARCH_VFP_V1
},
13440 {"arm1020e", FPU_ARCH_VFP_V2
},
13441 {"arm1136jfs", FPU_ARCH_VFP_V2
},
13445 struct arm_long_option_table
13447 char *option
; /* Substring to match. */
13448 char *help
; /* Help information. */
13449 int (*func
) PARAMS ((char *subopt
)); /* Function to decode sub-option. */
13450 char *deprecated
; /* If non-null, print this message. */
13454 arm_parse_extension (str
, opt_p
)
13458 while (str
!= NULL
&& *str
!= 0)
13460 struct arm_arch_extension_table
*opt
;
13466 as_bad (_("invalid architectural extension"));
13471 ext
= strchr (str
, '+');
13474 optlen
= ext
- str
;
13476 optlen
= strlen (str
);
13480 as_bad (_("missing architectural extension"));
13484 for (opt
= arm_extensions
; opt
->name
!= NULL
; opt
++)
13485 if (strncmp (opt
->name
, str
, optlen
) == 0)
13487 *opt_p
|= opt
->value
;
13491 if (opt
->name
== NULL
)
13493 as_bad (_("unknown architectural extnsion `%s'"), str
);
13504 arm_parse_cpu (str
)
13507 struct arm_cpu_option_table
*opt
;
13508 char *ext
= strchr (str
, '+');
13512 optlen
= ext
- str
;
13514 optlen
= strlen (str
);
13518 as_bad (_("missing cpu name `%s'"), str
);
13522 for (opt
= arm_cpus
; opt
->name
!= NULL
; opt
++)
13523 if (strncmp (opt
->name
, str
, optlen
) == 0)
13525 mcpu_cpu_opt
= opt
->value
;
13526 mcpu_fpu_opt
= opt
->default_fpu
;
13529 return arm_parse_extension (ext
, &mcpu_cpu_opt
);
13534 as_bad (_("unknown cpu `%s'"), str
);
13539 arm_parse_arch (str
)
13542 struct arm_arch_option_table
*opt
;
13543 char *ext
= strchr (str
, '+');
13547 optlen
= ext
- str
;
13549 optlen
= strlen (str
);
13553 as_bad (_("missing architecture name `%s'"), str
);
13558 for (opt
= arm_archs
; opt
->name
!= NULL
; opt
++)
13559 if (strcmp (opt
->name
, str
) == 0)
13561 march_cpu_opt
= opt
->value
;
13562 march_fpu_opt
= opt
->default_fpu
;
13565 return arm_parse_extension (ext
, &march_cpu_opt
);
13570 as_bad (_("unknown architecture `%s'\n"), str
);
13575 arm_parse_fpu (str
)
13578 struct arm_fpu_option_table
*opt
;
13580 for (opt
= arm_fpus
; opt
->name
!= NULL
; opt
++)
13581 if (strcmp (opt
->name
, str
) == 0)
13583 mfpu_opt
= opt
->value
;
13587 as_bad (_("unknown floating point format `%s'\n"), str
);
13591 struct arm_long_option_table arm_long_opts
[] =
13593 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13594 arm_parse_cpu
, NULL
},
13595 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13596 arm_parse_arch
, NULL
},
13597 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13598 arm_parse_fpu
, NULL
},
13599 {NULL
, NULL
, 0, NULL
}
13603 md_parse_option (c
, arg
)
13607 struct arm_option_table
*opt
;
13608 struct arm_long_option_table
*lopt
;
13614 target_big_endian
= 1;
13620 target_big_endian
= 0;
13625 /* Listing option. Just ignore these, we don't support additional
13630 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
13632 if (c
== opt
->option
[0]
13633 && ((arg
== NULL
&& opt
->option
[1] == 0)
13634 || strcmp (arg
, opt
->option
+ 1) == 0))
13636 #if WARN_DEPRECATED
13637 /* If the option is deprecated, tell the user. */
13638 if (opt
->deprecated
!= NULL
)
13639 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
,
13640 arg
? arg
: "", _(opt
->deprecated
));
13643 if (opt
->var
!= NULL
)
13644 *opt
->var
= opt
->value
;
13650 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
13652 /* These options are expected to have an argument. */
13653 if (c
== lopt
->option
[0]
13655 && strncmp (arg
, lopt
->option
+ 1,
13656 strlen (lopt
->option
+ 1)) == 0)
13658 #if WARN_DEPRECATED
13659 /* If the option is deprecated, tell the user. */
13660 if (lopt
->deprecated
!= NULL
)
13661 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
, arg
,
13662 _(lopt
->deprecated
));
13665 /* Call the sup-option parser. */
13666 return (*lopt
->func
)(arg
+ strlen (lopt
->option
) - 1);
13670 as_bad (_("unrecognized option `-%c%s'"), c
, arg
? arg
: "");
13681 struct arm_option_table
*opt
;
13682 struct arm_long_option_table
*lopt
;
13684 fprintf (fp
, _(" ARM-specific assembler options:\n"));
13686 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
13687 if (opt
->help
!= NULL
)
13688 fprintf (fp
, " -%-23s%s\n", opt
->option
, _(opt
->help
));
13690 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
13691 if (lopt
->help
!= NULL
)
13692 fprintf (fp
, " -%s%s\n", lopt
->option
, _(lopt
->help
));
13696 -EB assemble code for a big-endian cpu\n"));
13701 -EL assemble code for a little-endian cpu\n"));
13705 /* We need to be able to fix up arbitrary expressions in some statements.
13706 This is so that we can handle symbols that are an arbitrary distance from
13707 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
13708 which returns part of an address in a form which will be valid for
13709 a data instruction. We do this by pushing the expression into a symbol
13710 in the expr_section, and creating a fix for that. */
13713 fix_new_arm (frag
, where
, size
, exp
, pc_rel
, reloc
)
13722 arm_fix_data
* arm_data
;
13730 new_fix
= fix_new_exp (frag
, where
, size
, exp
, pc_rel
, reloc
);
13734 new_fix
= fix_new (frag
, where
, size
, make_expr_symbol (exp
), 0,
13739 /* Mark whether the fix is to a THUMB instruction, or an ARM
13741 arm_data
= (arm_fix_data
*) obstack_alloc (& notes
, sizeof (arm_fix_data
));
13742 new_fix
->tc_fix_data
= (PTR
) arm_data
;
13743 arm_data
->thumb_mode
= thumb_mode
;
13748 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13751 cons_fix_new_arm (frag
, where
, size
, exp
)
13757 bfd_reloc_code_real_type type
;
13761 FIXME: @@ Should look at CPU word size. */
13765 type
= BFD_RELOC_8
;
13768 type
= BFD_RELOC_16
;
13772 type
= BFD_RELOC_32
;
13775 type
= BFD_RELOC_64
;
13779 fix_new_exp (frag
, where
, (int) size
, exp
, pcrel
, type
);
13782 /* A good place to do this, although this was probably not intended
13783 for this kind of use. We need to dump the literal pool before
13784 references are made to a null symbol pointer. */
13789 literal_pool
* pool
;
13791 for (pool
= list_of_pools
; pool
; pool
= pool
->next
)
13793 /* Put it at the end of the relevent section. */
13794 subseg_set (pool
->section
, pool
->sub_section
);
13800 arm_start_line_hook ()
13802 last_label_seen
= NULL
;
13806 arm_frob_label (sym
)
13809 last_label_seen
= sym
;
13811 ARM_SET_THUMB (sym
, thumb_mode
);
13813 #if defined OBJ_COFF || defined OBJ_ELF
13814 ARM_SET_INTERWORK (sym
, support_interwork
);
13817 /* Note - do not allow local symbols (.Lxxx) to be labeled
13818 as Thumb functions. This is because these labels, whilst
13819 they exist inside Thumb code, are not the entry points for
13820 possible ARM->Thumb calls. Also, these labels can be used
13821 as part of a computed goto or switch statement. eg gcc
13822 can generate code that looks like this:
13824 ldr r2, [pc, .Laaa]
13834 The first instruction loads the address of the jump table.
13835 The second instruction converts a table index into a byte offset.
13836 The third instruction gets the jump address out of the table.
13837 The fourth instruction performs the jump.
13839 If the address stored at .Laaa is that of a symbol which has the
13840 Thumb_Func bit set, then the linker will arrange for this address
13841 to have the bottom bit set, which in turn would mean that the
13842 address computation performed by the third instruction would end
13843 up with the bottom bit set. Since the ARM is capable of unaligned
13844 word loads, the instruction would then load the incorrect address
13845 out of the jump table, and chaos would ensue. */
13846 if (label_is_thumb_function_name
13847 && (S_GET_NAME (sym
)[0] != '.' || S_GET_NAME (sym
)[1] != 'L')
13848 && (bfd_get_section_flags (stdoutput
, now_seg
) & SEC_CODE
) != 0)
13850 /* When the address of a Thumb function is taken the bottom
13851 bit of that address should be set. This will allow
13852 interworking between Arm and Thumb functions to work
13855 THUMB_SET_FUNC (sym
, 1);
13857 label_is_thumb_function_name
= FALSE
;
13861 /* Adjust the symbol table. This marks Thumb symbols as distinct from
13865 arm_adjust_symtab ()
13870 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
13872 if (ARM_IS_THUMB (sym
))
13874 if (THUMB_IS_FUNC (sym
))
13876 /* Mark the symbol as a Thumb function. */
13877 if ( S_GET_STORAGE_CLASS (sym
) == C_STAT
13878 || S_GET_STORAGE_CLASS (sym
) == C_LABEL
) /* This can happen! */
13879 S_SET_STORAGE_CLASS (sym
, C_THUMBSTATFUNC
);
13881 else if (S_GET_STORAGE_CLASS (sym
) == C_EXT
)
13882 S_SET_STORAGE_CLASS (sym
, C_THUMBEXTFUNC
);
13884 as_bad (_("%s: unexpected function type: %d"),
13885 S_GET_NAME (sym
), S_GET_STORAGE_CLASS (sym
));
13887 else switch (S_GET_STORAGE_CLASS (sym
))
13890 S_SET_STORAGE_CLASS (sym
, C_THUMBEXT
);
13893 S_SET_STORAGE_CLASS (sym
, C_THUMBSTAT
);
13896 S_SET_STORAGE_CLASS (sym
, C_THUMBLABEL
);
13904 if (ARM_IS_INTERWORK (sym
))
13905 coffsymbol (symbol_get_bfdsym (sym
))->native
->u
.syment
.n_flags
= 0xFF;
13912 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
13914 if (ARM_IS_THUMB (sym
))
13916 elf_symbol_type
* elf_sym
;
13918 elf_sym
= elf_symbol (symbol_get_bfdsym (sym
));
13919 bind
= ELF_ST_BIND (elf_sym
);
13921 /* If it's a .thumb_func, declare it as so,
13922 otherwise tag label as .code 16. */
13923 if (THUMB_IS_FUNC (sym
))
13924 elf_sym
->internal_elf_sym
.st_info
=
13925 ELF_ST_INFO (bind
, STT_ARM_TFUNC
);
13927 elf_sym
->internal_elf_sym
.st_info
=
13928 ELF_ST_INFO (bind
, STT_ARM_16BIT
);
13935 arm_data_in_code ()
13937 if (thumb_mode
&& ! strncmp (input_line_pointer
+ 1, "data:", 5))
13939 *input_line_pointer
= '/';
13940 input_line_pointer
+= 5;
13941 *input_line_pointer
= 0;
13949 arm_canonicalize_symbol_name (name
)
13954 if (thumb_mode
&& (len
= strlen (name
)) > 5
13955 && streq (name
+ len
- 5, "/data"))
13956 *(name
+ len
- 5) = 0;
13961 #if defined OBJ_COFF || defined OBJ_ELF
13963 arm_validate_fix (fixP
)
13966 /* If the destination of the branch is a defined symbol which does not have
13967 the THUMB_FUNC attribute, then we must be calling a function which has
13968 the (interfacearm) attribute. We look for the Thumb entry point to that
13969 function and change the branch to refer to that function instead. */
13970 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
13971 && fixP
->fx_addsy
!= NULL
13972 && S_IS_DEFINED (fixP
->fx_addsy
)
13973 && ! THUMB_IS_FUNC (fixP
->fx_addsy
))
13975 fixP
->fx_addsy
= find_real_start (fixP
->fx_addsy
);
13981 arm_force_relocation (fixp
)
13984 #if defined (OBJ_COFF) && defined (TE_PE)
13985 if (fixp
->fx_r_type
== BFD_RELOC_RVA
)
13989 if (fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
13990 || fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
13991 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
13992 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
)
13996 /* Resolve these relocations even if the symbol is extern or weak. */
13997 if (fixp
->fx_r_type
== BFD_RELOC_ARM_IMMEDIATE
13998 || fixp
->fx_r_type
== BFD_RELOC_ARM_OFFSET_IMM
13999 || fixp
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
14002 return generic_force_reloc (fixp
);
14006 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
14007 local labels from being added to the output symbol table when they
14008 are used with the ADRL pseudo op. The ADRL relocation should always
14009 be resolved before the binbary is emitted, so it is safe to say that
14010 it is adjustable. */
14013 arm_fix_adjustable (fixP
)
14016 if (fixP
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
14023 /* Relocations against Thumb function names must be left unadjusted,
14024 so that the linker can use this information to correctly set the
14025 bottom bit of their addresses. The MIPS version of this function
14026 also prevents relocations that are mips-16 specific, but I do not
14027 know why it does this.
14030 There is one other problem that ought to be addressed here, but
14031 which currently is not: Taking the address of a label (rather
14032 than a function) and then later jumping to that address. Such
14033 addresses also ought to have their bottom bit set (assuming that
14034 they reside in Thumb code), but at the moment they will not. */
14037 arm_fix_adjustable (fixP
)
14040 if (fixP
->fx_addsy
== NULL
)
14043 if (THUMB_IS_FUNC (fixP
->fx_addsy
)
14044 && fixP
->fx_subsy
== NULL
)
14047 /* We need the symbol name for the VTABLE entries. */
14048 if ( fixP
->fx_r_type
== BFD_RELOC_VTABLE_INHERIT
14049 || fixP
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
14052 /* Don't allow symbols to be discarded on GOT related relocs. */
14053 if (fixP
->fx_r_type
== BFD_RELOC_ARM_PLT32
14054 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOT32
14055 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOTOFF
)
14062 elf32_arm_target_format ()
14064 if (target_big_endian
)
14067 return "elf32-bigarm-oabi";
14069 return "elf32-bigarm";
14074 return "elf32-littlearm-oabi";
14076 return "elf32-littlearm";
14081 armelf_frob_symbol (symp
, puntp
)
14085 elf_frob_symbol (symp
, puntp
);
14088 static bfd_reloc_code_real_type
14098 bfd_reloc_code_real_type reloc
;
14102 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
14103 MAP ("(got)", BFD_RELOC_ARM_GOT32
),
14104 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF
),
14105 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
14106 branch instructions generated by GCC for PLT relocs. */
14107 MAP ("(plt)", BFD_RELOC_ARM_PLT32
),
14108 { NULL
, 0, BFD_RELOC_UNUSED
}
14112 for (i
= 0, ip
= input_line_pointer
;
14113 i
< sizeof (id
) && (ISALNUM (*ip
) || ISPUNCT (*ip
));
14115 id
[i
] = TOLOWER (*ip
);
14117 for (i
= 0; reloc_map
[i
].str
; i
++)
14118 if (strncmp (id
, reloc_map
[i
].str
, reloc_map
[i
].len
) == 0)
14121 input_line_pointer
+= reloc_map
[i
].len
;
14123 return reloc_map
[i
].reloc
;
14127 s_arm_elf_cons (nbytes
)
14132 #ifdef md_flush_pending_output
14133 md_flush_pending_output ();
14136 if (is_it_end_of_statement ())
14138 demand_empty_rest_of_line ();
14142 #ifdef md_cons_align
14143 md_cons_align (nbytes
);
14146 mapping_state (MAP_DATA
);
14149 bfd_reloc_code_real_type reloc
;
14151 expression (& exp
);
14153 if (exp
.X_op
== O_symbol
14154 && * input_line_pointer
== '('
14155 && (reloc
= arm_parse_reloc ()) != BFD_RELOC_UNUSED
)
14157 reloc_howto_type
*howto
= bfd_reloc_type_lookup (stdoutput
, reloc
);
14158 int size
= bfd_get_reloc_size (howto
);
14161 as_bad ("%s relocations do not fit in %d bytes",
14162 howto
->name
, nbytes
);
14165 register char *p
= frag_more ((int) nbytes
);
14166 int offset
= nbytes
- size
;
14168 fix_new_exp (frag_now
, p
- frag_now
->fr_literal
+ offset
, size
,
14173 emit_expr (&exp
, (unsigned int) nbytes
);
14175 while (*input_line_pointer
++ == ',');
14177 /* Put terminator back into stream. */
14178 input_line_pointer
--;
14179 demand_empty_rest_of_line ();
14182 #endif /* OBJ_ELF */
14184 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
14185 of an rs_align_code fragment. */
14188 arm_handle_align (fragP
)
14191 static char const arm_noop
[4] = { 0x00, 0x00, 0xa0, 0xe1 };
14192 static char const thumb_noop
[2] = { 0xc0, 0x46 };
14193 static char const arm_bigend_noop
[4] = { 0xe1, 0xa0, 0x00, 0x00 };
14194 static char const thumb_bigend_noop
[2] = { 0x46, 0xc0 };
14196 int bytes
, fix
, noop_size
;
14200 if (fragP
->fr_type
!= rs_align_code
)
14203 bytes
= fragP
->fr_next
->fr_address
- fragP
->fr_address
- fragP
->fr_fix
;
14204 p
= fragP
->fr_literal
+ fragP
->fr_fix
;
14207 if (bytes
> MAX_MEM_FOR_RS_ALIGN_CODE
)
14208 bytes
&= MAX_MEM_FOR_RS_ALIGN_CODE
;
14210 if (fragP
->tc_frag_data
)
14212 if (target_big_endian
)
14213 noop
= thumb_bigend_noop
;
14216 noop_size
= sizeof (thumb_noop
);
14220 if (target_big_endian
)
14221 noop
= arm_bigend_noop
;
14224 noop_size
= sizeof (arm_noop
);
14227 if (bytes
& (noop_size
- 1))
14229 fix
= bytes
& (noop_size
- 1);
14230 memset (p
, 0, fix
);
14235 while (bytes
>= noop_size
)
14237 memcpy (p
, noop
, noop_size
);
14239 bytes
-= noop_size
;
14243 fragP
->fr_fix
+= fix
;
14244 fragP
->fr_var
= noop_size
;
14247 /* Called from md_do_align. Used to create an alignment
14248 frag in a code section. */
14251 arm_frag_align_code (n
, max
)
14257 /* We assume that there will never be a requirement
14258 to support alignments greater than 32 bytes. */
14259 if (max
> MAX_MEM_FOR_RS_ALIGN_CODE
)
14260 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
14262 p
= frag_var (rs_align_code
,
14263 MAX_MEM_FOR_RS_ALIGN_CODE
,
14265 (relax_substateT
) max
,
14273 /* Perform target specific initialisation of a frag. */
14276 arm_init_frag (fragP
)
14279 /* Record whether this frag is in an ARM or a THUMB area. */
14280 fragP
->tc_frag_data
= thumb_mode
;