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. */
4042 /* Only one syntax. */
4043 skip_whitespace (str
);
4045 if (reg_required_here (&str
, 12) == FAIL
)
4047 inst
.error
= BAD_ARGS
;
4051 if (skip_past_comma (&str
) == FAIL
)
4053 inst
.error
= _("comma expected after register name");
4057 skip_whitespace (str
);
4059 if ( strcmp (str
, "CPSR") == 0
4060 || strcmp (str
, "SPSR") == 0
4061 /* Lower case versions for backwards compatibility. */
4062 || strcmp (str
, "cpsr") == 0
4063 || strcmp (str
, "spsr") == 0)
4066 /* This is for backwards compatibility with older toolchains. */
4067 else if ( strcmp (str
, "cpsr_all") == 0
4068 || strcmp (str
, "spsr_all") == 0)
4072 inst
.error
= _("CPSR or SPSR expected");
4076 if (* str
== 's' || * str
== 'S')
4077 inst
.instruction
|= SPSR_BIT
;
4083 /* Two possible forms:
4084 "{C|S}PSR_<field>, Rm",
4085 "{C|S}PSR_f, #expression". */
4091 skip_whitespace (str
);
4093 if (psr_required_here (& str
) == FAIL
)
4096 if (skip_past_comma (& str
) == FAIL
)
4098 inst
.error
= _("comma missing after psr flags");
4102 skip_whitespace (str
);
4104 if (reg_required_here (& str
, 0) != FAIL
)
4111 if (! is_immediate_prefix (* str
))
4114 _("only a register or immediate value can follow a psr flag");
4121 if (my_get_expression (& inst
.reloc
.exp
, & str
))
4124 _("only a register or immediate value can follow a psr flag");
4128 #if 0 /* The first edition of the ARM architecture manual stated that
4129 writing anything other than the flags with an immediate operation
4130 had UNPREDICTABLE effects. This constraint was removed in the
4131 second edition of the specification. */
4132 if ((cpu_variant
& ARM_EXT_V5
) != ARM_EXT_V5
4133 && inst
.instruction
& ((PSR_c
| PSR_x
| PSR_s
) << PSR_SHIFT
))
4135 inst
.error
= _("immediate value cannot be used to set this field");
4140 inst
.instruction
|= INST_IMMEDIATE
;
4142 if (inst
.reloc
.exp
.X_add_symbol
)
4144 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
4145 inst
.reloc
.pc_rel
= 0;
4149 unsigned value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
4151 if (value
== (unsigned) FAIL
)
4153 inst
.error
= _("invalid constant");
4157 inst
.instruction
|= value
;
4164 /* Long Multiply Parser
4165 UMULL RdLo, RdHi, Rm, Rs
4166 SMULL RdLo, RdHi, Rm, Rs
4167 UMLAL RdLo, RdHi, Rm, Rs
4168 SMLAL RdLo, RdHi, Rm, Rs. */
4174 int rdlo
, rdhi
, rm
, rs
;
4176 /* Only one format "rdlo, rdhi, rm, rs". */
4177 skip_whitespace (str
);
4179 if ((rdlo
= reg_required_here (&str
, 12)) == FAIL
)
4181 inst
.error
= BAD_ARGS
;
4185 if (skip_past_comma (&str
) == FAIL
4186 || (rdhi
= reg_required_here (&str
, 16)) == FAIL
)
4188 inst
.error
= BAD_ARGS
;
4192 if (skip_past_comma (&str
) == FAIL
4193 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4195 inst
.error
= BAD_ARGS
;
4199 /* rdhi, rdlo and rm must all be different. */
4200 if (rdlo
== rdhi
|| rdlo
== rm
|| rdhi
== rm
)
4201 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
4203 if (skip_past_comma (&str
) == FAIL
4204 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
4206 inst
.error
= BAD_ARGS
;
4210 if (rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
)
4212 inst
.error
= BAD_PC
;
4225 /* Only one format "rd, rm, rs". */
4226 skip_whitespace (str
);
4228 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
4230 inst
.error
= BAD_ARGS
;
4236 inst
.error
= BAD_PC
;
4240 if (skip_past_comma (&str
) == FAIL
4241 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4243 inst
.error
= BAD_ARGS
;
4249 inst
.error
= BAD_PC
;
4254 as_tsktsk (_("rd and rm should be different in mul"));
4256 if (skip_past_comma (&str
) == FAIL
4257 || (rm
= reg_required_here (&str
, 8)) == FAIL
)
4259 inst
.error
= BAD_ARGS
;
4265 inst
.error
= BAD_PC
;
4278 /* Only one format "rd, rm, rs, rn". */
4279 skip_whitespace (str
);
4281 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
4283 inst
.error
= BAD_ARGS
;
4289 inst
.error
= BAD_PC
;
4293 if (skip_past_comma (&str
) == FAIL
4294 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4296 inst
.error
= BAD_ARGS
;
4302 inst
.error
= BAD_PC
;
4307 as_tsktsk (_("rd and rm should be different in mla"));
4309 if (skip_past_comma (&str
) == FAIL
4310 || (rd
= reg_required_here (&str
, 8)) == FAIL
4311 || skip_past_comma (&str
) == FAIL
4312 || (rm
= reg_required_here (&str
, 12)) == FAIL
)
4314 inst
.error
= BAD_ARGS
;
4318 if (rd
== REG_PC
|| rm
== REG_PC
)
4320 inst
.error
= BAD_PC
;
4327 /* Expects *str -> the characters "acc0", possibly with leading blanks.
4328 Advances *str to the next non-alphanumeric.
4329 Returns 0, or else FAIL (in which case sets inst.error).
4331 (In a future XScale, there may be accumulators other than zero.
4332 At that time this routine and its callers can be upgraded to suit.) */
4335 accum0_required_here (str
)
4338 static char buff
[128]; /* Note the address is taken. Hence, static. */
4341 int result
= 0; /* The accum number. */
4343 skip_whitespace (p
);
4345 *str
= p
; /* Advance caller's string pointer too. */
4350 *--p
= 0; /* Aap nul into input buffer at non-alnum. */
4352 if (! ( streq (*str
, "acc0") || streq (*str
, "ACC0")))
4354 sprintf (buff
, _("acc0 expected, not '%.100s'"), *str
);
4359 *p
= c
; /* Unzap. */
4360 *str
= p
; /* Caller's string pointer to after match. */
4364 /* Expects **str -> after a comma. May be leading blanks.
4365 Advances *str, recognizing a load mode, and setting inst.instruction.
4366 Returns rn, or else FAIL (in which case may set inst.error
4367 and not advance str)
4369 Note: doesn't know Rd, so no err checks that require such knowledge. */
4372 ld_mode_required_here (string
)
4375 char * str
= * string
;
4379 skip_whitespace (str
);
4385 skip_whitespace (str
);
4387 if ((rn
= reg_required_here (& str
, 16)) == FAIL
)
4390 skip_whitespace (str
);
4396 if (skip_past_comma (& str
) == SUCCESS
)
4398 /* [Rn],... (post inc) */
4399 if (ldst_extend_v4 (&str
) == FAIL
)
4404 skip_whitespace (str
);
4409 inst
.instruction
|= WRITE_BACK
;
4412 inst
.instruction
|= INDEX_UP
| HWOFFSET_IMM
;
4418 if (skip_past_comma (& str
) == FAIL
)
4420 inst
.error
= _("pre-indexed expression expected");
4426 if (ldst_extend_v4 (&str
) == FAIL
)
4429 skip_whitespace (str
);
4431 if (* str
++ != ']')
4433 inst
.error
= _("missing ]");
4437 skip_whitespace (str
);
4442 inst
.instruction
|= WRITE_BACK
;
4446 else if (* str
== '=') /* ldr's "r,=label" syntax */
4447 /* We should never reach here, because <text> = <expression> is
4448 caught gas/read.c read_a_source_file() as a .set operation. */
4450 else /* PC +- 8 bit immediate offset. */
4452 if (my_get_expression (& inst
.reloc
.exp
, & str
))
4455 inst
.instruction
|= HWOFFSET_IMM
; /* The I bit. */
4456 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
4457 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
4458 inst
.reloc
.pc_rel
= 1;
4459 inst
.instruction
|= (REG_PC
<< 16);
4465 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
4471 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
4472 SMLAxy{cond} Rd,Rm,Rs,Rn
4473 SMLAWy{cond} Rd,Rm,Rs,Rn
4474 Error if any register is R15. */
4482 skip_whitespace (str
);
4484 if ((rd
= reg_required_here (& str
, 16)) == FAIL
4485 || skip_past_comma (& str
) == FAIL
4486 || (rm
= reg_required_here (& str
, 0)) == FAIL
4487 || skip_past_comma (& str
) == FAIL
4488 || (rs
= reg_required_here (& str
, 8)) == FAIL
4489 || skip_past_comma (& str
) == FAIL
4490 || (rn
= reg_required_here (& str
, 12)) == FAIL
)
4491 inst
.error
= BAD_ARGS
;
4493 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
|| rn
== REG_PC
)
4494 inst
.error
= BAD_PC
;
4500 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
4501 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
4502 Error if any register is R15.
4503 Warning if Rdlo == Rdhi. */
4509 int rdlo
, rdhi
, rm
, rs
;
4511 skip_whitespace (str
);
4513 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
4514 || skip_past_comma (& str
) == FAIL
4515 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
4516 || skip_past_comma (& str
) == FAIL
4517 || (rm
= reg_required_here (& str
, 0)) == FAIL
4518 || skip_past_comma (& str
) == FAIL
4519 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
4521 inst
.error
= BAD_ARGS
;
4525 if (rdlo
== REG_PC
|| rdhi
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
4527 inst
.error
= BAD_PC
;
4532 as_tsktsk (_("rdhi and rdlo must be different"));
4537 /* ARM V5E (El Segundo) signed-multiply (argument parse)
4538 SMULxy{cond} Rd,Rm,Rs
4539 Error if any register is R15. */
4547 skip_whitespace (str
);
4549 if ((rd
= reg_required_here (& str
, 16)) == FAIL
4550 || skip_past_comma (& str
) == FAIL
4551 || (rm
= reg_required_here (& str
, 0)) == FAIL
4552 || skip_past_comma (& str
) == FAIL
4553 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
4554 inst
.error
= BAD_ARGS
;
4556 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
4557 inst
.error
= BAD_PC
;
4563 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
4564 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
4565 Error if any register is R15. */
4573 skip_whitespace (str
);
4575 if ((rd
= reg_required_here (& str
, 12)) == FAIL
4576 || skip_past_comma (& str
) == FAIL
4577 || (rm
= reg_required_here (& str
, 0)) == FAIL
4578 || skip_past_comma (& str
) == FAIL
4579 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
4580 inst
.error
= BAD_ARGS
;
4582 else if (rd
== REG_PC
|| rm
== REG_PC
|| rn
== REG_PC
)
4583 inst
.error
= BAD_PC
;
4589 /* ARM V5E (el Segundo)
4590 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4591 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4593 These are equivalent to the XScale instructions MAR and MRA,
4594 respectively, when coproc == 0, opcode == 0, and CRm == 0.
4596 Result unpredicatable if Rd or Rn is R15. */
4604 skip_whitespace (str
);
4606 if (co_proc_number (& str
) == FAIL
)
4609 inst
.error
= BAD_ARGS
;
4613 if (skip_past_comma (& str
) == FAIL
4614 || cp_opc_expr (& str
, 4, 4) == FAIL
)
4617 inst
.error
= BAD_ARGS
;
4621 if (skip_past_comma (& str
) == FAIL
4622 || (rd
= reg_required_here (& str
, 12)) == FAIL
)
4625 inst
.error
= BAD_ARGS
;
4629 if (skip_past_comma (& str
) == FAIL
4630 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
4633 inst
.error
= BAD_ARGS
;
4637 /* Unpredictable result if rd or rn is R15. */
4638 if (rd
== REG_PC
|| rn
== REG_PC
)
4640 (_("Warning: instruction unpredictable when using r15"));
4642 if (skip_past_comma (& str
) == FAIL
4643 || cp_reg_required_here (& str
, 0) == FAIL
)
4646 inst
.error
= BAD_ARGS
;
4653 /* ARM V5 count-leading-zeroes instruction (argument parse)
4654 CLZ{<cond>} <Rd>, <Rm>
4655 Condition defaults to COND_ALWAYS.
4656 Error if Rd or Rm are R15. */
4664 skip_whitespace (str
);
4666 if (((rd
= reg_required_here (& str
, 12)) == FAIL
)
4667 || (skip_past_comma (& str
) == FAIL
)
4668 || ((rm
= reg_required_here (& str
, 0)) == FAIL
))
4669 inst
.error
= BAD_ARGS
;
4671 else if (rd
== REG_PC
|| rm
== REG_PC
)
4672 inst
.error
= BAD_PC
;
4678 /* ARM V5 (argument parse)
4679 LDC2{L} <coproc>, <CRd>, <addressing mode>
4680 STC2{L} <coproc>, <CRd>, <addressing mode>
4681 Instruction is not conditional, and has 0xf in the condition field.
4682 Otherwise, it's the same as LDC/STC. */
4688 skip_whitespace (str
);
4690 if (co_proc_number (& str
) == FAIL
)
4693 inst
.error
= BAD_ARGS
;
4695 else if (skip_past_comma (& str
) == FAIL
4696 || cp_reg_required_here (& str
, 12) == FAIL
)
4699 inst
.error
= BAD_ARGS
;
4701 else if (skip_past_comma (& str
) == FAIL
4702 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
4705 inst
.error
= BAD_ARGS
;
4711 /* ARM V5 (argument parse)
4712 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
4713 Instruction is not conditional, and has 0xf in the condition field.
4714 Otherwise, it's the same as CDP. */
4720 skip_whitespace (str
);
4722 if (co_proc_number (& str
) == FAIL
)
4725 inst
.error
= BAD_ARGS
;
4729 if (skip_past_comma (& str
) == FAIL
4730 || cp_opc_expr (& str
, 20,4) == FAIL
)
4733 inst
.error
= BAD_ARGS
;
4737 if (skip_past_comma (& str
) == FAIL
4738 || cp_reg_required_here (& str
, 12) == FAIL
)
4741 inst
.error
= BAD_ARGS
;
4745 if (skip_past_comma (& str
) == FAIL
4746 || cp_reg_required_here (& str
, 16) == FAIL
)
4749 inst
.error
= BAD_ARGS
;
4753 if (skip_past_comma (& str
) == FAIL
4754 || cp_reg_required_here (& str
, 0) == FAIL
)
4757 inst
.error
= BAD_ARGS
;
4761 if (skip_past_comma (& str
) == SUCCESS
)
4763 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
4766 inst
.error
= BAD_ARGS
;
4774 /* ARM V5 (argument parse)
4775 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4776 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4777 Instruction is not conditional, and has 0xf in the condition field.
4778 Otherwise, it's the same as MCR/MRC. */
4784 skip_whitespace (str
);
4786 if (co_proc_number (& str
) == FAIL
)
4789 inst
.error
= BAD_ARGS
;
4793 if (skip_past_comma (& str
) == FAIL
4794 || cp_opc_expr (& str
, 21, 3) == FAIL
)
4797 inst
.error
= BAD_ARGS
;
4801 if (skip_past_comma (& str
) == FAIL
4802 || reg_required_here (& str
, 12) == FAIL
)
4805 inst
.error
= BAD_ARGS
;
4809 if (skip_past_comma (& str
) == FAIL
4810 || cp_reg_required_here (& str
, 16) == FAIL
)
4813 inst
.error
= BAD_ARGS
;
4817 if (skip_past_comma (& str
) == FAIL
4818 || cp_reg_required_here (& str
, 0) == FAIL
)
4821 inst
.error
= BAD_ARGS
;
4825 if (skip_past_comma (& str
) == SUCCESS
)
4827 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
4830 inst
.error
= BAD_ARGS
;
4838 /* ARM v5TEJ. Jump to Jazelle code. */
4845 skip_whitespace (str
);
4847 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
4849 inst
.error
= BAD_ARGS
;
4853 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
4855 as_tsktsk (_("use of r15 in bxj is not really useful"));
4860 /* ARM V6 umaal (argument parse). */
4867 int rdlo
, rdhi
, rm
, rs
;
4869 skip_whitespace (str
);
4870 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
4871 || skip_past_comma (& str
) == FAIL
4872 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
4873 || skip_past_comma (& str
) == FAIL
4874 || (rm
= reg_required_here (& str
, 0)) == FAIL
4875 || skip_past_comma (& str
) == FAIL
4876 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
4878 inst
.error
= BAD_ARGS
;
4882 if (rdlo
== REG_PC
|| rdhi
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
4884 inst
.error
= BAD_PC
;
4891 /* ARM V6 strex (argument parse). */
4899 /* Parse Rd, Rm,. */
4900 skip_whitespace (str
);
4901 if ((rd
= reg_required_here (& str
, 12)) == FAIL
4902 || skip_past_comma (& str
) == FAIL
4903 || (rm
= reg_required_here (& str
, 0)) == FAIL
4904 || skip_past_comma (& str
) == FAIL
)
4906 inst
.error
= BAD_ARGS
;
4909 if (rd
== REG_PC
|| rm
== REG_PC
)
4911 inst
.error
= BAD_PC
;
4916 inst
.error
= _("Rd equal to Rm or Rn yields unpredictable results");
4920 /* Skip past '['. */
4921 if ((strlen (str
) >= 1)
4922 && strncmp (str
, "[", 1) == 0)
4924 skip_whitespace (str
);
4927 if ((rn
= reg_required_here (& str
, 16)) == FAIL
)
4929 inst
.error
= BAD_ARGS
;
4932 else if (rn
== REG_PC
)
4934 inst
.error
= BAD_PC
;
4939 inst
.error
= _("Rd equal to Rm or Rn yields unpredictable results");
4942 skip_whitespace (str
);
4944 /* Skip past ']'. */
4945 if ((strlen (str
) >= 1)
4946 && strncmp (str
, "]", 1) == 0)
4952 /* ARM V6 ssat (argument parse). */
4958 do_sat (&str
, /*bias=*/-1);
4962 /* ARM V6 usat (argument parse). */
4968 do_sat (&str
, /*bias=*/0);
4980 skip_whitespace (*str
);
4982 /* Parse <Rd>, field. */
4983 if ((rd
= reg_required_here (str
, 12)) == FAIL
4984 || skip_past_comma (str
) == FAIL
)
4986 inst
.error
= BAD_ARGS
;
4991 inst
.error
= BAD_PC
;
4995 /* Parse #<immed>, field. */
4996 if (is_immediate_prefix (**str
))
5000 inst
.error
= _("immediate expression expected");
5003 if (my_get_expression (&expr
, str
))
5005 inst
.error
= _("bad expression");
5008 if (expr
.X_op
!= O_constant
)
5010 inst
.error
= _("constant expression expected");
5013 if (expr
.X_add_number
+ bias
< 0
5014 || expr
.X_add_number
+ bias
> 31)
5016 inst
.error
= _("immediate value out of range");
5019 inst
.instruction
|= (expr
.X_add_number
+ bias
) << 16;
5020 if (skip_past_comma (str
) == FAIL
)
5022 inst
.error
= BAD_ARGS
;
5026 /* Parse <Rm> field. */
5027 if ((rm
= reg_required_here (str
, 0)) == FAIL
)
5029 inst
.error
= BAD_ARGS
;
5034 inst
.error
= BAD_PC
;
5038 if (skip_past_comma (str
) == SUCCESS
)
5039 decode_shift (str
, SHIFT_LSL_OR_ASR_IMMEDIATE
);
5042 /* ARM V6 ssat16 (argument parse). */
5048 do_sat16 (&str
, /*bias=*/-1);
5056 do_sat16 (&str
, /*bias=*/0);
5061 do_sat16 (str
, bias
)
5068 skip_whitespace (*str
);
5070 /* Parse the <Rd> field. */
5071 if ((rd
= reg_required_here (str
, 12)) == FAIL
5072 || skip_past_comma (str
) == FAIL
)
5074 inst
.error
= BAD_ARGS
;
5079 inst
.error
= BAD_PC
;
5083 /* Parse #<immed>, field. */
5084 if (is_immediate_prefix (**str
))
5088 inst
.error
= _("immediate expression expected");
5091 if (my_get_expression (&expr
, str
))
5093 inst
.error
= _("bad expression");
5096 if (expr
.X_op
!= O_constant
)
5098 inst
.error
= _("constant expression expected");
5101 if (expr
.X_add_number
+ bias
< 0
5102 || expr
.X_add_number
+ bias
> 15)
5104 inst
.error
= _("immediate value out of range");
5107 inst
.instruction
|= (expr
.X_add_number
+ bias
) << 16;
5108 if (skip_past_comma (str
) == FAIL
)
5110 inst
.error
= BAD_ARGS
;
5114 /* Parse <Rm> field. */
5115 if ((rm
= reg_required_here (str
, 0)) == FAIL
)
5117 inst
.error
= BAD_ARGS
;
5122 inst
.error
= BAD_PC
;
5127 /* ARM V6 srs (argument parse). */
5134 skip_whitespace (str
);
5135 exclam
= strchr (str
, '!');
5143 inst
.instruction
|= WRITE_BACK
;
5149 /* ARM V6 SMMUL (argument parse). */
5157 skip_whitespace (str
);
5158 if ((rd
= reg_required_here (&str
, 16)) == FAIL
5159 || skip_past_comma (&str
) == FAIL
5160 || (rm
= reg_required_here (&str
, 0)) == FAIL
5161 || skip_past_comma (&str
) == FAIL
5162 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
5164 inst
.error
= BAD_ARGS
;
5172 inst
.error
= BAD_PC
;
5180 /* ARM V6 SMLALD (argument parse). */
5186 int rdlo
, rdhi
, rm
, rs
;
5187 skip_whitespace (str
);
5188 if ((rdlo
= reg_required_here (&str
, 12)) == FAIL
5189 || skip_past_comma (&str
) == FAIL
5190 || (rdhi
= reg_required_here (&str
, 16)) == FAIL
5191 || skip_past_comma (&str
) == FAIL
5192 || (rm
= reg_required_here (&str
, 0)) == FAIL
5193 || skip_past_comma (&str
) == FAIL
5194 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
5196 inst
.error
= BAD_ARGS
;
5205 inst
.error
= BAD_PC
;
5212 /* ARM V6 SMLAD (argument parse). Signed multiply accumulate dual.
5213 smlad{x}{<cond>} Rd, Rm, Rs, Rn */
5221 skip_whitespace (str
);
5222 if ((rd
= reg_required_here (&str
, 16)) == FAIL
5223 || skip_past_comma (&str
) == FAIL
5224 || (rm
= reg_required_here (&str
, 0)) == FAIL
5225 || skip_past_comma (&str
) == FAIL
5226 || (rs
= reg_required_here (&str
, 8)) == FAIL
5227 || skip_past_comma (&str
) == FAIL
5228 || (rn
= reg_required_here (&str
, 12)) == FAIL
)
5230 inst
.error
= BAD_ARGS
;
5239 inst
.error
= BAD_PC
;
5246 /* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
5247 preserving the other bits.
5249 setend <endian_specifier>, where <endian_specifier> is either
5256 if (do_endian_specifier (str
))
5257 inst
.instruction
|= 0x200;
5260 /* Returns true if the endian-specifier indicates big-endianness. */
5263 do_endian_specifier (str
)
5268 skip_whitespace (str
);
5269 if (strlen (str
) < 2)
5270 inst
.error
= _("missing endian specifier");
5271 else if (strncasecmp (str
, "BE", 2) == 0)
5276 else if (strncasecmp (str
, "LE", 2) == 0)
5279 inst
.error
= _("valid endian specifiers are be or le");
5288 SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
5289 Condition defaults to COND_ALWAYS.
5290 Error if any register uses R15. */
5298 int rotation_clear_mask
= 0xfffff3ff;
5299 int rotation_eight_mask
= 0x00000400;
5300 int rotation_sixteen_mask
= 0x00000800;
5301 int rotation_twenty_four_mask
= 0x00000c00;
5303 skip_whitespace (str
);
5304 if ((rd
= reg_required_here (&str
, 12)) == FAIL
5305 || skip_past_comma (&str
) == FAIL
5306 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
5308 inst
.error
= BAD_ARGS
;
5312 else if (rd
== REG_PC
|| rm
== REG_PC
)
5314 inst
.error
= BAD_PC
;
5318 /* Zero out the rotation field. */
5319 inst
.instruction
&= rotation_clear_mask
;
5321 /* Check for lack of optional rotation field. */
5322 if (skip_past_comma (&str
) == FAIL
)
5328 /* Move past 'ROR'. */
5329 skip_whitespace (str
);
5330 if (strncasecmp (str
, "ROR", 3) == 0)
5334 inst
.error
= _("missing rotation field after comma");
5338 /* Get the immediate constant. */
5339 skip_whitespace (str
);
5340 if (is_immediate_prefix (* str
))
5344 inst
.error
= _("immediate expression expected");
5348 if (my_get_expression (&expr
, &str
))
5350 inst
.error
= _("bad expression");
5354 if (expr
.X_op
!= O_constant
)
5356 inst
.error
= _("constant expression expected");
5360 switch (expr
.X_add_number
)
5363 /* Rotation field has already been zeroed. */
5366 inst
.instruction
|= rotation_eight_mask
;
5370 inst
.instruction
|= rotation_sixteen_mask
;
5374 inst
.instruction
|= rotation_twenty_four_mask
;
5378 inst
.error
= _("rotation can be 8, 16, 24 or 0 when field is ommited");
5386 /* ARM V6 SXTAH extracts a 16-bit value from a register, sign
5387 extends it to 32-bits, and adds the result to a value in another
5388 register. You can specify a rotation by 0, 8, 16, or 24 bits
5389 before extracting the 16-bit value.
5390 SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
5391 Condition defaults to COND_ALWAYS.
5392 Error if any register uses R15. */
5400 int rotation_clear_mask
= 0xfffff3ff;
5401 int rotation_eight_mask
= 0x00000400;
5402 int rotation_sixteen_mask
= 0x00000800;
5403 int rotation_twenty_four_mask
= 0x00000c00;
5405 skip_whitespace (str
);
5406 if ((rd
= reg_required_here (&str
, 12)) == FAIL
5407 || skip_past_comma (&str
) == FAIL
5408 || (rn
= reg_required_here (&str
, 16)) == FAIL
5409 || skip_past_comma (&str
) == FAIL
5410 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
5412 inst
.error
= BAD_ARGS
;
5416 else if (rd
== REG_PC
|| rn
== REG_PC
|| rm
== REG_PC
)
5418 inst
.error
= BAD_PC
;
5422 /* Zero out the rotation field. */
5423 inst
.instruction
&= rotation_clear_mask
;
5425 /* Check for lack of optional rotation field. */
5426 if (skip_past_comma (&str
) == FAIL
)
5432 /* Move past 'ROR'. */
5433 skip_whitespace (str
);
5434 if (strncasecmp (str
, "ROR", 3) == 0)
5438 inst
.error
= _("missing rotation field after comma");
5442 /* Get the immediate constant. */
5443 skip_whitespace (str
);
5444 if (is_immediate_prefix (* str
))
5448 inst
.error
= _("immediate expression expected");
5452 if (my_get_expression (&expr
, &str
))
5454 inst
.error
= _("bad expression");
5458 if (expr
.X_op
!= O_constant
)
5460 inst
.error
= _("constant expression expected");
5464 switch (expr
.X_add_number
)
5467 /* Rotation field has already been zeroed. */
5471 inst
.instruction
|= rotation_eight_mask
;
5475 inst
.instruction
|= rotation_sixteen_mask
;
5479 inst
.instruction
|= rotation_twenty_four_mask
;
5483 inst
.error
= _("rotation can be 8, 16, 24 or 0 when field is ommited");
5492 /* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
5493 word at the specified address and the following word
5495 Unconditionally executed.
5505 skip_whitespace (str
);
5507 if ((rn
= reg_required_here (&str
, 16)) == FAIL
)
5512 inst
.error
= BAD_PC
;
5516 skip_whitespace (str
);
5520 inst
.instruction
|= WRITE_BACK
;
5526 /* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
5527 register (argument parse).
5529 Condition defaults to COND_ALWAYS.
5530 Error if Rd or Rm are R15. */
5538 skip_whitespace (str
);
5540 if ((rd
= reg_required_here (&str
, 12)) == FAIL
5541 || skip_past_comma (&str
) == FAIL
5542 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
5543 inst
.error
= BAD_ARGS
;
5545 else if (rd
== REG_PC
|| rm
== REG_PC
)
5546 inst
.error
= BAD_PC
;
5552 /* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
5553 QADD16{<cond>} <Rd>, <Rn>, <Rm>
5554 Condition defaults to COND_ALWAYS.
5555 Error if Rd, Rn or Rm are R15. */
5563 skip_whitespace (str
);
5565 if ((rd
= reg_required_here (&str
, 12)) == FAIL
5566 || skip_past_comma (&str
) == FAIL
5567 || (rn
= reg_required_here (&str
, 16)) == FAIL
5568 || skip_past_comma (&str
) == FAIL
5569 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
5570 inst
.error
= BAD_ARGS
;
5572 else if (rd
== REG_PC
|| rm
== REG_PC
|| rn
== REG_PC
)
5573 inst
.error
= BAD_PC
;
5579 /* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
5580 PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
5581 Condition defaults to COND_ALWAYS.
5582 Error if Rd, Rn or Rm are R15. */
5588 do_pkh_core (str
, SHIFT_LSL_IMMEDIATE
);
5591 /* ARM V6 PKHTB (Argument Parse). */
5597 do_pkh_core (str
, SHIFT_ASR_IMMEDIATE
);
5601 do_pkh_core (str
, shift
)
5607 skip_whitespace (str
);
5608 if (((rd
= reg_required_here (&str
, 12)) == FAIL
)
5609 || (skip_past_comma (&str
) == FAIL
)
5610 || ((rn
= reg_required_here (&str
, 16)) == FAIL
)
5611 || (skip_past_comma (&str
) == FAIL
)
5612 || ((rm
= reg_required_here (&str
, 0)) == FAIL
))
5614 inst
.error
= BAD_ARGS
;
5618 else if (rd
== REG_PC
|| rn
== REG_PC
|| rm
== REG_PC
)
5620 inst
.error
= BAD_PC
;
5624 /* Check for optional shift immediate constant. */
5625 if (skip_past_comma (&str
) == FAIL
)
5627 if (shift
== SHIFT_ASR_IMMEDIATE
)
5629 /* If the shift specifier is ommited, turn the instruction
5630 into pkhbt rd, rm, rn. First, switch the instruction
5631 code, and clear the rn and rm fields. */
5632 inst
.instruction
&= 0xfff0f010;
5633 /* Now, re-encode the registers. */
5634 inst
.instruction
|= (rm
<< 16) | rn
;
5639 decode_shift (&str
, shift
);
5642 /* ARM V6 Load Register Exclusive instruction (argument parse).
5643 LDREX{<cond>} <Rd, [<Rn>]
5644 Condition defaults to COND_ALWAYS.
5645 Error if Rd or Rn are R15.
5646 See ARMARMv6 A4.1.27: LDREX. */
5655 skip_whitespace (str
);
5658 if (((rd
= reg_required_here (&str
, 12)) == FAIL
)
5659 || (skip_past_comma (&str
) == FAIL
))
5661 inst
.error
= BAD_ARGS
;
5664 else if (rd
== REG_PC
)
5666 inst
.error
= BAD_PC
;
5669 skip_whitespace (str
);
5671 /* Skip past '['. */
5672 if ((strlen (str
) >= 1)
5673 &&strncmp (str
, "[", 1) == 0)
5675 skip_whitespace (str
);
5678 if ((rn
= reg_required_here (&str
, 16)) == FAIL
)
5680 inst
.error
= BAD_ARGS
;
5683 else if (rn
== REG_PC
)
5685 inst
.error
= BAD_PC
;
5688 skip_whitespace (str
);
5690 /* Skip past ']'. */
5691 if ((strlen (str
) >= 1)
5692 && strncmp (str
, "]", 1) == 0)
5698 /* ARM V6 change processor state instruction (argument parse)
5699 CPS, CPSIE, CSPID . */
5713 do_cps_flags (&str
, /*thumb_p=*/0);
5715 if (skip_past_comma (&str
) == SUCCESS
)
5717 skip_whitespace (str
);
5729 skip_whitespace (*str
);
5731 if (! is_immediate_prefix (**str
))
5733 inst
.error
= _("immediate expression expected");
5737 (*str
)++; /* Strip off the immediate signifier. */
5738 if (my_get_expression (&expr
, str
))
5740 inst
.error
= _("bad expression");
5744 if (expr
.X_op
!= O_constant
)
5746 inst
.error
= _("constant expression expected");
5750 /* The mode is a 5 bit field. Valid values are 0-31. */
5751 if (((unsigned) expr
.X_add_number
) > 31
5752 || (inst
.reloc
.exp
.X_add_number
) < 0)
5754 inst
.error
= _("invalid constant");
5758 inst
.instruction
|= expr
.X_add_number
;
5762 do_cps_flags (str
, thumb_p
)
5768 unsigned long arm_value
;
5769 unsigned long thumb_value
;
5771 static struct cps_flag flag_table
[] = {
5779 skip_whitespace (*str
);
5781 /* Get the a, f and i flags. */
5782 while (**str
&& **str
!= ',')
5785 struct cps_flag
*q
= flag_table
+ sizeof (flag_table
)/sizeof (*p
);
5786 for (p
= flag_table
; p
< q
; ++p
)
5787 if (strncasecmp (*str
, &p
->character
, 1) == 0)
5789 inst
.instruction
|= (thumb_p
? p
->thumb_value
: p
->arm_value
);
5795 inst
.error
= _("unrecognized flag");
5801 inst
.error
= _("no 'a', 'i', or 'f' flags for 'cps'");
5804 /* THUMB V5 breakpoint instruction (argument parse)
5812 unsigned long number
;
5814 skip_whitespace (str
);
5816 /* Allow optional leading '#'. */
5817 if (is_immediate_prefix (*str
))
5820 memset (& expr
, '\0', sizeof (expr
));
5821 if (my_get_expression (& expr
, & str
)
5822 || (expr
.X_op
!= O_constant
5823 /* As a convenience we allow 'bkpt' without an operand. */
5824 && expr
.X_op
!= O_absent
))
5826 inst
.error
= _("bad expression");
5830 number
= expr
.X_add_number
;
5832 /* Check it fits an 8 bit unsigned. */
5833 if (number
!= (number
& 0xff))
5835 inst
.error
= _("immediate value out of range");
5839 inst
.instruction
|= number
;
5844 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
5845 Expects inst.instruction is set for BLX(1).
5846 Note: this is cloned from do_branch, and the reloc changed to be a
5847 new one that can cope with setting one extra bit (the H bit). */
5853 if (my_get_expression (& inst
.reloc
.exp
, & str
))
5860 /* ScottB: February 5, 1998 */
5861 /* Check to see of PLT32 reloc required for the instruction. */
5863 /* arm_parse_reloc() works on input_line_pointer.
5864 We actually want to parse the operands to the branch instruction
5865 passed in 'str'. Save the input pointer and restore it later. */
5866 save_in
= input_line_pointer
;
5867 input_line_pointer
= str
;
5869 if (inst
.reloc
.exp
.X_op
== O_symbol
5871 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
5873 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
5874 inst
.reloc
.pc_rel
= 0;
5875 /* Modify str to point to after parsed operands, otherwise
5876 end_of_line() will complain about the (PLT) left in str. */
5877 str
= input_line_pointer
;
5881 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
5882 inst
.reloc
.pc_rel
= 1;
5885 input_line_pointer
= save_in
;
5888 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
5889 inst
.reloc
.pc_rel
= 1;
5890 #endif /* OBJ_ELF */
5895 /* ARM V5 branch-link-exchange instruction (argument parse)
5896 BLX <target_addr> ie BLX(1)
5897 BLX{<condition>} <Rm> ie BLX(2)
5898 Unfortunately, there are two different opcodes for this mnemonic.
5899 So, the insns[].value is not used, and the code here zaps values
5900 into inst.instruction.
5901 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
5910 skip_whitespace (mystr
);
5911 rm
= reg_required_here (& mystr
, 0);
5913 /* The above may set inst.error. Ignore his opinion. */
5918 /* Arg is a register.
5919 Use the condition code our caller put in inst.instruction.
5920 Pass ourselves off as a BX with a funny opcode. */
5921 inst
.instruction
|= 0x012fff30;
5926 /* This must be is BLX <target address>, no condition allowed. */
5927 if (inst
.instruction
!= COND_ALWAYS
)
5929 inst
.error
= BAD_COND
;
5933 inst
.instruction
= 0xfafffffe;
5935 /* Process like a B/BL, but with a different reloc.
5936 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
5941 /* ARM V5 Thumb BLX (argument parse)
5942 BLX <target_addr> which is BLX(1)
5943 BLX <Rm> which is BLX(2)
5944 Unfortunately, there are two different opcodes for this mnemonic.
5945 So, the tinsns[].value is not used, and the code here zaps values
5946 into inst.instruction. */
5955 skip_whitespace (mystr
);
5956 inst
.instruction
= 0x4780;
5958 /* Note that this call is to the ARM register recognizer. BLX(2)
5959 uses the ARM register space, not the Thumb one, so a call to
5960 thumb_reg() would be wrong. */
5961 rm
= reg_required_here (& mystr
, 3);
5966 /* It's BLX(2). The .instruction was zapped with rm & is final. */
5971 /* No ARM register. This must be BLX(1). Change the .instruction. */
5972 inst
.instruction
= 0xf7ffeffe;
5975 if (my_get_expression (& inst
.reloc
.exp
, & mystr
))
5978 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BLX
;
5979 inst
.reloc
.pc_rel
= 1;
5982 end_of_line (mystr
);
5985 /* ARM V5 breakpoint instruction (argument parse)
5986 BKPT <16 bit unsigned immediate>
5987 Instruction is not conditional.
5988 The bit pattern given in insns[] has the COND_ALWAYS condition,
5989 and it is an error if the caller tried to override that. */
5996 unsigned long number
;
5998 skip_whitespace (str
);
6000 /* Allow optional leading '#'. */
6001 if (is_immediate_prefix (* str
))
6004 memset (& expr
, '\0', sizeof (expr
));
6006 if (my_get_expression (& expr
, & str
)
6007 || (expr
.X_op
!= O_constant
6008 /* As a convenience we allow 'bkpt' without an operand. */
6009 && expr
.X_op
!= O_absent
))
6011 inst
.error
= _("bad expression");
6015 number
= expr
.X_add_number
;
6017 /* Check it fits a 16 bit unsigned. */
6018 if (number
!= (number
& 0xffff))
6020 inst
.error
= _("immediate value out of range");
6024 /* Top 12 of 16 bits to bits 19:8. */
6025 inst
.instruction
|= (number
& 0xfff0) << 4;
6027 /* Bottom 4 of 16 bits to bits 3:0. */
6028 inst
.instruction
|= number
& 0xf;
6033 /* THUMB CPS instruction (argument parse). */
6039 do_cps_flags (&str
, /*thumb_p=*/1);
6043 /* THUMB CPY instruction (argument parse). */
6049 thumb_mov_compare (str
, THUMB_CPY
);
6052 /* THUMB SETEND instruction (argument parse). */
6058 if (do_endian_specifier (str
))
6059 inst
.instruction
|= 0x8;
6062 static unsigned long check_iwmmxt_insn
PARAMS ((char *, enum iwmmxt_insn_type
, int));
6064 /* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
6066 static unsigned long
6067 check_iwmmxt_insn (str
, insn_type
, immediate_size
)
6069 enum iwmmxt_insn_type insn_type
;
6073 const char * inst_error
;
6075 unsigned long number
;
6077 inst_error
= inst
.error
;
6079 inst
.error
= BAD_ARGS
;
6080 skip_whitespace (str
);
6085 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
6090 if ((wreg_required_here (&str
, 0, IWMMXT_REG_WR
)) == FAIL
)
6095 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
6096 || skip_past_comma (&str
) == FAIL
6097 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
))
6102 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
6103 || skip_past_comma (&str
) == FAIL
6104 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6105 || skip_past_comma (&str
) == FAIL
6106 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
))
6111 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
6112 || skip_past_comma (&str
) == FAIL
6113 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6114 || skip_past_comma (&str
) == FAIL
6115 || wreg_required_here (&str
, 0, IWMMXT_REG_WCG
) == FAIL
))
6120 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6121 || skip_past_comma (&str
) == FAIL
6122 || reg_required_here (&str
, 12) == FAIL
))
6127 if ((reg_required_here (&str
, 12) == FAIL
6128 || skip_past_comma (&str
) == FAIL
6129 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
))
6134 if ((wreg_required_here (&str
, 5, IWMMXT_REG_WR
) == FAIL
6135 || skip_past_comma (&str
) == FAIL
6136 || reg_required_here (&str
, 0) == FAIL
6137 || skip_past_comma (&str
) == FAIL
6138 || reg_required_here (&str
, 12) == FAIL
))
6143 if ((wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
6144 || skip_past_comma (&str
) == FAIL
6145 || reg_required_here (&str
, 12) == FAIL
6146 || skip_past_comma (&str
) == FAIL
6147 || reg_required_here (&str
, 16) == FAIL
))
6152 if ((reg_required_here (&str
, 12) == FAIL
6153 || skip_past_comma (&str
) == FAIL
6154 || reg_required_here (&str
, 16) == FAIL
6155 || skip_past_comma (&str
) == FAIL
6156 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
))
6161 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WC
) == FAIL
6162 || skip_past_comma (&str
) == FAIL
6163 || reg_required_here (&str
, 12) == FAIL
))
6168 if ((reg_required_here (&str
, 12) == FAIL
6169 || skip_past_comma (&str
) == FAIL
6170 || wreg_required_here (&str
, 16, IWMMXT_REG_WC
) == FAIL
))
6175 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6176 || skip_past_comma (&str
) == FAIL
6177 || reg_required_here (&str
, 12) == FAIL
6178 || skip_past_comma (&str
) == FAIL
))
6183 if ((reg_required_here (&str
, 12) == FAIL
6184 || skip_past_comma (&str
) == FAIL
))
6189 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
6190 || skip_past_comma (&str
) == FAIL
6191 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6192 || skip_past_comma (&str
) == FAIL
6193 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
6194 || skip_past_comma (&str
) == FAIL
))
6199 if ((reg_required_here (&str
, 12) == FAIL
6200 || skip_past_comma (&str
) == FAIL
6201 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6202 || skip_past_comma (&str
) == FAIL
))
6207 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
6208 || skip_past_comma (&str
) == FAIL
6209 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6210 || skip_past_comma (&str
) == FAIL
))
6215 if (immediate_size
== 0)
6218 inst
.error
= inst_error
;
6223 skip_whitespace (str
);
6225 /* Allow optional leading '#'. */
6226 if (is_immediate_prefix (* str
))
6229 memset (& expr
, '\0', sizeof (expr
));
6231 if (my_get_expression (& expr
, & str
) || (expr
.X_op
!= O_constant
))
6233 inst
.error
= _("bad or missing expression");
6237 number
= expr
.X_add_number
;
6239 if (number
!= (number
& immediate_size
))
6241 inst
.error
= _("immediate value out of range");
6245 inst
.error
= inst_error
;
6251 do_iwmmxt_byte_addr (str
)
6254 int op
= (inst
.instruction
& 0x300) >> 8;
6257 inst
.instruction
&= ~0x300;
6258 inst
.instruction
|= (op
& 1) << 22 | (op
& 2) << 7;
6260 skip_whitespace (str
);
6262 if ((reg
= wreg_required_here (&str
, 12, IWMMXT_REG_WR_OR_WC
)) == FAIL
6263 || skip_past_comma (& str
) == FAIL
6264 || cp_byte_address_required_here (&str
) == FAIL
)
6267 inst
.error
= BAD_ARGS
;
6272 if (wc_register (reg
))
6274 as_bad (_("non-word size not supported with control register"));
6275 inst
.instruction
|= 0xf0000100;
6276 inst
.instruction
&= ~0x00400000;
6281 do_iwmmxt_tandc (str
)
6286 reg
= check_iwmmxt_insn (str
, check_rd
, 0);
6288 if (reg
!= REG_PC
&& !inst
.error
)
6289 inst
.error
= _("only r15 allowed here");
6293 do_iwmmxt_tbcst (str
)
6296 check_iwmmxt_insn (str
, check_tbcst
, 0);
6300 do_iwmmxt_textrc (str
)
6303 unsigned long number
;
6305 if ((number
= check_iwmmxt_insn (str
, check_textrc
, 7)) == (unsigned long) FAIL
)
6308 inst
.instruction
|= number
& 0x7;
6312 do_iwmmxt_textrm (str
)
6315 unsigned long number
;
6317 if ((number
= check_iwmmxt_insn (str
, check_textrm
, 7)) == (unsigned long) FAIL
)
6320 inst
.instruction
|= number
& 0x7;
6324 do_iwmmxt_tinsr (str
)
6327 unsigned long number
;
6329 if ((number
= check_iwmmxt_insn (str
, check_tinsr
, 7)) == (unsigned long) FAIL
)
6332 inst
.instruction
|= number
& 0x7;
6336 do_iwmmxt_tmcr (str
)
6339 check_iwmmxt_insn (str
, check_tmcr
, 0);
6343 do_iwmmxt_tmcrr (str
)
6346 check_iwmmxt_insn (str
, check_tmcrr
, 0);
6350 do_iwmmxt_tmia (str
)
6353 check_iwmmxt_insn (str
, check_tmia
, 0);
6357 do_iwmmxt_tmovmsk (str
)
6360 check_iwmmxt_insn (str
, check_tmovmsk
, 0);
6364 do_iwmmxt_tmrc (str
)
6367 check_iwmmxt_insn (str
, check_tmrc
, 0);
6371 do_iwmmxt_tmrrc (str
)
6374 check_iwmmxt_insn (str
, check_tmrrc
, 0);
6378 do_iwmmxt_torc (str
)
6381 check_iwmmxt_insn (str
, check_rd
, 0);
6385 do_iwmmxt_waligni (str
)
6388 unsigned long number
;
6390 if ((number
= check_iwmmxt_insn (str
, check_waligni
, 7)) == (unsigned long) FAIL
)
6393 inst
.instruction
|= ((number
& 0x7) << 20);
6397 do_iwmmxt_wmov (str
)
6400 if (check_iwmmxt_insn (str
, check_wrwr
, 0) == (unsigned long) FAIL
)
6403 inst
.instruction
|= ((inst
.instruction
>> 16) & 0xf);
6407 do_iwmmxt_word_addr (str
)
6410 int op
= (inst
.instruction
& 0x300) >> 8;
6413 inst
.instruction
&= ~0x300;
6414 inst
.instruction
|= (op
& 1) << 22 | (op
& 2) << 7;
6416 skip_whitespace (str
);
6418 if ((reg
= wreg_required_here (&str
, 12, IWMMXT_REG_WR_OR_WC
)) == FAIL
6419 || skip_past_comma (& str
) == FAIL
6420 || cp_address_required_here (& str
, CP_WB_OK
) == FAIL
)
6423 inst
.error
= BAD_ARGS
;
6428 if (wc_register (reg
))
6430 if ((inst
.instruction
& COND_MASK
) != COND_ALWAYS
)
6431 as_bad (_("conditional execution not supported with control register"));
6433 as_bad (_("non-word size not supported with control register"));
6434 inst
.instruction
|= 0xf0000100;
6435 inst
.instruction
&= ~0x00400000;
6440 do_iwmmxt_wrwr (str
)
6443 check_iwmmxt_insn (str
, check_wrwr
, 0);
6447 do_iwmmxt_wrwrwcg (str
)
6450 check_iwmmxt_insn (str
, check_wrwrwcg
, 0);
6454 do_iwmmxt_wrwrwr (str
)
6457 check_iwmmxt_insn (str
, check_wrwrwr
, 0);
6461 do_iwmmxt_wshufh (str
)
6464 unsigned long number
;
6466 if ((number
= check_iwmmxt_insn (str
, check_wshufh
, 0xff)) == (unsigned long) FAIL
)
6469 inst
.instruction
|= ((number
& 0xf0) << 16) | (number
& 0xf);
6473 do_iwmmxt_wzero (str
)
6476 if (check_iwmmxt_insn (str
, check_wr
, 0) == (unsigned long) FAIL
)
6479 inst
.instruction
|= ((inst
.instruction
& 0xf) << 12) | ((inst
.instruction
& 0xf) << 16);
6482 /* Xscale multiply-accumulate (argument parse)
6485 MIAxycc acc0,Rm,Rs. */
6494 if (accum0_required_here (& str
) == FAIL
)
6495 inst
.error
= ERR_NO_ACCUM
;
6497 else if (skip_past_comma (& str
) == FAIL
6498 || (rm
= reg_required_here (& str
, 0)) == FAIL
)
6499 inst
.error
= BAD_ARGS
;
6501 else if (skip_past_comma (& str
) == FAIL
6502 || (rs
= reg_required_here (& str
, 12)) == FAIL
)
6503 inst
.error
= BAD_ARGS
;
6505 /* inst.instruction has now been zapped with both rm and rs. */
6506 else if (rm
== REG_PC
|| rs
== REG_PC
)
6507 inst
.error
= BAD_PC
; /* Undefined result if rm or rs is R15. */
6513 /* Xscale move-accumulator-register (argument parse)
6515 MARcc acc0,RdLo,RdHi. */
6523 if (accum0_required_here (& str
) == FAIL
)
6524 inst
.error
= ERR_NO_ACCUM
;
6526 else if (skip_past_comma (& str
) == FAIL
6527 || (rdlo
= reg_required_here (& str
, 12)) == FAIL
)
6528 inst
.error
= BAD_ARGS
;
6530 else if (skip_past_comma (& str
) == FAIL
6531 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
6532 inst
.error
= BAD_ARGS
;
6534 /* inst.instruction has now been zapped with both rdlo and rdhi. */
6535 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
6536 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
6542 /* Xscale move-register-accumulator (argument parse)
6544 MRAcc RdLo,RdHi,acc0. */
6553 skip_whitespace (str
);
6555 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
)
6556 inst
.error
= BAD_ARGS
;
6558 else if (skip_past_comma (& str
) == FAIL
6559 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
6560 inst
.error
= BAD_ARGS
;
6562 else if (skip_past_comma (& str
) == FAIL
6563 || accum0_required_here (& str
) == FAIL
)
6564 inst
.error
= ERR_NO_ACCUM
;
6566 /* inst.instruction has now been zapped with both rdlo and rdhi. */
6567 else if (rdlo
== rdhi
)
6568 inst
.error
= BAD_ARGS
; /* Undefined result if 2 writes to same reg. */
6570 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
6571 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
6576 /* ARMv5TE: Preload-Cache
6580 Syntactically, like LDR with B=1, W=0, L=1. */
6588 skip_whitespace (str
);
6592 inst
.error
= _("'[' expected after PLD mnemonic");
6597 skip_whitespace (str
);
6599 if ((rd
= reg_required_here (& str
, 16)) == FAIL
)
6602 skip_whitespace (str
);
6608 skip_whitespace (str
);
6610 /* Post-indexed addressing is not allowed with PLD. */
6611 if (skip_past_comma (&str
) == SUCCESS
)
6614 = _("post-indexed expression used in preload instruction");
6617 else if (*str
== '!') /* [Rn]! */
6619 inst
.error
= _("writeback used in preload instruction");
6623 inst
.instruction
|= INDEX_UP
| PRE_INDEX
;
6625 else /* [Rn, ...] */
6627 if (skip_past_comma (& str
) == FAIL
)
6629 inst
.error
= _("pre-indexed expression expected");
6633 if (ldst_extend (&str
) == FAIL
)
6636 skip_whitespace (str
);
6640 inst
.error
= _("missing ]");
6645 skip_whitespace (str
);
6647 if (* str
== '!') /* [Rn]! */
6649 inst
.error
= _("writeback used in preload instruction");
6653 inst
.instruction
|= PRE_INDEX
;
6659 /* ARMv5TE load-consecutive (argument parse)
6672 skip_whitespace (str
);
6674 if ((rd
= reg_required_here (& str
, 12)) == FAIL
)
6676 inst
.error
= BAD_ARGS
;
6680 if (skip_past_comma (& str
) == FAIL
6681 || (rn
= ld_mode_required_here (& str
)) == FAIL
)
6684 inst
.error
= BAD_ARGS
;
6688 /* inst.instruction has now been zapped with Rd and the addressing mode. */
6689 if (rd
& 1) /* Unpredictable result if Rd is odd. */
6691 inst
.error
= _("destination register must be even");
6697 inst
.error
= _("r14 not allowed here");
6701 if (((rd
== rn
) || (rd
+ 1 == rn
))
6702 && ((inst
.instruction
& WRITE_BACK
)
6703 || (!(inst
.instruction
& PRE_INDEX
))))
6704 as_warn (_("pre/post-indexing used when modified address register is destination"));
6706 /* For an index-register load, the index register must not overlap the
6707 destination (even if not write-back). */
6708 if ((inst
.instruction
& V4_STR_BIT
) == 0
6709 && (inst
.instruction
& HWOFFSET_IMM
) == 0)
6711 int rm
= inst
.instruction
& 0x0000000f;
6713 if (rm
== rd
|| (rm
== rd
+ 1))
6714 as_warn (_("ldrd destination registers must not overlap index register"));
6720 /* Returns the index into fp_values of a floating point number,
6721 or -1 if not in the table. */
6724 my_get_float_expression (str
)
6727 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
6733 memset (words
, 0, MAX_LITTLENUMS
* sizeof (LITTLENUM_TYPE
));
6735 /* Look for a raw floating point number. */
6736 if ((save_in
= atof_ieee (*str
, 'x', words
)) != NULL
6737 && is_end_of_line
[(unsigned char) *save_in
])
6739 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
6741 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
6743 if (words
[j
] != fp_values
[i
][j
])
6747 if (j
== MAX_LITTLENUMS
)
6755 /* Try and parse a more complex expression, this will probably fail
6756 unless the code uses a floating point prefix (eg "0f"). */
6757 save_in
= input_line_pointer
;
6758 input_line_pointer
= *str
;
6759 if (expression (&exp
) == absolute_section
6760 && exp
.X_op
== O_big
6761 && exp
.X_add_number
< 0)
6763 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
6765 if (gen_to_words (words
, 5, (long) 15) == 0)
6767 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
6769 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
6771 if (words
[j
] != fp_values
[i
][j
])
6775 if (j
== MAX_LITTLENUMS
)
6777 *str
= input_line_pointer
;
6778 input_line_pointer
= save_in
;
6785 *str
= input_line_pointer
;
6786 input_line_pointer
= save_in
;
6790 /* Return TRUE if anything in the expression is a bignum. */
6793 walk_no_bignums (sp
)
6796 if (symbol_get_value_expression (sp
)->X_op
== O_big
)
6799 if (symbol_get_value_expression (sp
)->X_add_symbol
)
6801 return (walk_no_bignums (symbol_get_value_expression (sp
)->X_add_symbol
)
6802 || (symbol_get_value_expression (sp
)->X_op_symbol
6803 && walk_no_bignums (symbol_get_value_expression (sp
)->X_op_symbol
)));
6809 static int in_my_get_expression
= 0;
6812 my_get_expression (ep
, str
)
6819 save_in
= input_line_pointer
;
6820 input_line_pointer
= *str
;
6821 in_my_get_expression
= 1;
6822 seg
= expression (ep
);
6823 in_my_get_expression
= 0;
6825 if (ep
->X_op
== O_illegal
)
6827 /* We found a bad expression in md_operand(). */
6828 *str
= input_line_pointer
;
6829 input_line_pointer
= save_in
;
6834 if (seg
!= absolute_section
6835 && seg
!= text_section
6836 && seg
!= data_section
6837 && seg
!= bss_section
6838 && seg
!= undefined_section
)
6840 inst
.error
= _("bad_segment");
6841 *str
= input_line_pointer
;
6842 input_line_pointer
= save_in
;
6847 /* Get rid of any bignums now, so that we don't generate an error for which
6848 we can't establish a line number later on. Big numbers are never valid
6849 in instructions, which is where this routine is always called. */
6850 if (ep
->X_op
== O_big
6851 || (ep
->X_add_symbol
6852 && (walk_no_bignums (ep
->X_add_symbol
)
6854 && walk_no_bignums (ep
->X_op_symbol
)))))
6856 inst
.error
= _("invalid constant");
6857 *str
= input_line_pointer
;
6858 input_line_pointer
= save_in
;
6862 *str
= input_line_pointer
;
6863 input_line_pointer
= save_in
;
6867 /* We handle all bad expressions here, so that we can report the faulty
6868 instruction in the error message. */
6873 if (in_my_get_expression
)
6875 expr
->X_op
= O_illegal
;
6876 if (inst
.error
== NULL
)
6877 inst
.error
= _("bad expression");
6881 /* KIND indicates what kind of shifts are accepted. */
6884 decode_shift (str
, kind
)
6888 const struct asm_shift_name
* shift
;
6892 skip_whitespace (* str
);
6894 for (p
= * str
; ISALPHA (* p
); p
++)
6899 inst
.error
= _("shift expression expected");
6905 shift
= (const struct asm_shift_name
*) hash_find (arm_shift_hsh
, * str
);
6910 inst
.error
= _("shift expression expected");
6914 assert (shift
->properties
->index
== shift_properties
[shift
->properties
->index
].index
);
6916 if (kind
== SHIFT_LSL_OR_ASR_IMMEDIATE
6917 && shift
->properties
->index
!= SHIFT_LSL
6918 && shift
->properties
->index
!= SHIFT_ASR
)
6920 inst
.error
= _("'LSL' or 'ASR' required");
6923 else if (kind
== SHIFT_LSL_IMMEDIATE
6924 && shift
->properties
->index
!= SHIFT_LSL
)
6926 inst
.error
= _("'LSL' required");
6929 else if (kind
== SHIFT_ASR_IMMEDIATE
6930 && shift
->properties
->index
!= SHIFT_ASR
)
6932 inst
.error
= _("'ASR' required");
6936 if (shift
->properties
->index
== SHIFT_RRX
)
6939 inst
.instruction
|= shift
->properties
->bit_field
;
6943 skip_whitespace (p
);
6945 if (kind
== NO_SHIFT_RESTRICT
&& reg_required_here (& p
, 8) != FAIL
)
6947 inst
.instruction
|= shift
->properties
->bit_field
| SHIFT_BY_REG
;
6951 else if (! is_immediate_prefix (* p
))
6953 inst
.error
= (NO_SHIFT_RESTRICT
6954 ? _("shift requires register or #expression")
6955 : _("shift requires #expression"));
6963 if (my_get_expression (& inst
.reloc
.exp
, & p
))
6966 /* Validate some simple #expressions. */
6967 if (inst
.reloc
.exp
.X_op
== O_constant
)
6969 unsigned num
= inst
.reloc
.exp
.X_add_number
;
6971 /* Reject operations greater than 32. */
6973 /* Reject a shift of 0 unless the mode allows it. */
6974 || (num
== 0 && shift
->properties
->allows_0
== 0)
6975 /* Reject a shift of 32 unless the mode allows it. */
6976 || (num
== 32 && shift
->properties
->allows_32
== 0)
6979 /* As a special case we allow a shift of zero for
6980 modes that do not support it to be recoded as an
6981 logical shift left of zero (ie nothing). We warn
6982 about this though. */
6985 as_warn (_("shift of 0 ignored."));
6986 shift
= & shift_names
[0];
6987 assert (shift
->properties
->index
== SHIFT_LSL
);
6991 inst
.error
= _("invalid immediate shift");
6996 /* Shifts of 32 are encoded as 0, for those shifts that
7001 inst
.instruction
|= (num
<< 7) | shift
->properties
->bit_field
;
7005 inst
.reloc
.type
= BFD_RELOC_ARM_SHIFT_IMM
;
7006 inst
.reloc
.pc_rel
= 0;
7007 inst
.instruction
|= shift
->properties
->bit_field
;
7014 /* Do those data_ops which can take a negative immediate constant
7015 by altering the instruction. A bit of a hack really.
7019 by inverting the second operand, and
7022 by negating the second operand. */
7025 negate_data_op (instruction
, value
)
7026 unsigned long * instruction
;
7027 unsigned long value
;
7030 unsigned long negated
, inverted
;
7032 negated
= validate_immediate (-value
);
7033 inverted
= validate_immediate (~value
);
7035 op
= (*instruction
>> DATA_OP_SHIFT
) & 0xf;
7038 /* First negates. */
7039 case OPCODE_SUB
: /* ADD <-> SUB */
7040 new_inst
= OPCODE_ADD
;
7045 new_inst
= OPCODE_SUB
;
7049 case OPCODE_CMP
: /* CMP <-> CMN */
7050 new_inst
= OPCODE_CMN
;
7055 new_inst
= OPCODE_CMP
;
7059 /* Now Inverted ops. */
7060 case OPCODE_MOV
: /* MOV <-> MVN */
7061 new_inst
= OPCODE_MVN
;
7066 new_inst
= OPCODE_MOV
;
7070 case OPCODE_AND
: /* AND <-> BIC */
7071 new_inst
= OPCODE_BIC
;
7076 new_inst
= OPCODE_AND
;
7080 case OPCODE_ADC
: /* ADC <-> SBC */
7081 new_inst
= OPCODE_SBC
;
7086 new_inst
= OPCODE_ADC
;
7090 /* We cannot do anything. */
7095 if (value
== (unsigned) FAIL
)
7098 *instruction
&= OPCODE_MASK
;
7099 *instruction
|= new_inst
<< DATA_OP_SHIFT
;
7110 skip_whitespace (* str
);
7112 if (reg_required_here (str
, 0) != FAIL
)
7114 if (skip_past_comma (str
) == SUCCESS
)
7115 /* Shift operation on register. */
7116 return decode_shift (str
, NO_SHIFT_RESTRICT
);
7122 /* Immediate expression. */
7123 if (is_immediate_prefix (**str
))
7128 if (my_get_expression (&inst
.reloc
.exp
, str
))
7131 if (inst
.reloc
.exp
.X_add_symbol
)
7133 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
7134 inst
.reloc
.pc_rel
= 0;
7138 if (skip_past_comma (str
) == SUCCESS
)
7140 /* #x, y -- ie explicit rotation by Y. */
7141 if (my_get_expression (&expr
, str
))
7144 if (expr
.X_op
!= O_constant
)
7146 inst
.error
= _("constant expression expected");
7150 /* Rotate must be a multiple of 2. */
7151 if (((unsigned) expr
.X_add_number
) > 30
7152 || (expr
.X_add_number
& 1) != 0
7153 || ((unsigned) inst
.reloc
.exp
.X_add_number
) > 255)
7155 inst
.error
= _("invalid constant");
7158 inst
.instruction
|= INST_IMMEDIATE
;
7159 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
7160 inst
.instruction
|= expr
.X_add_number
<< 7;
7164 /* Implicit rotation, select a suitable one. */
7165 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
7169 /* Can't be done. Perhaps the code reads something like
7170 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
7171 if ((value
= negate_data_op (&inst
.instruction
,
7172 inst
.reloc
.exp
.X_add_number
))
7175 inst
.error
= _("invalid constant");
7180 inst
.instruction
|= value
;
7183 inst
.instruction
|= INST_IMMEDIATE
;
7188 inst
.error
= _("register or shift expression expected");
7197 skip_whitespace (* str
);
7199 if (fp_reg_required_here (str
, 0) != FAIL
)
7203 /* Immediate expression. */
7204 if (*((*str
)++) == '#')
7210 skip_whitespace (* str
);
7212 /* First try and match exact strings, this is to guarantee
7213 that some formats will work even for cross assembly. */
7215 for (i
= 0; fp_const
[i
]; i
++)
7217 if (strncmp (*str
, fp_const
[i
], strlen (fp_const
[i
])) == 0)
7221 *str
+= strlen (fp_const
[i
]);
7222 if (is_end_of_line
[(unsigned char) **str
])
7224 inst
.instruction
|= i
+ 8;
7231 /* Just because we didn't get a match doesn't mean that the
7232 constant isn't valid, just that it is in a format that we
7233 don't automatically recognize. Try parsing it with
7234 the standard expression routines. */
7235 if ((i
= my_get_float_expression (str
)) >= 0)
7237 inst
.instruction
|= i
+ 8;
7241 inst
.error
= _("invalid floating point immediate expression");
7245 _("floating point register or immediate expression expected");
7254 skip_whitespace (str
);
7256 if (reg_required_here (&str
, 12) == FAIL
7257 || skip_past_comma (&str
) == FAIL
7258 || reg_required_here (&str
, 16) == FAIL
7259 || skip_past_comma (&str
) == FAIL
7260 || data_op2 (&str
) == FAIL
)
7263 inst
.error
= BAD_ARGS
;
7274 /* This is a pseudo-op of the form "adr rd, label" to be converted
7275 into a relative address of the form "add rd, pc, #label-.-8". */
7276 skip_whitespace (str
);
7278 if (reg_required_here (&str
, 12) == FAIL
7279 || skip_past_comma (&str
) == FAIL
7280 || my_get_expression (&inst
.reloc
.exp
, &str
))
7283 inst
.error
= BAD_ARGS
;
7287 /* Frag hacking will turn this into a sub instruction if the offset turns
7288 out to be negative. */
7289 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
7290 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust. */
7291 inst
.reloc
.pc_rel
= 1;
7300 /* This is a pseudo-op of the form "adrl rd, label" to be converted
7301 into a relative address of the form:
7302 add rd, pc, #low(label-.-8)"
7303 add rd, rd, #high(label-.-8)" */
7305 skip_whitespace (str
);
7307 if (reg_required_here (&str
, 12) == FAIL
7308 || skip_past_comma (&str
) == FAIL
7309 || my_get_expression (&inst
.reloc
.exp
, &str
))
7312 inst
.error
= BAD_ARGS
;
7318 /* Frag hacking will turn this into a sub instruction if the offset turns
7319 out to be negative. */
7320 inst
.reloc
.type
= BFD_RELOC_ARM_ADRL_IMMEDIATE
;
7321 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust */
7322 inst
.reloc
.pc_rel
= 1;
7323 inst
.size
= INSN_SIZE
* 2;
7330 skip_whitespace (str
);
7332 if (reg_required_here (&str
, 16) == FAIL
)
7335 inst
.error
= BAD_ARGS
;
7339 if (skip_past_comma (&str
) == FAIL
7340 || data_op2 (&str
) == FAIL
)
7343 inst
.error
= BAD_ARGS
;
7354 skip_whitespace (str
);
7356 if (reg_required_here (&str
, 12) == FAIL
)
7359 inst
.error
= BAD_ARGS
;
7363 if (skip_past_comma (&str
) == FAIL
7364 || data_op2 (&str
) == FAIL
)
7367 inst
.error
= BAD_ARGS
;
7385 if (my_get_expression (& inst
.reloc
.exp
, str
))
7388 if (inst
.reloc
.exp
.X_op
== O_constant
)
7390 int value
= inst
.reloc
.exp
.X_add_number
;
7392 if (value
< -4095 || value
> 4095)
7394 inst
.error
= _("address offset too large");
7404 inst
.instruction
|= add
| value
;
7408 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
7409 inst
.reloc
.pc_rel
= 0;
7422 if (reg_required_here (str
, 0) == FAIL
)
7425 inst
.instruction
|= add
| OFFSET_REG
;
7426 if (skip_past_comma (str
) == SUCCESS
)
7427 return decode_shift (str
, SHIFT_IMMEDIATE
);
7441 skip_whitespace (str
);
7443 if ((conflict_reg
= reg_required_here (&str
, 12)) == FAIL
)
7446 inst
.error
= BAD_ARGS
;
7450 if (skip_past_comma (&str
) == FAIL
)
7452 inst
.error
= _("address expected");
7462 skip_whitespace (str
);
7464 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
7467 /* Conflicts can occur on stores as well as loads. */
7468 conflict_reg
= (conflict_reg
== reg
);
7470 skip_whitespace (str
);
7476 if (skip_past_comma (&str
) == SUCCESS
)
7478 /* [Rn],... (post inc) */
7479 if (ldst_extend (&str
) == FAIL
)
7482 as_warn (_("%s register same as write-back base"),
7483 ((inst
.instruction
& LOAD_BIT
)
7484 ? _("destination") : _("source")));
7489 skip_whitespace (str
);
7494 as_warn (_("%s register same as write-back base"),
7495 ((inst
.instruction
& LOAD_BIT
)
7496 ? _("destination") : _("source")));
7498 inst
.instruction
|= WRITE_BACK
;
7501 inst
.instruction
|= INDEX_UP
;
7508 if (skip_past_comma (&str
) == FAIL
)
7510 inst
.error
= _("pre-indexed expression expected");
7515 if (ldst_extend (&str
) == FAIL
)
7518 skip_whitespace (str
);
7522 inst
.error
= _("missing ]");
7526 skip_whitespace (str
);
7531 as_warn (_("%s register same as write-back base"),
7532 ((inst
.instruction
& LOAD_BIT
)
7533 ? _("destination") : _("source")));
7535 inst
.instruction
|= WRITE_BACK
;
7539 else if (*str
== '=')
7541 if ((inst
.instruction
& LOAD_BIT
) == 0)
7543 inst
.error
= _("invalid pseudo operation");
7547 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
7550 skip_whitespace (str
);
7552 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7555 if (inst
.reloc
.exp
.X_op
!= O_constant
7556 && inst
.reloc
.exp
.X_op
!= O_symbol
)
7558 inst
.error
= _("constant expression expected");
7562 if (inst
.reloc
.exp
.X_op
== O_constant
)
7564 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
7568 /* This can be done with a mov instruction. */
7569 inst
.instruction
&= LITERAL_MASK
;
7570 inst
.instruction
|= (INST_IMMEDIATE
7571 | (OPCODE_MOV
<< DATA_OP_SHIFT
));
7572 inst
.instruction
|= value
& 0xfff;
7577 value
= validate_immediate (~inst
.reloc
.exp
.X_add_number
);
7581 /* This can be done with a mvn instruction. */
7582 inst
.instruction
&= LITERAL_MASK
;
7583 inst
.instruction
|= (INST_IMMEDIATE
7584 | (OPCODE_MVN
<< DATA_OP_SHIFT
));
7585 inst
.instruction
|= value
& 0xfff;
7591 /* Insert into literal pool. */
7592 if (add_to_lit_pool () == FAIL
)
7595 inst
.error
= _("literal pool insertion failed");
7599 /* Change the instruction exp to point to the pool. */
7600 inst
.reloc
.type
= BFD_RELOC_ARM_LITERAL
;
7601 inst
.reloc
.pc_rel
= 1;
7602 inst
.instruction
|= (REG_PC
<< 16);
7607 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7610 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
7612 /* PC rel adjust. */
7613 inst
.reloc
.exp
.X_add_number
-= 8;
7615 inst
.reloc
.pc_rel
= 1;
7616 inst
.instruction
|= (REG_PC
<< 16);
7620 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
7630 skip_whitespace (str
);
7632 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
7635 inst
.error
= BAD_ARGS
;
7639 if (skip_past_comma (& str
) == FAIL
)
7641 inst
.error
= _("address expected");
7651 skip_whitespace (str
);
7653 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
7656 /* ldrt/strt always use post-indexed addressing, so if the base is
7657 the same as Rd, we warn. */
7658 if (conflict_reg
== reg
)
7659 as_warn (_("%s register same as write-back base"),
7660 ((inst
.instruction
& LOAD_BIT
)
7661 ? _("destination") : _("source")));
7663 skip_whitespace (str
);
7669 if (skip_past_comma (&str
) == SUCCESS
)
7671 /* [Rn],... (post inc) */
7672 if (ldst_extend (&str
) == FAIL
)
7678 skip_whitespace (str
);
7680 /* Skip a write-back '!'. */
7684 inst
.instruction
|= INDEX_UP
;
7689 inst
.error
= _("post-indexed expression expected");
7695 inst
.error
= _("post-indexed expression expected");
7703 ldst_extend_v4 (str
)
7713 if (my_get_expression (& inst
.reloc
.exp
, str
))
7716 if (inst
.reloc
.exp
.X_op
== O_constant
)
7718 int value
= inst
.reloc
.exp
.X_add_number
;
7720 if (value
< -255 || value
> 255)
7722 inst
.error
= _("address offset too large");
7732 /* Halfword and signextension instructions have the
7733 immediate value split across bits 11..8 and bits 3..0. */
7734 inst
.instruction
|= (add
| HWOFFSET_IMM
7735 | ((value
>> 4) << 8) | (value
& 0xF));
7739 inst
.instruction
|= HWOFFSET_IMM
;
7740 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
7741 inst
.reloc
.pc_rel
= 0;
7754 if (reg_required_here (str
, 0) == FAIL
)
7757 inst
.instruction
|= add
;
7762 /* Halfword and signed-byte load/store operations. */
7771 skip_whitespace (str
);
7773 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
7776 inst
.error
= BAD_ARGS
;
7780 if (skip_past_comma (& str
) == FAIL
)
7782 inst
.error
= _("address expected");
7792 skip_whitespace (str
);
7794 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
7797 /* Conflicts can occur on stores as well as loads. */
7798 conflict_reg
= (conflict_reg
== reg
);
7800 skip_whitespace (str
);
7806 if (skip_past_comma (&str
) == SUCCESS
)
7808 /* [Rn],... (post inc) */
7809 if (ldst_extend_v4 (&str
) == FAIL
)
7812 as_warn (_("%s register same as write-back base"),
7813 ((inst
.instruction
& LOAD_BIT
)
7814 ? _("destination") : _("source")));
7819 inst
.instruction
|= HWOFFSET_IMM
;
7821 skip_whitespace (str
);
7826 as_warn (_("%s register same as write-back base"),
7827 ((inst
.instruction
& LOAD_BIT
)
7828 ? _("destination") : _("source")));
7830 inst
.instruction
|= WRITE_BACK
;
7833 inst
.instruction
|= INDEX_UP
;
7840 if (skip_past_comma (&str
) == FAIL
)
7842 inst
.error
= _("pre-indexed expression expected");
7847 if (ldst_extend_v4 (&str
) == FAIL
)
7850 skip_whitespace (str
);
7854 inst
.error
= _("missing ]");
7858 skip_whitespace (str
);
7863 as_warn (_("%s register same as write-back base"),
7864 ((inst
.instruction
& LOAD_BIT
)
7865 ? _("destination") : _("source")));
7867 inst
.instruction
|= WRITE_BACK
;
7871 else if (*str
== '=')
7873 if ((inst
.instruction
& LOAD_BIT
) == 0)
7875 inst
.error
= _("invalid pseudo operation");
7879 /* XXX Does this work correctly for half-word/byte ops? */
7880 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
7883 skip_whitespace (str
);
7885 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7888 if (inst
.reloc
.exp
.X_op
!= O_constant
7889 && inst
.reloc
.exp
.X_op
!= O_symbol
)
7891 inst
.error
= _("constant expression expected");
7895 if (inst
.reloc
.exp
.X_op
== O_constant
)
7897 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
7901 /* This can be done with a mov instruction. */
7902 inst
.instruction
&= LITERAL_MASK
;
7903 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MOV
<< DATA_OP_SHIFT
);
7904 inst
.instruction
|= value
& 0xfff;
7909 value
= validate_immediate (~ inst
.reloc
.exp
.X_add_number
);
7913 /* This can be done with a mvn instruction. */
7914 inst
.instruction
&= LITERAL_MASK
;
7915 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MVN
<< DATA_OP_SHIFT
);
7916 inst
.instruction
|= value
& 0xfff;
7922 /* Insert into literal pool. */
7923 if (add_to_lit_pool () == FAIL
)
7926 inst
.error
= _("literal pool insertion failed");
7930 /* Change the instruction exp to point to the pool. */
7931 inst
.instruction
|= HWOFFSET_IMM
;
7932 inst
.reloc
.type
= BFD_RELOC_ARM_HWLITERAL
;
7933 inst
.reloc
.pc_rel
= 1;
7934 inst
.instruction
|= (REG_PC
<< 16);
7939 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7942 inst
.instruction
|= HWOFFSET_IMM
;
7943 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
7945 /* PC rel adjust. */
7946 inst
.reloc
.exp
.X_add_number
-= 8;
7948 inst
.reloc
.pc_rel
= 1;
7949 inst
.instruction
|= (REG_PC
<< 16);
7953 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
7961 char * str
= * strp
;
7965 /* We come back here if we get ranges concatenated by '+' or '|'. */
7980 skip_whitespace (str
);
7982 if ((reg
= reg_required_here (& str
, -1)) == FAIL
)
7991 inst
.error
= _("bad range in register list");
7995 for (i
= cur_reg
+ 1; i
< reg
; i
++)
7997 if (range
& (1 << i
))
7999 (_("Warning: duplicated register (r%d) in register list"),
8007 if (range
& (1 << reg
))
8008 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
8010 else if (reg
<= cur_reg
)
8011 as_tsktsk (_("Warning: register range not in ascending order"));
8016 while (skip_past_comma (&str
) != FAIL
8017 || (in_range
= 1, *str
++ == '-'));
8019 skip_whitespace (str
);
8023 inst
.error
= _("missing `}'");
8031 if (my_get_expression (&expr
, &str
))
8034 if (expr
.X_op
== O_constant
)
8036 if (expr
.X_add_number
8037 != (expr
.X_add_number
& 0x0000ffff))
8039 inst
.error
= _("invalid register mask");
8043 if ((range
& expr
.X_add_number
) != 0)
8045 int regno
= range
& expr
.X_add_number
;
8048 regno
= (1 << regno
) - 1;
8050 (_("Warning: duplicated register (r%d) in register list"),
8054 range
|= expr
.X_add_number
;
8058 if (inst
.reloc
.type
!= 0)
8060 inst
.error
= _("expression too complex");
8064 memcpy (&inst
.reloc
.exp
, &expr
, sizeof (expressionS
));
8065 inst
.reloc
.type
= BFD_RELOC_ARM_MULTI
;
8066 inst
.reloc
.pc_rel
= 0;
8070 skip_whitespace (str
);
8072 if (*str
== '|' || *str
== '+')
8078 while (another_range
);
8091 skip_whitespace (str
);
8093 if ((base_reg
= reg_required_here (&str
, 16)) == FAIL
)
8096 if (base_reg
== REG_PC
)
8098 inst
.error
= _("r15 not allowed as base register");
8102 skip_whitespace (str
);
8106 inst
.instruction
|= WRITE_BACK
;
8110 if (skip_past_comma (&str
) == FAIL
8111 || (range
= reg_list (&str
)) == FAIL
)
8114 inst
.error
= BAD_ARGS
;
8121 inst
.instruction
|= LDM_TYPE_2_OR_3
;
8124 if (inst
.instruction
& WRITE_BACK
)
8126 /* Check for unpredictable uses of writeback. */
8127 if (inst
.instruction
& LOAD_BIT
)
8129 /* Not allowed in LDM type 2. */
8130 if ((inst
.instruction
& LDM_TYPE_2_OR_3
)
8131 && ((range
& (1 << REG_PC
)) == 0))
8132 as_warn (_("writeback of base register is UNPREDICTABLE"));
8133 /* Only allowed if base reg not in list for other types. */
8134 else if (range
& (1 << base_reg
))
8135 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
8139 /* Not allowed for type 2. */
8140 if (inst
.instruction
& LDM_TYPE_2_OR_3
)
8141 as_warn (_("writeback of base register is UNPREDICTABLE"));
8142 /* Only allowed if base reg not in list, or first in list. */
8143 else if ((range
& (1 << base_reg
))
8144 && (range
& ((1 << base_reg
) - 1)))
8145 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
8149 inst
.instruction
|= range
;
8157 skip_whitespace (str
);
8159 /* Allow optional leading '#'. */
8160 if (is_immediate_prefix (*str
))
8163 if (my_get_expression (& inst
.reloc
.exp
, & str
))
8166 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
8167 inst
.reloc
.pc_rel
= 0;
8177 skip_whitespace (str
);
8179 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
8184 inst
.error
= _("r15 not allowed in swap");
8188 if (skip_past_comma (&str
) == FAIL
8189 || (reg
= reg_required_here (&str
, 0)) == FAIL
)
8192 inst
.error
= BAD_ARGS
;
8198 inst
.error
= _("r15 not allowed in swap");
8202 if (skip_past_comma (&str
) == FAIL
8205 inst
.error
= BAD_ARGS
;
8209 skip_whitespace (str
);
8211 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
8216 inst
.error
= BAD_PC
;
8220 skip_whitespace (str
);
8224 inst
.error
= _("missing ]");
8235 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8242 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
8243 required for the instruction. */
8245 /* arm_parse_reloc () works on input_line_pointer.
8246 We actually want to parse the operands to the branch instruction
8247 passed in 'str'. Save the input pointer and restore it later. */
8248 save_in
= input_line_pointer
;
8249 input_line_pointer
= str
;
8250 if (inst
.reloc
.exp
.X_op
== O_symbol
8252 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
8254 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
8255 inst
.reloc
.pc_rel
= 0;
8256 /* Modify str to point to after parsed operands, otherwise
8257 end_of_line() will complain about the (PLT) left in str. */
8258 str
= input_line_pointer
;
8262 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
8263 inst
.reloc
.pc_rel
= 1;
8265 input_line_pointer
= save_in
;
8268 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
8269 inst
.reloc
.pc_rel
= 1;
8270 #endif /* OBJ_ELF */
8281 skip_whitespace (str
);
8283 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
8285 inst
.error
= BAD_ARGS
;
8289 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
8291 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
8300 /* Co-processor data operation.
8301 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
8302 skip_whitespace (str
);
8304 if (co_proc_number (&str
) == FAIL
)
8307 inst
.error
= BAD_ARGS
;
8311 if (skip_past_comma (&str
) == FAIL
8312 || cp_opc_expr (&str
, 20,4) == FAIL
)
8315 inst
.error
= BAD_ARGS
;
8319 if (skip_past_comma (&str
) == FAIL
8320 || cp_reg_required_here (&str
, 12) == FAIL
)
8323 inst
.error
= BAD_ARGS
;
8327 if (skip_past_comma (&str
) == FAIL
8328 || cp_reg_required_here (&str
, 16) == FAIL
)
8331 inst
.error
= BAD_ARGS
;
8335 if (skip_past_comma (&str
) == FAIL
8336 || cp_reg_required_here (&str
, 0) == FAIL
)
8339 inst
.error
= BAD_ARGS
;
8343 if (skip_past_comma (&str
) == SUCCESS
)
8345 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
8348 inst
.error
= BAD_ARGS
;
8360 /* Co-processor register load/store.
8361 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
8363 skip_whitespace (str
);
8365 if (co_proc_number (&str
) == FAIL
)
8368 inst
.error
= BAD_ARGS
;
8372 if (skip_past_comma (&str
) == FAIL
8373 || cp_reg_required_here (&str
, 12) == FAIL
)
8376 inst
.error
= BAD_ARGS
;
8380 if (skip_past_comma (&str
) == FAIL
8381 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
8384 inst
.error
= BAD_ARGS
;
8395 /* Co-processor register transfer.
8396 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
8398 skip_whitespace (str
);
8400 if (co_proc_number (&str
) == FAIL
)
8403 inst
.error
= BAD_ARGS
;
8407 if (skip_past_comma (&str
) == FAIL
8408 || cp_opc_expr (&str
, 21, 3) == FAIL
)
8411 inst
.error
= BAD_ARGS
;
8415 if (skip_past_comma (&str
) == FAIL
8416 || reg_required_here (&str
, 12) == FAIL
)
8419 inst
.error
= BAD_ARGS
;
8423 if (skip_past_comma (&str
) == FAIL
8424 || cp_reg_required_here (&str
, 16) == FAIL
)
8427 inst
.error
= BAD_ARGS
;
8431 if (skip_past_comma (&str
) == FAIL
8432 || cp_reg_required_here (&str
, 0) == FAIL
)
8435 inst
.error
= BAD_ARGS
;
8439 if (skip_past_comma (&str
) == SUCCESS
)
8441 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
8444 inst
.error
= BAD_ARGS
;
8456 /* FP control registers.
8457 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
8459 skip_whitespace (str
);
8461 if (reg_required_here (&str
, 12) == FAIL
)
8464 inst
.error
= BAD_ARGS
;
8475 skip_whitespace (str
);
8477 if (fp_reg_required_here (&str
, 12) == FAIL
)
8480 inst
.error
= BAD_ARGS
;
8484 if (skip_past_comma (&str
) == FAIL
8485 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
8488 inst
.error
= BAD_ARGS
;
8501 skip_whitespace (str
);
8503 if (fp_reg_required_here (&str
, 12) == FAIL
)
8506 inst
.error
= BAD_ARGS
;
8510 /* Get Number of registers to transfer. */
8511 if (skip_past_comma (&str
) == FAIL
8512 || my_get_expression (&inst
.reloc
.exp
, &str
))
8515 inst
.error
= _("constant expression expected");
8519 if (inst
.reloc
.exp
.X_op
!= O_constant
)
8521 inst
.error
= _("constant value required for number of registers");
8525 num_regs
= inst
.reloc
.exp
.X_add_number
;
8527 if (num_regs
< 1 || num_regs
> 4)
8529 inst
.error
= _("number of registers must be in the range [1:4]");
8536 inst
.instruction
|= CP_T_X
;
8539 inst
.instruction
|= CP_T_Y
;
8542 inst
.instruction
|= CP_T_Y
| CP_T_X
;
8550 if (inst
.instruction
& (CP_T_Pre
| CP_T_UD
)) /* ea/fd format. */
8556 /* The instruction specified "ea" or "fd", so we can only accept
8557 [Rn]{!}. The instruction does not really support stacking or
8558 unstacking, so we have to emulate these by setting appropriate
8559 bits and offsets. */
8560 if (skip_past_comma (&str
) == FAIL
8564 inst
.error
= BAD_ARGS
;
8569 skip_whitespace (str
);
8571 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
8574 skip_whitespace (str
);
8578 inst
.error
= BAD_ARGS
;
8590 _("r15 not allowed as base register with write-back");
8597 if (inst
.instruction
& CP_T_Pre
)
8599 /* Pre-decrement. */
8600 offset
= 3 * num_regs
;
8602 inst
.instruction
|= CP_T_WB
;
8606 /* Post-increment. */
8609 inst
.instruction
|= CP_T_WB
;
8610 offset
= 3 * num_regs
;
8614 /* No write-back, so convert this into a standard pre-increment
8615 instruction -- aesthetically more pleasing. */
8616 inst
.instruction
|= CP_T_Pre
| CP_T_UD
;
8621 inst
.instruction
|= offset
;
8623 else if (skip_past_comma (&str
) == FAIL
8624 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
8627 inst
.error
= BAD_ARGS
;
8638 skip_whitespace (str
);
8640 if (fp_reg_required_here (&str
, 12) == FAIL
)
8643 inst
.error
= BAD_ARGS
;
8647 if (skip_past_comma (&str
) == FAIL
8648 || fp_reg_required_here (&str
, 16) == FAIL
)
8651 inst
.error
= BAD_ARGS
;
8655 if (skip_past_comma (&str
) == FAIL
8656 || fp_op2 (&str
) == FAIL
)
8659 inst
.error
= BAD_ARGS
;
8667 do_fpa_monadic (str
)
8670 skip_whitespace (str
);
8672 if (fp_reg_required_here (&str
, 12) == FAIL
)
8675 inst
.error
= BAD_ARGS
;
8679 if (skip_past_comma (&str
) == FAIL
8680 || fp_op2 (&str
) == FAIL
)
8683 inst
.error
= BAD_ARGS
;
8694 skip_whitespace (str
);
8696 if (fp_reg_required_here (&str
, 16) == FAIL
)
8699 inst
.error
= BAD_ARGS
;
8703 if (skip_past_comma (&str
) == FAIL
8704 || fp_op2 (&str
) == FAIL
)
8707 inst
.error
= BAD_ARGS
;
8715 do_fpa_from_reg (str
)
8718 skip_whitespace (str
);
8720 if (fp_reg_required_here (&str
, 16) == FAIL
)
8723 inst
.error
= BAD_ARGS
;
8727 if (skip_past_comma (&str
) == FAIL
8728 || reg_required_here (&str
, 12) == FAIL
)
8731 inst
.error
= BAD_ARGS
;
8742 skip_whitespace (str
);
8744 if (reg_required_here (&str
, 12) == FAIL
)
8747 if (skip_past_comma (&str
) == FAIL
8748 || fp_reg_required_here (&str
, 0) == FAIL
)
8751 inst
.error
= BAD_ARGS
;
8759 vfp_sp_reg_required_here (str
, pos
)
8761 enum vfp_sp_reg_pos pos
;
8766 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_SN
].htab
)) != FAIL
)
8771 inst
.instruction
|= ((reg
>> 1) << 12) | ((reg
& 1) << 22);
8775 inst
.instruction
|= ((reg
>> 1) << 16) | ((reg
& 1) << 7);
8779 inst
.instruction
|= ((reg
>> 1) << 0) | ((reg
& 1) << 5);
8788 /* In the few cases where we might be able to accept something else
8789 this error can be overridden. */
8790 inst
.error
= _(all_reg_maps
[REG_TYPE_SN
].expected
);
8792 /* Restore the start point. */
8798 vfp_dp_reg_required_here (str
, pos
)
8800 enum vfp_dp_reg_pos pos
;
8805 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_DN
].htab
)) != FAIL
)
8810 inst
.instruction
|= reg
<< 12;
8814 inst
.instruction
|= reg
<< 16;
8818 inst
.instruction
|= reg
<< 0;
8827 /* In the few cases where we might be able to accept something else
8828 this error can be overridden. */
8829 inst
.error
= _(all_reg_maps
[REG_TYPE_DN
].expected
);
8831 /* Restore the start point. */
8837 do_vfp_sp_monadic (str
)
8840 skip_whitespace (str
);
8842 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8845 if (skip_past_comma (&str
) == FAIL
8846 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
8849 inst
.error
= BAD_ARGS
;
8857 do_vfp_dp_monadic (str
)
8860 skip_whitespace (str
);
8862 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8865 if (skip_past_comma (&str
) == FAIL
8866 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
8869 inst
.error
= BAD_ARGS
;
8877 do_vfp_sp_dyadic (str
)
8880 skip_whitespace (str
);
8882 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8885 if (skip_past_comma (&str
) == FAIL
8886 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
8887 || skip_past_comma (&str
) == FAIL
8888 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
8891 inst
.error
= BAD_ARGS
;
8899 do_vfp_dp_dyadic (str
)
8902 skip_whitespace (str
);
8904 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8907 if (skip_past_comma (&str
) == FAIL
8908 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
8909 || skip_past_comma (&str
) == FAIL
8910 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
8913 inst
.error
= BAD_ARGS
;
8921 do_vfp_reg_from_sp (str
)
8924 skip_whitespace (str
);
8926 if (reg_required_here (&str
, 12) == FAIL
)
8929 if (skip_past_comma (&str
) == FAIL
8930 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
8933 inst
.error
= BAD_ARGS
;
8941 do_vfp_sp_reg2 (str
)
8944 skip_whitespace (str
);
8946 if (reg_required_here (&str
, 12) == FAIL
)
8949 if (skip_past_comma (&str
) == FAIL
8950 || reg_required_here (&str
, 16) == FAIL
8951 || skip_past_comma (&str
) == FAIL
)
8954 inst
.error
= BAD_ARGS
;
8958 /* We require exactly two consecutive SP registers. */
8959 if (vfp_sp_reg_list (&str
, VFP_REG_Sm
) != 2)
8962 inst
.error
= _("only two consecutive VFP SP registers allowed here");
8969 do_vfp_sp_from_reg (str
)
8972 skip_whitespace (str
);
8974 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
8977 if (skip_past_comma (&str
) == FAIL
8978 || reg_required_here (&str
, 12) == FAIL
)
8981 inst
.error
= BAD_ARGS
;
8989 do_vfp_reg_from_dp (str
)
8992 skip_whitespace (str
);
8994 if (reg_required_here (&str
, 12) == FAIL
)
8997 if (skip_past_comma (&str
) == FAIL
8998 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
9001 inst
.error
= BAD_ARGS
;
9009 do_vfp_reg2_from_dp (str
)
9012 skip_whitespace (str
);
9014 if (reg_required_here (&str
, 12) == FAIL
)
9017 if (skip_past_comma (&str
) == FAIL
9018 || reg_required_here (&str
, 16) == FAIL
9019 || skip_past_comma (&str
) == FAIL
9020 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
9023 inst
.error
= BAD_ARGS
;
9031 do_vfp_dp_from_reg (str
)
9034 skip_whitespace (str
);
9036 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
9039 if (skip_past_comma (&str
) == FAIL
9040 || reg_required_here (&str
, 12) == FAIL
)
9043 inst
.error
= BAD_ARGS
;
9051 do_vfp_dp_from_reg2 (str
)
9054 skip_whitespace (str
);
9056 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
9059 if (skip_past_comma (&str
) == FAIL
9060 || reg_required_here (&str
, 12) == FAIL
9061 || skip_past_comma (&str
) == FAIL
9062 || reg_required_here (&str
, 16))
9065 inst
.error
= BAD_ARGS
;
9072 static const struct vfp_reg
*
9079 const struct vfp_reg
*vreg
;
9083 /* Find the end of the current token. */
9088 while (ISALPHA (c
));
9093 for (vreg
= vfp_regs
+ 0;
9094 vreg
< vfp_regs
+ sizeof (vfp_regs
) / sizeof (struct vfp_reg
);
9097 if (strcmp (start
, vreg
->name
) == 0)
9110 vfp_psr_required_here (str
)
9114 const struct vfp_reg
*vreg
;
9116 vreg
= vfp_psr_parse (str
);
9120 inst
.instruction
|= vreg
->regno
;
9124 inst
.error
= _("VFP system register expected");
9131 do_vfp_reg_from_ctrl (str
)
9134 skip_whitespace (str
);
9136 if (reg_required_here (&str
, 12) == FAIL
)
9139 if (skip_past_comma (&str
) == FAIL
9140 || vfp_psr_required_here (&str
) == FAIL
)
9143 inst
.error
= BAD_ARGS
;
9151 do_vfp_ctrl_from_reg (str
)
9154 skip_whitespace (str
);
9156 if (vfp_psr_required_here (&str
) == FAIL
)
9159 if (skip_past_comma (&str
) == FAIL
9160 || reg_required_here (&str
, 12) == FAIL
)
9163 inst
.error
= BAD_ARGS
;
9171 do_vfp_sp_ldst (str
)
9174 skip_whitespace (str
);
9176 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
9179 inst
.error
= BAD_ARGS
;
9183 if (skip_past_comma (&str
) == FAIL
9184 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
9187 inst
.error
= BAD_ARGS
;
9195 do_vfp_dp_ldst (str
)
9198 skip_whitespace (str
);
9200 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
9203 inst
.error
= BAD_ARGS
;
9207 if (skip_past_comma (&str
) == FAIL
9208 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
9211 inst
.error
= BAD_ARGS
;
9218 /* Parse and encode a VFP SP register list, storing the initial
9219 register in position POS and returning the range as the result. If
9220 the string is invalid return FAIL (an invalid range). */
9222 vfp_sp_reg_list (str
, pos
)
9224 enum vfp_sp_reg_pos pos
;
9232 unsigned long mask
= 0;
9239 skip_whitespace (*str
);
9241 tempinst
= inst
.instruction
;
9245 inst
.instruction
= 0;
9247 if ((new_base
= vfp_sp_reg_required_here (str
, pos
)) == FAIL
)
9250 if (count
== 0 || base_reg
> new_base
)
9252 base_reg
= new_base
;
9253 base_bits
= inst
.instruction
;
9256 if (mask
& (1 << new_base
))
9258 inst
.error
= _("invalid register list");
9262 if ((mask
>> new_base
) != 0 && ! warned
)
9264 as_tsktsk (_("register list not in ascending order"));
9268 mask
|= 1 << new_base
;
9271 skip_whitespace (*str
);
9273 if (**str
== '-') /* We have the start of a range expression */
9280 = arm_reg_parse (str
, all_reg_maps
[REG_TYPE_SN
].htab
))
9283 inst
.error
= _(all_reg_maps
[REG_TYPE_SN
].expected
);
9287 if (high_range
<= new_base
)
9289 inst
.error
= _("register range not in ascending order");
9293 for (new_base
++; new_base
<= high_range
; new_base
++)
9295 if (mask
& (1 << new_base
))
9297 inst
.error
= _("invalid register list");
9301 mask
|= 1 << new_base
;
9306 while (skip_past_comma (str
) != FAIL
);
9310 inst
.error
= _("invalid register list");
9318 /* Sanity check -- should have raised a parse error above. */
9319 if (count
== 0 || count
> 32)
9322 /* Final test -- the registers must be consecutive. */
9325 if ((mask
& (1 << base_reg
++)) == 0)
9327 inst
.error
= _("non-contiguous register range");
9332 inst
.instruction
= tempinst
| base_bits
;
9337 vfp_dp_reg_list (str
)
9345 unsigned long mask
= 0;
9352 skip_whitespace (*str
);
9354 tempinst
= inst
.instruction
;
9358 inst
.instruction
= 0;
9360 if ((new_base
= vfp_dp_reg_required_here (str
, VFP_REG_Dd
)) == FAIL
)
9363 if (count
== 0 || base_reg
> new_base
)
9365 base_reg
= new_base
;
9366 range
= inst
.instruction
;
9369 if (mask
& (1 << new_base
))
9371 inst
.error
= _("invalid register list");
9375 if ((mask
>> new_base
) != 0 && ! warned
)
9377 as_tsktsk (_("register list not in ascending order"));
9381 mask
|= 1 << new_base
;
9384 skip_whitespace (*str
);
9386 if (**str
== '-') /* We have the start of a range expression */
9393 = arm_reg_parse (str
, all_reg_maps
[REG_TYPE_DN
].htab
))
9396 inst
.error
= _(all_reg_maps
[REG_TYPE_DN
].expected
);
9400 if (high_range
<= new_base
)
9402 inst
.error
= _("register range not in ascending order");
9406 for (new_base
++; new_base
<= high_range
; new_base
++)
9408 if (mask
& (1 << new_base
))
9410 inst
.error
= _("invalid register list");
9414 mask
|= 1 << new_base
;
9419 while (skip_past_comma (str
) != FAIL
);
9423 inst
.error
= _("invalid register list");
9431 /* Sanity check -- should have raised a parse error above. */
9432 if (count
== 0 || count
> 16)
9435 /* Final test -- the registers must be consecutive. */
9438 if ((mask
& (1 << base_reg
++)) == 0)
9440 inst
.error
= _("non-contiguous register range");
9445 inst
.instruction
= tempinst
;
9450 vfp_sp_ldstm (str
, ldstm_type
)
9452 enum vfp_ldstm_type ldstm_type
;
9456 skip_whitespace (str
);
9458 if (reg_required_here (&str
, 16) == FAIL
)
9461 skip_whitespace (str
);
9465 inst
.instruction
|= WRITE_BACK
;
9468 else if (ldstm_type
!= VFP_LDSTMIA
)
9470 inst
.error
= _("this addressing mode requires base-register writeback");
9474 if (skip_past_comma (&str
) == FAIL
9475 || (range
= vfp_sp_reg_list (&str
, VFP_REG_Sd
)) == FAIL
)
9478 inst
.error
= BAD_ARGS
;
9482 inst
.instruction
|= range
;
9487 vfp_dp_ldstm (str
, ldstm_type
)
9489 enum vfp_ldstm_type ldstm_type
;
9493 skip_whitespace (str
);
9495 if (reg_required_here (&str
, 16) == FAIL
)
9498 skip_whitespace (str
);
9502 inst
.instruction
|= WRITE_BACK
;
9505 else if (ldstm_type
!= VFP_LDSTMIA
&& ldstm_type
!= VFP_LDSTMIAX
)
9507 inst
.error
= _("this addressing mode requires base-register writeback");
9511 if (skip_past_comma (&str
) == FAIL
9512 || (range
= vfp_dp_reg_list (&str
)) == FAIL
)
9515 inst
.error
= BAD_ARGS
;
9519 if (ldstm_type
== VFP_LDSTMIAX
|| ldstm_type
== VFP_LDSTMDBX
)
9522 inst
.instruction
|= range
;
9527 do_vfp_sp_ldstmia (str
)
9530 vfp_sp_ldstm (str
, VFP_LDSTMIA
);
9534 do_vfp_sp_ldstmdb (str
)
9537 vfp_sp_ldstm (str
, VFP_LDSTMDB
);
9541 do_vfp_dp_ldstmia (str
)
9544 vfp_dp_ldstm (str
, VFP_LDSTMIA
);
9548 do_vfp_dp_ldstmdb (str
)
9551 vfp_dp_ldstm (str
, VFP_LDSTMDB
);
9555 do_vfp_xp_ldstmia (str
)
9558 vfp_dp_ldstm (str
, VFP_LDSTMIAX
);
9562 do_vfp_xp_ldstmdb (str
)
9565 vfp_dp_ldstm (str
, VFP_LDSTMDBX
);
9569 do_vfp_sp_compare_z (str
)
9572 skip_whitespace (str
);
9574 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
9577 inst
.error
= BAD_ARGS
;
9585 do_vfp_dp_compare_z (str
)
9588 skip_whitespace (str
);
9590 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
9593 inst
.error
= BAD_ARGS
;
9601 do_vfp_dp_sp_cvt (str
)
9604 skip_whitespace (str
);
9606 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
9609 if (skip_past_comma (&str
) == FAIL
9610 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
9613 inst
.error
= BAD_ARGS
;
9621 do_vfp_sp_dp_cvt (str
)
9624 skip_whitespace (str
);
9626 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
9629 if (skip_past_comma (&str
) == FAIL
9630 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
9633 inst
.error
= BAD_ARGS
;
9640 /* Thumb specific routines. */
9642 /* Parse and validate that a register is of the right form, this saves
9643 repeated checking of this information in many similar cases.
9644 Unlike the 32-bit case we do not insert the register into the opcode
9645 here, since the position is often unknown until the full instruction
9649 thumb_reg (strp
, hi_lo
)
9655 if ((reg
= reg_required_here (strp
, -1)) == FAIL
)
9663 inst
.error
= _("lo register required");
9671 inst
.error
= _("hi register required");
9683 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
9687 thumb_add_sub (str
, subtract
)
9691 int Rd
, Rs
, Rn
= FAIL
;
9693 skip_whitespace (str
);
9695 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
9696 || skip_past_comma (&str
) == FAIL
)
9699 inst
.error
= BAD_ARGS
;
9703 if (is_immediate_prefix (*str
))
9707 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9712 if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
9715 if (skip_past_comma (&str
) == FAIL
)
9717 /* Two operand format, shuffle the registers
9718 and pretend there are 3. */
9722 else if (is_immediate_prefix (*str
))
9725 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9728 else if ((Rn
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
9732 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
9733 for the latter case, EXPR contains the immediate that was found. */
9736 /* All register format. */
9737 if (Rd
> 7 || Rs
> 7 || Rn
> 7)
9741 inst
.error
= _("dest and source1 must be the same register");
9745 /* Can't do this for SUB. */
9748 inst
.error
= _("subtract valid only on lo regs");
9752 inst
.instruction
= (T_OPCODE_ADD_HI
9753 | (Rd
> 7 ? THUMB_H1
: 0)
9754 | (Rn
> 7 ? THUMB_H2
: 0));
9755 inst
.instruction
|= (Rd
& 7) | ((Rn
& 7) << 3);
9759 inst
.instruction
= subtract
? T_OPCODE_SUB_R3
: T_OPCODE_ADD_R3
;
9760 inst
.instruction
|= Rd
| (Rs
<< 3) | (Rn
<< 6);
9765 /* Immediate expression, now things start to get nasty. */
9767 /* First deal with HI regs, only very restricted cases allowed:
9768 Adjusting SP, and using PC or SP to get an address. */
9769 if ((Rd
> 7 && (Rd
!= REG_SP
|| Rs
!= REG_SP
))
9770 || (Rs
> 7 && Rs
!= REG_SP
&& Rs
!= REG_PC
))
9772 inst
.error
= _("invalid Hi register with immediate");
9776 if (inst
.reloc
.exp
.X_op
!= O_constant
)
9778 /* Value isn't known yet, all we can do is store all the fragments
9779 we know about in the instruction and let the reloc hacking
9781 inst
.instruction
= (subtract
? 0x8000 : 0) | (Rd
<< 4) | Rs
;
9782 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
9786 int offset
= inst
.reloc
.exp
.X_add_number
;
9796 /* Quick check, in case offset is MIN_INT. */
9799 inst
.error
= _("immediate value out of range");
9803 /* Note - you cannot convert a subtract of 0 into an
9804 add of 0 because the carry flag is set differently. */
9805 else if (offset
> 0)
9810 if (offset
& ~0x1fc)
9812 inst
.error
= _("invalid immediate value for stack adjust");
9815 inst
.instruction
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
9816 inst
.instruction
|= offset
>> 2;
9818 else if (Rs
== REG_PC
|| Rs
== REG_SP
)
9821 || (offset
& ~0x3fc))
9823 inst
.error
= _("invalid immediate for address calculation");
9826 inst
.instruction
= (Rs
== REG_PC
? T_OPCODE_ADD_PC
9828 inst
.instruction
|= (Rd
<< 8) | (offset
>> 2);
9834 inst
.error
= _("immediate value out of range");
9837 inst
.instruction
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
9838 inst
.instruction
|= (Rd
<< 8) | offset
;
9844 inst
.error
= _("immediate value out of range");
9847 inst
.instruction
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
9848 inst
.instruction
|= Rd
| (Rs
<< 3) | (offset
<< 6);
9857 thumb_shift (str
, shift
)
9861 int Rd
, Rs
, Rn
= FAIL
;
9863 skip_whitespace (str
);
9865 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9866 || skip_past_comma (&str
) == FAIL
)
9869 inst
.error
= BAD_ARGS
;
9873 if (is_immediate_prefix (*str
))
9875 /* Two operand immediate format, set Rs to Rd. */
9878 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9883 if ((Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9886 if (skip_past_comma (&str
) == FAIL
)
9888 /* Two operand format, shuffle the registers
9889 and pretend there are 3. */
9893 else if (is_immediate_prefix (*str
))
9896 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9899 else if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9903 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
9904 for the latter case, EXPR contains the immediate that was found. */
9910 inst
.error
= _("source1 and dest must be same register");
9916 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_R
; break;
9917 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_R
; break;
9918 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_R
; break;
9921 inst
.instruction
|= Rd
| (Rn
<< 3);
9927 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_I
; break;
9928 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_I
; break;
9929 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_I
; break;
9932 if (inst
.reloc
.exp
.X_op
!= O_constant
)
9934 /* Value isn't known yet, create a dummy reloc and let reloc
9935 hacking fix it up. */
9936 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_SHIFT
;
9940 unsigned shift_value
= inst
.reloc
.exp
.X_add_number
;
9942 if (shift_value
> 32 || (shift_value
== 32 && shift
== THUMB_LSL
))
9944 inst
.error
= _("invalid immediate for shift");
9948 /* Shifts of zero are handled by converting to LSL. */
9949 if (shift_value
== 0)
9950 inst
.instruction
= T_OPCODE_LSL_I
;
9952 /* Shifts of 32 are encoded as a shift of zero. */
9953 if (shift_value
== 32)
9956 inst
.instruction
|= shift_value
<< 6;
9959 inst
.instruction
|= Rd
| (Rs
<< 3);
9966 thumb_mov_compare (str
, move
)
9972 skip_whitespace (str
);
9974 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
9975 || skip_past_comma (&str
) == FAIL
)
9978 inst
.error
= BAD_ARGS
;
9982 if (move
!= THUMB_CPY
&& is_immediate_prefix (*str
))
9985 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9988 else if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
9993 if (move
!= THUMB_CPY
&& Rs
< 8 && Rd
< 8)
9995 if (move
== THUMB_MOVE
)
9996 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
9997 since a MOV instruction produces unpredictable results. */
9998 inst
.instruction
= T_OPCODE_ADD_I3
;
10000 inst
.instruction
= T_OPCODE_CMP_LR
;
10001 inst
.instruction
|= Rd
| (Rs
<< 3);
10005 if (move
== THUMB_MOVE
)
10006 inst
.instruction
= T_OPCODE_MOV_HR
;
10007 else if (move
!= THUMB_CPY
)
10008 inst
.instruction
= T_OPCODE_CMP_HR
;
10011 inst
.instruction
|= THUMB_H1
;
10014 inst
.instruction
|= THUMB_H2
;
10016 inst
.instruction
|= (Rd
& 7) | ((Rs
& 7) << 3);
10023 inst
.error
= _("only lo regs allowed with immediate");
10027 if (move
== THUMB_MOVE
)
10028 inst
.instruction
= T_OPCODE_MOV_I8
;
10030 inst
.instruction
= T_OPCODE_CMP_I8
;
10032 inst
.instruction
|= Rd
<< 8;
10034 if (inst
.reloc
.exp
.X_op
!= O_constant
)
10035 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_IMM
;
10038 unsigned value
= inst
.reloc
.exp
.X_add_number
;
10042 inst
.error
= _("invalid immediate");
10046 inst
.instruction
|= value
;
10054 thumb_load_store (str
, load_store
, size
)
10059 int Rd
, Rb
, Ro
= FAIL
;
10061 skip_whitespace (str
);
10063 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
10064 || skip_past_comma (&str
) == FAIL
)
10067 inst
.error
= BAD_ARGS
;
10074 if ((Rb
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
10077 if (skip_past_comma (&str
) != FAIL
)
10079 if (is_immediate_prefix (*str
))
10082 if (my_get_expression (&inst
.reloc
.exp
, &str
))
10085 else if ((Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
10090 inst
.reloc
.exp
.X_op
= O_constant
;
10091 inst
.reloc
.exp
.X_add_number
= 0;
10096 inst
.error
= _("expected ']'");
10101 else if (*str
== '=')
10103 if (load_store
!= THUMB_LOAD
)
10105 inst
.error
= _("invalid pseudo operation");
10109 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
10112 skip_whitespace (str
);
10114 if (my_get_expression (& inst
.reloc
.exp
, & str
))
10119 if ( inst
.reloc
.exp
.X_op
!= O_constant
10120 && inst
.reloc
.exp
.X_op
!= O_symbol
)
10122 inst
.error
= "Constant expression expected";
10126 if (inst
.reloc
.exp
.X_op
== O_constant
10127 && ((inst
.reloc
.exp
.X_add_number
& ~0xFF) == 0))
10129 /* This can be done with a mov instruction. */
10131 inst
.instruction
= T_OPCODE_MOV_I8
| (Rd
<< 8);
10132 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
10136 /* Insert into literal pool. */
10137 if (add_to_lit_pool () == FAIL
)
10140 inst
.error
= "literal pool insertion failed";
10144 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
10145 inst
.reloc
.pc_rel
= 1;
10146 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
10147 /* Adjust ARM pipeline offset to Thumb. */
10148 inst
.reloc
.exp
.X_add_number
+= 4;
10154 if (my_get_expression (&inst
.reloc
.exp
, &str
))
10157 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
10158 inst
.reloc
.pc_rel
= 1;
10159 inst
.reloc
.exp
.X_add_number
-= 4; /* Pipeline offset. */
10160 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
10165 if (Rb
== REG_PC
|| Rb
== REG_SP
)
10167 if (size
!= THUMB_WORD
)
10169 inst
.error
= _("byte or halfword not valid for base register");
10172 else if (Rb
== REG_PC
&& load_store
!= THUMB_LOAD
)
10174 inst
.error
= _("r15 based store not allowed");
10177 else if (Ro
!= FAIL
)
10179 inst
.error
= _("invalid base register for register offset");
10184 inst
.instruction
= T_OPCODE_LDR_PC
;
10185 else if (load_store
== THUMB_LOAD
)
10186 inst
.instruction
= T_OPCODE_LDR_SP
;
10188 inst
.instruction
= T_OPCODE_STR_SP
;
10190 inst
.instruction
|= Rd
<< 8;
10191 if (inst
.reloc
.exp
.X_op
== O_constant
)
10193 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
10195 if (offset
& ~0x3fc)
10197 inst
.error
= _("invalid offset");
10201 inst
.instruction
|= offset
>> 2;
10204 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
10208 inst
.error
= _("invalid base register in load/store");
10211 else if (Ro
== FAIL
)
10213 /* Immediate offset. */
10214 if (size
== THUMB_WORD
)
10215 inst
.instruction
= (load_store
== THUMB_LOAD
10216 ? T_OPCODE_LDR_IW
: T_OPCODE_STR_IW
);
10217 else if (size
== THUMB_HALFWORD
)
10218 inst
.instruction
= (load_store
== THUMB_LOAD
10219 ? T_OPCODE_LDR_IH
: T_OPCODE_STR_IH
);
10221 inst
.instruction
= (load_store
== THUMB_LOAD
10222 ? T_OPCODE_LDR_IB
: T_OPCODE_STR_IB
);
10224 inst
.instruction
|= Rd
| (Rb
<< 3);
10226 if (inst
.reloc
.exp
.X_op
== O_constant
)
10228 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
10230 if (offset
& ~(0x1f << size
))
10232 inst
.error
= _("invalid offset");
10235 inst
.instruction
|= (offset
>> size
) << 6;
10238 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
10242 /* Register offset. */
10243 if (size
== THUMB_WORD
)
10244 inst
.instruction
= (load_store
== THUMB_LOAD
10245 ? T_OPCODE_LDR_RW
: T_OPCODE_STR_RW
);
10246 else if (size
== THUMB_HALFWORD
)
10247 inst
.instruction
= (load_store
== THUMB_LOAD
10248 ? T_OPCODE_LDR_RH
: T_OPCODE_STR_RH
);
10250 inst
.instruction
= (load_store
== THUMB_LOAD
10251 ? T_OPCODE_LDR_RB
: T_OPCODE_STR_RB
);
10253 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
10259 /* A register must be given at this point.
10261 Shift is the place to put it in inst.instruction.
10263 Restores input start point on err.
10264 Returns the reg#, or FAIL. */
10267 mav_reg_required_here (str
, shift
, regtype
)
10270 enum arm_reg_type regtype
;
10273 char *start
= *str
;
10275 if ((reg
= arm_reg_parse (str
, all_reg_maps
[regtype
].htab
)) != FAIL
)
10278 inst
.instruction
|= reg
<< shift
;
10283 /* Restore the start point. */
10286 /* In the few cases where we might be able to accept something else
10287 this error can be overridden. */
10288 inst
.error
= _(all_reg_maps
[regtype
].expected
);
10293 /* Cirrus Maverick Instructions. */
10295 /* Wrapper functions. */
10298 do_mav_binops_1a (str
)
10301 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVF
);
10305 do_mav_binops_1b (str
)
10308 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVD
);
10312 do_mav_binops_1c (str
)
10315 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVDX
);
10319 do_mav_binops_1d (str
)
10322 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVF
);
10326 do_mav_binops_1e (str
)
10329 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVD
);
10333 do_mav_binops_1f (str
)
10336 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVF
);
10340 do_mav_binops_1g (str
)
10343 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVD
);
10347 do_mav_binops_1h (str
)
10350 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVFX
);
10354 do_mav_binops_1i (str
)
10357 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVFX
);
10361 do_mav_binops_1j (str
)
10364 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVDX
);
10368 do_mav_binops_1k (str
)
10371 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVDX
);
10375 do_mav_binops_1l (str
)
10378 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVF
);
10382 do_mav_binops_1m (str
)
10385 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVD
);
10389 do_mav_binops_1n (str
)
10392 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
10396 do_mav_binops_1o (str
)
10399 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
10403 do_mav_binops_2a (str
)
10406 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVF
, REG_TYPE_RN
);
10410 do_mav_binops_2b (str
)
10413 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVD
, REG_TYPE_RN
);
10417 do_mav_binops_2c (str
)
10420 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVDX
, REG_TYPE_RN
);
10424 do_mav_binops_3a (str
)
10427 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVFX
);
10431 do_mav_binops_3b (str
)
10434 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVFX
, REG_TYPE_MVAX
);
10438 do_mav_binops_3c (str
)
10441 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVDX
);
10445 do_mav_binops_3d (str
)
10448 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVDX
, REG_TYPE_MVAX
);
10452 do_mav_triple_4a (str
)
10455 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_RN
);
10459 do_mav_triple_4b (str
)
10462 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_RN
);
10466 do_mav_triple_5a (str
)
10469 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVF
, REG_TYPE_MVF
);
10473 do_mav_triple_5b (str
)
10476 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVD
, REG_TYPE_MVD
);
10480 do_mav_triple_5c (str
)
10483 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
10487 do_mav_triple_5d (str
)
10490 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
10494 do_mav_triple_5e (str
)
10497 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVF
, REG_TYPE_MVF
, REG_TYPE_MVF
);
10501 do_mav_triple_5f (str
)
10504 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVD
, REG_TYPE_MVD
, REG_TYPE_MVD
);
10508 do_mav_triple_5g (str
)
10511 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
10515 do_mav_triple_5h (str
)
10518 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
10522 do_mav_quad_6a (str
)
10525 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
,
10530 do_mav_quad_6b (str
)
10533 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVAX
, REG_TYPE_MVFX
,
10537 /* cfmvsc32<cond> DSPSC,MVFX[15:0]. */
10539 do_mav_dspsc_1 (str
)
10542 skip_whitespace (str
);
10545 if (mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
10546 || skip_past_comma (&str
) == FAIL
10547 || mav_reg_required_here (&str
, 16, REG_TYPE_MVFX
) == FAIL
)
10550 inst
.error
= BAD_ARGS
;
10558 /* cfmv32sc<cond> MVFX[15:0],DSPSC. */
10560 do_mav_dspsc_2 (str
)
10563 skip_whitespace (str
);
10566 if (mav_reg_required_here (&str
, 0, REG_TYPE_MVFX
) == FAIL
10567 || skip_past_comma (&str
) == FAIL
10568 || mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
)
10571 inst
.error
= BAD_ARGS
;
10580 do_mav_shift_1 (str
)
10583 do_mav_shift (str
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
10587 do_mav_shift_2 (str
)
10590 do_mav_shift (str
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
10594 do_mav_ldst_1 (str
)
10597 do_mav_ldst (str
, REG_TYPE_MVF
);
10601 do_mav_ldst_2 (str
)
10604 do_mav_ldst (str
, REG_TYPE_MVD
);
10608 do_mav_ldst_3 (str
)
10611 do_mav_ldst (str
, REG_TYPE_MVFX
);
10615 do_mav_ldst_4 (str
)
10618 do_mav_ldst (str
, REG_TYPE_MVDX
);
10621 /* Isnsn like "foo X,Y". */
10624 do_mav_binops (str
, mode
, reg0
, reg1
)
10627 enum arm_reg_type reg0
;
10628 enum arm_reg_type reg1
;
10630 int shift0
, shift1
;
10632 shift0
= mode
& 0xff;
10633 shift1
= (mode
>> 8) & 0xff;
10635 skip_whitespace (str
);
10637 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
10638 || skip_past_comma (&str
) == FAIL
10639 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
)
10642 inst
.error
= BAD_ARGS
;
10648 /* Isnsn like "foo X,Y,Z". */
10651 do_mav_triple (str
, mode
, reg0
, reg1
, reg2
)
10654 enum arm_reg_type reg0
;
10655 enum arm_reg_type reg1
;
10656 enum arm_reg_type reg2
;
10658 int shift0
, shift1
, shift2
;
10660 shift0
= mode
& 0xff;
10661 shift1
= (mode
>> 8) & 0xff;
10662 shift2
= (mode
>> 16) & 0xff;
10664 skip_whitespace (str
);
10666 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
10667 || skip_past_comma (&str
) == FAIL
10668 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
10669 || skip_past_comma (&str
) == FAIL
10670 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
)
10673 inst
.error
= BAD_ARGS
;
10679 /* Isnsn like "foo W,X,Y,Z".
10680 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
10683 do_mav_quad (str
, mode
, reg0
, reg1
, reg2
, reg3
)
10686 enum arm_reg_type reg0
;
10687 enum arm_reg_type reg1
;
10688 enum arm_reg_type reg2
;
10689 enum arm_reg_type reg3
;
10691 int shift0
, shift1
, shift2
, shift3
;
10693 shift0
= mode
& 0xff;
10694 shift1
= (mode
>> 8) & 0xff;
10695 shift2
= (mode
>> 16) & 0xff;
10696 shift3
= (mode
>> 24) & 0xff;
10698 skip_whitespace (str
);
10700 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
10701 || skip_past_comma (&str
) == FAIL
10702 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
10703 || skip_past_comma (&str
) == FAIL
10704 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
10705 || skip_past_comma (&str
) == FAIL
10706 || mav_reg_required_here (&str
, shift3
, reg3
) == FAIL
)
10709 inst
.error
= BAD_ARGS
;
10715 /* Maverick shift immediate instructions.
10716 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
10717 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
10720 do_mav_shift (str
, reg0
, reg1
)
10722 enum arm_reg_type reg0
;
10723 enum arm_reg_type reg1
;
10728 skip_whitespace (str
);
10732 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
10733 || skip_past_comma (&str
) == FAIL
10734 || mav_reg_required_here (&str
, 16, reg1
) == FAIL
10735 || skip_past_comma (&str
) == FAIL
)
10738 inst
.error
= BAD_ARGS
;
10742 /* Calculate the immediate operand.
10743 The operand is a 7bit signed number. */
10744 skip_whitespace (str
);
10749 if (!ISDIGIT (*str
) && *str
!= '-')
10751 inst
.error
= _("expecting immediate, 7bit operand");
10761 for (imm
= 0; *str
&& ISDIGIT (*str
); ++str
)
10762 imm
= imm
* 10 + *str
- '0';
10766 inst
.error
= _("immediate out of range");
10770 /* Make negative imm's into 7bit signed numbers. */
10777 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
10778 Bits 5-7 of the insn should have bits 4-6 of the immediate.
10779 Bit 4 should be 0. */
10780 imm
= (imm
& 0xf) | ((imm
& 0x70) << 1);
10782 inst
.instruction
|= imm
;
10787 mav_parse_offset (str
, negative
)
10796 skip_whitespace (p
);
10809 inst
.error
= _("offset expected");
10813 for (offset
= 0; *p
&& ISDIGIT (*p
); ++p
)
10814 offset
= offset
* 10 + *p
- '0';
10818 inst
.error
= _("offset out of range");
10824 return *negative
? -offset
: offset
;
10827 /* Maverick load/store instructions.
10828 <insn><cond> CRd,[Rn,<offset>]{!}.
10829 <insn><cond> CRd,[Rn],<offset>. */
10832 do_mav_ldst (str
, reg0
)
10834 enum arm_reg_type reg0
;
10836 int offset
, negative
;
10838 skip_whitespace (str
);
10840 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
10841 || skip_past_comma (&str
) == FAIL
10843 || reg_required_here (&str
, 16) == FAIL
)
10846 if (skip_past_comma (&str
) == SUCCESS
)
10848 /* You are here: "<offset>]{!}". */
10849 inst
.instruction
|= PRE_INDEX
;
10851 offset
= mav_parse_offset (&str
, &negative
);
10858 inst
.error
= _("missing ]");
10864 inst
.instruction
|= WRITE_BACK
;
10870 /* You are here: "], <offset>". */
10873 inst
.error
= _("missing ]");
10877 if (skip_past_comma (&str
) == FAIL
10878 || (offset
= mav_parse_offset (&str
, &negative
), inst
.error
))
10881 inst
.instruction
|= CP_T_WB
; /* Post indexed, set bit W. */
10887 inst
.instruction
|= CP_T_UD
; /* Positive, so set bit U. */
10889 inst
.instruction
|= offset
>> 2;
10895 inst
.error
= BAD_ARGS
;
10906 /* Handle the Format 4 instructions that do not have equivalents in other
10907 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
10916 skip_whitespace (str
);
10918 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
10919 || skip_past_comma (&str
) == FAIL
10920 || (Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
10922 inst
.error
= BAD_ARGS
;
10926 if (skip_past_comma (&str
) != FAIL
)
10928 /* Three operand format not allowed for TST, CMN, NEG and MVN.
10929 (It isn't allowed for CMP either, but that isn't handled by this
10931 if (inst
.instruction
== T_OPCODE_TST
10932 || inst
.instruction
== T_OPCODE_CMN
10933 || inst
.instruction
== T_OPCODE_NEG
10934 || inst
.instruction
== T_OPCODE_MVN
)
10936 inst
.error
= BAD_ARGS
;
10940 if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
10945 inst
.error
= _("dest and source1 must be the same register");
10951 if (inst
.instruction
== T_OPCODE_MUL
10953 as_tsktsk (_("Rs and Rd must be different in MUL"));
10955 inst
.instruction
|= Rd
| (Rs
<< 3);
10963 thumb_add_sub (str
, 0);
10970 thumb_shift (str
, THUMB_ASR
);
10977 if (my_get_expression (&inst
.reloc
.exp
, &str
))
10979 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH9
;
10980 inst
.reloc
.pc_rel
= 1;
10985 do_t_branch12 (str
)
10988 if (my_get_expression (&inst
.reloc
.exp
, &str
))
10990 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH12
;
10991 inst
.reloc
.pc_rel
= 1;
10995 /* Find the real, Thumb encoded start of a Thumb function. */
10998 find_real_start (symbolP
)
11002 const char * name
= S_GET_NAME (symbolP
);
11003 symbolS
* new_target
;
11005 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
11006 #define STUB_NAME ".real_start_of"
11011 /* Names that start with '.' are local labels, not function entry points.
11012 The compiler may generate BL instructions to these labels because it
11013 needs to perform a branch to a far away location. */
11014 if (name
[0] == '.')
11017 real_start
= malloc (strlen (name
) + strlen (STUB_NAME
) + 1);
11018 sprintf (real_start
, "%s%s", STUB_NAME
, name
);
11020 new_target
= symbol_find (real_start
);
11022 if (new_target
== NULL
)
11024 as_warn ("Failed to find real start of function: %s\n", name
);
11025 new_target
= symbolP
;
11034 do_t_branch23 (str
)
11037 if (my_get_expression (& inst
.reloc
.exp
, & str
))
11040 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH23
;
11041 inst
.reloc
.pc_rel
= 1;
11044 /* If the destination of the branch is a defined symbol which does not have
11045 the THUMB_FUNC attribute, then we must be calling a function which has
11046 the (interfacearm) attribute. We look for the Thumb entry point to that
11047 function and change the branch to refer to that function instead. */
11048 if ( inst
.reloc
.exp
.X_op
== O_symbol
11049 && inst
.reloc
.exp
.X_add_symbol
!= NULL
11050 && S_IS_DEFINED (inst
.reloc
.exp
.X_add_symbol
)
11051 && ! THUMB_IS_FUNC (inst
.reloc
.exp
.X_add_symbol
))
11052 inst
.reloc
.exp
.X_add_symbol
=
11053 find_real_start (inst
.reloc
.exp
.X_add_symbol
);
11062 skip_whitespace (str
);
11064 if ((reg
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
11067 /* This sets THUMB_H2 from the top bit of reg. */
11068 inst
.instruction
|= reg
<< 3;
11070 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
11071 should cause the alignment to be checked once it is known. This is
11072 because BX PC only works if the instruction is word aligned. */
11081 thumb_mov_compare (str
, THUMB_COMPARE
);
11091 skip_whitespace (str
);
11093 if ((Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
11097 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
11101 if (skip_past_comma (&str
) == FAIL
11102 || (range
= reg_list (&str
)) == FAIL
)
11105 inst
.error
= BAD_ARGS
;
11109 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
11111 /* This really doesn't seem worth it. */
11112 inst
.reloc
.type
= BFD_RELOC_NONE
;
11113 inst
.error
= _("expression too complex");
11119 inst
.error
= _("only lo-regs valid in load/store multiple");
11123 inst
.instruction
|= (Rb
<< 8) | range
;
11131 thumb_load_store (str
, THUMB_LOAD
, THUMB_WORD
);
11138 thumb_load_store (str
, THUMB_LOAD
, THUMB_BYTE
);
11145 thumb_load_store (str
, THUMB_LOAD
, THUMB_HALFWORD
);
11154 skip_whitespace (str
);
11156 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
11157 || skip_past_comma (&str
) == FAIL
11159 || (Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
11160 || skip_past_comma (&str
) == FAIL
11161 || (Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
11165 inst
.error
= _("syntax: ldrs[b] Rd, [Rb, Ro]");
11169 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
11177 thumb_shift (str
, THUMB_LSL
);
11184 thumb_shift (str
, THUMB_LSR
);
11191 thumb_mov_compare (str
, THUMB_MOVE
);
11195 do_t_push_pop (str
)
11200 skip_whitespace (str
);
11202 if ((range
= reg_list (&str
)) == FAIL
)
11205 inst
.error
= BAD_ARGS
;
11209 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
11211 /* This really doesn't seem worth it. */
11212 inst
.reloc
.type
= BFD_RELOC_NONE
;
11213 inst
.error
= _("expression too complex");
11219 if ((inst
.instruction
== T_OPCODE_PUSH
11220 && (range
& ~0xff) == 1 << REG_LR
)
11221 || (inst
.instruction
== T_OPCODE_POP
11222 && (range
& ~0xff) == 1 << REG_PC
))
11224 inst
.instruction
|= THUMB_PP_PC_LR
;
11229 inst
.error
= _("invalid register list to push/pop instruction");
11234 inst
.instruction
|= range
;
11242 thumb_load_store (str
, THUMB_STORE
, THUMB_WORD
);
11249 thumb_load_store (str
, THUMB_STORE
, THUMB_BYTE
);
11256 thumb_load_store (str
, THUMB_STORE
, THUMB_HALFWORD
);
11263 thumb_add_sub (str
, 1);
11270 skip_whitespace (str
);
11272 if (my_get_expression (&inst
.reloc
.exp
, &str
))
11275 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
11285 /* This is a pseudo-op of the form "adr rd, label" to be converted
11286 into a relative address of the form "add rd, pc, #label-.-4". */
11287 skip_whitespace (str
);
11289 /* Store Rd in temporary location inside instruction. */
11290 if ((reg
= reg_required_here (&str
, 4)) == FAIL
11291 || (reg
> 7) /* For Thumb reg must be r0..r7. */
11292 || skip_past_comma (&str
) == FAIL
11293 || my_get_expression (&inst
.reloc
.exp
, &str
))
11296 inst
.error
= BAD_ARGS
;
11300 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
11301 inst
.reloc
.exp
.X_add_number
-= 4; /* PC relative adjust. */
11302 inst
.reloc
.pc_rel
= 1;
11303 inst
.instruction
|= REG_PC
; /* Rd is already placed into the instruction. */
11309 insert_reg (r
, htab
)
11310 const struct reg_entry
*r
;
11311 struct hash_control
*htab
;
11313 int len
= strlen (r
->name
) + 2;
11314 char * buf
= (char *) xmalloc (len
);
11315 char * buf2
= (char *) xmalloc (len
);
11318 #ifdef REGISTER_PREFIX
11319 buf
[i
++] = REGISTER_PREFIX
;
11322 strcpy (buf
+ i
, r
->name
);
11324 for (i
= 0; buf
[i
]; i
++)
11325 buf2
[i
] = TOUPPER (buf
[i
]);
11329 hash_insert (htab
, buf
, (PTR
) r
);
11330 hash_insert (htab
, buf2
, (PTR
) r
);
11334 build_reg_hsh (map
)
11335 struct reg_map
*map
;
11337 const struct reg_entry
*r
;
11339 if ((map
->htab
= hash_new ()) == NULL
)
11340 as_fatal (_("virtual memory exhausted"));
11342 for (r
= map
->names
; r
->name
!= NULL
; r
++)
11343 insert_reg (r
, map
->htab
);
11347 insert_reg_alias (str
, regnum
, htab
)
11350 struct hash_control
*htab
;
11353 struct reg_entry
*new = xmalloc (sizeof (struct reg_entry
));
11354 const char *name
= xmalloc (strlen (str
) + 1);
11356 strcpy ((char *) name
, str
);
11359 new->number
= regnum
;
11360 new->builtin
= FALSE
;
11362 error
= hash_insert (htab
, name
, (PTR
) new);
11365 as_bad (_("failed to create an alias for %s, reason: %s"),
11367 free ((char *) name
);
11372 /* Look for the .req directive. This is of the form:
11374 new_register_name .req existing_register_name
11376 If we find one, or if it looks sufficiently like one that we want to
11377 handle any error here, return non-zero. Otherwise return zero. */
11379 create_register_alias (newname
, p
)
11387 skip_whitespace (q
);
11392 if (*q
&& !strncmp (q
, ".req ", 5))
11397 #ifdef IGNORE_OPCODE_CASE
11398 newname
= original_case_string
;
11400 copy_of_str
= newname
;
11403 skip_whitespace (q
);
11405 for (r
= q
; *r
!= '\0'; r
++)
11411 enum arm_reg_type new_type
, old_type
;
11416 old_type
= arm_reg_parse_any (q
);
11419 new_type
= arm_reg_parse_any (newname
);
11421 if (new_type
== REG_TYPE_MAX
)
11423 if (old_type
!= REG_TYPE_MAX
)
11425 old_regno
= arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
);
11426 insert_reg_alias (newname
, old_regno
,
11427 all_reg_maps
[old_type
].htab
);
11430 as_warn (_("register '%s' does not exist\n"), q
);
11432 else if (old_type
== REG_TYPE_MAX
)
11434 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
11439 /* Do not warn about redefinitions to the same alias. */
11440 if (new_type
!= old_type
11441 || (arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
)
11442 != arm_reg_parse (&q
, all_reg_maps
[new_type
].htab
)))
11443 as_warn (_("ignoring redefinition of register alias '%s'"),
11449 as_warn (_("ignoring incomplete .req pseuso op"));
11460 set_constant_flonums ()
11464 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
11465 if (atof_ieee ((char *) fp_const
[i
], 'x', fp_values
[i
]) == NULL
)
11469 /* Iterate over the base tables to create the instruction patterns. */
11471 build_arm_ops_hsh ()
11475 static struct obstack insn_obstack
;
11477 obstack_begin (&insn_obstack
, 4000);
11479 for (i
= 0; i
< sizeof (insns
) / sizeof (struct asm_opcode
); i
++)
11481 const struct asm_opcode
*insn
= insns
+ i
;
11483 if (insn
->cond_offset
!= 0)
11485 /* Insn supports conditional execution. Build the varaints
11486 and insert them in the hash table. */
11487 for (j
= 0; j
< sizeof (conds
) / sizeof (struct asm_cond
); j
++)
11489 unsigned len
= strlen (insn
->template);
11490 struct asm_opcode
*new;
11493 new = obstack_alloc (&insn_obstack
, sizeof (struct asm_opcode
));
11494 /* All condition codes are two characters. */
11495 template = obstack_alloc (&insn_obstack
, len
+ 3);
11497 strncpy (template, insn
->template, insn
->cond_offset
);
11498 strcpy (template + insn
->cond_offset
, conds
[j
].template);
11499 if (len
> insn
->cond_offset
)
11500 strcpy (template + insn
->cond_offset
+ 2,
11501 insn
->template + insn
->cond_offset
);
11502 new->template = template;
11503 new->cond_offset
= 0;
11504 new->variant
= insn
->variant
;
11505 new->parms
= insn
->parms
;
11506 new->value
= (insn
->value
& ~COND_MASK
) | conds
[j
].value
;
11508 hash_insert (arm_ops_hsh
, new->template, (PTR
) new);
11511 /* Finally, insert the unconditional insn in the table directly;
11512 no need to build a copy. */
11513 hash_insert (arm_ops_hsh
, insn
->template, (PTR
) insn
);
11517 #if 0 /* Suppressed - for now. */
11518 #if defined OBJ_ELF || defined OBJ_COFF
11521 #define arm_Note Elf_External_Note
11525 unsigned char namesz
[4]; /* Size of entry's owner string. */
11526 unsigned char descsz
[4]; /* Size of the note descriptor. */
11527 unsigned char type
[4]; /* Interpretation of the descriptor. */
11528 char name
[1]; /* Start of the name+desc data. */
11532 /* The description is kept to a fix sized in order to make updating
11533 it and merging it easier. */
11534 #define ARM_NOTE_DESCRIPTION_LENGTH 8
11537 arm_add_note (name
, description
, type
)
11539 const char * description
;
11542 arm_Note note ATTRIBUTE_UNUSED
;
11544 unsigned int name_len
;
11546 name_len
= (strlen (name
) + 1 + 3) & ~3;
11548 p
= frag_more (sizeof (note
.namesz
));
11549 md_number_to_chars (p
, (valueT
) name_len
, sizeof (note
.namesz
));
11551 p
= frag_more (sizeof (note
.descsz
));
11552 md_number_to_chars (p
, (valueT
) ARM_NOTE_DESCRIPTION_LENGTH
, sizeof (note
.descsz
));
11554 p
= frag_more (sizeof (note
.type
));
11555 md_number_to_chars (p
, (valueT
) type
, sizeof (note
.type
));
11557 p
= frag_more (name_len
);
11560 p
= frag_more (ARM_NOTE_DESCRIPTION_LENGTH
);
11561 strncpy (p
, description
, ARM_NOTE_DESCRIPTION_LENGTH
);
11562 frag_align (2, 0, 0);
11573 if ( (arm_ops_hsh
= hash_new ()) == NULL
11574 || (arm_tops_hsh
= hash_new ()) == NULL
11575 || (arm_cond_hsh
= hash_new ()) == NULL
11576 || (arm_shift_hsh
= hash_new ()) == NULL
11577 || (arm_psr_hsh
= hash_new ()) == NULL
)
11578 as_fatal (_("virtual memory exhausted"));
11580 build_arm_ops_hsh ();
11581 for (i
= 0; i
< sizeof (tinsns
) / sizeof (struct thumb_opcode
); i
++)
11582 hash_insert (arm_tops_hsh
, tinsns
[i
].template, (PTR
) (tinsns
+ i
));
11583 for (i
= 0; i
< sizeof (conds
) / sizeof (struct asm_cond
); i
++)
11584 hash_insert (arm_cond_hsh
, conds
[i
].template, (PTR
) (conds
+ i
));
11585 for (i
= 0; i
< sizeof (shift_names
) / sizeof (struct asm_shift_name
); i
++)
11586 hash_insert (arm_shift_hsh
, shift_names
[i
].name
, (PTR
) (shift_names
+ i
));
11587 for (i
= 0; i
< sizeof (psrs
) / sizeof (struct asm_psr
); i
++)
11588 hash_insert (arm_psr_hsh
, psrs
[i
].template, (PTR
) (psrs
+ i
));
11590 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
11591 build_reg_hsh (all_reg_maps
+ i
);
11593 set_constant_flonums ();
11595 /* Set the cpu variant based on the command-line options. We prefer
11596 -mcpu= over -march= if both are set (as for GCC); and we prefer
11597 -mfpu= over any other way of setting the floating point unit.
11598 Use of legacy options with new options are faulted. */
11599 if (legacy_cpu
!= -1)
11601 if (mcpu_cpu_opt
!= -1 || march_cpu_opt
!= -1)
11602 as_bad (_("use of old and new-style options to set CPU type"));
11604 mcpu_cpu_opt
= legacy_cpu
;
11606 else if (mcpu_cpu_opt
== -1)
11607 mcpu_cpu_opt
= march_cpu_opt
;
11609 if (legacy_fpu
!= -1)
11611 if (mfpu_opt
!= -1)
11612 as_bad (_("use of old and new-style options to set FPU type"));
11614 mfpu_opt
= legacy_fpu
;
11616 else if (mfpu_opt
== -1)
11618 #if !(defined (TE_LINUX) || defined (TE_NetBSD))
11619 /* Some environments specify a default FPU. If they don't, infer it
11620 from the processor. */
11621 if (mcpu_fpu_opt
!= -1)
11622 mfpu_opt
= mcpu_fpu_opt
;
11624 mfpu_opt
= march_fpu_opt
;
11626 mfpu_opt
= FPU_DEFAULT
;
11630 if (mfpu_opt
== -1)
11632 if (mcpu_cpu_opt
== -1)
11633 mfpu_opt
= FPU_DEFAULT
;
11634 else if (mcpu_cpu_opt
& ARM_EXT_V5
)
11635 mfpu_opt
= FPU_ARCH_VFP_V2
;
11637 mfpu_opt
= FPU_ARCH_FPA
;
11640 if (mcpu_cpu_opt
== -1)
11641 mcpu_cpu_opt
= CPU_DEFAULT
;
11643 cpu_variant
= mcpu_cpu_opt
| mfpu_opt
;
11645 #if defined OBJ_COFF || defined OBJ_ELF
11647 unsigned int flags
= 0;
11649 /* Set the flags in the private structure. */
11650 if (uses_apcs_26
) flags
|= F_APCS26
;
11651 if (support_interwork
) flags
|= F_INTERWORK
;
11652 if (uses_apcs_float
) flags
|= F_APCS_FLOAT
;
11653 if (pic_code
) flags
|= F_PIC
;
11654 if ((cpu_variant
& FPU_ANY
) == FPU_NONE
11655 || (cpu_variant
& FPU_ANY
) == FPU_ARCH_VFP
) /* VFP layout only. */
11656 flags
|= F_SOFT_FLOAT
;
11657 /* Using VFP conventions (even if soft-float). */
11658 if (cpu_variant
& FPU_VFP_EXT_NONE
) flags
|= F_VFP_FLOAT
;
11660 #if defined OBJ_ELF
11661 if (cpu_variant
& ARM_CEXT_MAVERICK
)
11663 flags
&= ~ F_SOFT_FLOAT
;
11664 flags
|= EF_ARM_MAVERICK_FLOAT
;
11668 bfd_set_private_flags (stdoutput
, flags
);
11670 /* We have run out flags in the COFF header to encode the
11671 status of ATPCS support, so instead we create a dummy,
11672 empty, debug section called .arm.atpcs. */
11677 sec
= bfd_make_section (stdoutput
, ".arm.atpcs");
11681 bfd_set_section_flags
11682 (stdoutput
, sec
, SEC_READONLY
| SEC_DEBUGGING
/* | SEC_HAS_CONTENTS */);
11683 bfd_set_section_size (stdoutput
, sec
, 0);
11684 bfd_set_section_contents (stdoutput
, sec
, NULL
, 0, 0);
11690 /* Record the CPU type as well. */
11691 switch (cpu_variant
& ARM_CPU_MASK
)
11694 mach
= bfd_mach_arm_2
;
11697 case ARM_3
: /* Also ARM_250. */
11698 mach
= bfd_mach_arm_2a
;
11701 case ARM_6
: /* Also ARM_7. */
11702 mach
= bfd_mach_arm_3
;
11706 mach
= bfd_mach_arm_unknown
;
11710 /* Catch special cases. */
11711 if (cpu_variant
& ARM_CEXT_IWMMXT
)
11712 mach
= bfd_mach_arm_iWMMXt
;
11713 else if (cpu_variant
& ARM_CEXT_XSCALE
)
11714 mach
= bfd_mach_arm_XScale
;
11715 else if (cpu_variant
& ARM_CEXT_MAVERICK
)
11716 mach
= bfd_mach_arm_ep9312
;
11717 else if (cpu_variant
& ARM_EXT_V5E
)
11718 mach
= bfd_mach_arm_5TE
;
11719 else if (cpu_variant
& ARM_EXT_V5
)
11721 if (cpu_variant
& ARM_EXT_V4T
)
11722 mach
= bfd_mach_arm_5T
;
11724 mach
= bfd_mach_arm_5
;
11726 else if (cpu_variant
& ARM_EXT_V4
)
11728 if (cpu_variant
& ARM_EXT_V4T
)
11729 mach
= bfd_mach_arm_4T
;
11731 mach
= bfd_mach_arm_4
;
11733 else if (cpu_variant
& ARM_EXT_V3M
)
11734 mach
= bfd_mach_arm_3M
;
11736 #if 0 /* Suppressed - for now. */
11737 #if defined (OBJ_ELF) || defined (OBJ_COFF)
11739 /* Create a .note section to fully identify this arm binary. */
11741 #define NOTE_ARCH_STRING "arch: "
11743 #if defined OBJ_COFF && ! defined NT_VERSION
11744 #define NT_VERSION 1
11749 segT current_seg
= now_seg
;
11750 subsegT current_subseg
= now_subseg
;
11751 asection
* arm_arch
;
11752 const char * arch_string
;
11754 arm_arch
= bfd_make_section_old_way (stdoutput
, ARM_NOTE_SECTION
);
11757 bfd_set_section_flags (stdoutput
, arm_arch
,
11758 SEC_DATA
| SEC_ALLOC
| SEC_LOAD
| SEC_LINK_ONCE \
11759 | SEC_HAS_CONTENTS
);
11761 arm_arch
->output_section
= arm_arch
;
11762 subseg_set (arm_arch
, 0);
11767 case bfd_mach_arm_unknown
: arch_string
= "unknown"; break;
11768 case bfd_mach_arm_2
: arch_string
= "armv2"; break;
11769 case bfd_mach_arm_2a
: arch_string
= "armv2a"; break;
11770 case bfd_mach_arm_3
: arch_string
= "armv3"; break;
11771 case bfd_mach_arm_3M
: arch_string
= "armv3M"; break;
11772 case bfd_mach_arm_4
: arch_string
= "armv4"; break;
11773 case bfd_mach_arm_4T
: arch_string
= "armv4t"; break;
11774 case bfd_mach_arm_5
: arch_string
= "armv5"; break;
11775 case bfd_mach_arm_5T
: arch_string
= "armv5t"; break;
11776 case bfd_mach_arm_5TE
: arch_string
= "armv5te"; break;
11777 case bfd_mach_arm_XScale
: arch_string
= "XScale"; break;
11778 case bfd_mach_arm_ep9312
: arch_string
= "ep9312"; break;
11779 case bfd_mach_arm_iWMMXt
: arch_string
= "iWMMXt"; break;
11782 arm_add_note (NOTE_ARCH_STRING
, arch_string
, NT_ARCH
);
11784 subseg_set (current_seg
, current_subseg
);
11787 #endif /* Suppressed code. */
11789 bfd_set_arch_mach (stdoutput
, TARGET_ARCH
, mach
);
11792 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11793 for use in the a.out file, and stores them in the array pointed to by buf.
11794 This knows about the endian-ness of the target machine and does
11795 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11796 2 (short) and 4 (long) Floating numbers are put out as a series of
11797 LITTLENUMS (shorts, here at least). */
11800 md_number_to_chars (buf
, val
, n
)
11805 if (target_big_endian
)
11806 number_to_chars_bigendian (buf
, val
, n
);
11808 number_to_chars_littleendian (buf
, val
, n
);
11812 md_chars_to_number (buf
, n
)
11817 unsigned char * where
= (unsigned char *) buf
;
11819 if (target_big_endian
)
11824 result
|= (*where
++ & 255);
11832 result
|= (where
[n
] & 255);
11839 /* Turn a string in input_line_pointer into a floating point constant
11840 of type TYPE, and store the appropriate bytes in *LITP. The number
11841 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11842 returned, or NULL on OK.
11844 Note that fp constants aren't represent in the normal way on the ARM.
11845 In big endian mode, things are as expected. However, in little endian
11846 mode fp constants are big-endian word-wise, and little-endian byte-wise
11847 within the words. For example, (double) 1.1 in big endian mode is
11848 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11849 the byte sequence 99 99 f1 3f 9a 99 99 99.
11851 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11854 md_atof (type
, litP
, sizeP
)
11860 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
11892 return _("bad call to MD_ATOF()");
11895 t
= atof_ieee (input_line_pointer
, type
, words
);
11897 input_line_pointer
= t
;
11900 if (target_big_endian
)
11902 for (i
= 0; i
< prec
; i
++)
11904 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
11910 if (cpu_variant
& FPU_ARCH_VFP
)
11911 for (i
= prec
- 1; i
>= 0; i
--)
11913 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
11917 /* For a 4 byte float the order of elements in `words' is 1 0.
11918 For an 8 byte float the order is 1 0 3 2. */
11919 for (i
= 0; i
< prec
; i
+= 2)
11921 md_number_to_chars (litP
, (valueT
) words
[i
+ 1], 2);
11922 md_number_to_chars (litP
+ 2, (valueT
) words
[i
], 2);
11930 /* The knowledge of the PC's pipeline offset is built into the insns
11934 md_pcrel_from (fixP
)
11938 && S_GET_SEGMENT (fixP
->fx_addsy
) == undefined_section
11939 && fixP
->fx_subsy
== NULL
)
11942 if (fixP
->fx_pcrel
&& (fixP
->fx_r_type
== BFD_RELOC_ARM_THUMB_ADD
))
11944 /* PC relative addressing on the Thumb is slightly odd
11945 as the bottom two bits of the PC are forced to zero
11946 for the calculation. */
11947 return (fixP
->fx_where
+ fixP
->fx_frag
->fr_address
) & ~3;
11951 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
11952 so we un-adjust here to compensate for the accommodation. */
11953 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
+ 8;
11955 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
11959 /* Round up a section size to the appropriate boundary. */
11962 md_section_align (segment
, size
)
11963 segT segment ATTRIBUTE_UNUSED
;
11969 /* Round all sects to multiple of 4. */
11970 return (size
+ 3) & ~3;
11974 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
11975 Otherwise we have no need to default values of symbols. */
11978 md_undefined_symbol (name
)
11979 char * name ATTRIBUTE_UNUSED
;
11982 if (name
[0] == '_' && name
[1] == 'G'
11983 && streq (name
, GLOBAL_OFFSET_TABLE_NAME
))
11987 if (symbol_find (name
))
11988 as_bad ("GOT already in the symbol table");
11990 GOT_symbol
= symbol_new (name
, undefined_section
,
11991 (valueT
) 0, & zero_address_frag
);
12001 /* arm_reg_parse () := if it looks like a register, return its token and
12002 advance the pointer. */
12005 arm_reg_parse (ccp
, htab
)
12006 register char ** ccp
;
12007 struct hash_control
*htab
;
12009 char * start
= * ccp
;
12012 struct reg_entry
* reg
;
12014 #ifdef REGISTER_PREFIX
12015 if (*start
!= REGISTER_PREFIX
)
12020 #ifdef OPTIONAL_REGISTER_PREFIX
12021 if (*p
== OPTIONAL_REGISTER_PREFIX
)
12025 if (!ISALPHA (*p
) || !is_name_beginner (*p
))
12029 while (ISALPHA (c
) || ISDIGIT (c
) || c
== '_')
12033 reg
= (struct reg_entry
*) hash_find (htab
, start
);
12039 return reg
->number
;
12045 /* Search for the following register name in each of the possible reg name
12046 tables. Return the classification if found, or REG_TYPE_MAX if not
12048 static enum arm_reg_type
12049 arm_reg_parse_any (cp
)
12054 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
12055 if (arm_reg_parse (&cp
, all_reg_maps
[i
].htab
) != FAIL
)
12056 return (enum arm_reg_type
) i
;
12058 return REG_TYPE_MAX
;
12062 md_apply_fix3 (fixP
, valP
, seg
)
12067 offsetT value
= * valP
;
12069 unsigned int newimm
;
12070 unsigned long temp
;
12072 char * buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
12073 arm_fix_data
* arm_data
= (arm_fix_data
*) fixP
->tc_fix_data
;
12075 assert (fixP
->fx_r_type
< BFD_RELOC_UNUSED
);
12077 /* Note whether this will delete the relocation. */
12079 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
12080 doesn't work fully.) */
12081 if ((fixP
->fx_addsy
== 0 || symbol_constant_p (fixP
->fx_addsy
))
12082 && !fixP
->fx_pcrel
)
12084 if (fixP
->fx_addsy
== 0 && !fixP
->fx_pcrel
)
12088 /* If this symbol is in a different section then we need to leave it for
12089 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
12090 so we have to undo it's effects here. */
12091 if (fixP
->fx_pcrel
)
12093 if (fixP
->fx_addsy
!= NULL
12094 && S_IS_DEFINED (fixP
->fx_addsy
)
12095 && S_GET_SEGMENT (fixP
->fx_addsy
) != seg
)
12098 && (fixP
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
12099 || fixP
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
12103 value
+= md_pcrel_from (fixP
);
12107 /* Remember value for emit_reloc. */
12108 fixP
->fx_addnumber
= value
;
12110 switch (fixP
->fx_r_type
)
12112 case BFD_RELOC_ARM_IMMEDIATE
:
12113 newimm
= validate_immediate (value
);
12114 temp
= md_chars_to_number (buf
, INSN_SIZE
);
12116 /* If the instruction will fail, see if we can fix things up by
12117 changing the opcode. */
12118 if (newimm
== (unsigned int) FAIL
12119 && (newimm
= negate_data_op (&temp
, value
)) == (unsigned int) FAIL
)
12121 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12122 _("invalid constant (%lx) after fixup"),
12123 (unsigned long) value
);
12127 newimm
|= (temp
& 0xfffff000);
12128 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
12132 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
12134 unsigned int highpart
= 0;
12135 unsigned int newinsn
= 0xe1a00000; /* nop. */
12137 newimm
= validate_immediate (value
);
12138 temp
= md_chars_to_number (buf
, INSN_SIZE
);
12140 /* If the instruction will fail, see if we can fix things up by
12141 changing the opcode. */
12142 if (newimm
== (unsigned int) FAIL
12143 && (newimm
= negate_data_op (& temp
, value
)) == (unsigned int) FAIL
)
12145 /* No ? OK - try using two ADD instructions to generate
12147 newimm
= validate_immediate_twopart (value
, & highpart
);
12149 /* Yes - then make sure that the second instruction is
12151 if (newimm
!= (unsigned int) FAIL
)
12153 /* Still No ? Try using a negated value. */
12154 else if ((newimm
= validate_immediate_twopart (- value
, & highpart
)) != (unsigned int) FAIL
)
12155 temp
= newinsn
= (temp
& OPCODE_MASK
) | OPCODE_SUB
<< DATA_OP_SHIFT
;
12156 /* Otherwise - give up. */
12159 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12160 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
12165 /* Replace the first operand in the 2nd instruction (which
12166 is the PC) with the destination register. We have
12167 already added in the PC in the first instruction and we
12168 do not want to do it again. */
12169 newinsn
&= ~ 0xf0000;
12170 newinsn
|= ((newinsn
& 0x0f000) << 4);
12173 newimm
|= (temp
& 0xfffff000);
12174 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
12176 highpart
|= (newinsn
& 0xfffff000);
12177 md_number_to_chars (buf
+ INSN_SIZE
, (valueT
) highpart
, INSN_SIZE
);
12181 case BFD_RELOC_ARM_OFFSET_IMM
:
12187 if (validate_offset_imm (value
, 0) == FAIL
)
12189 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12190 _("bad immediate value for offset (%ld)"),
12195 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12196 newval
&= 0xff7ff000;
12197 newval
|= value
| (sign
? INDEX_UP
: 0);
12198 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12201 case BFD_RELOC_ARM_OFFSET_IMM8
:
12202 case BFD_RELOC_ARM_HWLITERAL
:
12208 if (validate_offset_imm (value
, 1) == FAIL
)
12210 if (fixP
->fx_r_type
== BFD_RELOC_ARM_HWLITERAL
)
12211 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12212 _("invalid literal constant: pool needs to be closer"));
12214 as_bad (_("bad immediate value for half-word offset (%ld)"),
12219 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12220 newval
&= 0xff7ff0f0;
12221 newval
|= ((value
>> 4) << 8) | (value
& 0xf) | (sign
? INDEX_UP
: 0);
12222 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12225 case BFD_RELOC_ARM_LITERAL
:
12231 if (validate_offset_imm (value
, 0) == FAIL
)
12233 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12234 _("invalid literal constant: pool needs to be closer"));
12238 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12239 newval
&= 0xff7ff000;
12240 newval
|= value
| (sign
? INDEX_UP
: 0);
12241 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12244 case BFD_RELOC_ARM_SHIFT_IMM
:
12245 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12246 if (((unsigned long) value
) > 32
12248 && (((newval
& 0x60) == 0) || (newval
& 0x60) == 0x60)))
12250 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12251 _("shift expression is too large"));
12256 /* Shifts of zero must be done as lsl. */
12258 else if (value
== 32)
12260 newval
&= 0xfffff07f;
12261 newval
|= (value
& 0x1f) << 7;
12262 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12265 case BFD_RELOC_ARM_SWI
:
12266 if (arm_data
->thumb_mode
)
12268 if (((unsigned long) value
) > 0xff)
12269 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12270 _("invalid swi expression"));
12271 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xff00;
12273 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12277 if (((unsigned long) value
) > 0x00ffffff)
12278 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12279 _("invalid swi expression"));
12280 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff000000;
12282 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12286 case BFD_RELOC_ARM_MULTI
:
12287 if (((unsigned long) value
) > 0xffff)
12288 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12289 _("invalid expression in load/store multiple"));
12290 newval
= value
| md_chars_to_number (buf
, INSN_SIZE
);
12291 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12294 case BFD_RELOC_ARM_PCREL_BRANCH
:
12295 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12297 /* Sign-extend a 24-bit number. */
12298 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
12302 value
= fixP
->fx_offset
;
12305 /* We are going to store value (shifted right by two) in the
12306 instruction, in a 24 bit, signed field. Thus we need to check
12307 that none of the top 8 bits of the shifted value (top 7 bits of
12308 the unshifted, unsigned value) are set, or that they are all set. */
12309 if ((value
& ~ ((offsetT
) 0x1ffffff)) != 0
12310 && ((value
& ~ ((offsetT
) 0x1ffffff)) != ~ ((offsetT
) 0x1ffffff)))
12313 /* Normally we would be stuck at this point, since we cannot store
12314 the absolute address that is the destination of the branch in the
12315 24 bits of the branch instruction. If however, we happen to know
12316 that the destination of the branch is in the same section as the
12317 branch instruction itself, then we can compute the relocation for
12318 ourselves and not have to bother the linker with it.
12320 FIXME: The tests for OBJ_ELF and ! target_oabi are only here
12321 because I have not worked out how to do this for OBJ_COFF or
12324 && fixP
->fx_addsy
!= NULL
12325 && S_IS_DEFINED (fixP
->fx_addsy
)
12326 && S_GET_SEGMENT (fixP
->fx_addsy
) == seg
)
12328 /* Get pc relative value to go into the branch. */
12331 /* Permit a backward branch provided that enough bits
12332 are set. Allow a forwards branch, provided that
12333 enough bits are clear. */
12334 if ( (value
& ~ ((offsetT
) 0x1ffffff)) == ~ ((offsetT
) 0x1ffffff)
12335 || (value
& ~ ((offsetT
) 0x1ffffff)) == 0)
12339 if (! fixP
->fx_done
)
12341 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12342 _("GAS can't handle same-section branch dest >= 0x04000000"));
12346 value
+= SEXT24 (newval
);
12348 if ( (value
& ~ ((offsetT
) 0xffffff)) != 0
12349 && ((value
& ~ ((offsetT
) 0xffffff)) != ~ ((offsetT
) 0xffffff)))
12350 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12351 _("out of range branch"));
12353 newval
= (value
& 0x00ffffff) | (newval
& 0xff000000);
12354 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12357 case BFD_RELOC_ARM_PCREL_BLX
:
12360 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12364 value
= fixP
->fx_offset
;
12366 hbit
= (value
>> 1) & 1;
12367 value
= (value
>> 2) & 0x00ffffff;
12368 value
= (value
+ (newval
& 0x00ffffff)) & 0x00ffffff;
12369 newval
= value
| (newval
& 0xfe000000) | (hbit
<< 24);
12370 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12374 case BFD_RELOC_THUMB_PCREL_BRANCH9
: /* Conditional branch. */
12375 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12377 addressT diff
= (newval
& 0xff) << 1;
12382 if ((value
& ~0xff) && ((value
& ~0xff) != ~0xff))
12383 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12384 _("branch out of range"));
12385 newval
= (newval
& 0xff00) | ((value
& 0x1ff) >> 1);
12387 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12390 case BFD_RELOC_THUMB_PCREL_BRANCH12
: /* Unconditional branch. */
12391 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12393 addressT diff
= (newval
& 0x7ff) << 1;
12398 if ((value
& ~0x7ff) && ((value
& ~0x7ff) != ~0x7ff))
12399 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12400 _("branch out of range"));
12401 newval
= (newval
& 0xf800) | ((value
& 0xfff) >> 1);
12403 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12406 case BFD_RELOC_THUMB_PCREL_BLX
:
12407 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
12412 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12413 newval2
= md_chars_to_number (buf
+ THUMB_SIZE
, THUMB_SIZE
);
12414 diff
= ((newval
& 0x7ff) << 12) | ((newval2
& 0x7ff) << 1);
12415 if (diff
& 0x400000)
12418 value
= fixP
->fx_offset
;
12422 if ((value
& ~0x3fffff) && ((value
& ~0x3fffff) != ~0x3fffff))
12423 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12424 _("branch with link out of range"));
12426 newval
= (newval
& 0xf800) | ((value
& 0x7fffff) >> 12);
12427 newval2
= (newval2
& 0xf800) | ((value
& 0xfff) >> 1);
12428 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
)
12429 /* For a BLX instruction, make sure that the relocation is rounded up
12430 to a word boundary. This follows the semantics of the instruction
12431 which specifies that bit 1 of the target address will come from bit
12432 1 of the base address. */
12433 newval2
= (newval2
+ 1) & ~ 1;
12434 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12435 md_number_to_chars (buf
+ THUMB_SIZE
, newval2
, THUMB_SIZE
);
12440 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
12441 md_number_to_chars (buf
, value
, 1);
12443 else if (!target_oabi
)
12445 value
= fixP
->fx_offset
;
12446 md_number_to_chars (buf
, value
, 1);
12452 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
12453 md_number_to_chars (buf
, value
, 2);
12455 else if (!target_oabi
)
12457 value
= fixP
->fx_offset
;
12458 md_number_to_chars (buf
, value
, 2);
12464 case BFD_RELOC_ARM_GOT32
:
12465 case BFD_RELOC_ARM_GOTOFF
:
12466 md_number_to_chars (buf
, 0, 4);
12470 case BFD_RELOC_RVA
:
12472 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
12473 md_number_to_chars (buf
, value
, 4);
12475 else if (!target_oabi
)
12477 value
= fixP
->fx_offset
;
12478 md_number_to_chars (buf
, value
, 4);
12484 case BFD_RELOC_ARM_PLT32
:
12485 /* It appears the instruction is fully prepared at this point. */
12489 case BFD_RELOC_ARM_CP_OFF_IMM
:
12491 if (value
< -1023 || value
> 1023 || (value
& 3))
12492 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12493 _("illegal value for co-processor offset"));
12496 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
12497 newval
|= (value
>> 2) | (sign
? INDEX_UP
: 0);
12498 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12501 case BFD_RELOC_ARM_CP_OFF_IMM_S2
:
12503 if (value
< -255 || value
> 255)
12504 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12505 _("Illegal value for co-processor offset"));
12508 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
12509 newval
|= value
| (sign
? INDEX_UP
: 0);
12510 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12513 case BFD_RELOC_ARM_THUMB_OFFSET
:
12514 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12515 /* Exactly what ranges, and where the offset is inserted depends
12516 on the type of instruction, we can establish this from the
12518 switch (newval
>> 12)
12520 case 4: /* PC load. */
12521 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
12522 forced to zero for these loads, so we will need to round
12523 up the offset if the instruction address is not word
12524 aligned (since the final address produced must be, and
12525 we can only describe word-aligned immediate offsets). */
12527 if ((fixP
->fx_frag
->fr_address
+ fixP
->fx_where
+ value
) & 3)
12528 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12529 _("invalid offset, target not word aligned (0x%08X)"),
12530 (unsigned int) (fixP
->fx_frag
->fr_address
12531 + fixP
->fx_where
+ value
));
12533 if ((value
+ 2) & ~0x3fe)
12534 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12535 _("invalid offset, value too big (0x%08lX)"),
12538 /* Round up, since pc will be rounded down. */
12539 newval
|= (value
+ 2) >> 2;
12542 case 9: /* SP load/store. */
12543 if (value
& ~0x3fc)
12544 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12545 _("invalid offset, value too big (0x%08lX)"),
12547 newval
|= value
>> 2;
12550 case 6: /* Word load/store. */
12552 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12553 _("invalid offset, value too big (0x%08lX)"),
12555 newval
|= value
<< 4; /* 6 - 2. */
12558 case 7: /* Byte load/store. */
12560 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12561 _("invalid offset, value too big (0x%08lX)"),
12563 newval
|= value
<< 6;
12566 case 8: /* Halfword load/store. */
12568 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12569 _("invalid offset, value too big (0x%08lX)"),
12571 newval
|= value
<< 5; /* 6 - 1. */
12575 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12576 "Unable to process relocation for thumb opcode: %lx",
12577 (unsigned long) newval
);
12580 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12583 case BFD_RELOC_ARM_THUMB_ADD
:
12584 /* This is a complicated relocation, since we use it for all of
12585 the following immediate relocations:
12589 9bit ADD/SUB SP word-aligned
12590 10bit ADD PC/SP word-aligned
12592 The type of instruction being processed is encoded in the
12599 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12601 int rd
= (newval
>> 4) & 0xf;
12602 int rs
= newval
& 0xf;
12603 int subtract
= newval
& 0x8000;
12607 if (value
& ~0x1fc)
12608 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12609 _("invalid immediate for stack address calculation"));
12610 newval
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
12611 newval
|= value
>> 2;
12613 else if (rs
== REG_PC
|| rs
== REG_SP
)
12617 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12618 _("invalid immediate for address calculation (value = 0x%08lX)"),
12619 (unsigned long) value
);
12620 newval
= (rs
== REG_PC
? T_OPCODE_ADD_PC
: T_OPCODE_ADD_SP
);
12622 newval
|= value
>> 2;
12627 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12628 _("invalid 8bit immediate"));
12629 newval
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
12630 newval
|= (rd
<< 8) | value
;
12635 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12636 _("invalid 3bit immediate"));
12637 newval
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
12638 newval
|= rd
| (rs
<< 3) | (value
<< 6);
12641 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12644 case BFD_RELOC_ARM_THUMB_IMM
:
12645 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12646 switch (newval
>> 11)
12648 case 0x04: /* 8bit immediate MOV. */
12649 case 0x05: /* 8bit immediate CMP. */
12650 if (value
< 0 || value
> 255)
12651 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12652 _("invalid immediate: %ld is too large"),
12660 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12663 case BFD_RELOC_ARM_THUMB_SHIFT
:
12664 /* 5bit shift value (0..31). */
12665 if (value
< 0 || value
> 31)
12666 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12667 _("illegal Thumb shift value: %ld"), (long) value
);
12668 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xf03f;
12669 newval
|= value
<< 6;
12670 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12673 case BFD_RELOC_VTABLE_INHERIT
:
12674 case BFD_RELOC_VTABLE_ENTRY
:
12678 case BFD_RELOC_NONE
:
12680 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12681 _("bad relocation fixup type (%d)"), fixP
->fx_r_type
);
12685 /* Translate internal representation of relocation info to BFD target
12689 tc_gen_reloc (section
, fixp
)
12690 asection
* section ATTRIBUTE_UNUSED
;
12694 bfd_reloc_code_real_type code
;
12696 reloc
= (arelent
*) xmalloc (sizeof (arelent
));
12698 reloc
->sym_ptr_ptr
= (asymbol
**) xmalloc (sizeof (asymbol
*));
12699 *reloc
->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
12700 reloc
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
12702 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12704 if (fixp
->fx_pcrel
== 0)
12705 reloc
->addend
= fixp
->fx_offset
;
12707 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
12708 #else /* OBJ_ELF */
12709 reloc
->addend
= fixp
->fx_offset
;
12712 switch (fixp
->fx_r_type
)
12715 if (fixp
->fx_pcrel
)
12717 code
= BFD_RELOC_8_PCREL
;
12722 if (fixp
->fx_pcrel
)
12724 code
= BFD_RELOC_16_PCREL
;
12729 if (fixp
->fx_pcrel
)
12731 code
= BFD_RELOC_32_PCREL
;
12735 case BFD_RELOC_ARM_PCREL_BRANCH
:
12736 case BFD_RELOC_ARM_PCREL_BLX
:
12737 case BFD_RELOC_RVA
:
12738 case BFD_RELOC_THUMB_PCREL_BRANCH9
:
12739 case BFD_RELOC_THUMB_PCREL_BRANCH12
:
12740 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
12741 case BFD_RELOC_THUMB_PCREL_BLX
:
12742 case BFD_RELOC_VTABLE_ENTRY
:
12743 case BFD_RELOC_VTABLE_INHERIT
:
12744 code
= fixp
->fx_r_type
;
12747 case BFD_RELOC_ARM_LITERAL
:
12748 case BFD_RELOC_ARM_HWLITERAL
:
12749 /* If this is called then the a literal has
12750 been referenced across a section boundary. */
12751 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12752 _("literal referenced across section boundary"));
12756 case BFD_RELOC_ARM_GOT32
:
12757 case BFD_RELOC_ARM_GOTOFF
:
12758 case BFD_RELOC_ARM_PLT32
:
12759 code
= fixp
->fx_r_type
;
12763 case BFD_RELOC_ARM_IMMEDIATE
:
12764 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12765 _("internal relocation (type: IMMEDIATE) not fixed up"));
12768 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
12769 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12770 _("ADRL used for a symbol not defined in the same file"));
12773 case BFD_RELOC_ARM_OFFSET_IMM
:
12774 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12775 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
12782 switch (fixp
->fx_r_type
)
12784 case BFD_RELOC_ARM_OFFSET_IMM8
: type
= "OFFSET_IMM8"; break;
12785 case BFD_RELOC_ARM_SHIFT_IMM
: type
= "SHIFT_IMM"; break;
12786 case BFD_RELOC_ARM_SWI
: type
= "SWI"; break;
12787 case BFD_RELOC_ARM_MULTI
: type
= "MULTI"; break;
12788 case BFD_RELOC_ARM_CP_OFF_IMM
: type
= "CP_OFF_IMM"; break;
12789 case BFD_RELOC_ARM_THUMB_ADD
: type
= "THUMB_ADD"; break;
12790 case BFD_RELOC_ARM_THUMB_SHIFT
: type
= "THUMB_SHIFT"; break;
12791 case BFD_RELOC_ARM_THUMB_IMM
: type
= "THUMB_IMM"; break;
12792 case BFD_RELOC_ARM_THUMB_OFFSET
: type
= "THUMB_OFFSET"; break;
12793 default: type
= _("<unknown>"); break;
12795 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12796 _("cannot represent %s relocation in this object file format"),
12803 if ((code
== BFD_RELOC_32_PCREL
|| code
== BFD_RELOC_32
)
12805 && fixp
->fx_addsy
== GOT_symbol
)
12807 code
= BFD_RELOC_ARM_GOTPC
;
12808 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
12812 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, code
);
12814 if (reloc
->howto
== NULL
)
12816 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12817 _("cannot represent %s relocation in this object file format"),
12818 bfd_get_reloc_code_name (code
));
12822 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12823 vtable entry to be used in the relocation's section offset. */
12824 if (fixp
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
12825 reloc
->address
= fixp
->fx_offset
;
12831 md_estimate_size_before_relax (fragP
, segtype
)
12832 fragS
* fragP ATTRIBUTE_UNUSED
;
12833 segT segtype ATTRIBUTE_UNUSED
;
12835 as_fatal (_("md_estimate_size_before_relax\n"));
12847 as_bad ("%s -- `%s'", inst
.error
, str
);
12851 to
= frag_more (inst
.size
);
12853 if (thumb_mode
&& (inst
.size
> THUMB_SIZE
))
12855 assert (inst
.size
== (2 * THUMB_SIZE
));
12856 md_number_to_chars (to
, inst
.instruction
>> 16, THUMB_SIZE
);
12857 md_number_to_chars (to
+ THUMB_SIZE
, inst
.instruction
, THUMB_SIZE
);
12859 else if (inst
.size
> INSN_SIZE
)
12861 assert (inst
.size
== (2 * INSN_SIZE
));
12862 md_number_to_chars (to
, inst
.instruction
, INSN_SIZE
);
12863 md_number_to_chars (to
+ INSN_SIZE
, inst
.instruction
, INSN_SIZE
);
12866 md_number_to_chars (to
, inst
.instruction
, inst
.size
);
12868 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
12869 fix_new_arm (frag_now
, to
- frag_now
->fr_literal
,
12870 inst
.size
, & inst
.reloc
.exp
, inst
.reloc
.pc_rel
,
12874 dwarf2_emit_insn (inst
.size
);
12886 /* Align the instruction.
12887 This may not be the right thing to do but ... */
12892 /* Align the previous label if needed. */
12893 if (last_label_seen
!= NULL
)
12895 symbol_set_frag (last_label_seen
, frag_now
);
12896 S_SET_VALUE (last_label_seen
, (valueT
) frag_now_fix ());
12897 S_SET_SEGMENT (last_label_seen
, now_seg
);
12900 memset (&inst
, '\0', sizeof (inst
));
12901 inst
.reloc
.type
= BFD_RELOC_NONE
;
12903 skip_whitespace (str
);
12905 /* Scan up to the end of the op-code, which must end in white space or
12907 for (start
= p
= str
; *p
!= '\0'; p
++)
12913 as_bad (_("no operator -- statement `%s'\n"), str
);
12919 const struct thumb_opcode
* opcode
;
12923 opcode
= (const struct thumb_opcode
*) hash_find (arm_tops_hsh
, str
);
12928 /* Check that this instruction is supported for this CPU. */
12929 if (thumb_mode
== 1 && (opcode
->variant
& cpu_variant
) == 0)
12931 as_bad (_("selected processor does not support `%s'"), str
);
12935 mapping_state (MAP_THUMB
);
12936 inst
.instruction
= opcode
->value
;
12937 inst
.size
= opcode
->size
;
12938 (*opcode
->parms
) (p
);
12945 const struct asm_opcode
* opcode
;
12949 opcode
= (const struct asm_opcode
*) hash_find (arm_ops_hsh
, str
);
12954 /* Check that this instruction is supported for this CPU. */
12955 if ((opcode
->variant
& cpu_variant
) == 0)
12957 as_bad (_("selected processor does not support `%s'"), str
);
12961 mapping_state (MAP_ARM
);
12962 inst
.instruction
= opcode
->value
;
12963 inst
.size
= INSN_SIZE
;
12964 (*opcode
->parms
) (p
);
12970 /* It wasn't an instruction, but it might be a register alias of the form
12972 if (create_register_alias (str
, p
))
12975 as_bad (_("bad instruction `%s'"), start
);
12979 Invocation line includes a switch not recognized by the base assembler.
12980 See if it's a processor-specific option.
12982 This routine is somewhat complicated by the need for backwards
12983 compatibility (since older releases of gcc can't be changed).
12984 The new options try to make the interface as compatible as
12987 New options (supported) are:
12989 -mcpu=<cpu name> Assemble for selected processor
12990 -march=<architecture name> Assemble for selected architecture
12991 -mfpu=<fpu architecture> Assemble for selected FPU.
12992 -EB/-mbig-endian Big-endian
12993 -EL/-mlittle-endian Little-endian
12994 -k Generate PIC code
12995 -mthumb Start in Thumb mode
12996 -mthumb-interwork Code supports ARM/Thumb interworking
12998 For now we will also provide support for:
13000 -mapcs-32 32-bit Program counter
13001 -mapcs-26 26-bit Program counter
13002 -macps-float Floats passed in FP registers
13003 -mapcs-reentrant Reentrant code
13005 (sometime these will probably be replaced with -mapcs=<list of options>
13006 and -matpcs=<list of options>)
13008 The remaining options are only supported for back-wards compatibility.
13009 Cpu variants, the arm part is optional:
13010 -m[arm]1 Currently not supported.
13011 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
13012 -m[arm]3 Arm 3 processor
13013 -m[arm]6[xx], Arm 6 processors
13014 -m[arm]7[xx][t][[d]m] Arm 7 processors
13015 -m[arm]8[10] Arm 8 processors
13016 -m[arm]9[20][tdmi] Arm 9 processors
13017 -mstrongarm[110[0]] StrongARM processors
13018 -mxscale XScale processors
13019 -m[arm]v[2345[t[e]]] Arm architectures
13020 -mall All (except the ARM1)
13022 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
13023 -mfpe-old (No float load/store multiples)
13024 -mvfpxd VFP Single precision
13026 -mno-fpu Disable all floating point instructions
13028 The following CPU names are recognized:
13029 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
13030 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
13031 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
13032 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
13033 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
13034 arm10t arm10e, arm1020t, arm1020e, arm10200e,
13035 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
13039 const char * md_shortopts
= "m:k";
13041 #ifdef ARM_BI_ENDIAN
13042 #define OPTION_EB (OPTION_MD_BASE + 0)
13043 #define OPTION_EL (OPTION_MD_BASE + 1)
13045 #if TARGET_BYTES_BIG_ENDIAN
13046 #define OPTION_EB (OPTION_MD_BASE + 0)
13048 #define OPTION_EL (OPTION_MD_BASE + 1)
13052 struct option md_longopts
[] =
13055 {"EB", no_argument
, NULL
, OPTION_EB
},
13058 {"EL", no_argument
, NULL
, OPTION_EL
},
13060 {NULL
, no_argument
, NULL
, 0}
13063 size_t md_longopts_size
= sizeof (md_longopts
);
13065 struct arm_option_table
13067 char *option
; /* Option name to match. */
13068 char *help
; /* Help information. */
13069 int *var
; /* Variable to change. */
13070 int value
; /* What to change it to. */
13071 char *deprecated
; /* If non-null, print this message. */
13074 struct arm_option_table arm_opts
[] =
13076 {"k", N_("generate PIC code"), &pic_code
, 1, NULL
},
13077 {"mthumb", N_("assemble Thumb code"), &thumb_mode
, 1, NULL
},
13078 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
13079 &support_interwork
, 1, NULL
},
13080 {"moabi", N_("use old ABI (ELF only)"), &target_oabi
, 1, NULL
},
13081 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26
, 0, NULL
},
13082 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26
, 1, NULL
},
13083 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float
,
13085 {"mapcs-reentrant", N_("re-entrant code"), &pic_code
, 1, NULL
},
13086 {"matpcs", N_("code is ATPCS conformant"), &atpcs
, 1, NULL
},
13087 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian
, 1, NULL
},
13088 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian
, 1,
13091 /* These are recognized by the assembler, but have no affect on code. */
13092 {"mapcs-frame", N_("use frame pointer"), NULL
, 0, NULL
},
13093 {"mapcs-stack-check", N_("use stack size checking"), NULL
, 0, NULL
},
13095 /* DON'T add any new processors to this list -- we want the whole list
13096 to go away... Add them to the processors table instead. */
13097 {"marm1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
13098 {"m1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
13099 {"marm2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
13100 {"m2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
13101 {"marm250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
13102 {"m250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
13103 {"marm3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
13104 {"m3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
13105 {"marm6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
13106 {"m6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
13107 {"marm600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
13108 {"m600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
13109 {"marm610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
13110 {"m610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
13111 {"marm620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
13112 {"m620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
13113 {"marm7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
13114 {"m7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
13115 {"marm70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
13116 {"m70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
13117 {"marm700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
13118 {"m700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
13119 {"marm700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
13120 {"m700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
13121 {"marm710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
13122 {"m710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
13123 {"marm710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
13124 {"m710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
13125 {"marm720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
13126 {"m720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
13127 {"marm7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
13128 {"m7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
13129 {"marm7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
13130 {"m7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
13131 {"marm7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
13132 {"m7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
13133 {"marm7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
13134 {"m7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
13135 {"marm7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
13136 {"m7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
13137 {"marm7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
13138 {"m7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
13139 {"marm7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
13140 {"m7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
13141 {"marm7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
13142 {"m7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
13143 {"marm7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
13144 {"m7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
13145 {"marm7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
13146 {"m7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
13147 {"marm710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
13148 {"m710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
13149 {"marm720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
13150 {"m720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
13151 {"marm740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
13152 {"m740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
13153 {"marm8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
13154 {"m8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
13155 {"marm810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
13156 {"m810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
13157 {"marm9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
13158 {"m9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
13159 {"marm9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
13160 {"m9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
13161 {"marm920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
13162 {"m920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
13163 {"marm940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
13164 {"m940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
13165 {"mstrongarm", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=strongarm")},
13166 {"mstrongarm110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
13167 N_("use -mcpu=strongarm110")},
13168 {"mstrongarm1100", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
13169 N_("use -mcpu=strongarm1100")},
13170 {"mstrongarm1110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
13171 N_("use -mcpu=strongarm1110")},
13172 {"mxscale", NULL
, &legacy_cpu
, ARM_ARCH_XSCALE
, N_("use -mcpu=xscale")},
13173 {"miwmmxt", NULL
, &legacy_cpu
, ARM_ARCH_IWMMXT
, N_("use -mcpu=iwmmxt")},
13174 {"mall", NULL
, &legacy_cpu
, ARM_ANY
, N_("use -mcpu=all")},
13176 /* Architecture variants -- don't add any more to this list either. */
13177 {"mv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
13178 {"marmv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
13179 {"mv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
13180 {"marmv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
13181 {"mv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
13182 {"marmv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
13183 {"mv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
13184 {"marmv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
13185 {"mv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
13186 {"marmv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
13187 {"mv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
13188 {"marmv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
13189 {"mv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
13190 {"marmv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
13191 {"mv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
13192 {"marmv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
13193 {"mv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
13194 {"marmv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
13196 /* Floating point variants -- don't add any more to this list either. */
13197 {"mfpe-old", NULL
, &legacy_fpu
, FPU_ARCH_FPE
, N_("use -mfpu=fpe")},
13198 {"mfpa10", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa10")},
13199 {"mfpa11", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa11")},
13200 {"mno-fpu", NULL
, &legacy_fpu
, 0,
13201 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
13203 {NULL
, NULL
, NULL
, 0, NULL
}
13206 struct arm_cpu_option_table
13210 /* For some CPUs we assume an FPU unless the user explicitly sets
13215 /* This list should, at a minimum, contain all the cpu names
13216 recognized by GCC. */
13217 static struct arm_cpu_option_table arm_cpus
[] =
13219 {"all", ARM_ANY
, FPU_ARCH_FPA
},
13220 {"arm1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
13221 {"arm2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
13222 {"arm250", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
13223 {"arm3", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
13224 {"arm6", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13225 {"arm60", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13226 {"arm600", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13227 {"arm610", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13228 {"arm620", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13229 {"arm7", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13230 {"arm7m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
13231 {"arm7d", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13232 {"arm7dm", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
13233 {"arm7di", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13234 {"arm7dmi", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
13235 {"arm70", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13236 {"arm700", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13237 {"arm700i", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13238 {"arm710", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13239 {"arm710t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13240 {"arm720", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13241 {"arm720t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13242 {"arm740t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13243 {"arm710c", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13244 {"arm7100", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13245 {"arm7500", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13246 {"arm7500fe", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13247 {"arm7t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13248 {"arm7tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13249 {"arm8", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13250 {"arm810", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13251 {"strongarm", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13252 {"strongarm1", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13253 {"strongarm110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13254 {"strongarm1100", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13255 {"strongarm1110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13256 {"arm9", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13257 {"arm920", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13258 {"arm920t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13259 {"arm922t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13260 {"arm940t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13261 {"arm9tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13262 /* For V5 or later processors we default to using VFP; but the user
13263 should really set the FPU type explicitly. */
13264 {"arm9e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
13265 {"arm9e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13266 {"arm926ej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
13267 {"arm946e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
13268 {"arm946e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13269 {"arm966e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
13270 {"arm966e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13271 {"arm10t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
13272 {"arm10e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13273 {"arm1020", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13274 {"arm1020t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
13275 {"arm1020e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13276 {"arm1136js", ARM_ARCH_V6
, FPU_NONE
},
13277 {"arm1136jfs", ARM_ARCH_V6
, FPU_ARCH_VFP_V2
},
13278 /* ??? XSCALE is really an architecture. */
13279 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
13280 /* ??? iwmmxt is not a processor. */
13281 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP_V2
},
13282 {"i80200", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
13284 {"ep9312", ARM_ARCH_V4T
| ARM_CEXT_MAVERICK
, FPU_NONE
},
13288 struct arm_arch_option_table
13295 /* This list should, at a minimum, contain all the architecture names
13296 recognized by GCC. */
13297 static struct arm_arch_option_table arm_archs
[] =
13299 {"all", ARM_ANY
, FPU_ARCH_FPA
},
13300 {"armv1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
13301 {"armv2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
13302 {"armv2a", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
13303 {"armv2s", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
13304 {"armv3", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13305 {"armv3m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
13306 {"armv4", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13307 {"armv4xm", ARM_ARCH_V4xM
, FPU_ARCH_FPA
},
13308 {"armv4t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13309 {"armv4txm", ARM_ARCH_V4TxM
, FPU_ARCH_FPA
},
13310 {"armv5", ARM_ARCH_V5
, FPU_ARCH_VFP
},
13311 {"armv5t", ARM_ARCH_V5T
, FPU_ARCH_VFP
},
13312 {"armv5txm", ARM_ARCH_V5TxM
, FPU_ARCH_VFP
},
13313 {"armv5te", ARM_ARCH_V5TE
, FPU_ARCH_VFP
},
13314 {"armv5texp", ARM_ARCH_V5TExP
, FPU_ARCH_VFP
},
13315 {"armv5tej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP
},
13316 {"armv6", ARM_ARCH_V6
, FPU_ARCH_VFP
},
13317 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP
},
13318 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP
},
13322 /* ISA extensions in the co-processor space. */
13323 struct arm_arch_extension_table
13329 static struct arm_arch_extension_table arm_extensions
[] =
13331 {"maverick", ARM_CEXT_MAVERICK
},
13332 {"xscale", ARM_CEXT_XSCALE
},
13333 {"iwmmxt", ARM_CEXT_IWMMXT
},
13337 struct arm_fpu_option_table
13343 /* This list should, at a minimum, contain all the fpu names
13344 recognized by GCC. */
13345 static struct arm_fpu_option_table arm_fpus
[] =
13347 {"softfpa", FPU_NONE
},
13348 {"fpe", FPU_ARCH_FPE
},
13349 {"fpe2", FPU_ARCH_FPE
},
13350 {"fpe3", FPU_ARCH_FPA
}, /* Third release supports LFM/SFM. */
13351 {"fpa", FPU_ARCH_FPA
},
13352 {"fpa10", FPU_ARCH_FPA
},
13353 {"fpa11", FPU_ARCH_FPA
},
13354 {"arm7500fe", FPU_ARCH_FPA
},
13355 {"softvfp", FPU_ARCH_VFP
},
13356 {"softvfp+vfp", FPU_ARCH_VFP_V2
},
13357 {"vfp", FPU_ARCH_VFP_V2
},
13358 {"vfp9", FPU_ARCH_VFP_V2
},
13359 {"vfp10", FPU_ARCH_VFP_V2
},
13360 {"vfp10-r0", FPU_ARCH_VFP_V1
},
13361 {"vfpxd", FPU_ARCH_VFP_V1xD
},
13362 {"arm1020t", FPU_ARCH_VFP_V1
},
13363 {"arm1020e", FPU_ARCH_VFP_V2
},
13364 {"arm1136jfs", FPU_ARCH_VFP_V2
},
13368 struct arm_long_option_table
13370 char *option
; /* Substring to match. */
13371 char *help
; /* Help information. */
13372 int (*func
) PARAMS ((char *subopt
)); /* Function to decode sub-option. */
13373 char *deprecated
; /* If non-null, print this message. */
13377 arm_parse_extension (str
, opt_p
)
13381 while (str
!= NULL
&& *str
!= 0)
13383 struct arm_arch_extension_table
*opt
;
13389 as_bad (_("invalid architectural extension"));
13394 ext
= strchr (str
, '+');
13397 optlen
= ext
- str
;
13399 optlen
= strlen (str
);
13403 as_bad (_("missing architectural extension"));
13407 for (opt
= arm_extensions
; opt
->name
!= NULL
; opt
++)
13408 if (strncmp (opt
->name
, str
, optlen
) == 0)
13410 *opt_p
|= opt
->value
;
13414 if (opt
->name
== NULL
)
13416 as_bad (_("unknown architectural extnsion `%s'"), str
);
13427 arm_parse_cpu (str
)
13430 struct arm_cpu_option_table
*opt
;
13431 char *ext
= strchr (str
, '+');
13435 optlen
= ext
- str
;
13437 optlen
= strlen (str
);
13441 as_bad (_("missing cpu name `%s'"), str
);
13445 for (opt
= arm_cpus
; opt
->name
!= NULL
; opt
++)
13446 if (strncmp (opt
->name
, str
, optlen
) == 0)
13448 mcpu_cpu_opt
= opt
->value
;
13449 mcpu_fpu_opt
= opt
->default_fpu
;
13452 return arm_parse_extension (ext
, &mcpu_cpu_opt
);
13457 as_bad (_("unknown cpu `%s'"), str
);
13462 arm_parse_arch (str
)
13465 struct arm_arch_option_table
*opt
;
13466 char *ext
= strchr (str
, '+');
13470 optlen
= ext
- str
;
13472 optlen
= strlen (str
);
13476 as_bad (_("missing architecture name `%s'"), str
);
13481 for (opt
= arm_archs
; opt
->name
!= NULL
; opt
++)
13482 if (strcmp (opt
->name
, str
) == 0)
13484 march_cpu_opt
= opt
->value
;
13485 march_fpu_opt
= opt
->default_fpu
;
13488 return arm_parse_extension (ext
, &march_cpu_opt
);
13493 as_bad (_("unknown architecture `%s'\n"), str
);
13498 arm_parse_fpu (str
)
13501 struct arm_fpu_option_table
*opt
;
13503 for (opt
= arm_fpus
; opt
->name
!= NULL
; opt
++)
13504 if (strcmp (opt
->name
, str
) == 0)
13506 mfpu_opt
= opt
->value
;
13510 as_bad (_("unknown floating point format `%s'\n"), str
);
13514 struct arm_long_option_table arm_long_opts
[] =
13516 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13517 arm_parse_cpu
, NULL
},
13518 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13519 arm_parse_arch
, NULL
},
13520 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13521 arm_parse_fpu
, NULL
},
13522 {NULL
, NULL
, 0, NULL
}
13526 md_parse_option (c
, arg
)
13530 struct arm_option_table
*opt
;
13531 struct arm_long_option_table
*lopt
;
13537 target_big_endian
= 1;
13543 target_big_endian
= 0;
13548 /* Listing option. Just ignore these, we don't support additional
13553 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
13555 if (c
== opt
->option
[0]
13556 && ((arg
== NULL
&& opt
->option
[1] == 0)
13557 || strcmp (arg
, opt
->option
+ 1) == 0))
13559 #if WARN_DEPRECATED
13560 /* If the option is deprecated, tell the user. */
13561 if (opt
->deprecated
!= NULL
)
13562 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
,
13563 arg
? arg
: "", _(opt
->deprecated
));
13566 if (opt
->var
!= NULL
)
13567 *opt
->var
= opt
->value
;
13573 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
13575 /* These options are expected to have an argument. */
13576 if (c
== lopt
->option
[0]
13578 && strncmp (arg
, lopt
->option
+ 1,
13579 strlen (lopt
->option
+ 1)) == 0)
13581 #if WARN_DEPRECATED
13582 /* If the option is deprecated, tell the user. */
13583 if (lopt
->deprecated
!= NULL
)
13584 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
, arg
,
13585 _(lopt
->deprecated
));
13588 /* Call the sup-option parser. */
13589 return (*lopt
->func
)(arg
+ strlen (lopt
->option
) - 1);
13593 as_bad (_("unrecognized option `-%c%s'"), c
, arg
? arg
: "");
13604 struct arm_option_table
*opt
;
13605 struct arm_long_option_table
*lopt
;
13607 fprintf (fp
, _(" ARM-specific assembler options:\n"));
13609 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
13610 if (opt
->help
!= NULL
)
13611 fprintf (fp
, " -%-23s%s\n", opt
->option
, _(opt
->help
));
13613 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
13614 if (lopt
->help
!= NULL
)
13615 fprintf (fp
, " -%s%s\n", lopt
->option
, _(lopt
->help
));
13619 -EB assemble code for a big-endian cpu\n"));
13624 -EL assemble code for a little-endian cpu\n"));
13628 /* We need to be able to fix up arbitrary expressions in some statements.
13629 This is so that we can handle symbols that are an arbitrary distance from
13630 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
13631 which returns part of an address in a form which will be valid for
13632 a data instruction. We do this by pushing the expression into a symbol
13633 in the expr_section, and creating a fix for that. */
13636 fix_new_arm (frag
, where
, size
, exp
, pc_rel
, reloc
)
13645 arm_fix_data
* arm_data
;
13653 new_fix
= fix_new_exp (frag
, where
, size
, exp
, pc_rel
, reloc
);
13657 new_fix
= fix_new (frag
, where
, size
, make_expr_symbol (exp
), 0,
13662 /* Mark whether the fix is to a THUMB instruction, or an ARM
13664 arm_data
= (arm_fix_data
*) obstack_alloc (& notes
, sizeof (arm_fix_data
));
13665 new_fix
->tc_fix_data
= (PTR
) arm_data
;
13666 arm_data
->thumb_mode
= thumb_mode
;
13669 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13672 cons_fix_new_arm (frag
, where
, size
, exp
)
13678 bfd_reloc_code_real_type type
;
13682 FIXME: @@ Should look at CPU word size. */
13686 type
= BFD_RELOC_8
;
13689 type
= BFD_RELOC_16
;
13693 type
= BFD_RELOC_32
;
13696 type
= BFD_RELOC_64
;
13700 fix_new_exp (frag
, where
, (int) size
, exp
, pcrel
, type
);
13703 /* A good place to do this, although this was probably not intended
13704 for this kind of use. We need to dump the literal pool before
13705 references are made to a null symbol pointer. */
13710 literal_pool
* pool
;
13712 for (pool
= list_of_pools
; pool
; pool
= pool
->next
)
13714 /* Put it at the end of the relevent section. */
13715 subseg_set (pool
->section
, pool
->sub_section
);
13721 arm_start_line_hook ()
13723 last_label_seen
= NULL
;
13727 arm_frob_label (sym
)
13730 last_label_seen
= sym
;
13732 ARM_SET_THUMB (sym
, thumb_mode
);
13734 #if defined OBJ_COFF || defined OBJ_ELF
13735 ARM_SET_INTERWORK (sym
, support_interwork
);
13738 /* Note - do not allow local symbols (.Lxxx) to be labeled
13739 as Thumb functions. This is because these labels, whilst
13740 they exist inside Thumb code, are not the entry points for
13741 possible ARM->Thumb calls. Also, these labels can be used
13742 as part of a computed goto or switch statement. eg gcc
13743 can generate code that looks like this:
13745 ldr r2, [pc, .Laaa]
13755 The first instruction loads the address of the jump table.
13756 The second instruction converts a table index into a byte offset.
13757 The third instruction gets the jump address out of the table.
13758 The fourth instruction performs the jump.
13760 If the address stored at .Laaa is that of a symbol which has the
13761 Thumb_Func bit set, then the linker will arrange for this address
13762 to have the bottom bit set, which in turn would mean that the
13763 address computation performed by the third instruction would end
13764 up with the bottom bit set. Since the ARM is capable of unaligned
13765 word loads, the instruction would then load the incorrect address
13766 out of the jump table, and chaos would ensue. */
13767 if (label_is_thumb_function_name
13768 && (S_GET_NAME (sym
)[0] != '.' || S_GET_NAME (sym
)[1] != 'L')
13769 && (bfd_get_section_flags (stdoutput
, now_seg
) & SEC_CODE
) != 0)
13771 /* When the address of a Thumb function is taken the bottom
13772 bit of that address should be set. This will allow
13773 interworking between Arm and Thumb functions to work
13776 THUMB_SET_FUNC (sym
, 1);
13778 label_is_thumb_function_name
= FALSE
;
13782 /* Adjust the symbol table. This marks Thumb symbols as distinct from
13786 arm_adjust_symtab ()
13791 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
13793 if (ARM_IS_THUMB (sym
))
13795 if (THUMB_IS_FUNC (sym
))
13797 /* Mark the symbol as a Thumb function. */
13798 if ( S_GET_STORAGE_CLASS (sym
) == C_STAT
13799 || S_GET_STORAGE_CLASS (sym
) == C_LABEL
) /* This can happen! */
13800 S_SET_STORAGE_CLASS (sym
, C_THUMBSTATFUNC
);
13802 else if (S_GET_STORAGE_CLASS (sym
) == C_EXT
)
13803 S_SET_STORAGE_CLASS (sym
, C_THUMBEXTFUNC
);
13805 as_bad (_("%s: unexpected function type: %d"),
13806 S_GET_NAME (sym
), S_GET_STORAGE_CLASS (sym
));
13808 else switch (S_GET_STORAGE_CLASS (sym
))
13811 S_SET_STORAGE_CLASS (sym
, C_THUMBEXT
);
13814 S_SET_STORAGE_CLASS (sym
, C_THUMBSTAT
);
13817 S_SET_STORAGE_CLASS (sym
, C_THUMBLABEL
);
13825 if (ARM_IS_INTERWORK (sym
))
13826 coffsymbol (symbol_get_bfdsym (sym
))->native
->u
.syment
.n_flags
= 0xFF;
13833 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
13835 if (ARM_IS_THUMB (sym
))
13837 elf_symbol_type
* elf_sym
;
13839 elf_sym
= elf_symbol (symbol_get_bfdsym (sym
));
13840 bind
= ELF_ST_BIND (elf_sym
);
13842 /* If it's a .thumb_func, declare it as so,
13843 otherwise tag label as .code 16. */
13844 if (THUMB_IS_FUNC (sym
))
13845 elf_sym
->internal_elf_sym
.st_info
=
13846 ELF_ST_INFO (bind
, STT_ARM_TFUNC
);
13848 elf_sym
->internal_elf_sym
.st_info
=
13849 ELF_ST_INFO (bind
, STT_ARM_16BIT
);
13856 arm_data_in_code ()
13858 if (thumb_mode
&& ! strncmp (input_line_pointer
+ 1, "data:", 5))
13860 *input_line_pointer
= '/';
13861 input_line_pointer
+= 5;
13862 *input_line_pointer
= 0;
13870 arm_canonicalize_symbol_name (name
)
13875 if (thumb_mode
&& (len
= strlen (name
)) > 5
13876 && streq (name
+ len
- 5, "/data"))
13877 *(name
+ len
- 5) = 0;
13882 #if defined OBJ_COFF || defined OBJ_ELF
13884 arm_validate_fix (fixP
)
13887 /* If the destination of the branch is a defined symbol which does not have
13888 the THUMB_FUNC attribute, then we must be calling a function which has
13889 the (interfacearm) attribute. We look for the Thumb entry point to that
13890 function and change the branch to refer to that function instead. */
13891 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
13892 && fixP
->fx_addsy
!= NULL
13893 && S_IS_DEFINED (fixP
->fx_addsy
)
13894 && ! THUMB_IS_FUNC (fixP
->fx_addsy
))
13896 fixP
->fx_addsy
= find_real_start (fixP
->fx_addsy
);
13902 arm_force_relocation (fixp
)
13905 #if defined (OBJ_COFF) && defined (TE_PE)
13906 if (fixp
->fx_r_type
== BFD_RELOC_RVA
)
13910 if (fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
13911 || fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
13912 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
13913 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
)
13917 /* Resolve these relocations even if the symbol is extern or weak. */
13918 if (fixp
->fx_r_type
== BFD_RELOC_ARM_IMMEDIATE
13919 || fixp
->fx_r_type
== BFD_RELOC_ARM_OFFSET_IMM
13920 || fixp
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
13923 return generic_force_reloc (fixp
);
13927 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
13928 local labels from being added to the output symbol table when they
13929 are used with the ADRL pseudo op. The ADRL relocation should always
13930 be resolved before the binbary is emitted, so it is safe to say that
13931 it is adjustable. */
13934 arm_fix_adjustable (fixP
)
13937 if (fixP
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
13944 /* Relocations against Thumb function names must be left unadjusted,
13945 so that the linker can use this information to correctly set the
13946 bottom bit of their addresses. The MIPS version of this function
13947 also prevents relocations that are mips-16 specific, but I do not
13948 know why it does this.
13951 There is one other problem that ought to be addressed here, but
13952 which currently is not: Taking the address of a label (rather
13953 than a function) and then later jumping to that address. Such
13954 addresses also ought to have their bottom bit set (assuming that
13955 they reside in Thumb code), but at the moment they will not. */
13958 arm_fix_adjustable (fixP
)
13961 if (fixP
->fx_addsy
== NULL
)
13964 if (THUMB_IS_FUNC (fixP
->fx_addsy
)
13965 && fixP
->fx_subsy
== NULL
)
13968 /* We need the symbol name for the VTABLE entries. */
13969 if ( fixP
->fx_r_type
== BFD_RELOC_VTABLE_INHERIT
13970 || fixP
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
13973 /* Don't allow symbols to be discarded on GOT related relocs. */
13974 if (fixP
->fx_r_type
== BFD_RELOC_ARM_PLT32
13975 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOT32
13976 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOTOFF
)
13983 elf32_arm_target_format ()
13985 if (target_big_endian
)
13988 return "elf32-bigarm-oabi";
13990 return "elf32-bigarm";
13995 return "elf32-littlearm-oabi";
13997 return "elf32-littlearm";
14002 armelf_frob_symbol (symp
, puntp
)
14006 elf_frob_symbol (symp
, puntp
);
14009 static bfd_reloc_code_real_type
14019 bfd_reloc_code_real_type reloc
;
14023 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
14024 MAP ("(got)", BFD_RELOC_ARM_GOT32
),
14025 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF
),
14026 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
14027 branch instructions generated by GCC for PLT relocs. */
14028 MAP ("(plt)", BFD_RELOC_ARM_PLT32
),
14029 { NULL
, 0, BFD_RELOC_UNUSED
}
14033 for (i
= 0, ip
= input_line_pointer
;
14034 i
< sizeof (id
) && (ISALNUM (*ip
) || ISPUNCT (*ip
));
14036 id
[i
] = TOLOWER (*ip
);
14038 for (i
= 0; reloc_map
[i
].str
; i
++)
14039 if (strncmp (id
, reloc_map
[i
].str
, reloc_map
[i
].len
) == 0)
14042 input_line_pointer
+= reloc_map
[i
].len
;
14044 return reloc_map
[i
].reloc
;
14048 s_arm_elf_cons (nbytes
)
14053 #ifdef md_flush_pending_output
14054 md_flush_pending_output ();
14057 if (is_it_end_of_statement ())
14059 demand_empty_rest_of_line ();
14063 #ifdef md_cons_align
14064 md_cons_align (nbytes
);
14067 mapping_state (MAP_DATA
);
14070 bfd_reloc_code_real_type reloc
;
14072 expression (& exp
);
14074 if (exp
.X_op
== O_symbol
14075 && * input_line_pointer
== '('
14076 && (reloc
= arm_parse_reloc ()) != BFD_RELOC_UNUSED
)
14078 reloc_howto_type
*howto
= bfd_reloc_type_lookup (stdoutput
, reloc
);
14079 int size
= bfd_get_reloc_size (howto
);
14082 as_bad ("%s relocations do not fit in %d bytes",
14083 howto
->name
, nbytes
);
14086 register char *p
= frag_more ((int) nbytes
);
14087 int offset
= nbytes
- size
;
14089 fix_new_exp (frag_now
, p
- frag_now
->fr_literal
+ offset
, size
,
14094 emit_expr (&exp
, (unsigned int) nbytes
);
14096 while (*input_line_pointer
++ == ',');
14098 /* Put terminator back into stream. */
14099 input_line_pointer
--;
14100 demand_empty_rest_of_line ();
14103 #endif /* OBJ_ELF */
14105 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
14106 of an rs_align_code fragment. */
14109 arm_handle_align (fragP
)
14112 static char const arm_noop
[4] = { 0x00, 0x00, 0xa0, 0xe1 };
14113 static char const thumb_noop
[2] = { 0xc0, 0x46 };
14114 static char const arm_bigend_noop
[4] = { 0xe1, 0xa0, 0x00, 0x00 };
14115 static char const thumb_bigend_noop
[2] = { 0x46, 0xc0 };
14117 int bytes
, fix
, noop_size
;
14121 if (fragP
->fr_type
!= rs_align_code
)
14124 bytes
= fragP
->fr_next
->fr_address
- fragP
->fr_address
- fragP
->fr_fix
;
14125 p
= fragP
->fr_literal
+ fragP
->fr_fix
;
14128 if (bytes
> MAX_MEM_FOR_RS_ALIGN_CODE
)
14129 bytes
&= MAX_MEM_FOR_RS_ALIGN_CODE
;
14131 if (fragP
->tc_frag_data
)
14133 if (target_big_endian
)
14134 noop
= thumb_bigend_noop
;
14137 noop_size
= sizeof (thumb_noop
);
14141 if (target_big_endian
)
14142 noop
= arm_bigend_noop
;
14145 noop_size
= sizeof (arm_noop
);
14148 if (bytes
& (noop_size
- 1))
14150 fix
= bytes
& (noop_size
- 1);
14151 memset (p
, 0, fix
);
14156 while (bytes
>= noop_size
)
14158 memcpy (p
, noop
, noop_size
);
14160 bytes
-= noop_size
;
14164 fragP
->fr_fix
+= fix
;
14165 fragP
->fr_var
= noop_size
;
14168 /* Called from md_do_align. Used to create an alignment
14169 frag in a code section. */
14172 arm_frag_align_code (n
, max
)
14178 /* We assume that there will never be a requirement
14179 to support alignments greater than 32 bytes. */
14180 if (max
> MAX_MEM_FOR_RS_ALIGN_CODE
)
14181 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
14183 p
= frag_var (rs_align_code
,
14184 MAX_MEM_FOR_RS_ALIGN_CODE
,
14186 (relax_substateT
) max
,
14194 /* Perform target specific initialisation of a frag. */
14197 arm_init_frag (fragP
)
14200 /* Record whether this frag is in an ARM or a THUMB area. */
14201 fragP
->tc_frag_data
= thumb_mode
;