1 /* tc-arm.c -- Assemble for the ARM
2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
3 Free Software Foundation, Inc.
4 Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
5 Modified by David Taylor (dtaylor@armltd.co.uk)
6 Cirrus coprocessor mods by Aldy Hernandez (aldyh@redhat.com)
8 This file is part of GAS, the GNU Assembler.
10 GAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
15 GAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with GAS; see the file COPYING. If not, write to the Free
22 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
28 #include "safe-ctype.h"
30 /* Need TARGET_CPU. */
39 #include "dwarf2dbg.h"
42 /* XXX Set this to 1 after the next binutils release */
43 #define WARN_DEPRECATED 0
45 /* The following bitmasks control CPU extensions: */
46 #define ARM_EXT_V1 0x00000001 /* All processors (core set). */
47 #define ARM_EXT_V2 0x00000002 /* Multiply instructions. */
48 #define ARM_EXT_V2S 0x00000004 /* SWP instructions. */
49 #define ARM_EXT_V3 0x00000008 /* MSR MRS. */
50 #define ARM_EXT_V3M 0x00000010 /* Allow long multiplies. */
51 #define ARM_EXT_V4 0x00000020 /* Allow half word loads. */
52 #define ARM_EXT_V4T 0x00000040 /* Thumb v1. */
53 #define ARM_EXT_V5 0x00000080 /* Allow CLZ, etc. */
54 #define ARM_EXT_V5T 0x00000100 /* Thumb v2. */
55 #define ARM_EXT_V5ExP 0x00000200 /* DSP core set. */
56 #define ARM_EXT_V5E 0x00000400 /* DSP Double transfers. */
57 #define ARM_EXT_V5J 0x00000800 /* Jazelle extension. */
59 /* Co-processor space extensions. */
60 #define ARM_CEXT_XSCALE 0x00800000 /* Allow MIA etc. */
61 #define ARM_CEXT_MAVERICK 0x00400000 /* Use Cirrus/DSP coprocessor. */
62 #define ARM_CEXT_IWMMXT 0x00200000 /* Intel Wireless MMX technology coprocessor. */
64 /* Architectures are the sum of the base and extensions. The ARM ARM (rev E)
65 defines the following: ARMv3, ARMv3M, ARMv4xM, ARMv4, ARMv4TxM, ARMv4T,
66 ARMv5xM, ARMv5, ARMv5TxM, ARMv5T, ARMv5TExP, ARMv5TE. To these we add
67 three more to cover cores prior to ARM6. Finally, there are cores which
68 implement further extensions in the co-processor space. */
69 #define ARM_ARCH_V1 ARM_EXT_V1
70 #define ARM_ARCH_V2 (ARM_ARCH_V1 | ARM_EXT_V2)
71 #define ARM_ARCH_V2S (ARM_ARCH_V2 | ARM_EXT_V2S)
72 #define ARM_ARCH_V3 (ARM_ARCH_V2S | ARM_EXT_V3)
73 #define ARM_ARCH_V3M (ARM_ARCH_V3 | ARM_EXT_V3M)
74 #define ARM_ARCH_V4xM (ARM_ARCH_V3 | ARM_EXT_V4)
75 #define ARM_ARCH_V4 (ARM_ARCH_V3M | ARM_EXT_V4)
76 #define ARM_ARCH_V4TxM (ARM_ARCH_V4xM | ARM_EXT_V4T)
77 #define ARM_ARCH_V4T (ARM_ARCH_V4 | ARM_EXT_V4T)
78 #define ARM_ARCH_V5xM (ARM_ARCH_V4xM | ARM_EXT_V5)
79 #define ARM_ARCH_V5 (ARM_ARCH_V4 | ARM_EXT_V5)
80 #define ARM_ARCH_V5TxM (ARM_ARCH_V5xM | ARM_EXT_V4T | ARM_EXT_V5T)
81 #define ARM_ARCH_V5T (ARM_ARCH_V5 | ARM_EXT_V4T | ARM_EXT_V5T)
82 #define ARM_ARCH_V5TExP (ARM_ARCH_V5T | ARM_EXT_V5ExP)
83 #define ARM_ARCH_V5TE (ARM_ARCH_V5TExP | ARM_EXT_V5E)
84 #define ARM_ARCH_V5TEJ (ARM_ARCH_V5TE | ARM_EXT_V5J)
86 /* Processors with specific extensions in the co-processor space. */
87 #define ARM_ARCH_XSCALE (ARM_ARCH_V5TE | ARM_CEXT_XSCALE)
88 #define ARM_ARCH_IWMMXT (ARM_ARCH_XSCALE | ARM_CEXT_IWMMXT)
90 /* Some useful combinations: */
91 #define ARM_ANY 0x0000ffff /* Any basic core. */
92 #define ARM_ALL 0x00ffffff /* Any core + co-processor */
93 #define CPROC_ANY 0x00ff0000 /* Any co-processor */
94 #define FPU_ANY 0xff000000 /* Note this is ~ARM_ALL. */
97 #define FPU_FPA_EXT_V1 0x80000000 /* Base FPA instruction set. */
98 #define FPU_FPA_EXT_V2 0x40000000 /* LFM/SFM. */
99 #define FPU_VFP_EXT_NONE 0x20000000 /* Use VFP word-ordering. */
100 #define FPU_VFP_EXT_V1xD 0x10000000 /* Base VFP instruction set. */
101 #define FPU_VFP_EXT_V1 0x08000000 /* Double-precision insns. */
102 #define FPU_VFP_EXT_V2 0x04000000 /* ARM10E VFPr1. */
105 #define FPU_ARCH_FPE FPU_FPA_EXT_V1
106 #define FPU_ARCH_FPA (FPU_ARCH_FPE | FPU_FPA_EXT_V2)
108 #define FPU_ARCH_VFP FPU_VFP_EXT_NONE
109 #define FPU_ARCH_VFP_V1xD (FPU_VFP_EXT_V1xD | FPU_VFP_EXT_NONE)
110 #define FPU_ARCH_VFP_V1 (FPU_ARCH_VFP_V1xD | FPU_VFP_EXT_V1)
111 #define FPU_ARCH_VFP_V2 (FPU_ARCH_VFP_V1 | FPU_VFP_EXT_V2)
113 /* Types of processor to assemble for. */
114 #define ARM_1 ARM_ARCH_V1
115 #define ARM_2 ARM_ARCH_V2
116 #define ARM_3 ARM_ARCH_V2S
117 #define ARM_250 ARM_ARCH_V2S
118 #define ARM_6 ARM_ARCH_V3
119 #define ARM_7 ARM_ARCH_V3
120 #define ARM_8 ARM_ARCH_V4
121 #define ARM_9 ARM_ARCH_V4T
122 #define ARM_STRONG ARM_ARCH_V4
123 #define ARM_CPU_MASK 0x0000000f /* XXX? */
126 #if defined __XSCALE__
127 #define CPU_DEFAULT (ARM_ARCH_XSCALE)
129 #if defined __thumb__
130 #define CPU_DEFAULT (ARM_ARCH_V5T)
132 #define CPU_DEFAULT ARM_ANY
138 #define FPU_DEFAULT FPU_ARCH_FPA
143 #define FPU_DEFAULT FPU_ARCH_VFP /* Soft-float, but VFP order. */
145 /* Legacy a.out format. */
146 #define FPU_DEFAULT FPU_ARCH_FPA /* Soft-float, but FPA order. */
150 /* For backwards compatibility we default to the FPA. */
152 #define FPU_DEFAULT FPU_ARCH_FPA
155 #define streq(a, b) (strcmp (a, b) == 0)
156 #define skip_whitespace(str) while (*(str) == ' ') ++(str)
158 static unsigned long cpu_variant
;
159 static int target_oabi
= 0;
161 /* Flags stored in private area of BFD structure. */
162 static int uses_apcs_26
= FALSE
;
163 static int atpcs
= FALSE
;
164 static int support_interwork
= FALSE
;
165 static int uses_apcs_float
= FALSE
;
166 static int pic_code
= FALSE
;
168 /* Variables that we set while parsing command-line options. Once all
169 options have been read we re-process these values to set the real
171 static int legacy_cpu
= -1;
172 static int legacy_fpu
= -1;
174 static int mcpu_cpu_opt
= -1;
175 static int mcpu_fpu_opt
= -1;
176 static int march_cpu_opt
= -1;
177 static int march_fpu_opt
= -1;
178 static int mfpu_opt
= -1;
180 /* This array holds the chars that always start a comment. If the
181 pre-processor is disabled, these aren't very useful. */
182 const char comment_chars
[] = "@";
184 /* This array holds the chars that only start a comment at the beginning of
185 a line. If the line seems to have the form '# 123 filename'
186 .line and .file directives will appear in the pre-processed output. */
187 /* Note that input_file.c hand checks for '#' at the beginning of the
188 first line of the input file. This is because the compiler outputs
189 #NO_APP at the beginning of its output. */
190 /* Also note that comments like this one will always work. */
191 const char line_comment_chars
[] = "#";
193 const char line_separator_chars
[] = ";";
195 /* Chars that can be used to separate mant
196 from exp in floating point numbers. */
197 const char EXP_CHARS
[] = "eE";
199 /* Chars that mean this number is a floating point constant. */
203 const char FLT_CHARS
[] = "rRsSfFdDxXeEpP";
205 /* Prefix characters that indicate the start of an immediate
207 #define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
210 /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
211 symbolS
* GOT_symbol
;
214 /* Size of relocation record. */
215 const int md_reloc_size
= 8;
217 /* 0: assemble for ARM,
218 1: assemble for Thumb,
219 2: assemble for Thumb even though target CPU does not support thumb
221 static int thumb_mode
= 0;
223 typedef struct arm_fix
231 unsigned long instruction
;
235 bfd_reloc_code_real_type type
;
252 struct asm_shift_properties
254 enum asm_shift_index index
;
255 unsigned long bit_field
;
256 unsigned int allows_0
: 1;
257 unsigned int allows_32
: 1;
260 static const struct asm_shift_properties shift_properties
[] =
262 { SHIFT_LSL
, 0, 1, 0},
263 { SHIFT_LSR
, 0x20, 0, 1},
264 { SHIFT_ASR
, 0x40, 0, 1},
265 { SHIFT_ROR
, 0x60, 0, 0},
266 { SHIFT_RRX
, 0x60, 0, 0}
269 struct asm_shift_name
272 const struct asm_shift_properties
* properties
;
275 static const struct asm_shift_name shift_names
[] =
277 { "asl", shift_properties
+ SHIFT_LSL
},
278 { "lsl", shift_properties
+ SHIFT_LSL
},
279 { "lsr", shift_properties
+ SHIFT_LSR
},
280 { "asr", shift_properties
+ SHIFT_ASR
},
281 { "ror", shift_properties
+ SHIFT_ROR
},
282 { "rrx", shift_properties
+ SHIFT_RRX
},
283 { "ASL", shift_properties
+ SHIFT_LSL
},
284 { "LSL", shift_properties
+ SHIFT_LSL
},
285 { "LSR", shift_properties
+ SHIFT_LSR
},
286 { "ASR", shift_properties
+ SHIFT_ASR
},
287 { "ROR", shift_properties
+ SHIFT_ROR
},
288 { "RRX", shift_properties
+ SHIFT_RRX
}
291 #define NO_SHIFT_RESTRICT 1
292 #define SHIFT_RESTRICT 0
294 #define NUM_FLOAT_VALS 8
296 const char * fp_const
[] =
298 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
301 /* Number of littlenums required to hold an extended precision number. */
302 #define MAX_LITTLENUMS 6
304 LITTLENUM_TYPE fp_values
[NUM_FLOAT_VALS
][MAX_LITTLENUMS
];
309 /* Whether a Co-processor load/store operation accepts write-back forms. */
318 #define CP_T_X 0x00008000
319 #define CP_T_Y 0x00400000
320 #define CP_T_Pre 0x01000000
321 #define CP_T_UD 0x00800000
322 #define CP_T_WB 0x00200000
324 #define CONDS_BIT 0x00100000
325 #define LOAD_BIT 0x00100000
327 #define DOUBLE_LOAD_FLAG 0x00000001
331 const char * template;
335 #define COND_ALWAYS 0xe0000000
336 #define COND_MASK 0xf0000000
338 static const struct asm_cond conds
[] =
342 {"cs", 0x20000000}, {"hs", 0x20000000},
343 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
360 const char *template;
365 /* The bit that distnguishes CPSR and SPSR. */
366 #define SPSR_BIT (1 << 22)
368 /* How many bits to shift the PSR_xxx bits up by. */
371 #define PSR_c (1 << 0)
372 #define PSR_x (1 << 1)
373 #define PSR_s (1 << 2)
374 #define PSR_f (1 << 3)
376 static const struct asm_psr psrs
[] =
378 {"CPSR", TRUE
, PSR_c
| PSR_f
},
379 {"CPSR_all", TRUE
, PSR_c
| PSR_f
},
380 {"SPSR", FALSE
, PSR_c
| PSR_f
},
381 {"SPSR_all", FALSE
, PSR_c
| PSR_f
},
382 {"CPSR_flg", TRUE
, PSR_f
},
383 {"CPSR_f", TRUE
, PSR_f
},
384 {"SPSR_flg", FALSE
, PSR_f
},
385 {"SPSR_f", FALSE
, PSR_f
},
386 {"CPSR_c", TRUE
, PSR_c
},
387 {"CPSR_ctl", TRUE
, PSR_c
},
388 {"SPSR_c", FALSE
, PSR_c
},
389 {"SPSR_ctl", FALSE
, PSR_c
},
390 {"CPSR_x", TRUE
, PSR_x
},
391 {"CPSR_s", TRUE
, PSR_s
},
392 {"SPSR_x", FALSE
, PSR_x
},
393 {"SPSR_s", FALSE
, PSR_s
},
394 /* Combinations of flags. */
395 {"CPSR_fs", TRUE
, PSR_f
| PSR_s
},
396 {"CPSR_fx", TRUE
, PSR_f
| PSR_x
},
397 {"CPSR_fc", TRUE
, PSR_f
| PSR_c
},
398 {"CPSR_sf", TRUE
, PSR_s
| PSR_f
},
399 {"CPSR_sx", TRUE
, PSR_s
| PSR_x
},
400 {"CPSR_sc", TRUE
, PSR_s
| PSR_c
},
401 {"CPSR_xf", TRUE
, PSR_x
| PSR_f
},
402 {"CPSR_xs", TRUE
, PSR_x
| PSR_s
},
403 {"CPSR_xc", TRUE
, PSR_x
| PSR_c
},
404 {"CPSR_cf", TRUE
, PSR_c
| PSR_f
},
405 {"CPSR_cs", TRUE
, PSR_c
| PSR_s
},
406 {"CPSR_cx", TRUE
, PSR_c
| PSR_x
},
407 {"CPSR_fsx", TRUE
, PSR_f
| PSR_s
| PSR_x
},
408 {"CPSR_fsc", TRUE
, PSR_f
| PSR_s
| PSR_c
},
409 {"CPSR_fxs", TRUE
, PSR_f
| PSR_x
| PSR_s
},
410 {"CPSR_fxc", TRUE
, PSR_f
| PSR_x
| PSR_c
},
411 {"CPSR_fcs", TRUE
, PSR_f
| PSR_c
| PSR_s
},
412 {"CPSR_fcx", TRUE
, PSR_f
| PSR_c
| PSR_x
},
413 {"CPSR_sfx", TRUE
, PSR_s
| PSR_f
| PSR_x
},
414 {"CPSR_sfc", TRUE
, PSR_s
| PSR_f
| PSR_c
},
415 {"CPSR_sxf", TRUE
, PSR_s
| PSR_x
| PSR_f
},
416 {"CPSR_sxc", TRUE
, PSR_s
| PSR_x
| PSR_c
},
417 {"CPSR_scf", TRUE
, PSR_s
| PSR_c
| PSR_f
},
418 {"CPSR_scx", TRUE
, PSR_s
| PSR_c
| PSR_x
},
419 {"CPSR_xfs", TRUE
, PSR_x
| PSR_f
| PSR_s
},
420 {"CPSR_xfc", TRUE
, PSR_x
| PSR_f
| PSR_c
},
421 {"CPSR_xsf", TRUE
, PSR_x
| PSR_s
| PSR_f
},
422 {"CPSR_xsc", TRUE
, PSR_x
| PSR_s
| PSR_c
},
423 {"CPSR_xcf", TRUE
, PSR_x
| PSR_c
| PSR_f
},
424 {"CPSR_xcs", TRUE
, PSR_x
| PSR_c
| PSR_s
},
425 {"CPSR_cfs", TRUE
, PSR_c
| PSR_f
| PSR_s
},
426 {"CPSR_cfx", TRUE
, PSR_c
| PSR_f
| PSR_x
},
427 {"CPSR_csf", TRUE
, PSR_c
| PSR_s
| PSR_f
},
428 {"CPSR_csx", TRUE
, PSR_c
| PSR_s
| PSR_x
},
429 {"CPSR_cxf", TRUE
, PSR_c
| PSR_x
| PSR_f
},
430 {"CPSR_cxs", TRUE
, PSR_c
| PSR_x
| PSR_s
},
431 {"CPSR_fsxc", TRUE
, PSR_f
| PSR_s
| PSR_x
| PSR_c
},
432 {"CPSR_fscx", TRUE
, PSR_f
| PSR_s
| PSR_c
| PSR_x
},
433 {"CPSR_fxsc", TRUE
, PSR_f
| PSR_x
| PSR_s
| PSR_c
},
434 {"CPSR_fxcs", TRUE
, PSR_f
| PSR_x
| PSR_c
| PSR_s
},
435 {"CPSR_fcsx", TRUE
, PSR_f
| PSR_c
| PSR_s
| PSR_x
},
436 {"CPSR_fcxs", TRUE
, PSR_f
| PSR_c
| PSR_x
| PSR_s
},
437 {"CPSR_sfxc", TRUE
, PSR_s
| PSR_f
| PSR_x
| PSR_c
},
438 {"CPSR_sfcx", TRUE
, PSR_s
| PSR_f
| PSR_c
| PSR_x
},
439 {"CPSR_sxfc", TRUE
, PSR_s
| PSR_x
| PSR_f
| PSR_c
},
440 {"CPSR_sxcf", TRUE
, PSR_s
| PSR_x
| PSR_c
| PSR_f
},
441 {"CPSR_scfx", TRUE
, PSR_s
| PSR_c
| PSR_f
| PSR_x
},
442 {"CPSR_scxf", TRUE
, PSR_s
| PSR_c
| PSR_x
| PSR_f
},
443 {"CPSR_xfsc", TRUE
, PSR_x
| PSR_f
| PSR_s
| PSR_c
},
444 {"CPSR_xfcs", TRUE
, PSR_x
| PSR_f
| PSR_c
| PSR_s
},
445 {"CPSR_xsfc", TRUE
, PSR_x
| PSR_s
| PSR_f
| PSR_c
},
446 {"CPSR_xscf", TRUE
, PSR_x
| PSR_s
| PSR_c
| PSR_f
},
447 {"CPSR_xcfs", TRUE
, PSR_x
| PSR_c
| PSR_f
| PSR_s
},
448 {"CPSR_xcsf", TRUE
, PSR_x
| PSR_c
| PSR_s
| PSR_f
},
449 {"CPSR_cfsx", TRUE
, PSR_c
| PSR_f
| PSR_s
| PSR_x
},
450 {"CPSR_cfxs", TRUE
, PSR_c
| PSR_f
| PSR_x
| PSR_s
},
451 {"CPSR_csfx", TRUE
, PSR_c
| PSR_s
| PSR_f
| PSR_x
},
452 {"CPSR_csxf", TRUE
, PSR_c
| PSR_s
| PSR_x
| PSR_f
},
453 {"CPSR_cxfs", TRUE
, PSR_c
| PSR_x
| PSR_f
| PSR_s
},
454 {"CPSR_cxsf", TRUE
, PSR_c
| PSR_x
| PSR_s
| PSR_f
},
455 {"SPSR_fs", FALSE
, PSR_f
| PSR_s
},
456 {"SPSR_fx", FALSE
, PSR_f
| PSR_x
},
457 {"SPSR_fc", FALSE
, PSR_f
| PSR_c
},
458 {"SPSR_sf", FALSE
, PSR_s
| PSR_f
},
459 {"SPSR_sx", FALSE
, PSR_s
| PSR_x
},
460 {"SPSR_sc", FALSE
, PSR_s
| PSR_c
},
461 {"SPSR_xf", FALSE
, PSR_x
| PSR_f
},
462 {"SPSR_xs", FALSE
, PSR_x
| PSR_s
},
463 {"SPSR_xc", FALSE
, PSR_x
| PSR_c
},
464 {"SPSR_cf", FALSE
, PSR_c
| PSR_f
},
465 {"SPSR_cs", FALSE
, PSR_c
| PSR_s
},
466 {"SPSR_cx", FALSE
, PSR_c
| PSR_x
},
467 {"SPSR_fsx", FALSE
, PSR_f
| PSR_s
| PSR_x
},
468 {"SPSR_fsc", FALSE
, PSR_f
| PSR_s
| PSR_c
},
469 {"SPSR_fxs", FALSE
, PSR_f
| PSR_x
| PSR_s
},
470 {"SPSR_fxc", FALSE
, PSR_f
| PSR_x
| PSR_c
},
471 {"SPSR_fcs", FALSE
, PSR_f
| PSR_c
| PSR_s
},
472 {"SPSR_fcx", FALSE
, PSR_f
| PSR_c
| PSR_x
},
473 {"SPSR_sfx", FALSE
, PSR_s
| PSR_f
| PSR_x
},
474 {"SPSR_sfc", FALSE
, PSR_s
| PSR_f
| PSR_c
},
475 {"SPSR_sxf", FALSE
, PSR_s
| PSR_x
| PSR_f
},
476 {"SPSR_sxc", FALSE
, PSR_s
| PSR_x
| PSR_c
},
477 {"SPSR_scf", FALSE
, PSR_s
| PSR_c
| PSR_f
},
478 {"SPSR_scx", FALSE
, PSR_s
| PSR_c
| PSR_x
},
479 {"SPSR_xfs", FALSE
, PSR_x
| PSR_f
| PSR_s
},
480 {"SPSR_xfc", FALSE
, PSR_x
| PSR_f
| PSR_c
},
481 {"SPSR_xsf", FALSE
, PSR_x
| PSR_s
| PSR_f
},
482 {"SPSR_xsc", FALSE
, PSR_x
| PSR_s
| PSR_c
},
483 {"SPSR_xcf", FALSE
, PSR_x
| PSR_c
| PSR_f
},
484 {"SPSR_xcs", FALSE
, PSR_x
| PSR_c
| PSR_s
},
485 {"SPSR_cfs", FALSE
, PSR_c
| PSR_f
| PSR_s
},
486 {"SPSR_cfx", FALSE
, PSR_c
| PSR_f
| PSR_x
},
487 {"SPSR_csf", FALSE
, PSR_c
| PSR_s
| PSR_f
},
488 {"SPSR_csx", FALSE
, PSR_c
| PSR_s
| PSR_x
},
489 {"SPSR_cxf", FALSE
, PSR_c
| PSR_x
| PSR_f
},
490 {"SPSR_cxs", FALSE
, PSR_c
| PSR_x
| PSR_s
},
491 {"SPSR_fsxc", FALSE
, PSR_f
| PSR_s
| PSR_x
| PSR_c
},
492 {"SPSR_fscx", FALSE
, PSR_f
| PSR_s
| PSR_c
| PSR_x
},
493 {"SPSR_fxsc", FALSE
, PSR_f
| PSR_x
| PSR_s
| PSR_c
},
494 {"SPSR_fxcs", FALSE
, PSR_f
| PSR_x
| PSR_c
| PSR_s
},
495 {"SPSR_fcsx", FALSE
, PSR_f
| PSR_c
| PSR_s
| PSR_x
},
496 {"SPSR_fcxs", FALSE
, PSR_f
| PSR_c
| PSR_x
| PSR_s
},
497 {"SPSR_sfxc", FALSE
, PSR_s
| PSR_f
| PSR_x
| PSR_c
},
498 {"SPSR_sfcx", FALSE
, PSR_s
| PSR_f
| PSR_c
| PSR_x
},
499 {"SPSR_sxfc", FALSE
, PSR_s
| PSR_x
| PSR_f
| PSR_c
},
500 {"SPSR_sxcf", FALSE
, PSR_s
| PSR_x
| PSR_c
| PSR_f
},
501 {"SPSR_scfx", FALSE
, PSR_s
| PSR_c
| PSR_f
| PSR_x
},
502 {"SPSR_scxf", FALSE
, PSR_s
| PSR_c
| PSR_x
| PSR_f
},
503 {"SPSR_xfsc", FALSE
, PSR_x
| PSR_f
| PSR_s
| PSR_c
},
504 {"SPSR_xfcs", FALSE
, PSR_x
| PSR_f
| PSR_c
| PSR_s
},
505 {"SPSR_xsfc", FALSE
, PSR_x
| PSR_s
| PSR_f
| PSR_c
},
506 {"SPSR_xscf", FALSE
, PSR_x
| PSR_s
| PSR_c
| PSR_f
},
507 {"SPSR_xcfs", FALSE
, PSR_x
| PSR_c
| PSR_f
| PSR_s
},
508 {"SPSR_xcsf", FALSE
, PSR_x
| PSR_c
| PSR_s
| PSR_f
},
509 {"SPSR_cfsx", FALSE
, PSR_c
| PSR_f
| PSR_s
| PSR_x
},
510 {"SPSR_cfxs", FALSE
, PSR_c
| PSR_f
| PSR_x
| PSR_s
},
511 {"SPSR_csfx", FALSE
, PSR_c
| PSR_s
| PSR_f
| PSR_x
},
512 {"SPSR_csxf", FALSE
, PSR_c
| PSR_s
| PSR_x
| PSR_f
},
513 {"SPSR_cxfs", FALSE
, PSR_c
| PSR_x
| PSR_f
| PSR_s
},
514 {"SPSR_cxsf", FALSE
, PSR_c
| PSR_x
| PSR_s
| PSR_f
},
521 IWMMXT_REG_WR_OR_WC
= 2,
525 enum iwmmxt_insn_type
548 VFP_REG_Dd
, VFP_REG_Dm
, VFP_REG_Dn
553 VFP_REG_Sd
, VFP_REG_Sm
, VFP_REG_Sn
558 VFP_LDSTMIA
, VFP_LDSTMDB
, VFP_LDSTMIAX
, VFP_LDSTMDBX
561 /* VFP system registers. */
568 static const struct vfp_reg vfp_regs
[] =
570 {"fpsid", 0x00000000},
571 {"FPSID", 0x00000000},
572 {"fpscr", 0x00010000},
573 {"FPSCR", 0x00010000},
574 {"fpexc", 0x00080000},
575 {"FPEXC", 0x00080000}
578 /* Structure for a hash table entry for a register. */
586 /* Some well known registers that we refer to directly elsewhere. */
591 #define wr_register(reg) ((reg ^ WR_PREFIX) >= 0 && (reg ^ WR_PREFIX) <= 15)
592 #define wc_register(reg) ((reg ^ WC_PREFIX) >= 0 && (reg ^ WC_PREFIX) <= 15)
593 #define wcg_register(reg) ((reg ^ WC_PREFIX) >= 8 && (reg ^ WC_PREFIX) <= 11)
595 /* These are the standard names. Users can add aliases with .req.
596 and delete them with .unreq. */
598 /* Integer Register Numbers. */
599 static const struct reg_entry rn_table
[] =
601 {"r0", 0, TRUE
}, {"r1", 1, TRUE
}, {"r2", 2, TRUE
}, {"r3", 3, TRUE
},
602 {"r4", 4, TRUE
}, {"r5", 5, TRUE
}, {"r6", 6, TRUE
}, {"r7", 7, TRUE
},
603 {"r8", 8, TRUE
}, {"r9", 9, TRUE
}, {"r10", 10, TRUE
}, {"r11", 11, TRUE
},
604 {"r12", 12, TRUE
}, {"r13", REG_SP
, TRUE
}, {"r14", REG_LR
, TRUE
}, {"r15", REG_PC
, TRUE
},
605 /* ATPCS Synonyms. */
606 {"a1", 0, TRUE
}, {"a2", 1, TRUE
}, {"a3", 2, TRUE
}, {"a4", 3, TRUE
},
607 {"v1", 4, TRUE
}, {"v2", 5, TRUE
}, {"v3", 6, TRUE
}, {"v4", 7, TRUE
},
608 {"v5", 8, TRUE
}, {"v6", 9, TRUE
}, {"v7", 10, TRUE
}, {"v8", 11, TRUE
},
609 /* Well-known aliases. */
610 {"wr", 7, TRUE
}, {"sb", 9, TRUE
}, {"sl", 10, TRUE
}, {"fp", 11, TRUE
},
611 {"ip", 12, TRUE
}, {"sp", REG_SP
, TRUE
}, {"lr", REG_LR
, TRUE
}, {"pc", REG_PC
, TRUE
},
615 #define WR_PREFIX 0x200
616 #define WC_PREFIX 0x400
618 static const struct reg_entry iwmmxt_table
[] =
620 /* Intel Wireless MMX technology register names. */
621 { "wr0", 0x0 | WR_PREFIX
, TRUE
}, {"wr1", 0x1 | WR_PREFIX
, TRUE
},
622 { "wr2", 0x2 | WR_PREFIX
, TRUE
}, {"wr3", 0x3 | WR_PREFIX
, TRUE
},
623 { "wr4", 0x4 | WR_PREFIX
, TRUE
}, {"wr5", 0x5 | WR_PREFIX
, TRUE
},
624 { "wr6", 0x6 | WR_PREFIX
, TRUE
}, {"wr7", 0x7 | WR_PREFIX
, TRUE
},
625 { "wr8", 0x8 | WR_PREFIX
, TRUE
}, {"wr9", 0x9 | WR_PREFIX
, TRUE
},
626 { "wr10", 0xa | WR_PREFIX
, TRUE
}, {"wr11", 0xb | WR_PREFIX
, TRUE
},
627 { "wr12", 0xc | WR_PREFIX
, TRUE
}, {"wr13", 0xd | WR_PREFIX
, TRUE
},
628 { "wr14", 0xe | WR_PREFIX
, TRUE
}, {"wr15", 0xf | WR_PREFIX
, TRUE
},
629 { "wcid", 0x0 | WC_PREFIX
, TRUE
}, {"wcon", 0x1 | WC_PREFIX
, TRUE
},
630 {"wcssf", 0x2 | WC_PREFIX
, TRUE
}, {"wcasf", 0x3 | WC_PREFIX
, TRUE
},
631 {"wcgr0", 0x8 | WC_PREFIX
, TRUE
}, {"wcgr1", 0x9 | WC_PREFIX
, TRUE
},
632 {"wcgr2", 0xa | WC_PREFIX
, TRUE
}, {"wcgr3", 0xb | WC_PREFIX
, TRUE
},
634 { "wR0", 0x0 | WR_PREFIX
, TRUE
}, {"wR1", 0x1 | WR_PREFIX
, TRUE
},
635 { "wR2", 0x2 | WR_PREFIX
, TRUE
}, {"wR3", 0x3 | WR_PREFIX
, TRUE
},
636 { "wR4", 0x4 | WR_PREFIX
, TRUE
}, {"wR5", 0x5 | WR_PREFIX
, TRUE
},
637 { "wR6", 0x6 | WR_PREFIX
, TRUE
}, {"wR7", 0x7 | WR_PREFIX
, TRUE
},
638 { "wR8", 0x8 | WR_PREFIX
, TRUE
}, {"wR9", 0x9 | WR_PREFIX
, TRUE
},
639 { "wR10", 0xa | WR_PREFIX
, TRUE
}, {"wR11", 0xb | WR_PREFIX
, TRUE
},
640 { "wR12", 0xc | WR_PREFIX
, TRUE
}, {"wR13", 0xd | WR_PREFIX
, TRUE
},
641 { "wR14", 0xe | WR_PREFIX
, TRUE
}, {"wR15", 0xf | WR_PREFIX
, TRUE
},
642 { "wCID", 0x0 | WC_PREFIX
, TRUE
}, {"wCon", 0x1 | WC_PREFIX
, TRUE
},
643 {"wCSSF", 0x2 | WC_PREFIX
, TRUE
}, {"wCASF", 0x3 | WC_PREFIX
, TRUE
},
644 {"wCGR0", 0x8 | WC_PREFIX
, TRUE
}, {"wCGR1", 0x9 | WC_PREFIX
, TRUE
},
645 {"wCGR2", 0xa | WC_PREFIX
, TRUE
}, {"wCGR3", 0xb | WC_PREFIX
, TRUE
},
649 /* Co-processor Numbers. */
650 static const struct reg_entry cp_table
[] =
652 {"p0", 0, TRUE
}, {"p1", 1, TRUE
}, {"p2", 2, TRUE
}, {"p3", 3, TRUE
},
653 {"p4", 4, TRUE
}, {"p5", 5, TRUE
}, {"p6", 6, TRUE
}, {"p7", 7, TRUE
},
654 {"p8", 8, TRUE
}, {"p9", 9, TRUE
}, {"p10", 10, TRUE
}, {"p11", 11, TRUE
},
655 {"p12", 12, TRUE
}, {"p13", 13, TRUE
}, {"p14", 14, TRUE
}, {"p15", 15, TRUE
},
659 /* Co-processor Register Numbers. */
660 static const struct reg_entry cn_table
[] =
662 {"c0", 0, TRUE
}, {"c1", 1, TRUE
}, {"c2", 2, TRUE
}, {"c3", 3, TRUE
},
663 {"c4", 4, TRUE
}, {"c5", 5, TRUE
}, {"c6", 6, TRUE
}, {"c7", 7, TRUE
},
664 {"c8", 8, TRUE
}, {"c9", 9, TRUE
}, {"c10", 10, TRUE
}, {"c11", 11, TRUE
},
665 {"c12", 12, TRUE
}, {"c13", 13, TRUE
}, {"c14", 14, TRUE
}, {"c15", 15, TRUE
},
666 /* Not really valid, but kept for back-wards compatibility. */
667 {"cr0", 0, TRUE
}, {"cr1", 1, TRUE
}, {"cr2", 2, TRUE
}, {"cr3", 3, TRUE
},
668 {"cr4", 4, TRUE
}, {"cr5", 5, TRUE
}, {"cr6", 6, TRUE
}, {"cr7", 7, TRUE
},
669 {"cr8", 8, TRUE
}, {"cr9", 9, TRUE
}, {"cr10", 10, TRUE
}, {"cr11", 11, TRUE
},
670 {"cr12", 12, TRUE
}, {"cr13", 13, TRUE
}, {"cr14", 14, TRUE
}, {"cr15", 15, TRUE
},
675 static const struct reg_entry fn_table
[] =
677 {"f0", 0, TRUE
}, {"f1", 1, TRUE
}, {"f2", 2, TRUE
}, {"f3", 3, TRUE
},
678 {"f4", 4, TRUE
}, {"f5", 5, TRUE
}, {"f6", 6, TRUE
}, {"f7", 7, TRUE
},
682 /* VFP SP Registers. */
683 static const struct reg_entry sn_table
[] =
685 {"s0", 0, TRUE
}, {"s1", 1, TRUE
}, {"s2", 2, TRUE
}, {"s3", 3, TRUE
},
686 {"s4", 4, TRUE
}, {"s5", 5, TRUE
}, {"s6", 6, TRUE
}, {"s7", 7, TRUE
},
687 {"s8", 8, TRUE
}, {"s9", 9, TRUE
}, {"s10", 10, TRUE
}, {"s11", 11, TRUE
},
688 {"s12", 12, TRUE
}, {"s13", 13, TRUE
}, {"s14", 14, TRUE
}, {"s15", 15, TRUE
},
689 {"s16", 16, TRUE
}, {"s17", 17, TRUE
}, {"s18", 18, TRUE
}, {"s19", 19, TRUE
},
690 {"s20", 20, TRUE
}, {"s21", 21, TRUE
}, {"s22", 22, TRUE
}, {"s23", 23, TRUE
},
691 {"s24", 24, TRUE
}, {"s25", 25, TRUE
}, {"s26", 26, TRUE
}, {"s27", 27, TRUE
},
692 {"s28", 28, TRUE
}, {"s29", 29, TRUE
}, {"s30", 30, TRUE
}, {"s31", 31, TRUE
},
696 /* VFP DP Registers. */
697 static const struct reg_entry dn_table
[] =
699 {"d0", 0, TRUE
}, {"d1", 1, TRUE
}, {"d2", 2, TRUE
}, {"d3", 3, TRUE
},
700 {"d4", 4, TRUE
}, {"d5", 5, TRUE
}, {"d6", 6, TRUE
}, {"d7", 7, TRUE
},
701 {"d8", 8, TRUE
}, {"d9", 9, TRUE
}, {"d10", 10, TRUE
}, {"d11", 11, TRUE
},
702 {"d12", 12, TRUE
}, {"d13", 13, TRUE
}, {"d14", 14, TRUE
}, {"d15", 15, TRUE
},
706 /* Maverick DSP coprocessor registers. */
707 static const struct reg_entry mav_mvf_table
[] =
709 {"mvf0", 0, TRUE
}, {"mvf1", 1, TRUE
}, {"mvf2", 2, TRUE
}, {"mvf3", 3, TRUE
},
710 {"mvf4", 4, TRUE
}, {"mvf5", 5, TRUE
}, {"mvf6", 6, TRUE
}, {"mvf7", 7, TRUE
},
711 {"mvf8", 8, TRUE
}, {"mvf9", 9, TRUE
}, {"mvf10", 10, TRUE
}, {"mvf11", 11, TRUE
},
712 {"mvf12", 12, TRUE
}, {"mvf13", 13, TRUE
}, {"mvf14", 14, TRUE
}, {"mvf15", 15, TRUE
},
716 static const struct reg_entry mav_mvd_table
[] =
718 {"mvd0", 0, TRUE
}, {"mvd1", 1, TRUE
}, {"mvd2", 2, TRUE
}, {"mvd3", 3, TRUE
},
719 {"mvd4", 4, TRUE
}, {"mvd5", 5, TRUE
}, {"mvd6", 6, TRUE
}, {"mvd7", 7, TRUE
},
720 {"mvd8", 8, TRUE
}, {"mvd9", 9, TRUE
}, {"mvd10", 10, TRUE
}, {"mvd11", 11, TRUE
},
721 {"mvd12", 12, TRUE
}, {"mvd13", 13, TRUE
}, {"mvd14", 14, TRUE
}, {"mvd15", 15, TRUE
},
725 static const struct reg_entry mav_mvfx_table
[] =
727 {"mvfx0", 0, TRUE
}, {"mvfx1", 1, TRUE
}, {"mvfx2", 2, TRUE
}, {"mvfx3", 3, TRUE
},
728 {"mvfx4", 4, TRUE
}, {"mvfx5", 5, TRUE
}, {"mvfx6", 6, TRUE
}, {"mvfx7", 7, TRUE
},
729 {"mvfx8", 8, TRUE
}, {"mvfx9", 9, TRUE
}, {"mvfx10", 10, TRUE
}, {"mvfx11", 11, TRUE
},
730 {"mvfx12", 12, TRUE
}, {"mvfx13", 13, TRUE
}, {"mvfx14", 14, TRUE
}, {"mvfx15", 15, TRUE
},
734 static const struct reg_entry mav_mvdx_table
[] =
736 {"mvdx0", 0, TRUE
}, {"mvdx1", 1, TRUE
}, {"mvdx2", 2, TRUE
}, {"mvdx3", 3, TRUE
},
737 {"mvdx4", 4, TRUE
}, {"mvdx5", 5, TRUE
}, {"mvdx6", 6, TRUE
}, {"mvdx7", 7, TRUE
},
738 {"mvdx8", 8, TRUE
}, {"mvdx9", 9, TRUE
}, {"mvdx10", 10, TRUE
}, {"mvdx11", 11, TRUE
},
739 {"mvdx12", 12, TRUE
}, {"mvdx13", 13, TRUE
}, {"mvdx14", 14, TRUE
}, {"mvdx15", 15, TRUE
},
743 static const struct reg_entry mav_mvax_table
[] =
745 {"mvax0", 0, TRUE
}, {"mvax1", 1, TRUE
}, {"mvax2", 2, TRUE
}, {"mvax3", 3, TRUE
},
749 static const struct reg_entry mav_dspsc_table
[] =
757 const struct reg_entry
*names
;
759 struct hash_control
*htab
;
760 const char *expected
;
763 struct reg_map all_reg_maps
[] =
765 {rn_table
, 15, NULL
, N_("ARM register expected")},
766 {cp_table
, 15, NULL
, N_("bad or missing co-processor number")},
767 {cn_table
, 15, NULL
, N_("co-processor register expected")},
768 {fn_table
, 7, NULL
, N_("FPA register expected")},
769 {sn_table
, 31, NULL
, N_("VFP single precision register expected")},
770 {dn_table
, 15, NULL
, N_("VFP double precision register expected")},
771 {mav_mvf_table
, 15, NULL
, N_("Maverick MVF register expected")},
772 {mav_mvd_table
, 15, NULL
, N_("Maverick MVD register expected")},
773 {mav_mvfx_table
, 15, NULL
, N_("Maverick MVFX register expected")},
774 {mav_mvdx_table
, 15, NULL
, N_("Maverick MVDX register expected")},
775 {mav_mvax_table
, 3, NULL
, N_("Maverick MVAX register expected")},
776 {mav_dspsc_table
, 0, NULL
, N_("Maverick DSPSC register expected")},
777 {iwmmxt_table
, 23, NULL
, N_("Intel Wireless MMX technology register expected")},
780 /* Enumeration matching entries in table above. */
784 #define REG_TYPE_FIRST REG_TYPE_RN
796 REG_TYPE_IWMMXT
= 12,
801 /* Functions called by parser. */
802 /* ARM instructions. */
803 static void do_arit
PARAMS ((char *));
804 static void do_cmp
PARAMS ((char *));
805 static void do_mov
PARAMS ((char *));
806 static void do_ldst
PARAMS ((char *));
807 static void do_ldstt
PARAMS ((char *));
808 static void do_ldmstm
PARAMS ((char *));
809 static void do_branch
PARAMS ((char *));
810 static void do_swi
PARAMS ((char *));
812 /* Pseudo Op codes. */
813 static void do_adr
PARAMS ((char *));
814 static void do_adrl
PARAMS ((char *));
815 static void do_empty
PARAMS ((char *));
818 static void do_mul
PARAMS ((char *));
819 static void do_mla
PARAMS ((char *));
822 static void do_swap
PARAMS ((char *));
825 static void do_msr
PARAMS ((char *));
826 static void do_mrs
PARAMS ((char *));
829 static void do_mull
PARAMS ((char *));
832 static void do_ldstv4
PARAMS ((char *));
835 static void do_bx
PARAMS ((char *));
838 static void do_blx
PARAMS ((char *));
839 static void do_bkpt
PARAMS ((char *));
840 static void do_clz
PARAMS ((char *));
841 static void do_lstc2
PARAMS ((char *));
842 static void do_cdp2
PARAMS ((char *));
843 static void do_co_reg2
PARAMS ((char *));
846 static void do_smla
PARAMS ((char *));
847 static void do_smlal
PARAMS ((char *));
848 static void do_smul
PARAMS ((char *));
849 static void do_qadd
PARAMS ((char *));
852 static void do_pld
PARAMS ((char *));
853 static void do_ldrd
PARAMS ((char *));
854 static void do_co_reg2c
PARAMS ((char *));
857 static void do_bxj
PARAMS ((char *));
859 /* Coprocessor Instructions. */
860 static void do_cdp
PARAMS ((char *));
861 static void do_lstc
PARAMS ((char *));
862 static void do_co_reg
PARAMS ((char *));
864 /* FPA instructions. */
865 static void do_fpa_ctrl
PARAMS ((char *));
866 static void do_fpa_ldst
PARAMS ((char *));
867 static void do_fpa_ldmstm
PARAMS ((char *));
868 static void do_fpa_dyadic
PARAMS ((char *));
869 static void do_fpa_monadic
PARAMS ((char *));
870 static void do_fpa_cmp
PARAMS ((char *));
871 static void do_fpa_from_reg
PARAMS ((char *));
872 static void do_fpa_to_reg
PARAMS ((char *));
874 /* VFP instructions. */
875 static void do_vfp_sp_monadic
PARAMS ((char *));
876 static void do_vfp_dp_monadic
PARAMS ((char *));
877 static void do_vfp_sp_dyadic
PARAMS ((char *));
878 static void do_vfp_dp_dyadic
PARAMS ((char *));
879 static void do_vfp_reg_from_sp
PARAMS ((char *));
880 static void do_vfp_sp_from_reg
PARAMS ((char *));
881 static void do_vfp_sp_reg2
PARAMS ((char *));
882 static void do_vfp_reg_from_dp
PARAMS ((char *));
883 static void do_vfp_reg2_from_dp
PARAMS ((char *));
884 static void do_vfp_dp_from_reg
PARAMS ((char *));
885 static void do_vfp_dp_from_reg2
PARAMS ((char *));
886 static void do_vfp_reg_from_ctrl
PARAMS ((char *));
887 static void do_vfp_ctrl_from_reg
PARAMS ((char *));
888 static void do_vfp_sp_ldst
PARAMS ((char *));
889 static void do_vfp_dp_ldst
PARAMS ((char *));
890 static void do_vfp_sp_ldstmia
PARAMS ((char *));
891 static void do_vfp_sp_ldstmdb
PARAMS ((char *));
892 static void do_vfp_dp_ldstmia
PARAMS ((char *));
893 static void do_vfp_dp_ldstmdb
PARAMS ((char *));
894 static void do_vfp_xp_ldstmia
PARAMS ((char *));
895 static void do_vfp_xp_ldstmdb
PARAMS ((char *));
896 static void do_vfp_sp_compare_z
PARAMS ((char *));
897 static void do_vfp_dp_compare_z
PARAMS ((char *));
898 static void do_vfp_dp_sp_cvt
PARAMS ((char *));
899 static void do_vfp_sp_dp_cvt
PARAMS ((char *));
902 static void do_xsc_mia
PARAMS ((char *));
903 static void do_xsc_mar
PARAMS ((char *));
904 static void do_xsc_mra
PARAMS ((char *));
907 static void do_mav_binops
PARAMS ((char *, int, enum arm_reg_type
,
909 static void do_mav_binops_1a
PARAMS ((char *));
910 static void do_mav_binops_1b
PARAMS ((char *));
911 static void do_mav_binops_1c
PARAMS ((char *));
912 static void do_mav_binops_1d
PARAMS ((char *));
913 static void do_mav_binops_1e
PARAMS ((char *));
914 static void do_mav_binops_1f
PARAMS ((char *));
915 static void do_mav_binops_1g
PARAMS ((char *));
916 static void do_mav_binops_1h
PARAMS ((char *));
917 static void do_mav_binops_1i
PARAMS ((char *));
918 static void do_mav_binops_1j
PARAMS ((char *));
919 static void do_mav_binops_1k
PARAMS ((char *));
920 static void do_mav_binops_1l
PARAMS ((char *));
921 static void do_mav_binops_1m
PARAMS ((char *));
922 static void do_mav_binops_1n
PARAMS ((char *));
923 static void do_mav_binops_1o
PARAMS ((char *));
924 static void do_mav_binops_2a
PARAMS ((char *));
925 static void do_mav_binops_2b
PARAMS ((char *));
926 static void do_mav_binops_2c
PARAMS ((char *));
927 static void do_mav_binops_3a
PARAMS ((char *));
928 static void do_mav_binops_3b
PARAMS ((char *));
929 static void do_mav_binops_3c
PARAMS ((char *));
930 static void do_mav_binops_3d
PARAMS ((char *));
931 static void do_mav_triple
PARAMS ((char *, int, enum arm_reg_type
,
934 static void do_mav_triple_4a
PARAMS ((char *));
935 static void do_mav_triple_4b
PARAMS ((char *));
936 static void do_mav_triple_5a
PARAMS ((char *));
937 static void do_mav_triple_5b
PARAMS ((char *));
938 static void do_mav_triple_5c
PARAMS ((char *));
939 static void do_mav_triple_5d
PARAMS ((char *));
940 static void do_mav_triple_5e
PARAMS ((char *));
941 static void do_mav_triple_5f
PARAMS ((char *));
942 static void do_mav_triple_5g
PARAMS ((char *));
943 static void do_mav_triple_5h
PARAMS ((char *));
944 static void do_mav_quad
PARAMS ((char *, int, enum arm_reg_type
,
948 static void do_mav_quad_6a
PARAMS ((char *));
949 static void do_mav_quad_6b
PARAMS ((char *));
950 static void do_mav_dspsc_1
PARAMS ((char *));
951 static void do_mav_dspsc_2
PARAMS ((char *));
952 static void do_mav_shift
PARAMS ((char *, enum arm_reg_type
,
954 static void do_mav_shift_1
PARAMS ((char *));
955 static void do_mav_shift_2
PARAMS ((char *));
956 static void do_mav_ldst
PARAMS ((char *, enum arm_reg_type
));
957 static void do_mav_ldst_1
PARAMS ((char *));
958 static void do_mav_ldst_2
PARAMS ((char *));
959 static void do_mav_ldst_3
PARAMS ((char *));
960 static void do_mav_ldst_4
PARAMS ((char *));
962 static int mav_reg_required_here
PARAMS ((char **, int,
964 static int mav_parse_offset
PARAMS ((char **, int *));
966 static void fix_new_arm
PARAMS ((fragS
*, int, short, expressionS
*,
968 static int arm_reg_parse
PARAMS ((char **, struct hash_control
*));
969 static enum arm_reg_type arm_reg_parse_any
PARAMS ((char *));
970 static const struct asm_psr
* arm_psr_parse
PARAMS ((char **));
971 static void symbol_locate
PARAMS ((symbolS
*, const char *, segT
, valueT
,
973 static int add_to_lit_pool
PARAMS ((void));
974 static unsigned validate_immediate
PARAMS ((unsigned));
975 static unsigned validate_immediate_twopart
PARAMS ((unsigned int,
977 static int validate_offset_imm
PARAMS ((unsigned int, int));
978 static void opcode_select
PARAMS ((int));
979 static void end_of_line
PARAMS ((char *));
980 static int reg_required_here
PARAMS ((char **, int));
981 static int psr_required_here
PARAMS ((char **));
982 static int co_proc_number
PARAMS ((char **));
983 static int cp_opc_expr
PARAMS ((char **, int, int));
984 static int cp_reg_required_here
PARAMS ((char **, int));
985 static int fp_reg_required_here
PARAMS ((char **, int));
986 static int vfp_sp_reg_required_here
PARAMS ((char **, enum vfp_sp_reg_pos
));
987 static int vfp_dp_reg_required_here
PARAMS ((char **, enum vfp_dp_reg_pos
));
988 static void vfp_sp_ldstm
PARAMS ((char *, enum vfp_ldstm_type
));
989 static void vfp_dp_ldstm
PARAMS ((char *, enum vfp_ldstm_type
));
990 static long vfp_sp_reg_list
PARAMS ((char **, enum vfp_sp_reg_pos
));
991 static long vfp_dp_reg_list
PARAMS ((char **));
992 static int vfp_psr_required_here
PARAMS ((char **str
));
993 static const struct vfp_reg
*vfp_psr_parse
PARAMS ((char **str
));
994 static int cp_address_offset
PARAMS ((char **));
995 static int cp_address_required_here
PARAMS ((char **, int));
996 static int my_get_float_expression
PARAMS ((char **));
997 static int skip_past_comma
PARAMS ((char **));
998 static int walk_no_bignums
PARAMS ((symbolS
*));
999 static int negate_data_op
PARAMS ((unsigned long *, unsigned long));
1000 static int data_op2
PARAMS ((char **));
1001 static int fp_op2
PARAMS ((char **));
1002 static long reg_list
PARAMS ((char **));
1003 static void thumb_load_store
PARAMS ((char *, int, int));
1004 static int decode_shift
PARAMS ((char **, int));
1005 static int ldst_extend
PARAMS ((char **));
1006 static int ldst_extend_v4
PARAMS ((char **));
1007 static void thumb_add_sub
PARAMS ((char *, int));
1008 static void insert_reg
PARAMS ((const struct reg_entry
*,
1009 struct hash_control
*));
1010 static void thumb_shift
PARAMS ((char *, int));
1011 static void thumb_mov_compare
PARAMS ((char *, int));
1012 static void build_arm_ops_hsh
PARAMS ((void));
1013 static void set_constant_flonums
PARAMS ((void));
1014 static valueT md_chars_to_number
PARAMS ((char *, int));
1015 static void build_reg_hsh
PARAMS ((struct reg_map
*));
1016 static void insert_reg_alias
PARAMS ((char *, int, struct hash_control
*));
1017 static int create_register_alias
PARAMS ((char *, char *));
1018 static void output_inst
PARAMS ((const char *));
1019 static int accum0_required_here
PARAMS ((char **));
1020 static int ld_mode_required_here
PARAMS ((char **));
1021 static void do_branch25
PARAMS ((char *));
1022 static symbolS
* find_real_start
PARAMS ((symbolS
*));
1024 static bfd_reloc_code_real_type arm_parse_reloc
PARAMS ((void));
1027 static int wreg_required_here
PARAMS ((char **, int, enum wreg_type
));
1028 static void do_iwmmxt_byte_addr
PARAMS ((char *));
1029 static void do_iwmmxt_tandc
PARAMS ((char *));
1030 static void do_iwmmxt_tbcst
PARAMS ((char *));
1031 static void do_iwmmxt_textrc
PARAMS ((char *));
1032 static void do_iwmmxt_textrm
PARAMS ((char *));
1033 static void do_iwmmxt_tinsr
PARAMS ((char *));
1034 static void do_iwmmxt_tmcr
PARAMS ((char *));
1035 static void do_iwmmxt_tmcrr
PARAMS ((char *));
1036 static void do_iwmmxt_tmia
PARAMS ((char *));
1037 static void do_iwmmxt_tmovmsk
PARAMS ((char *));
1038 static void do_iwmmxt_tmrc
PARAMS ((char *));
1039 static void do_iwmmxt_tmrrc
PARAMS ((char *));
1040 static void do_iwmmxt_torc
PARAMS ((char *));
1041 static void do_iwmmxt_waligni
PARAMS ((char *));
1042 static void do_iwmmxt_wmov
PARAMS ((char *));
1043 static void do_iwmmxt_word_addr
PARAMS ((char *));
1044 static void do_iwmmxt_wrwr
PARAMS ((char *));
1045 static void do_iwmmxt_wrwrwcg
PARAMS ((char *));
1046 static void do_iwmmxt_wrwrwr
PARAMS ((char *));
1047 static void do_iwmmxt_wshufh
PARAMS ((char *));
1048 static void do_iwmmxt_wzero
PARAMS ((char *));
1049 static int cp_byte_address_offset
PARAMS ((char **));
1050 static int cp_byte_address_required_here
PARAMS ((char **));
1052 /* ARM instructions take 4bytes in the object file, Thumb instructions
1056 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
1057 #define MAV_MODE1 0x100c
1059 /* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
1060 #define MAV_MODE2 0x0c10
1062 /* "INSN<cond> X,Y" where X:0, Y:bit16. */
1063 #define MAV_MODE3 0x1000
1065 /* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
1066 #define MAV_MODE4 0x0c0010
1068 /* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
1069 #define MAV_MODE5 0x00100c
1071 /* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
1072 #define MAV_MODE6 0x00100c05
1076 /* Basic string to match. */
1077 const char * template;
1079 /* Basic instruction code. */
1080 unsigned long value
;
1082 /* Offset into the template where the condition code (if any) will be.
1083 If zero, then the instruction is never conditional. */
1084 unsigned cond_offset
;
1086 /* Which architecture variant provides this instruction. */
1087 unsigned long variant
;
1089 /* Function to call to parse args. */
1090 void (* parms
) PARAMS ((char *));
1093 static const struct asm_opcode insns
[] =
1095 /* Core ARM Instructions. */
1096 {"and", 0xe0000000, 3, ARM_EXT_V1
, do_arit
},
1097 {"ands", 0xe0100000, 3, ARM_EXT_V1
, do_arit
},
1098 {"eor", 0xe0200000, 3, ARM_EXT_V1
, do_arit
},
1099 {"eors", 0xe0300000, 3, ARM_EXT_V1
, do_arit
},
1100 {"sub", 0xe0400000, 3, ARM_EXT_V1
, do_arit
},
1101 {"subs", 0xe0500000, 3, ARM_EXT_V1
, do_arit
},
1102 {"rsb", 0xe0600000, 3, ARM_EXT_V1
, do_arit
},
1103 {"rsbs", 0xe0700000, 3, ARM_EXT_V1
, do_arit
},
1104 {"add", 0xe0800000, 3, ARM_EXT_V1
, do_arit
},
1105 {"adds", 0xe0900000, 3, ARM_EXT_V1
, do_arit
},
1106 {"adc", 0xe0a00000, 3, ARM_EXT_V1
, do_arit
},
1107 {"adcs", 0xe0b00000, 3, ARM_EXT_V1
, do_arit
},
1108 {"sbc", 0xe0c00000, 3, ARM_EXT_V1
, do_arit
},
1109 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1
, do_arit
},
1110 {"rsc", 0xe0e00000, 3, ARM_EXT_V1
, do_arit
},
1111 {"rscs", 0xe0f00000, 3, ARM_EXT_V1
, do_arit
},
1112 {"orr", 0xe1800000, 3, ARM_EXT_V1
, do_arit
},
1113 {"orrs", 0xe1900000, 3, ARM_EXT_V1
, do_arit
},
1114 {"bic", 0xe1c00000, 3, ARM_EXT_V1
, do_arit
},
1115 {"bics", 0xe1d00000, 3, ARM_EXT_V1
, do_arit
},
1117 {"tst", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
1118 {"tsts", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
1119 {"tstp", 0xe110f000, 3, ARM_EXT_V1
, do_cmp
},
1120 {"teq", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
1121 {"teqs", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
1122 {"teqp", 0xe130f000, 3, ARM_EXT_V1
, do_cmp
},
1123 {"cmp", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
1124 {"cmps", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
1125 {"cmpp", 0xe150f000, 3, ARM_EXT_V1
, do_cmp
},
1126 {"cmn", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
1127 {"cmns", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
1128 {"cmnp", 0xe170f000, 3, ARM_EXT_V1
, do_cmp
},
1130 {"mov", 0xe1a00000, 3, ARM_EXT_V1
, do_mov
},
1131 {"movs", 0xe1b00000, 3, ARM_EXT_V1
, do_mov
},
1132 {"mvn", 0xe1e00000, 3, ARM_EXT_V1
, do_mov
},
1133 {"mvns", 0xe1f00000, 3, ARM_EXT_V1
, do_mov
},
1135 {"ldr", 0xe4100000, 3, ARM_EXT_V1
, do_ldst
},
1136 {"ldrb", 0xe4500000, 3, ARM_EXT_V1
, do_ldst
},
1137 {"ldrt", 0xe4300000, 3, ARM_EXT_V1
, do_ldstt
},
1138 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1
, do_ldstt
},
1139 {"str", 0xe4000000, 3, ARM_EXT_V1
, do_ldst
},
1140 {"strb", 0xe4400000, 3, ARM_EXT_V1
, do_ldst
},
1141 {"strt", 0xe4200000, 3, ARM_EXT_V1
, do_ldstt
},
1142 {"strbt", 0xe4600000, 3, ARM_EXT_V1
, do_ldstt
},
1144 {"stmia", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
1145 {"stmib", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
1146 {"stmda", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
1147 {"stmdb", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
1148 {"stmfd", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
1149 {"stmfa", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
1150 {"stmea", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
1151 {"stmed", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
1153 {"ldmia", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
1154 {"ldmib", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
1155 {"ldmda", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
1156 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
1157 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
1158 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
1159 {"ldmea", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
1160 {"ldmed", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
1162 {"swi", 0xef000000, 3, ARM_EXT_V1
, do_swi
},
1164 /* XXX This is the wrong place to do this. Think multi-arch. */
1165 {"bl", 0xeb000000, 2, ARM_EXT_V1
, do_branch
},
1166 {"b", 0xea000000, 1, ARM_EXT_V1
, do_branch
},
1168 {"bl", 0xebfffffe, 2, ARM_EXT_V1
, do_branch
},
1169 {"b", 0xeafffffe, 1, ARM_EXT_V1
, do_branch
},
1173 {"adr", 0xe28f0000, 3, ARM_EXT_V1
, do_adr
},
1174 {"adrl", 0xe28f0000, 3, ARM_EXT_V1
, do_adrl
},
1175 {"nop", 0xe1a00000, 3, ARM_EXT_V1
, do_empty
},
1177 /* ARM 2 multiplies. */
1178 {"mul", 0xe0000090, 3, ARM_EXT_V2
, do_mul
},
1179 {"muls", 0xe0100090, 3, ARM_EXT_V2
, do_mul
},
1180 {"mla", 0xe0200090, 3, ARM_EXT_V2
, do_mla
},
1181 {"mlas", 0xe0300090, 3, ARM_EXT_V2
, do_mla
},
1183 /* Generic copressor instructions. */
1184 {"cdp", 0xee000000, 3, ARM_EXT_V2
, do_cdp
},
1185 {"ldc", 0xec100000, 3, ARM_EXT_V2
, do_lstc
},
1186 {"ldcl", 0xec500000, 3, ARM_EXT_V2
, do_lstc
},
1187 {"stc", 0xec000000, 3, ARM_EXT_V2
, do_lstc
},
1188 {"stcl", 0xec400000, 3, ARM_EXT_V2
, do_lstc
},
1189 {"mcr", 0xee000010, 3, ARM_EXT_V2
, do_co_reg
},
1190 {"mrc", 0xee100010, 3, ARM_EXT_V2
, do_co_reg
},
1192 /* ARM 3 - swp instructions. */
1193 {"swp", 0xe1000090, 3, ARM_EXT_V2S
, do_swap
},
1194 {"swpb", 0xe1400090, 3, ARM_EXT_V2S
, do_swap
},
1196 /* ARM 6 Status register instructions. */
1197 {"mrs", 0xe10f0000, 3, ARM_EXT_V3
, do_mrs
},
1198 {"msr", 0xe120f000, 3, ARM_EXT_V3
, do_msr
},
1199 /* ScottB: our code uses 0xe128f000 for msr.
1200 NickC: but this is wrong because the bits 16 through 19 are
1201 handled by the PSR_xxx defines above. */
1203 /* ARM 7M long multiplies. */
1204 {"smull", 0xe0c00090, 5, ARM_EXT_V3M
, do_mull
},
1205 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M
, do_mull
},
1206 {"umull", 0xe0800090, 5, ARM_EXT_V3M
, do_mull
},
1207 {"umulls", 0xe0900090, 5, ARM_EXT_V3M
, do_mull
},
1208 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M
, do_mull
},
1209 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M
, do_mull
},
1210 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M
, do_mull
},
1211 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M
, do_mull
},
1213 /* ARM Architecture 4. */
1214 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4
, do_ldstv4
},
1215 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4
, do_ldstv4
},
1216 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4
, do_ldstv4
},
1217 {"strh", 0xe00000b0, 3, ARM_EXT_V4
, do_ldstv4
},
1219 /* ARM Architecture 4T. */
1220 /* Note: bx (and blx) are required on V5, even if the processor does
1221 not support Thumb. */
1222 {"bx", 0xe12fff10, 2, ARM_EXT_V4T
| ARM_EXT_V5
, do_bx
},
1224 /* ARM Architecture 5T. */
1225 /* Note: blx has 2 variants, so the .value is set dynamically.
1226 Only one of the variants has conditional execution. */
1227 {"blx", 0xe0000000, 3, ARM_EXT_V5
, do_blx
},
1228 {"clz", 0xe16f0f10, 3, ARM_EXT_V5
, do_clz
},
1229 {"bkpt", 0xe1200070, 0, ARM_EXT_V5
, do_bkpt
},
1230 {"ldc2", 0xfc100000, 0, ARM_EXT_V5
, do_lstc2
},
1231 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5
, do_lstc2
},
1232 {"stc2", 0xfc000000, 0, ARM_EXT_V5
, do_lstc2
},
1233 {"stc2l", 0xfc400000, 0, ARM_EXT_V5
, do_lstc2
},
1234 {"cdp2", 0xfe000000, 0, ARM_EXT_V5
, do_cdp2
},
1235 {"mcr2", 0xfe000010, 0, ARM_EXT_V5
, do_co_reg2
},
1236 {"mrc2", 0xfe100010, 0, ARM_EXT_V5
, do_co_reg2
},
1238 /* ARM Architecture 5TExP. */
1239 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP
, do_smla
},
1240 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP
, do_smla
},
1241 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP
, do_smla
},
1242 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP
, do_smla
},
1244 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP
, do_smla
},
1245 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP
, do_smla
},
1247 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP
, do_smlal
},
1248 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP
, do_smlal
},
1249 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP
, do_smlal
},
1250 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP
, do_smlal
},
1252 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP
, do_smul
},
1253 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP
, do_smul
},
1254 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP
, do_smul
},
1255 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP
, do_smul
},
1257 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP
, do_smul
},
1258 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP
, do_smul
},
1260 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP
, do_qadd
},
1261 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP
, do_qadd
},
1262 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP
, do_qadd
},
1263 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP
, do_qadd
},
1265 /* ARM Architecture 5TE. */
1266 {"pld", 0xf450f000, 0, ARM_EXT_V5E
, do_pld
},
1267 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E
, do_ldrd
},
1268 {"strd", 0xe00000f0, 3, ARM_EXT_V5E
, do_ldrd
},
1270 {"mcrr", 0xec400000, 4, ARM_EXT_V5E
, do_co_reg2c
},
1271 {"mrrc", 0xec500000, 4, ARM_EXT_V5E
, do_co_reg2c
},
1273 /* ARM Architecture 5TEJ. */
1274 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J
, do_bxj
},
1276 /* Core FPA instruction set (V1). */
1277 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1278 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1279 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1280 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1282 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1283 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1284 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1285 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1287 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1288 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1289 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1290 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1292 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1293 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1294 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1295 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1296 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1297 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1298 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1299 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1300 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1301 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1302 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1303 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1305 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1306 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1307 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1308 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1309 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1310 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1311 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1312 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1313 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1314 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1315 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1316 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1318 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1319 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1320 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1321 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1322 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1323 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1324 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1325 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1326 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1327 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1328 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1329 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1331 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1332 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1333 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1334 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1335 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1336 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1337 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1338 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1339 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1340 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1341 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1342 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1344 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1345 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1346 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1347 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1348 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1349 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1350 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1351 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1352 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1353 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1354 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1355 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1357 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1358 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1359 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1360 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1361 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1362 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1363 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1364 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1365 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1366 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1367 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1368 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1370 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1371 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1372 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1373 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1374 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1375 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1376 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1377 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1378 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1379 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1380 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1381 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1383 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1384 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1385 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1386 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1387 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1388 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1389 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1390 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1391 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1392 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1393 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1394 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1396 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1397 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1398 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1399 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1400 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1401 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1402 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1403 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1404 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1405 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1406 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1407 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1409 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1410 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1411 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1412 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1413 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1414 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1415 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1416 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1417 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1418 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1419 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1420 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1422 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1423 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1424 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1425 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1426 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1427 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1428 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1429 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1430 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1431 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1432 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1433 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1435 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1436 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1437 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1438 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1439 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1440 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1441 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1442 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1443 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1444 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1445 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1446 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1448 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1449 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1450 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1451 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1452 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1453 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1454 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1455 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1456 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1457 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1458 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1459 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1461 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1462 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1463 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1464 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1465 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1466 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1467 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1468 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1469 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1470 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1471 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1472 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1474 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1475 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1476 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1477 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1478 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1479 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1480 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1481 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1482 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1483 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1484 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1485 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1487 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1488 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1489 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1490 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1491 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1492 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1493 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1494 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1495 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1496 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1497 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1498 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1500 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1501 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1502 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1503 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1504 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1505 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1506 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1507 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1508 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1509 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1510 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1511 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1513 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1514 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1515 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1516 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1517 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1518 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1519 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1520 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1521 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1522 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1523 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1524 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1526 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1527 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1528 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1529 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1530 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1531 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1532 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1533 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1534 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1535 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1536 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1537 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1539 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1540 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1541 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1542 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1543 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1544 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1545 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1546 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1547 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1548 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1549 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1550 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1552 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1553 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1554 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1555 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1556 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1557 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1558 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1559 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1560 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1561 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1562 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1563 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1565 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1566 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1567 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1568 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1569 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1570 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1571 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1572 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1573 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1574 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1575 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1576 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1578 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1579 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1580 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1581 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1582 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1583 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1584 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1585 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1586 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1587 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1588 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1589 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1591 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1592 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1593 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1594 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1595 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1596 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1597 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1598 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1599 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1600 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1601 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1602 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1604 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1605 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1606 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1607 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1608 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1609 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1610 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1611 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1612 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1613 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1614 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1615 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1617 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1618 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1619 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1620 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1621 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1622 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1623 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1624 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1625 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1626 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1627 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1628 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1630 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1631 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1632 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1633 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1634 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1635 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1636 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1637 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1638 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1639 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1640 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1641 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1643 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1644 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1645 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1646 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1647 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1648 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1649 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1650 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1651 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1652 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1653 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1654 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1656 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1657 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1658 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1659 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1660 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1661 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1662 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1663 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1664 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1665 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1666 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1667 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1669 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1670 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1671 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1672 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1673 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
1674 not be an optional suffix, but part of the instruction. To be
1675 compatible, we accept either. */
1676 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1677 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1679 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1680 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1681 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1682 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1683 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1684 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1685 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1686 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1687 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1688 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1689 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1690 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1692 /* The implementation of the FIX instruction is broken on some
1693 assemblers, in that it accepts a precision specifier as well as a
1694 rounding specifier, despite the fact that this is meaningless.
1695 To be more compatible, we accept it as well, though of course it
1696 does not set any bits. */
1697 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1698 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1699 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1700 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1701 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1702 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1703 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1704 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1705 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1706 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1707 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1708 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1709 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1711 /* Instructions that were new with the real FPA, call them V2. */
1712 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1713 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1714 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1715 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1716 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1717 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1719 /* VFP V1xD (single precision). */
1720 /* Moves and type conversions. */
1721 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1722 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_reg_from_sp
},
1723 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_from_reg
},
1724 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD
, do_empty
},
1725 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1726 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1727 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1728 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1729 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1730 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1731 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_reg_from_ctrl
},
1732 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_ctrl_from_reg
},
1734 /* Memory operations. */
1735 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldst
},
1736 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldst
},
1737 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1738 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1739 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1740 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1741 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1742 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1743 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1744 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1745 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1746 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1747 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1748 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1749 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1750 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1751 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1752 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1754 /* Monadic operations. */
1755 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1756 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1757 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1759 /* Dyadic operations. */
1760 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1761 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1762 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1763 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1764 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1765 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1766 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1767 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1768 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1771 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1772 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_compare_z
},
1773 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1774 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_compare_z
},
1776 /* VFP V1 (Double precision). */
1777 /* Moves and type conversions. */
1778 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1779 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
1780 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1781 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1
, do_vfp_dp_from_reg
},
1782 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1
, do_vfp_dp_from_reg
},
1783 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1
, do_vfp_reg_from_dp
},
1784 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1
, do_vfp_reg_from_dp
},
1785 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
1786 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
1787 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1788 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1789 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1790 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1792 /* Memory operations. */
1793 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1
, do_vfp_dp_ldst
},
1794 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1
, do_vfp_dp_ldst
},
1795 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1796 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1797 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1798 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1799 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1800 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1801 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1802 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1804 /* Monadic operations. */
1805 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1806 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1807 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1809 /* Dyadic operations. */
1810 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1811 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1812 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1813 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1814 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1815 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1816 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1817 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1818 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1821 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1822 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_compare_z
},
1823 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1824 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1
, do_vfp_dp_compare_z
},
1827 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2
, do_vfp_sp_reg2
},
1828 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2
, do_vfp_sp_reg2
},
1829 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2
, do_vfp_dp_from_reg2
},
1830 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2
, do_vfp_reg2_from_dp
},
1832 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
1833 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE
, do_xsc_mia
},
1834 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1835 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1836 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1837 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1838 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1839 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE
, do_xsc_mar
},
1840 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE
, do_xsc_mra
},
1842 /* Intel Wireless MMX technology instructions. */
1843 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
1844 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
1845 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
1846 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
1847 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
1848 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
1849 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
1850 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
1851 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
1852 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
1853 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
1854 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
1855 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
1856 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
1857 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
1858 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
1859 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
1860 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
1861 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmcr
},
1862 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_tmcrr
},
1863 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
1864 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
1865 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
1866 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
1867 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
1868 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
1869 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
1870 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
1871 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
1872 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmrc
},
1873 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_tmrrc
},
1874 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
1875 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
1876 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
1877 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1878 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1879 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1880 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1881 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1882 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1883 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1884 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1885 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1886 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1887 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1888 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1889 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_waligni
},
1890 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1891 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1892 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1893 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1894 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1895 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1896 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1897 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1898 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1899 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1900 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1901 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1902 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1903 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1904 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1905 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1906 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1907 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1908 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1909 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
1910 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
1911 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
1912 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
1913 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1914 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1915 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1916 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1917 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1918 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1919 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1920 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1921 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1922 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1923 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1924 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1925 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1926 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1927 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1928 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1929 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1930 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1931 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wmov
},
1932 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1933 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1934 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1935 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1936 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1937 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1938 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1939 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1940 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1941 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1942 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1943 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1944 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1945 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1946 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1947 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1948 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1949 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1950 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1951 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1952 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1953 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wshufh
},
1954 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1955 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1956 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1957 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1958 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1959 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1960 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1961 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1962 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1963 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1964 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1965 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1966 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1967 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1968 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1969 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1970 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1971 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1972 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
1973 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
1974 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
1975 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
1976 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1977 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1978 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1979 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1980 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1981 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1982 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1983 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1984 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1985 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1986 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1987 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1988 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1989 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1990 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1991 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1992 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1993 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1994 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1995 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1996 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1997 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1998 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1999 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2000 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2001 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2002 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2003 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2004 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wzero
},
2006 /* Cirrus Maverick instructions. */
2007 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_1
},
2008 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_2
},
2009 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_3
},
2010 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_4
},
2011 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_1
},
2012 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_2
},
2013 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_3
},
2014 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_4
},
2015 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK
, do_mav_binops_2a
},
2016 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1a
},
2017 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK
, do_mav_binops_2b
},
2018 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1b
},
2019 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK
, do_mav_binops_2b
},
2020 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1b
},
2021 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK
, do_mav_binops_2c
},
2022 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1c
},
2023 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK
, do_mav_binops_2c
},
2024 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1c
},
2025 {"cfmval32", 0xee100610, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
2026 {"cfmv32al", 0xee000610, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
2027 {"cfmvam32", 0xee100630, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
2028 {"cfmv32am", 0xee000630, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
2029 {"cfmvah32", 0xee100650, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
2030 {"cfmv32ah", 0xee000650, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
2031 {"cfmva32", 0xee100670, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
2032 {"cfmv32a", 0xee000670, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
2033 {"cfmva64", 0xee100690, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3c
},
2034 {"cfmv64a", 0xee000690, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3d
},
2035 {"cfmvsc32", 0xee1006b0, 8, ARM_CEXT_MAVERICK
, do_mav_dspsc_1
},
2036 {"cfmv32sc", 0xee0006b0, 8, ARM_CEXT_MAVERICK
, do_mav_dspsc_2
},
2037 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
2038 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
2039 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1f
},
2040 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1g
},
2041 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1h
},
2042 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1i
},
2043 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1j
},
2044 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1k
},
2045 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1l
},
2046 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1m
},
2047 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK
, do_mav_binops_1l
},
2048 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK
, do_mav_binops_1m
},
2049 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK
, do_mav_triple_4a
},
2050 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK
, do_mav_triple_4b
},
2051 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK
, do_mav_shift_1
},
2052 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK
, do_mav_shift_2
},
2053 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5a
},
2054 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5b
},
2055 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5c
},
2056 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5d
},
2057 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
2058 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
2059 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
2060 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
2061 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
2062 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
2063 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
2064 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
2065 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
2066 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
2067 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1n
},
2068 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1o
},
2069 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1n
},
2070 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1o
},
2071 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2072 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
2073 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2074 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
2075 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2076 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
2077 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2078 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2079 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK
, do_mav_quad_6a
},
2080 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK
, do_mav_quad_6a
},
2081 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK
, do_mav_quad_6b
},
2082 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK
, do_mav_quad_6b
},
2085 /* Defines for various bits that we will want to toggle. */
2086 #define INST_IMMEDIATE 0x02000000
2087 #define OFFSET_REG 0x02000000
2088 #define HWOFFSET_IMM 0x00400000
2089 #define SHIFT_BY_REG 0x00000010
2090 #define PRE_INDEX 0x01000000
2091 #define INDEX_UP 0x00800000
2092 #define WRITE_BACK 0x00200000
2093 #define LDM_TYPE_2_OR_3 0x00400000
2095 #define LITERAL_MASK 0xf000f000
2096 #define OPCODE_MASK 0xfe1fffff
2097 #define V4_STR_BIT 0x00000020
2099 #define DATA_OP_SHIFT 21
2101 /* Codes to distinguish the arithmetic instructions. */
2102 #define OPCODE_AND 0
2103 #define OPCODE_EOR 1
2104 #define OPCODE_SUB 2
2105 #define OPCODE_RSB 3
2106 #define OPCODE_ADD 4
2107 #define OPCODE_ADC 5
2108 #define OPCODE_SBC 6
2109 #define OPCODE_RSC 7
2110 #define OPCODE_TST 8
2111 #define OPCODE_TEQ 9
2112 #define OPCODE_CMP 10
2113 #define OPCODE_CMN 11
2114 #define OPCODE_ORR 12
2115 #define OPCODE_MOV 13
2116 #define OPCODE_BIC 14
2117 #define OPCODE_MVN 15
2119 /* Thumb v1 (ARMv4T). */
2120 static void do_t_nop
PARAMS ((char *));
2121 static void do_t_arit
PARAMS ((char *));
2122 static void do_t_add
PARAMS ((char *));
2123 static void do_t_asr
PARAMS ((char *));
2124 static void do_t_branch9
PARAMS ((char *));
2125 static void do_t_branch12
PARAMS ((char *));
2126 static void do_t_branch23
PARAMS ((char *));
2127 static void do_t_bx
PARAMS ((char *));
2128 static void do_t_compare
PARAMS ((char *));
2129 static void do_t_ldmstm
PARAMS ((char *));
2130 static void do_t_ldr
PARAMS ((char *));
2131 static void do_t_ldrb
PARAMS ((char *));
2132 static void do_t_ldrh
PARAMS ((char *));
2133 static void do_t_lds
PARAMS ((char *));
2134 static void do_t_lsl
PARAMS ((char *));
2135 static void do_t_lsr
PARAMS ((char *));
2136 static void do_t_mov
PARAMS ((char *));
2137 static void do_t_push_pop
PARAMS ((char *));
2138 static void do_t_str
PARAMS ((char *));
2139 static void do_t_strb
PARAMS ((char *));
2140 static void do_t_strh
PARAMS ((char *));
2141 static void do_t_sub
PARAMS ((char *));
2142 static void do_t_swi
PARAMS ((char *));
2143 static void do_t_adr
PARAMS ((char *));
2145 /* Thumb v2 (ARMv5T). */
2146 static void do_t_blx
PARAMS ((char *));
2147 static void do_t_bkpt
PARAMS ((char *));
2149 #define T_OPCODE_MUL 0x4340
2150 #define T_OPCODE_TST 0x4200
2151 #define T_OPCODE_CMN 0x42c0
2152 #define T_OPCODE_NEG 0x4240
2153 #define T_OPCODE_MVN 0x43c0
2155 #define T_OPCODE_ADD_R3 0x1800
2156 #define T_OPCODE_SUB_R3 0x1a00
2157 #define T_OPCODE_ADD_HI 0x4400
2158 #define T_OPCODE_ADD_ST 0xb000
2159 #define T_OPCODE_SUB_ST 0xb080
2160 #define T_OPCODE_ADD_SP 0xa800
2161 #define T_OPCODE_ADD_PC 0xa000
2162 #define T_OPCODE_ADD_I8 0x3000
2163 #define T_OPCODE_SUB_I8 0x3800
2164 #define T_OPCODE_ADD_I3 0x1c00
2165 #define T_OPCODE_SUB_I3 0x1e00
2167 #define T_OPCODE_ASR_R 0x4100
2168 #define T_OPCODE_LSL_R 0x4080
2169 #define T_OPCODE_LSR_R 0x40c0
2170 #define T_OPCODE_ASR_I 0x1000
2171 #define T_OPCODE_LSL_I 0x0000
2172 #define T_OPCODE_LSR_I 0x0800
2174 #define T_OPCODE_MOV_I8 0x2000
2175 #define T_OPCODE_CMP_I8 0x2800
2176 #define T_OPCODE_CMP_LR 0x4280
2177 #define T_OPCODE_MOV_HR 0x4600
2178 #define T_OPCODE_CMP_HR 0x4500
2180 #define T_OPCODE_LDR_PC 0x4800
2181 #define T_OPCODE_LDR_SP 0x9800
2182 #define T_OPCODE_STR_SP 0x9000
2183 #define T_OPCODE_LDR_IW 0x6800
2184 #define T_OPCODE_STR_IW 0x6000
2185 #define T_OPCODE_LDR_IH 0x8800
2186 #define T_OPCODE_STR_IH 0x8000
2187 #define T_OPCODE_LDR_IB 0x7800
2188 #define T_OPCODE_STR_IB 0x7000
2189 #define T_OPCODE_LDR_RW 0x5800
2190 #define T_OPCODE_STR_RW 0x5000
2191 #define T_OPCODE_LDR_RH 0x5a00
2192 #define T_OPCODE_STR_RH 0x5200
2193 #define T_OPCODE_LDR_RB 0x5c00
2194 #define T_OPCODE_STR_RB 0x5400
2196 #define T_OPCODE_PUSH 0xb400
2197 #define T_OPCODE_POP 0xbc00
2199 #define T_OPCODE_BRANCH 0xe7fe
2201 static int thumb_reg
PARAMS ((char ** str
, int hi_lo
));
2203 #define THUMB_SIZE 2 /* Size of thumb instruction. */
2204 #define THUMB_REG_LO 0x1
2205 #define THUMB_REG_HI 0x2
2206 #define THUMB_REG_ANY 0x3
2208 #define THUMB_H1 0x0080
2209 #define THUMB_H2 0x0040
2215 #define THUMB_MOVE 0
2216 #define THUMB_COMPARE 1
2218 #define THUMB_LOAD 0
2219 #define THUMB_STORE 1
2221 #define THUMB_PP_PC_LR 0x0100
2223 /* These three are used for immediate shifts, do not alter. */
2224 #define THUMB_WORD 2
2225 #define THUMB_HALFWORD 1
2226 #define THUMB_BYTE 0
2230 /* Basic string to match. */
2231 const char * template;
2233 /* Basic instruction code. */
2234 unsigned long value
;
2238 /* Which CPU variants this exists for. */
2239 unsigned long variant
;
2241 /* Function to call to parse args. */
2242 void (* parms
) PARAMS ((char *));
2245 static const struct thumb_opcode tinsns
[] =
2247 /* Thumb v1 (ARMv4T). */
2248 {"adc", 0x4140, 2, ARM_EXT_V4T
, do_t_arit
},
2249 {"add", 0x0000, 2, ARM_EXT_V4T
, do_t_add
},
2250 {"and", 0x4000, 2, ARM_EXT_V4T
, do_t_arit
},
2251 {"asr", 0x0000, 2, ARM_EXT_V4T
, do_t_asr
},
2252 {"b", T_OPCODE_BRANCH
, 2, ARM_EXT_V4T
, do_t_branch12
},
2253 {"beq", 0xd0fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2254 {"bne", 0xd1fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2255 {"bcs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2256 {"bhs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2257 {"bcc", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2258 {"bul", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2259 {"blo", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2260 {"bmi", 0xd4fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2261 {"bpl", 0xd5fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2262 {"bvs", 0xd6fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2263 {"bvc", 0xd7fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2264 {"bhi", 0xd8fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2265 {"bls", 0xd9fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2266 {"bge", 0xdafe, 2, ARM_EXT_V4T
, do_t_branch9
},
2267 {"blt", 0xdbfe, 2, ARM_EXT_V4T
, do_t_branch9
},
2268 {"bgt", 0xdcfe, 2, ARM_EXT_V4T
, do_t_branch9
},
2269 {"ble", 0xddfe, 2, ARM_EXT_V4T
, do_t_branch9
},
2270 {"bal", 0xdefe, 2, ARM_EXT_V4T
, do_t_branch9
},
2271 {"bic", 0x4380, 2, ARM_EXT_V4T
, do_t_arit
},
2272 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T
, do_t_branch23
},
2273 {"bx", 0x4700, 2, ARM_EXT_V4T
, do_t_bx
},
2274 {"cmn", T_OPCODE_CMN
, 2, ARM_EXT_V4T
, do_t_arit
},
2275 {"cmp", 0x0000, 2, ARM_EXT_V4T
, do_t_compare
},
2276 {"eor", 0x4040, 2, ARM_EXT_V4T
, do_t_arit
},
2277 {"ldmia", 0xc800, 2, ARM_EXT_V4T
, do_t_ldmstm
},
2278 {"ldr", 0x0000, 2, ARM_EXT_V4T
, do_t_ldr
},
2279 {"ldrb", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrb
},
2280 {"ldrh", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrh
},
2281 {"ldrsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
2282 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
2283 {"ldsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
2284 {"ldsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
2285 {"lsl", 0x0000, 2, ARM_EXT_V4T
, do_t_lsl
},
2286 {"lsr", 0x0000, 2, ARM_EXT_V4T
, do_t_lsr
},
2287 {"mov", 0x0000, 2, ARM_EXT_V4T
, do_t_mov
},
2288 {"mul", T_OPCODE_MUL
, 2, ARM_EXT_V4T
, do_t_arit
},
2289 {"mvn", T_OPCODE_MVN
, 2, ARM_EXT_V4T
, do_t_arit
},
2290 {"neg", T_OPCODE_NEG
, 2, ARM_EXT_V4T
, do_t_arit
},
2291 {"orr", 0x4300, 2, ARM_EXT_V4T
, do_t_arit
},
2292 {"pop", 0xbc00, 2, ARM_EXT_V4T
, do_t_push_pop
},
2293 {"push", 0xb400, 2, ARM_EXT_V4T
, do_t_push_pop
},
2294 {"ror", 0x41c0, 2, ARM_EXT_V4T
, do_t_arit
},
2295 {"sbc", 0x4180, 2, ARM_EXT_V4T
, do_t_arit
},
2296 {"stmia", 0xc000, 2, ARM_EXT_V4T
, do_t_ldmstm
},
2297 {"str", 0x0000, 2, ARM_EXT_V4T
, do_t_str
},
2298 {"strb", 0x0000, 2, ARM_EXT_V4T
, do_t_strb
},
2299 {"strh", 0x0000, 2, ARM_EXT_V4T
, do_t_strh
},
2300 {"swi", 0xdf00, 2, ARM_EXT_V4T
, do_t_swi
},
2301 {"sub", 0x0000, 2, ARM_EXT_V4T
, do_t_sub
},
2302 {"tst", T_OPCODE_TST
, 2, ARM_EXT_V4T
, do_t_arit
},
2304 {"adr", 0x0000, 2, ARM_EXT_V4T
, do_t_adr
},
2305 {"nop", 0x46C0, 2, ARM_EXT_V4T
, do_t_nop
}, /* mov r8,r8 */
2306 /* Thumb v2 (ARMv5T). */
2307 {"blx", 0, 0, ARM_EXT_V5T
, do_t_blx
},
2308 {"bkpt", 0xbe00, 2, ARM_EXT_V5T
, do_t_bkpt
},
2311 #define BAD_ARGS _("bad arguments to instruction")
2312 #define BAD_PC _("r15 not allowed here")
2313 #define BAD_COND _("instruction is not conditional")
2314 #define ERR_NO_ACCUM _("acc0 expected")
2316 static struct hash_control
* arm_ops_hsh
= NULL
;
2317 static struct hash_control
* arm_tops_hsh
= NULL
;
2318 static struct hash_control
* arm_cond_hsh
= NULL
;
2319 static struct hash_control
* arm_shift_hsh
= NULL
;
2320 static struct hash_control
* arm_psr_hsh
= NULL
;
2322 /* This table describes all the machine specific pseudo-ops the assembler
2323 has to support. The fields are:
2324 pseudo-op name without dot
2325 function to call to execute this pseudo-op
2326 Integer arg to pass to the function. */
2328 static void s_req
PARAMS ((int));
2329 static void s_unreq
PARAMS ((int));
2330 static void s_align
PARAMS ((int));
2331 static void s_bss
PARAMS ((int));
2332 static void s_even
PARAMS ((int));
2333 static void s_ltorg
PARAMS ((int));
2334 static void s_arm
PARAMS ((int));
2335 static void s_thumb
PARAMS ((int));
2336 static void s_code
PARAMS ((int));
2337 static void s_force_thumb
PARAMS ((int));
2338 static void s_thumb_func
PARAMS ((int));
2339 static void s_thumb_set
PARAMS ((int));
2341 static void s_arm_elf_cons
PARAMS ((int));
2344 static int my_get_expression
PARAMS ((expressionS
*, char **));
2346 const pseudo_typeS md_pseudo_table
[] =
2348 /* Never called because '.req' does not start a line. */
2349 { "req", s_req
, 0 },
2350 { "unreq", s_unreq
, 0 },
2351 { "bss", s_bss
, 0 },
2352 { "align", s_align
, 0 },
2353 { "arm", s_arm
, 0 },
2354 { "thumb", s_thumb
, 0 },
2355 { "code", s_code
, 0 },
2356 { "force_thumb", s_force_thumb
, 0 },
2357 { "thumb_func", s_thumb_func
, 0 },
2358 { "thumb_set", s_thumb_set
, 0 },
2359 { "even", s_even
, 0 },
2360 { "ltorg", s_ltorg
, 0 },
2361 { "pool", s_ltorg
, 0 },
2363 { "word", s_arm_elf_cons
, 4 },
2364 { "long", s_arm_elf_cons
, 4 },
2368 { "extend", float_cons
, 'x' },
2369 { "ldouble", float_cons
, 'x' },
2370 { "packed", float_cons
, 'p' },
2374 /* Other internal functions. */
2375 static int arm_parse_extension
PARAMS ((char *, int *));
2376 static int arm_parse_cpu
PARAMS ((char *));
2377 static int arm_parse_arch
PARAMS ((char *));
2378 static int arm_parse_fpu
PARAMS ((char *));
2379 #if 0 /* Suppressed - for now. */
2380 #if defined OBJ_COFF || defined OBJ_ELF
2381 static void arm_add_note
PARAMS ((const char *, const char *, unsigned int));
2385 /* Stuff needed to resolve the label ambiguity
2395 symbolS
* last_label_seen
;
2396 static int label_is_thumb_function_name
= FALSE
;
2398 /* Literal Pool stuff. */
2400 #define MAX_LITERAL_POOL_SIZE 1024
2402 /* Literal pool structure. Held on a per-section
2403 and per-sub-section basis. */
2404 typedef struct literal_pool
2406 expressionS literals
[MAX_LITERAL_POOL_SIZE
];
2407 unsigned int next_free_entry
;
2411 subsegT sub_section
;
2412 struct literal_pool
* next
;
2415 /* Pointer to a linked list of literal pools. */
2416 literal_pool
* list_of_pools
= NULL
;
2418 static literal_pool
* find_literal_pool
PARAMS ((void));
2419 static literal_pool
* find_or_make_literal_pool
PARAMS ((void));
2421 static literal_pool
*
2422 find_literal_pool ()
2424 literal_pool
* pool
;
2426 for (pool
= list_of_pools
; pool
!= NULL
; pool
= pool
->next
)
2428 if (pool
->section
== now_seg
2429 && pool
->sub_section
== now_subseg
)
2436 static literal_pool
*
2437 find_or_make_literal_pool ()
2439 /* Next literal pool ID number. */
2440 static unsigned int latest_pool_num
= 1;
2441 literal_pool
* pool
;
2443 pool
= find_literal_pool ();
2447 /* Create a new pool. */
2448 pool
= (literal_pool
*) xmalloc (sizeof (* pool
));
2452 pool
->next_free_entry
= 0;
2453 pool
->section
= now_seg
;
2454 pool
->sub_section
= now_subseg
;
2455 pool
->next
= list_of_pools
;
2456 pool
->symbol
= NULL
;
2458 /* Add it to the list. */
2459 list_of_pools
= pool
;
2462 /* New pools, and emptied pools, will have a NULL symbol. */
2463 if (pool
->symbol
== NULL
)
2465 pool
->symbol
= symbol_create (FAKE_LABEL_NAME
, undefined_section
,
2466 (valueT
) 0, &zero_address_frag
);
2467 pool
->id
= latest_pool_num
++;
2474 /* Add the literal in the global 'inst'
2475 structure to the relevent literal pool. */
2479 literal_pool
* pool
;
2482 pool
= find_or_make_literal_pool ();
2484 /* Check if this literal value is already in the pool. */
2485 for (entry
= 0; entry
< pool
->next_free_entry
; entry
++)
2487 if ((pool
->literals
[entry
].X_op
== inst
.reloc
.exp
.X_op
)
2488 && (inst
.reloc
.exp
.X_op
== O_constant
)
2489 && (pool
->literals
[entry
].X_add_number
2490 == inst
.reloc
.exp
.X_add_number
)
2491 && (pool
->literals
[entry
].X_unsigned
2492 == inst
.reloc
.exp
.X_unsigned
))
2495 if ((pool
->literals
[entry
].X_op
== inst
.reloc
.exp
.X_op
)
2496 && (inst
.reloc
.exp
.X_op
== O_symbol
)
2497 && (pool
->literals
[entry
].X_add_number
2498 == inst
.reloc
.exp
.X_add_number
)
2499 && (pool
->literals
[entry
].X_add_symbol
2500 == inst
.reloc
.exp
.X_add_symbol
)
2501 && (pool
->literals
[entry
].X_op_symbol
2502 == inst
.reloc
.exp
.X_op_symbol
))
2506 /* Do we need to create a new entry? */
2507 if (entry
== pool
->next_free_entry
)
2509 if (entry
>= MAX_LITERAL_POOL_SIZE
)
2511 inst
.error
= _("literal pool overflow");
2515 pool
->literals
[entry
] = inst
.reloc
.exp
;
2516 pool
->next_free_entry
+= 1;
2519 inst
.reloc
.exp
.X_op
= O_symbol
;
2520 inst
.reloc
.exp
.X_add_number
= ((int) entry
) * 4 - 8;
2521 inst
.reloc
.exp
.X_add_symbol
= pool
->symbol
;
2526 /* Can't use symbol_new here, so have to create a symbol and then at
2527 a later date assign it a value. Thats what these functions do. */
2530 symbol_locate (symbolP
, name
, segment
, valu
, frag
)
2532 const char * name
; /* It is copied, the caller can modify. */
2533 segT segment
; /* Segment identifier (SEG_<something>). */
2534 valueT valu
; /* Symbol value. */
2535 fragS
* frag
; /* Associated fragment. */
2537 unsigned int name_length
;
2538 char * preserved_copy_of_name
;
2540 name_length
= strlen (name
) + 1; /* +1 for \0. */
2541 obstack_grow (¬es
, name
, name_length
);
2542 preserved_copy_of_name
= obstack_finish (¬es
);
2543 #ifdef STRIP_UNDERSCORE
2544 if (preserved_copy_of_name
[0] == '_')
2545 preserved_copy_of_name
++;
2548 #ifdef tc_canonicalize_symbol_name
2549 preserved_copy_of_name
=
2550 tc_canonicalize_symbol_name (preserved_copy_of_name
);
2553 S_SET_NAME (symbolP
, preserved_copy_of_name
);
2555 S_SET_SEGMENT (symbolP
, segment
);
2556 S_SET_VALUE (symbolP
, valu
);
2557 symbol_clear_list_pointers (symbolP
);
2559 symbol_set_frag (symbolP
, frag
);
2561 /* Link to end of symbol chain. */
2563 extern int symbol_table_frozen
;
2564 if (symbol_table_frozen
)
2568 symbol_append (symbolP
, symbol_lastP
, & symbol_rootP
, & symbol_lastP
);
2570 obj_symbol_new_hook (symbolP
);
2572 #ifdef tc_symbol_new_hook
2573 tc_symbol_new_hook (symbolP
);
2577 verify_symbol_chain (symbol_rootP
, symbol_lastP
);
2578 #endif /* DEBUG_SYMS */
2581 /* Check that an immediate is valid.
2582 If so, convert it to the right format. */
2585 validate_immediate (val
)
2591 #define rotate_left(v, n) (v << n | v >> (32 - n))
2593 for (i
= 0; i
< 32; i
+= 2)
2594 if ((a
= rotate_left (val
, i
)) <= 0xff)
2595 return a
| (i
<< 7); /* 12-bit pack: [shift-cnt,const]. */
2600 /* Check to see if an immediate can be computed as two seperate immediate
2601 values, added together. We already know that this value cannot be
2602 computed by just one ARM instruction. */
2605 validate_immediate_twopart (val
, highpart
)
2607 unsigned int * highpart
;
2612 for (i
= 0; i
< 32; i
+= 2)
2613 if (((a
= rotate_left (val
, i
)) & 0xff) != 0)
2619 * highpart
= (a
>> 8) | ((i
+ 24) << 7);
2621 else if (a
& 0xff0000)
2625 * highpart
= (a
>> 16) | ((i
+ 16) << 7);
2629 assert (a
& 0xff000000);
2630 * highpart
= (a
>> 24) | ((i
+ 8) << 7);
2633 return (a
& 0xff) | (i
<< 7);
2640 validate_offset_imm (val
, hwse
)
2644 if ((hwse
&& val
> 255) || val
> 4095)
2651 int a ATTRIBUTE_UNUSED
;
2653 as_bad (_("invalid syntax for .req directive"));
2656 /* The .unreq directive deletes an alias which was previously defined
2657 by .req. For example:
2663 s_unreq (int a ATTRIBUTE_UNUSED
)
2668 skip_whitespace (input_line_pointer
);
2669 name
= input_line_pointer
;
2671 while (*input_line_pointer
!= 0
2672 && *input_line_pointer
!= ' '
2673 && *input_line_pointer
!= '\n')
2674 ++input_line_pointer
;
2676 saved_char
= *input_line_pointer
;
2677 *input_line_pointer
= 0;
2681 enum arm_reg_type req_type
= arm_reg_parse_any (name
);
2683 if (req_type
!= REG_TYPE_MAX
)
2685 char *temp_name
= name
;
2686 int req_no
= arm_reg_parse (&temp_name
, all_reg_maps
[req_type
].htab
);
2690 struct reg_entry
*req_entry
;
2692 /* Check to see if this alias is a builtin one. */
2693 req_entry
= hash_delete (all_reg_maps
[req_type
].htab
, name
);
2696 as_bad (_("unreq: missing hash entry for \"%s\""), name
);
2697 else if (req_entry
->builtin
)
2698 /* FIXME: We are deleteing a built in register alias which
2699 points to a const data structure, so we only need to
2700 free up the memory used by the key in the hash table.
2701 Unfortunately we have not recorded this value, so this
2702 is a memory leak. */
2703 /* FIXME: Should we issue a warning message ? */
2707 /* Deleteing a user defined alias. We need to free the
2708 key and the value, but fortunately the key is the same
2709 as the value->name field. */
2710 free ((char *) req_entry
->name
);
2715 as_bad (_(".unreq: unrecognized symbol \"%s\""), name
);
2718 as_bad (_(".unreq: unrecognized symbol \"%s\""), name
);
2721 as_bad (_("invalid syntax for .unreq directive"));
2723 *input_line_pointer
= saved_char
;
2724 demand_empty_rest_of_line ();
2729 int ignore ATTRIBUTE_UNUSED
;
2731 /* We don't support putting frags in the BSS segment, we fake it by
2732 marking in_bss, then looking at s_skip for clues. */
2733 subseg_set (bss_section
, 0);
2734 demand_empty_rest_of_line ();
2739 int ignore ATTRIBUTE_UNUSED
;
2741 /* Never make frag if expect extra pass. */
2743 frag_align (1, 0, 0);
2745 record_alignment (now_seg
, 1);
2747 demand_empty_rest_of_line ();
2752 int ignored ATTRIBUTE_UNUSED
;
2755 literal_pool
* pool
;
2758 pool
= find_literal_pool ();
2760 || pool
->symbol
== NULL
2761 || pool
->next_free_entry
== 0)
2764 /* Align pool as you have word accesses.
2765 Only make a frag if we have to. */
2767 frag_align (2, 0, 0);
2769 record_alignment (now_seg
, 2);
2771 sprintf (sym_name
, "$$lit_\002%x", pool
->id
);
2773 symbol_locate (pool
->symbol
, sym_name
, now_seg
,
2774 (valueT
) frag_now_fix (), frag_now
);
2775 symbol_table_insert (pool
->symbol
);
2777 ARM_SET_THUMB (pool
->symbol
, thumb_mode
);
2779 #if defined OBJ_COFF || defined OBJ_ELF
2780 ARM_SET_INTERWORK (pool
->symbol
, support_interwork
);
2783 for (entry
= 0; entry
< pool
->next_free_entry
; entry
++)
2784 /* First output the expression in the instruction to the pool. */
2785 emit_expr (&(pool
->literals
[entry
]), 4); /* .word */
2787 /* Mark the pool as empty. */
2788 pool
->next_free_entry
= 0;
2789 pool
->symbol
= NULL
;
2792 /* Same as s_align_ptwo but align 0 => align 2. */
2796 int unused ATTRIBUTE_UNUSED
;
2799 register long temp_fill
;
2800 long max_alignment
= 15;
2802 temp
= get_absolute_expression ();
2803 if (temp
> max_alignment
)
2804 as_bad (_("alignment too large: %d assumed"), temp
= max_alignment
);
2807 as_bad (_("alignment negative. 0 assumed."));
2811 if (*input_line_pointer
== ',')
2813 input_line_pointer
++;
2814 temp_fill
= get_absolute_expression ();
2822 /* Only make a frag if we HAVE to. */
2823 if (temp
&& !need_pass_2
)
2824 frag_align (temp
, (int) temp_fill
, 0);
2825 demand_empty_rest_of_line ();
2827 record_alignment (now_seg
, temp
);
2831 s_force_thumb (ignore
)
2832 int ignore ATTRIBUTE_UNUSED
;
2834 /* If we are not already in thumb mode go into it, EVEN if
2835 the target processor does not support thumb instructions.
2836 This is used by gcc/config/arm/lib1funcs.asm for example
2837 to compile interworking support functions even if the
2838 target processor should not support interworking. */
2843 record_alignment (now_seg
, 1);
2846 demand_empty_rest_of_line ();
2850 s_thumb_func (ignore
)
2851 int ignore ATTRIBUTE_UNUSED
;
2856 /* The following label is the name/address of the start of a Thumb function.
2857 We need to know this for the interworking support. */
2858 label_is_thumb_function_name
= TRUE
;
2860 demand_empty_rest_of_line ();
2863 /* Perform a .set directive, but also mark the alias as
2864 being a thumb function. */
2870 /* XXX the following is a duplicate of the code for s_set() in read.c
2871 We cannot just call that code as we need to get at the symbol that
2873 register char * name
;
2874 register char delim
;
2875 register char * end_name
;
2876 register symbolS
* symbolP
;
2878 /* Especial apologies for the random logic:
2879 This just grew, and could be parsed much more simply!
2881 name
= input_line_pointer
;
2882 delim
= get_symbol_end ();
2883 end_name
= input_line_pointer
;
2888 if (*input_line_pointer
!= ',')
2891 as_bad (_("expected comma after name \"%s\""), name
);
2893 ignore_rest_of_line ();
2897 input_line_pointer
++;
2900 if (name
[0] == '.' && name
[1] == '\0')
2902 /* XXX - this should not happen to .thumb_set. */
2906 if ((symbolP
= symbol_find (name
)) == NULL
2907 && (symbolP
= md_undefined_symbol (name
)) == NULL
)
2910 /* When doing symbol listings, play games with dummy fragments living
2911 outside the normal fragment chain to record the file and line info
2913 if (listing
& LISTING_SYMBOLS
)
2915 extern struct list_info_struct
* listing_tail
;
2916 fragS
* dummy_frag
= (fragS
*) xmalloc (sizeof (fragS
));
2918 memset (dummy_frag
, 0, sizeof (fragS
));
2919 dummy_frag
->fr_type
= rs_fill
;
2920 dummy_frag
->line
= listing_tail
;
2921 symbolP
= symbol_new (name
, undefined_section
, 0, dummy_frag
);
2922 dummy_frag
->fr_symbol
= symbolP
;
2926 symbolP
= symbol_new (name
, undefined_section
, 0, &zero_address_frag
);
2929 /* "set" symbols are local unless otherwise specified. */
2930 SF_SET_LOCAL (symbolP
);
2931 #endif /* OBJ_COFF */
2932 } /* Make a new symbol. */
2934 symbol_table_insert (symbolP
);
2939 && S_IS_DEFINED (symbolP
)
2940 && S_GET_SEGMENT (symbolP
) != reg_section
)
2941 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP
));
2943 pseudo_set (symbolP
);
2945 demand_empty_rest_of_line ();
2947 /* XXX Now we come to the Thumb specific bit of code. */
2949 THUMB_SET_FUNC (symbolP
, 1);
2950 ARM_SET_THUMB (symbolP
, 1);
2951 #if defined OBJ_ELF || defined OBJ_COFF
2952 ARM_SET_INTERWORK (symbolP
, support_interwork
);
2957 opcode_select (width
)
2965 if (! (cpu_variant
& ARM_EXT_V4T
))
2966 as_bad (_("selected processor does not support THUMB opcodes"));
2969 /* No need to force the alignment, since we will have been
2970 coming from ARM mode, which is word-aligned. */
2971 record_alignment (now_seg
, 1);
2978 if ((cpu_variant
& ARM_ALL
) == ARM_EXT_V4T
)
2979 as_bad (_("selected processor does not support ARM opcodes"));
2984 frag_align (2, 0, 0);
2986 record_alignment (now_seg
, 1);
2991 as_bad (_("invalid instruction size selected (%d)"), width
);
2997 int ignore ATTRIBUTE_UNUSED
;
3000 demand_empty_rest_of_line ();
3005 int ignore ATTRIBUTE_UNUSED
;
3008 demand_empty_rest_of_line ();
3013 int unused ATTRIBUTE_UNUSED
;
3017 temp
= get_absolute_expression ();
3022 opcode_select (temp
);
3026 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp
);
3034 skip_whitespace (str
);
3036 if (*str
!= '\0' && !inst
.error
)
3037 inst
.error
= _("garbage following instruction");
3041 skip_past_comma (str
)
3044 char * p
= * str
, c
;
3047 while ((c
= *p
) == ' ' || c
== ',')
3050 if (c
== ',' && comma
++)
3058 return comma
? SUCCESS
: FAIL
;
3061 /* A standard register must be given at this point.
3062 SHIFT is the place to put it in inst.instruction.
3063 Restores input start point on error.
3064 Returns the reg#, or FAIL. */
3067 reg_required_here (str
, shift
)
3071 static char buff
[128]; /* XXX */
3073 char * start
= * str
;
3075 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_RN
].htab
)) != FAIL
)
3078 inst
.instruction
|= reg
<< shift
;
3082 /* Restore the start point, we may have got a reg of the wrong class. */
3085 /* In the few cases where we might be able to accept something else
3086 this error can be overridden. */
3087 sprintf (buff
, _("register expected, not '%.100s'"), start
);
3093 /* A Intel Wireless MMX technology register
3094 must be given at this point.
3095 Shift is the place to put it in inst.instruction.
3096 Restores input start point on err.
3097 Returns the reg#, or FAIL. */
3100 wreg_required_here (str
, shift
, reg_type
)
3103 enum wreg_type reg_type
;
3105 static char buff
[128];
3107 char * start
= *str
;
3109 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_IWMMXT
].htab
)) != FAIL
)
3111 if (wr_register (reg
)
3112 && (reg_type
== IWMMXT_REG_WR
|| reg_type
== IWMMXT_REG_WR_OR_WC
))
3115 inst
.instruction
|= (reg
^ WR_PREFIX
) << shift
;
3118 else if (wc_register (reg
)
3119 && (reg_type
== IWMMXT_REG_WC
|| reg_type
== IWMMXT_REG_WR_OR_WC
))
3122 inst
.instruction
|= (reg
^ WC_PREFIX
) << shift
;
3125 else if ((wcg_register (reg
) && reg_type
== IWMMXT_REG_WCG
))
3128 inst
.instruction
|= ((reg
^ WC_PREFIX
) - 8) << shift
;
3133 /* Restore the start point, we may have got a reg of the wrong class. */
3136 /* In the few cases where we might be able to accept
3137 something else this error can be overridden. */
3138 sprintf (buff
, _("Intel Wireless MMX technology register expected, not '%.100s'"), start
);
3144 static const struct asm_psr
*
3146 register char ** ccp
;
3148 char * start
= * ccp
;
3151 const struct asm_psr
* psr
;
3155 /* Skip to the end of the next word in the input stream. */
3160 while (ISALPHA (c
) || c
== '_');
3162 /* Terminate the word. */
3165 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
3166 feature for ease of use and backwards compatibility. */
3167 if (!strncmp (start
, "cpsr", 4))
3168 strncpy (start
, "CPSR", 4);
3169 else if (!strncmp (start
, "spsr", 4))
3170 strncpy (start
, "SPSR", 4);
3172 /* Now locate the word in the psr hash table. */
3173 psr
= (const struct asm_psr
*) hash_find (arm_psr_hsh
, start
);
3175 /* Restore the input stream. */
3178 /* If we found a valid match, advance the
3179 stream pointer past the end of the word. */
3185 /* Parse the input looking for a PSR flag. */
3188 psr_required_here (str
)
3191 char * start
= * str
;
3192 const struct asm_psr
* psr
;
3194 psr
= arm_psr_parse (str
);
3198 /* If this is the SPSR that is being modified, set the R bit. */
3200 inst
.instruction
|= SPSR_BIT
;
3202 /* Set the psr flags in the MSR instruction. */
3203 inst
.instruction
|= psr
->field
<< PSR_SHIFT
;
3208 /* In the few cases where we might be able to accept
3209 something else this error can be overridden. */
3210 inst
.error
= _("flag for {c}psr instruction expected");
3212 /* Restore the start point. */
3218 co_proc_number (str
)
3221 int processor
, pchar
;
3224 skip_whitespace (*str
);
3227 /* The data sheet seems to imply that just a number on its own is valid
3228 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
3230 if ((processor
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CP
].htab
))
3236 if (pchar
>= '0' && pchar
<= '9')
3238 processor
= pchar
- '0';
3239 if (**str
>= '0' && **str
<= '9')
3241 processor
= processor
* 10 + *(*str
)++ - '0';
3244 inst
.error
= _("illegal co-processor number");
3251 inst
.error
= _("bad or missing co-processor number");
3256 inst
.instruction
|= processor
<< 8;
3261 cp_opc_expr (str
, where
, length
)
3268 skip_whitespace (* str
);
3270 memset (&expr
, '\0', sizeof (expr
));
3272 if (my_get_expression (&expr
, str
))
3274 if (expr
.X_op
!= O_constant
)
3276 inst
.error
= _("bad or missing expression");
3280 if ((expr
.X_add_number
& ((1 << length
) - 1)) != expr
.X_add_number
)
3282 inst
.error
= _("immediate co-processor expression too large");
3286 inst
.instruction
|= expr
.X_add_number
<< where
;
3291 cp_reg_required_here (str
, where
)
3296 char * start
= *str
;
3298 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CN
].htab
)) != FAIL
)
3300 inst
.instruction
|= reg
<< where
;
3304 /* In the few cases where we might be able to accept something else
3305 this error can be overridden. */
3306 inst
.error
= _("co-processor register expected");
3308 /* Restore the start point. */
3314 fp_reg_required_here (str
, where
)
3319 char * start
= * str
;
3321 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_FN
].htab
)) != FAIL
)
3323 inst
.instruction
|= reg
<< where
;
3327 /* In the few cases where we might be able to accept something else
3328 this error can be overridden. */
3329 inst
.error
= _("floating point register expected");
3331 /* Restore the start point. */
3337 cp_address_offset (str
)
3342 skip_whitespace (* str
);
3344 if (! is_immediate_prefix (**str
))
3346 inst
.error
= _("immediate expression expected");
3352 if (my_get_expression (& inst
.reloc
.exp
, str
))
3355 if (inst
.reloc
.exp
.X_op
== O_constant
)
3357 offset
= inst
.reloc
.exp
.X_add_number
;
3361 inst
.error
= _("co-processor address must be word aligned");
3365 if (offset
> 1023 || offset
< -1023)
3367 inst
.error
= _("offset too large");
3372 inst
.instruction
|= INDEX_UP
;
3376 inst
.instruction
|= offset
>> 2;
3379 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
3385 cp_address_required_here (str
, wb_ok
)
3398 skip_whitespace (p
);
3400 if ((reg
= reg_required_here (& p
, 16)) == FAIL
)
3403 skip_whitespace (p
);
3409 skip_whitespace (p
);
3413 /* As an extension to the official ARM syntax we allow:
3417 as a short hand for:
3420 inst
.instruction
|= PRE_INDEX
| INDEX_UP
;
3425 if (skip_past_comma (& p
) == FAIL
)
3427 inst
.error
= _("comma expected after closing square bracket");
3431 skip_whitespace (p
);
3438 write_back
= WRITE_BACK
;
3442 inst
.error
= _("pc may not be used in post-increment");
3446 if (cp_address_offset (& p
) == FAIL
)
3450 pre_inc
= PRE_INDEX
| INDEX_UP
;
3456 /* [Rn], {<expr>} */
3459 skip_whitespace (p
);
3461 if (my_get_expression (& inst
.reloc
.exp
, & p
))
3464 if (inst
.reloc
.exp
.X_op
== O_constant
)
3466 option
= inst
.reloc
.exp
.X_add_number
;
3468 if (option
> 255 || option
< 0)
3470 inst
.error
= _("'option' field too large");
3474 skip_whitespace (p
);
3478 inst
.error
= _("'}' expected at end of 'option' field");
3484 inst
.instruction
|= option
;
3485 inst
.instruction
|= INDEX_UP
;
3490 inst
.error
= _("non-constant expressions for 'option' field not supported");
3496 inst
.error
= _("# or { expected after comma");
3502 /* '['Rn, #expr']'[!] */
3504 if (skip_past_comma (& p
) == FAIL
)
3506 inst
.error
= _("pre-indexed expression expected");
3510 pre_inc
= PRE_INDEX
;
3512 if (cp_address_offset (& p
) == FAIL
)
3515 skip_whitespace (p
);
3519 inst
.error
= _("missing ]");
3523 skip_whitespace (p
);
3525 if (wb_ok
&& *p
== '!')
3529 inst
.error
= _("pc may not be used with write-back");
3534 write_back
= WRITE_BACK
;
3540 if (my_get_expression (&inst
.reloc
.exp
, &p
))
3543 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
3544 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
3545 inst
.reloc
.pc_rel
= 1;
3546 inst
.instruction
|= (REG_PC
<< 16);
3547 pre_inc
= PRE_INDEX
;
3550 inst
.instruction
|= write_back
| pre_inc
;
3556 cp_byte_address_offset (str
)
3561 skip_whitespace (* str
);
3563 if (! is_immediate_prefix (**str
))
3565 inst
.error
= _("immediate expression expected");
3571 if (my_get_expression (& inst
.reloc
.exp
, str
))
3574 if (inst
.reloc
.exp
.X_op
== O_constant
)
3576 offset
= inst
.reloc
.exp
.X_add_number
;
3578 if (offset
> 255 || offset
< -255)
3580 inst
.error
= _("offset too large");
3585 inst
.instruction
|= INDEX_UP
;
3589 inst
.instruction
|= offset
;
3592 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM_S2
;
3598 cp_byte_address_required_here (str
)
3610 skip_whitespace (p
);
3612 if ((reg
= reg_required_here (& p
, 16)) == FAIL
)
3615 skip_whitespace (p
);
3621 if (skip_past_comma (& p
) == SUCCESS
)
3624 write_back
= WRITE_BACK
;
3628 inst
.error
= _("pc may not be used in post-increment");
3632 if (cp_byte_address_offset (& p
) == FAIL
)
3636 pre_inc
= PRE_INDEX
| INDEX_UP
;
3640 /* '['Rn, #expr']'[!] */
3642 if (skip_past_comma (& p
) == FAIL
)
3644 inst
.error
= _("pre-indexed expression expected");
3648 pre_inc
= PRE_INDEX
;
3650 if (cp_byte_address_offset (& p
) == FAIL
)
3653 skip_whitespace (p
);
3657 inst
.error
= _("missing ]");
3661 skip_whitespace (p
);
3667 inst
.error
= _("pc may not be used with write-back");
3672 write_back
= WRITE_BACK
;
3678 if (my_get_expression (&inst
.reloc
.exp
, &p
))
3681 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM_S2
;
3682 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
3683 inst
.reloc
.pc_rel
= 1;
3684 inst
.instruction
|= (REG_PC
<< 16);
3685 pre_inc
= PRE_INDEX
;
3688 inst
.instruction
|= write_back
| pre_inc
;
3697 /* Do nothing really. */
3708 /* Only one syntax. */
3709 skip_whitespace (str
);
3711 if (reg_required_here (&str
, 12) == FAIL
)
3713 inst
.error
= BAD_ARGS
;
3717 if (skip_past_comma (&str
) == FAIL
)
3719 inst
.error
= _("comma expected after register name");
3723 skip_whitespace (str
);
3725 if ( strcmp (str
, "CPSR") == 0
3726 || strcmp (str
, "SPSR") == 0
3727 /* Lower case versions for backwards compatability. */
3728 || strcmp (str
, "cpsr") == 0
3729 || strcmp (str
, "spsr") == 0)
3732 /* This is for backwards compatability with older toolchains. */
3733 else if ( strcmp (str
, "cpsr_all") == 0
3734 || strcmp (str
, "spsr_all") == 0)
3738 inst
.error
= _("CPSR or SPSR expected");
3742 if (* str
== 's' || * str
== 'S')
3743 inst
.instruction
|= SPSR_BIT
;
3749 /* Two possible forms:
3750 "{C|S}PSR_<field>, Rm",
3751 "{C|S}PSR_f, #expression". */
3757 skip_whitespace (str
);
3759 if (psr_required_here (& str
) == FAIL
)
3762 if (skip_past_comma (& str
) == FAIL
)
3764 inst
.error
= _("comma missing after psr flags");
3768 skip_whitespace (str
);
3770 if (reg_required_here (& str
, 0) != FAIL
)
3777 if (! is_immediate_prefix (* str
))
3780 _("only a register or immediate value can follow a psr flag");
3787 if (my_get_expression (& inst
.reloc
.exp
, & str
))
3790 _("only a register or immediate value can follow a psr flag");
3794 #if 0 /* The first edition of the ARM architecture manual stated that
3795 writing anything other than the flags with an immediate operation
3796 had UNPREDICTABLE effects. This constraint was removed in the
3797 second edition of the specification. */
3798 if ((cpu_variant
& ARM_EXT_V5
) != ARM_EXT_V5
3799 && inst
.instruction
& ((PSR_c
| PSR_x
| PSR_s
) << PSR_SHIFT
))
3801 inst
.error
= _("immediate value cannot be used to set this field");
3806 inst
.instruction
|= INST_IMMEDIATE
;
3808 if (inst
.reloc
.exp
.X_add_symbol
)
3810 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
3811 inst
.reloc
.pc_rel
= 0;
3815 unsigned value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
3817 if (value
== (unsigned) FAIL
)
3819 inst
.error
= _("invalid constant");
3823 inst
.instruction
|= value
;
3830 /* Long Multiply Parser
3831 UMULL RdLo, RdHi, Rm, Rs
3832 SMULL RdLo, RdHi, Rm, Rs
3833 UMLAL RdLo, RdHi, Rm, Rs
3834 SMLAL RdLo, RdHi, Rm, Rs. */
3840 int rdlo
, rdhi
, rm
, rs
;
3842 /* Only one format "rdlo, rdhi, rm, rs". */
3843 skip_whitespace (str
);
3845 if ((rdlo
= reg_required_here (&str
, 12)) == FAIL
)
3847 inst
.error
= BAD_ARGS
;
3851 if (skip_past_comma (&str
) == FAIL
3852 || (rdhi
= reg_required_here (&str
, 16)) == FAIL
)
3854 inst
.error
= BAD_ARGS
;
3858 if (skip_past_comma (&str
) == FAIL
3859 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
3861 inst
.error
= BAD_ARGS
;
3865 /* rdhi, rdlo and rm must all be different. */
3866 if (rdlo
== rdhi
|| rdlo
== rm
|| rdhi
== rm
)
3867 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
3869 if (skip_past_comma (&str
) == FAIL
3870 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
3872 inst
.error
= BAD_ARGS
;
3876 if (rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
)
3878 inst
.error
= BAD_PC
;
3892 /* Only one format "rd, rm, rs". */
3893 skip_whitespace (str
);
3895 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
3897 inst
.error
= BAD_ARGS
;
3903 inst
.error
= BAD_PC
;
3907 if (skip_past_comma (&str
) == FAIL
3908 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
3910 inst
.error
= BAD_ARGS
;
3916 inst
.error
= BAD_PC
;
3921 as_tsktsk (_("rd and rm should be different in mul"));
3923 if (skip_past_comma (&str
) == FAIL
3924 || (rm
= reg_required_here (&str
, 8)) == FAIL
)
3926 inst
.error
= BAD_ARGS
;
3932 inst
.error
= BAD_PC
;
3946 /* Only one format "rd, rm, rs, rn". */
3947 skip_whitespace (str
);
3949 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
3951 inst
.error
= BAD_ARGS
;
3957 inst
.error
= BAD_PC
;
3961 if (skip_past_comma (&str
) == FAIL
3962 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
3964 inst
.error
= BAD_ARGS
;
3970 inst
.error
= BAD_PC
;
3975 as_tsktsk (_("rd and rm should be different in mla"));
3977 if (skip_past_comma (&str
) == FAIL
3978 || (rd
= reg_required_here (&str
, 8)) == FAIL
3979 || skip_past_comma (&str
) == FAIL
3980 || (rm
= reg_required_here (&str
, 12)) == FAIL
)
3982 inst
.error
= BAD_ARGS
;
3986 if (rd
== REG_PC
|| rm
== REG_PC
)
3988 inst
.error
= BAD_PC
;
3996 /* Expects *str -> the characters "acc0", possibly with leading blanks.
3997 Advances *str to the next non-alphanumeric.
3998 Returns 0, or else FAIL (in which case sets inst.error).
4000 (In a future XScale, there may be accumulators other than zero.
4001 At that time this routine and its callers can be upgraded to suit.) */
4004 accum0_required_here (str
)
4007 static char buff
[128]; /* Note the address is taken. Hence, static. */
4010 int result
= 0; /* The accum number. */
4012 skip_whitespace (p
);
4014 *str
= p
; /* Advance caller's string pointer too. */
4019 *--p
= 0; /* Aap nul into input buffer at non-alnum. */
4021 if (! ( streq (*str
, "acc0") || streq (*str
, "ACC0")))
4023 sprintf (buff
, _("acc0 expected, not '%.100s'"), *str
);
4028 *p
= c
; /* Unzap. */
4029 *str
= p
; /* Caller's string pointer to after match. */
4033 /* Expects **str -> after a comma. May be leading blanks.
4034 Advances *str, recognizing a load mode, and setting inst.instruction.
4035 Returns rn, or else FAIL (in which case may set inst.error
4036 and not advance str)
4038 Note: doesn't know Rd, so no err checks that require such knowledge. */
4041 ld_mode_required_here (string
)
4044 char * str
= * string
;
4048 skip_whitespace (str
);
4054 skip_whitespace (str
);
4056 if ((rn
= reg_required_here (& str
, 16)) == FAIL
)
4059 skip_whitespace (str
);
4065 if (skip_past_comma (& str
) == SUCCESS
)
4067 /* [Rn],... (post inc) */
4068 if (ldst_extend_v4 (&str
) == FAIL
)
4073 skip_whitespace (str
);
4078 inst
.instruction
|= WRITE_BACK
;
4081 inst
.instruction
|= INDEX_UP
| HWOFFSET_IMM
;
4087 if (skip_past_comma (& str
) == FAIL
)
4089 inst
.error
= _("pre-indexed expression expected");
4095 if (ldst_extend_v4 (&str
) == FAIL
)
4098 skip_whitespace (str
);
4100 if (* str
++ != ']')
4102 inst
.error
= _("missing ]");
4106 skip_whitespace (str
);
4111 inst
.instruction
|= WRITE_BACK
;
4115 else if (* str
== '=') /* ldr's "r,=label" syntax */
4116 /* We should never reach here, because <text> = <expression> is
4117 caught gas/read.c read_a_source_file() as a .set operation. */
4119 else /* PC +- 8 bit immediate offset. */
4121 if (my_get_expression (& inst
.reloc
.exp
, & str
))
4124 inst
.instruction
|= HWOFFSET_IMM
; /* The I bit. */
4125 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
4126 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
4127 inst
.reloc
.pc_rel
= 1;
4128 inst
.instruction
|= (REG_PC
<< 16);
4134 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
4140 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
4141 SMLAxy{cond} Rd,Rm,Rs,Rn
4142 SMLAWy{cond} Rd,Rm,Rs,Rn
4143 Error if any register is R15. */
4151 skip_whitespace (str
);
4153 if ((rd
= reg_required_here (& str
, 16)) == FAIL
4154 || skip_past_comma (& str
) == FAIL
4155 || (rm
= reg_required_here (& str
, 0)) == FAIL
4156 || skip_past_comma (& str
) == FAIL
4157 || (rs
= reg_required_here (& str
, 8)) == FAIL
4158 || skip_past_comma (& str
) == FAIL
4159 || (rn
= reg_required_here (& str
, 12)) == FAIL
)
4160 inst
.error
= BAD_ARGS
;
4162 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
|| rn
== REG_PC
)
4163 inst
.error
= BAD_PC
;
4169 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
4170 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
4171 Error if any register is R15.
4172 Warning if Rdlo == Rdhi. */
4178 int rdlo
, rdhi
, rm
, rs
;
4180 skip_whitespace (str
);
4182 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
4183 || skip_past_comma (& str
) == FAIL
4184 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
4185 || skip_past_comma (& str
) == FAIL
4186 || (rm
= reg_required_here (& str
, 0)) == FAIL
4187 || skip_past_comma (& str
) == FAIL
4188 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
4190 inst
.error
= BAD_ARGS
;
4194 if (rdlo
== REG_PC
|| rdhi
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
4196 inst
.error
= BAD_PC
;
4201 as_tsktsk (_("rdhi and rdlo must be different"));
4206 /* ARM V5E (El Segundo) signed-multiply (argument parse)
4207 SMULxy{cond} Rd,Rm,Rs
4208 Error if any register is R15. */
4216 skip_whitespace (str
);
4218 if ((rd
= reg_required_here (& str
, 16)) == FAIL
4219 || skip_past_comma (& str
) == FAIL
4220 || (rm
= reg_required_here (& str
, 0)) == FAIL
4221 || skip_past_comma (& str
) == FAIL
4222 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
4223 inst
.error
= BAD_ARGS
;
4225 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
4226 inst
.error
= BAD_PC
;
4232 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
4233 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
4234 Error if any register is R15. */
4242 skip_whitespace (str
);
4244 if ((rd
= reg_required_here (& str
, 12)) == FAIL
4245 || skip_past_comma (& str
) == FAIL
4246 || (rm
= reg_required_here (& str
, 0)) == FAIL
4247 || skip_past_comma (& str
) == FAIL
4248 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
4249 inst
.error
= BAD_ARGS
;
4251 else if (rd
== REG_PC
|| rm
== REG_PC
|| rn
== REG_PC
)
4252 inst
.error
= BAD_PC
;
4258 /* ARM V5E (el Segundo)
4259 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4260 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4262 These are equivalent to the XScale instructions MAR and MRA,
4263 respectively, when coproc == 0, opcode == 0, and CRm == 0.
4265 Result unpredicatable if Rd or Rn is R15. */
4273 skip_whitespace (str
);
4275 if (co_proc_number (& str
) == FAIL
)
4278 inst
.error
= BAD_ARGS
;
4282 if (skip_past_comma (& str
) == FAIL
4283 || cp_opc_expr (& str
, 4, 4) == FAIL
)
4286 inst
.error
= BAD_ARGS
;
4290 if (skip_past_comma (& str
) == FAIL
4291 || (rd
= reg_required_here (& str
, 12)) == FAIL
)
4294 inst
.error
= BAD_ARGS
;
4298 if (skip_past_comma (& str
) == FAIL
4299 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
4302 inst
.error
= BAD_ARGS
;
4306 /* Unpredictable result if rd or rn is R15. */
4307 if (rd
== REG_PC
|| rn
== REG_PC
)
4309 (_("Warning: instruction unpredictable when using r15"));
4311 if (skip_past_comma (& str
) == FAIL
4312 || cp_reg_required_here (& str
, 0) == FAIL
)
4315 inst
.error
= BAD_ARGS
;
4322 /* ARM V5 count-leading-zeroes instruction (argument parse)
4323 CLZ{<cond>} <Rd>, <Rm>
4324 Condition defaults to COND_ALWAYS.
4325 Error if Rd or Rm are R15. */
4333 skip_whitespace (str
);
4335 if (((rd
= reg_required_here (& str
, 12)) == FAIL
)
4336 || (skip_past_comma (& str
) == FAIL
)
4337 || ((rm
= reg_required_here (& str
, 0)) == FAIL
))
4338 inst
.error
= BAD_ARGS
;
4340 else if (rd
== REG_PC
|| rm
== REG_PC
)
4341 inst
.error
= BAD_PC
;
4347 /* ARM V5 (argument parse)
4348 LDC2{L} <coproc>, <CRd>, <addressing mode>
4349 STC2{L} <coproc>, <CRd>, <addressing mode>
4350 Instruction is not conditional, and has 0xf in the codition field.
4351 Otherwise, it's the same as LDC/STC. */
4357 skip_whitespace (str
);
4359 if (co_proc_number (& str
) == FAIL
)
4362 inst
.error
= BAD_ARGS
;
4364 else if (skip_past_comma (& str
) == FAIL
4365 || cp_reg_required_here (& str
, 12) == FAIL
)
4368 inst
.error
= BAD_ARGS
;
4370 else if (skip_past_comma (& str
) == FAIL
4371 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
4374 inst
.error
= BAD_ARGS
;
4380 /* ARM V5 (argument parse)
4381 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
4382 Instruction is not conditional, and has 0xf in the condition field.
4383 Otherwise, it's the same as CDP. */
4389 skip_whitespace (str
);
4391 if (co_proc_number (& str
) == FAIL
)
4394 inst
.error
= BAD_ARGS
;
4398 if (skip_past_comma (& str
) == FAIL
4399 || cp_opc_expr (& str
, 20,4) == FAIL
)
4402 inst
.error
= BAD_ARGS
;
4406 if (skip_past_comma (& str
) == FAIL
4407 || cp_reg_required_here (& str
, 12) == FAIL
)
4410 inst
.error
= BAD_ARGS
;
4414 if (skip_past_comma (& str
) == FAIL
4415 || cp_reg_required_here (& str
, 16) == FAIL
)
4418 inst
.error
= BAD_ARGS
;
4422 if (skip_past_comma (& str
) == FAIL
4423 || cp_reg_required_here (& str
, 0) == FAIL
)
4426 inst
.error
= BAD_ARGS
;
4430 if (skip_past_comma (& str
) == SUCCESS
)
4432 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
4435 inst
.error
= BAD_ARGS
;
4443 /* ARM V5 (argument parse)
4444 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4445 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4446 Instruction is not conditional, and has 0xf in the condition field.
4447 Otherwise, it's the same as MCR/MRC. */
4453 skip_whitespace (str
);
4455 if (co_proc_number (& str
) == FAIL
)
4458 inst
.error
= BAD_ARGS
;
4462 if (skip_past_comma (& str
) == FAIL
4463 || cp_opc_expr (& str
, 21, 3) == FAIL
)
4466 inst
.error
= BAD_ARGS
;
4470 if (skip_past_comma (& str
) == FAIL
4471 || reg_required_here (& str
, 12) == FAIL
)
4474 inst
.error
= BAD_ARGS
;
4478 if (skip_past_comma (& str
) == FAIL
4479 || cp_reg_required_here (& str
, 16) == FAIL
)
4482 inst
.error
= BAD_ARGS
;
4486 if (skip_past_comma (& str
) == FAIL
4487 || cp_reg_required_here (& str
, 0) == FAIL
)
4490 inst
.error
= BAD_ARGS
;
4494 if (skip_past_comma (& str
) == SUCCESS
)
4496 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
4499 inst
.error
= BAD_ARGS
;
4507 /* ARM v5TEJ. Jump to Jazelle code. */
4514 skip_whitespace (str
);
4516 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
4518 inst
.error
= BAD_ARGS
;
4522 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
4524 as_tsktsk (_("use of r15 in bxj is not really useful"));
4529 /* THUMB V5 breakpoint instruction (argument parse)
4537 unsigned long number
;
4539 skip_whitespace (str
);
4541 /* Allow optional leading '#'. */
4542 if (is_immediate_prefix (*str
))
4545 memset (& expr
, '\0', sizeof (expr
));
4546 if (my_get_expression (& expr
, & str
)
4547 || (expr
.X_op
!= O_constant
4548 /* As a convenience we allow 'bkpt' without an operand. */
4549 && expr
.X_op
!= O_absent
))
4551 inst
.error
= _("bad expression");
4555 number
= expr
.X_add_number
;
4557 /* Check it fits an 8 bit unsigned. */
4558 if (number
!= (number
& 0xff))
4560 inst
.error
= _("immediate value out of range");
4564 inst
.instruction
|= number
;
4569 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
4570 Expects inst.instruction is set for BLX(1).
4571 Note: this is cloned from do_branch, and the reloc changed to be a
4572 new one that can cope with setting one extra bit (the H bit). */
4578 if (my_get_expression (& inst
.reloc
.exp
, & str
))
4585 /* ScottB: February 5, 1998 */
4586 /* Check to see of PLT32 reloc required for the instruction. */
4588 /* arm_parse_reloc() works on input_line_pointer.
4589 We actually want to parse the operands to the branch instruction
4590 passed in 'str'. Save the input pointer and restore it later. */
4591 save_in
= input_line_pointer
;
4592 input_line_pointer
= str
;
4594 if (inst
.reloc
.exp
.X_op
== O_symbol
4596 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
4598 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
4599 inst
.reloc
.pc_rel
= 0;
4600 /* Modify str to point to after parsed operands, otherwise
4601 end_of_line() will complain about the (PLT) left in str. */
4602 str
= input_line_pointer
;
4606 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
4607 inst
.reloc
.pc_rel
= 1;
4610 input_line_pointer
= save_in
;
4613 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
4614 inst
.reloc
.pc_rel
= 1;
4615 #endif /* OBJ_ELF */
4620 /* ARM V5 branch-link-exchange instruction (argument parse)
4621 BLX <target_addr> ie BLX(1)
4622 BLX{<condition>} <Rm> ie BLX(2)
4623 Unfortunately, there are two different opcodes for this mnemonic.
4624 So, the insns[].value is not used, and the code here zaps values
4625 into inst.instruction.
4626 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
4635 skip_whitespace (mystr
);
4636 rm
= reg_required_here (& mystr
, 0);
4638 /* The above may set inst.error. Ignore his opinion. */
4643 /* Arg is a register.
4644 Use the condition code our caller put in inst.instruction.
4645 Pass ourselves off as a BX with a funny opcode. */
4646 inst
.instruction
|= 0x012fff30;
4651 /* This must be is BLX <target address>, no condition allowed. */
4652 if (inst
.instruction
!= COND_ALWAYS
)
4654 inst
.error
= BAD_COND
;
4658 inst
.instruction
= 0xfafffffe;
4660 /* Process like a B/BL, but with a different reloc.
4661 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
4666 /* ARM V5 Thumb BLX (argument parse)
4667 BLX <target_addr> which is BLX(1)
4668 BLX <Rm> which is BLX(2)
4669 Unfortunately, there are two different opcodes for this mnemonic.
4670 So, the tinsns[].value is not used, and the code here zaps values
4671 into inst.instruction. */
4680 skip_whitespace (mystr
);
4681 inst
.instruction
= 0x4780;
4683 /* Note that this call is to the ARM register recognizer. BLX(2)
4684 uses the ARM register space, not the Thumb one, so a call to
4685 thumb_reg() would be wrong. */
4686 rm
= reg_required_here (& mystr
, 3);
4691 /* It's BLX(2). The .instruction was zapped with rm & is final. */
4696 /* No ARM register. This must be BLX(1). Change the .instruction. */
4697 inst
.instruction
= 0xf7ffeffe;
4700 if (my_get_expression (& inst
.reloc
.exp
, & mystr
))
4703 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BLX
;
4704 inst
.reloc
.pc_rel
= 1;
4707 end_of_line (mystr
);
4710 /* ARM V5 breakpoint instruction (argument parse)
4711 BKPT <16 bit unsigned immediate>
4712 Instruction is not conditional.
4713 The bit pattern given in insns[] has the COND_ALWAYS condition,
4714 and it is an error if the caller tried to override that. */
4721 unsigned long number
;
4723 skip_whitespace (str
);
4725 /* Allow optional leading '#'. */
4726 if (is_immediate_prefix (* str
))
4729 memset (& expr
, '\0', sizeof (expr
));
4731 if (my_get_expression (& expr
, & str
)
4732 || (expr
.X_op
!= O_constant
4733 /* As a convenience we allow 'bkpt' without an operand. */
4734 && expr
.X_op
!= O_absent
))
4736 inst
.error
= _("bad expression");
4740 number
= expr
.X_add_number
;
4742 /* Check it fits a 16 bit unsigned. */
4743 if (number
!= (number
& 0xffff))
4745 inst
.error
= _("immediate value out of range");
4749 /* Top 12 of 16 bits to bits 19:8. */
4750 inst
.instruction
|= (number
& 0xfff0) << 4;
4752 /* Bottom 4 of 16 bits to bits 3:0. */
4753 inst
.instruction
|= number
& 0xf;
4758 static unsigned long check_iwmmxt_insn
PARAMS ((char *, enum iwmmxt_insn_type
, int));
4760 /* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
4762 static unsigned long
4763 check_iwmmxt_insn (str
, insn_type
, immediate_size
)
4765 enum iwmmxt_insn_type insn_type
;
4769 const char * inst_error
;
4771 unsigned long number
;
4773 inst_error
= inst
.error
;
4775 inst
.error
= BAD_ARGS
;
4776 skip_whitespace (str
);
4781 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
4786 if ((wreg_required_here (&str
, 0, IWMMXT_REG_WR
)) == FAIL
)
4791 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
4792 || skip_past_comma (&str
) == FAIL
4793 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
))
4798 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
4799 || skip_past_comma (&str
) == FAIL
4800 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4801 || skip_past_comma (&str
) == FAIL
4802 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
))
4807 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
4808 || skip_past_comma (&str
) == FAIL
4809 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4810 || skip_past_comma (&str
) == FAIL
4811 || wreg_required_here (&str
, 0, IWMMXT_REG_WCG
) == FAIL
))
4816 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4817 || skip_past_comma (&str
) == FAIL
4818 || reg_required_here (&str
, 12) == FAIL
))
4823 if ((reg_required_here (&str
, 12) == FAIL
4824 || skip_past_comma (&str
) == FAIL
4825 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
))
4830 if ((wreg_required_here (&str
, 5, IWMMXT_REG_WR
) == FAIL
4831 || skip_past_comma (&str
) == FAIL
4832 || reg_required_here (&str
, 0) == FAIL
4833 || skip_past_comma (&str
) == FAIL
4834 || reg_required_here (&str
, 12) == FAIL
))
4839 if ((wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
4840 || skip_past_comma (&str
) == FAIL
4841 || reg_required_here (&str
, 12) == FAIL
4842 || skip_past_comma (&str
) == FAIL
4843 || reg_required_here (&str
, 16) == FAIL
))
4848 if ((reg_required_here (&str
, 12) == FAIL
4849 || skip_past_comma (&str
) == FAIL
4850 || reg_required_here (&str
, 16) == FAIL
4851 || skip_past_comma (&str
) == FAIL
4852 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
))
4857 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WC
) == FAIL
4858 || skip_past_comma (&str
) == FAIL
4859 || reg_required_here (&str
, 12) == FAIL
))
4864 if ((reg_required_here (&str
, 12) == FAIL
4865 || skip_past_comma (&str
) == FAIL
4866 || wreg_required_here (&str
, 16, IWMMXT_REG_WC
) == FAIL
))
4871 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4872 || skip_past_comma (&str
) == FAIL
4873 || reg_required_here (&str
, 12) == FAIL
4874 || skip_past_comma (&str
) == FAIL
))
4879 if ((reg_required_here (&str
, 12) == FAIL
4880 || skip_past_comma (&str
) == FAIL
))
4885 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
4886 || skip_past_comma (&str
) == FAIL
4887 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4888 || skip_past_comma (&str
) == FAIL
4889 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
4890 || skip_past_comma (&str
) == FAIL
))
4895 if ((reg_required_here (&str
, 12) == FAIL
4896 || skip_past_comma (&str
) == FAIL
4897 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4898 || skip_past_comma (&str
) == FAIL
))
4903 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
4904 || skip_past_comma (&str
) == FAIL
4905 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4906 || skip_past_comma (&str
) == FAIL
))
4911 if (immediate_size
== 0)
4914 inst
.error
= inst_error
;
4919 skip_whitespace (str
);
4921 /* Allow optional leading '#'. */
4922 if (is_immediate_prefix (* str
))
4925 memset (& expr
, '\0', sizeof (expr
));
4927 if (my_get_expression (& expr
, & str
) || (expr
.X_op
!= O_constant
))
4929 inst
.error
= _("bad or missing expression");
4933 number
= expr
.X_add_number
;
4935 if (number
!= (number
& immediate_size
))
4937 inst
.error
= _("immediate value out of range");
4941 inst
.error
= inst_error
;
4947 do_iwmmxt_byte_addr (str
)
4950 int op
= (inst
.instruction
& 0x300) >> 8;
4953 inst
.instruction
&= ~0x300;
4954 inst
.instruction
|= (op
& 1) << 22 | (op
& 2) << 7;
4956 skip_whitespace (str
);
4958 if ((reg
= wreg_required_here (&str
, 12, IWMMXT_REG_WR_OR_WC
)) == FAIL
4959 || skip_past_comma (& str
) == FAIL
4960 || cp_byte_address_required_here (&str
) == FAIL
)
4963 inst
.error
= BAD_ARGS
;
4968 if (wc_register (reg
))
4970 as_bad (_("non-word size not supported with control register"));
4971 inst
.instruction
|= 0xf0000100;
4972 inst
.instruction
&= ~0x00400000;
4977 do_iwmmxt_tandc (str
)
4982 reg
= check_iwmmxt_insn (str
, check_rd
, 0);
4984 if (reg
!= REG_PC
&& !inst
.error
)
4985 inst
.error
= _("only r15 allowed here");
4990 do_iwmmxt_tbcst (str
)
4993 check_iwmmxt_insn (str
, check_tbcst
, 0);
4999 do_iwmmxt_textrc (str
)
5002 unsigned long number
;
5004 if ((number
= check_iwmmxt_insn (str
, check_textrc
, 7)) == (unsigned long) FAIL
)
5007 inst
.instruction
|= number
& 0x7;
5012 do_iwmmxt_textrm (str
)
5015 unsigned long number
;
5017 if ((number
= check_iwmmxt_insn (str
, check_textrm
, 7)) == (unsigned long) FAIL
)
5020 inst
.instruction
|= number
& 0x7;
5024 do_iwmmxt_tinsr (str
)
5027 unsigned long number
;
5029 if ((number
= check_iwmmxt_insn (str
, check_tinsr
, 7)) == (unsigned long) FAIL
)
5032 inst
.instruction
|= number
& 0x7;
5037 do_iwmmxt_tmcr (str
)
5040 check_iwmmxt_insn (str
, check_tmcr
, 0);
5046 do_iwmmxt_tmcrr (str
)
5049 check_iwmmxt_insn (str
, check_tmcrr
, 0);
5055 do_iwmmxt_tmia (str
)
5058 check_iwmmxt_insn (str
, check_tmia
, 0);
5064 do_iwmmxt_tmovmsk (str
)
5067 check_iwmmxt_insn (str
, check_tmovmsk
, 0);
5073 do_iwmmxt_tmrc (str
)
5076 check_iwmmxt_insn (str
, check_tmrc
, 0);
5082 do_iwmmxt_tmrrc (str
)
5085 check_iwmmxt_insn (str
, check_tmrrc
, 0);
5091 do_iwmmxt_torc (str
)
5094 check_iwmmxt_insn (str
, check_rd
, 0);
5099 do_iwmmxt_waligni (str
)
5102 unsigned long number
;
5104 if ((number
= check_iwmmxt_insn (str
, check_waligni
, 7)) == (unsigned long) FAIL
)
5107 inst
.instruction
|= ((number
& 0x7) << 20);
5112 do_iwmmxt_wmov (str
)
5115 if (check_iwmmxt_insn (str
, check_wrwr
, 0) == (unsigned long) FAIL
)
5118 inst
.instruction
|= ((inst
.instruction
>> 16) & 0xf);
5123 do_iwmmxt_word_addr (str
)
5126 int op
= (inst
.instruction
& 0x300) >> 8;
5129 inst
.instruction
&= ~0x300;
5130 inst
.instruction
|= (op
& 1) << 22 | (op
& 2) << 7;
5132 skip_whitespace (str
);
5134 if ((reg
= wreg_required_here (&str
, 12, IWMMXT_REG_WR_OR_WC
)) == FAIL
5135 || skip_past_comma (& str
) == FAIL
5136 || cp_address_required_here (& str
, CP_WB_OK
) == FAIL
)
5139 inst
.error
= BAD_ARGS
;
5144 if (wc_register (reg
))
5146 if ((inst
.instruction
& COND_MASK
) != COND_ALWAYS
)
5147 as_bad (_("conditional execution not supported with control register"));
5149 as_bad (_("non-word size not supported with control register"));
5150 inst
.instruction
|= 0xf0000100;
5151 inst
.instruction
&= ~0x00400000;
5156 do_iwmmxt_wrwr (str
)
5159 check_iwmmxt_insn (str
, check_wrwr
, 0);
5165 do_iwmmxt_wrwrwcg (str
)
5168 check_iwmmxt_insn (str
, check_wrwrwcg
, 0);
5174 do_iwmmxt_wrwrwr (str
)
5177 check_iwmmxt_insn (str
, check_wrwrwr
, 0);
5183 do_iwmmxt_wshufh (str
)
5186 unsigned long number
;
5188 if ((number
= check_iwmmxt_insn (str
, check_wshufh
, 0xff)) == (unsigned long) FAIL
)
5191 inst
.instruction
|= ((number
& 0xf0) << 16) | (number
& 0xf);
5196 do_iwmmxt_wzero (str
)
5199 if (check_iwmmxt_insn (str
, check_wr
, 0) == (unsigned long) FAIL
)
5202 inst
.instruction
|= ((inst
.instruction
& 0xf) << 12) | ((inst
.instruction
& 0xf) << 16);
5206 /* Xscale multiply-accumulate (argument parse)
5209 MIAxycc acc0,Rm,Rs. */
5218 if (accum0_required_here (& str
) == FAIL
)
5219 inst
.error
= ERR_NO_ACCUM
;
5221 else if (skip_past_comma (& str
) == FAIL
5222 || (rm
= reg_required_here (& str
, 0)) == FAIL
)
5223 inst
.error
= BAD_ARGS
;
5225 else if (skip_past_comma (& str
) == FAIL
5226 || (rs
= reg_required_here (& str
, 12)) == FAIL
)
5227 inst
.error
= BAD_ARGS
;
5229 /* inst.instruction has now been zapped with both rm and rs. */
5230 else if (rm
== REG_PC
|| rs
== REG_PC
)
5231 inst
.error
= BAD_PC
; /* Undefined result if rm or rs is R15. */
5237 /* Xscale move-accumulator-register (argument parse)
5239 MARcc acc0,RdLo,RdHi. */
5247 if (accum0_required_here (& str
) == FAIL
)
5248 inst
.error
= ERR_NO_ACCUM
;
5250 else if (skip_past_comma (& str
) == FAIL
5251 || (rdlo
= reg_required_here (& str
, 12)) == FAIL
)
5252 inst
.error
= BAD_ARGS
;
5254 else if (skip_past_comma (& str
) == FAIL
5255 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
5256 inst
.error
= BAD_ARGS
;
5258 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5259 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
5260 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
5266 /* Xscale move-register-accumulator (argument parse)
5268 MRAcc RdLo,RdHi,acc0. */
5277 skip_whitespace (str
);
5279 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
)
5280 inst
.error
= BAD_ARGS
;
5282 else if (skip_past_comma (& str
) == FAIL
5283 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
5284 inst
.error
= BAD_ARGS
;
5286 else if (skip_past_comma (& str
) == FAIL
5287 || accum0_required_here (& str
) == FAIL
)
5288 inst
.error
= ERR_NO_ACCUM
;
5290 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5291 else if (rdlo
== rdhi
)
5292 inst
.error
= BAD_ARGS
; /* Undefined result if 2 writes to same reg. */
5294 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
5295 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
5300 /* ARMv5TE: Preload-Cache
5304 Syntactically, like LDR with B=1, W=0, L=1. */
5312 skip_whitespace (str
);
5316 inst
.error
= _("'[' expected after PLD mnemonic");
5321 skip_whitespace (str
);
5323 if ((rd
= reg_required_here (& str
, 16)) == FAIL
)
5326 skip_whitespace (str
);
5332 skip_whitespace (str
);
5334 /* Post-indexed addressing is not allowed with PLD. */
5335 if (skip_past_comma (&str
) == SUCCESS
)
5338 = _("post-indexed expression used in preload instruction");
5341 else if (*str
== '!') /* [Rn]! */
5343 inst
.error
= _("writeback used in preload instruction");
5347 inst
.instruction
|= INDEX_UP
| PRE_INDEX
;
5349 else /* [Rn, ...] */
5351 if (skip_past_comma (& str
) == FAIL
)
5353 inst
.error
= _("pre-indexed expression expected");
5357 if (ldst_extend (&str
) == FAIL
)
5360 skip_whitespace (str
);
5364 inst
.error
= _("missing ]");
5369 skip_whitespace (str
);
5371 if (* str
== '!') /* [Rn]! */
5373 inst
.error
= _("writeback used in preload instruction");
5377 inst
.instruction
|= PRE_INDEX
;
5383 /* ARMv5TE load-consecutive (argument parse)
5396 skip_whitespace (str
);
5398 if ((rd
= reg_required_here (& str
, 12)) == FAIL
)
5400 inst
.error
= BAD_ARGS
;
5404 if (skip_past_comma (& str
) == FAIL
5405 || (rn
= ld_mode_required_here (& str
)) == FAIL
)
5408 inst
.error
= BAD_ARGS
;
5412 /* inst.instruction has now been zapped with Rd and the addressing mode. */
5413 if (rd
& 1) /* Unpredictable result if Rd is odd. */
5415 inst
.error
= _("destination register must be even");
5421 inst
.error
= _("r14 not allowed here");
5425 if (((rd
== rn
) || (rd
+ 1 == rn
))
5426 && ((inst
.instruction
& WRITE_BACK
)
5427 || (!(inst
.instruction
& PRE_INDEX
))))
5428 as_warn (_("pre/post-indexing used when modified address register is destination"));
5430 /* For an index-register load, the index register must not overlap the
5431 destination (even if not write-back). */
5432 if ((inst
.instruction
& V4_STR_BIT
) == 0
5433 && (inst
.instruction
& HWOFFSET_IMM
) == 0)
5435 int rm
= inst
.instruction
& 0x0000000f;
5437 if (rm
== rd
|| (rm
== rd
+ 1))
5438 as_warn (_("ldrd destination registers must not overlap index register"));
5444 /* Returns the index into fp_values of a floating point number,
5445 or -1 if not in the table. */
5448 my_get_float_expression (str
)
5451 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
5457 memset (words
, 0, MAX_LITTLENUMS
* sizeof (LITTLENUM_TYPE
));
5459 /* Look for a raw floating point number. */
5460 if ((save_in
= atof_ieee (*str
, 'x', words
)) != NULL
5461 && is_end_of_line
[(unsigned char) *save_in
])
5463 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
5465 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
5467 if (words
[j
] != fp_values
[i
][j
])
5471 if (j
== MAX_LITTLENUMS
)
5479 /* Try and parse a more complex expression, this will probably fail
5480 unless the code uses a floating point prefix (eg "0f"). */
5481 save_in
= input_line_pointer
;
5482 input_line_pointer
= *str
;
5483 if (expression (&exp
) == absolute_section
5484 && exp
.X_op
== O_big
5485 && exp
.X_add_number
< 0)
5487 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
5489 if (gen_to_words (words
, 5, (long) 15) == 0)
5491 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
5493 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
5495 if (words
[j
] != fp_values
[i
][j
])
5499 if (j
== MAX_LITTLENUMS
)
5501 *str
= input_line_pointer
;
5502 input_line_pointer
= save_in
;
5509 *str
= input_line_pointer
;
5510 input_line_pointer
= save_in
;
5514 /* Return TRUE if anything in the expression is a bignum. */
5517 walk_no_bignums (sp
)
5520 if (symbol_get_value_expression (sp
)->X_op
== O_big
)
5523 if (symbol_get_value_expression (sp
)->X_add_symbol
)
5525 return (walk_no_bignums (symbol_get_value_expression (sp
)->X_add_symbol
)
5526 || (symbol_get_value_expression (sp
)->X_op_symbol
5527 && walk_no_bignums (symbol_get_value_expression (sp
)->X_op_symbol
)));
5533 static int in_my_get_expression
= 0;
5536 my_get_expression (ep
, str
)
5543 save_in
= input_line_pointer
;
5544 input_line_pointer
= *str
;
5545 in_my_get_expression
= 1;
5546 seg
= expression (ep
);
5547 in_my_get_expression
= 0;
5549 if (ep
->X_op
== O_illegal
)
5551 /* We found a bad expression in md_operand(). */
5552 *str
= input_line_pointer
;
5553 input_line_pointer
= save_in
;
5558 if (seg
!= absolute_section
5559 && seg
!= text_section
5560 && seg
!= data_section
5561 && seg
!= bss_section
5562 && seg
!= undefined_section
)
5564 inst
.error
= _("bad_segment");
5565 *str
= input_line_pointer
;
5566 input_line_pointer
= save_in
;
5571 /* Get rid of any bignums now, so that we don't generate an error for which
5572 we can't establish a line number later on. Big numbers are never valid
5573 in instructions, which is where this routine is always called. */
5574 if (ep
->X_op
== O_big
5575 || (ep
->X_add_symbol
5576 && (walk_no_bignums (ep
->X_add_symbol
)
5578 && walk_no_bignums (ep
->X_op_symbol
)))))
5580 inst
.error
= _("invalid constant");
5581 *str
= input_line_pointer
;
5582 input_line_pointer
= save_in
;
5586 *str
= input_line_pointer
;
5587 input_line_pointer
= save_in
;
5591 /* We handle all bad expressions here, so that we can report the faulty
5592 instruction in the error message. */
5597 if (in_my_get_expression
)
5599 expr
->X_op
= O_illegal
;
5600 if (inst
.error
== NULL
)
5601 inst
.error
= _("bad expression");
5605 /* UNRESTRICT should be one if <shift> <register> is permitted for this
5609 decode_shift (str
, unrestrict
)
5613 const struct asm_shift_name
* shift
;
5617 skip_whitespace (* str
);
5619 for (p
= * str
; ISALPHA (* p
); p
++)
5624 inst
.error
= _("shift expression expected");
5630 shift
= (const struct asm_shift_name
*) hash_find (arm_shift_hsh
, * str
);
5635 inst
.error
= _("shift expression expected");
5639 assert (shift
->properties
->index
== shift_properties
[shift
->properties
->index
].index
);
5641 if (shift
->properties
->index
== SHIFT_RRX
)
5644 inst
.instruction
|= shift
->properties
->bit_field
;
5648 skip_whitespace (p
);
5650 if (unrestrict
&& reg_required_here (& p
, 8) != FAIL
)
5652 inst
.instruction
|= shift
->properties
->bit_field
| SHIFT_BY_REG
;
5656 else if (! is_immediate_prefix (* p
))
5658 inst
.error
= (unrestrict
5659 ? _("shift requires register or #expression")
5660 : _("shift requires #expression"));
5668 if (my_get_expression (& inst
.reloc
.exp
, & p
))
5671 /* Validate some simple #expressions. */
5672 if (inst
.reloc
.exp
.X_op
== O_constant
)
5674 unsigned num
= inst
.reloc
.exp
.X_add_number
;
5676 /* Reject operations greater than 32. */
5678 /* Reject a shift of 0 unless the mode allows it. */
5679 || (num
== 0 && shift
->properties
->allows_0
== 0)
5680 /* Reject a shift of 32 unless the mode allows it. */
5681 || (num
== 32 && shift
->properties
->allows_32
== 0)
5684 /* As a special case we allow a shift of zero for
5685 modes that do not support it to be recoded as an
5686 logical shift left of zero (ie nothing). We warn
5687 about this though. */
5690 as_warn (_("shift of 0 ignored."));
5691 shift
= & shift_names
[0];
5692 assert (shift
->properties
->index
== SHIFT_LSL
);
5696 inst
.error
= _("invalid immediate shift");
5701 /* Shifts of 32 are encoded as 0, for those shifts that
5706 inst
.instruction
|= (num
<< 7) | shift
->properties
->bit_field
;
5710 inst
.reloc
.type
= BFD_RELOC_ARM_SHIFT_IMM
;
5711 inst
.reloc
.pc_rel
= 0;
5712 inst
.instruction
|= shift
->properties
->bit_field
;
5719 /* Do those data_ops which can take a negative immediate constant
5720 by altering the instuction. A bit of a hack really.
5724 by inverting the second operand, and
5727 by negating the second operand. */
5730 negate_data_op (instruction
, value
)
5731 unsigned long * instruction
;
5732 unsigned long value
;
5735 unsigned long negated
, inverted
;
5737 negated
= validate_immediate (-value
);
5738 inverted
= validate_immediate (~value
);
5740 op
= (*instruction
>> DATA_OP_SHIFT
) & 0xf;
5743 /* First negates. */
5744 case OPCODE_SUB
: /* ADD <-> SUB */
5745 new_inst
= OPCODE_ADD
;
5750 new_inst
= OPCODE_SUB
;
5754 case OPCODE_CMP
: /* CMP <-> CMN */
5755 new_inst
= OPCODE_CMN
;
5760 new_inst
= OPCODE_CMP
;
5764 /* Now Inverted ops. */
5765 case OPCODE_MOV
: /* MOV <-> MVN */
5766 new_inst
= OPCODE_MVN
;
5771 new_inst
= OPCODE_MOV
;
5775 case OPCODE_AND
: /* AND <-> BIC */
5776 new_inst
= OPCODE_BIC
;
5781 new_inst
= OPCODE_AND
;
5785 case OPCODE_ADC
: /* ADC <-> SBC */
5786 new_inst
= OPCODE_SBC
;
5791 new_inst
= OPCODE_ADC
;
5795 /* We cannot do anything. */
5800 if (value
== (unsigned) FAIL
)
5803 *instruction
&= OPCODE_MASK
;
5804 *instruction
|= new_inst
<< DATA_OP_SHIFT
;
5815 skip_whitespace (* str
);
5817 if (reg_required_here (str
, 0) != FAIL
)
5819 if (skip_past_comma (str
) == SUCCESS
)
5820 /* Shift operation on register. */
5821 return decode_shift (str
, NO_SHIFT_RESTRICT
);
5827 /* Immediate expression. */
5828 if (is_immediate_prefix (**str
))
5833 if (my_get_expression (&inst
.reloc
.exp
, str
))
5836 if (inst
.reloc
.exp
.X_add_symbol
)
5838 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
5839 inst
.reloc
.pc_rel
= 0;
5843 if (skip_past_comma (str
) == SUCCESS
)
5845 /* #x, y -- ie explicit rotation by Y. */
5846 if (my_get_expression (&expr
, str
))
5849 if (expr
.X_op
!= O_constant
)
5851 inst
.error
= _("constant expression expected");
5855 /* Rotate must be a multiple of 2. */
5856 if (((unsigned) expr
.X_add_number
) > 30
5857 || (expr
.X_add_number
& 1) != 0
5858 || ((unsigned) inst
.reloc
.exp
.X_add_number
) > 255)
5860 inst
.error
= _("invalid constant");
5863 inst
.instruction
|= INST_IMMEDIATE
;
5864 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
5865 inst
.instruction
|= expr
.X_add_number
<< 7;
5869 /* Implicit rotation, select a suitable one. */
5870 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
5874 /* Can't be done. Perhaps the code reads something like
5875 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
5876 if ((value
= negate_data_op (&inst
.instruction
,
5877 inst
.reloc
.exp
.X_add_number
))
5880 inst
.error
= _("invalid constant");
5885 inst
.instruction
|= value
;
5888 inst
.instruction
|= INST_IMMEDIATE
;
5893 inst
.error
= _("register or shift expression expected");
5902 skip_whitespace (* str
);
5904 if (fp_reg_required_here (str
, 0) != FAIL
)
5908 /* Immediate expression. */
5909 if (*((*str
)++) == '#')
5915 skip_whitespace (* str
);
5917 /* First try and match exact strings, this is to guarantee
5918 that some formats will work even for cross assembly. */
5920 for (i
= 0; fp_const
[i
]; i
++)
5922 if (strncmp (*str
, fp_const
[i
], strlen (fp_const
[i
])) == 0)
5926 *str
+= strlen (fp_const
[i
]);
5927 if (is_end_of_line
[(unsigned char) **str
])
5929 inst
.instruction
|= i
+ 8;
5936 /* Just because we didn't get a match doesn't mean that the
5937 constant isn't valid, just that it is in a format that we
5938 don't automatically recognize. Try parsing it with
5939 the standard expression routines. */
5940 if ((i
= my_get_float_expression (str
)) >= 0)
5942 inst
.instruction
|= i
+ 8;
5946 inst
.error
= _("invalid floating point immediate expression");
5950 _("floating point register or immediate expression expected");
5959 skip_whitespace (str
);
5961 if (reg_required_here (&str
, 12) == FAIL
5962 || skip_past_comma (&str
) == FAIL
5963 || reg_required_here (&str
, 16) == FAIL
5964 || skip_past_comma (&str
) == FAIL
5965 || data_op2 (&str
) == FAIL
)
5968 inst
.error
= BAD_ARGS
;
5980 /* This is a pseudo-op of the form "adr rd, label" to be converted
5981 into a relative address of the form "add rd, pc, #label-.-8". */
5982 skip_whitespace (str
);
5984 if (reg_required_here (&str
, 12) == FAIL
5985 || skip_past_comma (&str
) == FAIL
5986 || my_get_expression (&inst
.reloc
.exp
, &str
))
5989 inst
.error
= BAD_ARGS
;
5993 /* Frag hacking will turn this into a sub instruction if the offset turns
5994 out to be negative. */
5995 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
5996 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust. */
5997 inst
.reloc
.pc_rel
= 1;
6006 /* This is a pseudo-op of the form "adrl rd, label" to be converted
6007 into a relative address of the form:
6008 add rd, pc, #low(label-.-8)"
6009 add rd, rd, #high(label-.-8)" */
6011 skip_whitespace (str
);
6013 if (reg_required_here (&str
, 12) == FAIL
6014 || skip_past_comma (&str
) == FAIL
6015 || my_get_expression (&inst
.reloc
.exp
, &str
))
6018 inst
.error
= BAD_ARGS
;
6024 /* Frag hacking will turn this into a sub instruction if the offset turns
6025 out to be negative. */
6026 inst
.reloc
.type
= BFD_RELOC_ARM_ADRL_IMMEDIATE
;
6027 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust */
6028 inst
.reloc
.pc_rel
= 1;
6029 inst
.size
= INSN_SIZE
* 2;
6038 skip_whitespace (str
);
6040 if (reg_required_here (&str
, 16) == FAIL
)
6043 inst
.error
= BAD_ARGS
;
6047 if (skip_past_comma (&str
) == FAIL
6048 || data_op2 (&str
) == FAIL
)
6051 inst
.error
= BAD_ARGS
;
6063 skip_whitespace (str
);
6065 if (reg_required_here (&str
, 12) == FAIL
)
6068 inst
.error
= BAD_ARGS
;
6072 if (skip_past_comma (&str
) == FAIL
6073 || data_op2 (&str
) == FAIL
)
6076 inst
.error
= BAD_ARGS
;
6095 if (my_get_expression (& inst
.reloc
.exp
, str
))
6098 if (inst
.reloc
.exp
.X_op
== O_constant
)
6100 int value
= inst
.reloc
.exp
.X_add_number
;
6102 if (value
< -4095 || value
> 4095)
6104 inst
.error
= _("address offset too large");
6114 inst
.instruction
|= add
| value
;
6118 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
6119 inst
.reloc
.pc_rel
= 0;
6132 if (reg_required_here (str
, 0) == FAIL
)
6135 inst
.instruction
|= add
| OFFSET_REG
;
6136 if (skip_past_comma (str
) == SUCCESS
)
6137 return decode_shift (str
, SHIFT_RESTRICT
);
6151 skip_whitespace (str
);
6153 if ((conflict_reg
= reg_required_here (&str
, 12)) == FAIL
)
6156 inst
.error
= BAD_ARGS
;
6160 if (skip_past_comma (&str
) == FAIL
)
6162 inst
.error
= _("address expected");
6172 skip_whitespace (str
);
6174 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6177 /* Conflicts can occur on stores as well as loads. */
6178 conflict_reg
= (conflict_reg
== reg
);
6180 skip_whitespace (str
);
6186 if (skip_past_comma (&str
) == SUCCESS
)
6188 /* [Rn],... (post inc) */
6189 if (ldst_extend (&str
) == FAIL
)
6192 as_warn (_("%s register same as write-back base"),
6193 ((inst
.instruction
& LOAD_BIT
)
6194 ? _("destination") : _("source")));
6199 skip_whitespace (str
);
6204 as_warn (_("%s register same as write-back base"),
6205 ((inst
.instruction
& LOAD_BIT
)
6206 ? _("destination") : _("source")));
6208 inst
.instruction
|= WRITE_BACK
;
6211 inst
.instruction
|= INDEX_UP
;
6218 if (skip_past_comma (&str
) == FAIL
)
6220 inst
.error
= _("pre-indexed expression expected");
6225 if (ldst_extend (&str
) == FAIL
)
6228 skip_whitespace (str
);
6232 inst
.error
= _("missing ]");
6236 skip_whitespace (str
);
6241 as_warn (_("%s register same as write-back base"),
6242 ((inst
.instruction
& LOAD_BIT
)
6243 ? _("destination") : _("source")));
6245 inst
.instruction
|= WRITE_BACK
;
6249 else if (*str
== '=')
6251 if ((inst
.instruction
& LOAD_BIT
) == 0)
6253 inst
.error
= _("invalid pseudo operation");
6257 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6260 skip_whitespace (str
);
6262 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6265 if (inst
.reloc
.exp
.X_op
!= O_constant
6266 && inst
.reloc
.exp
.X_op
!= O_symbol
)
6268 inst
.error
= _("constant expression expected");
6272 if (inst
.reloc
.exp
.X_op
== O_constant
)
6274 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
6278 /* This can be done with a mov instruction. */
6279 inst
.instruction
&= LITERAL_MASK
;
6280 inst
.instruction
|= (INST_IMMEDIATE
6281 | (OPCODE_MOV
<< DATA_OP_SHIFT
));
6282 inst
.instruction
|= value
& 0xfff;
6287 value
= validate_immediate (~inst
.reloc
.exp
.X_add_number
);
6291 /* This can be done with a mvn instruction. */
6292 inst
.instruction
&= LITERAL_MASK
;
6293 inst
.instruction
|= (INST_IMMEDIATE
6294 | (OPCODE_MVN
<< DATA_OP_SHIFT
));
6295 inst
.instruction
|= value
& 0xfff;
6301 /* Insert into literal pool. */
6302 if (add_to_lit_pool () == FAIL
)
6305 inst
.error
= _("literal pool insertion failed");
6309 /* Change the instruction exp to point to the pool. */
6310 inst
.reloc
.type
= BFD_RELOC_ARM_LITERAL
;
6311 inst
.reloc
.pc_rel
= 1;
6312 inst
.instruction
|= (REG_PC
<< 16);
6317 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6320 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
6322 /* PC rel adjust. */
6323 inst
.reloc
.exp
.X_add_number
-= 8;
6325 inst
.reloc
.pc_rel
= 1;
6326 inst
.instruction
|= (REG_PC
<< 16);
6330 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
6341 skip_whitespace (str
);
6343 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
6346 inst
.error
= BAD_ARGS
;
6350 if (skip_past_comma (& str
) == FAIL
)
6352 inst
.error
= _("address expected");
6362 skip_whitespace (str
);
6364 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6367 /* ldrt/strt always use post-indexed addressing, so if the base is
6368 the same as Rd, we warn. */
6369 if (conflict_reg
== reg
)
6370 as_warn (_("%s register same as write-back base"),
6371 ((inst
.instruction
& LOAD_BIT
)
6372 ? _("destination") : _("source")));
6374 skip_whitespace (str
);
6380 if (skip_past_comma (&str
) == SUCCESS
)
6382 /* [Rn],... (post inc) */
6383 if (ldst_extend (&str
) == FAIL
)
6389 skip_whitespace (str
);
6391 /* Skip a write-back '!'. */
6395 inst
.instruction
|= INDEX_UP
;
6400 inst
.error
= _("post-indexed expression expected");
6406 inst
.error
= _("post-indexed expression expected");
6415 ldst_extend_v4 (str
)
6425 if (my_get_expression (& inst
.reloc
.exp
, str
))
6428 if (inst
.reloc
.exp
.X_op
== O_constant
)
6430 int value
= inst
.reloc
.exp
.X_add_number
;
6432 if (value
< -255 || value
> 255)
6434 inst
.error
= _("address offset too large");
6444 /* Halfword and signextension instructions have the
6445 immediate value split across bits 11..8 and bits 3..0. */
6446 inst
.instruction
|= (add
| HWOFFSET_IMM
6447 | ((value
>> 4) << 8) | (value
& 0xF));
6451 inst
.instruction
|= HWOFFSET_IMM
;
6452 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
6453 inst
.reloc
.pc_rel
= 0;
6466 if (reg_required_here (str
, 0) == FAIL
)
6469 inst
.instruction
|= add
;
6474 /* Halfword and signed-byte load/store operations. */
6483 skip_whitespace (str
);
6485 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
6488 inst
.error
= BAD_ARGS
;
6492 if (skip_past_comma (& str
) == FAIL
)
6494 inst
.error
= _("address expected");
6504 skip_whitespace (str
);
6506 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6509 /* Conflicts can occur on stores as well as loads. */
6510 conflict_reg
= (conflict_reg
== reg
);
6512 skip_whitespace (str
);
6518 if (skip_past_comma (&str
) == SUCCESS
)
6520 /* [Rn],... (post inc) */
6521 if (ldst_extend_v4 (&str
) == FAIL
)
6524 as_warn (_("%s register same as write-back base"),
6525 ((inst
.instruction
& LOAD_BIT
)
6526 ? _("destination") : _("source")));
6531 inst
.instruction
|= HWOFFSET_IMM
;
6533 skip_whitespace (str
);
6538 as_warn (_("%s register same as write-back base"),
6539 ((inst
.instruction
& LOAD_BIT
)
6540 ? _("destination") : _("source")));
6542 inst
.instruction
|= WRITE_BACK
;
6545 inst
.instruction
|= INDEX_UP
;
6552 if (skip_past_comma (&str
) == FAIL
)
6554 inst
.error
= _("pre-indexed expression expected");
6559 if (ldst_extend_v4 (&str
) == FAIL
)
6562 skip_whitespace (str
);
6566 inst
.error
= _("missing ]");
6570 skip_whitespace (str
);
6575 as_warn (_("%s register same as write-back base"),
6576 ((inst
.instruction
& LOAD_BIT
)
6577 ? _("destination") : _("source")));
6579 inst
.instruction
|= WRITE_BACK
;
6583 else if (*str
== '=')
6585 if ((inst
.instruction
& LOAD_BIT
) == 0)
6587 inst
.error
= _("invalid pseudo operation");
6591 /* XXX Does this work correctly for half-word/byte ops? */
6592 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6595 skip_whitespace (str
);
6597 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6600 if (inst
.reloc
.exp
.X_op
!= O_constant
6601 && inst
.reloc
.exp
.X_op
!= O_symbol
)
6603 inst
.error
= _("constant expression expected");
6607 if (inst
.reloc
.exp
.X_op
== O_constant
)
6609 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
6613 /* This can be done with a mov instruction. */
6614 inst
.instruction
&= LITERAL_MASK
;
6615 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MOV
<< DATA_OP_SHIFT
);
6616 inst
.instruction
|= value
& 0xfff;
6621 value
= validate_immediate (~ inst
.reloc
.exp
.X_add_number
);
6625 /* This can be done with a mvn instruction. */
6626 inst
.instruction
&= LITERAL_MASK
;
6627 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MVN
<< DATA_OP_SHIFT
);
6628 inst
.instruction
|= value
& 0xfff;
6634 /* Insert into literal pool. */
6635 if (add_to_lit_pool () == FAIL
)
6638 inst
.error
= _("literal pool insertion failed");
6642 /* Change the instruction exp to point to the pool. */
6643 inst
.instruction
|= HWOFFSET_IMM
;
6644 inst
.reloc
.type
= BFD_RELOC_ARM_HWLITERAL
;
6645 inst
.reloc
.pc_rel
= 1;
6646 inst
.instruction
|= (REG_PC
<< 16);
6651 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6654 inst
.instruction
|= HWOFFSET_IMM
;
6655 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
6657 /* PC rel adjust. */
6658 inst
.reloc
.exp
.X_add_number
-= 8;
6660 inst
.reloc
.pc_rel
= 1;
6661 inst
.instruction
|= (REG_PC
<< 16);
6665 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
6674 char * str
= * strp
;
6678 /* We come back here if we get ranges concatenated by '+' or '|'. */
6693 skip_whitespace (str
);
6695 if ((reg
= reg_required_here (& str
, -1)) == FAIL
)
6704 inst
.error
= _("bad range in register list");
6708 for (i
= cur_reg
+ 1; i
< reg
; i
++)
6710 if (range
& (1 << i
))
6712 (_("Warning: duplicated register (r%d) in register list"),
6720 if (range
& (1 << reg
))
6721 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
6723 else if (reg
<= cur_reg
)
6724 as_tsktsk (_("Warning: register range not in ascending order"));
6729 while (skip_past_comma (&str
) != FAIL
6730 || (in_range
= 1, *str
++ == '-'));
6732 skip_whitespace (str
);
6736 inst
.error
= _("missing `}'");
6744 if (my_get_expression (&expr
, &str
))
6747 if (expr
.X_op
== O_constant
)
6749 if (expr
.X_add_number
6750 != (expr
.X_add_number
& 0x0000ffff))
6752 inst
.error
= _("invalid register mask");
6756 if ((range
& expr
.X_add_number
) != 0)
6758 int regno
= range
& expr
.X_add_number
;
6761 regno
= (1 << regno
) - 1;
6763 (_("Warning: duplicated register (r%d) in register list"),
6767 range
|= expr
.X_add_number
;
6771 if (inst
.reloc
.type
!= 0)
6773 inst
.error
= _("expression too complex");
6777 memcpy (&inst
.reloc
.exp
, &expr
, sizeof (expressionS
));
6778 inst
.reloc
.type
= BFD_RELOC_ARM_MULTI
;
6779 inst
.reloc
.pc_rel
= 0;
6783 skip_whitespace (str
);
6785 if (*str
== '|' || *str
== '+')
6791 while (another_range
);
6804 skip_whitespace (str
);
6806 if ((base_reg
= reg_required_here (&str
, 16)) == FAIL
)
6809 if (base_reg
== REG_PC
)
6811 inst
.error
= _("r15 not allowed as base register");
6815 skip_whitespace (str
);
6819 inst
.instruction
|= WRITE_BACK
;
6823 if (skip_past_comma (&str
) == FAIL
6824 || (range
= reg_list (&str
)) == FAIL
)
6827 inst
.error
= BAD_ARGS
;
6834 inst
.instruction
|= LDM_TYPE_2_OR_3
;
6837 if (inst
.instruction
& WRITE_BACK
)
6839 /* Check for unpredictable uses of writeback. */
6840 if (inst
.instruction
& LOAD_BIT
)
6842 /* Not allowed in LDM type 2. */
6843 if ((inst
.instruction
& LDM_TYPE_2_OR_3
)
6844 && ((range
& (1 << REG_PC
)) == 0))
6845 as_warn (_("writeback of base register is UNPREDICTABLE"));
6846 /* Only allowed if base reg not in list for other types. */
6847 else if (range
& (1 << base_reg
))
6848 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
6852 /* Not allowed for type 2. */
6853 if (inst
.instruction
& LDM_TYPE_2_OR_3
)
6854 as_warn (_("writeback of base register is UNPREDICTABLE"));
6855 /* Only allowed if base reg not in list, or first in list. */
6856 else if ((range
& (1 << base_reg
))
6857 && (range
& ((1 << base_reg
) - 1)))
6858 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
6862 inst
.instruction
|= range
;
6871 skip_whitespace (str
);
6873 /* Allow optional leading '#'. */
6874 if (is_immediate_prefix (*str
))
6877 if (my_get_expression (& inst
.reloc
.exp
, & str
))
6880 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
6881 inst
.reloc
.pc_rel
= 0;
6893 skip_whitespace (str
);
6895 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
6900 inst
.error
= _("r15 not allowed in swap");
6904 if (skip_past_comma (&str
) == FAIL
6905 || (reg
= reg_required_here (&str
, 0)) == FAIL
)
6908 inst
.error
= BAD_ARGS
;
6914 inst
.error
= _("r15 not allowed in swap");
6918 if (skip_past_comma (&str
) == FAIL
6921 inst
.error
= BAD_ARGS
;
6925 skip_whitespace (str
);
6927 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6932 inst
.error
= BAD_PC
;
6936 skip_whitespace (str
);
6940 inst
.error
= _("missing ]");
6952 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6959 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
6960 required for the instruction. */
6962 /* arm_parse_reloc () works on input_line_pointer.
6963 We actually want to parse the operands to the branch instruction
6964 passed in 'str'. Save the input pointer and restore it later. */
6965 save_in
= input_line_pointer
;
6966 input_line_pointer
= str
;
6967 if (inst
.reloc
.exp
.X_op
== O_symbol
6969 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
6971 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
6972 inst
.reloc
.pc_rel
= 0;
6973 /* Modify str to point to after parsed operands, otherwise
6974 end_of_line() will complain about the (PLT) left in str. */
6975 str
= input_line_pointer
;
6979 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
6980 inst
.reloc
.pc_rel
= 1;
6982 input_line_pointer
= save_in
;
6985 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
6986 inst
.reloc
.pc_rel
= 1;
6987 #endif /* OBJ_ELF */
6999 skip_whitespace (str
);
7001 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
7003 inst
.error
= BAD_ARGS
;
7007 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
7009 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
7018 /* Co-processor data operation.
7019 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
7020 skip_whitespace (str
);
7022 if (co_proc_number (&str
) == FAIL
)
7025 inst
.error
= BAD_ARGS
;
7029 if (skip_past_comma (&str
) == FAIL
7030 || cp_opc_expr (&str
, 20,4) == FAIL
)
7033 inst
.error
= BAD_ARGS
;
7037 if (skip_past_comma (&str
) == FAIL
7038 || cp_reg_required_here (&str
, 12) == FAIL
)
7041 inst
.error
= BAD_ARGS
;
7045 if (skip_past_comma (&str
) == FAIL
7046 || cp_reg_required_here (&str
, 16) == FAIL
)
7049 inst
.error
= BAD_ARGS
;
7053 if (skip_past_comma (&str
) == FAIL
7054 || cp_reg_required_here (&str
, 0) == FAIL
)
7057 inst
.error
= BAD_ARGS
;
7061 if (skip_past_comma (&str
) == SUCCESS
)
7063 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
7066 inst
.error
= BAD_ARGS
;
7079 /* Co-processor register load/store.
7080 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
7082 skip_whitespace (str
);
7084 if (co_proc_number (&str
) == FAIL
)
7087 inst
.error
= BAD_ARGS
;
7091 if (skip_past_comma (&str
) == FAIL
7092 || cp_reg_required_here (&str
, 12) == FAIL
)
7095 inst
.error
= BAD_ARGS
;
7099 if (skip_past_comma (&str
) == FAIL
7100 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
7103 inst
.error
= BAD_ARGS
;
7115 /* Co-processor register transfer.
7116 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
7118 skip_whitespace (str
);
7120 if (co_proc_number (&str
) == FAIL
)
7123 inst
.error
= BAD_ARGS
;
7127 if (skip_past_comma (&str
) == FAIL
7128 || cp_opc_expr (&str
, 21, 3) == FAIL
)
7131 inst
.error
= BAD_ARGS
;
7135 if (skip_past_comma (&str
) == FAIL
7136 || reg_required_here (&str
, 12) == FAIL
)
7139 inst
.error
= BAD_ARGS
;
7143 if (skip_past_comma (&str
) == FAIL
7144 || cp_reg_required_here (&str
, 16) == FAIL
)
7147 inst
.error
= BAD_ARGS
;
7151 if (skip_past_comma (&str
) == FAIL
7152 || cp_reg_required_here (&str
, 0) == FAIL
)
7155 inst
.error
= BAD_ARGS
;
7159 if (skip_past_comma (&str
) == SUCCESS
)
7161 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
7164 inst
.error
= BAD_ARGS
;
7177 /* FP control registers.
7178 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
7180 skip_whitespace (str
);
7182 if (reg_required_here (&str
, 12) == FAIL
)
7185 inst
.error
= BAD_ARGS
;
7197 skip_whitespace (str
);
7199 if (fp_reg_required_here (&str
, 12) == FAIL
)
7202 inst
.error
= BAD_ARGS
;
7206 if (skip_past_comma (&str
) == FAIL
7207 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
7210 inst
.error
= BAD_ARGS
;
7223 skip_whitespace (str
);
7225 if (fp_reg_required_here (&str
, 12) == FAIL
)
7228 inst
.error
= BAD_ARGS
;
7232 /* Get Number of registers to transfer. */
7233 if (skip_past_comma (&str
) == FAIL
7234 || my_get_expression (&inst
.reloc
.exp
, &str
))
7237 inst
.error
= _("constant expression expected");
7241 if (inst
.reloc
.exp
.X_op
!= O_constant
)
7243 inst
.error
= _("constant value required for number of registers");
7247 num_regs
= inst
.reloc
.exp
.X_add_number
;
7249 if (num_regs
< 1 || num_regs
> 4)
7251 inst
.error
= _("number of registers must be in the range [1:4]");
7258 inst
.instruction
|= CP_T_X
;
7261 inst
.instruction
|= CP_T_Y
;
7264 inst
.instruction
|= CP_T_Y
| CP_T_X
;
7272 if (inst
.instruction
& (CP_T_Pre
| CP_T_UD
)) /* ea/fd format. */
7278 /* The instruction specified "ea" or "fd", so we can only accept
7279 [Rn]{!}. The instruction does not really support stacking or
7280 unstacking, so we have to emulate these by setting appropriate
7281 bits and offsets. */
7282 if (skip_past_comma (&str
) == FAIL
7286 inst
.error
= BAD_ARGS
;
7291 skip_whitespace (str
);
7293 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
7296 skip_whitespace (str
);
7300 inst
.error
= BAD_ARGS
;
7312 _("r15 not allowed as base register with write-back");
7319 if (inst
.instruction
& CP_T_Pre
)
7321 /* Pre-decrement. */
7322 offset
= 3 * num_regs
;
7324 inst
.instruction
|= CP_T_WB
;
7328 /* Post-increment. */
7331 inst
.instruction
|= CP_T_WB
;
7332 offset
= 3 * num_regs
;
7336 /* No write-back, so convert this into a standard pre-increment
7337 instruction -- aesthetically more pleasing. */
7338 inst
.instruction
|= CP_T_Pre
| CP_T_UD
;
7343 inst
.instruction
|= offset
;
7345 else if (skip_past_comma (&str
) == FAIL
7346 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
7349 inst
.error
= BAD_ARGS
;
7360 skip_whitespace (str
);
7362 if (fp_reg_required_here (&str
, 12) == FAIL
)
7365 inst
.error
= BAD_ARGS
;
7369 if (skip_past_comma (&str
) == FAIL
7370 || fp_reg_required_here (&str
, 16) == FAIL
)
7373 inst
.error
= BAD_ARGS
;
7377 if (skip_past_comma (&str
) == FAIL
7378 || fp_op2 (&str
) == FAIL
)
7381 inst
.error
= BAD_ARGS
;
7390 do_fpa_monadic (str
)
7393 skip_whitespace (str
);
7395 if (fp_reg_required_here (&str
, 12) == FAIL
)
7398 inst
.error
= BAD_ARGS
;
7402 if (skip_past_comma (&str
) == FAIL
7403 || fp_op2 (&str
) == FAIL
)
7406 inst
.error
= BAD_ARGS
;
7418 skip_whitespace (str
);
7420 if (fp_reg_required_here (&str
, 16) == FAIL
)
7423 inst
.error
= BAD_ARGS
;
7427 if (skip_past_comma (&str
) == FAIL
7428 || fp_op2 (&str
) == FAIL
)
7431 inst
.error
= BAD_ARGS
;
7440 do_fpa_from_reg (str
)
7443 skip_whitespace (str
);
7445 if (fp_reg_required_here (&str
, 16) == FAIL
)
7448 inst
.error
= BAD_ARGS
;
7452 if (skip_past_comma (&str
) == FAIL
7453 || reg_required_here (&str
, 12) == FAIL
)
7456 inst
.error
= BAD_ARGS
;
7468 skip_whitespace (str
);
7470 if (reg_required_here (&str
, 12) == FAIL
)
7473 if (skip_past_comma (&str
) == FAIL
7474 || fp_reg_required_here (&str
, 0) == FAIL
)
7477 inst
.error
= BAD_ARGS
;
7486 vfp_sp_reg_required_here (str
, pos
)
7488 enum vfp_sp_reg_pos pos
;
7493 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_SN
].htab
)) != FAIL
)
7498 inst
.instruction
|= ((reg
>> 1) << 12) | ((reg
& 1) << 22);
7502 inst
.instruction
|= ((reg
>> 1) << 16) | ((reg
& 1) << 7);
7506 inst
.instruction
|= ((reg
>> 1) << 0) | ((reg
& 1) << 5);
7515 /* In the few cases where we might be able to accept something else
7516 this error can be overridden. */
7517 inst
.error
= _(all_reg_maps
[REG_TYPE_SN
].expected
);
7519 /* Restore the start point. */
7525 vfp_dp_reg_required_here (str
, pos
)
7527 enum vfp_dp_reg_pos pos
;
7532 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_DN
].htab
)) != FAIL
)
7537 inst
.instruction
|= reg
<< 12;
7541 inst
.instruction
|= reg
<< 16;
7545 inst
.instruction
|= reg
<< 0;
7554 /* In the few cases where we might be able to accept something else
7555 this error can be overridden. */
7556 inst
.error
= _(all_reg_maps
[REG_TYPE_DN
].expected
);
7558 /* Restore the start point. */
7564 do_vfp_sp_monadic (str
)
7567 skip_whitespace (str
);
7569 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7572 if (skip_past_comma (&str
) == FAIL
7573 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
7576 inst
.error
= BAD_ARGS
;
7585 do_vfp_dp_monadic (str
)
7588 skip_whitespace (str
);
7590 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7593 if (skip_past_comma (&str
) == FAIL
7594 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7597 inst
.error
= BAD_ARGS
;
7606 do_vfp_sp_dyadic (str
)
7609 skip_whitespace (str
);
7611 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7614 if (skip_past_comma (&str
) == FAIL
7615 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
7616 || skip_past_comma (&str
) == FAIL
7617 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
7620 inst
.error
= BAD_ARGS
;
7629 do_vfp_dp_dyadic (str
)
7632 skip_whitespace (str
);
7634 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7637 if (skip_past_comma (&str
) == FAIL
7638 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
7639 || skip_past_comma (&str
) == FAIL
7640 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7643 inst
.error
= BAD_ARGS
;
7652 do_vfp_reg_from_sp (str
)
7655 skip_whitespace (str
);
7657 if (reg_required_here (&str
, 12) == FAIL
)
7660 if (skip_past_comma (&str
) == FAIL
7661 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
7664 inst
.error
= BAD_ARGS
;
7673 do_vfp_sp_reg2 (str
)
7676 skip_whitespace (str
);
7678 if (reg_required_here (&str
, 12) == FAIL
)
7681 if (skip_past_comma (&str
) == FAIL
7682 || reg_required_here (&str
, 16) == FAIL
7683 || skip_past_comma (&str
) == FAIL
)
7686 inst
.error
= BAD_ARGS
;
7690 /* We require exactly two consecutive SP registers. */
7691 if (vfp_sp_reg_list (&str
, VFP_REG_Sm
) != 2)
7694 inst
.error
= _("only two consecutive VFP SP registers allowed here");
7702 do_vfp_sp_from_reg (str
)
7705 skip_whitespace (str
);
7707 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
7710 if (skip_past_comma (&str
) == FAIL
7711 || reg_required_here (&str
, 12) == FAIL
)
7714 inst
.error
= BAD_ARGS
;
7723 do_vfp_reg_from_dp (str
)
7726 skip_whitespace (str
);
7728 if (reg_required_here (&str
, 12) == FAIL
)
7731 if (skip_past_comma (&str
) == FAIL
7732 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
7735 inst
.error
= BAD_ARGS
;
7744 do_vfp_reg2_from_dp (str
)
7747 skip_whitespace (str
);
7749 if (reg_required_here (&str
, 12) == FAIL
)
7752 if (skip_past_comma (&str
) == FAIL
7753 || reg_required_here (&str
, 16) == FAIL
7754 || skip_past_comma (&str
) == FAIL
7755 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7758 inst
.error
= BAD_ARGS
;
7767 do_vfp_dp_from_reg (str
)
7770 skip_whitespace (str
);
7772 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
7775 if (skip_past_comma (&str
) == FAIL
7776 || reg_required_here (&str
, 12) == FAIL
)
7779 inst
.error
= BAD_ARGS
;
7788 do_vfp_dp_from_reg2 (str
)
7791 skip_whitespace (str
);
7793 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7796 if (skip_past_comma (&str
) == FAIL
7797 || reg_required_here (&str
, 12) == FAIL
7798 || skip_past_comma (&str
) == FAIL
7799 || reg_required_here (&str
, 16))
7802 inst
.error
= BAD_ARGS
;
7810 static const struct vfp_reg
*
7817 const struct vfp_reg
*vreg
;
7821 /* Find the end of the current token. */
7826 while (ISALPHA (c
));
7831 for (vreg
= vfp_regs
+ 0;
7832 vreg
< vfp_regs
+ sizeof (vfp_regs
) / sizeof (struct vfp_reg
);
7835 if (strcmp (start
, vreg
->name
) == 0)
7848 vfp_psr_required_here (str
)
7852 const struct vfp_reg
*vreg
;
7854 vreg
= vfp_psr_parse (str
);
7858 inst
.instruction
|= vreg
->regno
;
7862 inst
.error
= _("VFP system register expected");
7869 do_vfp_reg_from_ctrl (str
)
7872 skip_whitespace (str
);
7874 if (reg_required_here (&str
, 12) == FAIL
)
7877 if (skip_past_comma (&str
) == FAIL
7878 || vfp_psr_required_here (&str
) == FAIL
)
7881 inst
.error
= BAD_ARGS
;
7890 do_vfp_ctrl_from_reg (str
)
7893 skip_whitespace (str
);
7895 if (vfp_psr_required_here (&str
) == FAIL
)
7898 if (skip_past_comma (&str
) == FAIL
7899 || reg_required_here (&str
, 12) == FAIL
)
7902 inst
.error
= BAD_ARGS
;
7911 do_vfp_sp_ldst (str
)
7914 skip_whitespace (str
);
7916 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7919 inst
.error
= BAD_ARGS
;
7923 if (skip_past_comma (&str
) == FAIL
7924 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
7927 inst
.error
= BAD_ARGS
;
7936 do_vfp_dp_ldst (str
)
7939 skip_whitespace (str
);
7941 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7944 inst
.error
= BAD_ARGS
;
7948 if (skip_past_comma (&str
) == FAIL
7949 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
7952 inst
.error
= BAD_ARGS
;
7960 /* Parse and encode a VFP SP register list, storing the initial
7961 register in position POS and returning the range as the result. If
7962 the string is invalid return FAIL (an invalid range). */
7964 vfp_sp_reg_list (str
, pos
)
7966 enum vfp_sp_reg_pos pos
;
7974 unsigned long mask
= 0;
7981 skip_whitespace (*str
);
7983 tempinst
= inst
.instruction
;
7987 inst
.instruction
= 0;
7989 if ((new_base
= vfp_sp_reg_required_here (str
, pos
)) == FAIL
)
7992 if (count
== 0 || base_reg
> new_base
)
7994 base_reg
= new_base
;
7995 base_bits
= inst
.instruction
;
7998 if (mask
& (1 << new_base
))
8000 inst
.error
= _("invalid register list");
8004 if ((mask
>> new_base
) != 0 && ! warned
)
8006 as_tsktsk (_("register list not in ascending order"));
8010 mask
|= 1 << new_base
;
8013 skip_whitespace (*str
);
8015 if (**str
== '-') /* We have the start of a range expression */
8022 = arm_reg_parse (str
, all_reg_maps
[REG_TYPE_SN
].htab
))
8025 inst
.error
= _(all_reg_maps
[REG_TYPE_SN
].expected
);
8029 if (high_range
<= new_base
)
8031 inst
.error
= _("register range not in ascending order");
8035 for (new_base
++; new_base
<= high_range
; new_base
++)
8037 if (mask
& (1 << new_base
))
8039 inst
.error
= _("invalid register list");
8043 mask
|= 1 << new_base
;
8048 while (skip_past_comma (str
) != FAIL
);
8052 inst
.error
= _("invalid register list");
8060 /* Sanity check -- should have raised a parse error above. */
8061 if (count
== 0 || count
> 32)
8064 /* Final test -- the registers must be consecutive. */
8067 if ((mask
& (1 << base_reg
++)) == 0)
8069 inst
.error
= _("non-contiguous register range");
8074 inst
.instruction
= tempinst
| base_bits
;
8079 vfp_dp_reg_list (str
)
8087 unsigned long mask
= 0;
8094 skip_whitespace (*str
);
8096 tempinst
= inst
.instruction
;
8100 inst
.instruction
= 0;
8102 if ((new_base
= vfp_dp_reg_required_here (str
, VFP_REG_Dd
)) == FAIL
)
8105 if (count
== 0 || base_reg
> new_base
)
8107 base_reg
= new_base
;
8108 range
= inst
.instruction
;
8111 if (mask
& (1 << new_base
))
8113 inst
.error
= _("invalid register list");
8117 if ((mask
>> new_base
) != 0 && ! warned
)
8119 as_tsktsk (_("register list not in ascending order"));
8123 mask
|= 1 << new_base
;
8126 skip_whitespace (*str
);
8128 if (**str
== '-') /* We have the start of a range expression */
8135 = arm_reg_parse (str
, all_reg_maps
[REG_TYPE_DN
].htab
))
8138 inst
.error
= _(all_reg_maps
[REG_TYPE_DN
].expected
);
8142 if (high_range
<= new_base
)
8144 inst
.error
= _("register range not in ascending order");
8148 for (new_base
++; new_base
<= high_range
; new_base
++)
8150 if (mask
& (1 << new_base
))
8152 inst
.error
= _("invalid register list");
8156 mask
|= 1 << new_base
;
8161 while (skip_past_comma (str
) != FAIL
);
8165 inst
.error
= _("invalid register list");
8173 /* Sanity check -- should have raised a parse error above. */
8174 if (count
== 0 || count
> 16)
8177 /* Final test -- the registers must be consecutive. */
8180 if ((mask
& (1 << base_reg
++)) == 0)
8182 inst
.error
= _("non-contiguous register range");
8187 inst
.instruction
= tempinst
;
8192 vfp_sp_ldstm (str
, ldstm_type
)
8194 enum vfp_ldstm_type ldstm_type
;
8198 skip_whitespace (str
);
8200 if (reg_required_here (&str
, 16) == FAIL
)
8203 skip_whitespace (str
);
8207 inst
.instruction
|= WRITE_BACK
;
8210 else if (ldstm_type
!= VFP_LDSTMIA
)
8212 inst
.error
= _("this addressing mode requires base-register writeback");
8216 if (skip_past_comma (&str
) == FAIL
8217 || (range
= vfp_sp_reg_list (&str
, VFP_REG_Sd
)) == FAIL
)
8220 inst
.error
= BAD_ARGS
;
8224 inst
.instruction
|= range
;
8229 vfp_dp_ldstm (str
, ldstm_type
)
8231 enum vfp_ldstm_type ldstm_type
;
8235 skip_whitespace (str
);
8237 if (reg_required_here (&str
, 16) == FAIL
)
8240 skip_whitespace (str
);
8244 inst
.instruction
|= WRITE_BACK
;
8247 else if (ldstm_type
!= VFP_LDSTMIA
&& ldstm_type
!= VFP_LDSTMIAX
)
8249 inst
.error
= _("this addressing mode requires base-register writeback");
8253 if (skip_past_comma (&str
) == FAIL
8254 || (range
= vfp_dp_reg_list (&str
)) == FAIL
)
8257 inst
.error
= BAD_ARGS
;
8261 if (ldstm_type
== VFP_LDSTMIAX
|| ldstm_type
== VFP_LDSTMDBX
)
8264 inst
.instruction
|= range
;
8269 do_vfp_sp_ldstmia (str
)
8272 vfp_sp_ldstm (str
, VFP_LDSTMIA
);
8276 do_vfp_sp_ldstmdb (str
)
8279 vfp_sp_ldstm (str
, VFP_LDSTMDB
);
8283 do_vfp_dp_ldstmia (str
)
8286 vfp_dp_ldstm (str
, VFP_LDSTMIA
);
8290 do_vfp_dp_ldstmdb (str
)
8293 vfp_dp_ldstm (str
, VFP_LDSTMDB
);
8297 do_vfp_xp_ldstmia (str
)
8300 vfp_dp_ldstm (str
, VFP_LDSTMIAX
);
8304 do_vfp_xp_ldstmdb (str
)
8307 vfp_dp_ldstm (str
, VFP_LDSTMDBX
);
8311 do_vfp_sp_compare_z (str
)
8314 skip_whitespace (str
);
8316 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8319 inst
.error
= BAD_ARGS
;
8328 do_vfp_dp_compare_z (str
)
8331 skip_whitespace (str
);
8333 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8336 inst
.error
= BAD_ARGS
;
8345 do_vfp_dp_sp_cvt (str
)
8348 skip_whitespace (str
);
8350 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8353 if (skip_past_comma (&str
) == FAIL
8354 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
8357 inst
.error
= BAD_ARGS
;
8366 do_vfp_sp_dp_cvt (str
)
8369 skip_whitespace (str
);
8371 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8374 if (skip_past_comma (&str
) == FAIL
8375 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
8378 inst
.error
= BAD_ARGS
;
8386 /* Thumb specific routines. */
8388 /* Parse and validate that a register is of the right form, this saves
8389 repeated checking of this information in many similar cases.
8390 Unlike the 32-bit case we do not insert the register into the opcode
8391 here, since the position is often unknown until the full instruction
8395 thumb_reg (strp
, hi_lo
)
8401 if ((reg
= reg_required_here (strp
, -1)) == FAIL
)
8409 inst
.error
= _("lo register required");
8417 inst
.error
= _("hi register required");
8429 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
8433 thumb_add_sub (str
, subtract
)
8437 int Rd
, Rs
, Rn
= FAIL
;
8439 skip_whitespace (str
);
8441 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
8442 || skip_past_comma (&str
) == FAIL
)
8445 inst
.error
= BAD_ARGS
;
8449 if (is_immediate_prefix (*str
))
8453 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8458 if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8461 if (skip_past_comma (&str
) == FAIL
)
8463 /* Two operand format, shuffle the registers
8464 and pretend there are 3. */
8468 else if (is_immediate_prefix (*str
))
8471 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8474 else if ((Rn
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8478 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8479 for the latter case, EXPR contains the immediate that was found. */
8482 /* All register format. */
8483 if (Rd
> 7 || Rs
> 7 || Rn
> 7)
8487 inst
.error
= _("dest and source1 must be the same register");
8491 /* Can't do this for SUB. */
8494 inst
.error
= _("subtract valid only on lo regs");
8498 inst
.instruction
= (T_OPCODE_ADD_HI
8499 | (Rd
> 7 ? THUMB_H1
: 0)
8500 | (Rn
> 7 ? THUMB_H2
: 0));
8501 inst
.instruction
|= (Rd
& 7) | ((Rn
& 7) << 3);
8505 inst
.instruction
= subtract
? T_OPCODE_SUB_R3
: T_OPCODE_ADD_R3
;
8506 inst
.instruction
|= Rd
| (Rs
<< 3) | (Rn
<< 6);
8511 /* Immediate expression, now things start to get nasty. */
8513 /* First deal with HI regs, only very restricted cases allowed:
8514 Adjusting SP, and using PC or SP to get an address. */
8515 if ((Rd
> 7 && (Rd
!= REG_SP
|| Rs
!= REG_SP
))
8516 || (Rs
> 7 && Rs
!= REG_SP
&& Rs
!= REG_PC
))
8518 inst
.error
= _("invalid Hi register with immediate");
8522 if (inst
.reloc
.exp
.X_op
!= O_constant
)
8524 /* Value isn't known yet, all we can do is store all the fragments
8525 we know about in the instruction and let the reloc hacking
8527 inst
.instruction
= (subtract
? 0x8000 : 0) | (Rd
<< 4) | Rs
;
8528 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
8532 int offset
= inst
.reloc
.exp
.X_add_number
;
8542 /* Quick check, in case offset is MIN_INT. */
8545 inst
.error
= _("immediate value out of range");
8549 /* Note - you cannot convert a subtract of 0 into an
8550 add of 0 because the carry flag is set differently. */
8551 else if (offset
> 0)
8556 if (offset
& ~0x1fc)
8558 inst
.error
= _("invalid immediate value for stack adjust");
8561 inst
.instruction
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
8562 inst
.instruction
|= offset
>> 2;
8564 else if (Rs
== REG_PC
|| Rs
== REG_SP
)
8567 || (offset
& ~0x3fc))
8569 inst
.error
= _("invalid immediate for address calculation");
8572 inst
.instruction
= (Rs
== REG_PC
? T_OPCODE_ADD_PC
8574 inst
.instruction
|= (Rd
<< 8) | (offset
>> 2);
8580 inst
.error
= _("immediate value out of range");
8583 inst
.instruction
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
8584 inst
.instruction
|= (Rd
<< 8) | offset
;
8590 inst
.error
= _("immediate value out of range");
8593 inst
.instruction
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
8594 inst
.instruction
|= Rd
| (Rs
<< 3) | (offset
<< 6);
8603 thumb_shift (str
, shift
)
8607 int Rd
, Rs
, Rn
= FAIL
;
8609 skip_whitespace (str
);
8611 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
8612 || skip_past_comma (&str
) == FAIL
)
8615 inst
.error
= BAD_ARGS
;
8619 if (is_immediate_prefix (*str
))
8621 /* Two operand immediate format, set Rs to Rd. */
8624 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8629 if ((Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8632 if (skip_past_comma (&str
) == FAIL
)
8634 /* Two operand format, shuffle the registers
8635 and pretend there are 3. */
8639 else if (is_immediate_prefix (*str
))
8642 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8645 else if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8649 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8650 for the latter case, EXPR contains the immediate that was found. */
8656 inst
.error
= _("source1 and dest must be same register");
8662 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_R
; break;
8663 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_R
; break;
8664 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_R
; break;
8667 inst
.instruction
|= Rd
| (Rn
<< 3);
8673 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_I
; break;
8674 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_I
; break;
8675 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_I
; break;
8678 if (inst
.reloc
.exp
.X_op
!= O_constant
)
8680 /* Value isn't known yet, create a dummy reloc and let reloc
8681 hacking fix it up. */
8682 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_SHIFT
;
8686 unsigned shift_value
= inst
.reloc
.exp
.X_add_number
;
8688 if (shift_value
> 32 || (shift_value
== 32 && shift
== THUMB_LSL
))
8690 inst
.error
= _("invalid immediate for shift");
8694 /* Shifts of zero are handled by converting to LSL. */
8695 if (shift_value
== 0)
8696 inst
.instruction
= T_OPCODE_LSL_I
;
8698 /* Shifts of 32 are encoded as a shift of zero. */
8699 if (shift_value
== 32)
8702 inst
.instruction
|= shift_value
<< 6;
8705 inst
.instruction
|= Rd
| (Rs
<< 3);
8712 thumb_mov_compare (str
, move
)
8718 skip_whitespace (str
);
8720 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
8721 || skip_past_comma (&str
) == FAIL
)
8724 inst
.error
= BAD_ARGS
;
8728 if (is_immediate_prefix (*str
))
8731 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8734 else if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8739 if (Rs
< 8 && Rd
< 8)
8741 if (move
== THUMB_MOVE
)
8742 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
8743 since a MOV instruction produces unpredictable results. */
8744 inst
.instruction
= T_OPCODE_ADD_I3
;
8746 inst
.instruction
= T_OPCODE_CMP_LR
;
8747 inst
.instruction
|= Rd
| (Rs
<< 3);
8751 if (move
== THUMB_MOVE
)
8752 inst
.instruction
= T_OPCODE_MOV_HR
;
8754 inst
.instruction
= T_OPCODE_CMP_HR
;
8757 inst
.instruction
|= THUMB_H1
;
8760 inst
.instruction
|= THUMB_H2
;
8762 inst
.instruction
|= (Rd
& 7) | ((Rs
& 7) << 3);
8769 inst
.error
= _("only lo regs allowed with immediate");
8773 if (move
== THUMB_MOVE
)
8774 inst
.instruction
= T_OPCODE_MOV_I8
;
8776 inst
.instruction
= T_OPCODE_CMP_I8
;
8778 inst
.instruction
|= Rd
<< 8;
8780 if (inst
.reloc
.exp
.X_op
!= O_constant
)
8781 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_IMM
;
8784 unsigned value
= inst
.reloc
.exp
.X_add_number
;
8788 inst
.error
= _("invalid immediate");
8792 inst
.instruction
|= value
;
8800 thumb_load_store (str
, load_store
, size
)
8805 int Rd
, Rb
, Ro
= FAIL
;
8807 skip_whitespace (str
);
8809 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
8810 || skip_past_comma (&str
) == FAIL
)
8813 inst
.error
= BAD_ARGS
;
8820 if ((Rb
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8823 if (skip_past_comma (&str
) != FAIL
)
8825 if (is_immediate_prefix (*str
))
8828 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8831 else if ((Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8836 inst
.reloc
.exp
.X_op
= O_constant
;
8837 inst
.reloc
.exp
.X_add_number
= 0;
8842 inst
.error
= _("expected ']'");
8847 else if (*str
== '=')
8849 if (load_store
!= THUMB_LOAD
)
8851 inst
.error
= _("invalid pseudo operation");
8855 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
8858 skip_whitespace (str
);
8860 if (my_get_expression (& inst
.reloc
.exp
, & str
))
8865 if ( inst
.reloc
.exp
.X_op
!= O_constant
8866 && inst
.reloc
.exp
.X_op
!= O_symbol
)
8868 inst
.error
= "Constant expression expected";
8872 if (inst
.reloc
.exp
.X_op
== O_constant
8873 && ((inst
.reloc
.exp
.X_add_number
& ~0xFF) == 0))
8875 /* This can be done with a mov instruction. */
8877 inst
.instruction
= T_OPCODE_MOV_I8
| (Rd
<< 8);
8878 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
8882 /* Insert into literal pool. */
8883 if (add_to_lit_pool () == FAIL
)
8886 inst
.error
= "literal pool insertion failed";
8890 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8891 inst
.reloc
.pc_rel
= 1;
8892 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
8893 /* Adjust ARM pipeline offset to Thumb. */
8894 inst
.reloc
.exp
.X_add_number
+= 4;
8900 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8903 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
8904 inst
.reloc
.pc_rel
= 1;
8905 inst
.reloc
.exp
.X_add_number
-= 4; /* Pipeline offset. */
8906 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8911 if (Rb
== REG_PC
|| Rb
== REG_SP
)
8913 if (size
!= THUMB_WORD
)
8915 inst
.error
= _("byte or halfword not valid for base register");
8918 else if (Rb
== REG_PC
&& load_store
!= THUMB_LOAD
)
8920 inst
.error
= _("r15 based store not allowed");
8923 else if (Ro
!= FAIL
)
8925 inst
.error
= _("invalid base register for register offset");
8930 inst
.instruction
= T_OPCODE_LDR_PC
;
8931 else if (load_store
== THUMB_LOAD
)
8932 inst
.instruction
= T_OPCODE_LDR_SP
;
8934 inst
.instruction
= T_OPCODE_STR_SP
;
8936 inst
.instruction
|= Rd
<< 8;
8937 if (inst
.reloc
.exp
.X_op
== O_constant
)
8939 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
8941 if (offset
& ~0x3fc)
8943 inst
.error
= _("invalid offset");
8947 inst
.instruction
|= offset
>> 2;
8950 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8954 inst
.error
= _("invalid base register in load/store");
8957 else if (Ro
== FAIL
)
8959 /* Immediate offset. */
8960 if (size
== THUMB_WORD
)
8961 inst
.instruction
= (load_store
== THUMB_LOAD
8962 ? T_OPCODE_LDR_IW
: T_OPCODE_STR_IW
);
8963 else if (size
== THUMB_HALFWORD
)
8964 inst
.instruction
= (load_store
== THUMB_LOAD
8965 ? T_OPCODE_LDR_IH
: T_OPCODE_STR_IH
);
8967 inst
.instruction
= (load_store
== THUMB_LOAD
8968 ? T_OPCODE_LDR_IB
: T_OPCODE_STR_IB
);
8970 inst
.instruction
|= Rd
| (Rb
<< 3);
8972 if (inst
.reloc
.exp
.X_op
== O_constant
)
8974 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
8976 if (offset
& ~(0x1f << size
))
8978 inst
.error
= _("invalid offset");
8981 inst
.instruction
|= (offset
>> size
) << 6;
8984 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8988 /* Register offset. */
8989 if (size
== THUMB_WORD
)
8990 inst
.instruction
= (load_store
== THUMB_LOAD
8991 ? T_OPCODE_LDR_RW
: T_OPCODE_STR_RW
);
8992 else if (size
== THUMB_HALFWORD
)
8993 inst
.instruction
= (load_store
== THUMB_LOAD
8994 ? T_OPCODE_LDR_RH
: T_OPCODE_STR_RH
);
8996 inst
.instruction
= (load_store
== THUMB_LOAD
8997 ? T_OPCODE_LDR_RB
: T_OPCODE_STR_RB
);
8999 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
9005 /* A register must be given at this point.
9007 Shift is the place to put it in inst.instruction.
9009 Restores input start point on err.
9010 Returns the reg#, or FAIL. */
9013 mav_reg_required_here (str
, shift
, regtype
)
9016 enum arm_reg_type regtype
;
9021 if ((reg
= arm_reg_parse (str
, all_reg_maps
[regtype
].htab
)) != FAIL
)
9024 inst
.instruction
|= reg
<< shift
;
9029 /* Restore the start point. */
9032 /* In the few cases where we might be able to accept something else
9033 this error can be overridden. */
9034 inst
.error
= _(all_reg_maps
[regtype
].expected
);
9039 /* Cirrus Maverick Instructions. */
9041 /* Wrapper functions. */
9044 do_mav_binops_1a (str
)
9047 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVF
);
9051 do_mav_binops_1b (str
)
9054 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVD
);
9058 do_mav_binops_1c (str
)
9061 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVDX
);
9065 do_mav_binops_1d (str
)
9068 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVF
);
9072 do_mav_binops_1e (str
)
9075 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVD
);
9079 do_mav_binops_1f (str
)
9082 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVF
);
9086 do_mav_binops_1g (str
)
9089 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVD
);
9093 do_mav_binops_1h (str
)
9096 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVFX
);
9100 do_mav_binops_1i (str
)
9103 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVFX
);
9107 do_mav_binops_1j (str
)
9110 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVDX
);
9114 do_mav_binops_1k (str
)
9117 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVDX
);
9121 do_mav_binops_1l (str
)
9124 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVF
);
9128 do_mav_binops_1m (str
)
9131 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVD
);
9135 do_mav_binops_1n (str
)
9138 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
9142 do_mav_binops_1o (str
)
9145 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
9149 do_mav_binops_2a (str
)
9152 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVF
, REG_TYPE_RN
);
9156 do_mav_binops_2b (str
)
9159 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVD
, REG_TYPE_RN
);
9163 do_mav_binops_2c (str
)
9166 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVDX
, REG_TYPE_RN
);
9170 do_mav_binops_3a (str
)
9173 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVFX
);
9177 do_mav_binops_3b (str
)
9180 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVFX
, REG_TYPE_MVAX
);
9184 do_mav_binops_3c (str
)
9187 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVDX
);
9191 do_mav_binops_3d (str
)
9194 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVDX
, REG_TYPE_MVAX
);
9198 do_mav_triple_4a (str
)
9201 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_RN
);
9205 do_mav_triple_4b (str
)
9208 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_RN
);
9212 do_mav_triple_5a (str
)
9215 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVF
, REG_TYPE_MVF
);
9219 do_mav_triple_5b (str
)
9222 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVD
, REG_TYPE_MVD
);
9226 do_mav_triple_5c (str
)
9229 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
9233 do_mav_triple_5d (str
)
9236 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
9240 do_mav_triple_5e (str
)
9243 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVF
, REG_TYPE_MVF
, REG_TYPE_MVF
);
9247 do_mav_triple_5f (str
)
9250 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVD
, REG_TYPE_MVD
, REG_TYPE_MVD
);
9254 do_mav_triple_5g (str
)
9257 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
9261 do_mav_triple_5h (str
)
9264 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
9268 do_mav_quad_6a (str
)
9271 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
,
9276 do_mav_quad_6b (str
)
9279 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVAX
, REG_TYPE_MVFX
,
9283 /* cfmvsc32<cond> DSPSC,MVFX[15:0]. */
9285 do_mav_dspsc_1 (str
)
9288 skip_whitespace (str
);
9291 if (mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
9292 || skip_past_comma (&str
) == FAIL
9293 || mav_reg_required_here (&str
, 16, REG_TYPE_MVFX
) == FAIL
)
9296 inst
.error
= BAD_ARGS
;
9304 /* cfmv32sc<cond> MVFX[15:0],DSPSC. */
9306 do_mav_dspsc_2 (str
)
9309 skip_whitespace (str
);
9312 if (mav_reg_required_here (&str
, 0, REG_TYPE_MVFX
) == FAIL
9313 || skip_past_comma (&str
) == FAIL
9314 || mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
)
9317 inst
.error
= BAD_ARGS
;
9326 do_mav_shift_1 (str
)
9329 do_mav_shift (str
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
9333 do_mav_shift_2 (str
)
9336 do_mav_shift (str
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
9343 do_mav_ldst (str
, REG_TYPE_MVF
);
9350 do_mav_ldst (str
, REG_TYPE_MVD
);
9357 do_mav_ldst (str
, REG_TYPE_MVFX
);
9364 do_mav_ldst (str
, REG_TYPE_MVDX
);
9367 /* Isnsn like "foo X,Y". */
9370 do_mav_binops (str
, mode
, reg0
, reg1
)
9373 enum arm_reg_type reg0
;
9374 enum arm_reg_type reg1
;
9378 shift0
= mode
& 0xff;
9379 shift1
= (mode
>> 8) & 0xff;
9381 skip_whitespace (str
);
9383 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
9384 || skip_past_comma (&str
) == FAIL
9385 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
)
9388 inst
.error
= BAD_ARGS
;
9394 /* Isnsn like "foo X,Y,Z". */
9397 do_mav_triple (str
, mode
, reg0
, reg1
, reg2
)
9400 enum arm_reg_type reg0
;
9401 enum arm_reg_type reg1
;
9402 enum arm_reg_type reg2
;
9404 int shift0
, shift1
, shift2
;
9406 shift0
= mode
& 0xff;
9407 shift1
= (mode
>> 8) & 0xff;
9408 shift2
= (mode
>> 16) & 0xff;
9410 skip_whitespace (str
);
9412 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
9413 || skip_past_comma (&str
) == FAIL
9414 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
9415 || skip_past_comma (&str
) == FAIL
9416 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
)
9419 inst
.error
= BAD_ARGS
;
9425 /* Isnsn like "foo W,X,Y,Z".
9426 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
9429 do_mav_quad (str
, mode
, reg0
, reg1
, reg2
, reg3
)
9432 enum arm_reg_type reg0
;
9433 enum arm_reg_type reg1
;
9434 enum arm_reg_type reg2
;
9435 enum arm_reg_type reg3
;
9437 int shift0
, shift1
, shift2
, shift3
;
9439 shift0
= mode
& 0xff;
9440 shift1
= (mode
>> 8) & 0xff;
9441 shift2
= (mode
>> 16) & 0xff;
9442 shift3
= (mode
>> 24) & 0xff;
9444 skip_whitespace (str
);
9446 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
9447 || skip_past_comma (&str
) == FAIL
9448 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
9449 || skip_past_comma (&str
) == FAIL
9450 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
9451 || skip_past_comma (&str
) == FAIL
9452 || mav_reg_required_here (&str
, shift3
, reg3
) == FAIL
)
9455 inst
.error
= BAD_ARGS
;
9461 /* Maverick shift immediate instructions.
9462 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
9463 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
9466 do_mav_shift (str
, reg0
, reg1
)
9468 enum arm_reg_type reg0
;
9469 enum arm_reg_type reg1
;
9474 skip_whitespace (str
);
9478 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
9479 || skip_past_comma (&str
) == FAIL
9480 || mav_reg_required_here (&str
, 16, reg1
) == FAIL
9481 || skip_past_comma (&str
) == FAIL
)
9484 inst
.error
= BAD_ARGS
;
9488 /* Calculate the immediate operand.
9489 The operand is a 7bit signed number. */
9490 skip_whitespace (str
);
9495 if (!ISDIGIT (*str
) && *str
!= '-')
9497 inst
.error
= _("expecting immediate, 7bit operand");
9507 for (imm
= 0; *str
&& ISDIGIT (*str
); ++str
)
9508 imm
= imm
* 10 + *str
- '0';
9512 inst
.error
= _("immediate out of range");
9516 /* Make negative imm's into 7bit signed numbers. */
9523 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
9524 Bits 5-7 of the insn should have bits 4-6 of the immediate.
9525 Bit 4 should be 0. */
9526 imm
= (imm
& 0xf) | ((imm
& 0x70) << 1);
9528 inst
.instruction
|= imm
;
9533 mav_parse_offset (str
, negative
)
9542 skip_whitespace (p
);
9555 inst
.error
= _("offset expected");
9559 for (offset
= 0; *p
&& ISDIGIT (*p
); ++p
)
9560 offset
= offset
* 10 + *p
- '0';
9564 inst
.error
= _("offset out of range");
9570 return *negative
? -offset
: offset
;
9573 /* Maverick load/store instructions.
9574 <insn><cond> CRd,[Rn,<offset>]{!}.
9575 <insn><cond> CRd,[Rn],<offset>. */
9578 do_mav_ldst (str
, reg0
)
9580 enum arm_reg_type reg0
;
9582 int offset
, negative
;
9584 skip_whitespace (str
);
9586 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
9587 || skip_past_comma (&str
) == FAIL
9589 || reg_required_here (&str
, 16) == FAIL
)
9592 if (skip_past_comma (&str
) == SUCCESS
)
9594 /* You are here: "<offset>]{!}". */
9595 inst
.instruction
|= PRE_INDEX
;
9597 offset
= mav_parse_offset (&str
, &negative
);
9604 inst
.error
= _("missing ]");
9610 inst
.instruction
|= WRITE_BACK
;
9616 /* You are here: "], <offset>". */
9619 inst
.error
= _("missing ]");
9623 if (skip_past_comma (&str
) == FAIL
9624 || (offset
= mav_parse_offset (&str
, &negative
), inst
.error
))
9627 inst
.instruction
|= CP_T_WB
; /* Post indexed, set bit W. */
9633 inst
.instruction
|= CP_T_UD
; /* Postive, so set bit U. */
9635 inst
.instruction
|= offset
>> 2;
9641 inst
.error
= BAD_ARGS
;
9654 /* Handle the Format 4 instructions that do not have equivalents in other
9655 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
9664 skip_whitespace (str
);
9666 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9667 || skip_past_comma (&str
) == FAIL
9668 || (Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9670 inst
.error
= BAD_ARGS
;
9674 if (skip_past_comma (&str
) != FAIL
)
9676 /* Three operand format not allowed for TST, CMN, NEG and MVN.
9677 (It isn't allowed for CMP either, but that isn't handled by this
9679 if (inst
.instruction
== T_OPCODE_TST
9680 || inst
.instruction
== T_OPCODE_CMN
9681 || inst
.instruction
== T_OPCODE_NEG
9682 || inst
.instruction
== T_OPCODE_MVN
)
9684 inst
.error
= BAD_ARGS
;
9688 if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9693 inst
.error
= _("dest and source1 must be the same register");
9699 if (inst
.instruction
== T_OPCODE_MUL
9701 as_tsktsk (_("Rs and Rd must be different in MUL"));
9703 inst
.instruction
|= Rd
| (Rs
<< 3);
9711 thumb_add_sub (str
, 0);
9718 thumb_shift (str
, THUMB_ASR
);
9725 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9727 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH9
;
9728 inst
.reloc
.pc_rel
= 1;
9736 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9738 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH12
;
9739 inst
.reloc
.pc_rel
= 1;
9743 /* Find the real, Thumb encoded start of a Thumb function. */
9746 find_real_start (symbolP
)
9750 const char * name
= S_GET_NAME (symbolP
);
9751 symbolS
* new_target
;
9753 /* This definiton must agree with the one in gcc/config/arm/thumb.c. */
9754 #define STUB_NAME ".real_start_of"
9759 /* Names that start with '.' are local labels, not function entry points.
9760 The compiler may generate BL instructions to these labels because it
9761 needs to perform a branch to a far away location. */
9765 real_start
= malloc (strlen (name
) + strlen (STUB_NAME
) + 1);
9766 sprintf (real_start
, "%s%s", STUB_NAME
, name
);
9768 new_target
= symbol_find (real_start
);
9770 if (new_target
== NULL
)
9772 as_warn ("Failed to find real start of function: %s\n", name
);
9773 new_target
= symbolP
;
9785 if (my_get_expression (& inst
.reloc
.exp
, & str
))
9788 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH23
;
9789 inst
.reloc
.pc_rel
= 1;
9792 /* If the destination of the branch is a defined symbol which does not have
9793 the THUMB_FUNC attribute, then we must be calling a function which has
9794 the (interfacearm) attribute. We look for the Thumb entry point to that
9795 function and change the branch to refer to that function instead. */
9796 if ( inst
.reloc
.exp
.X_op
== O_symbol
9797 && inst
.reloc
.exp
.X_add_symbol
!= NULL
9798 && S_IS_DEFINED (inst
.reloc
.exp
.X_add_symbol
)
9799 && ! THUMB_IS_FUNC (inst
.reloc
.exp
.X_add_symbol
))
9800 inst
.reloc
.exp
.X_add_symbol
=
9801 find_real_start (inst
.reloc
.exp
.X_add_symbol
);
9810 skip_whitespace (str
);
9812 if ((reg
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
9815 /* This sets THUMB_H2 from the top bit of reg. */
9816 inst
.instruction
|= reg
<< 3;
9818 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
9819 should cause the alignment to be checked once it is known. This is
9820 because BX PC only works if the instruction is word aligned. */
9829 thumb_mov_compare (str
, THUMB_COMPARE
);
9839 skip_whitespace (str
);
9841 if ((Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9845 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
9849 if (skip_past_comma (&str
) == FAIL
9850 || (range
= reg_list (&str
)) == FAIL
)
9853 inst
.error
= BAD_ARGS
;
9857 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
9859 /* This really doesn't seem worth it. */
9860 inst
.reloc
.type
= BFD_RELOC_NONE
;
9861 inst
.error
= _("expression too complex");
9867 inst
.error
= _("only lo-regs valid in load/store multiple");
9871 inst
.instruction
|= (Rb
<< 8) | range
;
9879 thumb_load_store (str
, THUMB_LOAD
, THUMB_WORD
);
9886 thumb_load_store (str
, THUMB_LOAD
, THUMB_BYTE
);
9893 thumb_load_store (str
, THUMB_LOAD
, THUMB_HALFWORD
);
9902 skip_whitespace (str
);
9904 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9905 || skip_past_comma (&str
) == FAIL
9907 || (Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9908 || skip_past_comma (&str
) == FAIL
9909 || (Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9913 inst
.error
= _("syntax: ldrs[b] Rd, [Rb, Ro]");
9917 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
9925 thumb_shift (str
, THUMB_LSL
);
9932 thumb_shift (str
, THUMB_LSR
);
9939 thumb_mov_compare (str
, THUMB_MOVE
);
9948 skip_whitespace (str
);
9950 if ((range
= reg_list (&str
)) == FAIL
)
9953 inst
.error
= BAD_ARGS
;
9957 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
9959 /* This really doesn't seem worth it. */
9960 inst
.reloc
.type
= BFD_RELOC_NONE
;
9961 inst
.error
= _("expression too complex");
9967 if ((inst
.instruction
== T_OPCODE_PUSH
9968 && (range
& ~0xff) == 1 << REG_LR
)
9969 || (inst
.instruction
== T_OPCODE_POP
9970 && (range
& ~0xff) == 1 << REG_PC
))
9972 inst
.instruction
|= THUMB_PP_PC_LR
;
9977 inst
.error
= _("invalid register list to push/pop instruction");
9982 inst
.instruction
|= range
;
9990 thumb_load_store (str
, THUMB_STORE
, THUMB_WORD
);
9997 thumb_load_store (str
, THUMB_STORE
, THUMB_BYTE
);
10004 thumb_load_store (str
, THUMB_STORE
, THUMB_HALFWORD
);
10011 thumb_add_sub (str
, 1);
10018 skip_whitespace (str
);
10020 if (my_get_expression (&inst
.reloc
.exp
, &str
))
10023 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
10034 /* This is a pseudo-op of the form "adr rd, label" to be converted
10035 into a relative address of the form "add rd, pc, #label-.-4". */
10036 skip_whitespace (str
);
10038 /* Store Rd in temporary location inside instruction. */
10039 if ((reg
= reg_required_here (&str
, 4)) == FAIL
10040 || (reg
> 7) /* For Thumb reg must be r0..r7. */
10041 || skip_past_comma (&str
) == FAIL
10042 || my_get_expression (&inst
.reloc
.exp
, &str
))
10045 inst
.error
= BAD_ARGS
;
10049 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
10050 inst
.reloc
.exp
.X_add_number
-= 4; /* PC relative adjust. */
10051 inst
.reloc
.pc_rel
= 1;
10052 inst
.instruction
|= REG_PC
; /* Rd is already placed into the instruction. */
10058 insert_reg (r
, htab
)
10059 const struct reg_entry
*r
;
10060 struct hash_control
*htab
;
10062 int len
= strlen (r
->name
) + 2;
10063 char * buf
= (char *) xmalloc (len
);
10064 char * buf2
= (char *) xmalloc (len
);
10067 #ifdef REGISTER_PREFIX
10068 buf
[i
++] = REGISTER_PREFIX
;
10071 strcpy (buf
+ i
, r
->name
);
10073 for (i
= 0; buf
[i
]; i
++)
10074 buf2
[i
] = TOUPPER (buf
[i
]);
10078 hash_insert (htab
, buf
, (PTR
) r
);
10079 hash_insert (htab
, buf2
, (PTR
) r
);
10083 build_reg_hsh (map
)
10084 struct reg_map
*map
;
10086 const struct reg_entry
*r
;
10088 if ((map
->htab
= hash_new ()) == NULL
)
10089 as_fatal (_("virtual memory exhausted"));
10091 for (r
= map
->names
; r
->name
!= NULL
; r
++)
10092 insert_reg (r
, map
->htab
);
10096 insert_reg_alias (str
, regnum
, htab
)
10099 struct hash_control
*htab
;
10102 struct reg_entry
*new = xmalloc (sizeof (struct reg_entry
));
10103 const char *name
= xmalloc (strlen (str
) + 1);
10105 strcpy ((char *) name
, str
);
10108 new->number
= regnum
;
10109 new->builtin
= FALSE
;
10111 error
= hash_insert (htab
, name
, (PTR
) new);
10114 as_bad (_("failed to create an alias for %s, reason: %s"),
10116 free ((char *) name
);
10121 /* Look for the .req directive. This is of the form:
10123 new_register_name .req existing_register_name
10125 If we find one, or if it looks sufficiently like one that we want to
10126 handle any error here, return non-zero. Otherwise return zero. */
10128 create_register_alias (newname
, p
)
10136 skip_whitespace (q
);
10141 if (*q
&& !strncmp (q
, ".req ", 5))
10146 #ifdef IGNORE_OPCODE_CASE
10147 newname
= original_case_string
;
10149 copy_of_str
= newname
;
10152 skip_whitespace (q
);
10154 for (r
= q
; *r
!= '\0'; r
++)
10160 enum arm_reg_type new_type
, old_type
;
10165 old_type
= arm_reg_parse_any (q
);
10168 new_type
= arm_reg_parse_any (newname
);
10170 if (new_type
== REG_TYPE_MAX
)
10172 if (old_type
!= REG_TYPE_MAX
)
10174 old_regno
= arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
);
10175 insert_reg_alias (newname
, old_regno
,
10176 all_reg_maps
[old_type
].htab
);
10179 as_warn (_("register '%s' does not exist\n"), q
);
10181 else if (old_type
== REG_TYPE_MAX
)
10183 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
10188 /* Do not warn about redefinitions to the same alias. */
10189 if (new_type
!= old_type
10190 || (arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
)
10191 != arm_reg_parse (&q
, all_reg_maps
[new_type
].htab
)))
10192 as_warn (_("ignoring redefinition of register alias '%s'"),
10198 as_warn (_("ignoring incomplete .req pseuso op"));
10209 set_constant_flonums ()
10213 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
10214 if (atof_ieee ((char *) fp_const
[i
], 'x', fp_values
[i
]) == NULL
)
10218 /* Iterate over the base tables to create the instruction patterns. */
10220 build_arm_ops_hsh ()
10224 static struct obstack insn_obstack
;
10226 obstack_begin (&insn_obstack
, 4000);
10228 for (i
= 0; i
< sizeof (insns
) / sizeof (struct asm_opcode
); i
++)
10230 const struct asm_opcode
*insn
= insns
+ i
;
10232 if (insn
->cond_offset
!= 0)
10234 /* Insn supports conditional execution. Build the varaints
10235 and insert them in the hash table. */
10236 for (j
= 0; j
< sizeof (conds
) / sizeof (struct asm_cond
); j
++)
10238 unsigned len
= strlen (insn
->template);
10239 struct asm_opcode
*new;
10242 new = obstack_alloc (&insn_obstack
, sizeof (struct asm_opcode
));
10243 /* All condition codes are two characters. */
10244 template = obstack_alloc (&insn_obstack
, len
+ 3);
10246 strncpy (template, insn
->template, insn
->cond_offset
);
10247 strcpy (template + insn
->cond_offset
, conds
[j
].template);
10248 if (len
> insn
->cond_offset
)
10249 strcpy (template + insn
->cond_offset
+ 2,
10250 insn
->template + insn
->cond_offset
);
10251 new->template = template;
10252 new->cond_offset
= 0;
10253 new->variant
= insn
->variant
;
10254 new->parms
= insn
->parms
;
10255 new->value
= (insn
->value
& ~COND_MASK
) | conds
[j
].value
;
10257 hash_insert (arm_ops_hsh
, new->template, (PTR
) new);
10260 /* Finally, insert the unconditional insn in the table directly;
10261 no need to build a copy. */
10262 hash_insert (arm_ops_hsh
, insn
->template, (PTR
) insn
);
10266 #if 0 /* Suppressed - for now. */
10267 #if defined OBJ_ELF || defined OBJ_COFF
10270 #define arm_Note Elf_External_Note
10274 unsigned char namesz
[4]; /* Size of entry's owner string. */
10275 unsigned char descsz
[4]; /* Size of the note descriptor. */
10276 unsigned char type
[4]; /* Interpretation of the descriptor. */
10277 char name
[1]; /* Start of the name+desc data. */
10281 /* The description is kept to a fix sized in order to make updating
10282 it and merging it easier. */
10283 #define ARM_NOTE_DESCRIPTION_LENGTH 8
10286 arm_add_note (name
, description
, type
)
10288 const char * description
;
10291 arm_Note note ATTRIBUTE_UNUSED
;
10293 unsigned int name_len
;
10295 name_len
= (strlen (name
) + 1 + 3) & ~3;
10297 p
= frag_more (sizeof (note
.namesz
));
10298 md_number_to_chars (p
, (valueT
) name_len
, sizeof (note
.namesz
));
10300 p
= frag_more (sizeof (note
.descsz
));
10301 md_number_to_chars (p
, (valueT
) ARM_NOTE_DESCRIPTION_LENGTH
, sizeof (note
.descsz
));
10303 p
= frag_more (sizeof (note
.type
));
10304 md_number_to_chars (p
, (valueT
) type
, sizeof (note
.type
));
10306 p
= frag_more (name_len
);
10309 p
= frag_more (ARM_NOTE_DESCRIPTION_LENGTH
);
10310 strncpy (p
, description
, ARM_NOTE_DESCRIPTION_LENGTH
);
10311 frag_align (2, 0, 0);
10322 if ( (arm_ops_hsh
= hash_new ()) == NULL
10323 || (arm_tops_hsh
= hash_new ()) == NULL
10324 || (arm_cond_hsh
= hash_new ()) == NULL
10325 || (arm_shift_hsh
= hash_new ()) == NULL
10326 || (arm_psr_hsh
= hash_new ()) == NULL
)
10327 as_fatal (_("virtual memory exhausted"));
10329 build_arm_ops_hsh ();
10330 for (i
= 0; i
< sizeof (tinsns
) / sizeof (struct thumb_opcode
); i
++)
10331 hash_insert (arm_tops_hsh
, tinsns
[i
].template, (PTR
) (tinsns
+ i
));
10332 for (i
= 0; i
< sizeof (conds
) / sizeof (struct asm_cond
); i
++)
10333 hash_insert (arm_cond_hsh
, conds
[i
].template, (PTR
) (conds
+ i
));
10334 for (i
= 0; i
< sizeof (shift_names
) / sizeof (struct asm_shift_name
); i
++)
10335 hash_insert (arm_shift_hsh
, shift_names
[i
].name
, (PTR
) (shift_names
+ i
));
10336 for (i
= 0; i
< sizeof (psrs
) / sizeof (struct asm_psr
); i
++)
10337 hash_insert (arm_psr_hsh
, psrs
[i
].template, (PTR
) (psrs
+ i
));
10339 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
10340 build_reg_hsh (all_reg_maps
+ i
);
10342 set_constant_flonums ();
10344 /* Set the cpu variant based on the command-line options. We prefer
10345 -mcpu= over -march= if both are set (as for GCC); and we prefer
10346 -mfpu= over any other way of setting the floating point unit.
10347 Use of legacy options with new options are faulted. */
10348 if (legacy_cpu
!= -1)
10350 if (mcpu_cpu_opt
!= -1 || march_cpu_opt
!= -1)
10351 as_bad (_("use of old and new-style options to set CPU type"));
10353 mcpu_cpu_opt
= legacy_cpu
;
10355 else if (mcpu_cpu_opt
== -1)
10356 mcpu_cpu_opt
= march_cpu_opt
;
10358 if (legacy_fpu
!= -1)
10360 if (mfpu_opt
!= -1)
10361 as_bad (_("use of old and new-style options to set FPU type"));
10363 mfpu_opt
= legacy_fpu
;
10365 else if (mfpu_opt
== -1)
10367 #if !(defined (TE_LINUX) || defined (TE_NetBSD))
10368 /* Some environments specify a default FPU. If they don't, infer it
10369 from the processor. */
10370 if (mcpu_fpu_opt
!= -1)
10371 mfpu_opt
= mcpu_fpu_opt
;
10373 mfpu_opt
= march_fpu_opt
;
10375 mfpu_opt
= FPU_DEFAULT
;
10379 if (mfpu_opt
== -1)
10381 if (mcpu_cpu_opt
== -1)
10382 mfpu_opt
= FPU_DEFAULT
;
10383 else if (mcpu_cpu_opt
& ARM_EXT_V5
)
10384 mfpu_opt
= FPU_ARCH_VFP_V2
;
10386 mfpu_opt
= FPU_ARCH_FPA
;
10389 if (mcpu_cpu_opt
== -1)
10390 mcpu_cpu_opt
= CPU_DEFAULT
;
10392 cpu_variant
= mcpu_cpu_opt
| mfpu_opt
;
10394 #if defined OBJ_COFF || defined OBJ_ELF
10396 unsigned int flags
= 0;
10398 /* Set the flags in the private structure. */
10399 if (uses_apcs_26
) flags
|= F_APCS26
;
10400 if (support_interwork
) flags
|= F_INTERWORK
;
10401 if (uses_apcs_float
) flags
|= F_APCS_FLOAT
;
10402 if (pic_code
) flags
|= F_PIC
;
10403 if ((cpu_variant
& FPU_ANY
) == FPU_NONE
10404 || (cpu_variant
& FPU_ANY
) == FPU_ARCH_VFP
) /* VFP layout only. */
10405 flags
|= F_SOFT_FLOAT
;
10406 /* Using VFP conventions (even if soft-float). */
10407 if (cpu_variant
& FPU_VFP_EXT_NONE
) flags
|= F_VFP_FLOAT
;
10409 #if defined OBJ_ELF
10410 if (cpu_variant
& ARM_CEXT_MAVERICK
)
10412 flags
&= ~ F_SOFT_FLOAT
;
10413 flags
|= EF_ARM_MAVERICK_FLOAT
;
10417 bfd_set_private_flags (stdoutput
, flags
);
10419 /* We have run out flags in the COFF header to encode the
10420 status of ATPCS support, so instead we create a dummy,
10421 empty, debug section called .arm.atpcs. */
10426 sec
= bfd_make_section (stdoutput
, ".arm.atpcs");
10430 bfd_set_section_flags
10431 (stdoutput
, sec
, SEC_READONLY
| SEC_DEBUGGING
/* | SEC_HAS_CONTENTS */);
10432 bfd_set_section_size (stdoutput
, sec
, 0);
10433 bfd_set_section_contents (stdoutput
, sec
, NULL
, 0, 0);
10439 /* Record the CPU type as well. */
10440 switch (cpu_variant
& ARM_CPU_MASK
)
10443 mach
= bfd_mach_arm_2
;
10446 case ARM_3
: /* Also ARM_250. */
10447 mach
= bfd_mach_arm_2a
;
10450 case ARM_6
: /* Also ARM_7. */
10451 mach
= bfd_mach_arm_3
;
10455 mach
= bfd_mach_arm_unknown
;
10459 /* Catch special cases. */
10460 if (cpu_variant
& ARM_CEXT_IWMMXT
)
10461 mach
= bfd_mach_arm_iWMMXt
;
10462 else if (cpu_variant
& ARM_CEXT_XSCALE
)
10463 mach
= bfd_mach_arm_XScale
;
10464 else if (cpu_variant
& ARM_CEXT_MAVERICK
)
10465 mach
= bfd_mach_arm_ep9312
;
10466 else if (cpu_variant
& ARM_EXT_V5E
)
10467 mach
= bfd_mach_arm_5TE
;
10468 else if (cpu_variant
& ARM_EXT_V5
)
10470 if (cpu_variant
& ARM_EXT_V4T
)
10471 mach
= bfd_mach_arm_5T
;
10473 mach
= bfd_mach_arm_5
;
10475 else if (cpu_variant
& ARM_EXT_V4
)
10477 if (cpu_variant
& ARM_EXT_V4T
)
10478 mach
= bfd_mach_arm_4T
;
10480 mach
= bfd_mach_arm_4
;
10482 else if (cpu_variant
& ARM_EXT_V3M
)
10483 mach
= bfd_mach_arm_3M
;
10485 #if 0 /* Suppressed - for now. */
10486 #if defined (OBJ_ELF) || defined (OBJ_COFF)
10488 /* Create a .note section to fully identify this arm binary. */
10490 #define NOTE_ARCH_STRING "arch: "
10492 #if defined OBJ_COFF && ! defined NT_VERSION
10493 #define NT_VERSION 1
10498 segT current_seg
= now_seg
;
10499 subsegT current_subseg
= now_subseg
;
10500 asection
* arm_arch
;
10501 const char * arch_string
;
10503 arm_arch
= bfd_make_section_old_way (stdoutput
, ARM_NOTE_SECTION
);
10506 bfd_set_section_flags (stdoutput
, arm_arch
,
10507 SEC_DATA
| SEC_ALLOC
| SEC_LOAD
| SEC_LINK_ONCE \
10508 | SEC_HAS_CONTENTS
);
10510 arm_arch
->output_section
= arm_arch
;
10511 subseg_set (arm_arch
, 0);
10516 case bfd_mach_arm_unknown
: arch_string
= "unknown"; break;
10517 case bfd_mach_arm_2
: arch_string
= "armv2"; break;
10518 case bfd_mach_arm_2a
: arch_string
= "armv2a"; break;
10519 case bfd_mach_arm_3
: arch_string
= "armv3"; break;
10520 case bfd_mach_arm_3M
: arch_string
= "armv3M"; break;
10521 case bfd_mach_arm_4
: arch_string
= "armv4"; break;
10522 case bfd_mach_arm_4T
: arch_string
= "armv4t"; break;
10523 case bfd_mach_arm_5
: arch_string
= "armv5"; break;
10524 case bfd_mach_arm_5T
: arch_string
= "armv5t"; break;
10525 case bfd_mach_arm_5TE
: arch_string
= "armv5te"; break;
10526 case bfd_mach_arm_XScale
: arch_string
= "XScale"; break;
10527 case bfd_mach_arm_ep9312
: arch_string
= "ep9312"; break;
10528 case bfd_mach_arm_iWMMXt
: arch_string
= "iWMMXt"; break;
10531 arm_add_note (NOTE_ARCH_STRING
, arch_string
, NT_ARCH
);
10533 subseg_set (current_seg
, current_subseg
);
10536 #endif /* Suppressed code. */
10538 bfd_set_arch_mach (stdoutput
, TARGET_ARCH
, mach
);
10541 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
10542 for use in the a.out file, and stores them in the array pointed to by buf.
10543 This knows about the endian-ness of the target machine and does
10544 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
10545 2 (short) and 4 (long) Floating numbers are put out as a series of
10546 LITTLENUMS (shorts, here at least). */
10549 md_number_to_chars (buf
, val
, n
)
10554 if (target_big_endian
)
10555 number_to_chars_bigendian (buf
, val
, n
);
10557 number_to_chars_littleendian (buf
, val
, n
);
10561 md_chars_to_number (buf
, n
)
10566 unsigned char * where
= (unsigned char *) buf
;
10568 if (target_big_endian
)
10573 result
|= (*where
++ & 255);
10581 result
|= (where
[n
] & 255);
10588 /* Turn a string in input_line_pointer into a floating point constant
10589 of type TYPE, and store the appropriate bytes in *LITP. The number
10590 of LITTLENUMS emitted is stored in *SIZEP. An error message is
10591 returned, or NULL on OK.
10593 Note that fp constants aren't represent in the normal way on the ARM.
10594 In big endian mode, things are as expected. However, in little endian
10595 mode fp constants are big-endian word-wise, and little-endian byte-wise
10596 within the words. For example, (double) 1.1 in big endian mode is
10597 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
10598 the byte sequence 99 99 f1 3f 9a 99 99 99.
10600 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
10603 md_atof (type
, litP
, sizeP
)
10609 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
10641 return _("bad call to MD_ATOF()");
10644 t
= atof_ieee (input_line_pointer
, type
, words
);
10646 input_line_pointer
= t
;
10649 if (target_big_endian
)
10651 for (i
= 0; i
< prec
; i
++)
10653 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
10659 if (cpu_variant
& FPU_ARCH_VFP
)
10660 for (i
= prec
- 1; i
>= 0; i
--)
10662 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
10666 /* For a 4 byte float the order of elements in `words' is 1 0.
10667 For an 8 byte float the order is 1 0 3 2. */
10668 for (i
= 0; i
< prec
; i
+= 2)
10670 md_number_to_chars (litP
, (valueT
) words
[i
+ 1], 2);
10671 md_number_to_chars (litP
+ 2, (valueT
) words
[i
], 2);
10679 /* The knowledge of the PC's pipeline offset is built into the insns
10683 md_pcrel_from (fixP
)
10687 && S_GET_SEGMENT (fixP
->fx_addsy
) == undefined_section
10688 && fixP
->fx_subsy
== NULL
)
10691 if (fixP
->fx_pcrel
&& (fixP
->fx_r_type
== BFD_RELOC_ARM_THUMB_ADD
))
10693 /* PC relative addressing on the Thumb is slightly odd
10694 as the bottom two bits of the PC are forced to zero
10695 for the calculation. */
10696 return (fixP
->fx_where
+ fixP
->fx_frag
->fr_address
) & ~3;
10700 /* The pattern was adjusted to accomodate CE's off-by-one fixups,
10701 so we un-adjust here to compensate for the accomodation. */
10702 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
+ 8;
10704 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
10708 /* Round up a section size to the appropriate boundary. */
10711 md_section_align (segment
, size
)
10712 segT segment ATTRIBUTE_UNUSED
;
10718 /* Round all sects to multiple of 4. */
10719 return (size
+ 3) & ~3;
10723 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
10724 Otherwise we have no need to default values of symbols. */
10727 md_undefined_symbol (name
)
10728 char * name ATTRIBUTE_UNUSED
;
10731 if (name
[0] == '_' && name
[1] == 'G'
10732 && streq (name
, GLOBAL_OFFSET_TABLE_NAME
))
10736 if (symbol_find (name
))
10737 as_bad ("GOT already in the symbol table");
10739 GOT_symbol
= symbol_new (name
, undefined_section
,
10740 (valueT
) 0, & zero_address_frag
);
10750 /* arm_reg_parse () := if it looks like a register, return its token and
10751 advance the pointer. */
10754 arm_reg_parse (ccp
, htab
)
10755 register char ** ccp
;
10756 struct hash_control
*htab
;
10758 char * start
= * ccp
;
10761 struct reg_entry
* reg
;
10763 #ifdef REGISTER_PREFIX
10764 if (*start
!= REGISTER_PREFIX
)
10769 #ifdef OPTIONAL_REGISTER_PREFIX
10770 if (*p
== OPTIONAL_REGISTER_PREFIX
)
10774 if (!ISALPHA (*p
) || !is_name_beginner (*p
))
10778 while (ISALPHA (c
) || ISDIGIT (c
) || c
== '_')
10782 reg
= (struct reg_entry
*) hash_find (htab
, start
);
10788 return reg
->number
;
10794 /* Search for the following register name in each of the possible reg name
10795 tables. Return the classification if found, or REG_TYPE_MAX if not
10797 static enum arm_reg_type
10798 arm_reg_parse_any (cp
)
10803 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
10804 if (arm_reg_parse (&cp
, all_reg_maps
[i
].htab
) != FAIL
)
10805 return (enum arm_reg_type
) i
;
10807 return REG_TYPE_MAX
;
10811 md_apply_fix3 (fixP
, valP
, seg
)
10816 offsetT value
= * valP
;
10818 unsigned int newimm
;
10819 unsigned long temp
;
10821 char * buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
10822 arm_fix_data
* arm_data
= (arm_fix_data
*) fixP
->tc_fix_data
;
10824 assert (fixP
->fx_r_type
< BFD_RELOC_UNUSED
);
10826 /* Note whether this will delete the relocation. */
10828 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
10829 doesn't work fully.) */
10830 if ((fixP
->fx_addsy
== 0 || symbol_constant_p (fixP
->fx_addsy
))
10831 && !fixP
->fx_pcrel
)
10833 if (fixP
->fx_addsy
== 0 && !fixP
->fx_pcrel
)
10837 /* If this symbol is in a different section then we need to leave it for
10838 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
10839 so we have to undo it's effects here. */
10840 if (fixP
->fx_pcrel
)
10842 if (fixP
->fx_addsy
!= NULL
10843 && S_IS_DEFINED (fixP
->fx_addsy
)
10844 && S_GET_SEGMENT (fixP
->fx_addsy
) != seg
)
10847 && (fixP
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
10848 || fixP
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
10852 value
+= md_pcrel_from (fixP
);
10856 /* Remember value for emit_reloc. */
10857 fixP
->fx_addnumber
= value
;
10859 switch (fixP
->fx_r_type
)
10861 case BFD_RELOC_ARM_IMMEDIATE
:
10862 newimm
= validate_immediate (value
);
10863 temp
= md_chars_to_number (buf
, INSN_SIZE
);
10865 /* If the instruction will fail, see if we can fix things up by
10866 changing the opcode. */
10867 if (newimm
== (unsigned int) FAIL
10868 && (newimm
= negate_data_op (&temp
, value
)) == (unsigned int) FAIL
)
10870 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10871 _("invalid constant (%lx) after fixup"),
10872 (unsigned long) value
);
10876 newimm
|= (temp
& 0xfffff000);
10877 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
10881 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
10883 unsigned int highpart
= 0;
10884 unsigned int newinsn
= 0xe1a00000; /* nop. */
10886 newimm
= validate_immediate (value
);
10887 temp
= md_chars_to_number (buf
, INSN_SIZE
);
10889 /* If the instruction will fail, see if we can fix things up by
10890 changing the opcode. */
10891 if (newimm
== (unsigned int) FAIL
10892 && (newimm
= negate_data_op (& temp
, value
)) == (unsigned int) FAIL
)
10894 /* No ? OK - try using two ADD instructions to generate
10896 newimm
= validate_immediate_twopart (value
, & highpart
);
10898 /* Yes - then make sure that the second instruction is
10900 if (newimm
!= (unsigned int) FAIL
)
10902 /* Still No ? Try using a negated value. */
10903 else if ((newimm
= validate_immediate_twopart (- value
, & highpart
)) != (unsigned int) FAIL
)
10904 temp
= newinsn
= (temp
& OPCODE_MASK
) | OPCODE_SUB
<< DATA_OP_SHIFT
;
10905 /* Otherwise - give up. */
10908 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10909 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
10914 /* Replace the first operand in the 2nd instruction (which
10915 is the PC) with the destination register. We have
10916 already added in the PC in the first instruction and we
10917 do not want to do it again. */
10918 newinsn
&= ~ 0xf0000;
10919 newinsn
|= ((newinsn
& 0x0f000) << 4);
10922 newimm
|= (temp
& 0xfffff000);
10923 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
10925 highpart
|= (newinsn
& 0xfffff000);
10926 md_number_to_chars (buf
+ INSN_SIZE
, (valueT
) highpart
, INSN_SIZE
);
10930 case BFD_RELOC_ARM_OFFSET_IMM
:
10936 if (validate_offset_imm (value
, 0) == FAIL
)
10938 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10939 _("bad immediate value for offset (%ld)"),
10944 newval
= md_chars_to_number (buf
, INSN_SIZE
);
10945 newval
&= 0xff7ff000;
10946 newval
|= value
| (sign
? INDEX_UP
: 0);
10947 md_number_to_chars (buf
, newval
, INSN_SIZE
);
10950 case BFD_RELOC_ARM_OFFSET_IMM8
:
10951 case BFD_RELOC_ARM_HWLITERAL
:
10957 if (validate_offset_imm (value
, 1) == FAIL
)
10959 if (fixP
->fx_r_type
== BFD_RELOC_ARM_HWLITERAL
)
10960 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10961 _("invalid literal constant: pool needs to be closer"));
10963 as_bad (_("bad immediate value for half-word offset (%ld)"),
10968 newval
= md_chars_to_number (buf
, INSN_SIZE
);
10969 newval
&= 0xff7ff0f0;
10970 newval
|= ((value
>> 4) << 8) | (value
& 0xf) | (sign
? INDEX_UP
: 0);
10971 md_number_to_chars (buf
, newval
, INSN_SIZE
);
10974 case BFD_RELOC_ARM_LITERAL
:
10980 if (validate_offset_imm (value
, 0) == FAIL
)
10982 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10983 _("invalid literal constant: pool needs to be closer"));
10987 newval
= md_chars_to_number (buf
, INSN_SIZE
);
10988 newval
&= 0xff7ff000;
10989 newval
|= value
| (sign
? INDEX_UP
: 0);
10990 md_number_to_chars (buf
, newval
, INSN_SIZE
);
10993 case BFD_RELOC_ARM_SHIFT_IMM
:
10994 newval
= md_chars_to_number (buf
, INSN_SIZE
);
10995 if (((unsigned long) value
) > 32
10997 && (((newval
& 0x60) == 0) || (newval
& 0x60) == 0x60)))
10999 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11000 _("shift expression is too large"));
11005 /* Shifts of zero must be done as lsl. */
11007 else if (value
== 32)
11009 newval
&= 0xfffff07f;
11010 newval
|= (value
& 0x1f) << 7;
11011 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11014 case BFD_RELOC_ARM_SWI
:
11015 if (arm_data
->thumb_mode
)
11017 if (((unsigned long) value
) > 0xff)
11018 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11019 _("invalid swi expression"));
11020 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xff00;
11022 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11026 if (((unsigned long) value
) > 0x00ffffff)
11027 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11028 _("invalid swi expression"));
11029 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff000000;
11031 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11035 case BFD_RELOC_ARM_MULTI
:
11036 if (((unsigned long) value
) > 0xffff)
11037 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11038 _("invalid expression in load/store multiple"));
11039 newval
= value
| md_chars_to_number (buf
, INSN_SIZE
);
11040 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11043 case BFD_RELOC_ARM_PCREL_BRANCH
:
11044 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11046 /* Sign-extend a 24-bit number. */
11047 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
11051 value
= fixP
->fx_offset
;
11054 /* We are going to store value (shifted right by two) in the
11055 instruction, in a 24 bit, signed field. Thus we need to check
11056 that none of the top 8 bits of the shifted value (top 7 bits of
11057 the unshifted, unsigned value) are set, or that they are all set. */
11058 if ((value
& ~ ((offsetT
) 0x1ffffff)) != 0
11059 && ((value
& ~ ((offsetT
) 0x1ffffff)) != ~ ((offsetT
) 0x1ffffff)))
11062 /* Normally we would be stuck at this point, since we cannot store
11063 the absolute address that is the destination of the branch in the
11064 24 bits of the branch instruction. If however, we happen to know
11065 that the destination of the branch is in the same section as the
11066 branch instruciton itself, then we can compute the relocation for
11067 ourselves and not have to bother the linker with it.
11069 FIXME: The tests for OBJ_ELF and ! target_oabi are only here
11070 because I have not worked out how to do this for OBJ_COFF or
11073 && fixP
->fx_addsy
!= NULL
11074 && S_IS_DEFINED (fixP
->fx_addsy
)
11075 && S_GET_SEGMENT (fixP
->fx_addsy
) == seg
)
11077 /* Get pc relative value to go into the branch. */
11080 /* Permit a backward branch provided that enough bits
11081 are set. Allow a forwards branch, provided that
11082 enough bits are clear. */
11083 if ( (value
& ~ ((offsetT
) 0x1ffffff)) == ~ ((offsetT
) 0x1ffffff)
11084 || (value
& ~ ((offsetT
) 0x1ffffff)) == 0)
11088 if (! fixP
->fx_done
)
11090 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11091 _("GAS can't handle same-section branch dest >= 0x04000000"));
11095 value
+= SEXT24 (newval
);
11097 if ( (value
& ~ ((offsetT
) 0xffffff)) != 0
11098 && ((value
& ~ ((offsetT
) 0xffffff)) != ~ ((offsetT
) 0xffffff)))
11099 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11100 _("out of range branch"));
11102 newval
= (value
& 0x00ffffff) | (newval
& 0xff000000);
11103 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11106 case BFD_RELOC_ARM_PCREL_BLX
:
11109 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11113 value
= fixP
->fx_offset
;
11115 hbit
= (value
>> 1) & 1;
11116 value
= (value
>> 2) & 0x00ffffff;
11117 value
= (value
+ (newval
& 0x00ffffff)) & 0x00ffffff;
11118 newval
= value
| (newval
& 0xfe000000) | (hbit
<< 24);
11119 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11123 case BFD_RELOC_THUMB_PCREL_BRANCH9
: /* Conditional branch. */
11124 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11126 addressT diff
= (newval
& 0xff) << 1;
11131 if ((value
& ~0xff) && ((value
& ~0xff) != ~0xff))
11132 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11133 _("branch out of range"));
11134 newval
= (newval
& 0xff00) | ((value
& 0x1ff) >> 1);
11136 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11139 case BFD_RELOC_THUMB_PCREL_BRANCH12
: /* Unconditional branch. */
11140 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11142 addressT diff
= (newval
& 0x7ff) << 1;
11147 if ((value
& ~0x7ff) && ((value
& ~0x7ff) != ~0x7ff))
11148 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11149 _("branch out of range"));
11150 newval
= (newval
& 0xf800) | ((value
& 0xfff) >> 1);
11152 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11155 case BFD_RELOC_THUMB_PCREL_BLX
:
11156 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
11161 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11162 newval2
= md_chars_to_number (buf
+ THUMB_SIZE
, THUMB_SIZE
);
11163 diff
= ((newval
& 0x7ff) << 12) | ((newval2
& 0x7ff) << 1);
11164 if (diff
& 0x400000)
11167 value
= fixP
->fx_offset
;
11171 if ((value
& ~0x3fffff) && ((value
& ~0x3fffff) != ~0x3fffff))
11172 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11173 _("branch with link out of range"));
11175 newval
= (newval
& 0xf800) | ((value
& 0x7fffff) >> 12);
11176 newval2
= (newval2
& 0xf800) | ((value
& 0xfff) >> 1);
11177 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
)
11178 /* For a BLX instruction, make sure that the relocation is rounded up
11179 to a word boundary. This follows the semantics of the instruction
11180 which specifies that bit 1 of the target address will come from bit
11181 1 of the base address. */
11182 newval2
= (newval2
+ 1) & ~ 1;
11183 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11184 md_number_to_chars (buf
+ THUMB_SIZE
, newval2
, THUMB_SIZE
);
11189 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11190 md_number_to_chars (buf
, value
, 1);
11192 else if (!target_oabi
)
11194 value
= fixP
->fx_offset
;
11195 md_number_to_chars (buf
, value
, 1);
11201 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11202 md_number_to_chars (buf
, value
, 2);
11204 else if (!target_oabi
)
11206 value
= fixP
->fx_offset
;
11207 md_number_to_chars (buf
, value
, 2);
11213 case BFD_RELOC_ARM_GOT32
:
11214 case BFD_RELOC_ARM_GOTOFF
:
11215 md_number_to_chars (buf
, 0, 4);
11219 case BFD_RELOC_RVA
:
11221 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11222 md_number_to_chars (buf
, value
, 4);
11224 else if (!target_oabi
)
11226 value
= fixP
->fx_offset
;
11227 md_number_to_chars (buf
, value
, 4);
11233 case BFD_RELOC_ARM_PLT32
:
11234 /* It appears the instruction is fully prepared at this point. */
11238 case BFD_RELOC_ARM_CP_OFF_IMM
:
11240 if (value
< -1023 || value
> 1023 || (value
& 3))
11241 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11242 _("illegal value for co-processor offset"));
11245 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
11246 newval
|= (value
>> 2) | (sign
? INDEX_UP
: 0);
11247 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11250 case BFD_RELOC_ARM_CP_OFF_IMM_S2
:
11252 if (value
< -255 || value
> 255)
11253 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11254 _("Illegal value for co-processor offset"));
11257 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
11258 newval
|= value
| (sign
? INDEX_UP
: 0);
11259 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11262 case BFD_RELOC_ARM_THUMB_OFFSET
:
11263 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11264 /* Exactly what ranges, and where the offset is inserted depends
11265 on the type of instruction, we can establish this from the
11267 switch (newval
>> 12)
11269 case 4: /* PC load. */
11270 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
11271 forced to zero for these loads, so we will need to round
11272 up the offset if the instruction address is not word
11273 aligned (since the final address produced must be, and
11274 we can only describe word-aligned immediate offsets). */
11276 if ((fixP
->fx_frag
->fr_address
+ fixP
->fx_where
+ value
) & 3)
11277 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11278 _("invalid offset, target not word aligned (0x%08X)"),
11279 (unsigned int) (fixP
->fx_frag
->fr_address
11280 + fixP
->fx_where
+ value
));
11282 if ((value
+ 2) & ~0x3fe)
11283 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11284 _("invalid offset, value too big (0x%08lX)"),
11287 /* Round up, since pc will be rounded down. */
11288 newval
|= (value
+ 2) >> 2;
11291 case 9: /* SP load/store. */
11292 if (value
& ~0x3fc)
11293 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11294 _("invalid offset, value too big (0x%08lX)"),
11296 newval
|= value
>> 2;
11299 case 6: /* Word load/store. */
11301 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11302 _("invalid offset, value too big (0x%08lX)"),
11304 newval
|= value
<< 4; /* 6 - 2. */
11307 case 7: /* Byte load/store. */
11309 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11310 _("invalid offset, value too big (0x%08lX)"),
11312 newval
|= value
<< 6;
11315 case 8: /* Halfword load/store. */
11317 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11318 _("invalid offset, value too big (0x%08lX)"),
11320 newval
|= value
<< 5; /* 6 - 1. */
11324 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11325 "Unable to process relocation for thumb opcode: %lx",
11326 (unsigned long) newval
);
11329 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11332 case BFD_RELOC_ARM_THUMB_ADD
:
11333 /* This is a complicated relocation, since we use it for all of
11334 the following immediate relocations:
11338 9bit ADD/SUB SP word-aligned
11339 10bit ADD PC/SP word-aligned
11341 The type of instruction being processed is encoded in the
11348 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11350 int rd
= (newval
>> 4) & 0xf;
11351 int rs
= newval
& 0xf;
11352 int subtract
= newval
& 0x8000;
11356 if (value
& ~0x1fc)
11357 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11358 _("invalid immediate for stack address calculation"));
11359 newval
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
11360 newval
|= value
>> 2;
11362 else if (rs
== REG_PC
|| rs
== REG_SP
)
11366 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11367 _("invalid immediate for address calculation (value = 0x%08lX)"),
11368 (unsigned long) value
);
11369 newval
= (rs
== REG_PC
? T_OPCODE_ADD_PC
: T_OPCODE_ADD_SP
);
11371 newval
|= value
>> 2;
11376 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11377 _("invalid 8bit immediate"));
11378 newval
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
11379 newval
|= (rd
<< 8) | value
;
11384 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11385 _("invalid 3bit immediate"));
11386 newval
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
11387 newval
|= rd
| (rs
<< 3) | (value
<< 6);
11390 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11393 case BFD_RELOC_ARM_THUMB_IMM
:
11394 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11395 switch (newval
>> 11)
11397 case 0x04: /* 8bit immediate MOV. */
11398 case 0x05: /* 8bit immediate CMP. */
11399 if (value
< 0 || value
> 255)
11400 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11401 _("invalid immediate: %ld is too large"),
11409 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11412 case BFD_RELOC_ARM_THUMB_SHIFT
:
11413 /* 5bit shift value (0..31). */
11414 if (value
< 0 || value
> 31)
11415 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11416 _("illegal Thumb shift value: %ld"), (long) value
);
11417 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xf03f;
11418 newval
|= value
<< 6;
11419 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11422 case BFD_RELOC_VTABLE_INHERIT
:
11423 case BFD_RELOC_VTABLE_ENTRY
:
11427 case BFD_RELOC_NONE
:
11429 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11430 _("bad relocation fixup type (%d)"), fixP
->fx_r_type
);
11434 /* Translate internal representation of relocation info to BFD target
11438 tc_gen_reloc (section
, fixp
)
11439 asection
* section ATTRIBUTE_UNUSED
;
11443 bfd_reloc_code_real_type code
;
11445 reloc
= (arelent
*) xmalloc (sizeof (arelent
));
11447 reloc
->sym_ptr_ptr
= (asymbol
**) xmalloc (sizeof (asymbol
*));
11448 *reloc
->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
11449 reloc
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
11451 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
11453 if (fixp
->fx_pcrel
== 0)
11454 reloc
->addend
= fixp
->fx_offset
;
11456 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
11457 #else /* OBJ_ELF */
11458 reloc
->addend
= fixp
->fx_offset
;
11461 switch (fixp
->fx_r_type
)
11464 if (fixp
->fx_pcrel
)
11466 code
= BFD_RELOC_8_PCREL
;
11471 if (fixp
->fx_pcrel
)
11473 code
= BFD_RELOC_16_PCREL
;
11478 if (fixp
->fx_pcrel
)
11480 code
= BFD_RELOC_32_PCREL
;
11484 case BFD_RELOC_ARM_PCREL_BRANCH
:
11485 case BFD_RELOC_ARM_PCREL_BLX
:
11486 case BFD_RELOC_RVA
:
11487 case BFD_RELOC_THUMB_PCREL_BRANCH9
:
11488 case BFD_RELOC_THUMB_PCREL_BRANCH12
:
11489 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
11490 case BFD_RELOC_THUMB_PCREL_BLX
:
11491 case BFD_RELOC_VTABLE_ENTRY
:
11492 case BFD_RELOC_VTABLE_INHERIT
:
11493 code
= fixp
->fx_r_type
;
11496 case BFD_RELOC_ARM_LITERAL
:
11497 case BFD_RELOC_ARM_HWLITERAL
:
11498 /* If this is called then the a literal has
11499 been referenced across a section boundary. */
11500 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
11501 _("literal referenced across section boundary"));
11505 case BFD_RELOC_ARM_GOT32
:
11506 case BFD_RELOC_ARM_GOTOFF
:
11507 case BFD_RELOC_ARM_PLT32
:
11508 code
= fixp
->fx_r_type
;
11512 case BFD_RELOC_ARM_IMMEDIATE
:
11513 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
11514 _("internal relocation (type: IMMEDIATE) not fixed up"));
11517 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
11518 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
11519 _("ADRL used for a symbol not defined in the same file"));
11522 case BFD_RELOC_ARM_OFFSET_IMM
:
11523 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
11524 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
11531 switch (fixp
->fx_r_type
)
11533 case BFD_RELOC_ARM_OFFSET_IMM8
: type
= "OFFSET_IMM8"; break;
11534 case BFD_RELOC_ARM_SHIFT_IMM
: type
= "SHIFT_IMM"; break;
11535 case BFD_RELOC_ARM_SWI
: type
= "SWI"; break;
11536 case BFD_RELOC_ARM_MULTI
: type
= "MULTI"; break;
11537 case BFD_RELOC_ARM_CP_OFF_IMM
: type
= "CP_OFF_IMM"; break;
11538 case BFD_RELOC_ARM_THUMB_ADD
: type
= "THUMB_ADD"; break;
11539 case BFD_RELOC_ARM_THUMB_SHIFT
: type
= "THUMB_SHIFT"; break;
11540 case BFD_RELOC_ARM_THUMB_IMM
: type
= "THUMB_IMM"; break;
11541 case BFD_RELOC_ARM_THUMB_OFFSET
: type
= "THUMB_OFFSET"; break;
11542 default: type
= _("<unknown>"); break;
11544 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
11545 _("cannot represent %s relocation in this object file format"),
11552 if ((code
== BFD_RELOC_32_PCREL
|| code
== BFD_RELOC_32
)
11554 && fixp
->fx_addsy
== GOT_symbol
)
11556 code
= BFD_RELOC_ARM_GOTPC
;
11557 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
11561 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, code
);
11563 if (reloc
->howto
== NULL
)
11565 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
11566 _("cannot represent %s relocation in this object file format"),
11567 bfd_get_reloc_code_name (code
));
11571 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
11572 vtable entry to be used in the relocation's section offset. */
11573 if (fixp
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
11574 reloc
->address
= fixp
->fx_offset
;
11580 md_estimate_size_before_relax (fragP
, segtype
)
11581 fragS
* fragP ATTRIBUTE_UNUSED
;
11582 segT segtype ATTRIBUTE_UNUSED
;
11584 as_fatal (_("md_estimate_size_before_relax\n"));
11596 as_bad ("%s -- `%s'", inst
.error
, str
);
11600 to
= frag_more (inst
.size
);
11602 if (thumb_mode
&& (inst
.size
> THUMB_SIZE
))
11604 assert (inst
.size
== (2 * THUMB_SIZE
));
11605 md_number_to_chars (to
, inst
.instruction
>> 16, THUMB_SIZE
);
11606 md_number_to_chars (to
+ THUMB_SIZE
, inst
.instruction
, THUMB_SIZE
);
11608 else if (inst
.size
> INSN_SIZE
)
11610 assert (inst
.size
== (2 * INSN_SIZE
));
11611 md_number_to_chars (to
, inst
.instruction
, INSN_SIZE
);
11612 md_number_to_chars (to
+ INSN_SIZE
, inst
.instruction
, INSN_SIZE
);
11615 md_number_to_chars (to
, inst
.instruction
, inst
.size
);
11617 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
11618 fix_new_arm (frag_now
, to
- frag_now
->fr_literal
,
11619 inst
.size
, & inst
.reloc
.exp
, inst
.reloc
.pc_rel
,
11623 dwarf2_emit_insn (inst
.size
);
11635 /* Align the instruction.
11636 This may not be the right thing to do but ... */
11641 /* Align the previous label if needed. */
11642 if (last_label_seen
!= NULL
)
11644 symbol_set_frag (last_label_seen
, frag_now
);
11645 S_SET_VALUE (last_label_seen
, (valueT
) frag_now_fix ());
11646 S_SET_SEGMENT (last_label_seen
, now_seg
);
11649 memset (&inst
, '\0', sizeof (inst
));
11650 inst
.reloc
.type
= BFD_RELOC_NONE
;
11652 skip_whitespace (str
);
11654 /* Scan up to the end of the op-code, which must end in white space or
11656 for (start
= p
= str
; *p
!= '\0'; p
++)
11662 as_bad (_("no operator -- statement `%s'\n"), str
);
11668 const struct thumb_opcode
* opcode
;
11672 opcode
= (const struct thumb_opcode
*) hash_find (arm_tops_hsh
, str
);
11677 /* Check that this instruction is supported for this CPU. */
11678 if (thumb_mode
== 1 && (opcode
->variant
& cpu_variant
) == 0)
11680 as_bad (_("selected processor does not support `%s'"), str
);
11684 inst
.instruction
= opcode
->value
;
11685 inst
.size
= opcode
->size
;
11686 (*opcode
->parms
) (p
);
11693 const struct asm_opcode
* opcode
;
11697 opcode
= (const struct asm_opcode
*) hash_find (arm_ops_hsh
, str
);
11702 /* Check that this instruction is supported for this CPU. */
11703 if ((opcode
->variant
& cpu_variant
) == 0)
11705 as_bad (_("selected processor does not support `%s'"), str
);
11709 inst
.instruction
= opcode
->value
;
11710 inst
.size
= INSN_SIZE
;
11711 (*opcode
->parms
) (p
);
11717 /* It wasn't an instruction, but it might be a register alias of the form
11719 if (create_register_alias (str
, p
))
11722 as_bad (_("bad instruction `%s'"), start
);
11726 Invocation line includes a switch not recognized by the base assembler.
11727 See if it's a processor-specific option.
11729 This routine is somewhat complicated by the need for backwards
11730 compatibility (since older releases of gcc can't be changed).
11731 The new options try to make the interface as compatible as
11734 New options (supported) are:
11736 -mcpu=<cpu name> Assemble for selected processor
11737 -march=<architecture name> Assemble for selected architecture
11738 -mfpu=<fpu architecture> Assemble for selected FPU.
11739 -EB/-mbig-endian Big-endian
11740 -EL/-mlittle-endian Little-endian
11741 -k Generate PIC code
11742 -mthumb Start in Thumb mode
11743 -mthumb-interwork Code supports ARM/Thumb interworking
11745 For now we will also provide support for:
11747 -mapcs-32 32-bit Program counter
11748 -mapcs-26 26-bit Program counter
11749 -macps-float Floats passed in FP registers
11750 -mapcs-reentrant Reentrant code
11752 (sometime these will probably be replaced with -mapcs=<list of options>
11753 and -matpcs=<list of options>)
11755 The remaining options are only supported for back-wards compatibility.
11756 Cpu variants, the arm part is optional:
11757 -m[arm]1 Currently not supported.
11758 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
11759 -m[arm]3 Arm 3 processor
11760 -m[arm]6[xx], Arm 6 processors
11761 -m[arm]7[xx][t][[d]m] Arm 7 processors
11762 -m[arm]8[10] Arm 8 processors
11763 -m[arm]9[20][tdmi] Arm 9 processors
11764 -mstrongarm[110[0]] StrongARM processors
11765 -mxscale XScale processors
11766 -m[arm]v[2345[t[e]]] Arm architectures
11767 -mall All (except the ARM1)
11769 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
11770 -mfpe-old (No float load/store multiples)
11771 -mvfpxd VFP Single precision
11773 -mno-fpu Disable all floating point instructions
11775 The following CPU names are recognized:
11776 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
11777 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
11778 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
11779 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
11780 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
11781 arm10t arm10e, arm1020t, arm1020e, arm10200e,
11782 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
11786 const char * md_shortopts
= "m:k";
11788 #ifdef ARM_BI_ENDIAN
11789 #define OPTION_EB (OPTION_MD_BASE + 0)
11790 #define OPTION_EL (OPTION_MD_BASE + 1)
11792 #if TARGET_BYTES_BIG_ENDIAN
11793 #define OPTION_EB (OPTION_MD_BASE + 0)
11795 #define OPTION_EL (OPTION_MD_BASE + 1)
11799 struct option md_longopts
[] =
11802 {"EB", no_argument
, NULL
, OPTION_EB
},
11805 {"EL", no_argument
, NULL
, OPTION_EL
},
11807 {NULL
, no_argument
, NULL
, 0}
11810 size_t md_longopts_size
= sizeof (md_longopts
);
11812 struct arm_option_table
11814 char *option
; /* Option name to match. */
11815 char *help
; /* Help information. */
11816 int *var
; /* Variable to change. */
11817 int value
; /* What to change it to. */
11818 char *deprecated
; /* If non-null, print this message. */
11821 struct arm_option_table arm_opts
[] =
11823 {"k", N_("generate PIC code"), &pic_code
, 1, NULL
},
11824 {"mthumb", N_("assemble Thumb code"), &thumb_mode
, 1, NULL
},
11825 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
11826 &support_interwork
, 1, NULL
},
11827 {"moabi", N_("use old ABI (ELF only)"), &target_oabi
, 1, NULL
},
11828 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26
, 0, NULL
},
11829 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26
, 1, NULL
},
11830 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float
,
11832 {"mapcs-reentrant", N_("re-entrant code"), &pic_code
, 1, NULL
},
11833 {"matpcs", N_("code is ATPCS conformant"), &atpcs
, 1, NULL
},
11834 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian
, 1, NULL
},
11835 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian
, 1,
11838 /* These are recognized by the assembler, but have no affect on code. */
11839 {"mapcs-frame", N_("use frame pointer"), NULL
, 0, NULL
},
11840 {"mapcs-stack-check", N_("use stack size checking"), NULL
, 0, NULL
},
11842 /* DON'T add any new processors to this list -- we want the whole list
11843 to go away... Add them to the processors table instead. */
11844 {"marm1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
11845 {"m1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
11846 {"marm2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
11847 {"m2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
11848 {"marm250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
11849 {"m250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
11850 {"marm3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
11851 {"m3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
11852 {"marm6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
11853 {"m6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
11854 {"marm600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
11855 {"m600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
11856 {"marm610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
11857 {"m610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
11858 {"marm620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
11859 {"m620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
11860 {"marm7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
11861 {"m7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
11862 {"marm70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
11863 {"m70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
11864 {"marm700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
11865 {"m700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
11866 {"marm700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
11867 {"m700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
11868 {"marm710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
11869 {"m710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
11870 {"marm710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
11871 {"m710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
11872 {"marm720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
11873 {"m720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
11874 {"marm7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
11875 {"m7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
11876 {"marm7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
11877 {"m7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
11878 {"marm7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
11879 {"m7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
11880 {"marm7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
11881 {"m7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
11882 {"marm7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
11883 {"m7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
11884 {"marm7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
11885 {"m7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
11886 {"marm7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
11887 {"m7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
11888 {"marm7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
11889 {"m7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
11890 {"marm7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
11891 {"m7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
11892 {"marm7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
11893 {"m7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
11894 {"marm710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
11895 {"m710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
11896 {"marm720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
11897 {"m720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
11898 {"marm740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
11899 {"m740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
11900 {"marm8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
11901 {"m8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
11902 {"marm810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
11903 {"m810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
11904 {"marm9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
11905 {"m9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
11906 {"marm9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
11907 {"m9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
11908 {"marm920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
11909 {"m920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
11910 {"marm940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
11911 {"m940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
11912 {"mstrongarm", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=strongarm")},
11913 {"mstrongarm110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
11914 N_("use -mcpu=strongarm110")},
11915 {"mstrongarm1100", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
11916 N_("use -mcpu=strongarm1100")},
11917 {"mstrongarm1110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
11918 N_("use -mcpu=strongarm1110")},
11919 {"mxscale", NULL
, &legacy_cpu
, ARM_ARCH_XSCALE
, N_("use -mcpu=xscale")},
11920 {"miwmmxt", NULL
, &legacy_cpu
, ARM_ARCH_IWMMXT
, N_("use -mcpu=iwmmxt")},
11921 {"mall", NULL
, &legacy_cpu
, ARM_ANY
, N_("use -mcpu=all")},
11923 /* Architecture variants -- don't add any more to this list either. */
11924 {"mv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
11925 {"marmv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
11926 {"mv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
11927 {"marmv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
11928 {"mv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
11929 {"marmv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
11930 {"mv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
11931 {"marmv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
11932 {"mv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
11933 {"marmv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
11934 {"mv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
11935 {"marmv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
11936 {"mv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
11937 {"marmv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
11938 {"mv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
11939 {"marmv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
11940 {"mv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
11941 {"marmv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
11943 /* Floating point variants -- don't add any more to this list either. */
11944 {"mfpe-old", NULL
, &legacy_fpu
, FPU_ARCH_FPE
, N_("use -mfpu=fpe")},
11945 {"mfpa10", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa10")},
11946 {"mfpa11", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa11")},
11947 {"mno-fpu", NULL
, &legacy_fpu
, 0,
11948 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
11950 {NULL
, NULL
, NULL
, 0, NULL
}
11953 struct arm_cpu_option_table
11957 /* For some CPUs we assume an FPU unless the user explicitly sets
11962 /* This list should, at a minimum, contain all the cpu names
11963 recognized by GCC. */
11964 static struct arm_cpu_option_table arm_cpus
[] =
11966 {"all", ARM_ANY
, FPU_ARCH_FPA
},
11967 {"arm1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
11968 {"arm2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
11969 {"arm250", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
11970 {"arm3", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
11971 {"arm6", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11972 {"arm60", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11973 {"arm600", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11974 {"arm610", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11975 {"arm620", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11976 {"arm7", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11977 {"arm7m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
11978 {"arm7d", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11979 {"arm7dm", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
11980 {"arm7di", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11981 {"arm7dmi", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
11982 {"arm70", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11983 {"arm700", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11984 {"arm700i", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11985 {"arm710", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11986 {"arm710t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
11987 {"arm720", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11988 {"arm720t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
11989 {"arm740t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
11990 {"arm710c", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11991 {"arm7100", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11992 {"arm7500", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11993 {"arm7500fe", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11994 {"arm7t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
11995 {"arm7tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
11996 {"arm8", ARM_ARCH_V4
, FPU_ARCH_FPA
},
11997 {"arm810", ARM_ARCH_V4
, FPU_ARCH_FPA
},
11998 {"strongarm", ARM_ARCH_V4
, FPU_ARCH_FPA
},
11999 {"strongarm1", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12000 {"strongarm110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12001 {"strongarm1100", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12002 {"strongarm1110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12003 {"arm9", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12004 {"arm920", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12005 {"arm920t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12006 {"arm922t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12007 {"arm940t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12008 {"arm9tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12009 /* For V5 or later processors we default to using VFP; but the user
12010 should really set the FPU type explicitly. */
12011 {"arm9e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
12012 {"arm9e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12013 {"arm926ej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
12014 {"arm946e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
12015 {"arm946e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12016 {"arm966e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
12017 {"arm966e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12018 {"arm10t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
12019 {"arm10e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12020 {"arm1020", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12021 {"arm1020t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
12022 {"arm1020e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12023 /* ??? XSCALE is really an architecture. */
12024 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
12025 /* ??? iwmmxt is not a processor. */
12026 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP_V2
},
12027 {"i80200", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
12029 {"ep9312", ARM_ARCH_V4T
| ARM_CEXT_MAVERICK
, FPU_NONE
},
12033 struct arm_arch_option_table
12040 /* This list should, at a minimum, contain all the architecture names
12041 recognized by GCC. */
12042 static struct arm_arch_option_table arm_archs
[] =
12044 {"all", ARM_ANY
, FPU_ARCH_FPA
},
12045 {"armv1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
12046 {"armv2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
12047 {"armv2a", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
12048 {"armv2s", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
12049 {"armv3", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12050 {"armv3m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
12051 {"armv4", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12052 {"armv4xm", ARM_ARCH_V4xM
, FPU_ARCH_FPA
},
12053 {"armv4t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12054 {"armv4txm", ARM_ARCH_V4TxM
, FPU_ARCH_FPA
},
12055 {"armv5", ARM_ARCH_V5
, FPU_ARCH_VFP
},
12056 {"armv5t", ARM_ARCH_V5T
, FPU_ARCH_VFP
},
12057 {"armv5txm", ARM_ARCH_V5TxM
, FPU_ARCH_VFP
},
12058 {"armv5te", ARM_ARCH_V5TE
, FPU_ARCH_VFP
},
12059 {"armv5texp", ARM_ARCH_V5TExP
, FPU_ARCH_VFP
},
12060 {"armv5tej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP
},
12061 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP
},
12062 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP
},
12066 /* ISA extensions in the co-processor space. */
12067 struct arm_arch_extension_table
12073 static struct arm_arch_extension_table arm_extensions
[] =
12075 {"maverick", ARM_CEXT_MAVERICK
},
12076 {"xscale", ARM_CEXT_XSCALE
},
12077 {"iwmmxt", ARM_CEXT_IWMMXT
},
12081 struct arm_fpu_option_table
12087 /* This list should, at a minimum, contain all the fpu names
12088 recognized by GCC. */
12089 static struct arm_fpu_option_table arm_fpus
[] =
12091 {"softfpa", FPU_NONE
},
12092 {"fpe", FPU_ARCH_FPE
},
12093 {"fpe2", FPU_ARCH_FPE
},
12094 {"fpe3", FPU_ARCH_FPA
}, /* Third release supports LFM/SFM. */
12095 {"fpa", FPU_ARCH_FPA
},
12096 {"fpa10", FPU_ARCH_FPA
},
12097 {"fpa11", FPU_ARCH_FPA
},
12098 {"arm7500fe", FPU_ARCH_FPA
},
12099 {"softvfp", FPU_ARCH_VFP
},
12100 {"softvfp+vfp", FPU_ARCH_VFP_V2
},
12101 {"vfp", FPU_ARCH_VFP_V2
},
12102 {"vfp9", FPU_ARCH_VFP_V2
},
12103 {"vfp10", FPU_ARCH_VFP_V2
},
12104 {"vfp10-r0", FPU_ARCH_VFP_V1
},
12105 {"vfpxd", FPU_ARCH_VFP_V1xD
},
12106 {"arm1020t", FPU_ARCH_VFP_V1
},
12107 {"arm1020e", FPU_ARCH_VFP_V2
},
12111 struct arm_long_option_table
12113 char *option
; /* Substring to match. */
12114 char *help
; /* Help information. */
12115 int (*func
) PARAMS ((char *subopt
)); /* Function to decode sub-option. */
12116 char *deprecated
; /* If non-null, print this message. */
12120 arm_parse_extension (str
, opt_p
)
12124 while (str
!= NULL
&& *str
!= 0)
12126 struct arm_arch_extension_table
*opt
;
12132 as_bad (_("invalid architectural extension"));
12137 ext
= strchr (str
, '+');
12140 optlen
= ext
- str
;
12142 optlen
= strlen (str
);
12146 as_bad (_("missing architectural extension"));
12150 for (opt
= arm_extensions
; opt
->name
!= NULL
; opt
++)
12151 if (strncmp (opt
->name
, str
, optlen
) == 0)
12153 *opt_p
|= opt
->value
;
12157 if (opt
->name
== NULL
)
12159 as_bad (_("unknown architectural extnsion `%s'"), str
);
12170 arm_parse_cpu (str
)
12173 struct arm_cpu_option_table
*opt
;
12174 char *ext
= strchr (str
, '+');
12178 optlen
= ext
- str
;
12180 optlen
= strlen (str
);
12184 as_bad (_("missing cpu name `%s'"), str
);
12188 for (opt
= arm_cpus
; opt
->name
!= NULL
; opt
++)
12189 if (strncmp (opt
->name
, str
, optlen
) == 0)
12191 mcpu_cpu_opt
= opt
->value
;
12192 mcpu_fpu_opt
= opt
->default_fpu
;
12195 return arm_parse_extension (ext
, &mcpu_cpu_opt
);
12200 as_bad (_("unknown cpu `%s'"), str
);
12205 arm_parse_arch (str
)
12208 struct arm_arch_option_table
*opt
;
12209 char *ext
= strchr (str
, '+');
12213 optlen
= ext
- str
;
12215 optlen
= strlen (str
);
12219 as_bad (_("missing architecture name `%s'"), str
);
12224 for (opt
= arm_archs
; opt
->name
!= NULL
; opt
++)
12225 if (strcmp (opt
->name
, str
) == 0)
12227 march_cpu_opt
= opt
->value
;
12228 march_fpu_opt
= opt
->default_fpu
;
12231 return arm_parse_extension (ext
, &march_cpu_opt
);
12236 as_bad (_("unknown architecture `%s'\n"), str
);
12241 arm_parse_fpu (str
)
12244 struct arm_fpu_option_table
*opt
;
12246 for (opt
= arm_fpus
; opt
->name
!= NULL
; opt
++)
12247 if (strcmp (opt
->name
, str
) == 0)
12249 mfpu_opt
= opt
->value
;
12253 as_bad (_("unknown floating point format `%s'\n"), str
);
12257 struct arm_long_option_table arm_long_opts
[] =
12259 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
12260 arm_parse_cpu
, NULL
},
12261 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
12262 arm_parse_arch
, NULL
},
12263 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
12264 arm_parse_fpu
, NULL
},
12265 {NULL
, NULL
, 0, NULL
}
12269 md_parse_option (c
, arg
)
12273 struct arm_option_table
*opt
;
12274 struct arm_long_option_table
*lopt
;
12280 target_big_endian
= 1;
12286 target_big_endian
= 0;
12291 /* Listing option. Just ignore these, we don't support additional
12296 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
12298 if (c
== opt
->option
[0]
12299 && ((arg
== NULL
&& opt
->option
[1] == 0)
12300 || strcmp (arg
, opt
->option
+ 1) == 0))
12302 #if WARN_DEPRECATED
12303 /* If the option is deprecated, tell the user. */
12304 if (opt
->deprecated
!= NULL
)
12305 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
,
12306 arg
? arg
: "", _(opt
->deprecated
));
12309 if (opt
->var
!= NULL
)
12310 *opt
->var
= opt
->value
;
12316 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
12318 /* These options are expected to have an argument. */
12319 if (c
== lopt
->option
[0]
12321 && strncmp (arg
, lopt
->option
+ 1,
12322 strlen (lopt
->option
+ 1)) == 0)
12324 #if WARN_DEPRECATED
12325 /* If the option is deprecated, tell the user. */
12326 if (lopt
->deprecated
!= NULL
)
12327 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
, arg
,
12328 _(lopt
->deprecated
));
12331 /* Call the sup-option parser. */
12332 return (*lopt
->func
)(arg
+ strlen (lopt
->option
) - 1);
12336 as_bad (_("unrecognized option `-%c%s'"), c
, arg
? arg
: "");
12347 struct arm_option_table
*opt
;
12348 struct arm_long_option_table
*lopt
;
12350 fprintf (fp
, _(" ARM-specific assembler options:\n"));
12352 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
12353 if (opt
->help
!= NULL
)
12354 fprintf (fp
, " -%-23s%s\n", opt
->option
, _(opt
->help
));
12356 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
12357 if (lopt
->help
!= NULL
)
12358 fprintf (fp
, " -%s%s\n", lopt
->option
, _(lopt
->help
));
12362 -EB assemble code for a big-endian cpu\n"));
12367 -EL assemble code for a little-endian cpu\n"));
12371 /* We need to be able to fix up arbitrary expressions in some statements.
12372 This is so that we can handle symbols that are an arbitrary distance from
12373 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
12374 which returns part of an address in a form which will be valid for
12375 a data instruction. We do this by pushing the expression into a symbol
12376 in the expr_section, and creating a fix for that. */
12379 fix_new_arm (frag
, where
, size
, exp
, pc_rel
, reloc
)
12388 arm_fix_data
* arm_data
;
12396 new_fix
= fix_new_exp (frag
, where
, size
, exp
, pc_rel
, reloc
);
12400 new_fix
= fix_new (frag
, where
, size
, make_expr_symbol (exp
), 0,
12405 /* Mark whether the fix is to a THUMB instruction, or an ARM
12407 arm_data
= (arm_fix_data
*) obstack_alloc (& notes
, sizeof (arm_fix_data
));
12408 new_fix
->tc_fix_data
= (PTR
) arm_data
;
12409 arm_data
->thumb_mode
= thumb_mode
;
12414 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
12417 cons_fix_new_arm (frag
, where
, size
, exp
)
12423 bfd_reloc_code_real_type type
;
12427 FIXME: @@ Should look at CPU word size. */
12431 type
= BFD_RELOC_8
;
12434 type
= BFD_RELOC_16
;
12438 type
= BFD_RELOC_32
;
12441 type
= BFD_RELOC_64
;
12445 fix_new_exp (frag
, where
, (int) size
, exp
, pcrel
, type
);
12448 /* A good place to do this, although this was probably not intended
12449 for this kind of use. We need to dump the literal pool before
12450 references are made to a null symbol pointer. */
12455 literal_pool
* pool
;
12457 for (pool
= list_of_pools
; pool
; pool
= pool
->next
)
12459 /* Put it at the end of the relevent section. */
12460 subseg_set (pool
->section
, pool
->sub_section
);
12466 arm_start_line_hook ()
12468 last_label_seen
= NULL
;
12472 arm_frob_label (sym
)
12475 last_label_seen
= sym
;
12477 ARM_SET_THUMB (sym
, thumb_mode
);
12479 #if defined OBJ_COFF || defined OBJ_ELF
12480 ARM_SET_INTERWORK (sym
, support_interwork
);
12483 /* Note - do not allow local symbols (.Lxxx) to be labeled
12484 as Thumb functions. This is because these labels, whilst
12485 they exist inside Thumb code, are not the entry points for
12486 possible ARM->Thumb calls. Also, these labels can be used
12487 as part of a computed goto or switch statement. eg gcc
12488 can generate code that looks like this:
12490 ldr r2, [pc, .Laaa]
12500 The first instruction loads the address of the jump table.
12501 The second instruction converts a table index into a byte offset.
12502 The third instruction gets the jump address out of the table.
12503 The fourth instruction performs the jump.
12505 If the address stored at .Laaa is that of a symbol which has the
12506 Thumb_Func bit set, then the linker will arrange for this address
12507 to have the bottom bit set, which in turn would mean that the
12508 address computation performed by the third instruction would end
12509 up with the bottom bit set. Since the ARM is capable of unaligned
12510 word loads, the instruction would then load the incorrect address
12511 out of the jump table, and chaos would ensue. */
12512 if (label_is_thumb_function_name
12513 && (S_GET_NAME (sym
)[0] != '.' || S_GET_NAME (sym
)[1] != 'L')
12514 && (bfd_get_section_flags (stdoutput
, now_seg
) & SEC_CODE
) != 0)
12516 /* When the address of a Thumb function is taken the bottom
12517 bit of that address should be set. This will allow
12518 interworking between Arm and Thumb functions to work
12521 THUMB_SET_FUNC (sym
, 1);
12523 label_is_thumb_function_name
= FALSE
;
12527 /* Adjust the symbol table. This marks Thumb symbols as distinct from
12531 arm_adjust_symtab ()
12536 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
12538 if (ARM_IS_THUMB (sym
))
12540 if (THUMB_IS_FUNC (sym
))
12542 /* Mark the symbol as a Thumb function. */
12543 if ( S_GET_STORAGE_CLASS (sym
) == C_STAT
12544 || S_GET_STORAGE_CLASS (sym
) == C_LABEL
) /* This can happen! */
12545 S_SET_STORAGE_CLASS (sym
, C_THUMBSTATFUNC
);
12547 else if (S_GET_STORAGE_CLASS (sym
) == C_EXT
)
12548 S_SET_STORAGE_CLASS (sym
, C_THUMBEXTFUNC
);
12550 as_bad (_("%s: unexpected function type: %d"),
12551 S_GET_NAME (sym
), S_GET_STORAGE_CLASS (sym
));
12553 else switch (S_GET_STORAGE_CLASS (sym
))
12556 S_SET_STORAGE_CLASS (sym
, C_THUMBEXT
);
12559 S_SET_STORAGE_CLASS (sym
, C_THUMBSTAT
);
12562 S_SET_STORAGE_CLASS (sym
, C_THUMBLABEL
);
12570 if (ARM_IS_INTERWORK (sym
))
12571 coffsymbol (symbol_get_bfdsym (sym
))->native
->u
.syment
.n_flags
= 0xFF;
12578 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
12580 if (ARM_IS_THUMB (sym
))
12582 elf_symbol_type
* elf_sym
;
12584 elf_sym
= elf_symbol (symbol_get_bfdsym (sym
));
12585 bind
= ELF_ST_BIND (elf_sym
);
12587 /* If it's a .thumb_func, declare it as so,
12588 otherwise tag label as .code 16. */
12589 if (THUMB_IS_FUNC (sym
))
12590 elf_sym
->internal_elf_sym
.st_info
=
12591 ELF_ST_INFO (bind
, STT_ARM_TFUNC
);
12593 elf_sym
->internal_elf_sym
.st_info
=
12594 ELF_ST_INFO (bind
, STT_ARM_16BIT
);
12601 arm_data_in_code ()
12603 if (thumb_mode
&& ! strncmp (input_line_pointer
+ 1, "data:", 5))
12605 *input_line_pointer
= '/';
12606 input_line_pointer
+= 5;
12607 *input_line_pointer
= 0;
12615 arm_canonicalize_symbol_name (name
)
12620 if (thumb_mode
&& (len
= strlen (name
)) > 5
12621 && streq (name
+ len
- 5, "/data"))
12622 *(name
+ len
- 5) = 0;
12627 #if defined OBJ_COFF || defined OBJ_ELF
12629 arm_validate_fix (fixP
)
12632 /* If the destination of the branch is a defined symbol which does not have
12633 the THUMB_FUNC attribute, then we must be calling a function which has
12634 the (interfacearm) attribute. We look for the Thumb entry point to that
12635 function and change the branch to refer to that function instead. */
12636 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
12637 && fixP
->fx_addsy
!= NULL
12638 && S_IS_DEFINED (fixP
->fx_addsy
)
12639 && ! THUMB_IS_FUNC (fixP
->fx_addsy
))
12641 fixP
->fx_addsy
= find_real_start (fixP
->fx_addsy
);
12647 arm_force_relocation (fixp
)
12650 #if defined (OBJ_COFF) && defined (TE_PE)
12651 if (fixp
->fx_r_type
== BFD_RELOC_RVA
)
12655 if (fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
12656 || fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
12657 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
12658 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
)
12662 /* Resolve these relocations even if the symbol is extern or weak. */
12663 if (fixp
->fx_r_type
== BFD_RELOC_ARM_IMMEDIATE
12664 || fixp
->fx_r_type
== BFD_RELOC_ARM_OFFSET_IMM
12665 || fixp
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
12668 return generic_force_reloc (fixp
);
12672 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
12673 local labels from being added to the output symbol table when they
12674 are used with the ADRL pseudo op. The ADRL relocation should always
12675 be resolved before the binbary is emitted, so it is safe to say that
12676 it is adjustable. */
12679 arm_fix_adjustable (fixP
)
12682 if (fixP
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
12689 /* Relocations against Thumb function names must be left unadjusted,
12690 so that the linker can use this information to correctly set the
12691 bottom bit of their addresses. The MIPS version of this function
12692 also prevents relocations that are mips-16 specific, but I do not
12693 know why it does this.
12696 There is one other problem that ought to be addressed here, but
12697 which currently is not: Taking the address of a label (rather
12698 than a function) and then later jumping to that address. Such
12699 addresses also ought to have their bottom bit set (assuming that
12700 they reside in Thumb code), but at the moment they will not. */
12703 arm_fix_adjustable (fixP
)
12706 if (fixP
->fx_addsy
== NULL
)
12709 if (THUMB_IS_FUNC (fixP
->fx_addsy
)
12710 && fixP
->fx_subsy
== NULL
)
12713 /* We need the symbol name for the VTABLE entries. */
12714 if ( fixP
->fx_r_type
== BFD_RELOC_VTABLE_INHERIT
12715 || fixP
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
12718 /* Don't allow symbols to be discarded on GOT related relocs. */
12719 if (fixP
->fx_r_type
== BFD_RELOC_ARM_PLT32
12720 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOT32
12721 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOTOFF
)
12728 elf32_arm_target_format ()
12730 if (target_big_endian
)
12733 return "elf32-bigarm-oabi";
12735 return "elf32-bigarm";
12740 return "elf32-littlearm-oabi";
12742 return "elf32-littlearm";
12747 armelf_frob_symbol (symp
, puntp
)
12751 elf_frob_symbol (symp
, puntp
);
12754 static bfd_reloc_code_real_type
12764 bfd_reloc_code_real_type reloc
;
12768 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
12769 MAP ("(got)", BFD_RELOC_ARM_GOT32
),
12770 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF
),
12771 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
12772 branch instructions generated by GCC for PLT relocs. */
12773 MAP ("(plt)", BFD_RELOC_ARM_PLT32
),
12774 { NULL
, 0, BFD_RELOC_UNUSED
}
12778 for (i
= 0, ip
= input_line_pointer
;
12779 i
< sizeof (id
) && (ISALNUM (*ip
) || ISPUNCT (*ip
));
12781 id
[i
] = TOLOWER (*ip
);
12783 for (i
= 0; reloc_map
[i
].str
; i
++)
12784 if (strncmp (id
, reloc_map
[i
].str
, reloc_map
[i
].len
) == 0)
12787 input_line_pointer
+= reloc_map
[i
].len
;
12789 return reloc_map
[i
].reloc
;
12793 s_arm_elf_cons (nbytes
)
12798 #ifdef md_flush_pending_output
12799 md_flush_pending_output ();
12802 if (is_it_end_of_statement ())
12804 demand_empty_rest_of_line ();
12808 #ifdef md_cons_align
12809 md_cons_align (nbytes
);
12814 bfd_reloc_code_real_type reloc
;
12816 expression (& exp
);
12818 if (exp
.X_op
== O_symbol
12819 && * input_line_pointer
== '('
12820 && (reloc
= arm_parse_reloc ()) != BFD_RELOC_UNUSED
)
12822 reloc_howto_type
*howto
= bfd_reloc_type_lookup (stdoutput
, reloc
);
12823 int size
= bfd_get_reloc_size (howto
);
12826 as_bad ("%s relocations do not fit in %d bytes",
12827 howto
->name
, nbytes
);
12830 register char *p
= frag_more ((int) nbytes
);
12831 int offset
= nbytes
- size
;
12833 fix_new_exp (frag_now
, p
- frag_now
->fr_literal
+ offset
, size
,
12838 emit_expr (&exp
, (unsigned int) nbytes
);
12840 while (*input_line_pointer
++ == ',');
12842 /* Put terminator back into stream. */
12843 input_line_pointer
--;
12844 demand_empty_rest_of_line ();
12847 #endif /* OBJ_ELF */
12849 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
12850 of an rs_align_code fragment. */
12853 arm_handle_align (fragP
)
12856 static char const arm_noop
[4] = { 0x00, 0x00, 0xa0, 0xe1 };
12857 static char const thumb_noop
[2] = { 0xc0, 0x46 };
12858 static char const arm_bigend_noop
[4] = { 0xe1, 0xa0, 0x00, 0x00 };
12859 static char const thumb_bigend_noop
[2] = { 0x46, 0xc0 };
12861 int bytes
, fix
, noop_size
;
12865 if (fragP
->fr_type
!= rs_align_code
)
12868 bytes
= fragP
->fr_next
->fr_address
- fragP
->fr_address
- fragP
->fr_fix
;
12869 p
= fragP
->fr_literal
+ fragP
->fr_fix
;
12872 if (bytes
> MAX_MEM_FOR_RS_ALIGN_CODE
)
12873 bytes
&= MAX_MEM_FOR_RS_ALIGN_CODE
;
12875 if (fragP
->tc_frag_data
)
12877 if (target_big_endian
)
12878 noop
= thumb_bigend_noop
;
12881 noop_size
= sizeof (thumb_noop
);
12885 if (target_big_endian
)
12886 noop
= arm_bigend_noop
;
12889 noop_size
= sizeof (arm_noop
);
12892 if (bytes
& (noop_size
- 1))
12894 fix
= bytes
& (noop_size
- 1);
12895 memset (p
, 0, fix
);
12900 while (bytes
>= noop_size
)
12902 memcpy (p
, noop
, noop_size
);
12904 bytes
-= noop_size
;
12908 fragP
->fr_fix
+= fix
;
12909 fragP
->fr_var
= noop_size
;
12912 /* Called from md_do_align. Used to create an alignment
12913 frag in a code section. */
12916 arm_frag_align_code (n
, max
)
12922 /* We assume that there will never be a requirment
12923 to support alignments greater than 32 bytes. */
12924 if (max
> MAX_MEM_FOR_RS_ALIGN_CODE
)
12925 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
12927 p
= frag_var (rs_align_code
,
12928 MAX_MEM_FOR_RS_ALIGN_CODE
,
12930 (relax_substateT
) max
,
12938 /* Perform target specific initialisation of a frag. */
12941 arm_init_frag (fragP
)
12944 /* Record whether this frag is in an ARM or a THUMB area. */
12945 fragP
->tc_frag_data
= thumb_mode
;