1 /* tc-arm.c -- Assemble for the ARM
2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
3 Free Software Foundation, Inc.
4 Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
5 Modified by David Taylor (dtaylor@armltd.co.uk)
6 Cirrus coprocessor mods by Aldy Hernandez (aldyh@redhat.com)
8 This file is part of GAS, the GNU Assembler.
10 GAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
15 GAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with GAS; see the file COPYING. If not, write to the Free
22 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
28 #include "safe-ctype.h"
30 /* Need TARGET_CPU. */
39 #include "dwarf2dbg.h"
42 /* XXX Set this to 1 after the next binutils release */
43 #define WARN_DEPRECATED 0
45 /* The following bitmasks control CPU extensions: */
46 #define ARM_EXT_V1 0x00000001 /* All processors (core set). */
47 #define ARM_EXT_V2 0x00000002 /* Multiply instructions. */
48 #define ARM_EXT_V2S 0x00000004 /* SWP instructions. */
49 #define ARM_EXT_V3 0x00000008 /* MSR MRS. */
50 #define ARM_EXT_V3M 0x00000010 /* Allow long multiplies. */
51 #define ARM_EXT_V4 0x00000020 /* Allow half word loads. */
52 #define ARM_EXT_V4T 0x00000040 /* Thumb v1. */
53 #define ARM_EXT_V5 0x00000080 /* Allow CLZ, etc. */
54 #define ARM_EXT_V5T 0x00000100 /* Thumb v2. */
55 #define ARM_EXT_V5ExP 0x00000200 /* DSP core set. */
56 #define ARM_EXT_V5E 0x00000400 /* DSP Double transfers. */
57 #define ARM_EXT_V5J 0x00000800 /* Jazelle extension. */
59 /* Co-processor space extensions. */
60 #define ARM_CEXT_XSCALE 0x00800000 /* Allow MIA etc. */
61 #define ARM_CEXT_MAVERICK 0x00400000 /* Use Cirrus/DSP coprocessor. */
62 #define ARM_CEXT_IWMMXT 0x00200000 /* Intel Wireless MMX technology coprocessor. */
64 /* Architectures are the sum of the base and extensions. The ARM ARM (rev E)
65 defines the following: ARMv3, ARMv3M, ARMv4xM, ARMv4, ARMv4TxM, ARMv4T,
66 ARMv5xM, ARMv5, ARMv5TxM, ARMv5T, ARMv5TExP, ARMv5TE. To these we add
67 three more to cover cores prior to ARM6. Finally, there are cores which
68 implement further extensions in the co-processor space. */
69 #define ARM_ARCH_V1 ARM_EXT_V1
70 #define ARM_ARCH_V2 (ARM_ARCH_V1 | ARM_EXT_V2)
71 #define ARM_ARCH_V2S (ARM_ARCH_V2 | ARM_EXT_V2S)
72 #define ARM_ARCH_V3 (ARM_ARCH_V2S | ARM_EXT_V3)
73 #define ARM_ARCH_V3M (ARM_ARCH_V3 | ARM_EXT_V3M)
74 #define ARM_ARCH_V4xM (ARM_ARCH_V3 | ARM_EXT_V4)
75 #define ARM_ARCH_V4 (ARM_ARCH_V3M | ARM_EXT_V4)
76 #define ARM_ARCH_V4TxM (ARM_ARCH_V4xM | ARM_EXT_V4T)
77 #define ARM_ARCH_V4T (ARM_ARCH_V4 | ARM_EXT_V4T)
78 #define ARM_ARCH_V5xM (ARM_ARCH_V4xM | ARM_EXT_V5)
79 #define ARM_ARCH_V5 (ARM_ARCH_V4 | ARM_EXT_V5)
80 #define ARM_ARCH_V5TxM (ARM_ARCH_V5xM | ARM_EXT_V4T | ARM_EXT_V5T)
81 #define ARM_ARCH_V5T (ARM_ARCH_V5 | ARM_EXT_V4T | ARM_EXT_V5T)
82 #define ARM_ARCH_V5TExP (ARM_ARCH_V5T | ARM_EXT_V5ExP)
83 #define ARM_ARCH_V5TE (ARM_ARCH_V5TExP | ARM_EXT_V5E)
84 #define ARM_ARCH_V5TEJ (ARM_ARCH_V5TE | ARM_EXT_V5J)
86 /* Processors with specific extensions in the co-processor space. */
87 #define ARM_ARCH_XSCALE (ARM_ARCH_V5TE | ARM_CEXT_XSCALE)
88 #define ARM_ARCH_IWMMXT (ARM_ARCH_XSCALE | ARM_CEXT_IWMMXT)
90 /* Some useful combinations: */
91 #define ARM_ANY 0x0000ffff /* Any basic core. */
92 #define ARM_ALL 0x00ffffff /* Any core + co-processor */
93 #define CPROC_ANY 0x00ff0000 /* Any co-processor */
94 #define FPU_ANY 0xff000000 /* Note this is ~ARM_ALL. */
97 #define FPU_FPA_EXT_V1 0x80000000 /* Base FPA instruction set. */
98 #define FPU_FPA_EXT_V2 0x40000000 /* LFM/SFM. */
99 #define FPU_VFP_EXT_NONE 0x20000000 /* Use VFP word-ordering. */
100 #define FPU_VFP_EXT_V1xD 0x10000000 /* Base VFP instruction set. */
101 #define FPU_VFP_EXT_V1 0x08000000 /* Double-precision insns. */
102 #define FPU_VFP_EXT_V2 0x04000000 /* ARM10E VFPr1. */
105 #define FPU_ARCH_FPE FPU_FPA_EXT_V1
106 #define FPU_ARCH_FPA (FPU_ARCH_FPE | FPU_FPA_EXT_V2)
108 #define FPU_ARCH_VFP FPU_VFP_EXT_NONE
109 #define FPU_ARCH_VFP_V1xD (FPU_VFP_EXT_V1xD | FPU_VFP_EXT_NONE)
110 #define FPU_ARCH_VFP_V1 (FPU_ARCH_VFP_V1xD | FPU_VFP_EXT_V1)
111 #define FPU_ARCH_VFP_V2 (FPU_ARCH_VFP_V1 | FPU_VFP_EXT_V2)
113 /* Types of processor to assemble for. */
114 #define ARM_1 ARM_ARCH_V1
115 #define ARM_2 ARM_ARCH_V2
116 #define ARM_3 ARM_ARCH_V2S
117 #define ARM_250 ARM_ARCH_V2S
118 #define ARM_6 ARM_ARCH_V3
119 #define ARM_7 ARM_ARCH_V3
120 #define ARM_8 ARM_ARCH_V4
121 #define ARM_9 ARM_ARCH_V4T
122 #define ARM_STRONG ARM_ARCH_V4
123 #define ARM_CPU_MASK 0x0000000f /* XXX? */
126 #if defined __XSCALE__
127 #define CPU_DEFAULT (ARM_ARCH_XSCALE)
129 #if defined __thumb__
130 #define CPU_DEFAULT (ARM_ARCH_V5T)
132 #define CPU_DEFAULT ARM_ANY
138 #define FPU_DEFAULT FPU_ARCH_FPA
143 #define FPU_DEFAULT FPU_ARCH_VFP /* Soft-float, but VFP order. */
145 /* Legacy a.out format. */
146 #define FPU_DEFAULT FPU_ARCH_FPA /* Soft-float, but FPA order. */
150 /* For backwards compatibility we default to the FPA. */
152 #define FPU_DEFAULT FPU_ARCH_FPA
155 #define streq(a, b) (strcmp (a, b) == 0)
156 #define skip_whitespace(str) while (*(str) == ' ') ++(str)
158 static unsigned long cpu_variant
;
159 static int target_oabi
= 0;
161 /* Flags stored in private area of BFD structure. */
162 static int uses_apcs_26
= FALSE
;
163 static int atpcs
= FALSE
;
164 static int support_interwork
= FALSE
;
165 static int uses_apcs_float
= FALSE
;
166 static int pic_code
= FALSE
;
168 /* Variables that we set while parsing command-line options. Once all
169 options have been read we re-process these values to set the real
171 static int legacy_cpu
= -1;
172 static int legacy_fpu
= -1;
174 static int mcpu_cpu_opt
= -1;
175 static int mcpu_fpu_opt
= -1;
176 static int march_cpu_opt
= -1;
177 static int march_fpu_opt
= -1;
178 static int mfpu_opt
= -1;
180 /* This array holds the chars that always start a comment. If the
181 pre-processor is disabled, these aren't very useful. */
182 const char comment_chars
[] = "@";
184 /* This array holds the chars that only start a comment at the beginning of
185 a line. If the line seems to have the form '# 123 filename'
186 .line and .file directives will appear in the pre-processed output. */
187 /* Note that input_file.c hand checks for '#' at the beginning of the
188 first line of the input file. This is because the compiler outputs
189 #NO_APP at the beginning of its output. */
190 /* Also note that comments like this one will always work. */
191 const char line_comment_chars
[] = "#";
193 const char line_separator_chars
[] = ";";
195 /* Chars that can be used to separate mant
196 from exp in floating point numbers. */
197 const char EXP_CHARS
[] = "eE";
199 /* Chars that mean this number is a floating point constant. */
203 const char FLT_CHARS
[] = "rRsSfFdDxXeEpP";
205 /* Prefix characters that indicate the start of an immediate
207 #define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
210 /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
211 symbolS
* GOT_symbol
;
214 /* Size of relocation record. */
215 const int md_reloc_size
= 8;
217 /* 0: assemble for ARM,
218 1: assemble for Thumb,
219 2: assemble for Thumb even though target CPU does not support thumb
221 static int thumb_mode
= 0;
223 typedef struct arm_fix
231 unsigned long instruction
;
235 bfd_reloc_code_real_type type
;
252 struct asm_shift_properties
254 enum asm_shift_index index
;
255 unsigned long bit_field
;
256 unsigned int allows_0
: 1;
257 unsigned int allows_32
: 1;
260 static const struct asm_shift_properties shift_properties
[] =
262 { SHIFT_LSL
, 0, 1, 0},
263 { SHIFT_LSR
, 0x20, 0, 1},
264 { SHIFT_ASR
, 0x40, 0, 1},
265 { SHIFT_ROR
, 0x60, 0, 0},
266 { SHIFT_RRX
, 0x60, 0, 0}
269 struct asm_shift_name
272 const struct asm_shift_properties
* properties
;
275 static const struct asm_shift_name shift_names
[] =
277 { "asl", shift_properties
+ SHIFT_LSL
},
278 { "lsl", shift_properties
+ SHIFT_LSL
},
279 { "lsr", shift_properties
+ SHIFT_LSR
},
280 { "asr", shift_properties
+ SHIFT_ASR
},
281 { "ror", shift_properties
+ SHIFT_ROR
},
282 { "rrx", shift_properties
+ SHIFT_RRX
},
283 { "ASL", shift_properties
+ SHIFT_LSL
},
284 { "LSL", shift_properties
+ SHIFT_LSL
},
285 { "LSR", shift_properties
+ SHIFT_LSR
},
286 { "ASR", shift_properties
+ SHIFT_ASR
},
287 { "ROR", shift_properties
+ SHIFT_ROR
},
288 { "RRX", shift_properties
+ SHIFT_RRX
}
291 #define NO_SHIFT_RESTRICT 1
292 #define SHIFT_RESTRICT 0
294 #define NUM_FLOAT_VALS 8
296 const char * fp_const
[] =
298 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
301 /* Number of littlenums required to hold an extended precision number. */
302 #define MAX_LITTLENUMS 6
304 LITTLENUM_TYPE fp_values
[NUM_FLOAT_VALS
][MAX_LITTLENUMS
];
309 /* Whether a Co-processor load/store operation accepts write-back forms. */
318 #define CP_T_X 0x00008000
319 #define CP_T_Y 0x00400000
320 #define CP_T_Pre 0x01000000
321 #define CP_T_UD 0x00800000
322 #define CP_T_WB 0x00200000
324 #define CONDS_BIT 0x00100000
325 #define LOAD_BIT 0x00100000
327 #define DOUBLE_LOAD_FLAG 0x00000001
331 const char * template;
335 #define COND_ALWAYS 0xe0000000
336 #define COND_MASK 0xf0000000
338 static const struct asm_cond conds
[] =
342 {"cs", 0x20000000}, {"hs", 0x20000000},
343 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
360 const char *template;
365 /* The bit that distnguishes CPSR and SPSR. */
366 #define SPSR_BIT (1 << 22)
368 /* How many bits to shift the PSR_xxx bits up by. */
371 #define PSR_c (1 << 0)
372 #define PSR_x (1 << 1)
373 #define PSR_s (1 << 2)
374 #define PSR_f (1 << 3)
376 static const struct asm_psr psrs
[] =
378 {"CPSR", TRUE
, PSR_c
| PSR_f
},
379 {"CPSR_all", TRUE
, PSR_c
| PSR_f
},
380 {"SPSR", FALSE
, PSR_c
| PSR_f
},
381 {"SPSR_all", FALSE
, PSR_c
| PSR_f
},
382 {"CPSR_flg", TRUE
, PSR_f
},
383 {"CPSR_f", TRUE
, PSR_f
},
384 {"SPSR_flg", FALSE
, PSR_f
},
385 {"SPSR_f", FALSE
, PSR_f
},
386 {"CPSR_c", TRUE
, PSR_c
},
387 {"CPSR_ctl", TRUE
, PSR_c
},
388 {"SPSR_c", FALSE
, PSR_c
},
389 {"SPSR_ctl", FALSE
, PSR_c
},
390 {"CPSR_x", TRUE
, PSR_x
},
391 {"CPSR_s", TRUE
, PSR_s
},
392 {"SPSR_x", FALSE
, PSR_x
},
393 {"SPSR_s", FALSE
, PSR_s
},
394 /* Combinations of flags. */
395 {"CPSR_fs", TRUE
, PSR_f
| PSR_s
},
396 {"CPSR_fx", TRUE
, PSR_f
| PSR_x
},
397 {"CPSR_fc", TRUE
, PSR_f
| PSR_c
},
398 {"CPSR_sf", TRUE
, PSR_s
| PSR_f
},
399 {"CPSR_sx", TRUE
, PSR_s
| PSR_x
},
400 {"CPSR_sc", TRUE
, PSR_s
| PSR_c
},
401 {"CPSR_xf", TRUE
, PSR_x
| PSR_f
},
402 {"CPSR_xs", TRUE
, PSR_x
| PSR_s
},
403 {"CPSR_xc", TRUE
, PSR_x
| PSR_c
},
404 {"CPSR_cf", TRUE
, PSR_c
| PSR_f
},
405 {"CPSR_cs", TRUE
, PSR_c
| PSR_s
},
406 {"CPSR_cx", TRUE
, PSR_c
| PSR_x
},
407 {"CPSR_fsx", TRUE
, PSR_f
| PSR_s
| PSR_x
},
408 {"CPSR_fsc", TRUE
, PSR_f
| PSR_s
| PSR_c
},
409 {"CPSR_fxs", TRUE
, PSR_f
| PSR_x
| PSR_s
},
410 {"CPSR_fxc", TRUE
, PSR_f
| PSR_x
| PSR_c
},
411 {"CPSR_fcs", TRUE
, PSR_f
| PSR_c
| PSR_s
},
412 {"CPSR_fcx", TRUE
, PSR_f
| PSR_c
| PSR_x
},
413 {"CPSR_sfx", TRUE
, PSR_s
| PSR_f
| PSR_x
},
414 {"CPSR_sfc", TRUE
, PSR_s
| PSR_f
| PSR_c
},
415 {"CPSR_sxf", TRUE
, PSR_s
| PSR_x
| PSR_f
},
416 {"CPSR_sxc", TRUE
, PSR_s
| PSR_x
| PSR_c
},
417 {"CPSR_scf", TRUE
, PSR_s
| PSR_c
| PSR_f
},
418 {"CPSR_scx", TRUE
, PSR_s
| PSR_c
| PSR_x
},
419 {"CPSR_xfs", TRUE
, PSR_x
| PSR_f
| PSR_s
},
420 {"CPSR_xfc", TRUE
, PSR_x
| PSR_f
| PSR_c
},
421 {"CPSR_xsf", TRUE
, PSR_x
| PSR_s
| PSR_f
},
422 {"CPSR_xsc", TRUE
, PSR_x
| PSR_s
| PSR_c
},
423 {"CPSR_xcf", TRUE
, PSR_x
| PSR_c
| PSR_f
},
424 {"CPSR_xcs", TRUE
, PSR_x
| PSR_c
| PSR_s
},
425 {"CPSR_cfs", TRUE
, PSR_c
| PSR_f
| PSR_s
},
426 {"CPSR_cfx", TRUE
, PSR_c
| PSR_f
| PSR_x
},
427 {"CPSR_csf", TRUE
, PSR_c
| PSR_s
| PSR_f
},
428 {"CPSR_csx", TRUE
, PSR_c
| PSR_s
| PSR_x
},
429 {"CPSR_cxf", TRUE
, PSR_c
| PSR_x
| PSR_f
},
430 {"CPSR_cxs", TRUE
, PSR_c
| PSR_x
| PSR_s
},
431 {"CPSR_fsxc", TRUE
, PSR_f
| PSR_s
| PSR_x
| PSR_c
},
432 {"CPSR_fscx", TRUE
, PSR_f
| PSR_s
| PSR_c
| PSR_x
},
433 {"CPSR_fxsc", TRUE
, PSR_f
| PSR_x
| PSR_s
| PSR_c
},
434 {"CPSR_fxcs", TRUE
, PSR_f
| PSR_x
| PSR_c
| PSR_s
},
435 {"CPSR_fcsx", TRUE
, PSR_f
| PSR_c
| PSR_s
| PSR_x
},
436 {"CPSR_fcxs", TRUE
, PSR_f
| PSR_c
| PSR_x
| PSR_s
},
437 {"CPSR_sfxc", TRUE
, PSR_s
| PSR_f
| PSR_x
| PSR_c
},
438 {"CPSR_sfcx", TRUE
, PSR_s
| PSR_f
| PSR_c
| PSR_x
},
439 {"CPSR_sxfc", TRUE
, PSR_s
| PSR_x
| PSR_f
| PSR_c
},
440 {"CPSR_sxcf", TRUE
, PSR_s
| PSR_x
| PSR_c
| PSR_f
},
441 {"CPSR_scfx", TRUE
, PSR_s
| PSR_c
| PSR_f
| PSR_x
},
442 {"CPSR_scxf", TRUE
, PSR_s
| PSR_c
| PSR_x
| PSR_f
},
443 {"CPSR_xfsc", TRUE
, PSR_x
| PSR_f
| PSR_s
| PSR_c
},
444 {"CPSR_xfcs", TRUE
, PSR_x
| PSR_f
| PSR_c
| PSR_s
},
445 {"CPSR_xsfc", TRUE
, PSR_x
| PSR_s
| PSR_f
| PSR_c
},
446 {"CPSR_xscf", TRUE
, PSR_x
| PSR_s
| PSR_c
| PSR_f
},
447 {"CPSR_xcfs", TRUE
, PSR_x
| PSR_c
| PSR_f
| PSR_s
},
448 {"CPSR_xcsf", TRUE
, PSR_x
| PSR_c
| PSR_s
| PSR_f
},
449 {"CPSR_cfsx", TRUE
, PSR_c
| PSR_f
| PSR_s
| PSR_x
},
450 {"CPSR_cfxs", TRUE
, PSR_c
| PSR_f
| PSR_x
| PSR_s
},
451 {"CPSR_csfx", TRUE
, PSR_c
| PSR_s
| PSR_f
| PSR_x
},
452 {"CPSR_csxf", TRUE
, PSR_c
| PSR_s
| PSR_x
| PSR_f
},
453 {"CPSR_cxfs", TRUE
, PSR_c
| PSR_x
| PSR_f
| PSR_s
},
454 {"CPSR_cxsf", TRUE
, PSR_c
| PSR_x
| PSR_s
| PSR_f
},
455 {"SPSR_fs", FALSE
, PSR_f
| PSR_s
},
456 {"SPSR_fx", FALSE
, PSR_f
| PSR_x
},
457 {"SPSR_fc", FALSE
, PSR_f
| PSR_c
},
458 {"SPSR_sf", FALSE
, PSR_s
| PSR_f
},
459 {"SPSR_sx", FALSE
, PSR_s
| PSR_x
},
460 {"SPSR_sc", FALSE
, PSR_s
| PSR_c
},
461 {"SPSR_xf", FALSE
, PSR_x
| PSR_f
},
462 {"SPSR_xs", FALSE
, PSR_x
| PSR_s
},
463 {"SPSR_xc", FALSE
, PSR_x
| PSR_c
},
464 {"SPSR_cf", FALSE
, PSR_c
| PSR_f
},
465 {"SPSR_cs", FALSE
, PSR_c
| PSR_s
},
466 {"SPSR_cx", FALSE
, PSR_c
| PSR_x
},
467 {"SPSR_fsx", FALSE
, PSR_f
| PSR_s
| PSR_x
},
468 {"SPSR_fsc", FALSE
, PSR_f
| PSR_s
| PSR_c
},
469 {"SPSR_fxs", FALSE
, PSR_f
| PSR_x
| PSR_s
},
470 {"SPSR_fxc", FALSE
, PSR_f
| PSR_x
| PSR_c
},
471 {"SPSR_fcs", FALSE
, PSR_f
| PSR_c
| PSR_s
},
472 {"SPSR_fcx", FALSE
, PSR_f
| PSR_c
| PSR_x
},
473 {"SPSR_sfx", FALSE
, PSR_s
| PSR_f
| PSR_x
},
474 {"SPSR_sfc", FALSE
, PSR_s
| PSR_f
| PSR_c
},
475 {"SPSR_sxf", FALSE
, PSR_s
| PSR_x
| PSR_f
},
476 {"SPSR_sxc", FALSE
, PSR_s
| PSR_x
| PSR_c
},
477 {"SPSR_scf", FALSE
, PSR_s
| PSR_c
| PSR_f
},
478 {"SPSR_scx", FALSE
, PSR_s
| PSR_c
| PSR_x
},
479 {"SPSR_xfs", FALSE
, PSR_x
| PSR_f
| PSR_s
},
480 {"SPSR_xfc", FALSE
, PSR_x
| PSR_f
| PSR_c
},
481 {"SPSR_xsf", FALSE
, PSR_x
| PSR_s
| PSR_f
},
482 {"SPSR_xsc", FALSE
, PSR_x
| PSR_s
| PSR_c
},
483 {"SPSR_xcf", FALSE
, PSR_x
| PSR_c
| PSR_f
},
484 {"SPSR_xcs", FALSE
, PSR_x
| PSR_c
| PSR_s
},
485 {"SPSR_cfs", FALSE
, PSR_c
| PSR_f
| PSR_s
},
486 {"SPSR_cfx", FALSE
, PSR_c
| PSR_f
| PSR_x
},
487 {"SPSR_csf", FALSE
, PSR_c
| PSR_s
| PSR_f
},
488 {"SPSR_csx", FALSE
, PSR_c
| PSR_s
| PSR_x
},
489 {"SPSR_cxf", FALSE
, PSR_c
| PSR_x
| PSR_f
},
490 {"SPSR_cxs", FALSE
, PSR_c
| PSR_x
| PSR_s
},
491 {"SPSR_fsxc", FALSE
, PSR_f
| PSR_s
| PSR_x
| PSR_c
},
492 {"SPSR_fscx", FALSE
, PSR_f
| PSR_s
| PSR_c
| PSR_x
},
493 {"SPSR_fxsc", FALSE
, PSR_f
| PSR_x
| PSR_s
| PSR_c
},
494 {"SPSR_fxcs", FALSE
, PSR_f
| PSR_x
| PSR_c
| PSR_s
},
495 {"SPSR_fcsx", FALSE
, PSR_f
| PSR_c
| PSR_s
| PSR_x
},
496 {"SPSR_fcxs", FALSE
, PSR_f
| PSR_c
| PSR_x
| PSR_s
},
497 {"SPSR_sfxc", FALSE
, PSR_s
| PSR_f
| PSR_x
| PSR_c
},
498 {"SPSR_sfcx", FALSE
, PSR_s
| PSR_f
| PSR_c
| PSR_x
},
499 {"SPSR_sxfc", FALSE
, PSR_s
| PSR_x
| PSR_f
| PSR_c
},
500 {"SPSR_sxcf", FALSE
, PSR_s
| PSR_x
| PSR_c
| PSR_f
},
501 {"SPSR_scfx", FALSE
, PSR_s
| PSR_c
| PSR_f
| PSR_x
},
502 {"SPSR_scxf", FALSE
, PSR_s
| PSR_c
| PSR_x
| PSR_f
},
503 {"SPSR_xfsc", FALSE
, PSR_x
| PSR_f
| PSR_s
| PSR_c
},
504 {"SPSR_xfcs", FALSE
, PSR_x
| PSR_f
| PSR_c
| PSR_s
},
505 {"SPSR_xsfc", FALSE
, PSR_x
| PSR_s
| PSR_f
| PSR_c
},
506 {"SPSR_xscf", FALSE
, PSR_x
| PSR_s
| PSR_c
| PSR_f
},
507 {"SPSR_xcfs", FALSE
, PSR_x
| PSR_c
| PSR_f
| PSR_s
},
508 {"SPSR_xcsf", FALSE
, PSR_x
| PSR_c
| PSR_s
| PSR_f
},
509 {"SPSR_cfsx", FALSE
, PSR_c
| PSR_f
| PSR_s
| PSR_x
},
510 {"SPSR_cfxs", FALSE
, PSR_c
| PSR_f
| PSR_x
| PSR_s
},
511 {"SPSR_csfx", FALSE
, PSR_c
| PSR_s
| PSR_f
| PSR_x
},
512 {"SPSR_csxf", FALSE
, PSR_c
| PSR_s
| PSR_x
| PSR_f
},
513 {"SPSR_cxfs", FALSE
, PSR_c
| PSR_x
| PSR_f
| PSR_s
},
514 {"SPSR_cxsf", FALSE
, PSR_c
| PSR_x
| PSR_s
| PSR_f
},
521 IWMMXT_REG_WR_OR_WC
= 2,
525 enum iwmmxt_insn_type
548 VFP_REG_Dd
, VFP_REG_Dm
, VFP_REG_Dn
553 VFP_REG_Sd
, VFP_REG_Sm
, VFP_REG_Sn
558 VFP_LDSTMIA
, VFP_LDSTMDB
, VFP_LDSTMIAX
, VFP_LDSTMDBX
561 /* VFP system registers. */
568 static const struct vfp_reg vfp_regs
[] =
570 {"fpsid", 0x00000000},
571 {"FPSID", 0x00000000},
572 {"fpscr", 0x00010000},
573 {"FPSCR", 0x00010000},
574 {"fpexc", 0x00080000},
575 {"FPEXC", 0x00080000}
578 /* Structure for a hash table entry for a register. */
585 /* Some well known registers that we refer to directly elsewhere. */
590 #define wr_register(reg) ((reg ^ WR_PREFIX) >= 0 && (reg ^ WR_PREFIX) <= 15)
591 #define wc_register(reg) ((reg ^ WC_PREFIX) >= 0 && (reg ^ WC_PREFIX) <= 15)
592 #define wcg_register(reg) ((reg ^ WC_PREFIX) >= 8 && (reg ^ WC_PREFIX) <= 11)
594 /* These are the standard names. Users can add aliases with .req. */
595 /* Integer Register Numbers. */
596 static const struct reg_entry rn_table
[] =
598 {"r0", 0}, {"r1", 1}, {"r2", 2}, {"r3", 3},
599 {"r4", 4}, {"r5", 5}, {"r6", 6}, {"r7", 7},
600 {"r8", 8}, {"r9", 9}, {"r10", 10}, {"r11", 11},
601 {"r12", 12}, {"r13", REG_SP
}, {"r14", REG_LR
}, {"r15", REG_PC
},
602 /* ATPCS Synonyms. */
603 {"a1", 0}, {"a2", 1}, {"a3", 2}, {"a4", 3},
604 {"v1", 4}, {"v2", 5}, {"v3", 6}, {"v4", 7},
605 {"v5", 8}, {"v6", 9}, {"v7", 10}, {"v8", 11},
606 /* Well-known aliases. */
608 {"sb", 9}, {"sl", 10}, {"fp", 11},
609 {"ip", 12}, {"sp", REG_SP
}, {"lr", REG_LR
}, {"pc", REG_PC
},
613 #define WR_PREFIX 0x200
614 #define WC_PREFIX 0x400
616 static const struct reg_entry iwmmxt_table
[] =
618 /* Intel Wireless MMX technology register names. */
619 { "wr0", 0x0 | WR_PREFIX
}, {"wr1", 0x1 | WR_PREFIX
},
620 { "wr2", 0x2 | WR_PREFIX
}, {"wr3", 0x3 | WR_PREFIX
},
621 { "wr4", 0x4 | WR_PREFIX
}, {"wr5", 0x5 | WR_PREFIX
},
622 { "wr6", 0x6 | WR_PREFIX
}, {"wr7", 0x7 | WR_PREFIX
},
623 { "wr8", 0x8 | WR_PREFIX
}, {"wr9", 0x9 | WR_PREFIX
},
624 { "wr10", 0xa | WR_PREFIX
}, {"wr11", 0xb | WR_PREFIX
},
625 { "wr12", 0xc | WR_PREFIX
}, {"wr13", 0xd | WR_PREFIX
},
626 { "wr14", 0xe | WR_PREFIX
}, {"wr15", 0xf | WR_PREFIX
},
627 { "wcid", 0x0 | WC_PREFIX
}, {"wcon", 0x1 | WC_PREFIX
},
628 {"wcssf", 0x2 | WC_PREFIX
}, {"wcasf", 0x3 | WC_PREFIX
},
629 {"wcgr0", 0x8 | WC_PREFIX
}, {"wcgr1", 0x9 | WC_PREFIX
},
630 {"wcgr2", 0xa | WC_PREFIX
}, {"wcgr3", 0xb | WC_PREFIX
},
632 { "wR0", 0x0 | WR_PREFIX
}, {"wR1", 0x1 | WR_PREFIX
},
633 { "wR2", 0x2 | WR_PREFIX
}, {"wR3", 0x3 | WR_PREFIX
},
634 { "wR4", 0x4 | WR_PREFIX
}, {"wR5", 0x5 | WR_PREFIX
},
635 { "wR6", 0x6 | WR_PREFIX
}, {"wR7", 0x7 | WR_PREFIX
},
636 { "wR8", 0x8 | WR_PREFIX
}, {"wR9", 0x9 | WR_PREFIX
},
637 { "wR10", 0xa | WR_PREFIX
}, {"wR11", 0xb | WR_PREFIX
},
638 { "wR12", 0xc | WR_PREFIX
}, {"wR13", 0xd | WR_PREFIX
},
639 { "wR14", 0xe | WR_PREFIX
}, {"wR15", 0xf | WR_PREFIX
},
640 { "wCID", 0x0 | WC_PREFIX
}, {"wCon", 0x1 | WC_PREFIX
},
641 {"wCSSF", 0x2 | WC_PREFIX
}, {"wCASF", 0x3 | WC_PREFIX
},
642 {"wCGR0", 0x8 | WC_PREFIX
}, {"wCGR1", 0x9 | WC_PREFIX
},
643 {"wCGR2", 0xa | WC_PREFIX
}, {"wCGR3", 0xb | WC_PREFIX
},
647 /* Co-processor Numbers. */
648 static const struct reg_entry cp_table
[] =
650 {"p0", 0}, {"p1", 1}, {"p2", 2}, {"p3", 3},
651 {"p4", 4}, {"p5", 5}, {"p6", 6}, {"p7", 7},
652 {"p8", 8}, {"p9", 9}, {"p10", 10}, {"p11", 11},
653 {"p12", 12}, {"p13", 13}, {"p14", 14}, {"p15", 15},
657 /* Co-processor Register Numbers. */
658 static const struct reg_entry cn_table
[] =
660 {"c0", 0}, {"c1", 1}, {"c2", 2}, {"c3", 3},
661 {"c4", 4}, {"c5", 5}, {"c6", 6}, {"c7", 7},
662 {"c8", 8}, {"c9", 9}, {"c10", 10}, {"c11", 11},
663 {"c12", 12}, {"c13", 13}, {"c14", 14}, {"c15", 15},
664 /* Not really valid, but kept for back-wards compatibility. */
665 {"cr0", 0}, {"cr1", 1}, {"cr2", 2}, {"cr3", 3},
666 {"cr4", 4}, {"cr5", 5}, {"cr6", 6}, {"cr7", 7},
667 {"cr8", 8}, {"cr9", 9}, {"cr10", 10}, {"cr11", 11},
668 {"cr12", 12}, {"cr13", 13}, {"cr14", 14}, {"cr15", 15},
673 static const struct reg_entry fn_table
[] =
675 {"f0", 0}, {"f1", 1}, {"f2", 2}, {"f3", 3},
676 {"f4", 4}, {"f5", 5}, {"f6", 6}, {"f7", 7},
680 /* VFP SP Registers. */
681 static const struct reg_entry sn_table
[] =
683 {"s0", 0}, {"s1", 1}, {"s2", 2}, {"s3", 3},
684 {"s4", 4}, {"s5", 5}, {"s6", 6}, {"s7", 7},
685 {"s8", 8}, {"s9", 9}, {"s10", 10}, {"s11", 11},
686 {"s12", 12}, {"s13", 13}, {"s14", 14}, {"s15", 15},
687 {"s16", 16}, {"s17", 17}, {"s18", 18}, {"s19", 19},
688 {"s20", 20}, {"s21", 21}, {"s22", 22}, {"s23", 23},
689 {"s24", 24}, {"s25", 25}, {"s26", 26}, {"s27", 27},
690 {"s28", 28}, {"s29", 29}, {"s30", 30}, {"s31", 31},
694 /* VFP DP Registers. */
695 static const struct reg_entry dn_table
[] =
697 {"d0", 0}, {"d1", 1}, {"d2", 2}, {"d3", 3},
698 {"d4", 4}, {"d5", 5}, {"d6", 6}, {"d7", 7},
699 {"d8", 8}, {"d9", 9}, {"d10", 10}, {"d11", 11},
700 {"d12", 12}, {"d13", 13}, {"d14", 14}, {"d15", 15},
704 /* Maverick DSP coprocessor registers. */
705 static const struct reg_entry mav_mvf_table
[] =
707 {"mvf0", 0}, {"mvf1", 1}, {"mvf2", 2}, {"mvf3", 3},
708 {"mvf4", 4}, {"mvf5", 5}, {"mvf6", 6}, {"mvf7", 7},
709 {"mvf8", 8}, {"mvf9", 9}, {"mvf10", 10}, {"mvf11", 11},
710 {"mvf12", 12}, {"mvf13", 13}, {"mvf14", 14}, {"mvf15", 15},
714 static const struct reg_entry mav_mvd_table
[] =
716 {"mvd0", 0}, {"mvd1", 1}, {"mvd2", 2}, {"mvd3", 3},
717 {"mvd4", 4}, {"mvd5", 5}, {"mvd6", 6}, {"mvd7", 7},
718 {"mvd8", 8}, {"mvd9", 9}, {"mvd10", 10}, {"mvd11", 11},
719 {"mvd12", 12}, {"mvd13", 13}, {"mvd14", 14}, {"mvd15", 15},
723 static const struct reg_entry mav_mvfx_table
[] =
725 {"mvfx0", 0}, {"mvfx1", 1}, {"mvfx2", 2}, {"mvfx3", 3},
726 {"mvfx4", 4}, {"mvfx5", 5}, {"mvfx6", 6}, {"mvfx7", 7},
727 {"mvfx8", 8}, {"mvfx9", 9}, {"mvfx10", 10}, {"mvfx11", 11},
728 {"mvfx12", 12}, {"mvfx13", 13}, {"mvfx14", 14}, {"mvfx15", 15},
732 static const struct reg_entry mav_mvdx_table
[] =
734 {"mvdx0", 0}, {"mvdx1", 1}, {"mvdx2", 2}, {"mvdx3", 3},
735 {"mvdx4", 4}, {"mvdx5", 5}, {"mvdx6", 6}, {"mvdx7", 7},
736 {"mvdx8", 8}, {"mvdx9", 9}, {"mvdx10", 10}, {"mvdx11", 11},
737 {"mvdx12", 12}, {"mvdx13", 13}, {"mvdx14", 14}, {"mvdx15", 15},
741 static const struct reg_entry mav_mvax_table
[] =
743 {"mvax0", 0}, {"mvax1", 1}, {"mvax2", 2}, {"mvax3", 3},
747 static const struct reg_entry mav_dspsc_table
[] =
755 const struct reg_entry
*names
;
757 struct hash_control
*htab
;
758 const char *expected
;
761 struct reg_map all_reg_maps
[] =
763 {rn_table
, 15, NULL
, N_("ARM register expected")},
764 {cp_table
, 15, NULL
, N_("bad or missing co-processor number")},
765 {cn_table
, 15, NULL
, N_("co-processor register expected")},
766 {fn_table
, 7, NULL
, N_("FPA register expected")},
767 {sn_table
, 31, NULL
, N_("VFP single precision register expected")},
768 {dn_table
, 15, NULL
, N_("VFP double precision register expected")},
769 {mav_mvf_table
, 15, NULL
, N_("Maverick MVF register expected")},
770 {mav_mvd_table
, 15, NULL
, N_("Maverick MVD register expected")},
771 {mav_mvfx_table
, 15, NULL
, N_("Maverick MVFX register expected")},
772 {mav_mvdx_table
, 15, NULL
, N_("Maverick MVFX register expected")},
773 {mav_mvax_table
, 3, NULL
, N_("Maverick MVAX register expected")},
774 {mav_dspsc_table
, 0, NULL
, N_("Maverick DSPSC register expected")},
775 {iwmmxt_table
, 23, NULL
, N_("Intel Wireless MMX technology register expected")},
778 /* Enumeration matching entries in table above. */
782 #define REG_TYPE_FIRST REG_TYPE_RN
794 REG_TYPE_IWMMXT
= 12,
799 /* Functions called by parser. */
800 /* ARM instructions. */
801 static void do_arit
PARAMS ((char *));
802 static void do_cmp
PARAMS ((char *));
803 static void do_mov
PARAMS ((char *));
804 static void do_ldst
PARAMS ((char *));
805 static void do_ldstt
PARAMS ((char *));
806 static void do_ldmstm
PARAMS ((char *));
807 static void do_branch
PARAMS ((char *));
808 static void do_swi
PARAMS ((char *));
810 /* Pseudo Op codes. */
811 static void do_adr
PARAMS ((char *));
812 static void do_adrl
PARAMS ((char *));
813 static void do_empty
PARAMS ((char *));
816 static void do_mul
PARAMS ((char *));
817 static void do_mla
PARAMS ((char *));
820 static void do_swap
PARAMS ((char *));
823 static void do_msr
PARAMS ((char *));
824 static void do_mrs
PARAMS ((char *));
827 static void do_mull
PARAMS ((char *));
830 static void do_ldstv4
PARAMS ((char *));
833 static void do_bx
PARAMS ((char *));
836 static void do_blx
PARAMS ((char *));
837 static void do_bkpt
PARAMS ((char *));
838 static void do_clz
PARAMS ((char *));
839 static void do_lstc2
PARAMS ((char *));
840 static void do_cdp2
PARAMS ((char *));
841 static void do_co_reg2
PARAMS ((char *));
844 static void do_smla
PARAMS ((char *));
845 static void do_smlal
PARAMS ((char *));
846 static void do_smul
PARAMS ((char *));
847 static void do_qadd
PARAMS ((char *));
850 static void do_pld
PARAMS ((char *));
851 static void do_ldrd
PARAMS ((char *));
852 static void do_co_reg2c
PARAMS ((char *));
855 static void do_bxj
PARAMS ((char *));
857 /* Coprocessor Instructions. */
858 static void do_cdp
PARAMS ((char *));
859 static void do_lstc
PARAMS ((char *));
860 static void do_co_reg
PARAMS ((char *));
862 /* FPA instructions. */
863 static void do_fpa_ctrl
PARAMS ((char *));
864 static void do_fpa_ldst
PARAMS ((char *));
865 static void do_fpa_ldmstm
PARAMS ((char *));
866 static void do_fpa_dyadic
PARAMS ((char *));
867 static void do_fpa_monadic
PARAMS ((char *));
868 static void do_fpa_cmp
PARAMS ((char *));
869 static void do_fpa_from_reg
PARAMS ((char *));
870 static void do_fpa_to_reg
PARAMS ((char *));
872 /* VFP instructions. */
873 static void do_vfp_sp_monadic
PARAMS ((char *));
874 static void do_vfp_dp_monadic
PARAMS ((char *));
875 static void do_vfp_sp_dyadic
PARAMS ((char *));
876 static void do_vfp_dp_dyadic
PARAMS ((char *));
877 static void do_vfp_reg_from_sp
PARAMS ((char *));
878 static void do_vfp_sp_from_reg
PARAMS ((char *));
879 static void do_vfp_sp_reg2
PARAMS ((char *));
880 static void do_vfp_reg_from_dp
PARAMS ((char *));
881 static void do_vfp_reg2_from_dp
PARAMS ((char *));
882 static void do_vfp_dp_from_reg
PARAMS ((char *));
883 static void do_vfp_dp_from_reg2
PARAMS ((char *));
884 static void do_vfp_reg_from_ctrl
PARAMS ((char *));
885 static void do_vfp_ctrl_from_reg
PARAMS ((char *));
886 static void do_vfp_sp_ldst
PARAMS ((char *));
887 static void do_vfp_dp_ldst
PARAMS ((char *));
888 static void do_vfp_sp_ldstmia
PARAMS ((char *));
889 static void do_vfp_sp_ldstmdb
PARAMS ((char *));
890 static void do_vfp_dp_ldstmia
PARAMS ((char *));
891 static void do_vfp_dp_ldstmdb
PARAMS ((char *));
892 static void do_vfp_xp_ldstmia
PARAMS ((char *));
893 static void do_vfp_xp_ldstmdb
PARAMS ((char *));
894 static void do_vfp_sp_compare_z
PARAMS ((char *));
895 static void do_vfp_dp_compare_z
PARAMS ((char *));
896 static void do_vfp_dp_sp_cvt
PARAMS ((char *));
897 static void do_vfp_sp_dp_cvt
PARAMS ((char *));
900 static void do_xsc_mia
PARAMS ((char *));
901 static void do_xsc_mar
PARAMS ((char *));
902 static void do_xsc_mra
PARAMS ((char *));
905 static void do_mav_binops
PARAMS ((char *, int, enum arm_reg_type
,
907 static void do_mav_binops_1a
PARAMS ((char *));
908 static void do_mav_binops_1b
PARAMS ((char *));
909 static void do_mav_binops_1c
PARAMS ((char *));
910 static void do_mav_binops_1d
PARAMS ((char *));
911 static void do_mav_binops_1e
PARAMS ((char *));
912 static void do_mav_binops_1f
PARAMS ((char *));
913 static void do_mav_binops_1g
PARAMS ((char *));
914 static void do_mav_binops_1h
PARAMS ((char *));
915 static void do_mav_binops_1i
PARAMS ((char *));
916 static void do_mav_binops_1j
PARAMS ((char *));
917 static void do_mav_binops_1k
PARAMS ((char *));
918 static void do_mav_binops_1l
PARAMS ((char *));
919 static void do_mav_binops_1m
PARAMS ((char *));
920 static void do_mav_binops_1n
PARAMS ((char *));
921 static void do_mav_binops_1o
PARAMS ((char *));
922 static void do_mav_binops_2a
PARAMS ((char *));
923 static void do_mav_binops_2b
PARAMS ((char *));
924 static void do_mav_binops_2c
PARAMS ((char *));
925 static void do_mav_binops_3a
PARAMS ((char *));
926 static void do_mav_binops_3b
PARAMS ((char *));
927 static void do_mav_binops_3c
PARAMS ((char *));
928 static void do_mav_binops_3d
PARAMS ((char *));
929 static void do_mav_triple
PARAMS ((char *, int, enum arm_reg_type
,
932 static void do_mav_triple_4a
PARAMS ((char *));
933 static void do_mav_triple_4b
PARAMS ((char *));
934 static void do_mav_triple_5a
PARAMS ((char *));
935 static void do_mav_triple_5b
PARAMS ((char *));
936 static void do_mav_triple_5c
PARAMS ((char *));
937 static void do_mav_triple_5d
PARAMS ((char *));
938 static void do_mav_triple_5e
PARAMS ((char *));
939 static void do_mav_triple_5f
PARAMS ((char *));
940 static void do_mav_triple_5g
PARAMS ((char *));
941 static void do_mav_triple_5h
PARAMS ((char *));
942 static void do_mav_quad
PARAMS ((char *, int, enum arm_reg_type
,
946 static void do_mav_quad_6a
PARAMS ((char *));
947 static void do_mav_quad_6b
PARAMS ((char *));
948 static void do_mav_dspsc_1
PARAMS ((char *));
949 static void do_mav_dspsc_2
PARAMS ((char *));
950 static void do_mav_shift
PARAMS ((char *, enum arm_reg_type
,
952 static void do_mav_shift_1
PARAMS ((char *));
953 static void do_mav_shift_2
PARAMS ((char *));
954 static void do_mav_ldst
PARAMS ((char *, enum arm_reg_type
));
955 static void do_mav_ldst_1
PARAMS ((char *));
956 static void do_mav_ldst_2
PARAMS ((char *));
957 static void do_mav_ldst_3
PARAMS ((char *));
958 static void do_mav_ldst_4
PARAMS ((char *));
960 static int mav_reg_required_here
PARAMS ((char **, int,
962 static int mav_parse_offset
PARAMS ((char **, int *));
964 static void fix_new_arm
PARAMS ((fragS
*, int, short, expressionS
*,
966 static int arm_reg_parse
PARAMS ((char **, struct hash_control
*));
967 static enum arm_reg_type arm_reg_parse_any
PARAMS ((char *));
968 static const struct asm_psr
* arm_psr_parse
PARAMS ((char **));
969 static void symbol_locate
PARAMS ((symbolS
*, const char *, segT
, valueT
,
971 static int add_to_lit_pool
PARAMS ((void));
972 static unsigned validate_immediate
PARAMS ((unsigned));
973 static unsigned validate_immediate_twopart
PARAMS ((unsigned int,
975 static int validate_offset_imm
PARAMS ((unsigned int, int));
976 static void opcode_select
PARAMS ((int));
977 static void end_of_line
PARAMS ((char *));
978 static int reg_required_here
PARAMS ((char **, int));
979 static int psr_required_here
PARAMS ((char **));
980 static int co_proc_number
PARAMS ((char **));
981 static int cp_opc_expr
PARAMS ((char **, int, int));
982 static int cp_reg_required_here
PARAMS ((char **, int));
983 static int fp_reg_required_here
PARAMS ((char **, int));
984 static int vfp_sp_reg_required_here
PARAMS ((char **, enum vfp_sp_reg_pos
));
985 static int vfp_dp_reg_required_here
PARAMS ((char **, enum vfp_dp_reg_pos
));
986 static void vfp_sp_ldstm
PARAMS ((char *, enum vfp_ldstm_type
));
987 static void vfp_dp_ldstm
PARAMS ((char *, enum vfp_ldstm_type
));
988 static long vfp_sp_reg_list
PARAMS ((char **, enum vfp_sp_reg_pos
));
989 static long vfp_dp_reg_list
PARAMS ((char **));
990 static int vfp_psr_required_here
PARAMS ((char **str
));
991 static const struct vfp_reg
*vfp_psr_parse
PARAMS ((char **str
));
992 static int cp_address_offset
PARAMS ((char **));
993 static int cp_address_required_here
PARAMS ((char **, int));
994 static int my_get_float_expression
PARAMS ((char **));
995 static int skip_past_comma
PARAMS ((char **));
996 static int walk_no_bignums
PARAMS ((symbolS
*));
997 static int negate_data_op
PARAMS ((unsigned long *, unsigned long));
998 static int data_op2
PARAMS ((char **));
999 static int fp_op2
PARAMS ((char **));
1000 static long reg_list
PARAMS ((char **));
1001 static void thumb_load_store
PARAMS ((char *, int, int));
1002 static int decode_shift
PARAMS ((char **, int));
1003 static int ldst_extend
PARAMS ((char **));
1004 static int ldst_extend_v4
PARAMS ((char **));
1005 static void thumb_add_sub
PARAMS ((char *, int));
1006 static void insert_reg
PARAMS ((const struct reg_entry
*,
1007 struct hash_control
*));
1008 static void thumb_shift
PARAMS ((char *, int));
1009 static void thumb_mov_compare
PARAMS ((char *, int));
1010 static void build_arm_ops_hsh
PARAMS ((void));
1011 static void set_constant_flonums
PARAMS ((void));
1012 static valueT md_chars_to_number
PARAMS ((char *, int));
1013 static void build_reg_hsh
PARAMS ((struct reg_map
*));
1014 static void insert_reg_alias
PARAMS ((char *, int, struct hash_control
*));
1015 static int create_register_alias
PARAMS ((char *, char *));
1016 static void output_inst
PARAMS ((const char *));
1017 static int accum0_required_here
PARAMS ((char **));
1018 static int ld_mode_required_here
PARAMS ((char **));
1019 static void do_branch25
PARAMS ((char *));
1020 static symbolS
* find_real_start
PARAMS ((symbolS
*));
1022 static bfd_reloc_code_real_type arm_parse_reloc
PARAMS ((void));
1025 static int wreg_required_here
PARAMS ((char **, int, enum wreg_type
));
1026 static void do_iwmmxt_byte_addr
PARAMS ((char *));
1027 static void do_iwmmxt_tandc
PARAMS ((char *));
1028 static void do_iwmmxt_tbcst
PARAMS ((char *));
1029 static void do_iwmmxt_textrc
PARAMS ((char *));
1030 static void do_iwmmxt_textrm
PARAMS ((char *));
1031 static void do_iwmmxt_tinsr
PARAMS ((char *));
1032 static void do_iwmmxt_tmcr
PARAMS ((char *));
1033 static void do_iwmmxt_tmcrr
PARAMS ((char *));
1034 static void do_iwmmxt_tmia
PARAMS ((char *));
1035 static void do_iwmmxt_tmovmsk
PARAMS ((char *));
1036 static void do_iwmmxt_tmrc
PARAMS ((char *));
1037 static void do_iwmmxt_tmrrc
PARAMS ((char *));
1038 static void do_iwmmxt_torc
PARAMS ((char *));
1039 static void do_iwmmxt_waligni
PARAMS ((char *));
1040 static void do_iwmmxt_wmov
PARAMS ((char *));
1041 static void do_iwmmxt_word_addr
PARAMS ((char *));
1042 static void do_iwmmxt_wrwr
PARAMS ((char *));
1043 static void do_iwmmxt_wrwrwcg
PARAMS ((char *));
1044 static void do_iwmmxt_wrwrwr
PARAMS ((char *));
1045 static void do_iwmmxt_wshufh
PARAMS ((char *));
1046 static void do_iwmmxt_wzero
PARAMS ((char *));
1047 static int cp_byte_address_offset
PARAMS ((char **));
1048 static int cp_byte_address_required_here
PARAMS ((char **));
1050 /* ARM instructions take 4bytes in the object file, Thumb instructions
1054 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
1055 #define MAV_MODE1 0x100c
1057 /* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
1058 #define MAV_MODE2 0x0c10
1060 /* "INSN<cond> X,Y" where X:0, Y:bit16. */
1061 #define MAV_MODE3 0x1000
1063 /* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
1064 #define MAV_MODE4 0x0c0010
1066 /* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
1067 #define MAV_MODE5 0x00100c
1069 /* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
1070 #define MAV_MODE6 0x00100c05
1074 /* Basic string to match. */
1075 const char * template;
1077 /* Basic instruction code. */
1078 unsigned long value
;
1080 /* Offset into the template where the condition code (if any) will be.
1081 If zero, then the instruction is never conditional. */
1082 unsigned cond_offset
;
1084 /* Which architecture variant provides this instruction. */
1085 unsigned long variant
;
1087 /* Function to call to parse args. */
1088 void (* parms
) PARAMS ((char *));
1091 static const struct asm_opcode insns
[] =
1093 /* Core ARM Instructions. */
1094 {"and", 0xe0000000, 3, ARM_EXT_V1
, do_arit
},
1095 {"ands", 0xe0100000, 3, ARM_EXT_V1
, do_arit
},
1096 {"eor", 0xe0200000, 3, ARM_EXT_V1
, do_arit
},
1097 {"eors", 0xe0300000, 3, ARM_EXT_V1
, do_arit
},
1098 {"sub", 0xe0400000, 3, ARM_EXT_V1
, do_arit
},
1099 {"subs", 0xe0500000, 3, ARM_EXT_V1
, do_arit
},
1100 {"rsb", 0xe0600000, 3, ARM_EXT_V1
, do_arit
},
1101 {"rsbs", 0xe0700000, 3, ARM_EXT_V1
, do_arit
},
1102 {"add", 0xe0800000, 3, ARM_EXT_V1
, do_arit
},
1103 {"adds", 0xe0900000, 3, ARM_EXT_V1
, do_arit
},
1104 {"adc", 0xe0a00000, 3, ARM_EXT_V1
, do_arit
},
1105 {"adcs", 0xe0b00000, 3, ARM_EXT_V1
, do_arit
},
1106 {"sbc", 0xe0c00000, 3, ARM_EXT_V1
, do_arit
},
1107 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1
, do_arit
},
1108 {"rsc", 0xe0e00000, 3, ARM_EXT_V1
, do_arit
},
1109 {"rscs", 0xe0f00000, 3, ARM_EXT_V1
, do_arit
},
1110 {"orr", 0xe1800000, 3, ARM_EXT_V1
, do_arit
},
1111 {"orrs", 0xe1900000, 3, ARM_EXT_V1
, do_arit
},
1112 {"bic", 0xe1c00000, 3, ARM_EXT_V1
, do_arit
},
1113 {"bics", 0xe1d00000, 3, ARM_EXT_V1
, do_arit
},
1115 {"tst", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
1116 {"tsts", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
1117 {"tstp", 0xe110f000, 3, ARM_EXT_V1
, do_cmp
},
1118 {"teq", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
1119 {"teqs", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
1120 {"teqp", 0xe130f000, 3, ARM_EXT_V1
, do_cmp
},
1121 {"cmp", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
1122 {"cmps", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
1123 {"cmpp", 0xe150f000, 3, ARM_EXT_V1
, do_cmp
},
1124 {"cmn", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
1125 {"cmns", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
1126 {"cmnp", 0xe170f000, 3, ARM_EXT_V1
, do_cmp
},
1128 {"mov", 0xe1a00000, 3, ARM_EXT_V1
, do_mov
},
1129 {"movs", 0xe1b00000, 3, ARM_EXT_V1
, do_mov
},
1130 {"mvn", 0xe1e00000, 3, ARM_EXT_V1
, do_mov
},
1131 {"mvns", 0xe1f00000, 3, ARM_EXT_V1
, do_mov
},
1133 {"ldr", 0xe4100000, 3, ARM_EXT_V1
, do_ldst
},
1134 {"ldrb", 0xe4500000, 3, ARM_EXT_V1
, do_ldst
},
1135 {"ldrt", 0xe4300000, 3, ARM_EXT_V1
, do_ldstt
},
1136 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1
, do_ldstt
},
1137 {"str", 0xe4000000, 3, ARM_EXT_V1
, do_ldst
},
1138 {"strb", 0xe4400000, 3, ARM_EXT_V1
, do_ldst
},
1139 {"strt", 0xe4200000, 3, ARM_EXT_V1
, do_ldstt
},
1140 {"strbt", 0xe4600000, 3, ARM_EXT_V1
, do_ldstt
},
1142 {"stmia", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
1143 {"stmib", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
1144 {"stmda", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
1145 {"stmdb", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
1146 {"stmfd", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
1147 {"stmfa", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
1148 {"stmea", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
1149 {"stmed", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
1151 {"ldmia", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
1152 {"ldmib", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
1153 {"ldmda", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
1154 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
1155 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
1156 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
1157 {"ldmea", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
1158 {"ldmed", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
1160 {"swi", 0xef000000, 3, ARM_EXT_V1
, do_swi
},
1162 /* XXX This is the wrong place to do this. Think multi-arch. */
1163 {"bl", 0xeb000000, 2, ARM_EXT_V1
, do_branch
},
1164 {"b", 0xea000000, 1, ARM_EXT_V1
, do_branch
},
1166 {"bl", 0xebfffffe, 2, ARM_EXT_V1
, do_branch
},
1167 {"b", 0xeafffffe, 1, ARM_EXT_V1
, do_branch
},
1171 {"adr", 0xe28f0000, 3, ARM_EXT_V1
, do_adr
},
1172 {"adrl", 0xe28f0000, 3, ARM_EXT_V1
, do_adrl
},
1173 {"nop", 0xe1a00000, 3, ARM_EXT_V1
, do_empty
},
1175 /* ARM 2 multiplies. */
1176 {"mul", 0xe0000090, 3, ARM_EXT_V2
, do_mul
},
1177 {"muls", 0xe0100090, 3, ARM_EXT_V2
, do_mul
},
1178 {"mla", 0xe0200090, 3, ARM_EXT_V2
, do_mla
},
1179 {"mlas", 0xe0300090, 3, ARM_EXT_V2
, do_mla
},
1181 /* Generic copressor instructions. */
1182 {"cdp", 0xee000000, 3, ARM_EXT_V2
, do_cdp
},
1183 {"ldc", 0xec100000, 3, ARM_EXT_V2
, do_lstc
},
1184 {"ldcl", 0xec500000, 3, ARM_EXT_V2
, do_lstc
},
1185 {"stc", 0xec000000, 3, ARM_EXT_V2
, do_lstc
},
1186 {"stcl", 0xec400000, 3, ARM_EXT_V2
, do_lstc
},
1187 {"mcr", 0xee000010, 3, ARM_EXT_V2
, do_co_reg
},
1188 {"mrc", 0xee100010, 3, ARM_EXT_V2
, do_co_reg
},
1190 /* ARM 3 - swp instructions. */
1191 {"swp", 0xe1000090, 3, ARM_EXT_V2S
, do_swap
},
1192 {"swpb", 0xe1400090, 3, ARM_EXT_V2S
, do_swap
},
1194 /* ARM 6 Status register instructions. */
1195 {"mrs", 0xe10f0000, 3, ARM_EXT_V3
, do_mrs
},
1196 {"msr", 0xe120f000, 3, ARM_EXT_V3
, do_msr
},
1197 /* ScottB: our code uses 0xe128f000 for msr.
1198 NickC: but this is wrong because the bits 16 through 19 are
1199 handled by the PSR_xxx defines above. */
1201 /* ARM 7M long multiplies. */
1202 {"smull", 0xe0c00090, 5, ARM_EXT_V3M
, do_mull
},
1203 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M
, do_mull
},
1204 {"umull", 0xe0800090, 5, ARM_EXT_V3M
, do_mull
},
1205 {"umulls", 0xe0900090, 5, ARM_EXT_V3M
, do_mull
},
1206 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M
, do_mull
},
1207 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M
, do_mull
},
1208 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M
, do_mull
},
1209 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M
, do_mull
},
1211 /* ARM Architecture 4. */
1212 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4
, do_ldstv4
},
1213 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4
, do_ldstv4
},
1214 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4
, do_ldstv4
},
1215 {"strh", 0xe00000b0, 3, ARM_EXT_V4
, do_ldstv4
},
1217 /* ARM Architecture 4T. */
1218 /* Note: bx (and blx) are required on V5, even if the processor does
1219 not support Thumb. */
1220 {"bx", 0xe12fff10, 2, ARM_EXT_V4T
| ARM_EXT_V5
, do_bx
},
1222 /* ARM Architecture 5T. */
1223 /* Note: blx has 2 variants, so the .value is set dynamically.
1224 Only one of the variants has conditional execution. */
1225 {"blx", 0xe0000000, 3, ARM_EXT_V5
, do_blx
},
1226 {"clz", 0xe16f0f10, 3, ARM_EXT_V5
, do_clz
},
1227 {"bkpt", 0xe1200070, 0, ARM_EXT_V5
, do_bkpt
},
1228 {"ldc2", 0xfc100000, 0, ARM_EXT_V5
, do_lstc2
},
1229 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5
, do_lstc2
},
1230 {"stc2", 0xfc000000, 0, ARM_EXT_V5
, do_lstc2
},
1231 {"stc2l", 0xfc400000, 0, ARM_EXT_V5
, do_lstc2
},
1232 {"cdp2", 0xfe000000, 0, ARM_EXT_V5
, do_cdp2
},
1233 {"mcr2", 0xfe000010, 0, ARM_EXT_V5
, do_co_reg2
},
1234 {"mrc2", 0xfe100010, 0, ARM_EXT_V5
, do_co_reg2
},
1236 /* ARM Architecture 5TExP. */
1237 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP
, do_smla
},
1238 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP
, do_smla
},
1239 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP
, do_smla
},
1240 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP
, do_smla
},
1242 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP
, do_smla
},
1243 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP
, do_smla
},
1245 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP
, do_smlal
},
1246 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP
, do_smlal
},
1247 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP
, do_smlal
},
1248 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP
, do_smlal
},
1250 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP
, do_smul
},
1251 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP
, do_smul
},
1252 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP
, do_smul
},
1253 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP
, do_smul
},
1255 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP
, do_smul
},
1256 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP
, do_smul
},
1258 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP
, do_qadd
},
1259 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP
, do_qadd
},
1260 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP
, do_qadd
},
1261 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP
, do_qadd
},
1263 /* ARM Architecture 5TE. */
1264 {"pld", 0xf450f000, 0, ARM_EXT_V5E
, do_pld
},
1265 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E
, do_ldrd
},
1266 {"strd", 0xe00000f0, 3, ARM_EXT_V5E
, do_ldrd
},
1268 {"mcrr", 0xec400000, 4, ARM_EXT_V5E
, do_co_reg2c
},
1269 {"mrrc", 0xec500000, 4, ARM_EXT_V5E
, do_co_reg2c
},
1271 /* ARM Architecture 5TEJ. */
1272 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J
, do_bxj
},
1274 /* Core FPA instruction set (V1). */
1275 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1276 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1277 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1278 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1280 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1281 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1282 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1283 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1285 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1286 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1287 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1288 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1290 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1291 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1292 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1293 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1294 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1295 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1296 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1297 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1298 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1299 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1300 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1301 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1303 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1304 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1305 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1306 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1307 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1308 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1309 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1310 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1311 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1312 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1313 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1314 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1316 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1317 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1318 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1319 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1320 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1321 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1322 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1323 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1324 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1325 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1326 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1327 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1329 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1330 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1331 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1332 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1333 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1334 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1335 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1336 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1337 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1338 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1339 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1340 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1342 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1343 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1344 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1345 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1346 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1347 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1348 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1349 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1350 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1351 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1352 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1353 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1355 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1356 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1357 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1358 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1359 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1360 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1361 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1362 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1363 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1364 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1365 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1366 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1368 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1369 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1370 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1371 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1372 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1373 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1374 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1375 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1376 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1377 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1378 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1379 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1381 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1382 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1383 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1384 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1385 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1386 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1387 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1388 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1389 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1390 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1391 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1392 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1394 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1395 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1396 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1397 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1398 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1399 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1400 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1401 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1402 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1403 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1404 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1405 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1407 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1408 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1409 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1410 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1411 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1412 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1413 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1414 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1415 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1416 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1417 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1418 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1420 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1421 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1422 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1423 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1424 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1425 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1426 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1427 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1428 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1429 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1430 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1431 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1433 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1434 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1435 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1436 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1437 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1438 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1439 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1440 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1441 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1442 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1443 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1444 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1446 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1447 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1448 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1449 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1450 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1451 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1452 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1453 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1454 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1455 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1456 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1457 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1459 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1460 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1461 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1462 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1463 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1464 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1465 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1466 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1467 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1468 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1469 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1470 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1472 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1473 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1474 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1475 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1476 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1477 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1478 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1479 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1480 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1481 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1482 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1483 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1485 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1486 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1487 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1488 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1489 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1490 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1491 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1492 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1493 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1494 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1495 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1496 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1498 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1499 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1500 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1501 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1502 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1503 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1504 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1505 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1506 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1507 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1508 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1509 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1511 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1512 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1513 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1514 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1515 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1516 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1517 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1518 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1519 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1520 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1521 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1522 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1524 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1525 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1526 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1527 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1528 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1529 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1530 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1531 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1532 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1533 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1534 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1535 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1537 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1538 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1539 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1540 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1541 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1542 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1543 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1544 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1545 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1546 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1547 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1548 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1550 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1551 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1552 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1553 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1554 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1555 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1556 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1557 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1558 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1559 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1560 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1561 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1563 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1564 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1565 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1566 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1567 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1568 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1569 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1570 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1571 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1572 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1573 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1574 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1576 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1577 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1578 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1579 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1580 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1581 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1582 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1583 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1584 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1585 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1586 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1587 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1589 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1590 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1591 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1592 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1593 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1594 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1595 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1596 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1597 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1598 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1599 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1600 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1602 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1603 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1604 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1605 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1606 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1607 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1608 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1609 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1610 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1611 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1612 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1613 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1615 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1616 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1617 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1618 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1619 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1620 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1621 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1622 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1623 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1624 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1625 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1626 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1628 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1629 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1630 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1631 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1632 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1633 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1634 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1635 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1636 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1637 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1638 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1639 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1641 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1642 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1643 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1644 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1645 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1646 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1647 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1648 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1649 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1650 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1651 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1652 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1654 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1655 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1656 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1657 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1658 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1659 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1660 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1661 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1662 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1663 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1664 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1665 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1667 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1668 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1669 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1670 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1671 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
1672 not be an optional suffix, but part of the instruction. To be
1673 compatible, we accept either. */
1674 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1675 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1677 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1678 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1679 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1680 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1681 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1682 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1683 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1684 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1685 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1686 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1687 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1688 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1690 /* The implementation of the FIX instruction is broken on some
1691 assemblers, in that it accepts a precision specifier as well as a
1692 rounding specifier, despite the fact that this is meaningless.
1693 To be more compatible, we accept it as well, though of course it
1694 does not set any bits. */
1695 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1696 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1697 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1698 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1699 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1700 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1701 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1702 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1703 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1704 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1705 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1706 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1707 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1709 /* Instructions that were new with the real FPA, call them V2. */
1710 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1711 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1712 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1713 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1714 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1715 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1717 /* VFP V1xD (single precision). */
1718 /* Moves and type conversions. */
1719 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1720 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_reg_from_sp
},
1721 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_from_reg
},
1722 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD
, do_empty
},
1723 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1724 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1725 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1726 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1727 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1728 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1729 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_reg_from_ctrl
},
1730 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_ctrl_from_reg
},
1732 /* Memory operations. */
1733 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldst
},
1734 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldst
},
1735 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1736 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1737 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1738 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1739 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1740 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1741 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1742 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1743 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1744 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1745 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1746 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1747 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1748 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1749 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1750 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1752 /* Monadic operations. */
1753 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1754 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1755 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1757 /* Dyadic operations. */
1758 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1759 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1760 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1761 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1762 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1763 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1764 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1765 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1766 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1769 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1770 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_compare_z
},
1771 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1772 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_compare_z
},
1774 /* VFP V1 (Double precision). */
1775 /* Moves and type conversions. */
1776 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1777 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
1778 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1779 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1
, do_vfp_dp_from_reg
},
1780 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1
, do_vfp_dp_from_reg
},
1781 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1
, do_vfp_reg_from_dp
},
1782 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1
, do_vfp_reg_from_dp
},
1783 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
1784 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
1785 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1786 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1787 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1788 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1790 /* Memory operations. */
1791 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1
, do_vfp_dp_ldst
},
1792 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1
, do_vfp_dp_ldst
},
1793 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1794 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1795 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1796 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1797 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1798 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1799 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1800 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1802 /* Monadic operations. */
1803 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1804 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1805 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1807 /* Dyadic operations. */
1808 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1809 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1810 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1811 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1812 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1813 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1814 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1815 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1816 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1819 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1820 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_compare_z
},
1821 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1822 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1
, do_vfp_dp_compare_z
},
1825 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2
, do_vfp_sp_reg2
},
1826 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2
, do_vfp_sp_reg2
},
1827 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2
, do_vfp_dp_from_reg2
},
1828 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2
, do_vfp_reg2_from_dp
},
1830 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
1831 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE
, do_xsc_mia
},
1832 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1833 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1834 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1835 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1836 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1837 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE
, do_xsc_mar
},
1838 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE
, do_xsc_mra
},
1840 /* Intel Wireless MMX technology instructions. */
1841 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
1842 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
1843 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
1844 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
1845 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
1846 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
1847 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
1848 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
1849 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
1850 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
1851 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
1852 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
1853 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
1854 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
1855 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
1856 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
1857 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
1858 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
1859 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmcr
},
1860 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_tmcrr
},
1861 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
1862 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
1863 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
1864 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
1865 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
1866 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
1867 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
1868 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
1869 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
1870 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmrc
},
1871 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_tmrrc
},
1872 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
1873 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
1874 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
1875 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1876 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1877 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1878 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1879 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1880 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1881 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1882 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1883 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1884 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1885 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1886 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1887 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_waligni
},
1888 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1889 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1890 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1891 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1892 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1893 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1894 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1895 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1896 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1897 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1898 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1899 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1900 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1901 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1902 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1903 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1904 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1905 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1906 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1907 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
1908 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
1909 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
1910 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
1911 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1912 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1913 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1914 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1915 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1916 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1917 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1918 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1919 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1920 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1921 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1922 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1923 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1924 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1925 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1926 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1927 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1928 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1929 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wmov
},
1930 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1931 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1932 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1933 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1934 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1935 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1936 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1937 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1938 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1939 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1940 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1941 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1942 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1943 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1944 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1945 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1946 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1947 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1948 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1949 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1950 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1951 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wshufh
},
1952 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1953 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1954 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1955 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1956 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1957 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1958 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1959 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1960 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1961 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1962 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1963 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1964 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1965 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1966 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1967 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1968 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1969 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1970 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
1971 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
1972 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
1973 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
1974 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1975 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1976 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1977 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1978 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1979 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1980 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1981 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1982 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1983 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1984 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1985 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1986 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1987 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1988 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1989 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1990 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1991 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1992 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1993 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1994 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1995 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1996 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1997 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1998 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1999 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2000 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2001 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2002 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wzero
},
2004 /* Cirrus Maverick instructions. */
2005 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_1
},
2006 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_2
},
2007 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_3
},
2008 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_4
},
2009 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_1
},
2010 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_2
},
2011 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_3
},
2012 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_4
},
2013 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK
, do_mav_binops_2a
},
2014 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1a
},
2015 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK
, do_mav_binops_2b
},
2016 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1b
},
2017 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK
, do_mav_binops_2b
},
2018 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1b
},
2019 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK
, do_mav_binops_2c
},
2020 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1c
},
2021 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK
, do_mav_binops_2c
},
2022 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1c
},
2023 {"cfmval32", 0xee100610, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
2024 {"cfmv32al", 0xee000610, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
2025 {"cfmvam32", 0xee100630, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
2026 {"cfmv32am", 0xee000630, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
2027 {"cfmvah32", 0xee100650, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
2028 {"cfmv32ah", 0xee000650, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
2029 {"cfmva32", 0xee100670, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
2030 {"cfmv32a", 0xee000670, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
2031 {"cfmva64", 0xee100690, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3c
},
2032 {"cfmv64a", 0xee000690, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3d
},
2033 {"cfmvsc32", 0xee1006b0, 8, ARM_CEXT_MAVERICK
, do_mav_dspsc_1
},
2034 {"cfmv32sc", 0xee0006b0, 8, ARM_CEXT_MAVERICK
, do_mav_dspsc_2
},
2035 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
2036 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
2037 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1f
},
2038 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1g
},
2039 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1h
},
2040 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1i
},
2041 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1j
},
2042 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1k
},
2043 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1l
},
2044 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1m
},
2045 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK
, do_mav_binops_1l
},
2046 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK
, do_mav_binops_1m
},
2047 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK
, do_mav_triple_4a
},
2048 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK
, do_mav_triple_4b
},
2049 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK
, do_mav_shift_1
},
2050 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK
, do_mav_shift_2
},
2051 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5a
},
2052 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5b
},
2053 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5c
},
2054 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5d
},
2055 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
2056 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
2057 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
2058 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
2059 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
2060 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
2061 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
2062 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
2063 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
2064 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
2065 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1n
},
2066 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1o
},
2067 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1n
},
2068 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1o
},
2069 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2070 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
2071 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2072 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
2073 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2074 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
2075 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2076 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2077 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK
, do_mav_quad_6a
},
2078 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK
, do_mav_quad_6a
},
2079 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK
, do_mav_quad_6b
},
2080 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK
, do_mav_quad_6b
},
2083 /* Defines for various bits that we will want to toggle. */
2084 #define INST_IMMEDIATE 0x02000000
2085 #define OFFSET_REG 0x02000000
2086 #define HWOFFSET_IMM 0x00400000
2087 #define SHIFT_BY_REG 0x00000010
2088 #define PRE_INDEX 0x01000000
2089 #define INDEX_UP 0x00800000
2090 #define WRITE_BACK 0x00200000
2091 #define LDM_TYPE_2_OR_3 0x00400000
2093 #define LITERAL_MASK 0xf000f000
2094 #define OPCODE_MASK 0xfe1fffff
2095 #define V4_STR_BIT 0x00000020
2097 #define DATA_OP_SHIFT 21
2099 /* Codes to distinguish the arithmetic instructions. */
2100 #define OPCODE_AND 0
2101 #define OPCODE_EOR 1
2102 #define OPCODE_SUB 2
2103 #define OPCODE_RSB 3
2104 #define OPCODE_ADD 4
2105 #define OPCODE_ADC 5
2106 #define OPCODE_SBC 6
2107 #define OPCODE_RSC 7
2108 #define OPCODE_TST 8
2109 #define OPCODE_TEQ 9
2110 #define OPCODE_CMP 10
2111 #define OPCODE_CMN 11
2112 #define OPCODE_ORR 12
2113 #define OPCODE_MOV 13
2114 #define OPCODE_BIC 14
2115 #define OPCODE_MVN 15
2117 /* Thumb v1 (ARMv4T). */
2118 static void do_t_nop
PARAMS ((char *));
2119 static void do_t_arit
PARAMS ((char *));
2120 static void do_t_add
PARAMS ((char *));
2121 static void do_t_asr
PARAMS ((char *));
2122 static void do_t_branch9
PARAMS ((char *));
2123 static void do_t_branch12
PARAMS ((char *));
2124 static void do_t_branch23
PARAMS ((char *));
2125 static void do_t_bx
PARAMS ((char *));
2126 static void do_t_compare
PARAMS ((char *));
2127 static void do_t_ldmstm
PARAMS ((char *));
2128 static void do_t_ldr
PARAMS ((char *));
2129 static void do_t_ldrb
PARAMS ((char *));
2130 static void do_t_ldrh
PARAMS ((char *));
2131 static void do_t_lds
PARAMS ((char *));
2132 static void do_t_lsl
PARAMS ((char *));
2133 static void do_t_lsr
PARAMS ((char *));
2134 static void do_t_mov
PARAMS ((char *));
2135 static void do_t_push_pop
PARAMS ((char *));
2136 static void do_t_str
PARAMS ((char *));
2137 static void do_t_strb
PARAMS ((char *));
2138 static void do_t_strh
PARAMS ((char *));
2139 static void do_t_sub
PARAMS ((char *));
2140 static void do_t_swi
PARAMS ((char *));
2141 static void do_t_adr
PARAMS ((char *));
2143 /* Thumb v2 (ARMv5T). */
2144 static void do_t_blx
PARAMS ((char *));
2145 static void do_t_bkpt
PARAMS ((char *));
2147 #define T_OPCODE_MUL 0x4340
2148 #define T_OPCODE_TST 0x4200
2149 #define T_OPCODE_CMN 0x42c0
2150 #define T_OPCODE_NEG 0x4240
2151 #define T_OPCODE_MVN 0x43c0
2153 #define T_OPCODE_ADD_R3 0x1800
2154 #define T_OPCODE_SUB_R3 0x1a00
2155 #define T_OPCODE_ADD_HI 0x4400
2156 #define T_OPCODE_ADD_ST 0xb000
2157 #define T_OPCODE_SUB_ST 0xb080
2158 #define T_OPCODE_ADD_SP 0xa800
2159 #define T_OPCODE_ADD_PC 0xa000
2160 #define T_OPCODE_ADD_I8 0x3000
2161 #define T_OPCODE_SUB_I8 0x3800
2162 #define T_OPCODE_ADD_I3 0x1c00
2163 #define T_OPCODE_SUB_I3 0x1e00
2165 #define T_OPCODE_ASR_R 0x4100
2166 #define T_OPCODE_LSL_R 0x4080
2167 #define T_OPCODE_LSR_R 0x40c0
2168 #define T_OPCODE_ASR_I 0x1000
2169 #define T_OPCODE_LSL_I 0x0000
2170 #define T_OPCODE_LSR_I 0x0800
2172 #define T_OPCODE_MOV_I8 0x2000
2173 #define T_OPCODE_CMP_I8 0x2800
2174 #define T_OPCODE_CMP_LR 0x4280
2175 #define T_OPCODE_MOV_HR 0x4600
2176 #define T_OPCODE_CMP_HR 0x4500
2178 #define T_OPCODE_LDR_PC 0x4800
2179 #define T_OPCODE_LDR_SP 0x9800
2180 #define T_OPCODE_STR_SP 0x9000
2181 #define T_OPCODE_LDR_IW 0x6800
2182 #define T_OPCODE_STR_IW 0x6000
2183 #define T_OPCODE_LDR_IH 0x8800
2184 #define T_OPCODE_STR_IH 0x8000
2185 #define T_OPCODE_LDR_IB 0x7800
2186 #define T_OPCODE_STR_IB 0x7000
2187 #define T_OPCODE_LDR_RW 0x5800
2188 #define T_OPCODE_STR_RW 0x5000
2189 #define T_OPCODE_LDR_RH 0x5a00
2190 #define T_OPCODE_STR_RH 0x5200
2191 #define T_OPCODE_LDR_RB 0x5c00
2192 #define T_OPCODE_STR_RB 0x5400
2194 #define T_OPCODE_PUSH 0xb400
2195 #define T_OPCODE_POP 0xbc00
2197 #define T_OPCODE_BRANCH 0xe7fe
2199 static int thumb_reg
PARAMS ((char ** str
, int hi_lo
));
2201 #define THUMB_SIZE 2 /* Size of thumb instruction. */
2202 #define THUMB_REG_LO 0x1
2203 #define THUMB_REG_HI 0x2
2204 #define THUMB_REG_ANY 0x3
2206 #define THUMB_H1 0x0080
2207 #define THUMB_H2 0x0040
2213 #define THUMB_MOVE 0
2214 #define THUMB_COMPARE 1
2216 #define THUMB_LOAD 0
2217 #define THUMB_STORE 1
2219 #define THUMB_PP_PC_LR 0x0100
2221 /* These three are used for immediate shifts, do not alter. */
2222 #define THUMB_WORD 2
2223 #define THUMB_HALFWORD 1
2224 #define THUMB_BYTE 0
2228 /* Basic string to match. */
2229 const char * template;
2231 /* Basic instruction code. */
2232 unsigned long value
;
2236 /* Which CPU variants this exists for. */
2237 unsigned long variant
;
2239 /* Function to call to parse args. */
2240 void (* parms
) PARAMS ((char *));
2243 static const struct thumb_opcode tinsns
[] =
2245 /* Thumb v1 (ARMv4T). */
2246 {"adc", 0x4140, 2, ARM_EXT_V4T
, do_t_arit
},
2247 {"add", 0x0000, 2, ARM_EXT_V4T
, do_t_add
},
2248 {"and", 0x4000, 2, ARM_EXT_V4T
, do_t_arit
},
2249 {"asr", 0x0000, 2, ARM_EXT_V4T
, do_t_asr
},
2250 {"b", T_OPCODE_BRANCH
, 2, ARM_EXT_V4T
, do_t_branch12
},
2251 {"beq", 0xd0fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2252 {"bne", 0xd1fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2253 {"bcs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2254 {"bhs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2255 {"bcc", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2256 {"bul", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2257 {"blo", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2258 {"bmi", 0xd4fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2259 {"bpl", 0xd5fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2260 {"bvs", 0xd6fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2261 {"bvc", 0xd7fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2262 {"bhi", 0xd8fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2263 {"bls", 0xd9fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2264 {"bge", 0xdafe, 2, ARM_EXT_V4T
, do_t_branch9
},
2265 {"blt", 0xdbfe, 2, ARM_EXT_V4T
, do_t_branch9
},
2266 {"bgt", 0xdcfe, 2, ARM_EXT_V4T
, do_t_branch9
},
2267 {"ble", 0xddfe, 2, ARM_EXT_V4T
, do_t_branch9
},
2268 {"bal", 0xdefe, 2, ARM_EXT_V4T
, do_t_branch9
},
2269 {"bic", 0x4380, 2, ARM_EXT_V4T
, do_t_arit
},
2270 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T
, do_t_branch23
},
2271 {"bx", 0x4700, 2, ARM_EXT_V4T
, do_t_bx
},
2272 {"cmn", T_OPCODE_CMN
, 2, ARM_EXT_V4T
, do_t_arit
},
2273 {"cmp", 0x0000, 2, ARM_EXT_V4T
, do_t_compare
},
2274 {"eor", 0x4040, 2, ARM_EXT_V4T
, do_t_arit
},
2275 {"ldmia", 0xc800, 2, ARM_EXT_V4T
, do_t_ldmstm
},
2276 {"ldr", 0x0000, 2, ARM_EXT_V4T
, do_t_ldr
},
2277 {"ldrb", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrb
},
2278 {"ldrh", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrh
},
2279 {"ldrsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
2280 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
2281 {"ldsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
2282 {"ldsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
2283 {"lsl", 0x0000, 2, ARM_EXT_V4T
, do_t_lsl
},
2284 {"lsr", 0x0000, 2, ARM_EXT_V4T
, do_t_lsr
},
2285 {"mov", 0x0000, 2, ARM_EXT_V4T
, do_t_mov
},
2286 {"mul", T_OPCODE_MUL
, 2, ARM_EXT_V4T
, do_t_arit
},
2287 {"mvn", T_OPCODE_MVN
, 2, ARM_EXT_V4T
, do_t_arit
},
2288 {"neg", T_OPCODE_NEG
, 2, ARM_EXT_V4T
, do_t_arit
},
2289 {"orr", 0x4300, 2, ARM_EXT_V4T
, do_t_arit
},
2290 {"pop", 0xbc00, 2, ARM_EXT_V4T
, do_t_push_pop
},
2291 {"push", 0xb400, 2, ARM_EXT_V4T
, do_t_push_pop
},
2292 {"ror", 0x41c0, 2, ARM_EXT_V4T
, do_t_arit
},
2293 {"sbc", 0x4180, 2, ARM_EXT_V4T
, do_t_arit
},
2294 {"stmia", 0xc000, 2, ARM_EXT_V4T
, do_t_ldmstm
},
2295 {"str", 0x0000, 2, ARM_EXT_V4T
, do_t_str
},
2296 {"strb", 0x0000, 2, ARM_EXT_V4T
, do_t_strb
},
2297 {"strh", 0x0000, 2, ARM_EXT_V4T
, do_t_strh
},
2298 {"swi", 0xdf00, 2, ARM_EXT_V4T
, do_t_swi
},
2299 {"sub", 0x0000, 2, ARM_EXT_V4T
, do_t_sub
},
2300 {"tst", T_OPCODE_TST
, 2, ARM_EXT_V4T
, do_t_arit
},
2302 {"adr", 0x0000, 2, ARM_EXT_V4T
, do_t_adr
},
2303 {"nop", 0x46C0, 2, ARM_EXT_V4T
, do_t_nop
}, /* mov r8,r8 */
2304 /* Thumb v2 (ARMv5T). */
2305 {"blx", 0, 0, ARM_EXT_V5T
, do_t_blx
},
2306 {"bkpt", 0xbe00, 2, ARM_EXT_V5T
, do_t_bkpt
},
2309 #define BAD_ARGS _("bad arguments to instruction")
2310 #define BAD_PC _("r15 not allowed here")
2311 #define BAD_COND _("instruction is not conditional")
2312 #define ERR_NO_ACCUM _("acc0 expected")
2314 static struct hash_control
* arm_ops_hsh
= NULL
;
2315 static struct hash_control
* arm_tops_hsh
= NULL
;
2316 static struct hash_control
* arm_cond_hsh
= NULL
;
2317 static struct hash_control
* arm_shift_hsh
= NULL
;
2318 static struct hash_control
* arm_psr_hsh
= NULL
;
2320 /* This table describes all the machine specific pseudo-ops the assembler
2321 has to support. The fields are:
2322 pseudo-op name without dot
2323 function to call to execute this pseudo-op
2324 Integer arg to pass to the function. */
2326 static void s_req
PARAMS ((int));
2327 static void s_align
PARAMS ((int));
2328 static void s_bss
PARAMS ((int));
2329 static void s_even
PARAMS ((int));
2330 static void s_ltorg
PARAMS ((int));
2331 static void s_arm
PARAMS ((int));
2332 static void s_thumb
PARAMS ((int));
2333 static void s_code
PARAMS ((int));
2334 static void s_force_thumb
PARAMS ((int));
2335 static void s_thumb_func
PARAMS ((int));
2336 static void s_thumb_set
PARAMS ((int));
2338 static void s_arm_elf_cons
PARAMS ((int));
2341 static int my_get_expression
PARAMS ((expressionS
*, char **));
2343 const pseudo_typeS md_pseudo_table
[] =
2345 /* Never called becasue '.req' does not start line. */
2346 { "req", s_req
, 0 },
2347 { "bss", s_bss
, 0 },
2348 { "align", s_align
, 0 },
2349 { "arm", s_arm
, 0 },
2350 { "thumb", s_thumb
, 0 },
2351 { "code", s_code
, 0 },
2352 { "force_thumb", s_force_thumb
, 0 },
2353 { "thumb_func", s_thumb_func
, 0 },
2354 { "thumb_set", s_thumb_set
, 0 },
2355 { "even", s_even
, 0 },
2356 { "ltorg", s_ltorg
, 0 },
2357 { "pool", s_ltorg
, 0 },
2359 { "word", s_arm_elf_cons
, 4 },
2360 { "long", s_arm_elf_cons
, 4 },
2364 { "extend", float_cons
, 'x' },
2365 { "ldouble", float_cons
, 'x' },
2366 { "packed", float_cons
, 'p' },
2370 /* Other internal functions. */
2371 static int arm_parse_extension
PARAMS ((char *, int *));
2372 static int arm_parse_cpu
PARAMS ((char *));
2373 static int arm_parse_arch
PARAMS ((char *));
2374 static int arm_parse_fpu
PARAMS ((char *));
2375 #if defined OBJ_COFF || defined OBJ_ELF
2376 static void arm_add_note
PARAMS ((const char *, const char *, unsigned int));
2379 /* Stuff needed to resolve the label ambiguity
2389 symbolS
* last_label_seen
;
2390 static int label_is_thumb_function_name
= FALSE
;
2392 /* Literal Pool stuff. */
2394 #define MAX_LITERAL_POOL_SIZE 1024
2396 /* Literal pool structure. Held on a per-section
2397 and per-sub-section basis. */
2398 typedef struct literal_pool
2400 expressionS literals
[MAX_LITERAL_POOL_SIZE
];
2401 unsigned int next_free_entry
;
2405 subsegT sub_section
;
2406 struct literal_pool
* next
;
2409 /* Pointer to a linked list of literal pools. */
2410 literal_pool
* list_of_pools
= NULL
;
2412 static literal_pool
* find_literal_pool
PARAMS ((void));
2413 static literal_pool
* find_or_make_literal_pool
PARAMS ((void));
2415 static literal_pool
*
2416 find_literal_pool ()
2418 literal_pool
* pool
;
2420 for (pool
= list_of_pools
; pool
!= NULL
; pool
= pool
->next
)
2422 if (pool
->section
== now_seg
2423 && pool
->sub_section
== now_subseg
)
2430 static literal_pool
*
2431 find_or_make_literal_pool ()
2433 /* Next literal pool ID number. */
2434 static unsigned int latest_pool_num
= 1;
2435 literal_pool
* pool
;
2437 pool
= find_literal_pool ();
2441 /* Create a new pool. */
2442 pool
= (literal_pool
*) xmalloc (sizeof (* pool
));
2446 pool
->next_free_entry
= 0;
2447 pool
->section
= now_seg
;
2448 pool
->sub_section
= now_subseg
;
2449 pool
->next
= list_of_pools
;
2450 pool
->symbol
= NULL
;
2452 /* Add it to the list. */
2453 list_of_pools
= pool
;
2456 /* New pools, and emptied pools, will have a NULL symbol. */
2457 if (pool
->symbol
== NULL
)
2459 pool
->symbol
= symbol_create (FAKE_LABEL_NAME
, undefined_section
,
2460 (valueT
) 0, &zero_address_frag
);
2461 pool
->id
= latest_pool_num
++;
2468 /* Add the literal in the global 'inst'
2469 structure to the relevent literal pool. */
2473 literal_pool
* pool
;
2476 pool
= find_or_make_literal_pool ();
2478 /* Check if this literal value is already in the pool. */
2479 for (entry
= 0; entry
< pool
->next_free_entry
; entry
++)
2481 if ((pool
->literals
[entry
].X_op
== inst
.reloc
.exp
.X_op
)
2482 && (inst
.reloc
.exp
.X_op
== O_constant
)
2483 && (pool
->literals
[entry
].X_add_number
2484 == inst
.reloc
.exp
.X_add_number
)
2485 && (pool
->literals
[entry
].X_unsigned
2486 == inst
.reloc
.exp
.X_unsigned
))
2489 if ((pool
->literals
[entry
].X_op
== inst
.reloc
.exp
.X_op
)
2490 && (inst
.reloc
.exp
.X_op
== O_symbol
)
2491 && (pool
->literals
[entry
].X_add_number
2492 == inst
.reloc
.exp
.X_add_number
)
2493 && (pool
->literals
[entry
].X_add_symbol
2494 == inst
.reloc
.exp
.X_add_symbol
)
2495 && (pool
->literals
[entry
].X_op_symbol
2496 == inst
.reloc
.exp
.X_op_symbol
))
2500 /* Do we need to create a new entry? */
2501 if (entry
== pool
->next_free_entry
)
2503 if (entry
>= MAX_LITERAL_POOL_SIZE
)
2505 inst
.error
= _("literal pool overflow");
2509 pool
->literals
[entry
] = inst
.reloc
.exp
;
2510 pool
->next_free_entry
+= 1;
2513 inst
.reloc
.exp
.X_op
= O_symbol
;
2514 inst
.reloc
.exp
.X_add_number
= ((int) entry
) * 4 - 8;
2515 inst
.reloc
.exp
.X_add_symbol
= pool
->symbol
;
2520 /* Can't use symbol_new here, so have to create a symbol and then at
2521 a later date assign it a value. Thats what these functions do. */
2524 symbol_locate (symbolP
, name
, segment
, valu
, frag
)
2526 const char * name
; /* It is copied, the caller can modify. */
2527 segT segment
; /* Segment identifier (SEG_<something>). */
2528 valueT valu
; /* Symbol value. */
2529 fragS
* frag
; /* Associated fragment. */
2531 unsigned int name_length
;
2532 char * preserved_copy_of_name
;
2534 name_length
= strlen (name
) + 1; /* +1 for \0. */
2535 obstack_grow (¬es
, name
, name_length
);
2536 preserved_copy_of_name
= obstack_finish (¬es
);
2537 #ifdef STRIP_UNDERSCORE
2538 if (preserved_copy_of_name
[0] == '_')
2539 preserved_copy_of_name
++;
2542 #ifdef tc_canonicalize_symbol_name
2543 preserved_copy_of_name
=
2544 tc_canonicalize_symbol_name (preserved_copy_of_name
);
2547 S_SET_NAME (symbolP
, preserved_copy_of_name
);
2549 S_SET_SEGMENT (symbolP
, segment
);
2550 S_SET_VALUE (symbolP
, valu
);
2551 symbol_clear_list_pointers (symbolP
);
2553 symbol_set_frag (symbolP
, frag
);
2555 /* Link to end of symbol chain. */
2557 extern int symbol_table_frozen
;
2558 if (symbol_table_frozen
)
2562 symbol_append (symbolP
, symbol_lastP
, & symbol_rootP
, & symbol_lastP
);
2564 obj_symbol_new_hook (symbolP
);
2566 #ifdef tc_symbol_new_hook
2567 tc_symbol_new_hook (symbolP
);
2571 verify_symbol_chain (symbol_rootP
, symbol_lastP
);
2572 #endif /* DEBUG_SYMS */
2575 /* Check that an immediate is valid.
2576 If so, convert it to the right format. */
2579 validate_immediate (val
)
2585 #define rotate_left(v, n) (v << n | v >> (32 - n))
2587 for (i
= 0; i
< 32; i
+= 2)
2588 if ((a
= rotate_left (val
, i
)) <= 0xff)
2589 return a
| (i
<< 7); /* 12-bit pack: [shift-cnt,const]. */
2594 /* Check to see if an immediate can be computed as two seperate immediate
2595 values, added together. We already know that this value cannot be
2596 computed by just one ARM instruction. */
2599 validate_immediate_twopart (val
, highpart
)
2601 unsigned int * highpart
;
2606 for (i
= 0; i
< 32; i
+= 2)
2607 if (((a
= rotate_left (val
, i
)) & 0xff) != 0)
2613 * highpart
= (a
>> 8) | ((i
+ 24) << 7);
2615 else if (a
& 0xff0000)
2619 * highpart
= (a
>> 16) | ((i
+ 16) << 7);
2623 assert (a
& 0xff000000);
2624 * highpart
= (a
>> 24) | ((i
+ 8) << 7);
2627 return (a
& 0xff) | (i
<< 7);
2634 validate_offset_imm (val
, hwse
)
2638 if ((hwse
&& val
> 255) || val
> 4095)
2645 int a ATTRIBUTE_UNUSED
;
2647 as_bad (_("invalid syntax for .req directive"));
2652 int ignore ATTRIBUTE_UNUSED
;
2654 /* We don't support putting frags in the BSS segment, we fake it by
2655 marking in_bss, then looking at s_skip for clues. */
2656 subseg_set (bss_section
, 0);
2657 demand_empty_rest_of_line ();
2662 int ignore ATTRIBUTE_UNUSED
;
2664 /* Never make frag if expect extra pass. */
2666 frag_align (1, 0, 0);
2668 record_alignment (now_seg
, 1);
2670 demand_empty_rest_of_line ();
2675 int ignored ATTRIBUTE_UNUSED
;
2678 literal_pool
* pool
;
2681 pool
= find_literal_pool ();
2683 || pool
->symbol
== NULL
2684 || pool
->next_free_entry
== 0)
2687 /* Align pool as you have word accesses.
2688 Only make a frag if we have to. */
2690 frag_align (2, 0, 0);
2692 record_alignment (now_seg
, 2);
2694 sprintf (sym_name
, "$$lit_\002%x", pool
->id
);
2696 symbol_locate (pool
->symbol
, sym_name
, now_seg
,
2697 (valueT
) frag_now_fix (), frag_now
);
2698 symbol_table_insert (pool
->symbol
);
2700 ARM_SET_THUMB (pool
->symbol
, thumb_mode
);
2702 #if defined OBJ_COFF || defined OBJ_ELF
2703 ARM_SET_INTERWORK (pool
->symbol
, support_interwork
);
2706 for (entry
= 0; entry
< pool
->next_free_entry
; entry
++)
2707 /* First output the expression in the instruction to the pool. */
2708 emit_expr (&(pool
->literals
[entry
]), 4); /* .word */
2710 /* Mark the pool as empty. */
2711 pool
->next_free_entry
= 0;
2712 pool
->symbol
= NULL
;
2715 /* Same as s_align_ptwo but align 0 => align 2. */
2719 int unused ATTRIBUTE_UNUSED
;
2722 register long temp_fill
;
2723 long max_alignment
= 15;
2725 temp
= get_absolute_expression ();
2726 if (temp
> max_alignment
)
2727 as_bad (_("alignment too large: %d assumed"), temp
= max_alignment
);
2730 as_bad (_("alignment negative. 0 assumed."));
2734 if (*input_line_pointer
== ',')
2736 input_line_pointer
++;
2737 temp_fill
= get_absolute_expression ();
2745 /* Only make a frag if we HAVE to. */
2746 if (temp
&& !need_pass_2
)
2747 frag_align (temp
, (int) temp_fill
, 0);
2748 demand_empty_rest_of_line ();
2750 record_alignment (now_seg
, temp
);
2754 s_force_thumb (ignore
)
2755 int ignore ATTRIBUTE_UNUSED
;
2757 /* If we are not already in thumb mode go into it, EVEN if
2758 the target processor does not support thumb instructions.
2759 This is used by gcc/config/arm/lib1funcs.asm for example
2760 to compile interworking support functions even if the
2761 target processor should not support interworking. */
2766 record_alignment (now_seg
, 1);
2769 demand_empty_rest_of_line ();
2773 s_thumb_func (ignore
)
2774 int ignore ATTRIBUTE_UNUSED
;
2779 /* The following label is the name/address of the start of a Thumb function.
2780 We need to know this for the interworking support. */
2781 label_is_thumb_function_name
= TRUE
;
2783 demand_empty_rest_of_line ();
2786 /* Perform a .set directive, but also mark the alias as
2787 being a thumb function. */
2793 /* XXX the following is a duplicate of the code for s_set() in read.c
2794 We cannot just call that code as we need to get at the symbol that
2796 register char * name
;
2797 register char delim
;
2798 register char * end_name
;
2799 register symbolS
* symbolP
;
2801 /* Especial apologies for the random logic:
2802 This just grew, and could be parsed much more simply!
2804 name
= input_line_pointer
;
2805 delim
= get_symbol_end ();
2806 end_name
= input_line_pointer
;
2811 if (*input_line_pointer
!= ',')
2814 as_bad (_("expected comma after name \"%s\""), name
);
2816 ignore_rest_of_line ();
2820 input_line_pointer
++;
2823 if (name
[0] == '.' && name
[1] == '\0')
2825 /* XXX - this should not happen to .thumb_set. */
2829 if ((symbolP
= symbol_find (name
)) == NULL
2830 && (symbolP
= md_undefined_symbol (name
)) == NULL
)
2833 /* When doing symbol listings, play games with dummy fragments living
2834 outside the normal fragment chain to record the file and line info
2836 if (listing
& LISTING_SYMBOLS
)
2838 extern struct list_info_struct
* listing_tail
;
2839 fragS
* dummy_frag
= (fragS
*) xmalloc (sizeof (fragS
));
2841 memset (dummy_frag
, 0, sizeof (fragS
));
2842 dummy_frag
->fr_type
= rs_fill
;
2843 dummy_frag
->line
= listing_tail
;
2844 symbolP
= symbol_new (name
, undefined_section
, 0, dummy_frag
);
2845 dummy_frag
->fr_symbol
= symbolP
;
2849 symbolP
= symbol_new (name
, undefined_section
, 0, &zero_address_frag
);
2852 /* "set" symbols are local unless otherwise specified. */
2853 SF_SET_LOCAL (symbolP
);
2854 #endif /* OBJ_COFF */
2855 } /* Make a new symbol. */
2857 symbol_table_insert (symbolP
);
2862 && S_IS_DEFINED (symbolP
)
2863 && S_GET_SEGMENT (symbolP
) != reg_section
)
2864 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP
));
2866 pseudo_set (symbolP
);
2868 demand_empty_rest_of_line ();
2870 /* XXX Now we come to the Thumb specific bit of code. */
2872 THUMB_SET_FUNC (symbolP
, 1);
2873 ARM_SET_THUMB (symbolP
, 1);
2874 #if defined OBJ_ELF || defined OBJ_COFF
2875 ARM_SET_INTERWORK (symbolP
, support_interwork
);
2880 opcode_select (width
)
2888 if (! (cpu_variant
& ARM_EXT_V4T
))
2889 as_bad (_("selected processor does not support THUMB opcodes"));
2892 /* No need to force the alignment, since we will have been
2893 coming from ARM mode, which is word-aligned. */
2894 record_alignment (now_seg
, 1);
2901 if ((cpu_variant
& ARM_ALL
) == ARM_EXT_V4T
)
2902 as_bad (_("selected processor does not support ARM opcodes"));
2907 frag_align (2, 0, 0);
2909 record_alignment (now_seg
, 1);
2914 as_bad (_("invalid instruction size selected (%d)"), width
);
2920 int ignore ATTRIBUTE_UNUSED
;
2923 demand_empty_rest_of_line ();
2928 int ignore ATTRIBUTE_UNUSED
;
2931 demand_empty_rest_of_line ();
2936 int unused ATTRIBUTE_UNUSED
;
2940 temp
= get_absolute_expression ();
2945 opcode_select (temp
);
2949 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp
);
2957 skip_whitespace (str
);
2959 if (*str
!= '\0' && !inst
.error
)
2960 inst
.error
= _("garbage following instruction");
2964 skip_past_comma (str
)
2967 char * p
= * str
, c
;
2970 while ((c
= *p
) == ' ' || c
== ',')
2973 if (c
== ',' && comma
++)
2981 return comma
? SUCCESS
: FAIL
;
2984 /* A standard register must be given at this point.
2985 SHIFT is the place to put it in inst.instruction.
2986 Restores input start point on error.
2987 Returns the reg#, or FAIL. */
2990 reg_required_here (str
, shift
)
2994 static char buff
[128]; /* XXX */
2996 char * start
= * str
;
2998 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_RN
].htab
)) != FAIL
)
3001 inst
.instruction
|= reg
<< shift
;
3005 /* Restore the start point, we may have got a reg of the wrong class. */
3008 /* In the few cases where we might be able to accept something else
3009 this error can be overridden. */
3010 sprintf (buff
, _("register expected, not '%.100s'"), start
);
3016 /* A Intel Wireless MMX technology register
3017 must be given at this point.
3018 Shift is the place to put it in inst.instruction.
3019 Restores input start point on err.
3020 Returns the reg#, or FAIL. */
3023 wreg_required_here (str
, shift
, reg_type
)
3026 enum wreg_type reg_type
;
3028 static char buff
[128];
3030 char * start
= *str
;
3032 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_IWMMXT
].htab
)) != FAIL
)
3034 if (wr_register (reg
)
3035 && (reg_type
== IWMMXT_REG_WR
|| reg_type
== IWMMXT_REG_WR_OR_WC
))
3038 inst
.instruction
|= (reg
^ WR_PREFIX
) << shift
;
3041 else if (wc_register (reg
)
3042 && (reg_type
== IWMMXT_REG_WC
|| reg_type
== IWMMXT_REG_WR_OR_WC
))
3045 inst
.instruction
|= (reg
^ WC_PREFIX
) << shift
;
3048 else if ((wcg_register (reg
) && reg_type
== IWMMXT_REG_WCG
))
3051 inst
.instruction
|= ((reg
^ WC_PREFIX
) - 8) << shift
;
3056 /* Restore the start point, we may have got a reg of the wrong class. */
3059 /* In the few cases where we might be able to accept
3060 something else this error can be overridden. */
3061 sprintf (buff
, _("Intel Wireless MMX technology register expected, not '%.100s'"), start
);
3067 static const struct asm_psr
*
3069 register char ** ccp
;
3071 char * start
= * ccp
;
3074 const struct asm_psr
* psr
;
3078 /* Skip to the end of the next word in the input stream. */
3083 while (ISALPHA (c
) || c
== '_');
3085 /* Terminate the word. */
3088 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
3089 feature for ease of use and backwards compatibility. */
3090 if (!strncmp (start
, "cpsr", 4))
3091 strncpy (start
, "CPSR", 4);
3092 else if (!strncmp (start
, "spsr", 4))
3093 strncpy (start
, "SPSR", 4);
3095 /* Now locate the word in the psr hash table. */
3096 psr
= (const struct asm_psr
*) hash_find (arm_psr_hsh
, start
);
3098 /* Restore the input stream. */
3101 /* If we found a valid match, advance the
3102 stream pointer past the end of the word. */
3108 /* Parse the input looking for a PSR flag. */
3111 psr_required_here (str
)
3114 char * start
= * str
;
3115 const struct asm_psr
* psr
;
3117 psr
= arm_psr_parse (str
);
3121 /* If this is the SPSR that is being modified, set the R bit. */
3123 inst
.instruction
|= SPSR_BIT
;
3125 /* Set the psr flags in the MSR instruction. */
3126 inst
.instruction
|= psr
->field
<< PSR_SHIFT
;
3131 /* In the few cases where we might be able to accept
3132 something else this error can be overridden. */
3133 inst
.error
= _("flag for {c}psr instruction expected");
3135 /* Restore the start point. */
3141 co_proc_number (str
)
3144 int processor
, pchar
;
3147 skip_whitespace (*str
);
3150 /* The data sheet seems to imply that just a number on its own is valid
3151 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
3153 if ((processor
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CP
].htab
))
3159 if (pchar
>= '0' && pchar
<= '9')
3161 processor
= pchar
- '0';
3162 if (**str
>= '0' && **str
<= '9')
3164 processor
= processor
* 10 + *(*str
)++ - '0';
3167 inst
.error
= _("illegal co-processor number");
3174 inst
.error
= _("bad or missing co-processor number");
3179 inst
.instruction
|= processor
<< 8;
3184 cp_opc_expr (str
, where
, length
)
3191 skip_whitespace (* str
);
3193 memset (&expr
, '\0', sizeof (expr
));
3195 if (my_get_expression (&expr
, str
))
3197 if (expr
.X_op
!= O_constant
)
3199 inst
.error
= _("bad or missing expression");
3203 if ((expr
.X_add_number
& ((1 << length
) - 1)) != expr
.X_add_number
)
3205 inst
.error
= _("immediate co-processor expression too large");
3209 inst
.instruction
|= expr
.X_add_number
<< where
;
3214 cp_reg_required_here (str
, where
)
3219 char * start
= *str
;
3221 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CN
].htab
)) != FAIL
)
3223 inst
.instruction
|= reg
<< where
;
3227 /* In the few cases where we might be able to accept something else
3228 this error can be overridden. */
3229 inst
.error
= _("co-processor register expected");
3231 /* Restore the start point. */
3237 fp_reg_required_here (str
, where
)
3242 char * start
= * str
;
3244 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_FN
].htab
)) != FAIL
)
3246 inst
.instruction
|= reg
<< where
;
3250 /* In the few cases where we might be able to accept something else
3251 this error can be overridden. */
3252 inst
.error
= _("floating point register expected");
3254 /* Restore the start point. */
3260 cp_address_offset (str
)
3265 skip_whitespace (* str
);
3267 if (! is_immediate_prefix (**str
))
3269 inst
.error
= _("immediate expression expected");
3275 if (my_get_expression (& inst
.reloc
.exp
, str
))
3278 if (inst
.reloc
.exp
.X_op
== O_constant
)
3280 offset
= inst
.reloc
.exp
.X_add_number
;
3284 inst
.error
= _("co-processor address must be word aligned");
3288 if (offset
> 1023 || offset
< -1023)
3290 inst
.error
= _("offset too large");
3295 inst
.instruction
|= INDEX_UP
;
3299 inst
.instruction
|= offset
>> 2;
3302 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
3308 cp_address_required_here (str
, wb_ok
)
3321 skip_whitespace (p
);
3323 if ((reg
= reg_required_here (& p
, 16)) == FAIL
)
3326 skip_whitespace (p
);
3332 if (wb_ok
&& skip_past_comma (& p
) == SUCCESS
)
3335 write_back
= WRITE_BACK
;
3339 inst
.error
= _("pc may not be used in post-increment");
3343 if (cp_address_offset (& p
) == FAIL
)
3347 pre_inc
= PRE_INDEX
| INDEX_UP
;
3351 /* '['Rn, #expr']'[!] */
3353 if (skip_past_comma (& p
) == FAIL
)
3355 inst
.error
= _("pre-indexed expression expected");
3359 pre_inc
= PRE_INDEX
;
3361 if (cp_address_offset (& p
) == FAIL
)
3364 skip_whitespace (p
);
3368 inst
.error
= _("missing ]");
3372 skip_whitespace (p
);
3374 if (wb_ok
&& *p
== '!')
3378 inst
.error
= _("pc may not be used with write-back");
3383 write_back
= WRITE_BACK
;
3389 if (my_get_expression (&inst
.reloc
.exp
, &p
))
3392 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
3393 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
3394 inst
.reloc
.pc_rel
= 1;
3395 inst
.instruction
|= (REG_PC
<< 16);
3396 pre_inc
= PRE_INDEX
;
3399 inst
.instruction
|= write_back
| pre_inc
;
3405 cp_byte_address_offset (str
)
3410 skip_whitespace (* str
);
3412 if (! is_immediate_prefix (**str
))
3414 inst
.error
= _("immediate expression expected");
3420 if (my_get_expression (& inst
.reloc
.exp
, str
))
3423 if (inst
.reloc
.exp
.X_op
== O_constant
)
3425 offset
= inst
.reloc
.exp
.X_add_number
;
3427 if (offset
> 255 || offset
< -255)
3429 inst
.error
= _("offset too large");
3434 inst
.instruction
|= INDEX_UP
;
3438 inst
.instruction
|= offset
;
3441 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM_S2
;
3447 cp_byte_address_required_here (str
)
3459 skip_whitespace (p
);
3461 if ((reg
= reg_required_here (& p
, 16)) == FAIL
)
3464 skip_whitespace (p
);
3470 if (skip_past_comma (& p
) == SUCCESS
)
3473 write_back
= WRITE_BACK
;
3477 inst
.error
= _("pc may not be used in post-increment");
3481 if (cp_byte_address_offset (& p
) == FAIL
)
3485 pre_inc
= PRE_INDEX
| INDEX_UP
;
3489 /* '['Rn, #expr']'[!] */
3491 if (skip_past_comma (& p
) == FAIL
)
3493 inst
.error
= _("pre-indexed expression expected");
3497 pre_inc
= PRE_INDEX
;
3499 if (cp_byte_address_offset (& p
) == FAIL
)
3502 skip_whitespace (p
);
3506 inst
.error
= _("missing ]");
3510 skip_whitespace (p
);
3516 inst
.error
= _("pc may not be used with write-back");
3521 write_back
= WRITE_BACK
;
3527 if (my_get_expression (&inst
.reloc
.exp
, &p
))
3530 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM_S2
;
3531 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
3532 inst
.reloc
.pc_rel
= 1;
3533 inst
.instruction
|= (REG_PC
<< 16);
3534 pre_inc
= PRE_INDEX
;
3537 inst
.instruction
|= write_back
| pre_inc
;
3546 /* Do nothing really. */
3557 /* Only one syntax. */
3558 skip_whitespace (str
);
3560 if (reg_required_here (&str
, 12) == FAIL
)
3562 inst
.error
= BAD_ARGS
;
3566 if (skip_past_comma (&str
) == FAIL
)
3568 inst
.error
= _("comma expected after register name");
3572 skip_whitespace (str
);
3574 if ( strcmp (str
, "CPSR") == 0
3575 || strcmp (str
, "SPSR") == 0
3576 /* Lower case versions for backwards compatability. */
3577 || strcmp (str
, "cpsr") == 0
3578 || strcmp (str
, "spsr") == 0)
3581 /* This is for backwards compatability with older toolchains. */
3582 else if ( strcmp (str
, "cpsr_all") == 0
3583 || strcmp (str
, "spsr_all") == 0)
3587 inst
.error
= _("CPSR or SPSR expected");
3591 if (* str
== 's' || * str
== 'S')
3592 inst
.instruction
|= SPSR_BIT
;
3598 /* Two possible forms:
3599 "{C|S}PSR_<field>, Rm",
3600 "{C|S}PSR_f, #expression". */
3606 skip_whitespace (str
);
3608 if (psr_required_here (& str
) == FAIL
)
3611 if (skip_past_comma (& str
) == FAIL
)
3613 inst
.error
= _("comma missing after psr flags");
3617 skip_whitespace (str
);
3619 if (reg_required_here (& str
, 0) != FAIL
)
3626 if (! is_immediate_prefix (* str
))
3629 _("only a register or immediate value can follow a psr flag");
3636 if (my_get_expression (& inst
.reloc
.exp
, & str
))
3639 _("only a register or immediate value can follow a psr flag");
3643 #if 0 /* The first edition of the ARM architecture manual stated that
3644 writing anything other than the flags with an immediate operation
3645 had UNPREDICTABLE effects. This constraint was removed in the
3646 second edition of the specification. */
3647 if ((cpu_variant
& ARM_EXT_V5
) != ARM_EXT_V5
3648 && inst
.instruction
& ((PSR_c
| PSR_x
| PSR_s
) << PSR_SHIFT
))
3650 inst
.error
= _("immediate value cannot be used to set this field");
3655 inst
.instruction
|= INST_IMMEDIATE
;
3657 if (inst
.reloc
.exp
.X_add_symbol
)
3659 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
3660 inst
.reloc
.pc_rel
= 0;
3664 unsigned value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
3666 if (value
== (unsigned) FAIL
)
3668 inst
.error
= _("invalid constant");
3672 inst
.instruction
|= value
;
3679 /* Long Multiply Parser
3680 UMULL RdLo, RdHi, Rm, Rs
3681 SMULL RdLo, RdHi, Rm, Rs
3682 UMLAL RdLo, RdHi, Rm, Rs
3683 SMLAL RdLo, RdHi, Rm, Rs. */
3689 int rdlo
, rdhi
, rm
, rs
;
3691 /* Only one format "rdlo, rdhi, rm, rs". */
3692 skip_whitespace (str
);
3694 if ((rdlo
= reg_required_here (&str
, 12)) == FAIL
)
3696 inst
.error
= BAD_ARGS
;
3700 if (skip_past_comma (&str
) == FAIL
3701 || (rdhi
= reg_required_here (&str
, 16)) == FAIL
)
3703 inst
.error
= BAD_ARGS
;
3707 if (skip_past_comma (&str
) == FAIL
3708 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
3710 inst
.error
= BAD_ARGS
;
3714 /* rdhi, rdlo and rm must all be different. */
3715 if (rdlo
== rdhi
|| rdlo
== rm
|| rdhi
== rm
)
3716 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
3718 if (skip_past_comma (&str
) == FAIL
3719 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
3721 inst
.error
= BAD_ARGS
;
3725 if (rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
)
3727 inst
.error
= BAD_PC
;
3741 /* Only one format "rd, rm, rs". */
3742 skip_whitespace (str
);
3744 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
3746 inst
.error
= BAD_ARGS
;
3752 inst
.error
= BAD_PC
;
3756 if (skip_past_comma (&str
) == FAIL
3757 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
3759 inst
.error
= BAD_ARGS
;
3765 inst
.error
= BAD_PC
;
3770 as_tsktsk (_("rd and rm should be different in mul"));
3772 if (skip_past_comma (&str
) == FAIL
3773 || (rm
= reg_required_here (&str
, 8)) == FAIL
)
3775 inst
.error
= BAD_ARGS
;
3781 inst
.error
= BAD_PC
;
3795 /* Only one format "rd, rm, rs, rn". */
3796 skip_whitespace (str
);
3798 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
3800 inst
.error
= BAD_ARGS
;
3806 inst
.error
= BAD_PC
;
3810 if (skip_past_comma (&str
) == FAIL
3811 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
3813 inst
.error
= BAD_ARGS
;
3819 inst
.error
= BAD_PC
;
3824 as_tsktsk (_("rd and rm should be different in mla"));
3826 if (skip_past_comma (&str
) == FAIL
3827 || (rd
= reg_required_here (&str
, 8)) == FAIL
3828 || skip_past_comma (&str
) == FAIL
3829 || (rm
= reg_required_here (&str
, 12)) == FAIL
)
3831 inst
.error
= BAD_ARGS
;
3835 if (rd
== REG_PC
|| rm
== REG_PC
)
3837 inst
.error
= BAD_PC
;
3845 /* Expects *str -> the characters "acc0", possibly with leading blanks.
3846 Advances *str to the next non-alphanumeric.
3847 Returns 0, or else FAIL (in which case sets inst.error).
3849 (In a future XScale, there may be accumulators other than zero.
3850 At that time this routine and its callers can be upgraded to suit.) */
3853 accum0_required_here (str
)
3856 static char buff
[128]; /* Note the address is taken. Hence, static. */
3859 int result
= 0; /* The accum number. */
3861 skip_whitespace (p
);
3863 *str
= p
; /* Advance caller's string pointer too. */
3868 *--p
= 0; /* Aap nul into input buffer at non-alnum. */
3870 if (! ( streq (*str
, "acc0") || streq (*str
, "ACC0")))
3872 sprintf (buff
, _("acc0 expected, not '%.100s'"), *str
);
3877 *p
= c
; /* Unzap. */
3878 *str
= p
; /* Caller's string pointer to after match. */
3882 /* Expects **str -> after a comma. May be leading blanks.
3883 Advances *str, recognizing a load mode, and setting inst.instruction.
3884 Returns rn, or else FAIL (in which case may set inst.error
3885 and not advance str)
3887 Note: doesn't know Rd, so no err checks that require such knowledge. */
3890 ld_mode_required_here (string
)
3893 char * str
= * string
;
3897 skip_whitespace (str
);
3903 skip_whitespace (str
);
3905 if ((rn
= reg_required_here (& str
, 16)) == FAIL
)
3908 skip_whitespace (str
);
3914 if (skip_past_comma (& str
) == SUCCESS
)
3916 /* [Rn],... (post inc) */
3917 if (ldst_extend_v4 (&str
) == FAIL
)
3922 skip_whitespace (str
);
3927 inst
.instruction
|= WRITE_BACK
;
3930 inst
.instruction
|= INDEX_UP
| HWOFFSET_IMM
;
3936 if (skip_past_comma (& str
) == FAIL
)
3938 inst
.error
= _("pre-indexed expression expected");
3944 if (ldst_extend_v4 (&str
) == FAIL
)
3947 skip_whitespace (str
);
3949 if (* str
++ != ']')
3951 inst
.error
= _("missing ]");
3955 skip_whitespace (str
);
3960 inst
.instruction
|= WRITE_BACK
;
3964 else if (* str
== '=') /* ldr's "r,=label" syntax */
3965 /* We should never reach here, because <text> = <expression> is
3966 caught gas/read.c read_a_source_file() as a .set operation. */
3968 else /* PC +- 8 bit immediate offset. */
3970 if (my_get_expression (& inst
.reloc
.exp
, & str
))
3973 inst
.instruction
|= HWOFFSET_IMM
; /* The I bit. */
3974 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
3975 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
3976 inst
.reloc
.pc_rel
= 1;
3977 inst
.instruction
|= (REG_PC
<< 16);
3983 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
3989 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
3990 SMLAxy{cond} Rd,Rm,Rs,Rn
3991 SMLAWy{cond} Rd,Rm,Rs,Rn
3992 Error if any register is R15. */
4000 skip_whitespace (str
);
4002 if ((rd
= reg_required_here (& str
, 16)) == FAIL
4003 || skip_past_comma (& str
) == FAIL
4004 || (rm
= reg_required_here (& str
, 0)) == FAIL
4005 || skip_past_comma (& str
) == FAIL
4006 || (rs
= reg_required_here (& str
, 8)) == FAIL
4007 || skip_past_comma (& str
) == FAIL
4008 || (rn
= reg_required_here (& str
, 12)) == FAIL
)
4009 inst
.error
= BAD_ARGS
;
4011 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
|| rn
== REG_PC
)
4012 inst
.error
= BAD_PC
;
4018 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
4019 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
4020 Error if any register is R15.
4021 Warning if Rdlo == Rdhi. */
4027 int rdlo
, rdhi
, rm
, rs
;
4029 skip_whitespace (str
);
4031 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
4032 || skip_past_comma (& str
) == FAIL
4033 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
4034 || skip_past_comma (& str
) == FAIL
4035 || (rm
= reg_required_here (& str
, 0)) == FAIL
4036 || skip_past_comma (& str
) == FAIL
4037 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
4039 inst
.error
= BAD_ARGS
;
4043 if (rdlo
== REG_PC
|| rdhi
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
4045 inst
.error
= BAD_PC
;
4050 as_tsktsk (_("rdhi and rdlo must be different"));
4055 /* ARM V5E (El Segundo) signed-multiply (argument parse)
4056 SMULxy{cond} Rd,Rm,Rs
4057 Error if any register is R15. */
4065 skip_whitespace (str
);
4067 if ((rd
= reg_required_here (& str
, 16)) == FAIL
4068 || skip_past_comma (& str
) == FAIL
4069 || (rm
= reg_required_here (& str
, 0)) == FAIL
4070 || skip_past_comma (& str
) == FAIL
4071 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
4072 inst
.error
= BAD_ARGS
;
4074 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
4075 inst
.error
= BAD_PC
;
4081 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
4082 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
4083 Error if any register is R15. */
4091 skip_whitespace (str
);
4093 if ((rd
= reg_required_here (& str
, 12)) == FAIL
4094 || skip_past_comma (& str
) == FAIL
4095 || (rm
= reg_required_here (& str
, 0)) == FAIL
4096 || skip_past_comma (& str
) == FAIL
4097 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
4098 inst
.error
= BAD_ARGS
;
4100 else if (rd
== REG_PC
|| rm
== REG_PC
|| rn
== REG_PC
)
4101 inst
.error
= BAD_PC
;
4107 /* ARM V5E (el Segundo)
4108 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4109 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4111 These are equivalent to the XScale instructions MAR and MRA,
4112 respectively, when coproc == 0, opcode == 0, and CRm == 0.
4114 Result unpredicatable if Rd or Rn is R15. */
4122 skip_whitespace (str
);
4124 if (co_proc_number (& str
) == FAIL
)
4127 inst
.error
= BAD_ARGS
;
4131 if (skip_past_comma (& str
) == FAIL
4132 || cp_opc_expr (& str
, 4, 4) == FAIL
)
4135 inst
.error
= BAD_ARGS
;
4139 if (skip_past_comma (& str
) == FAIL
4140 || (rd
= reg_required_here (& str
, 12)) == FAIL
)
4143 inst
.error
= BAD_ARGS
;
4147 if (skip_past_comma (& str
) == FAIL
4148 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
4151 inst
.error
= BAD_ARGS
;
4155 /* Unpredictable result if rd or rn is R15. */
4156 if (rd
== REG_PC
|| rn
== REG_PC
)
4158 (_("Warning: instruction unpredictable when using r15"));
4160 if (skip_past_comma (& str
) == FAIL
4161 || cp_reg_required_here (& str
, 0) == FAIL
)
4164 inst
.error
= BAD_ARGS
;
4171 /* ARM V5 count-leading-zeroes instruction (argument parse)
4172 CLZ{<cond>} <Rd>, <Rm>
4173 Condition defaults to COND_ALWAYS.
4174 Error if Rd or Rm are R15. */
4182 skip_whitespace (str
);
4184 if (((rd
= reg_required_here (& str
, 12)) == FAIL
)
4185 || (skip_past_comma (& str
) == FAIL
)
4186 || ((rm
= reg_required_here (& str
, 0)) == FAIL
))
4187 inst
.error
= BAD_ARGS
;
4189 else if (rd
== REG_PC
|| rm
== REG_PC
)
4190 inst
.error
= BAD_PC
;
4196 /* ARM V5 (argument parse)
4197 LDC2{L} <coproc>, <CRd>, <addressing mode>
4198 STC2{L} <coproc>, <CRd>, <addressing mode>
4199 Instruction is not conditional, and has 0xf in the codition field.
4200 Otherwise, it's the same as LDC/STC. */
4206 skip_whitespace (str
);
4208 if (co_proc_number (& str
) == FAIL
)
4211 inst
.error
= BAD_ARGS
;
4213 else if (skip_past_comma (& str
) == FAIL
4214 || cp_reg_required_here (& str
, 12) == FAIL
)
4217 inst
.error
= BAD_ARGS
;
4219 else if (skip_past_comma (& str
) == FAIL
4220 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
4223 inst
.error
= BAD_ARGS
;
4229 /* ARM V5 (argument parse)
4230 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
4231 Instruction is not conditional, and has 0xf in the condition field.
4232 Otherwise, it's the same as CDP. */
4238 skip_whitespace (str
);
4240 if (co_proc_number (& str
) == FAIL
)
4243 inst
.error
= BAD_ARGS
;
4247 if (skip_past_comma (& str
) == FAIL
4248 || cp_opc_expr (& str
, 20,4) == FAIL
)
4251 inst
.error
= BAD_ARGS
;
4255 if (skip_past_comma (& str
) == FAIL
4256 || cp_reg_required_here (& str
, 12) == FAIL
)
4259 inst
.error
= BAD_ARGS
;
4263 if (skip_past_comma (& str
) == FAIL
4264 || cp_reg_required_here (& str
, 16) == FAIL
)
4267 inst
.error
= BAD_ARGS
;
4271 if (skip_past_comma (& str
) == FAIL
4272 || cp_reg_required_here (& str
, 0) == FAIL
)
4275 inst
.error
= BAD_ARGS
;
4279 if (skip_past_comma (& str
) == SUCCESS
)
4281 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
4284 inst
.error
= BAD_ARGS
;
4292 /* ARM V5 (argument parse)
4293 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4294 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4295 Instruction is not conditional, and has 0xf in the condition field.
4296 Otherwise, it's the same as MCR/MRC. */
4302 skip_whitespace (str
);
4304 if (co_proc_number (& str
) == FAIL
)
4307 inst
.error
= BAD_ARGS
;
4311 if (skip_past_comma (& str
) == FAIL
4312 || cp_opc_expr (& str
, 21, 3) == FAIL
)
4315 inst
.error
= BAD_ARGS
;
4319 if (skip_past_comma (& str
) == FAIL
4320 || reg_required_here (& str
, 12) == FAIL
)
4323 inst
.error
= BAD_ARGS
;
4327 if (skip_past_comma (& str
) == FAIL
4328 || cp_reg_required_here (& str
, 16) == FAIL
)
4331 inst
.error
= BAD_ARGS
;
4335 if (skip_past_comma (& str
) == FAIL
4336 || cp_reg_required_here (& str
, 0) == FAIL
)
4339 inst
.error
= BAD_ARGS
;
4343 if (skip_past_comma (& str
) == SUCCESS
)
4345 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
4348 inst
.error
= BAD_ARGS
;
4356 /* ARM v5TEJ. Jump to Jazelle code. */
4363 skip_whitespace (str
);
4365 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
4367 inst
.error
= BAD_ARGS
;
4371 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
4373 as_tsktsk (_("use of r15 in bxj is not really useful"));
4378 /* THUMB V5 breakpoint instruction (argument parse)
4386 unsigned long number
;
4388 skip_whitespace (str
);
4390 /* Allow optional leading '#'. */
4391 if (is_immediate_prefix (*str
))
4394 memset (& expr
, '\0', sizeof (expr
));
4395 if (my_get_expression (& expr
, & str
)
4396 || (expr
.X_op
!= O_constant
4397 /* As a convenience we allow 'bkpt' without an operand. */
4398 && expr
.X_op
!= O_absent
))
4400 inst
.error
= _("bad expression");
4404 number
= expr
.X_add_number
;
4406 /* Check it fits an 8 bit unsigned. */
4407 if (number
!= (number
& 0xff))
4409 inst
.error
= _("immediate value out of range");
4413 inst
.instruction
|= number
;
4418 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
4419 Expects inst.instruction is set for BLX(1).
4420 Note: this is cloned from do_branch, and the reloc changed to be a
4421 new one that can cope with setting one extra bit (the H bit). */
4427 if (my_get_expression (& inst
.reloc
.exp
, & str
))
4434 /* ScottB: February 5, 1998 */
4435 /* Check to see of PLT32 reloc required for the instruction. */
4437 /* arm_parse_reloc() works on input_line_pointer.
4438 We actually want to parse the operands to the branch instruction
4439 passed in 'str'. Save the input pointer and restore it later. */
4440 save_in
= input_line_pointer
;
4441 input_line_pointer
= str
;
4443 if (inst
.reloc
.exp
.X_op
== O_symbol
4445 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
4447 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
4448 inst
.reloc
.pc_rel
= 0;
4449 /* Modify str to point to after parsed operands, otherwise
4450 end_of_line() will complain about the (PLT) left in str. */
4451 str
= input_line_pointer
;
4455 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
4456 inst
.reloc
.pc_rel
= 1;
4459 input_line_pointer
= save_in
;
4462 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
4463 inst
.reloc
.pc_rel
= 1;
4464 #endif /* OBJ_ELF */
4469 /* ARM V5 branch-link-exchange instruction (argument parse)
4470 BLX <target_addr> ie BLX(1)
4471 BLX{<condition>} <Rm> ie BLX(2)
4472 Unfortunately, there are two different opcodes for this mnemonic.
4473 So, the insns[].value is not used, and the code here zaps values
4474 into inst.instruction.
4475 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
4484 skip_whitespace (mystr
);
4485 rm
= reg_required_here (& mystr
, 0);
4487 /* The above may set inst.error. Ignore his opinion. */
4492 /* Arg is a register.
4493 Use the condition code our caller put in inst.instruction.
4494 Pass ourselves off as a BX with a funny opcode. */
4495 inst
.instruction
|= 0x012fff30;
4500 /* This must be is BLX <target address>, no condition allowed. */
4501 if (inst
.instruction
!= COND_ALWAYS
)
4503 inst
.error
= BAD_COND
;
4507 inst
.instruction
= 0xfafffffe;
4509 /* Process like a B/BL, but with a different reloc.
4510 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
4515 /* ARM V5 Thumb BLX (argument parse)
4516 BLX <target_addr> which is BLX(1)
4517 BLX <Rm> which is BLX(2)
4518 Unfortunately, there are two different opcodes for this mnemonic.
4519 So, the tinsns[].value is not used, and the code here zaps values
4520 into inst.instruction. */
4529 skip_whitespace (mystr
);
4530 inst
.instruction
= 0x4780;
4532 /* Note that this call is to the ARM register recognizer. BLX(2)
4533 uses the ARM register space, not the Thumb one, so a call to
4534 thumb_reg() would be wrong. */
4535 rm
= reg_required_here (& mystr
, 3);
4540 /* It's BLX(2). The .instruction was zapped with rm & is final. */
4545 /* No ARM register. This must be BLX(1). Change the .instruction. */
4546 inst
.instruction
= 0xf7ffeffe;
4549 if (my_get_expression (& inst
.reloc
.exp
, & mystr
))
4552 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BLX
;
4553 inst
.reloc
.pc_rel
= 1;
4556 end_of_line (mystr
);
4559 /* ARM V5 breakpoint instruction (argument parse)
4560 BKPT <16 bit unsigned immediate>
4561 Instruction is not conditional.
4562 The bit pattern given in insns[] has the COND_ALWAYS condition,
4563 and it is an error if the caller tried to override that. */
4570 unsigned long number
;
4572 skip_whitespace (str
);
4574 /* Allow optional leading '#'. */
4575 if (is_immediate_prefix (* str
))
4578 memset (& expr
, '\0', sizeof (expr
));
4580 if (my_get_expression (& expr
, & str
)
4581 || (expr
.X_op
!= O_constant
4582 /* As a convenience we allow 'bkpt' without an operand. */
4583 && expr
.X_op
!= O_absent
))
4585 inst
.error
= _("bad expression");
4589 number
= expr
.X_add_number
;
4591 /* Check it fits a 16 bit unsigned. */
4592 if (number
!= (number
& 0xffff))
4594 inst
.error
= _("immediate value out of range");
4598 /* Top 12 of 16 bits to bits 19:8. */
4599 inst
.instruction
|= (number
& 0xfff0) << 4;
4601 /* Bottom 4 of 16 bits to bits 3:0. */
4602 inst
.instruction
|= number
& 0xf;
4607 static unsigned long check_iwmmxt_insn
PARAMS ((char *, enum iwmmxt_insn_type
, int));
4609 /* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
4611 static unsigned long
4612 check_iwmmxt_insn (str
, insn_type
, immediate_size
)
4614 enum iwmmxt_insn_type insn_type
;
4618 const char * inst_error
;
4620 unsigned long number
;
4622 inst_error
= inst
.error
;
4624 inst
.error
= BAD_ARGS
;
4625 skip_whitespace (str
);
4630 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
4635 if ((wreg_required_here (&str
, 0, IWMMXT_REG_WR
)) == FAIL
)
4640 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
4641 || skip_past_comma (&str
) == FAIL
4642 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
))
4647 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
4648 || skip_past_comma (&str
) == FAIL
4649 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4650 || skip_past_comma (&str
) == FAIL
4651 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
))
4656 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
4657 || skip_past_comma (&str
) == FAIL
4658 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4659 || skip_past_comma (&str
) == FAIL
4660 || wreg_required_here (&str
, 0, IWMMXT_REG_WCG
) == FAIL
))
4665 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4666 || skip_past_comma (&str
) == FAIL
4667 || reg_required_here (&str
, 12) == FAIL
))
4672 if ((reg_required_here (&str
, 12) == FAIL
4673 || skip_past_comma (&str
) == FAIL
4674 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
))
4679 if ((wreg_required_here (&str
, 5, IWMMXT_REG_WR
) == FAIL
4680 || skip_past_comma (&str
) == FAIL
4681 || reg_required_here (&str
, 0) == FAIL
4682 || skip_past_comma (&str
) == FAIL
4683 || reg_required_here (&str
, 12) == FAIL
))
4688 if ((wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
4689 || skip_past_comma (&str
) == FAIL
4690 || reg_required_here (&str
, 12) == FAIL
4691 || skip_past_comma (&str
) == FAIL
4692 || reg_required_here (&str
, 16) == FAIL
))
4697 if ((reg_required_here (&str
, 12) == FAIL
4698 || skip_past_comma (&str
) == FAIL
4699 || reg_required_here (&str
, 16) == FAIL
4700 || skip_past_comma (&str
) == FAIL
4701 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
))
4706 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WC
) == FAIL
4707 || skip_past_comma (&str
) == FAIL
4708 || reg_required_here (&str
, 12) == FAIL
))
4713 if ((reg_required_here (&str
, 12) == FAIL
4714 || skip_past_comma (&str
) == FAIL
4715 || wreg_required_here (&str
, 16, IWMMXT_REG_WC
) == FAIL
))
4720 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4721 || skip_past_comma (&str
) == FAIL
4722 || reg_required_here (&str
, 12) == FAIL
4723 || skip_past_comma (&str
) == FAIL
))
4728 if ((reg_required_here (&str
, 12) == FAIL
4729 || skip_past_comma (&str
) == FAIL
))
4734 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
4735 || skip_past_comma (&str
) == FAIL
4736 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4737 || skip_past_comma (&str
) == FAIL
4738 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
4739 || skip_past_comma (&str
) == FAIL
))
4744 if ((reg_required_here (&str
, 12) == FAIL
4745 || skip_past_comma (&str
) == FAIL
4746 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4747 || skip_past_comma (&str
) == FAIL
))
4752 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
4753 || skip_past_comma (&str
) == FAIL
4754 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4755 || skip_past_comma (&str
) == FAIL
))
4760 if (immediate_size
== 0)
4763 inst
.error
= inst_error
;
4768 skip_whitespace (str
);
4770 /* Allow optional leading '#'. */
4771 if (is_immediate_prefix (* str
))
4774 memset (& expr
, '\0', sizeof (expr
));
4776 if (my_get_expression (& expr
, & str
) || (expr
.X_op
!= O_constant
))
4778 inst
.error
= _("bad or missing expression");
4782 number
= expr
.X_add_number
;
4784 if (number
!= (number
& immediate_size
))
4786 inst
.error
= _("immediate value out of range");
4790 inst
.error
= inst_error
;
4796 do_iwmmxt_byte_addr (str
)
4799 int op
= (inst
.instruction
& 0x300) >> 8;
4802 inst
.instruction
&= ~0x300;
4803 inst
.instruction
|= (op
& 1) << 22 | (op
& 2) << 7;
4805 skip_whitespace (str
);
4807 if ((reg
= wreg_required_here (&str
, 12, IWMMXT_REG_WR_OR_WC
)) == FAIL
4808 || skip_past_comma (& str
) == FAIL
4809 || cp_byte_address_required_here (&str
) == FAIL
)
4812 inst
.error
= BAD_ARGS
;
4817 if (wc_register (reg
))
4819 inst
.instruction
|= 0xf0000100;
4820 inst
.instruction
&= ~0x00400000;
4825 do_iwmmxt_tandc (str
)
4830 reg
= check_iwmmxt_insn (str
, check_rd
, 0);
4832 if (reg
!= REG_PC
&& !inst
.error
)
4833 inst
.error
= _("only r15 allowed here");
4838 do_iwmmxt_tbcst (str
)
4841 check_iwmmxt_insn (str
, check_tbcst
, 0);
4847 do_iwmmxt_textrc (str
)
4850 unsigned long number
;
4852 if ((number
= check_iwmmxt_insn (str
, check_textrc
, 7)) == (unsigned long) FAIL
)
4855 inst
.instruction
|= number
& 0x7;
4860 do_iwmmxt_textrm (str
)
4863 unsigned long number
;
4865 if ((number
= check_iwmmxt_insn (str
, check_textrm
, 7)) == (unsigned long) FAIL
)
4868 inst
.instruction
|= number
& 0x7;
4872 do_iwmmxt_tinsr (str
)
4875 unsigned long number
;
4877 if ((number
= check_iwmmxt_insn (str
, check_tinsr
, 7)) == (unsigned long) FAIL
)
4880 inst
.instruction
|= number
& 0x7;
4885 do_iwmmxt_tmcr (str
)
4888 check_iwmmxt_insn (str
, check_tmcr
, 0);
4894 do_iwmmxt_tmcrr (str
)
4897 check_iwmmxt_insn (str
, check_tmcrr
, 0);
4903 do_iwmmxt_tmia (str
)
4906 check_iwmmxt_insn (str
, check_tmia
, 0);
4912 do_iwmmxt_tmovmsk (str
)
4915 check_iwmmxt_insn (str
, check_tmovmsk
, 0);
4921 do_iwmmxt_tmrc (str
)
4924 check_iwmmxt_insn (str
, check_tmrc
, 0);
4930 do_iwmmxt_tmrrc (str
)
4933 check_iwmmxt_insn (str
, check_tmrrc
, 0);
4939 do_iwmmxt_torc (str
)
4942 check_iwmmxt_insn (str
, check_rd
, 0);
4947 do_iwmmxt_waligni (str
)
4950 unsigned long number
;
4952 if ((number
= check_iwmmxt_insn (str
, check_waligni
, 7)) == (unsigned long) FAIL
)
4955 inst
.instruction
|= ((number
& 0x7) << 20);
4960 do_iwmmxt_wmov (str
)
4963 if (check_iwmmxt_insn (str
, check_wrwr
, 0) == (unsigned long) FAIL
)
4966 inst
.instruction
|= ((inst
.instruction
>> 16) & 0xf);
4971 do_iwmmxt_word_addr (str
)
4974 int op
= (inst
.instruction
& 0x300) >> 8;
4977 inst
.instruction
&= ~0x300;
4978 inst
.instruction
|= (op
& 1) << 22 | (op
& 2) << 7;
4980 skip_whitespace (str
);
4982 if ((reg
= wreg_required_here (&str
, 12, IWMMXT_REG_WR_OR_WC
)) == FAIL
4983 || skip_past_comma (& str
) == FAIL
4984 || cp_address_required_here (& str
, CP_WB_OK
) == FAIL
)
4987 inst
.error
= BAD_ARGS
;
4992 if (wc_register (reg
))
4994 inst
.instruction
|= 0xf0000100;
4995 inst
.instruction
&= ~0x00400000;
5000 do_iwmmxt_wrwr (str
)
5003 check_iwmmxt_insn (str
, check_wrwr
, 0);
5009 do_iwmmxt_wrwrwcg (str
)
5012 check_iwmmxt_insn (str
, check_wrwrwcg
, 0);
5018 do_iwmmxt_wrwrwr (str
)
5021 check_iwmmxt_insn (str
, check_wrwrwr
, 0);
5027 do_iwmmxt_wshufh (str
)
5030 unsigned long number
;
5032 if ((number
= check_iwmmxt_insn (str
, check_wshufh
, 0xff)) == (unsigned long) FAIL
)
5035 inst
.instruction
|= ((number
& 0xf0) << 16) | (number
& 0xf);
5040 do_iwmmxt_wzero (str
)
5043 if (check_iwmmxt_insn (str
, check_wr
, 0) == (unsigned long) FAIL
)
5046 inst
.instruction
|= ((inst
.instruction
& 0xf) << 12) | ((inst
.instruction
& 0xf) << 16);
5050 /* Xscale multiply-accumulate (argument parse)
5053 MIAxycc acc0,Rm,Rs. */
5062 if (accum0_required_here (& str
) == FAIL
)
5063 inst
.error
= ERR_NO_ACCUM
;
5065 else if (skip_past_comma (& str
) == FAIL
5066 || (rm
= reg_required_here (& str
, 0)) == FAIL
)
5067 inst
.error
= BAD_ARGS
;
5069 else if (skip_past_comma (& str
) == FAIL
5070 || (rs
= reg_required_here (& str
, 12)) == FAIL
)
5071 inst
.error
= BAD_ARGS
;
5073 /* inst.instruction has now been zapped with both rm and rs. */
5074 else if (rm
== REG_PC
|| rs
== REG_PC
)
5075 inst
.error
= BAD_PC
; /* Undefined result if rm or rs is R15. */
5081 /* Xscale move-accumulator-register (argument parse)
5083 MARcc acc0,RdLo,RdHi. */
5091 if (accum0_required_here (& str
) == FAIL
)
5092 inst
.error
= ERR_NO_ACCUM
;
5094 else if (skip_past_comma (& str
) == FAIL
5095 || (rdlo
= reg_required_here (& str
, 12)) == FAIL
)
5096 inst
.error
= BAD_ARGS
;
5098 else if (skip_past_comma (& str
) == FAIL
5099 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
5100 inst
.error
= BAD_ARGS
;
5102 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5103 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
5104 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
5110 /* Xscale move-register-accumulator (argument parse)
5112 MRAcc RdLo,RdHi,acc0. */
5121 skip_whitespace (str
);
5123 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
)
5124 inst
.error
= BAD_ARGS
;
5126 else if (skip_past_comma (& str
) == FAIL
5127 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
5128 inst
.error
= BAD_ARGS
;
5130 else if (skip_past_comma (& str
) == FAIL
5131 || accum0_required_here (& str
) == FAIL
)
5132 inst
.error
= ERR_NO_ACCUM
;
5134 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5135 else if (rdlo
== rdhi
)
5136 inst
.error
= BAD_ARGS
; /* Undefined result if 2 writes to same reg. */
5138 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
5139 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
5144 /* ARMv5TE: Preload-Cache
5148 Syntactically, like LDR with B=1, W=0, L=1. */
5156 skip_whitespace (str
);
5160 inst
.error
= _("'[' expected after PLD mnemonic");
5165 skip_whitespace (str
);
5167 if ((rd
= reg_required_here (& str
, 16)) == FAIL
)
5170 skip_whitespace (str
);
5176 skip_whitespace (str
);
5178 /* Post-indexed addressing is not allowed with PLD. */
5179 if (skip_past_comma (&str
) == SUCCESS
)
5182 = _("post-indexed expression used in preload instruction");
5185 else if (*str
== '!') /* [Rn]! */
5187 inst
.error
= _("writeback used in preload instruction");
5191 inst
.instruction
|= INDEX_UP
| PRE_INDEX
;
5193 else /* [Rn, ...] */
5195 if (skip_past_comma (& str
) == FAIL
)
5197 inst
.error
= _("pre-indexed expression expected");
5201 if (ldst_extend (&str
) == FAIL
)
5204 skip_whitespace (str
);
5208 inst
.error
= _("missing ]");
5213 skip_whitespace (str
);
5215 if (* str
== '!') /* [Rn]! */
5217 inst
.error
= _("writeback used in preload instruction");
5221 inst
.instruction
|= PRE_INDEX
;
5227 /* ARMv5TE load-consecutive (argument parse)
5240 skip_whitespace (str
);
5242 if ((rd
= reg_required_here (& str
, 12)) == FAIL
)
5244 inst
.error
= BAD_ARGS
;
5248 if (skip_past_comma (& str
) == FAIL
5249 || (rn
= ld_mode_required_here (& str
)) == FAIL
)
5252 inst
.error
= BAD_ARGS
;
5256 /* inst.instruction has now been zapped with Rd and the addressing mode. */
5257 if (rd
& 1) /* Unpredictable result if Rd is odd. */
5259 inst
.error
= _("destination register must be even");
5265 inst
.error
= _("r14 not allowed here");
5269 if (((rd
== rn
) || (rd
+ 1 == rn
))
5270 && ((inst
.instruction
& WRITE_BACK
)
5271 || (!(inst
.instruction
& PRE_INDEX
))))
5272 as_warn (_("pre/post-indexing used when modified address register is destination"));
5274 /* For an index-register load, the index register must not overlap the
5275 destination (even if not write-back). */
5276 if ((inst
.instruction
& V4_STR_BIT
) == 0
5277 && (inst
.instruction
& HWOFFSET_IMM
) == 0)
5279 int rm
= inst
.instruction
& 0x0000000f;
5281 if (rm
== rd
|| (rm
== rd
+ 1))
5282 as_warn (_("ldrd destination registers must not overlap index register"));
5288 /* Returns the index into fp_values of a floating point number,
5289 or -1 if not in the table. */
5292 my_get_float_expression (str
)
5295 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
5301 memset (words
, 0, MAX_LITTLENUMS
* sizeof (LITTLENUM_TYPE
));
5303 /* Look for a raw floating point number. */
5304 if ((save_in
= atof_ieee (*str
, 'x', words
)) != NULL
5305 && is_end_of_line
[(unsigned char) *save_in
])
5307 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
5309 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
5311 if (words
[j
] != fp_values
[i
][j
])
5315 if (j
== MAX_LITTLENUMS
)
5323 /* Try and parse a more complex expression, this will probably fail
5324 unless the code uses a floating point prefix (eg "0f"). */
5325 save_in
= input_line_pointer
;
5326 input_line_pointer
= *str
;
5327 if (expression (&exp
) == absolute_section
5328 && exp
.X_op
== O_big
5329 && exp
.X_add_number
< 0)
5331 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
5333 if (gen_to_words (words
, 5, (long) 15) == 0)
5335 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
5337 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
5339 if (words
[j
] != fp_values
[i
][j
])
5343 if (j
== MAX_LITTLENUMS
)
5345 *str
= input_line_pointer
;
5346 input_line_pointer
= save_in
;
5353 *str
= input_line_pointer
;
5354 input_line_pointer
= save_in
;
5358 /* Return TRUE if anything in the expression is a bignum. */
5361 walk_no_bignums (sp
)
5364 if (symbol_get_value_expression (sp
)->X_op
== O_big
)
5367 if (symbol_get_value_expression (sp
)->X_add_symbol
)
5369 return (walk_no_bignums (symbol_get_value_expression (sp
)->X_add_symbol
)
5370 || (symbol_get_value_expression (sp
)->X_op_symbol
5371 && walk_no_bignums (symbol_get_value_expression (sp
)->X_op_symbol
)));
5377 static int in_my_get_expression
= 0;
5380 my_get_expression (ep
, str
)
5387 save_in
= input_line_pointer
;
5388 input_line_pointer
= *str
;
5389 in_my_get_expression
= 1;
5390 seg
= expression (ep
);
5391 in_my_get_expression
= 0;
5393 if (ep
->X_op
== O_illegal
)
5395 /* We found a bad expression in md_operand(). */
5396 *str
= input_line_pointer
;
5397 input_line_pointer
= save_in
;
5402 if (seg
!= absolute_section
5403 && seg
!= text_section
5404 && seg
!= data_section
5405 && seg
!= bss_section
5406 && seg
!= undefined_section
)
5408 inst
.error
= _("bad_segment");
5409 *str
= input_line_pointer
;
5410 input_line_pointer
= save_in
;
5415 /* Get rid of any bignums now, so that we don't generate an error for which
5416 we can't establish a line number later on. Big numbers are never valid
5417 in instructions, which is where this routine is always called. */
5418 if (ep
->X_op
== O_big
5419 || (ep
->X_add_symbol
5420 && (walk_no_bignums (ep
->X_add_symbol
)
5422 && walk_no_bignums (ep
->X_op_symbol
)))))
5424 inst
.error
= _("invalid constant");
5425 *str
= input_line_pointer
;
5426 input_line_pointer
= save_in
;
5430 *str
= input_line_pointer
;
5431 input_line_pointer
= save_in
;
5435 /* We handle all bad expressions here, so that we can report the faulty
5436 instruction in the error message. */
5441 if (in_my_get_expression
)
5443 expr
->X_op
= O_illegal
;
5444 if (inst
.error
== NULL
)
5445 inst
.error
= _("bad expression");
5449 /* UNRESTRICT should be one if <shift> <register> is permitted for this
5453 decode_shift (str
, unrestrict
)
5457 const struct asm_shift_name
* shift
;
5461 skip_whitespace (* str
);
5463 for (p
= * str
; ISALPHA (* p
); p
++)
5468 inst
.error
= _("shift expression expected");
5474 shift
= (const struct asm_shift_name
*) hash_find (arm_shift_hsh
, * str
);
5479 inst
.error
= _("shift expression expected");
5483 assert (shift
->properties
->index
== shift_properties
[shift
->properties
->index
].index
);
5485 if (shift
->properties
->index
== SHIFT_RRX
)
5488 inst
.instruction
|= shift
->properties
->bit_field
;
5492 skip_whitespace (p
);
5494 if (unrestrict
&& reg_required_here (& p
, 8) != FAIL
)
5496 inst
.instruction
|= shift
->properties
->bit_field
| SHIFT_BY_REG
;
5500 else if (! is_immediate_prefix (* p
))
5502 inst
.error
= (unrestrict
5503 ? _("shift requires register or #expression")
5504 : _("shift requires #expression"));
5512 if (my_get_expression (& inst
.reloc
.exp
, & p
))
5515 /* Validate some simple #expressions. */
5516 if (inst
.reloc
.exp
.X_op
== O_constant
)
5518 unsigned num
= inst
.reloc
.exp
.X_add_number
;
5520 /* Reject operations greater than 32. */
5522 /* Reject a shift of 0 unless the mode allows it. */
5523 || (num
== 0 && shift
->properties
->allows_0
== 0)
5524 /* Reject a shift of 32 unless the mode allows it. */
5525 || (num
== 32 && shift
->properties
->allows_32
== 0)
5528 /* As a special case we allow a shift of zero for
5529 modes that do not support it to be recoded as an
5530 logical shift left of zero (ie nothing). We warn
5531 about this though. */
5534 as_warn (_("shift of 0 ignored."));
5535 shift
= & shift_names
[0];
5536 assert (shift
->properties
->index
== SHIFT_LSL
);
5540 inst
.error
= _("invalid immediate shift");
5545 /* Shifts of 32 are encoded as 0, for those shifts that
5550 inst
.instruction
|= (num
<< 7) | shift
->properties
->bit_field
;
5554 inst
.reloc
.type
= BFD_RELOC_ARM_SHIFT_IMM
;
5555 inst
.reloc
.pc_rel
= 0;
5556 inst
.instruction
|= shift
->properties
->bit_field
;
5563 /* Do those data_ops which can take a negative immediate constant
5564 by altering the instuction. A bit of a hack really.
5568 by inverting the second operand, and
5571 by negating the second operand. */
5574 negate_data_op (instruction
, value
)
5575 unsigned long * instruction
;
5576 unsigned long value
;
5579 unsigned long negated
, inverted
;
5581 negated
= validate_immediate (-value
);
5582 inverted
= validate_immediate (~value
);
5584 op
= (*instruction
>> DATA_OP_SHIFT
) & 0xf;
5587 /* First negates. */
5588 case OPCODE_SUB
: /* ADD <-> SUB */
5589 new_inst
= OPCODE_ADD
;
5594 new_inst
= OPCODE_SUB
;
5598 case OPCODE_CMP
: /* CMP <-> CMN */
5599 new_inst
= OPCODE_CMN
;
5604 new_inst
= OPCODE_CMP
;
5608 /* Now Inverted ops. */
5609 case OPCODE_MOV
: /* MOV <-> MVN */
5610 new_inst
= OPCODE_MVN
;
5615 new_inst
= OPCODE_MOV
;
5619 case OPCODE_AND
: /* AND <-> BIC */
5620 new_inst
= OPCODE_BIC
;
5625 new_inst
= OPCODE_AND
;
5629 case OPCODE_ADC
: /* ADC <-> SBC */
5630 new_inst
= OPCODE_SBC
;
5635 new_inst
= OPCODE_ADC
;
5639 /* We cannot do anything. */
5644 if (value
== (unsigned) FAIL
)
5647 *instruction
&= OPCODE_MASK
;
5648 *instruction
|= new_inst
<< DATA_OP_SHIFT
;
5659 skip_whitespace (* str
);
5661 if (reg_required_here (str
, 0) != FAIL
)
5663 if (skip_past_comma (str
) == SUCCESS
)
5664 /* Shift operation on register. */
5665 return decode_shift (str
, NO_SHIFT_RESTRICT
);
5671 /* Immediate expression. */
5672 if (is_immediate_prefix (**str
))
5677 if (my_get_expression (&inst
.reloc
.exp
, str
))
5680 if (inst
.reloc
.exp
.X_add_symbol
)
5682 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
5683 inst
.reloc
.pc_rel
= 0;
5687 if (skip_past_comma (str
) == SUCCESS
)
5689 /* #x, y -- ie explicit rotation by Y. */
5690 if (my_get_expression (&expr
, str
))
5693 if (expr
.X_op
!= O_constant
)
5695 inst
.error
= _("constant expression expected");
5699 /* Rotate must be a multiple of 2. */
5700 if (((unsigned) expr
.X_add_number
) > 30
5701 || (expr
.X_add_number
& 1) != 0
5702 || ((unsigned) inst
.reloc
.exp
.X_add_number
) > 255)
5704 inst
.error
= _("invalid constant");
5707 inst
.instruction
|= INST_IMMEDIATE
;
5708 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
5709 inst
.instruction
|= expr
.X_add_number
<< 7;
5713 /* Implicit rotation, select a suitable one. */
5714 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
5718 /* Can't be done. Perhaps the code reads something like
5719 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
5720 if ((value
= negate_data_op (&inst
.instruction
,
5721 inst
.reloc
.exp
.X_add_number
))
5724 inst
.error
= _("invalid constant");
5729 inst
.instruction
|= value
;
5732 inst
.instruction
|= INST_IMMEDIATE
;
5737 inst
.error
= _("register or shift expression expected");
5746 skip_whitespace (* str
);
5748 if (fp_reg_required_here (str
, 0) != FAIL
)
5752 /* Immediate expression. */
5753 if (*((*str
)++) == '#')
5759 skip_whitespace (* str
);
5761 /* First try and match exact strings, this is to guarantee
5762 that some formats will work even for cross assembly. */
5764 for (i
= 0; fp_const
[i
]; i
++)
5766 if (strncmp (*str
, fp_const
[i
], strlen (fp_const
[i
])) == 0)
5770 *str
+= strlen (fp_const
[i
]);
5771 if (is_end_of_line
[(unsigned char) **str
])
5773 inst
.instruction
|= i
+ 8;
5780 /* Just because we didn't get a match doesn't mean that the
5781 constant isn't valid, just that it is in a format that we
5782 don't automatically recognize. Try parsing it with
5783 the standard expression routines. */
5784 if ((i
= my_get_float_expression (str
)) >= 0)
5786 inst
.instruction
|= i
+ 8;
5790 inst
.error
= _("invalid floating point immediate expression");
5794 _("floating point register or immediate expression expected");
5803 skip_whitespace (str
);
5805 if (reg_required_here (&str
, 12) == FAIL
5806 || skip_past_comma (&str
) == FAIL
5807 || reg_required_here (&str
, 16) == FAIL
5808 || skip_past_comma (&str
) == FAIL
5809 || data_op2 (&str
) == FAIL
)
5812 inst
.error
= BAD_ARGS
;
5824 /* This is a pseudo-op of the form "adr rd, label" to be converted
5825 into a relative address of the form "add rd, pc, #label-.-8". */
5826 skip_whitespace (str
);
5828 if (reg_required_here (&str
, 12) == FAIL
5829 || skip_past_comma (&str
) == FAIL
5830 || my_get_expression (&inst
.reloc
.exp
, &str
))
5833 inst
.error
= BAD_ARGS
;
5837 /* Frag hacking will turn this into a sub instruction if the offset turns
5838 out to be negative. */
5839 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
5840 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust. */
5841 inst
.reloc
.pc_rel
= 1;
5850 /* This is a pseudo-op of the form "adrl rd, label" to be converted
5851 into a relative address of the form:
5852 add rd, pc, #low(label-.-8)"
5853 add rd, rd, #high(label-.-8)" */
5855 skip_whitespace (str
);
5857 if (reg_required_here (&str
, 12) == FAIL
5858 || skip_past_comma (&str
) == FAIL
5859 || my_get_expression (&inst
.reloc
.exp
, &str
))
5862 inst
.error
= BAD_ARGS
;
5868 /* Frag hacking will turn this into a sub instruction if the offset turns
5869 out to be negative. */
5870 inst
.reloc
.type
= BFD_RELOC_ARM_ADRL_IMMEDIATE
;
5871 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust */
5872 inst
.reloc
.pc_rel
= 1;
5873 inst
.size
= INSN_SIZE
* 2;
5882 skip_whitespace (str
);
5884 if (reg_required_here (&str
, 16) == FAIL
)
5887 inst
.error
= BAD_ARGS
;
5891 if (skip_past_comma (&str
) == FAIL
5892 || data_op2 (&str
) == FAIL
)
5895 inst
.error
= BAD_ARGS
;
5907 skip_whitespace (str
);
5909 if (reg_required_here (&str
, 12) == FAIL
)
5912 inst
.error
= BAD_ARGS
;
5916 if (skip_past_comma (&str
) == FAIL
5917 || data_op2 (&str
) == FAIL
)
5920 inst
.error
= BAD_ARGS
;
5939 if (my_get_expression (& inst
.reloc
.exp
, str
))
5942 if (inst
.reloc
.exp
.X_op
== O_constant
)
5944 int value
= inst
.reloc
.exp
.X_add_number
;
5946 if (value
< -4095 || value
> 4095)
5948 inst
.error
= _("address offset too large");
5958 inst
.instruction
|= add
| value
;
5962 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
5963 inst
.reloc
.pc_rel
= 0;
5976 if (reg_required_here (str
, 0) == FAIL
)
5979 inst
.instruction
|= add
| OFFSET_REG
;
5980 if (skip_past_comma (str
) == SUCCESS
)
5981 return decode_shift (str
, SHIFT_RESTRICT
);
5995 skip_whitespace (str
);
5997 if ((conflict_reg
= reg_required_here (&str
, 12)) == FAIL
)
6000 inst
.error
= BAD_ARGS
;
6004 if (skip_past_comma (&str
) == FAIL
)
6006 inst
.error
= _("address expected");
6016 skip_whitespace (str
);
6018 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6021 /* Conflicts can occur on stores as well as loads. */
6022 conflict_reg
= (conflict_reg
== reg
);
6024 skip_whitespace (str
);
6030 if (skip_past_comma (&str
) == SUCCESS
)
6032 /* [Rn],... (post inc) */
6033 if (ldst_extend (&str
) == FAIL
)
6036 as_warn (_("%s register same as write-back base"),
6037 ((inst
.instruction
& LOAD_BIT
)
6038 ? _("destination") : _("source")));
6043 skip_whitespace (str
);
6048 as_warn (_("%s register same as write-back base"),
6049 ((inst
.instruction
& LOAD_BIT
)
6050 ? _("destination") : _("source")));
6052 inst
.instruction
|= WRITE_BACK
;
6055 inst
.instruction
|= INDEX_UP
;
6062 if (skip_past_comma (&str
) == FAIL
)
6064 inst
.error
= _("pre-indexed expression expected");
6069 if (ldst_extend (&str
) == FAIL
)
6072 skip_whitespace (str
);
6076 inst
.error
= _("missing ]");
6080 skip_whitespace (str
);
6085 as_warn (_("%s register same as write-back base"),
6086 ((inst
.instruction
& LOAD_BIT
)
6087 ? _("destination") : _("source")));
6089 inst
.instruction
|= WRITE_BACK
;
6093 else if (*str
== '=')
6095 if ((inst
.instruction
& LOAD_BIT
) == 0)
6097 inst
.error
= _("invalid pseudo operation");
6101 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6104 skip_whitespace (str
);
6106 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6109 if (inst
.reloc
.exp
.X_op
!= O_constant
6110 && inst
.reloc
.exp
.X_op
!= O_symbol
)
6112 inst
.error
= _("constant expression expected");
6116 if (inst
.reloc
.exp
.X_op
== O_constant
)
6118 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
6122 /* This can be done with a mov instruction. */
6123 inst
.instruction
&= LITERAL_MASK
;
6124 inst
.instruction
|= (INST_IMMEDIATE
6125 | (OPCODE_MOV
<< DATA_OP_SHIFT
));
6126 inst
.instruction
|= value
& 0xfff;
6131 value
= validate_immediate (~inst
.reloc
.exp
.X_add_number
);
6135 /* This can be done with a mvn instruction. */
6136 inst
.instruction
&= LITERAL_MASK
;
6137 inst
.instruction
|= (INST_IMMEDIATE
6138 | (OPCODE_MVN
<< DATA_OP_SHIFT
));
6139 inst
.instruction
|= value
& 0xfff;
6145 /* Insert into literal pool. */
6146 if (add_to_lit_pool () == FAIL
)
6149 inst
.error
= _("literal pool insertion failed");
6153 /* Change the instruction exp to point to the pool. */
6154 inst
.reloc
.type
= BFD_RELOC_ARM_LITERAL
;
6155 inst
.reloc
.pc_rel
= 1;
6156 inst
.instruction
|= (REG_PC
<< 16);
6161 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6164 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
6166 /* PC rel adjust. */
6167 inst
.reloc
.exp
.X_add_number
-= 8;
6169 inst
.reloc
.pc_rel
= 1;
6170 inst
.instruction
|= (REG_PC
<< 16);
6174 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
6185 skip_whitespace (str
);
6187 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
6190 inst
.error
= BAD_ARGS
;
6194 if (skip_past_comma (& str
) == FAIL
)
6196 inst
.error
= _("address expected");
6206 skip_whitespace (str
);
6208 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6211 /* ldrt/strt always use post-indexed addressing, so if the base is
6212 the same as Rd, we warn. */
6213 if (conflict_reg
== reg
)
6214 as_warn (_("%s register same as write-back base"),
6215 ((inst
.instruction
& LOAD_BIT
)
6216 ? _("destination") : _("source")));
6218 skip_whitespace (str
);
6224 if (skip_past_comma (&str
) == SUCCESS
)
6226 /* [Rn],... (post inc) */
6227 if (ldst_extend (&str
) == FAIL
)
6233 skip_whitespace (str
);
6235 /* Skip a write-back '!'. */
6239 inst
.instruction
|= INDEX_UP
;
6244 inst
.error
= _("post-indexed expression expected");
6250 inst
.error
= _("post-indexed expression expected");
6259 ldst_extend_v4 (str
)
6269 if (my_get_expression (& inst
.reloc
.exp
, str
))
6272 if (inst
.reloc
.exp
.X_op
== O_constant
)
6274 int value
= inst
.reloc
.exp
.X_add_number
;
6276 if (value
< -255 || value
> 255)
6278 inst
.error
= _("address offset too large");
6288 /* Halfword and signextension instructions have the
6289 immediate value split across bits 11..8 and bits 3..0. */
6290 inst
.instruction
|= (add
| HWOFFSET_IMM
6291 | ((value
>> 4) << 8) | (value
& 0xF));
6295 inst
.instruction
|= HWOFFSET_IMM
;
6296 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
6297 inst
.reloc
.pc_rel
= 0;
6310 if (reg_required_here (str
, 0) == FAIL
)
6313 inst
.instruction
|= add
;
6318 /* Halfword and signed-byte load/store operations. */
6327 skip_whitespace (str
);
6329 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
6332 inst
.error
= BAD_ARGS
;
6336 if (skip_past_comma (& str
) == FAIL
)
6338 inst
.error
= _("address expected");
6348 skip_whitespace (str
);
6350 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6353 /* Conflicts can occur on stores as well as loads. */
6354 conflict_reg
= (conflict_reg
== reg
);
6356 skip_whitespace (str
);
6362 if (skip_past_comma (&str
) == SUCCESS
)
6364 /* [Rn],... (post inc) */
6365 if (ldst_extend_v4 (&str
) == FAIL
)
6368 as_warn (_("%s register same as write-back base"),
6369 ((inst
.instruction
& LOAD_BIT
)
6370 ? _("destination") : _("source")));
6375 inst
.instruction
|= HWOFFSET_IMM
;
6377 skip_whitespace (str
);
6382 as_warn (_("%s register same as write-back base"),
6383 ((inst
.instruction
& LOAD_BIT
)
6384 ? _("destination") : _("source")));
6386 inst
.instruction
|= WRITE_BACK
;
6389 inst
.instruction
|= INDEX_UP
;
6396 if (skip_past_comma (&str
) == FAIL
)
6398 inst
.error
= _("pre-indexed expression expected");
6403 if (ldst_extend_v4 (&str
) == FAIL
)
6406 skip_whitespace (str
);
6410 inst
.error
= _("missing ]");
6414 skip_whitespace (str
);
6419 as_warn (_("%s register same as write-back base"),
6420 ((inst
.instruction
& LOAD_BIT
)
6421 ? _("destination") : _("source")));
6423 inst
.instruction
|= WRITE_BACK
;
6427 else if (*str
== '=')
6429 if ((inst
.instruction
& LOAD_BIT
) == 0)
6431 inst
.error
= _("invalid pseudo operation");
6435 /* XXX Does this work correctly for half-word/byte ops? */
6436 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6439 skip_whitespace (str
);
6441 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6444 if (inst
.reloc
.exp
.X_op
!= O_constant
6445 && inst
.reloc
.exp
.X_op
!= O_symbol
)
6447 inst
.error
= _("constant expression expected");
6451 if (inst
.reloc
.exp
.X_op
== O_constant
)
6453 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
6457 /* This can be done with a mov instruction. */
6458 inst
.instruction
&= LITERAL_MASK
;
6459 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MOV
<< DATA_OP_SHIFT
);
6460 inst
.instruction
|= value
& 0xfff;
6465 value
= validate_immediate (~ inst
.reloc
.exp
.X_add_number
);
6469 /* This can be done with a mvn instruction. */
6470 inst
.instruction
&= LITERAL_MASK
;
6471 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MVN
<< DATA_OP_SHIFT
);
6472 inst
.instruction
|= value
& 0xfff;
6478 /* Insert into literal pool. */
6479 if (add_to_lit_pool () == FAIL
)
6482 inst
.error
= _("literal pool insertion failed");
6486 /* Change the instruction exp to point to the pool. */
6487 inst
.instruction
|= HWOFFSET_IMM
;
6488 inst
.reloc
.type
= BFD_RELOC_ARM_HWLITERAL
;
6489 inst
.reloc
.pc_rel
= 1;
6490 inst
.instruction
|= (REG_PC
<< 16);
6495 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6498 inst
.instruction
|= HWOFFSET_IMM
;
6499 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
6501 /* PC rel adjust. */
6502 inst
.reloc
.exp
.X_add_number
-= 8;
6504 inst
.reloc
.pc_rel
= 1;
6505 inst
.instruction
|= (REG_PC
<< 16);
6509 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
6518 char * str
= * strp
;
6522 /* We come back here if we get ranges concatenated by '+' or '|'. */
6537 skip_whitespace (str
);
6539 if ((reg
= reg_required_here (& str
, -1)) == FAIL
)
6548 inst
.error
= _("bad range in register list");
6552 for (i
= cur_reg
+ 1; i
< reg
; i
++)
6554 if (range
& (1 << i
))
6556 (_("Warning: duplicated register (r%d) in register list"),
6564 if (range
& (1 << reg
))
6565 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
6567 else if (reg
<= cur_reg
)
6568 as_tsktsk (_("Warning: register range not in ascending order"));
6573 while (skip_past_comma (&str
) != FAIL
6574 || (in_range
= 1, *str
++ == '-'));
6576 skip_whitespace (str
);
6580 inst
.error
= _("missing `}'");
6588 if (my_get_expression (&expr
, &str
))
6591 if (expr
.X_op
== O_constant
)
6593 if (expr
.X_add_number
6594 != (expr
.X_add_number
& 0x0000ffff))
6596 inst
.error
= _("invalid register mask");
6600 if ((range
& expr
.X_add_number
) != 0)
6602 int regno
= range
& expr
.X_add_number
;
6605 regno
= (1 << regno
) - 1;
6607 (_("Warning: duplicated register (r%d) in register list"),
6611 range
|= expr
.X_add_number
;
6615 if (inst
.reloc
.type
!= 0)
6617 inst
.error
= _("expression too complex");
6621 memcpy (&inst
.reloc
.exp
, &expr
, sizeof (expressionS
));
6622 inst
.reloc
.type
= BFD_RELOC_ARM_MULTI
;
6623 inst
.reloc
.pc_rel
= 0;
6627 skip_whitespace (str
);
6629 if (*str
== '|' || *str
== '+')
6635 while (another_range
);
6648 skip_whitespace (str
);
6650 if ((base_reg
= reg_required_here (&str
, 16)) == FAIL
)
6653 if (base_reg
== REG_PC
)
6655 inst
.error
= _("r15 not allowed as base register");
6659 skip_whitespace (str
);
6663 inst
.instruction
|= WRITE_BACK
;
6667 if (skip_past_comma (&str
) == FAIL
6668 || (range
= reg_list (&str
)) == FAIL
)
6671 inst
.error
= BAD_ARGS
;
6678 inst
.instruction
|= LDM_TYPE_2_OR_3
;
6681 if (inst
.instruction
& WRITE_BACK
)
6683 /* Check for unpredictable uses of writeback. */
6684 if (inst
.instruction
& LOAD_BIT
)
6686 /* Not allowed in LDM type 2. */
6687 if ((inst
.instruction
& LDM_TYPE_2_OR_3
)
6688 && ((range
& (1 << REG_PC
)) == 0))
6689 as_warn (_("writeback of base register is UNPREDICTABLE"));
6690 /* Only allowed if base reg not in list for other types. */
6691 else if (range
& (1 << base_reg
))
6692 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
6696 /* Not allowed for type 2. */
6697 if (inst
.instruction
& LDM_TYPE_2_OR_3
)
6698 as_warn (_("writeback of base register is UNPREDICTABLE"));
6699 /* Only allowed if base reg not in list, or first in list. */
6700 else if ((range
& (1 << base_reg
))
6701 && (range
& ((1 << base_reg
) - 1)))
6702 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
6706 inst
.instruction
|= range
;
6715 skip_whitespace (str
);
6717 /* Allow optional leading '#'. */
6718 if (is_immediate_prefix (*str
))
6721 if (my_get_expression (& inst
.reloc
.exp
, & str
))
6724 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
6725 inst
.reloc
.pc_rel
= 0;
6737 skip_whitespace (str
);
6739 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
6744 inst
.error
= _("r15 not allowed in swap");
6748 if (skip_past_comma (&str
) == FAIL
6749 || (reg
= reg_required_here (&str
, 0)) == FAIL
)
6752 inst
.error
= BAD_ARGS
;
6758 inst
.error
= _("r15 not allowed in swap");
6762 if (skip_past_comma (&str
) == FAIL
6765 inst
.error
= BAD_ARGS
;
6769 skip_whitespace (str
);
6771 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6776 inst
.error
= BAD_PC
;
6780 skip_whitespace (str
);
6784 inst
.error
= _("missing ]");
6796 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6803 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
6804 required for the instruction. */
6806 /* arm_parse_reloc () works on input_line_pointer.
6807 We actually want to parse the operands to the branch instruction
6808 passed in 'str'. Save the input pointer and restore it later. */
6809 save_in
= input_line_pointer
;
6810 input_line_pointer
= str
;
6811 if (inst
.reloc
.exp
.X_op
== O_symbol
6813 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
6815 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
6816 inst
.reloc
.pc_rel
= 0;
6817 /* Modify str to point to after parsed operands, otherwise
6818 end_of_line() will complain about the (PLT) left in str. */
6819 str
= input_line_pointer
;
6823 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
6824 inst
.reloc
.pc_rel
= 1;
6826 input_line_pointer
= save_in
;
6829 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
6830 inst
.reloc
.pc_rel
= 1;
6831 #endif /* OBJ_ELF */
6843 skip_whitespace (str
);
6845 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
6847 inst
.error
= BAD_ARGS
;
6851 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
6853 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
6862 /* Co-processor data operation.
6863 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
6864 skip_whitespace (str
);
6866 if (co_proc_number (&str
) == FAIL
)
6869 inst
.error
= BAD_ARGS
;
6873 if (skip_past_comma (&str
) == FAIL
6874 || cp_opc_expr (&str
, 20,4) == FAIL
)
6877 inst
.error
= BAD_ARGS
;
6881 if (skip_past_comma (&str
) == FAIL
6882 || cp_reg_required_here (&str
, 12) == FAIL
)
6885 inst
.error
= BAD_ARGS
;
6889 if (skip_past_comma (&str
) == FAIL
6890 || cp_reg_required_here (&str
, 16) == FAIL
)
6893 inst
.error
= BAD_ARGS
;
6897 if (skip_past_comma (&str
) == FAIL
6898 || cp_reg_required_here (&str
, 0) == FAIL
)
6901 inst
.error
= BAD_ARGS
;
6905 if (skip_past_comma (&str
) == SUCCESS
)
6907 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
6910 inst
.error
= BAD_ARGS
;
6923 /* Co-processor register load/store.
6924 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
6926 skip_whitespace (str
);
6928 if (co_proc_number (&str
) == FAIL
)
6931 inst
.error
= BAD_ARGS
;
6935 if (skip_past_comma (&str
) == FAIL
6936 || cp_reg_required_here (&str
, 12) == FAIL
)
6939 inst
.error
= BAD_ARGS
;
6943 if (skip_past_comma (&str
) == FAIL
6944 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
6947 inst
.error
= BAD_ARGS
;
6959 /* Co-processor register transfer.
6960 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
6962 skip_whitespace (str
);
6964 if (co_proc_number (&str
) == FAIL
)
6967 inst
.error
= BAD_ARGS
;
6971 if (skip_past_comma (&str
) == FAIL
6972 || cp_opc_expr (&str
, 21, 3) == FAIL
)
6975 inst
.error
= BAD_ARGS
;
6979 if (skip_past_comma (&str
) == FAIL
6980 || reg_required_here (&str
, 12) == FAIL
)
6983 inst
.error
= BAD_ARGS
;
6987 if (skip_past_comma (&str
) == FAIL
6988 || cp_reg_required_here (&str
, 16) == FAIL
)
6991 inst
.error
= BAD_ARGS
;
6995 if (skip_past_comma (&str
) == FAIL
6996 || cp_reg_required_here (&str
, 0) == FAIL
)
6999 inst
.error
= BAD_ARGS
;
7003 if (skip_past_comma (&str
) == SUCCESS
)
7005 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
7008 inst
.error
= BAD_ARGS
;
7021 /* FP control registers.
7022 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
7024 skip_whitespace (str
);
7026 if (reg_required_here (&str
, 12) == FAIL
)
7029 inst
.error
= BAD_ARGS
;
7041 skip_whitespace (str
);
7043 if (fp_reg_required_here (&str
, 12) == FAIL
)
7046 inst
.error
= BAD_ARGS
;
7050 if (skip_past_comma (&str
) == FAIL
7051 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
7054 inst
.error
= BAD_ARGS
;
7067 skip_whitespace (str
);
7069 if (fp_reg_required_here (&str
, 12) == FAIL
)
7072 inst
.error
= BAD_ARGS
;
7076 /* Get Number of registers to transfer. */
7077 if (skip_past_comma (&str
) == FAIL
7078 || my_get_expression (&inst
.reloc
.exp
, &str
))
7081 inst
.error
= _("constant expression expected");
7085 if (inst
.reloc
.exp
.X_op
!= O_constant
)
7087 inst
.error
= _("constant value required for number of registers");
7091 num_regs
= inst
.reloc
.exp
.X_add_number
;
7093 if (num_regs
< 1 || num_regs
> 4)
7095 inst
.error
= _("number of registers must be in the range [1:4]");
7102 inst
.instruction
|= CP_T_X
;
7105 inst
.instruction
|= CP_T_Y
;
7108 inst
.instruction
|= CP_T_Y
| CP_T_X
;
7116 if (inst
.instruction
& (CP_T_Pre
| CP_T_UD
)) /* ea/fd format. */
7122 /* The instruction specified "ea" or "fd", so we can only accept
7123 [Rn]{!}. The instruction does not really support stacking or
7124 unstacking, so we have to emulate these by setting appropriate
7125 bits and offsets. */
7126 if (skip_past_comma (&str
) == FAIL
7130 inst
.error
= BAD_ARGS
;
7135 skip_whitespace (str
);
7137 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
7140 skip_whitespace (str
);
7144 inst
.error
= BAD_ARGS
;
7156 _("r15 not allowed as base register with write-back");
7163 if (inst
.instruction
& CP_T_Pre
)
7165 /* Pre-decrement. */
7166 offset
= 3 * num_regs
;
7168 inst
.instruction
|= CP_T_WB
;
7172 /* Post-increment. */
7175 inst
.instruction
|= CP_T_WB
;
7176 offset
= 3 * num_regs
;
7180 /* No write-back, so convert this into a standard pre-increment
7181 instruction -- aesthetically more pleasing. */
7182 inst
.instruction
|= CP_T_Pre
| CP_T_UD
;
7187 inst
.instruction
|= offset
;
7189 else if (skip_past_comma (&str
) == FAIL
7190 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
7193 inst
.error
= BAD_ARGS
;
7204 skip_whitespace (str
);
7206 if (fp_reg_required_here (&str
, 12) == FAIL
)
7209 inst
.error
= BAD_ARGS
;
7213 if (skip_past_comma (&str
) == FAIL
7214 || fp_reg_required_here (&str
, 16) == FAIL
)
7217 inst
.error
= BAD_ARGS
;
7221 if (skip_past_comma (&str
) == FAIL
7222 || fp_op2 (&str
) == FAIL
)
7225 inst
.error
= BAD_ARGS
;
7234 do_fpa_monadic (str
)
7237 skip_whitespace (str
);
7239 if (fp_reg_required_here (&str
, 12) == FAIL
)
7242 inst
.error
= BAD_ARGS
;
7246 if (skip_past_comma (&str
) == FAIL
7247 || fp_op2 (&str
) == FAIL
)
7250 inst
.error
= BAD_ARGS
;
7262 skip_whitespace (str
);
7264 if (fp_reg_required_here (&str
, 16) == FAIL
)
7267 inst
.error
= BAD_ARGS
;
7271 if (skip_past_comma (&str
) == FAIL
7272 || fp_op2 (&str
) == FAIL
)
7275 inst
.error
= BAD_ARGS
;
7284 do_fpa_from_reg (str
)
7287 skip_whitespace (str
);
7289 if (fp_reg_required_here (&str
, 16) == FAIL
)
7292 inst
.error
= BAD_ARGS
;
7296 if (skip_past_comma (&str
) == FAIL
7297 || reg_required_here (&str
, 12) == FAIL
)
7300 inst
.error
= BAD_ARGS
;
7312 skip_whitespace (str
);
7314 if (reg_required_here (&str
, 12) == FAIL
)
7317 if (skip_past_comma (&str
) == FAIL
7318 || fp_reg_required_here (&str
, 0) == FAIL
)
7321 inst
.error
= BAD_ARGS
;
7330 vfp_sp_reg_required_here (str
, pos
)
7332 enum vfp_sp_reg_pos pos
;
7337 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_SN
].htab
)) != FAIL
)
7342 inst
.instruction
|= ((reg
>> 1) << 12) | ((reg
& 1) << 22);
7346 inst
.instruction
|= ((reg
>> 1) << 16) | ((reg
& 1) << 7);
7350 inst
.instruction
|= ((reg
>> 1) << 0) | ((reg
& 1) << 5);
7359 /* In the few cases where we might be able to accept something else
7360 this error can be overridden. */
7361 inst
.error
= _(all_reg_maps
[REG_TYPE_SN
].expected
);
7363 /* Restore the start point. */
7369 vfp_dp_reg_required_here (str
, pos
)
7371 enum vfp_dp_reg_pos pos
;
7376 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_DN
].htab
)) != FAIL
)
7381 inst
.instruction
|= reg
<< 12;
7385 inst
.instruction
|= reg
<< 16;
7389 inst
.instruction
|= reg
<< 0;
7398 /* In the few cases where we might be able to accept something else
7399 this error can be overridden. */
7400 inst
.error
= _(all_reg_maps
[REG_TYPE_DN
].expected
);
7402 /* Restore the start point. */
7408 do_vfp_sp_monadic (str
)
7411 skip_whitespace (str
);
7413 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7416 if (skip_past_comma (&str
) == FAIL
7417 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
7420 inst
.error
= BAD_ARGS
;
7429 do_vfp_dp_monadic (str
)
7432 skip_whitespace (str
);
7434 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7437 if (skip_past_comma (&str
) == FAIL
7438 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7441 inst
.error
= BAD_ARGS
;
7450 do_vfp_sp_dyadic (str
)
7453 skip_whitespace (str
);
7455 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7458 if (skip_past_comma (&str
) == FAIL
7459 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
7460 || skip_past_comma (&str
) == FAIL
7461 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
7464 inst
.error
= BAD_ARGS
;
7473 do_vfp_dp_dyadic (str
)
7476 skip_whitespace (str
);
7478 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7481 if (skip_past_comma (&str
) == FAIL
7482 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
7483 || skip_past_comma (&str
) == FAIL
7484 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7487 inst
.error
= BAD_ARGS
;
7496 do_vfp_reg_from_sp (str
)
7499 skip_whitespace (str
);
7501 if (reg_required_here (&str
, 12) == FAIL
)
7504 if (skip_past_comma (&str
) == FAIL
7505 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
7508 inst
.error
= BAD_ARGS
;
7517 do_vfp_sp_reg2 (str
)
7520 skip_whitespace (str
);
7522 if (reg_required_here (&str
, 12) == FAIL
)
7525 if (skip_past_comma (&str
) == FAIL
7526 || reg_required_here (&str
, 16) == FAIL
7527 || skip_past_comma (&str
) == FAIL
)
7530 inst
.error
= BAD_ARGS
;
7534 /* We require exactly two consecutive SP registers. */
7535 if (vfp_sp_reg_list (&str
, VFP_REG_Sm
) != 2)
7538 inst
.error
= _("only two consecutive VFP SP registers allowed here");
7546 do_vfp_sp_from_reg (str
)
7549 skip_whitespace (str
);
7551 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
7554 if (skip_past_comma (&str
) == FAIL
7555 || reg_required_here (&str
, 12) == FAIL
)
7558 inst
.error
= BAD_ARGS
;
7567 do_vfp_reg_from_dp (str
)
7570 skip_whitespace (str
);
7572 if (reg_required_here (&str
, 12) == FAIL
)
7575 if (skip_past_comma (&str
) == FAIL
7576 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
7579 inst
.error
= BAD_ARGS
;
7588 do_vfp_reg2_from_dp (str
)
7591 skip_whitespace (str
);
7593 if (reg_required_here (&str
, 12) == FAIL
)
7596 if (skip_past_comma (&str
) == FAIL
7597 || reg_required_here (&str
, 16) == FAIL
7598 || skip_past_comma (&str
) == FAIL
7599 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7602 inst
.error
= BAD_ARGS
;
7611 do_vfp_dp_from_reg (str
)
7614 skip_whitespace (str
);
7616 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
7619 if (skip_past_comma (&str
) == FAIL
7620 || reg_required_here (&str
, 12) == FAIL
)
7623 inst
.error
= BAD_ARGS
;
7632 do_vfp_dp_from_reg2 (str
)
7635 skip_whitespace (str
);
7637 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7640 if (skip_past_comma (&str
) == FAIL
7641 || reg_required_here (&str
, 12) == FAIL
7642 || skip_past_comma (&str
) == FAIL
7643 || reg_required_here (&str
, 16))
7646 inst
.error
= BAD_ARGS
;
7654 static const struct vfp_reg
*
7661 const struct vfp_reg
*vreg
;
7665 /* Find the end of the current token. */
7670 while (ISALPHA (c
));
7675 for (vreg
= vfp_regs
+ 0;
7676 vreg
< vfp_regs
+ sizeof (vfp_regs
) / sizeof (struct vfp_reg
);
7679 if (strcmp (start
, vreg
->name
) == 0)
7692 vfp_psr_required_here (str
)
7696 const struct vfp_reg
*vreg
;
7698 vreg
= vfp_psr_parse (str
);
7702 inst
.instruction
|= vreg
->regno
;
7706 inst
.error
= _("VFP system register expected");
7713 do_vfp_reg_from_ctrl (str
)
7716 skip_whitespace (str
);
7718 if (reg_required_here (&str
, 12) == FAIL
)
7721 if (skip_past_comma (&str
) == FAIL
7722 || vfp_psr_required_here (&str
) == FAIL
)
7725 inst
.error
= BAD_ARGS
;
7734 do_vfp_ctrl_from_reg (str
)
7737 skip_whitespace (str
);
7739 if (vfp_psr_required_here (&str
) == FAIL
)
7742 if (skip_past_comma (&str
) == FAIL
7743 || reg_required_here (&str
, 12) == FAIL
)
7746 inst
.error
= BAD_ARGS
;
7755 do_vfp_sp_ldst (str
)
7758 skip_whitespace (str
);
7760 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7763 inst
.error
= BAD_ARGS
;
7767 if (skip_past_comma (&str
) == FAIL
7768 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
7771 inst
.error
= BAD_ARGS
;
7780 do_vfp_dp_ldst (str
)
7783 skip_whitespace (str
);
7785 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7788 inst
.error
= BAD_ARGS
;
7792 if (skip_past_comma (&str
) == FAIL
7793 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
7796 inst
.error
= BAD_ARGS
;
7804 /* Parse and encode a VFP SP register list, storing the initial
7805 register in position POS and returning the range as the result. If
7806 the string is invalid return FAIL (an invalid range). */
7808 vfp_sp_reg_list (str
, pos
)
7810 enum vfp_sp_reg_pos pos
;
7818 unsigned long mask
= 0;
7825 skip_whitespace (*str
);
7827 tempinst
= inst
.instruction
;
7831 inst
.instruction
= 0;
7833 if ((new_base
= vfp_sp_reg_required_here (str
, pos
)) == FAIL
)
7836 if (count
== 0 || base_reg
> new_base
)
7838 base_reg
= new_base
;
7839 base_bits
= inst
.instruction
;
7842 if (mask
& (1 << new_base
))
7844 inst
.error
= _("invalid register list");
7848 if ((mask
>> new_base
) != 0 && ! warned
)
7850 as_tsktsk (_("register list not in ascending order"));
7854 mask
|= 1 << new_base
;
7857 skip_whitespace (*str
);
7859 if (**str
== '-') /* We have the start of a range expression */
7866 = arm_reg_parse (str
, all_reg_maps
[REG_TYPE_SN
].htab
))
7869 inst
.error
= _(all_reg_maps
[REG_TYPE_SN
].expected
);
7873 if (high_range
<= new_base
)
7875 inst
.error
= _("register range not in ascending order");
7879 for (new_base
++; new_base
<= high_range
; new_base
++)
7881 if (mask
& (1 << new_base
))
7883 inst
.error
= _("invalid register list");
7887 mask
|= 1 << new_base
;
7892 while (skip_past_comma (str
) != FAIL
);
7896 inst
.error
= _("invalid register list");
7904 /* Sanity check -- should have raised a parse error above. */
7905 if (count
== 0 || count
> 32)
7908 /* Final test -- the registers must be consecutive. */
7911 if ((mask
& (1 << base_reg
++)) == 0)
7913 inst
.error
= _("non-contiguous register range");
7918 inst
.instruction
= tempinst
| base_bits
;
7923 vfp_dp_reg_list (str
)
7931 unsigned long mask
= 0;
7938 skip_whitespace (*str
);
7940 tempinst
= inst
.instruction
;
7944 inst
.instruction
= 0;
7946 if ((new_base
= vfp_dp_reg_required_here (str
, VFP_REG_Dd
)) == FAIL
)
7949 if (count
== 0 || base_reg
> new_base
)
7951 base_reg
= new_base
;
7952 range
= inst
.instruction
;
7955 if (mask
& (1 << new_base
))
7957 inst
.error
= _("invalid register list");
7961 if ((mask
>> new_base
) != 0 && ! warned
)
7963 as_tsktsk (_("register list not in ascending order"));
7967 mask
|= 1 << new_base
;
7970 skip_whitespace (*str
);
7972 if (**str
== '-') /* We have the start of a range expression */
7979 = arm_reg_parse (str
, all_reg_maps
[REG_TYPE_DN
].htab
))
7982 inst
.error
= _(all_reg_maps
[REG_TYPE_DN
].expected
);
7986 if (high_range
<= new_base
)
7988 inst
.error
= _("register range not in ascending order");
7992 for (new_base
++; new_base
<= high_range
; new_base
++)
7994 if (mask
& (1 << new_base
))
7996 inst
.error
= _("invalid register list");
8000 mask
|= 1 << new_base
;
8005 while (skip_past_comma (str
) != FAIL
);
8009 inst
.error
= _("invalid register list");
8017 /* Sanity check -- should have raised a parse error above. */
8018 if (count
== 0 || count
> 16)
8021 /* Final test -- the registers must be consecutive. */
8024 if ((mask
& (1 << base_reg
++)) == 0)
8026 inst
.error
= _("non-contiguous register range");
8031 inst
.instruction
= tempinst
;
8036 vfp_sp_ldstm (str
, ldstm_type
)
8038 enum vfp_ldstm_type ldstm_type
;
8042 skip_whitespace (str
);
8044 if (reg_required_here (&str
, 16) == FAIL
)
8047 skip_whitespace (str
);
8051 inst
.instruction
|= WRITE_BACK
;
8054 else if (ldstm_type
!= VFP_LDSTMIA
)
8056 inst
.error
= _("this addressing mode requires base-register writeback");
8060 if (skip_past_comma (&str
) == FAIL
8061 || (range
= vfp_sp_reg_list (&str
, VFP_REG_Sd
)) == FAIL
)
8064 inst
.error
= BAD_ARGS
;
8068 inst
.instruction
|= range
;
8073 vfp_dp_ldstm (str
, ldstm_type
)
8075 enum vfp_ldstm_type ldstm_type
;
8079 skip_whitespace (str
);
8081 if (reg_required_here (&str
, 16) == FAIL
)
8084 skip_whitespace (str
);
8088 inst
.instruction
|= WRITE_BACK
;
8091 else if (ldstm_type
!= VFP_LDSTMIA
&& ldstm_type
!= VFP_LDSTMIAX
)
8093 inst
.error
= _("this addressing mode requires base-register writeback");
8097 if (skip_past_comma (&str
) == FAIL
8098 || (range
= vfp_dp_reg_list (&str
)) == FAIL
)
8101 inst
.error
= BAD_ARGS
;
8105 if (ldstm_type
== VFP_LDSTMIAX
|| ldstm_type
== VFP_LDSTMDBX
)
8108 inst
.instruction
|= range
;
8113 do_vfp_sp_ldstmia (str
)
8116 vfp_sp_ldstm (str
, VFP_LDSTMIA
);
8120 do_vfp_sp_ldstmdb (str
)
8123 vfp_sp_ldstm (str
, VFP_LDSTMDB
);
8127 do_vfp_dp_ldstmia (str
)
8130 vfp_dp_ldstm (str
, VFP_LDSTMIA
);
8134 do_vfp_dp_ldstmdb (str
)
8137 vfp_dp_ldstm (str
, VFP_LDSTMDB
);
8141 do_vfp_xp_ldstmia (str
)
8144 vfp_dp_ldstm (str
, VFP_LDSTMIAX
);
8148 do_vfp_xp_ldstmdb (str
)
8151 vfp_dp_ldstm (str
, VFP_LDSTMDBX
);
8155 do_vfp_sp_compare_z (str
)
8158 skip_whitespace (str
);
8160 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8163 inst
.error
= BAD_ARGS
;
8172 do_vfp_dp_compare_z (str
)
8175 skip_whitespace (str
);
8177 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8180 inst
.error
= BAD_ARGS
;
8189 do_vfp_dp_sp_cvt (str
)
8192 skip_whitespace (str
);
8194 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8197 if (skip_past_comma (&str
) == FAIL
8198 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
8201 inst
.error
= BAD_ARGS
;
8210 do_vfp_sp_dp_cvt (str
)
8213 skip_whitespace (str
);
8215 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8218 if (skip_past_comma (&str
) == FAIL
8219 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
8222 inst
.error
= BAD_ARGS
;
8230 /* Thumb specific routines. */
8232 /* Parse and validate that a register is of the right form, this saves
8233 repeated checking of this information in many similar cases.
8234 Unlike the 32-bit case we do not insert the register into the opcode
8235 here, since the position is often unknown until the full instruction
8239 thumb_reg (strp
, hi_lo
)
8245 if ((reg
= reg_required_here (strp
, -1)) == FAIL
)
8253 inst
.error
= _("lo register required");
8261 inst
.error
= _("hi register required");
8273 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
8277 thumb_add_sub (str
, subtract
)
8281 int Rd
, Rs
, Rn
= FAIL
;
8283 skip_whitespace (str
);
8285 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
8286 || skip_past_comma (&str
) == FAIL
)
8289 inst
.error
= BAD_ARGS
;
8293 if (is_immediate_prefix (*str
))
8297 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8302 if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8305 if (skip_past_comma (&str
) == FAIL
)
8307 /* Two operand format, shuffle the registers
8308 and pretend there are 3. */
8312 else if (is_immediate_prefix (*str
))
8315 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8318 else if ((Rn
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8322 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8323 for the latter case, EXPR contains the immediate that was found. */
8326 /* All register format. */
8327 if (Rd
> 7 || Rs
> 7 || Rn
> 7)
8331 inst
.error
= _("dest and source1 must be the same register");
8335 /* Can't do this for SUB. */
8338 inst
.error
= _("subtract valid only on lo regs");
8342 inst
.instruction
= (T_OPCODE_ADD_HI
8343 | (Rd
> 7 ? THUMB_H1
: 0)
8344 | (Rn
> 7 ? THUMB_H2
: 0));
8345 inst
.instruction
|= (Rd
& 7) | ((Rn
& 7) << 3);
8349 inst
.instruction
= subtract
? T_OPCODE_SUB_R3
: T_OPCODE_ADD_R3
;
8350 inst
.instruction
|= Rd
| (Rs
<< 3) | (Rn
<< 6);
8355 /* Immediate expression, now things start to get nasty. */
8357 /* First deal with HI regs, only very restricted cases allowed:
8358 Adjusting SP, and using PC or SP to get an address. */
8359 if ((Rd
> 7 && (Rd
!= REG_SP
|| Rs
!= REG_SP
))
8360 || (Rs
> 7 && Rs
!= REG_SP
&& Rs
!= REG_PC
))
8362 inst
.error
= _("invalid Hi register with immediate");
8366 if (inst
.reloc
.exp
.X_op
!= O_constant
)
8368 /* Value isn't known yet, all we can do is store all the fragments
8369 we know about in the instruction and let the reloc hacking
8371 inst
.instruction
= (subtract
? 0x8000 : 0) | (Rd
<< 4) | Rs
;
8372 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
8376 int offset
= inst
.reloc
.exp
.X_add_number
;
8386 /* Quick check, in case offset is MIN_INT. */
8389 inst
.error
= _("immediate value out of range");
8393 /* Note - you cannot convert a subtract of 0 into an
8394 add of 0 because the carry flag is set differently. */
8395 else if (offset
> 0)
8400 if (offset
& ~0x1fc)
8402 inst
.error
= _("invalid immediate value for stack adjust");
8405 inst
.instruction
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
8406 inst
.instruction
|= offset
>> 2;
8408 else if (Rs
== REG_PC
|| Rs
== REG_SP
)
8411 || (offset
& ~0x3fc))
8413 inst
.error
= _("invalid immediate for address calculation");
8416 inst
.instruction
= (Rs
== REG_PC
? T_OPCODE_ADD_PC
8418 inst
.instruction
|= (Rd
<< 8) | (offset
>> 2);
8424 inst
.error
= _("immediate value out of range");
8427 inst
.instruction
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
8428 inst
.instruction
|= (Rd
<< 8) | offset
;
8434 inst
.error
= _("immediate value out of range");
8437 inst
.instruction
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
8438 inst
.instruction
|= Rd
| (Rs
<< 3) | (offset
<< 6);
8447 thumb_shift (str
, shift
)
8451 int Rd
, Rs
, Rn
= FAIL
;
8453 skip_whitespace (str
);
8455 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
8456 || skip_past_comma (&str
) == FAIL
)
8459 inst
.error
= BAD_ARGS
;
8463 if (is_immediate_prefix (*str
))
8465 /* Two operand immediate format, set Rs to Rd. */
8468 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8473 if ((Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8476 if (skip_past_comma (&str
) == FAIL
)
8478 /* Two operand format, shuffle the registers
8479 and pretend there are 3. */
8483 else if (is_immediate_prefix (*str
))
8486 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8489 else if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8493 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8494 for the latter case, EXPR contains the immediate that was found. */
8500 inst
.error
= _("source1 and dest must be same register");
8506 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_R
; break;
8507 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_R
; break;
8508 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_R
; break;
8511 inst
.instruction
|= Rd
| (Rn
<< 3);
8517 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_I
; break;
8518 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_I
; break;
8519 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_I
; break;
8522 if (inst
.reloc
.exp
.X_op
!= O_constant
)
8524 /* Value isn't known yet, create a dummy reloc and let reloc
8525 hacking fix it up. */
8526 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_SHIFT
;
8530 unsigned shift_value
= inst
.reloc
.exp
.X_add_number
;
8532 if (shift_value
> 32 || (shift_value
== 32 && shift
== THUMB_LSL
))
8534 inst
.error
= _("invalid immediate for shift");
8538 /* Shifts of zero are handled by converting to LSL. */
8539 if (shift_value
== 0)
8540 inst
.instruction
= T_OPCODE_LSL_I
;
8542 /* Shifts of 32 are encoded as a shift of zero. */
8543 if (shift_value
== 32)
8546 inst
.instruction
|= shift_value
<< 6;
8549 inst
.instruction
|= Rd
| (Rs
<< 3);
8556 thumb_mov_compare (str
, move
)
8562 skip_whitespace (str
);
8564 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
8565 || skip_past_comma (&str
) == FAIL
)
8568 inst
.error
= BAD_ARGS
;
8572 if (is_immediate_prefix (*str
))
8575 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8578 else if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8583 if (Rs
< 8 && Rd
< 8)
8585 if (move
== THUMB_MOVE
)
8586 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
8587 since a MOV instruction produces unpredictable results. */
8588 inst
.instruction
= T_OPCODE_ADD_I3
;
8590 inst
.instruction
= T_OPCODE_CMP_LR
;
8591 inst
.instruction
|= Rd
| (Rs
<< 3);
8595 if (move
== THUMB_MOVE
)
8596 inst
.instruction
= T_OPCODE_MOV_HR
;
8598 inst
.instruction
= T_OPCODE_CMP_HR
;
8601 inst
.instruction
|= THUMB_H1
;
8604 inst
.instruction
|= THUMB_H2
;
8606 inst
.instruction
|= (Rd
& 7) | ((Rs
& 7) << 3);
8613 inst
.error
= _("only lo regs allowed with immediate");
8617 if (move
== THUMB_MOVE
)
8618 inst
.instruction
= T_OPCODE_MOV_I8
;
8620 inst
.instruction
= T_OPCODE_CMP_I8
;
8622 inst
.instruction
|= Rd
<< 8;
8624 if (inst
.reloc
.exp
.X_op
!= O_constant
)
8625 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_IMM
;
8628 unsigned value
= inst
.reloc
.exp
.X_add_number
;
8632 inst
.error
= _("invalid immediate");
8636 inst
.instruction
|= value
;
8644 thumb_load_store (str
, load_store
, size
)
8649 int Rd
, Rb
, Ro
= FAIL
;
8651 skip_whitespace (str
);
8653 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
8654 || skip_past_comma (&str
) == FAIL
)
8657 inst
.error
= BAD_ARGS
;
8664 if ((Rb
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8667 if (skip_past_comma (&str
) != FAIL
)
8669 if (is_immediate_prefix (*str
))
8672 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8675 else if ((Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8680 inst
.reloc
.exp
.X_op
= O_constant
;
8681 inst
.reloc
.exp
.X_add_number
= 0;
8686 inst
.error
= _("expected ']'");
8691 else if (*str
== '=')
8693 if (load_store
!= THUMB_LOAD
)
8695 inst
.error
= _("invalid pseudo operation");
8699 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
8702 skip_whitespace (str
);
8704 if (my_get_expression (& inst
.reloc
.exp
, & str
))
8709 if ( inst
.reloc
.exp
.X_op
!= O_constant
8710 && inst
.reloc
.exp
.X_op
!= O_symbol
)
8712 inst
.error
= "Constant expression expected";
8716 if (inst
.reloc
.exp
.X_op
== O_constant
8717 && ((inst
.reloc
.exp
.X_add_number
& ~0xFF) == 0))
8719 /* This can be done with a mov instruction. */
8721 inst
.instruction
= T_OPCODE_MOV_I8
| (Rd
<< 8);
8722 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
8726 /* Insert into literal pool. */
8727 if (add_to_lit_pool () == FAIL
)
8730 inst
.error
= "literal pool insertion failed";
8734 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8735 inst
.reloc
.pc_rel
= 1;
8736 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
8737 /* Adjust ARM pipeline offset to Thumb. */
8738 inst
.reloc
.exp
.X_add_number
+= 4;
8744 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8747 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
8748 inst
.reloc
.pc_rel
= 1;
8749 inst
.reloc
.exp
.X_add_number
-= 4; /* Pipeline offset. */
8750 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8755 if (Rb
== REG_PC
|| Rb
== REG_SP
)
8757 if (size
!= THUMB_WORD
)
8759 inst
.error
= _("byte or halfword not valid for base register");
8762 else if (Rb
== REG_PC
&& load_store
!= THUMB_LOAD
)
8764 inst
.error
= _("r15 based store not allowed");
8767 else if (Ro
!= FAIL
)
8769 inst
.error
= _("invalid base register for register offset");
8774 inst
.instruction
= T_OPCODE_LDR_PC
;
8775 else if (load_store
== THUMB_LOAD
)
8776 inst
.instruction
= T_OPCODE_LDR_SP
;
8778 inst
.instruction
= T_OPCODE_STR_SP
;
8780 inst
.instruction
|= Rd
<< 8;
8781 if (inst
.reloc
.exp
.X_op
== O_constant
)
8783 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
8785 if (offset
& ~0x3fc)
8787 inst
.error
= _("invalid offset");
8791 inst
.instruction
|= offset
>> 2;
8794 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8798 inst
.error
= _("invalid base register in load/store");
8801 else if (Ro
== FAIL
)
8803 /* Immediate offset. */
8804 if (size
== THUMB_WORD
)
8805 inst
.instruction
= (load_store
== THUMB_LOAD
8806 ? T_OPCODE_LDR_IW
: T_OPCODE_STR_IW
);
8807 else if (size
== THUMB_HALFWORD
)
8808 inst
.instruction
= (load_store
== THUMB_LOAD
8809 ? T_OPCODE_LDR_IH
: T_OPCODE_STR_IH
);
8811 inst
.instruction
= (load_store
== THUMB_LOAD
8812 ? T_OPCODE_LDR_IB
: T_OPCODE_STR_IB
);
8814 inst
.instruction
|= Rd
| (Rb
<< 3);
8816 if (inst
.reloc
.exp
.X_op
== O_constant
)
8818 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
8820 if (offset
& ~(0x1f << size
))
8822 inst
.error
= _("invalid offset");
8825 inst
.instruction
|= (offset
>> size
) << 6;
8828 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8832 /* Register offset. */
8833 if (size
== THUMB_WORD
)
8834 inst
.instruction
= (load_store
== THUMB_LOAD
8835 ? T_OPCODE_LDR_RW
: T_OPCODE_STR_RW
);
8836 else if (size
== THUMB_HALFWORD
)
8837 inst
.instruction
= (load_store
== THUMB_LOAD
8838 ? T_OPCODE_LDR_RH
: T_OPCODE_STR_RH
);
8840 inst
.instruction
= (load_store
== THUMB_LOAD
8841 ? T_OPCODE_LDR_RB
: T_OPCODE_STR_RB
);
8843 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
8849 /* A register must be given at this point.
8851 Shift is the place to put it in inst.instruction.
8853 Restores input start point on err.
8854 Returns the reg#, or FAIL. */
8857 mav_reg_required_here (str
, shift
, regtype
)
8860 enum arm_reg_type regtype
;
8865 if ((reg
= arm_reg_parse (str
, all_reg_maps
[regtype
].htab
)) != FAIL
)
8868 inst
.instruction
|= reg
<< shift
;
8873 /* Restore the start point. */
8876 /* In the few cases where we might be able to accept something else
8877 this error can be overridden. */
8878 inst
.error
= _(all_reg_maps
[regtype
].expected
);
8883 /* Cirrus Maverick Instructions. */
8885 /* Wrapper functions. */
8888 do_mav_binops_1a (str
)
8891 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVF
);
8895 do_mav_binops_1b (str
)
8898 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVD
);
8902 do_mav_binops_1c (str
)
8905 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVDX
);
8909 do_mav_binops_1d (str
)
8912 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVF
);
8916 do_mav_binops_1e (str
)
8919 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVD
);
8923 do_mav_binops_1f (str
)
8926 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVF
);
8930 do_mav_binops_1g (str
)
8933 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVD
);
8937 do_mav_binops_1h (str
)
8940 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVFX
);
8944 do_mav_binops_1i (str
)
8947 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVFX
);
8951 do_mav_binops_1j (str
)
8954 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVDX
);
8958 do_mav_binops_1k (str
)
8961 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVDX
);
8965 do_mav_binops_1l (str
)
8968 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVF
);
8972 do_mav_binops_1m (str
)
8975 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVD
);
8979 do_mav_binops_1n (str
)
8982 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
8986 do_mav_binops_1o (str
)
8989 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
8993 do_mav_binops_2a (str
)
8996 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVF
, REG_TYPE_RN
);
9000 do_mav_binops_2b (str
)
9003 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVD
, REG_TYPE_RN
);
9007 do_mav_binops_2c (str
)
9010 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVDX
, REG_TYPE_RN
);
9014 do_mav_binops_3a (str
)
9017 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVFX
);
9021 do_mav_binops_3b (str
)
9024 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVFX
, REG_TYPE_MVAX
);
9028 do_mav_binops_3c (str
)
9031 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVDX
);
9035 do_mav_binops_3d (str
)
9038 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVDX
, REG_TYPE_MVAX
);
9042 do_mav_triple_4a (str
)
9045 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_RN
);
9049 do_mav_triple_4b (str
)
9052 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_RN
);
9056 do_mav_triple_5a (str
)
9059 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVF
, REG_TYPE_MVF
);
9063 do_mav_triple_5b (str
)
9066 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVD
, REG_TYPE_MVD
);
9070 do_mav_triple_5c (str
)
9073 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
9077 do_mav_triple_5d (str
)
9080 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
9084 do_mav_triple_5e (str
)
9087 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVF
, REG_TYPE_MVF
, REG_TYPE_MVF
);
9091 do_mav_triple_5f (str
)
9094 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVD
, REG_TYPE_MVD
, REG_TYPE_MVD
);
9098 do_mav_triple_5g (str
)
9101 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
9105 do_mav_triple_5h (str
)
9108 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
9112 do_mav_quad_6a (str
)
9115 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
,
9120 do_mav_quad_6b (str
)
9123 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVAX
, REG_TYPE_MVFX
,
9127 /* cfmvsc32<cond> DSPSC,MVFX[15:0]. */
9129 do_mav_dspsc_1 (str
)
9132 skip_whitespace (str
);
9135 if (mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
9136 || skip_past_comma (&str
) == FAIL
9137 || mav_reg_required_here (&str
, 16, REG_TYPE_MVFX
) == FAIL
)
9140 inst
.error
= BAD_ARGS
;
9148 /* cfmv32sc<cond> MVFX[15:0],DSPSC. */
9150 do_mav_dspsc_2 (str
)
9153 skip_whitespace (str
);
9156 if (mav_reg_required_here (&str
, 0, REG_TYPE_MVFX
) == FAIL
9157 || skip_past_comma (&str
) == FAIL
9158 || mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
)
9161 inst
.error
= BAD_ARGS
;
9170 do_mav_shift_1 (str
)
9173 do_mav_shift (str
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
9177 do_mav_shift_2 (str
)
9180 do_mav_shift (str
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
9187 do_mav_ldst (str
, REG_TYPE_MVF
);
9194 do_mav_ldst (str
, REG_TYPE_MVD
);
9201 do_mav_ldst (str
, REG_TYPE_MVFX
);
9208 do_mav_ldst (str
, REG_TYPE_MVDX
);
9211 /* Isnsn like "foo X,Y". */
9214 do_mav_binops (str
, mode
, reg0
, reg1
)
9217 enum arm_reg_type reg0
;
9218 enum arm_reg_type reg1
;
9222 shift0
= mode
& 0xff;
9223 shift1
= (mode
>> 8) & 0xff;
9225 skip_whitespace (str
);
9227 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
9228 || skip_past_comma (&str
) == FAIL
9229 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
)
9232 inst
.error
= BAD_ARGS
;
9238 /* Isnsn like "foo X,Y,Z". */
9241 do_mav_triple (str
, mode
, reg0
, reg1
, reg2
)
9244 enum arm_reg_type reg0
;
9245 enum arm_reg_type reg1
;
9246 enum arm_reg_type reg2
;
9248 int shift0
, shift1
, shift2
;
9250 shift0
= mode
& 0xff;
9251 shift1
= (mode
>> 8) & 0xff;
9252 shift2
= (mode
>> 16) & 0xff;
9254 skip_whitespace (str
);
9256 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
9257 || skip_past_comma (&str
) == FAIL
9258 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
9259 || skip_past_comma (&str
) == FAIL
9260 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
)
9263 inst
.error
= BAD_ARGS
;
9269 /* Isnsn like "foo W,X,Y,Z".
9270 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
9273 do_mav_quad (str
, mode
, reg0
, reg1
, reg2
, reg3
)
9276 enum arm_reg_type reg0
;
9277 enum arm_reg_type reg1
;
9278 enum arm_reg_type reg2
;
9279 enum arm_reg_type reg3
;
9281 int shift0
, shift1
, shift2
, shift3
;
9283 shift0
= mode
& 0xff;
9284 shift1
= (mode
>> 8) & 0xff;
9285 shift2
= (mode
>> 16) & 0xff;
9286 shift3
= (mode
>> 24) & 0xff;
9288 skip_whitespace (str
);
9290 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
9291 || skip_past_comma (&str
) == FAIL
9292 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
9293 || skip_past_comma (&str
) == FAIL
9294 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
9295 || skip_past_comma (&str
) == FAIL
9296 || mav_reg_required_here (&str
, shift3
, reg3
) == FAIL
)
9299 inst
.error
= BAD_ARGS
;
9305 /* Maverick shift immediate instructions.
9306 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
9307 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
9310 do_mav_shift (str
, reg0
, reg1
)
9312 enum arm_reg_type reg0
;
9313 enum arm_reg_type reg1
;
9318 skip_whitespace (str
);
9322 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
9323 || skip_past_comma (&str
) == FAIL
9324 || mav_reg_required_here (&str
, 16, reg1
) == FAIL
9325 || skip_past_comma (&str
) == FAIL
)
9328 inst
.error
= BAD_ARGS
;
9332 /* Calculate the immediate operand.
9333 The operand is a 7bit signed number. */
9334 skip_whitespace (str
);
9339 if (!ISDIGIT (*str
) && *str
!= '-')
9341 inst
.error
= _("expecting immediate, 7bit operand");
9351 for (imm
= 0; *str
&& ISDIGIT (*str
); ++str
)
9352 imm
= imm
* 10 + *str
- '0';
9356 inst
.error
= _("immediate out of range");
9360 /* Make negative imm's into 7bit signed numbers. */
9367 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
9368 Bits 5-7 of the insn should have bits 4-6 of the immediate.
9369 Bit 4 should be 0. */
9370 imm
= (imm
& 0xf) | ((imm
& 0x70) << 1);
9372 inst
.instruction
|= imm
;
9377 mav_parse_offset (str
, negative
)
9386 skip_whitespace (p
);
9399 inst
.error
= _("offset expected");
9403 for (offset
= 0; *p
&& ISDIGIT (*p
); ++p
)
9404 offset
= offset
* 10 + *p
- '0';
9408 inst
.error
= _("offset out of range");
9414 return *negative
? -offset
: offset
;
9417 /* Maverick load/store instructions.
9418 <insn><cond> CRd,[Rn,<offset>]{!}.
9419 <insn><cond> CRd,[Rn],<offset>. */
9422 do_mav_ldst (str
, reg0
)
9424 enum arm_reg_type reg0
;
9426 int offset
, negative
;
9428 skip_whitespace (str
);
9430 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
9431 || skip_past_comma (&str
) == FAIL
9433 || reg_required_here (&str
, 16) == FAIL
)
9436 if (skip_past_comma (&str
) == SUCCESS
)
9438 /* You are here: "<offset>]{!}". */
9439 inst
.instruction
|= PRE_INDEX
;
9441 offset
= mav_parse_offset (&str
, &negative
);
9448 inst
.error
= _("missing ]");
9454 inst
.instruction
|= WRITE_BACK
;
9460 /* You are here: "], <offset>". */
9463 inst
.error
= _("missing ]");
9467 if (skip_past_comma (&str
) == FAIL
9468 || (offset
= mav_parse_offset (&str
, &negative
), inst
.error
))
9471 inst
.instruction
|= CP_T_WB
; /* Post indexed, set bit W. */
9477 inst
.instruction
|= CP_T_UD
; /* Postive, so set bit U. */
9479 inst
.instruction
|= offset
>> 2;
9485 inst
.error
= BAD_ARGS
;
9498 /* Handle the Format 4 instructions that do not have equivalents in other
9499 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
9508 skip_whitespace (str
);
9510 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9511 || skip_past_comma (&str
) == FAIL
9512 || (Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9514 inst
.error
= BAD_ARGS
;
9518 if (skip_past_comma (&str
) != FAIL
)
9520 /* Three operand format not allowed for TST, CMN, NEG and MVN.
9521 (It isn't allowed for CMP either, but that isn't handled by this
9523 if (inst
.instruction
== T_OPCODE_TST
9524 || inst
.instruction
== T_OPCODE_CMN
9525 || inst
.instruction
== T_OPCODE_NEG
9526 || inst
.instruction
== T_OPCODE_MVN
)
9528 inst
.error
= BAD_ARGS
;
9532 if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9537 inst
.error
= _("dest and source1 must be the same register");
9543 if (inst
.instruction
== T_OPCODE_MUL
9545 as_tsktsk (_("Rs and Rd must be different in MUL"));
9547 inst
.instruction
|= Rd
| (Rs
<< 3);
9555 thumb_add_sub (str
, 0);
9562 thumb_shift (str
, THUMB_ASR
);
9569 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9571 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH9
;
9572 inst
.reloc
.pc_rel
= 1;
9580 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9582 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH12
;
9583 inst
.reloc
.pc_rel
= 1;
9587 /* Find the real, Thumb encoded start of a Thumb function. */
9590 find_real_start (symbolP
)
9594 const char * name
= S_GET_NAME (symbolP
);
9595 symbolS
* new_target
;
9597 /* This definiton must agree with the one in gcc/config/arm/thumb.c. */
9598 #define STUB_NAME ".real_start_of"
9603 /* Names that start with '.' are local labels, not function entry points.
9604 The compiler may generate BL instructions to these labels because it
9605 needs to perform a branch to a far away location. */
9609 real_start
= malloc (strlen (name
) + strlen (STUB_NAME
) + 1);
9610 sprintf (real_start
, "%s%s", STUB_NAME
, name
);
9612 new_target
= symbol_find (real_start
);
9614 if (new_target
== NULL
)
9616 as_warn ("Failed to find real start of function: %s\n", name
);
9617 new_target
= symbolP
;
9629 if (my_get_expression (& inst
.reloc
.exp
, & str
))
9632 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH23
;
9633 inst
.reloc
.pc_rel
= 1;
9636 /* If the destination of the branch is a defined symbol which does not have
9637 the THUMB_FUNC attribute, then we must be calling a function which has
9638 the (interfacearm) attribute. We look for the Thumb entry point to that
9639 function and change the branch to refer to that function instead. */
9640 if ( inst
.reloc
.exp
.X_op
== O_symbol
9641 && inst
.reloc
.exp
.X_add_symbol
!= NULL
9642 && S_IS_DEFINED (inst
.reloc
.exp
.X_add_symbol
)
9643 && ! THUMB_IS_FUNC (inst
.reloc
.exp
.X_add_symbol
))
9644 inst
.reloc
.exp
.X_add_symbol
=
9645 find_real_start (inst
.reloc
.exp
.X_add_symbol
);
9654 skip_whitespace (str
);
9656 if ((reg
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
9659 /* This sets THUMB_H2 from the top bit of reg. */
9660 inst
.instruction
|= reg
<< 3;
9662 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
9663 should cause the alignment to be checked once it is known. This is
9664 because BX PC only works if the instruction is word aligned. */
9673 thumb_mov_compare (str
, THUMB_COMPARE
);
9683 skip_whitespace (str
);
9685 if ((Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9689 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
9693 if (skip_past_comma (&str
) == FAIL
9694 || (range
= reg_list (&str
)) == FAIL
)
9697 inst
.error
= BAD_ARGS
;
9701 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
9703 /* This really doesn't seem worth it. */
9704 inst
.reloc
.type
= BFD_RELOC_NONE
;
9705 inst
.error
= _("expression too complex");
9711 inst
.error
= _("only lo-regs valid in load/store multiple");
9715 inst
.instruction
|= (Rb
<< 8) | range
;
9723 thumb_load_store (str
, THUMB_LOAD
, THUMB_WORD
);
9730 thumb_load_store (str
, THUMB_LOAD
, THUMB_BYTE
);
9737 thumb_load_store (str
, THUMB_LOAD
, THUMB_HALFWORD
);
9746 skip_whitespace (str
);
9748 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9749 || skip_past_comma (&str
) == FAIL
9751 || (Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9752 || skip_past_comma (&str
) == FAIL
9753 || (Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9757 inst
.error
= _("syntax: ldrs[b] Rd, [Rb, Ro]");
9761 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
9769 thumb_shift (str
, THUMB_LSL
);
9776 thumb_shift (str
, THUMB_LSR
);
9783 thumb_mov_compare (str
, THUMB_MOVE
);
9792 skip_whitespace (str
);
9794 if ((range
= reg_list (&str
)) == FAIL
)
9797 inst
.error
= BAD_ARGS
;
9801 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
9803 /* This really doesn't seem worth it. */
9804 inst
.reloc
.type
= BFD_RELOC_NONE
;
9805 inst
.error
= _("expression too complex");
9811 if ((inst
.instruction
== T_OPCODE_PUSH
9812 && (range
& ~0xff) == 1 << REG_LR
)
9813 || (inst
.instruction
== T_OPCODE_POP
9814 && (range
& ~0xff) == 1 << REG_PC
))
9816 inst
.instruction
|= THUMB_PP_PC_LR
;
9821 inst
.error
= _("invalid register list to push/pop instruction");
9826 inst
.instruction
|= range
;
9834 thumb_load_store (str
, THUMB_STORE
, THUMB_WORD
);
9841 thumb_load_store (str
, THUMB_STORE
, THUMB_BYTE
);
9848 thumb_load_store (str
, THUMB_STORE
, THUMB_HALFWORD
);
9855 thumb_add_sub (str
, 1);
9862 skip_whitespace (str
);
9864 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9867 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
9878 /* This is a pseudo-op of the form "adr rd, label" to be converted
9879 into a relative address of the form "add rd, pc, #label-.-4". */
9880 skip_whitespace (str
);
9882 /* Store Rd in temporary location inside instruction. */
9883 if ((reg
= reg_required_here (&str
, 4)) == FAIL
9884 || (reg
> 7) /* For Thumb reg must be r0..r7. */
9885 || skip_past_comma (&str
) == FAIL
9886 || my_get_expression (&inst
.reloc
.exp
, &str
))
9889 inst
.error
= BAD_ARGS
;
9893 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
9894 inst
.reloc
.exp
.X_add_number
-= 4; /* PC relative adjust. */
9895 inst
.reloc
.pc_rel
= 1;
9896 inst
.instruction
|= REG_PC
; /* Rd is already placed into the instruction. */
9902 insert_reg (r
, htab
)
9903 const struct reg_entry
*r
;
9904 struct hash_control
*htab
;
9906 int len
= strlen (r
->name
) + 2;
9907 char * buf
= (char *) xmalloc (len
);
9908 char * buf2
= (char *) xmalloc (len
);
9911 #ifdef REGISTER_PREFIX
9912 buf
[i
++] = REGISTER_PREFIX
;
9915 strcpy (buf
+ i
, r
->name
);
9917 for (i
= 0; buf
[i
]; i
++)
9918 buf2
[i
] = TOUPPER (buf
[i
]);
9922 hash_insert (htab
, buf
, (PTR
) r
);
9923 hash_insert (htab
, buf2
, (PTR
) r
);
9928 struct reg_map
*map
;
9930 const struct reg_entry
*r
;
9932 if ((map
->htab
= hash_new ()) == NULL
)
9933 as_fatal (_("virtual memory exhausted"));
9935 for (r
= map
->names
; r
->name
!= NULL
; r
++)
9936 insert_reg (r
, map
->htab
);
9940 insert_reg_alias (str
, regnum
, htab
)
9943 struct hash_control
*htab
;
9945 struct reg_entry
*new =
9946 (struct reg_entry
*) xmalloc (sizeof (struct reg_entry
));
9947 char *name
= xmalloc (strlen (str
) + 1);
9951 new->number
= regnum
;
9953 hash_insert (htab
, name
, (PTR
) new);
9956 /* Look for the .req directive. This is of the form:
9958 newname .req existing_name
9960 If we find one, or if it looks sufficiently like one that we want to
9961 handle any error here, return non-zero. Otherwise return zero. */
9963 create_register_alias (newname
, p
)
9971 skip_whitespace (q
);
9976 if (*q
&& !strncmp (q
, ".req ", 5))
9981 #ifdef IGNORE_OPCODE_CASE
9982 newname
= original_case_string
;
9984 copy_of_str
= newname
;
9987 skip_whitespace (q
);
9989 for (r
= q
; *r
!= '\0'; r
++)
9995 enum arm_reg_type new_type
, old_type
;
10000 old_type
= arm_reg_parse_any (q
);
10003 new_type
= arm_reg_parse_any (newname
);
10005 if (new_type
== REG_TYPE_MAX
)
10007 if (old_type
!= REG_TYPE_MAX
)
10009 old_regno
= arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
);
10010 insert_reg_alias (newname
, old_regno
,
10011 all_reg_maps
[old_type
].htab
);
10014 as_warn (_("register '%s' does not exist\n"), q
);
10016 else if (old_type
== REG_TYPE_MAX
)
10018 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
10023 /* Do not warn about redefinitions to the same alias. */
10024 if (new_type
!= old_type
10025 || (arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
)
10026 != arm_reg_parse (&q
, all_reg_maps
[new_type
].htab
)))
10027 as_warn (_("ignoring redefinition of register alias '%s'"),
10033 as_warn (_("ignoring incomplete .req pseuso op"));
10043 set_constant_flonums ()
10047 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
10048 if (atof_ieee ((char *) fp_const
[i
], 'x', fp_values
[i
]) == NULL
)
10052 /* Iterate over the base tables to create the instruction patterns. */
10054 build_arm_ops_hsh ()
10058 static struct obstack insn_obstack
;
10060 obstack_begin (&insn_obstack
, 4000);
10062 for (i
= 0; i
< sizeof (insns
) / sizeof (struct asm_opcode
); i
++)
10064 const struct asm_opcode
*insn
= insns
+ i
;
10066 if (insn
->cond_offset
!= 0)
10068 /* Insn supports conditional execution. Build the varaints
10069 and insert them in the hash table. */
10070 for (j
= 0; j
< sizeof (conds
) / sizeof (struct asm_cond
); j
++)
10072 unsigned len
= strlen (insn
->template);
10073 struct asm_opcode
*new;
10076 new = obstack_alloc (&insn_obstack
, sizeof (struct asm_opcode
));
10077 /* All condition codes are two characters. */
10078 template = obstack_alloc (&insn_obstack
, len
+ 3);
10080 strncpy (template, insn
->template, insn
->cond_offset
);
10081 strcpy (template + insn
->cond_offset
, conds
[j
].template);
10082 if (len
> insn
->cond_offset
)
10083 strcpy (template + insn
->cond_offset
+ 2,
10084 insn
->template + insn
->cond_offset
);
10085 new->template = template;
10086 new->cond_offset
= 0;
10087 new->variant
= insn
->variant
;
10088 new->parms
= insn
->parms
;
10089 new->value
= (insn
->value
& ~COND_MASK
) | conds
[j
].value
;
10091 hash_insert (arm_ops_hsh
, new->template, (PTR
) new);
10094 /* Finally, insert the unconditional insn in the table directly;
10095 no need to build a copy. */
10096 hash_insert (arm_ops_hsh
, insn
->template, (PTR
) insn
);
10100 #if defined OBJ_ELF || defined OBJ_COFF
10103 #define arm_Note Elf_External_Note
10107 unsigned char namesz
[4]; /* Size of entry's owner string. */
10108 unsigned char descsz
[4]; /* Size of the note descriptor. */
10109 unsigned char type
[4]; /* Interpretation of the descriptor. */
10110 char name
[1]; /* Start of the name+desc data. */
10114 /* The description is kept to a fix sized in order to make updating
10115 it and merging it easier. */
10116 #define ARM_NOTE_DESCRIPTION_LENGTH 8
10119 arm_add_note (name
, description
, type
)
10121 const char * description
;
10124 arm_Note note ATTRIBUTE_UNUSED
;
10126 unsigned int name_len
;
10128 name_len
= (strlen (name
) + 1 + 3) & ~3;
10130 p
= frag_more (sizeof (note
.namesz
));
10131 md_number_to_chars (p
, (valueT
) name_len
, sizeof (note
.namesz
));
10133 p
= frag_more (sizeof (note
.descsz
));
10134 md_number_to_chars (p
, (valueT
) ARM_NOTE_DESCRIPTION_LENGTH
, sizeof (note
.descsz
));
10136 p
= frag_more (sizeof (note
.type
));
10137 md_number_to_chars (p
, (valueT
) type
, sizeof (note
.type
));
10139 p
= frag_more (name_len
);
10142 p
= frag_more (ARM_NOTE_DESCRIPTION_LENGTH
);
10143 strncpy (p
, description
, ARM_NOTE_DESCRIPTION_LENGTH
);
10144 frag_align (2, 0, 0);
10154 if ( (arm_ops_hsh
= hash_new ()) == NULL
10155 || (arm_tops_hsh
= hash_new ()) == NULL
10156 || (arm_cond_hsh
= hash_new ()) == NULL
10157 || (arm_shift_hsh
= hash_new ()) == NULL
10158 || (arm_psr_hsh
= hash_new ()) == NULL
)
10159 as_fatal (_("virtual memory exhausted"));
10161 build_arm_ops_hsh ();
10162 for (i
= 0; i
< sizeof (tinsns
) / sizeof (struct thumb_opcode
); i
++)
10163 hash_insert (arm_tops_hsh
, tinsns
[i
].template, (PTR
) (tinsns
+ i
));
10164 for (i
= 0; i
< sizeof (conds
) / sizeof (struct asm_cond
); i
++)
10165 hash_insert (arm_cond_hsh
, conds
[i
].template, (PTR
) (conds
+ i
));
10166 for (i
= 0; i
< sizeof (shift_names
) / sizeof (struct asm_shift_name
); i
++)
10167 hash_insert (arm_shift_hsh
, shift_names
[i
].name
, (PTR
) (shift_names
+ i
));
10168 for (i
= 0; i
< sizeof (psrs
) / sizeof (struct asm_psr
); i
++)
10169 hash_insert (arm_psr_hsh
, psrs
[i
].template, (PTR
) (psrs
+ i
));
10171 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
10172 build_reg_hsh (all_reg_maps
+ i
);
10174 set_constant_flonums ();
10176 /* Set the cpu variant based on the command-line options. We prefer
10177 -mcpu= over -march= if both are set (as for GCC); and we prefer
10178 -mfpu= over any other way of setting the floating point unit.
10179 Use of legacy options with new options are faulted. */
10180 if (legacy_cpu
!= -1)
10182 if (mcpu_cpu_opt
!= -1 || march_cpu_opt
!= -1)
10183 as_bad (_("use of old and new-style options to set CPU type"));
10185 mcpu_cpu_opt
= legacy_cpu
;
10187 else if (mcpu_cpu_opt
== -1)
10188 mcpu_cpu_opt
= march_cpu_opt
;
10190 if (legacy_fpu
!= -1)
10192 if (mfpu_opt
!= -1)
10193 as_bad (_("use of old and new-style options to set FPU type"));
10195 mfpu_opt
= legacy_fpu
;
10197 else if (mfpu_opt
== -1)
10199 #if !(defined (TE_LINUX) || defined (TE_NetBSD))
10200 /* Some environments specify a default FPU. If they don't, infer it
10201 from the processor. */
10202 if (mcpu_fpu_opt
!= -1)
10203 mfpu_opt
= mcpu_fpu_opt
;
10205 mfpu_opt
= march_fpu_opt
;
10207 mfpu_opt
= FPU_DEFAULT
;
10211 if (mfpu_opt
== -1)
10213 if (mcpu_cpu_opt
== -1)
10214 mfpu_opt
= FPU_DEFAULT
;
10215 else if (mcpu_cpu_opt
& ARM_EXT_V5
)
10216 mfpu_opt
= FPU_ARCH_VFP_V2
;
10218 mfpu_opt
= FPU_ARCH_FPA
;
10221 if (mcpu_cpu_opt
== -1)
10222 mcpu_cpu_opt
= CPU_DEFAULT
;
10224 cpu_variant
= mcpu_cpu_opt
| mfpu_opt
;
10226 #if defined OBJ_COFF || defined OBJ_ELF
10228 unsigned int flags
= 0;
10230 /* Set the flags in the private structure. */
10231 if (uses_apcs_26
) flags
|= F_APCS26
;
10232 if (support_interwork
) flags
|= F_INTERWORK
;
10233 if (uses_apcs_float
) flags
|= F_APCS_FLOAT
;
10234 if (pic_code
) flags
|= F_PIC
;
10235 if ((cpu_variant
& FPU_ANY
) == FPU_NONE
10236 || (cpu_variant
& FPU_ANY
) == FPU_ARCH_VFP
) /* VFP layout only. */
10237 flags
|= F_SOFT_FLOAT
;
10238 /* Using VFP conventions (even if soft-float). */
10239 if (cpu_variant
& FPU_VFP_EXT_NONE
) flags
|= F_VFP_FLOAT
;
10241 #if defined OBJ_ELF
10242 if (cpu_variant
& ARM_CEXT_MAVERICK
)
10244 flags
^= F_SOFT_FLOAT
;
10245 flags
|= EF_ARM_MAVERICK_FLOAT
;
10249 bfd_set_private_flags (stdoutput
, flags
);
10251 /* We have run out flags in the COFF header to encode the
10252 status of ATPCS support, so instead we create a dummy,
10253 empty, debug section called .arm.atpcs. */
10258 sec
= bfd_make_section (stdoutput
, ".arm.atpcs");
10262 bfd_set_section_flags
10263 (stdoutput
, sec
, SEC_READONLY
| SEC_DEBUGGING
/* | SEC_HAS_CONTENTS */);
10264 bfd_set_section_size (stdoutput
, sec
, 0);
10265 bfd_set_section_contents (stdoutput
, sec
, NULL
, 0, 0);
10271 /* Record the CPU type as well. */
10272 switch (cpu_variant
& ARM_CPU_MASK
)
10275 mach
= bfd_mach_arm_2
;
10278 case ARM_3
: /* Also ARM_250. */
10279 mach
= bfd_mach_arm_2a
;
10282 case ARM_6
: /* Also ARM_7. */
10283 mach
= bfd_mach_arm_3
;
10287 mach
= bfd_mach_arm_unknown
;
10291 /* Catch special cases. */
10292 if (cpu_variant
& ARM_CEXT_IWMMXT
)
10293 mach
= bfd_mach_arm_iWMMXt
;
10294 else if (cpu_variant
& ARM_CEXT_XSCALE
)
10295 mach
= bfd_mach_arm_XScale
;
10296 else if (cpu_variant
& ARM_CEXT_MAVERICK
)
10297 mach
= bfd_mach_arm_ep9312
;
10298 else if (cpu_variant
& ARM_EXT_V5E
)
10299 mach
= bfd_mach_arm_5TE
;
10300 else if (cpu_variant
& ARM_EXT_V5
)
10302 if (cpu_variant
& ARM_EXT_V4T
)
10303 mach
= bfd_mach_arm_5T
;
10305 mach
= bfd_mach_arm_5
;
10307 else if (cpu_variant
& ARM_EXT_V4
)
10309 if (cpu_variant
& ARM_EXT_V4T
)
10310 mach
= bfd_mach_arm_4T
;
10312 mach
= bfd_mach_arm_4
;
10314 else if (cpu_variant
& ARM_EXT_V3M
)
10315 mach
= bfd_mach_arm_3M
;
10317 #if 0 /* Suppressed - for now. */
10318 #if defined (OBJ_ELF) || defined (OBJ_COFF)
10320 /* Create a .note section to fully identify this arm binary. */
10322 #define NOTE_ARCH_STRING "arch: "
10324 #if defined OBJ_COFF && ! defined NT_VERSION
10325 #define NT_VERSION 1
10330 segT current_seg
= now_seg
;
10331 subsegT current_subseg
= now_subseg
;
10332 asection
* arm_arch
;
10333 const char * arch_string
;
10335 arm_arch
= bfd_make_section_old_way (stdoutput
, ARM_NOTE_SECTION
);
10338 bfd_set_section_flags (stdoutput
, arm_arch
,
10339 SEC_DATA
| SEC_ALLOC
| SEC_LOAD
| SEC_LINK_ONCE \
10340 | SEC_HAS_CONTENTS
);
10342 arm_arch
->output_section
= arm_arch
;
10343 subseg_set (arm_arch
, 0);
10348 case bfd_mach_arm_unknown
: arch_string
= "unknown"; break;
10349 case bfd_mach_arm_2
: arch_string
= "armv2"; break;
10350 case bfd_mach_arm_2a
: arch_string
= "armv2a"; break;
10351 case bfd_mach_arm_3
: arch_string
= "armv3"; break;
10352 case bfd_mach_arm_3M
: arch_string
= "armv3M"; break;
10353 case bfd_mach_arm_4
: arch_string
= "armv4"; break;
10354 case bfd_mach_arm_4T
: arch_string
= "armv4t"; break;
10355 case bfd_mach_arm_5
: arch_string
= "armv5"; break;
10356 case bfd_mach_arm_5T
: arch_string
= "armv5t"; break;
10357 case bfd_mach_arm_5TE
: arch_string
= "armv5te"; break;
10358 case bfd_mach_arm_XScale
: arch_string
= "XScale"; break;
10359 case bfd_mach_arm_ep9312
: arch_string
= "ep9312"; break;
10360 case bfd_mach_arm_iWMMXt
: arch_string
= "iWMMXt"; break;
10363 arm_add_note (NOTE_ARCH_STRING
, arch_string
, NT_ARCH
);
10365 subseg_set (current_seg
, current_subseg
);
10368 #endif /* Suppressed code. */
10370 bfd_set_arch_mach (stdoutput
, TARGET_ARCH
, mach
);
10373 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
10374 for use in the a.out file, and stores them in the array pointed to by buf.
10375 This knows about the endian-ness of the target machine and does
10376 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
10377 2 (short) and 4 (long) Floating numbers are put out as a series of
10378 LITTLENUMS (shorts, here at least). */
10381 md_number_to_chars (buf
, val
, n
)
10386 if (target_big_endian
)
10387 number_to_chars_bigendian (buf
, val
, n
);
10389 number_to_chars_littleendian (buf
, val
, n
);
10393 md_chars_to_number (buf
, n
)
10398 unsigned char * where
= (unsigned char *) buf
;
10400 if (target_big_endian
)
10405 result
|= (*where
++ & 255);
10413 result
|= (where
[n
] & 255);
10420 /* Turn a string in input_line_pointer into a floating point constant
10421 of type TYPE, and store the appropriate bytes in *LITP. The number
10422 of LITTLENUMS emitted is stored in *SIZEP. An error message is
10423 returned, or NULL on OK.
10425 Note that fp constants aren't represent in the normal way on the ARM.
10426 In big endian mode, things are as expected. However, in little endian
10427 mode fp constants are big-endian word-wise, and little-endian byte-wise
10428 within the words. For example, (double) 1.1 in big endian mode is
10429 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
10430 the byte sequence 99 99 f1 3f 9a 99 99 99.
10432 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
10435 md_atof (type
, litP
, sizeP
)
10441 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
10473 return _("bad call to MD_ATOF()");
10476 t
= atof_ieee (input_line_pointer
, type
, words
);
10478 input_line_pointer
= t
;
10481 if (target_big_endian
)
10483 for (i
= 0; i
< prec
; i
++)
10485 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
10491 if (cpu_variant
& FPU_ARCH_VFP
)
10492 for (i
= prec
- 1; i
>= 0; i
--)
10494 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
10498 /* For a 4 byte float the order of elements in `words' is 1 0.
10499 For an 8 byte float the order is 1 0 3 2. */
10500 for (i
= 0; i
< prec
; i
+= 2)
10502 md_number_to_chars (litP
, (valueT
) words
[i
+ 1], 2);
10503 md_number_to_chars (litP
+ 2, (valueT
) words
[i
], 2);
10511 /* The knowledge of the PC's pipeline offset is built into the insns
10515 md_pcrel_from (fixP
)
10519 && S_GET_SEGMENT (fixP
->fx_addsy
) == undefined_section
10520 && fixP
->fx_subsy
== NULL
)
10523 if (fixP
->fx_pcrel
&& (fixP
->fx_r_type
== BFD_RELOC_ARM_THUMB_ADD
))
10525 /* PC relative addressing on the Thumb is slightly odd
10526 as the bottom two bits of the PC are forced to zero
10527 for the calculation. */
10528 return (fixP
->fx_where
+ fixP
->fx_frag
->fr_address
) & ~3;
10532 /* The pattern was adjusted to accomodate CE's off-by-one fixups,
10533 so we un-adjust here to compensate for the accomodation. */
10534 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
+ 8;
10536 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
10540 /* Round up a section size to the appropriate boundary. */
10543 md_section_align (segment
, size
)
10544 segT segment ATTRIBUTE_UNUSED
;
10550 /* Round all sects to multiple of 4. */
10551 return (size
+ 3) & ~3;
10555 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
10556 Otherwise we have no need to default values of symbols. */
10559 md_undefined_symbol (name
)
10560 char * name ATTRIBUTE_UNUSED
;
10563 if (name
[0] == '_' && name
[1] == 'G'
10564 && streq (name
, GLOBAL_OFFSET_TABLE_NAME
))
10568 if (symbol_find (name
))
10569 as_bad ("GOT already in the symbol table");
10571 GOT_symbol
= symbol_new (name
, undefined_section
,
10572 (valueT
) 0, & zero_address_frag
);
10582 /* arm_reg_parse () := if it looks like a register, return its token and
10583 advance the pointer. */
10586 arm_reg_parse (ccp
, htab
)
10587 register char ** ccp
;
10588 struct hash_control
*htab
;
10590 char * start
= * ccp
;
10593 struct reg_entry
* reg
;
10595 #ifdef REGISTER_PREFIX
10596 if (*start
!= REGISTER_PREFIX
)
10601 #ifdef OPTIONAL_REGISTER_PREFIX
10602 if (*p
== OPTIONAL_REGISTER_PREFIX
)
10606 if (!ISALPHA (*p
) || !is_name_beginner (*p
))
10610 while (ISALPHA (c
) || ISDIGIT (c
) || c
== '_')
10614 reg
= (struct reg_entry
*) hash_find (htab
, start
);
10620 return reg
->number
;
10626 /* Search for the following register name in each of the possible reg name
10627 tables. Return the classification if found, or REG_TYPE_MAX if not
10629 static enum arm_reg_type
10630 arm_reg_parse_any (cp
)
10635 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
10636 if (arm_reg_parse (&cp
, all_reg_maps
[i
].htab
) != FAIL
)
10637 return (enum arm_reg_type
) i
;
10639 return REG_TYPE_MAX
;
10643 md_apply_fix3 (fixP
, valP
, seg
)
10648 offsetT value
= * valP
;
10650 unsigned int newimm
;
10651 unsigned long temp
;
10653 char * buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
10654 arm_fix_data
* arm_data
= (arm_fix_data
*) fixP
->tc_fix_data
;
10656 assert (fixP
->fx_r_type
< BFD_RELOC_UNUSED
);
10658 /* Note whether this will delete the relocation. */
10660 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
10661 doesn't work fully.) */
10662 if ((fixP
->fx_addsy
== 0 || symbol_constant_p (fixP
->fx_addsy
))
10663 && !fixP
->fx_pcrel
)
10665 if (fixP
->fx_addsy
== 0 && !fixP
->fx_pcrel
)
10669 /* If this symbol is in a different section then we need to leave it for
10670 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
10671 so we have to undo it's effects here. */
10672 if (fixP
->fx_pcrel
)
10674 if (fixP
->fx_addsy
!= NULL
10675 && S_IS_DEFINED (fixP
->fx_addsy
)
10676 && S_GET_SEGMENT (fixP
->fx_addsy
) != seg
)
10679 && (fixP
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
10680 || fixP
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
10684 value
+= md_pcrel_from (fixP
);
10688 /* Remember value for emit_reloc. */
10689 fixP
->fx_addnumber
= value
;
10691 switch (fixP
->fx_r_type
)
10693 case BFD_RELOC_ARM_IMMEDIATE
:
10694 newimm
= validate_immediate (value
);
10695 temp
= md_chars_to_number (buf
, INSN_SIZE
);
10697 /* If the instruction will fail, see if we can fix things up by
10698 changing the opcode. */
10699 if (newimm
== (unsigned int) FAIL
10700 && (newimm
= negate_data_op (&temp
, value
)) == (unsigned int) FAIL
)
10702 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10703 _("invalid constant (%lx) after fixup"),
10704 (unsigned long) value
);
10708 newimm
|= (temp
& 0xfffff000);
10709 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
10713 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
10715 unsigned int highpart
= 0;
10716 unsigned int newinsn
= 0xe1a00000; /* nop. */
10718 newimm
= validate_immediate (value
);
10719 temp
= md_chars_to_number (buf
, INSN_SIZE
);
10721 /* If the instruction will fail, see if we can fix things up by
10722 changing the opcode. */
10723 if (newimm
== (unsigned int) FAIL
10724 && (newimm
= negate_data_op (& temp
, value
)) == (unsigned int) FAIL
)
10726 /* No ? OK - try using two ADD instructions to generate
10728 newimm
= validate_immediate_twopart (value
, & highpart
);
10730 /* Yes - then make sure that the second instruction is
10732 if (newimm
!= (unsigned int) FAIL
)
10734 /* Still No ? Try using a negated value. */
10735 else if ((newimm
= validate_immediate_twopart (- value
, & highpart
)) != (unsigned int) FAIL
)
10736 temp
= newinsn
= (temp
& OPCODE_MASK
) | OPCODE_SUB
<< DATA_OP_SHIFT
;
10737 /* Otherwise - give up. */
10740 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10741 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
10746 /* Replace the first operand in the 2nd instruction (which
10747 is the PC) with the destination register. We have
10748 already added in the PC in the first instruction and we
10749 do not want to do it again. */
10750 newinsn
&= ~ 0xf0000;
10751 newinsn
|= ((newinsn
& 0x0f000) << 4);
10754 newimm
|= (temp
& 0xfffff000);
10755 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
10757 highpart
|= (newinsn
& 0xfffff000);
10758 md_number_to_chars (buf
+ INSN_SIZE
, (valueT
) highpart
, INSN_SIZE
);
10762 case BFD_RELOC_ARM_OFFSET_IMM
:
10768 if (validate_offset_imm (value
, 0) == FAIL
)
10770 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10771 _("bad immediate value for offset (%ld)"),
10776 newval
= md_chars_to_number (buf
, INSN_SIZE
);
10777 newval
&= 0xff7ff000;
10778 newval
|= value
| (sign
? INDEX_UP
: 0);
10779 md_number_to_chars (buf
, newval
, INSN_SIZE
);
10782 case BFD_RELOC_ARM_OFFSET_IMM8
:
10783 case BFD_RELOC_ARM_HWLITERAL
:
10789 if (validate_offset_imm (value
, 1) == FAIL
)
10791 if (fixP
->fx_r_type
== BFD_RELOC_ARM_HWLITERAL
)
10792 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10793 _("invalid literal constant: pool needs to be closer"));
10795 as_bad (_("bad immediate value for half-word offset (%ld)"),
10800 newval
= md_chars_to_number (buf
, INSN_SIZE
);
10801 newval
&= 0xff7ff0f0;
10802 newval
|= ((value
>> 4) << 8) | (value
& 0xf) | (sign
? INDEX_UP
: 0);
10803 md_number_to_chars (buf
, newval
, INSN_SIZE
);
10806 case BFD_RELOC_ARM_LITERAL
:
10812 if (validate_offset_imm (value
, 0) == FAIL
)
10814 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10815 _("invalid literal constant: pool needs to be closer"));
10819 newval
= md_chars_to_number (buf
, INSN_SIZE
);
10820 newval
&= 0xff7ff000;
10821 newval
|= value
| (sign
? INDEX_UP
: 0);
10822 md_number_to_chars (buf
, newval
, INSN_SIZE
);
10825 case BFD_RELOC_ARM_SHIFT_IMM
:
10826 newval
= md_chars_to_number (buf
, INSN_SIZE
);
10827 if (((unsigned long) value
) > 32
10829 && (((newval
& 0x60) == 0) || (newval
& 0x60) == 0x60)))
10831 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10832 _("shift expression is too large"));
10837 /* Shifts of zero must be done as lsl. */
10839 else if (value
== 32)
10841 newval
&= 0xfffff07f;
10842 newval
|= (value
& 0x1f) << 7;
10843 md_number_to_chars (buf
, newval
, INSN_SIZE
);
10846 case BFD_RELOC_ARM_SWI
:
10847 if (arm_data
->thumb_mode
)
10849 if (((unsigned long) value
) > 0xff)
10850 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10851 _("invalid swi expression"));
10852 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xff00;
10854 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
10858 if (((unsigned long) value
) > 0x00ffffff)
10859 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10860 _("invalid swi expression"));
10861 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff000000;
10863 md_number_to_chars (buf
, newval
, INSN_SIZE
);
10867 case BFD_RELOC_ARM_MULTI
:
10868 if (((unsigned long) value
) > 0xffff)
10869 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10870 _("invalid expression in load/store multiple"));
10871 newval
= value
| md_chars_to_number (buf
, INSN_SIZE
);
10872 md_number_to_chars (buf
, newval
, INSN_SIZE
);
10875 case BFD_RELOC_ARM_PCREL_BRANCH
:
10876 newval
= md_chars_to_number (buf
, INSN_SIZE
);
10878 /* Sign-extend a 24-bit number. */
10879 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
10883 value
= fixP
->fx_offset
;
10886 /* We are going to store value (shifted right by two) in the
10887 instruction, in a 24 bit, signed field. Thus we need to check
10888 that none of the top 8 bits of the shifted value (top 7 bits of
10889 the unshifted, unsigned value) are set, or that they are all set. */
10890 if ((value
& ~ ((offsetT
) 0x1ffffff)) != 0
10891 && ((value
& ~ ((offsetT
) 0x1ffffff)) != ~ ((offsetT
) 0x1ffffff)))
10894 /* Normally we would be stuck at this point, since we cannot store
10895 the absolute address that is the destination of the branch in the
10896 24 bits of the branch instruction. If however, we happen to know
10897 that the destination of the branch is in the same section as the
10898 branch instruciton itself, then we can compute the relocation for
10899 ourselves and not have to bother the linker with it.
10901 FIXME: The tests for OBJ_ELF and ! target_oabi are only here
10902 because I have not worked out how to do this for OBJ_COFF or
10905 && fixP
->fx_addsy
!= NULL
10906 && S_IS_DEFINED (fixP
->fx_addsy
)
10907 && S_GET_SEGMENT (fixP
->fx_addsy
) == seg
)
10909 /* Get pc relative value to go into the branch. */
10912 /* Permit a backward branch provided that enough bits
10913 are set. Allow a forwards branch, provided that
10914 enough bits are clear. */
10915 if ( (value
& ~ ((offsetT
) 0x1ffffff)) == ~ ((offsetT
) 0x1ffffff)
10916 || (value
& ~ ((offsetT
) 0x1ffffff)) == 0)
10920 if (! fixP
->fx_done
)
10922 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10923 _("GAS can't handle same-section branch dest >= 0x04000000"));
10927 value
+= SEXT24 (newval
);
10929 if ( (value
& ~ ((offsetT
) 0xffffff)) != 0
10930 && ((value
& ~ ((offsetT
) 0xffffff)) != ~ ((offsetT
) 0xffffff)))
10931 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10932 _("out of range branch"));
10934 newval
= (value
& 0x00ffffff) | (newval
& 0xff000000);
10935 md_number_to_chars (buf
, newval
, INSN_SIZE
);
10938 case BFD_RELOC_ARM_PCREL_BLX
:
10941 newval
= md_chars_to_number (buf
, INSN_SIZE
);
10945 value
= fixP
->fx_offset
;
10947 hbit
= (value
>> 1) & 1;
10948 value
= (value
>> 2) & 0x00ffffff;
10949 value
= (value
+ (newval
& 0x00ffffff)) & 0x00ffffff;
10950 newval
= value
| (newval
& 0xfe000000) | (hbit
<< 24);
10951 md_number_to_chars (buf
, newval
, INSN_SIZE
);
10955 case BFD_RELOC_THUMB_PCREL_BRANCH9
: /* Conditional branch. */
10956 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
10958 addressT diff
= (newval
& 0xff) << 1;
10963 if ((value
& ~0xff) && ((value
& ~0xff) != ~0xff))
10964 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10965 _("branch out of range"));
10966 newval
= (newval
& 0xff00) | ((value
& 0x1ff) >> 1);
10968 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
10971 case BFD_RELOC_THUMB_PCREL_BRANCH12
: /* Unconditional branch. */
10972 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
10974 addressT diff
= (newval
& 0x7ff) << 1;
10979 if ((value
& ~0x7ff) && ((value
& ~0x7ff) != ~0x7ff))
10980 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10981 _("branch out of range"));
10982 newval
= (newval
& 0xf800) | ((value
& 0xfff) >> 1);
10984 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
10987 case BFD_RELOC_THUMB_PCREL_BLX
:
10988 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
10993 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
10994 newval2
= md_chars_to_number (buf
+ THUMB_SIZE
, THUMB_SIZE
);
10995 diff
= ((newval
& 0x7ff) << 12) | ((newval2
& 0x7ff) << 1);
10996 if (diff
& 0x400000)
10999 value
= fixP
->fx_offset
;
11003 if ((value
& ~0x3fffff) && ((value
& ~0x3fffff) != ~0x3fffff))
11004 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11005 _("branch with link out of range"));
11007 newval
= (newval
& 0xf800) | ((value
& 0x7fffff) >> 12);
11008 newval2
= (newval2
& 0xf800) | ((value
& 0xfff) >> 1);
11009 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
)
11010 /* For a BLX instruction, make sure that the relocation is rounded up
11011 to a word boundary. This follows the semantics of the instruction
11012 which specifies that bit 1 of the target address will come from bit
11013 1 of the base address. */
11014 newval2
= (newval2
+ 1) & ~ 1;
11015 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11016 md_number_to_chars (buf
+ THUMB_SIZE
, newval2
, THUMB_SIZE
);
11021 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11022 md_number_to_chars (buf
, value
, 1);
11024 else if (!target_oabi
)
11026 value
= fixP
->fx_offset
;
11027 md_number_to_chars (buf
, value
, 1);
11033 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11034 md_number_to_chars (buf
, value
, 2);
11036 else if (!target_oabi
)
11038 value
= fixP
->fx_offset
;
11039 md_number_to_chars (buf
, value
, 2);
11045 case BFD_RELOC_ARM_GOT32
:
11046 case BFD_RELOC_ARM_GOTOFF
:
11047 md_number_to_chars (buf
, 0, 4);
11051 case BFD_RELOC_RVA
:
11053 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11054 md_number_to_chars (buf
, value
, 4);
11056 else if (!target_oabi
)
11058 value
= fixP
->fx_offset
;
11059 md_number_to_chars (buf
, value
, 4);
11065 case BFD_RELOC_ARM_PLT32
:
11066 /* It appears the instruction is fully prepared at this point. */
11070 case BFD_RELOC_ARM_CP_OFF_IMM
:
11072 if (value
< -1023 || value
> 1023 || (value
& 3))
11073 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11074 _("illegal value for co-processor offset"));
11077 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
11078 newval
|= (value
>> 2) | (sign
? INDEX_UP
: 0);
11079 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11082 case BFD_RELOC_ARM_CP_OFF_IMM_S2
:
11084 if (value
< -255 || value
> 255)
11085 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11086 _("Illegal value for co-processor offset"));
11089 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
11090 newval
|= value
| (sign
? INDEX_UP
: 0);
11091 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11094 case BFD_RELOC_ARM_THUMB_OFFSET
:
11095 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11096 /* Exactly what ranges, and where the offset is inserted depends
11097 on the type of instruction, we can establish this from the
11099 switch (newval
>> 12)
11101 case 4: /* PC load. */
11102 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
11103 forced to zero for these loads, so we will need to round
11104 up the offset if the instruction address is not word
11105 aligned (since the final address produced must be, and
11106 we can only describe word-aligned immediate offsets). */
11108 if ((fixP
->fx_frag
->fr_address
+ fixP
->fx_where
+ value
) & 3)
11109 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11110 _("invalid offset, target not word aligned (0x%08X)"),
11111 (unsigned int) (fixP
->fx_frag
->fr_address
11112 + fixP
->fx_where
+ value
));
11114 if ((value
+ 2) & ~0x3fe)
11115 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11116 _("invalid offset, value too big (0x%08lX)"),
11119 /* Round up, since pc will be rounded down. */
11120 newval
|= (value
+ 2) >> 2;
11123 case 9: /* SP load/store. */
11124 if (value
& ~0x3fc)
11125 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11126 _("invalid offset, value too big (0x%08lX)"),
11128 newval
|= value
>> 2;
11131 case 6: /* Word load/store. */
11133 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11134 _("invalid offset, value too big (0x%08lX)"),
11136 newval
|= value
<< 4; /* 6 - 2. */
11139 case 7: /* Byte load/store. */
11141 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11142 _("invalid offset, value too big (0x%08lX)"),
11144 newval
|= value
<< 6;
11147 case 8: /* Halfword load/store. */
11149 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11150 _("invalid offset, value too big (0x%08lX)"),
11152 newval
|= value
<< 5; /* 6 - 1. */
11156 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11157 "Unable to process relocation for thumb opcode: %lx",
11158 (unsigned long) newval
);
11161 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11164 case BFD_RELOC_ARM_THUMB_ADD
:
11165 /* This is a complicated relocation, since we use it for all of
11166 the following immediate relocations:
11170 9bit ADD/SUB SP word-aligned
11171 10bit ADD PC/SP word-aligned
11173 The type of instruction being processed is encoded in the
11180 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11182 int rd
= (newval
>> 4) & 0xf;
11183 int rs
= newval
& 0xf;
11184 int subtract
= newval
& 0x8000;
11188 if (value
& ~0x1fc)
11189 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11190 _("invalid immediate for stack address calculation"));
11191 newval
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
11192 newval
|= value
>> 2;
11194 else if (rs
== REG_PC
|| rs
== REG_SP
)
11198 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11199 _("invalid immediate for address calculation (value = 0x%08lX)"),
11200 (unsigned long) value
);
11201 newval
= (rs
== REG_PC
? T_OPCODE_ADD_PC
: T_OPCODE_ADD_SP
);
11203 newval
|= value
>> 2;
11208 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11209 _("invalid 8bit immediate"));
11210 newval
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
11211 newval
|= (rd
<< 8) | value
;
11216 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11217 _("invalid 3bit immediate"));
11218 newval
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
11219 newval
|= rd
| (rs
<< 3) | (value
<< 6);
11222 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11225 case BFD_RELOC_ARM_THUMB_IMM
:
11226 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11227 switch (newval
>> 11)
11229 case 0x04: /* 8bit immediate MOV. */
11230 case 0x05: /* 8bit immediate CMP. */
11231 if (value
< 0 || value
> 255)
11232 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11233 _("invalid immediate: %ld is too large"),
11241 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11244 case BFD_RELOC_ARM_THUMB_SHIFT
:
11245 /* 5bit shift value (0..31). */
11246 if (value
< 0 || value
> 31)
11247 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11248 _("illegal Thumb shift value: %ld"), (long) value
);
11249 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xf03f;
11250 newval
|= value
<< 6;
11251 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11254 case BFD_RELOC_VTABLE_INHERIT
:
11255 case BFD_RELOC_VTABLE_ENTRY
:
11259 case BFD_RELOC_NONE
:
11261 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11262 _("bad relocation fixup type (%d)"), fixP
->fx_r_type
);
11266 /* Translate internal representation of relocation info to BFD target
11270 tc_gen_reloc (section
, fixp
)
11271 asection
* section ATTRIBUTE_UNUSED
;
11275 bfd_reloc_code_real_type code
;
11277 reloc
= (arelent
*) xmalloc (sizeof (arelent
));
11279 reloc
->sym_ptr_ptr
= (asymbol
**) xmalloc (sizeof (asymbol
*));
11280 *reloc
->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
11281 reloc
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
11283 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
11285 if (fixp
->fx_pcrel
== 0)
11286 reloc
->addend
= fixp
->fx_offset
;
11288 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
11289 #else /* OBJ_ELF */
11290 reloc
->addend
= fixp
->fx_offset
;
11293 switch (fixp
->fx_r_type
)
11296 if (fixp
->fx_pcrel
)
11298 code
= BFD_RELOC_8_PCREL
;
11303 if (fixp
->fx_pcrel
)
11305 code
= BFD_RELOC_16_PCREL
;
11310 if (fixp
->fx_pcrel
)
11312 code
= BFD_RELOC_32_PCREL
;
11316 case BFD_RELOC_ARM_PCREL_BRANCH
:
11317 case BFD_RELOC_ARM_PCREL_BLX
:
11318 case BFD_RELOC_RVA
:
11319 case BFD_RELOC_THUMB_PCREL_BRANCH9
:
11320 case BFD_RELOC_THUMB_PCREL_BRANCH12
:
11321 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
11322 case BFD_RELOC_THUMB_PCREL_BLX
:
11323 case BFD_RELOC_VTABLE_ENTRY
:
11324 case BFD_RELOC_VTABLE_INHERIT
:
11325 code
= fixp
->fx_r_type
;
11328 case BFD_RELOC_ARM_LITERAL
:
11329 case BFD_RELOC_ARM_HWLITERAL
:
11330 /* If this is called then the a literal has
11331 been referenced across a section boundary. */
11332 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
11333 _("literal referenced across section boundary"));
11337 case BFD_RELOC_ARM_GOT32
:
11338 case BFD_RELOC_ARM_GOTOFF
:
11339 case BFD_RELOC_ARM_PLT32
:
11340 code
= fixp
->fx_r_type
;
11344 case BFD_RELOC_ARM_IMMEDIATE
:
11345 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
11346 _("internal relocation (type: IMMEDIATE) not fixed up"));
11349 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
11350 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
11351 _("ADRL used for a symbol not defined in the same file"));
11354 case BFD_RELOC_ARM_OFFSET_IMM
:
11355 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
11356 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
11363 switch (fixp
->fx_r_type
)
11365 case BFD_RELOC_ARM_OFFSET_IMM8
: type
= "OFFSET_IMM8"; break;
11366 case BFD_RELOC_ARM_SHIFT_IMM
: type
= "SHIFT_IMM"; break;
11367 case BFD_RELOC_ARM_SWI
: type
= "SWI"; break;
11368 case BFD_RELOC_ARM_MULTI
: type
= "MULTI"; break;
11369 case BFD_RELOC_ARM_CP_OFF_IMM
: type
= "CP_OFF_IMM"; break;
11370 case BFD_RELOC_ARM_THUMB_ADD
: type
= "THUMB_ADD"; break;
11371 case BFD_RELOC_ARM_THUMB_SHIFT
: type
= "THUMB_SHIFT"; break;
11372 case BFD_RELOC_ARM_THUMB_IMM
: type
= "THUMB_IMM"; break;
11373 case BFD_RELOC_ARM_THUMB_OFFSET
: type
= "THUMB_OFFSET"; break;
11374 default: type
= _("<unknown>"); break;
11376 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
11377 _("cannot represent %s relocation in this object file format"),
11384 if ((code
== BFD_RELOC_32_PCREL
|| code
== BFD_RELOC_32
)
11386 && fixp
->fx_addsy
== GOT_symbol
)
11388 code
= BFD_RELOC_ARM_GOTPC
;
11389 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
11393 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, code
);
11395 if (reloc
->howto
== NULL
)
11397 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
11398 _("cannot represent %s relocation in this object file format"),
11399 bfd_get_reloc_code_name (code
));
11403 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
11404 vtable entry to be used in the relocation's section offset. */
11405 if (fixp
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
11406 reloc
->address
= fixp
->fx_offset
;
11412 md_estimate_size_before_relax (fragP
, segtype
)
11413 fragS
* fragP ATTRIBUTE_UNUSED
;
11414 segT segtype ATTRIBUTE_UNUSED
;
11416 as_fatal (_("md_estimate_size_before_relax\n"));
11428 as_bad ("%s -- `%s'", inst
.error
, str
);
11432 to
= frag_more (inst
.size
);
11434 if (thumb_mode
&& (inst
.size
> THUMB_SIZE
))
11436 assert (inst
.size
== (2 * THUMB_SIZE
));
11437 md_number_to_chars (to
, inst
.instruction
>> 16, THUMB_SIZE
);
11438 md_number_to_chars (to
+ THUMB_SIZE
, inst
.instruction
, THUMB_SIZE
);
11440 else if (inst
.size
> INSN_SIZE
)
11442 assert (inst
.size
== (2 * INSN_SIZE
));
11443 md_number_to_chars (to
, inst
.instruction
, INSN_SIZE
);
11444 md_number_to_chars (to
+ INSN_SIZE
, inst
.instruction
, INSN_SIZE
);
11447 md_number_to_chars (to
, inst
.instruction
, inst
.size
);
11449 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
11450 fix_new_arm (frag_now
, to
- frag_now
->fr_literal
,
11451 inst
.size
, & inst
.reloc
.exp
, inst
.reloc
.pc_rel
,
11455 dwarf2_emit_insn (inst
.size
);
11467 /* Align the instruction.
11468 This may not be the right thing to do but ... */
11473 /* Align the previous label if needed. */
11474 if (last_label_seen
!= NULL
)
11476 symbol_set_frag (last_label_seen
, frag_now
);
11477 S_SET_VALUE (last_label_seen
, (valueT
) frag_now_fix ());
11478 S_SET_SEGMENT (last_label_seen
, now_seg
);
11481 memset (&inst
, '\0', sizeof (inst
));
11482 inst
.reloc
.type
= BFD_RELOC_NONE
;
11484 skip_whitespace (str
);
11486 /* Scan up to the end of the op-code, which must end in white space or
11488 for (start
= p
= str
; *p
!= '\0'; p
++)
11494 as_bad (_("no operator -- statement `%s'\n"), str
);
11500 const struct thumb_opcode
* opcode
;
11504 opcode
= (const struct thumb_opcode
*) hash_find (arm_tops_hsh
, str
);
11509 /* Check that this instruction is supported for this CPU. */
11510 if (thumb_mode
== 1 && (opcode
->variant
& cpu_variant
) == 0)
11512 as_bad (_("selected processor does not support `%s'"), str
);
11516 inst
.instruction
= opcode
->value
;
11517 inst
.size
= opcode
->size
;
11518 (*opcode
->parms
) (p
);
11525 const struct asm_opcode
* opcode
;
11529 opcode
= (const struct asm_opcode
*) hash_find (arm_ops_hsh
, str
);
11534 /* Check that this instruction is supported for this CPU. */
11535 if ((opcode
->variant
& cpu_variant
) == 0)
11537 as_bad (_("selected processor does not support `%s'"), str
);
11541 inst
.instruction
= opcode
->value
;
11542 inst
.size
= INSN_SIZE
;
11543 (*opcode
->parms
) (p
);
11549 /* It wasn't an instruction, but it might be a register alias of the form
11551 if (create_register_alias (str
, p
))
11554 as_bad (_("bad instruction `%s'"), start
);
11558 Invocation line includes a switch not recognized by the base assembler.
11559 See if it's a processor-specific option.
11561 This routine is somewhat complicated by the need for backwards
11562 compatibility (since older releases of gcc can't be changed).
11563 The new options try to make the interface as compatible as
11566 New options (supported) are:
11568 -mcpu=<cpu name> Assemble for selected processor
11569 -march=<architecture name> Assemble for selected architecture
11570 -mfpu=<fpu architecture> Assemble for selected FPU.
11571 -EB/-mbig-endian Big-endian
11572 -EL/-mlittle-endian Little-endian
11573 -k Generate PIC code
11574 -mthumb Start in Thumb mode
11575 -mthumb-interwork Code supports ARM/Thumb interworking
11577 For now we will also provide support for:
11579 -mapcs-32 32-bit Program counter
11580 -mapcs-26 26-bit Program counter
11581 -macps-float Floats passed in FP registers
11582 -mapcs-reentrant Reentrant code
11584 (sometime these will probably be replaced with -mapcs=<list of options>
11585 and -matpcs=<list of options>)
11587 The remaining options are only supported for back-wards compatibility.
11588 Cpu variants, the arm part is optional:
11589 -m[arm]1 Currently not supported.
11590 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
11591 -m[arm]3 Arm 3 processor
11592 -m[arm]6[xx], Arm 6 processors
11593 -m[arm]7[xx][t][[d]m] Arm 7 processors
11594 -m[arm]8[10] Arm 8 processors
11595 -m[arm]9[20][tdmi] Arm 9 processors
11596 -mstrongarm[110[0]] StrongARM processors
11597 -mxscale XScale processors
11598 -m[arm]v[2345[t[e]]] Arm architectures
11599 -mall All (except the ARM1)
11601 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
11602 -mfpe-old (No float load/store multiples)
11603 -mvfpxd VFP Single precision
11605 -mno-fpu Disable all floating point instructions
11607 The following CPU names are recognized:
11608 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
11609 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
11610 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
11611 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
11612 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
11613 arm10t arm10e, arm1020t, arm1020e, arm10200e,
11614 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
11618 const char * md_shortopts
= "m:k";
11620 #ifdef ARM_BI_ENDIAN
11621 #define OPTION_EB (OPTION_MD_BASE + 0)
11622 #define OPTION_EL (OPTION_MD_BASE + 1)
11624 #if TARGET_BYTES_BIG_ENDIAN
11625 #define OPTION_EB (OPTION_MD_BASE + 0)
11627 #define OPTION_EL (OPTION_MD_BASE + 1)
11631 struct option md_longopts
[] =
11634 {"EB", no_argument
, NULL
, OPTION_EB
},
11637 {"EL", no_argument
, NULL
, OPTION_EL
},
11639 {NULL
, no_argument
, NULL
, 0}
11642 size_t md_longopts_size
= sizeof (md_longopts
);
11644 struct arm_option_table
11646 char *option
; /* Option name to match. */
11647 char *help
; /* Help information. */
11648 int *var
; /* Variable to change. */
11649 int value
; /* What to change it to. */
11650 char *deprecated
; /* If non-null, print this message. */
11653 struct arm_option_table arm_opts
[] =
11655 {"k", N_("generate PIC code"), &pic_code
, 1, NULL
},
11656 {"mthumb", N_("assemble Thumb code"), &thumb_mode
, 1, NULL
},
11657 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
11658 &support_interwork
, 1, NULL
},
11659 {"moabi", N_("use old ABI (ELF only)"), &target_oabi
, 1, NULL
},
11660 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26
, 0, NULL
},
11661 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26
, 1, NULL
},
11662 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float
,
11664 {"mapcs-reentrant", N_("re-entrant code"), &pic_code
, 1, NULL
},
11665 {"matpcs", N_("code is ATPCS conformant"), &atpcs
, 1, NULL
},
11666 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian
, 1, NULL
},
11667 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian
, 1,
11670 /* These are recognized by the assembler, but have no affect on code. */
11671 {"mapcs-frame", N_("use frame pointer"), NULL
, 0, NULL
},
11672 {"mapcs-stack-check", N_("use stack size checking"), NULL
, 0, NULL
},
11674 /* DON'T add any new processors to this list -- we want the whole list
11675 to go away... Add them to the processors table instead. */
11676 {"marm1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
11677 {"m1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
11678 {"marm2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
11679 {"m2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
11680 {"marm250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
11681 {"m250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
11682 {"marm3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
11683 {"m3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
11684 {"marm6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
11685 {"m6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
11686 {"marm600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
11687 {"m600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
11688 {"marm610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
11689 {"m610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
11690 {"marm620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
11691 {"m620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
11692 {"marm7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
11693 {"m7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
11694 {"marm70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
11695 {"m70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
11696 {"marm700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
11697 {"m700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
11698 {"marm700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
11699 {"m700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
11700 {"marm710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
11701 {"m710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
11702 {"marm710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
11703 {"m710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
11704 {"marm720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
11705 {"m720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
11706 {"marm7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
11707 {"m7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
11708 {"marm7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
11709 {"m7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
11710 {"marm7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
11711 {"m7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
11712 {"marm7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
11713 {"m7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
11714 {"marm7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
11715 {"m7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
11716 {"marm7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
11717 {"m7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
11718 {"marm7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
11719 {"m7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
11720 {"marm7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
11721 {"m7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
11722 {"marm7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
11723 {"m7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
11724 {"marm7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
11725 {"m7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
11726 {"marm710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
11727 {"m710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
11728 {"marm720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
11729 {"m720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
11730 {"marm740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
11731 {"m740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
11732 {"marm8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
11733 {"m8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
11734 {"marm810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
11735 {"m810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
11736 {"marm9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
11737 {"m9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
11738 {"marm9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
11739 {"m9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
11740 {"marm920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
11741 {"m920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
11742 {"marm940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
11743 {"m940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
11744 {"mstrongarm", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=strongarm")},
11745 {"mstrongarm110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
11746 N_("use -mcpu=strongarm110")},
11747 {"mstrongarm1100", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
11748 N_("use -mcpu=strongarm1100")},
11749 {"mstrongarm1110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
11750 N_("use -mcpu=strongarm1110")},
11751 {"mxscale", NULL
, &legacy_cpu
, ARM_ARCH_XSCALE
, N_("use -mcpu=xscale")},
11752 {"miwmmxt", NULL
, &legacy_cpu
, ARM_ARCH_IWMMXT
, N_("use -mcpu=iwmmxt")},
11753 {"mall", NULL
, &legacy_cpu
, ARM_ANY
, N_("use -mcpu=all")},
11755 /* Architecture variants -- don't add any more to this list either. */
11756 {"mv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
11757 {"marmv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
11758 {"mv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
11759 {"marmv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
11760 {"mv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
11761 {"marmv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
11762 {"mv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
11763 {"marmv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
11764 {"mv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
11765 {"marmv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
11766 {"mv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
11767 {"marmv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
11768 {"mv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
11769 {"marmv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
11770 {"mv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
11771 {"marmv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
11772 {"mv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
11773 {"marmv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
11775 /* Floating point variants -- don't add any more to this list either. */
11776 {"mfpe-old", NULL
, &legacy_fpu
, FPU_ARCH_FPE
, N_("use -mfpu=fpe")},
11777 {"mfpa10", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa10")},
11778 {"mfpa11", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa11")},
11779 {"mno-fpu", NULL
, &legacy_fpu
, 0,
11780 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
11782 {NULL
, NULL
, NULL
, 0, NULL
}
11785 struct arm_cpu_option_table
11789 /* For some CPUs we assume an FPU unless the user explicitly sets
11794 /* This list should, at a minimum, contain all the cpu names
11795 recognized by GCC. */
11796 static struct arm_cpu_option_table arm_cpus
[] =
11798 {"all", ARM_ANY
, FPU_ARCH_FPA
},
11799 {"arm1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
11800 {"arm2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
11801 {"arm250", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
11802 {"arm3", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
11803 {"arm6", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11804 {"arm60", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11805 {"arm600", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11806 {"arm610", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11807 {"arm620", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11808 {"arm7", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11809 {"arm7m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
11810 {"arm7d", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11811 {"arm7dm", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
11812 {"arm7di", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11813 {"arm7dmi", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
11814 {"arm70", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11815 {"arm700", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11816 {"arm700i", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11817 {"arm710", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11818 {"arm710t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
11819 {"arm720", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11820 {"arm720t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
11821 {"arm740t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
11822 {"arm710c", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11823 {"arm7100", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11824 {"arm7500", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11825 {"arm7500fe", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11826 {"arm7t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
11827 {"arm7tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
11828 {"arm8", ARM_ARCH_V4
, FPU_ARCH_FPA
},
11829 {"arm810", ARM_ARCH_V4
, FPU_ARCH_FPA
},
11830 {"strongarm", ARM_ARCH_V4
, FPU_ARCH_FPA
},
11831 {"strongarm1", ARM_ARCH_V4
, FPU_ARCH_FPA
},
11832 {"strongarm110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
11833 {"strongarm1100", ARM_ARCH_V4
, FPU_ARCH_FPA
},
11834 {"strongarm1110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
11835 {"arm9", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
11836 {"arm920", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
11837 {"arm920t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
11838 {"arm922t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
11839 {"arm940t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
11840 {"arm9tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
11841 /* For V5 or later processors we default to using VFP; but the user
11842 should really set the FPU type explicitly. */
11843 {"arm9e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
11844 {"arm9e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
11845 {"arm926ej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
11846 {"arm946e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
11847 {"arm946e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
11848 {"arm966e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
11849 {"arm966e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
11850 {"arm10t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
11851 {"arm10e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
11852 {"arm1020", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
11853 {"arm1020t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
11854 {"arm1020e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
11855 /* ??? XSCALE is really an architecture. */
11856 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
11857 /* ??? iwmmxt is not a processor. */
11858 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP_V2
},
11859 {"i80200", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
11861 {"ep9312", ARM_ARCH_V4T
| ARM_CEXT_MAVERICK
, FPU_NONE
},
11865 struct arm_arch_option_table
11872 /* This list should, at a minimum, contain all the architecture names
11873 recognized by GCC. */
11874 static struct arm_arch_option_table arm_archs
[] =
11876 {"all", ARM_ANY
, FPU_ARCH_FPA
},
11877 {"armv1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
11878 {"armv2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
11879 {"armv2a", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
11880 {"armv2s", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
11881 {"armv3", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11882 {"armv3m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
11883 {"armv4", ARM_ARCH_V4
, FPU_ARCH_FPA
},
11884 {"armv4xm", ARM_ARCH_V4xM
, FPU_ARCH_FPA
},
11885 {"armv4t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
11886 {"armv4txm", ARM_ARCH_V4TxM
, FPU_ARCH_FPA
},
11887 {"armv5", ARM_ARCH_V5
, FPU_ARCH_VFP
},
11888 {"armv5t", ARM_ARCH_V5T
, FPU_ARCH_VFP
},
11889 {"armv5txm", ARM_ARCH_V5TxM
, FPU_ARCH_VFP
},
11890 {"armv5te", ARM_ARCH_V5TE
, FPU_ARCH_VFP
},
11891 {"armv5texp", ARM_ARCH_V5TExP
, FPU_ARCH_VFP
},
11892 {"armv5tej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP
},
11893 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP
},
11897 /* ISA extensions in the co-processor space. */
11898 struct arm_arch_extension_table
11904 static struct arm_arch_extension_table arm_extensions
[] =
11906 {"maverick", ARM_CEXT_MAVERICK
},
11907 {"xscale", ARM_CEXT_XSCALE
},
11908 {"iwmmxt", ARM_CEXT_IWMMXT
},
11912 struct arm_fpu_option_table
11918 /* This list should, at a minimum, contain all the fpu names
11919 recognized by GCC. */
11920 static struct arm_fpu_option_table arm_fpus
[] =
11922 {"softfpa", FPU_NONE
},
11923 {"fpe", FPU_ARCH_FPE
},
11924 {"fpe2", FPU_ARCH_FPE
},
11925 {"fpe3", FPU_ARCH_FPA
}, /* Third release supports LFM/SFM. */
11926 {"fpa", FPU_ARCH_FPA
},
11927 {"fpa10", FPU_ARCH_FPA
},
11928 {"fpa11", FPU_ARCH_FPA
},
11929 {"arm7500fe", FPU_ARCH_FPA
},
11930 {"softvfp", FPU_ARCH_VFP
},
11931 {"softvfp+vfp", FPU_ARCH_VFP_V2
},
11932 {"vfp", FPU_ARCH_VFP_V2
},
11933 {"vfp9", FPU_ARCH_VFP_V2
},
11934 {"vfp10", FPU_ARCH_VFP_V2
},
11935 {"vfp10-r0", FPU_ARCH_VFP_V1
},
11936 {"vfpxd", FPU_ARCH_VFP_V1xD
},
11937 {"arm1020t", FPU_ARCH_VFP_V1
},
11938 {"arm1020e", FPU_ARCH_VFP_V2
},
11942 struct arm_long_option_table
11944 char *option
; /* Substring to match. */
11945 char *help
; /* Help information. */
11946 int (*func
) PARAMS ((char *subopt
)); /* Function to decode sub-option. */
11947 char *deprecated
; /* If non-null, print this message. */
11951 arm_parse_extension (str
, opt_p
)
11955 while (str
!= NULL
&& *str
!= 0)
11957 struct arm_arch_extension_table
*opt
;
11963 as_bad (_("invalid architectural extension"));
11968 ext
= strchr (str
, '+');
11971 optlen
= ext
- str
;
11973 optlen
= strlen (str
);
11977 as_bad (_("missing architectural extension"));
11981 for (opt
= arm_extensions
; opt
->name
!= NULL
; opt
++)
11982 if (strncmp (opt
->name
, str
, optlen
) == 0)
11984 *opt_p
|= opt
->value
;
11988 if (opt
->name
== NULL
)
11990 as_bad (_("unknown architectural extnsion `%s'"), str
);
12001 arm_parse_cpu (str
)
12004 struct arm_cpu_option_table
*opt
;
12005 char *ext
= strchr (str
, '+');
12009 optlen
= ext
- str
;
12011 optlen
= strlen (str
);
12015 as_bad (_("missing cpu name `%s'"), str
);
12019 for (opt
= arm_cpus
; opt
->name
!= NULL
; opt
++)
12020 if (strncmp (opt
->name
, str
, optlen
) == 0)
12022 mcpu_cpu_opt
= opt
->value
;
12023 mcpu_fpu_opt
= opt
->default_fpu
;
12026 return arm_parse_extension (ext
, &mcpu_cpu_opt
);
12031 as_bad (_("unknown cpu `%s'"), str
);
12036 arm_parse_arch (str
)
12039 struct arm_arch_option_table
*opt
;
12040 char *ext
= strchr (str
, '+');
12044 optlen
= ext
- str
;
12046 optlen
= strlen (str
);
12050 as_bad (_("missing architecture name `%s'"), str
);
12055 for (opt
= arm_archs
; opt
->name
!= NULL
; opt
++)
12056 if (strcmp (opt
->name
, str
) == 0)
12058 march_cpu_opt
= opt
->value
;
12059 march_fpu_opt
= opt
->default_fpu
;
12062 return arm_parse_extension (ext
, &march_cpu_opt
);
12067 as_bad (_("unknown architecture `%s'\n"), str
);
12072 arm_parse_fpu (str
)
12075 struct arm_fpu_option_table
*opt
;
12077 for (opt
= arm_fpus
; opt
->name
!= NULL
; opt
++)
12078 if (strcmp (opt
->name
, str
) == 0)
12080 mfpu_opt
= opt
->value
;
12084 as_bad (_("unknown floating point format `%s'\n"), str
);
12088 struct arm_long_option_table arm_long_opts
[] =
12090 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
12091 arm_parse_cpu
, NULL
},
12092 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
12093 arm_parse_arch
, NULL
},
12094 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
12095 arm_parse_fpu
, NULL
},
12096 {NULL
, NULL
, 0, NULL
}
12100 md_parse_option (c
, arg
)
12104 struct arm_option_table
*opt
;
12105 struct arm_long_option_table
*lopt
;
12111 target_big_endian
= 1;
12117 target_big_endian
= 0;
12122 /* Listing option. Just ignore these, we don't support additional
12127 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
12129 if (c
== opt
->option
[0]
12130 && ((arg
== NULL
&& opt
->option
[1] == 0)
12131 || strcmp (arg
, opt
->option
+ 1) == 0))
12133 #if WARN_DEPRECATED
12134 /* If the option is deprecated, tell the user. */
12135 if (opt
->deprecated
!= NULL
)
12136 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
,
12137 arg
? arg
: "", _(opt
->deprecated
));
12140 if (opt
->var
!= NULL
)
12141 *opt
->var
= opt
->value
;
12147 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
12149 /* These options are expected to have an argument. */
12150 if (c
== lopt
->option
[0]
12152 && strncmp (arg
, lopt
->option
+ 1,
12153 strlen (lopt
->option
+ 1)) == 0)
12155 #if WARN_DEPRECATED
12156 /* If the option is deprecated, tell the user. */
12157 if (lopt
->deprecated
!= NULL
)
12158 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
, arg
,
12159 _(lopt
->deprecated
));
12162 /* Call the sup-option parser. */
12163 return (*lopt
->func
)(arg
+ strlen (lopt
->option
) - 1);
12167 as_bad (_("unrecognized option `-%c%s'"), c
, arg
? arg
: "");
12178 struct arm_option_table
*opt
;
12179 struct arm_long_option_table
*lopt
;
12181 fprintf (fp
, _(" ARM-specific assembler options:\n"));
12183 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
12184 if (opt
->help
!= NULL
)
12185 fprintf (fp
, " -%-23s%s\n", opt
->option
, _(opt
->help
));
12187 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
12188 if (lopt
->help
!= NULL
)
12189 fprintf (fp
, " -%s%s\n", lopt
->option
, _(lopt
->help
));
12193 -EB assemble code for a big-endian cpu\n"));
12198 -EL assemble code for a little-endian cpu\n"));
12202 /* We need to be able to fix up arbitrary expressions in some statements.
12203 This is so that we can handle symbols that are an arbitrary distance from
12204 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
12205 which returns part of an address in a form which will be valid for
12206 a data instruction. We do this by pushing the expression into a symbol
12207 in the expr_section, and creating a fix for that. */
12210 fix_new_arm (frag
, where
, size
, exp
, pc_rel
, reloc
)
12219 arm_fix_data
* arm_data
;
12227 new_fix
= fix_new_exp (frag
, where
, size
, exp
, pc_rel
, reloc
);
12231 new_fix
= fix_new (frag
, where
, size
, make_expr_symbol (exp
), 0,
12236 /* Mark whether the fix is to a THUMB instruction, or an ARM
12238 arm_data
= (arm_fix_data
*) obstack_alloc (& notes
, sizeof (arm_fix_data
));
12239 new_fix
->tc_fix_data
= (PTR
) arm_data
;
12240 arm_data
->thumb_mode
= thumb_mode
;
12245 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
12248 cons_fix_new_arm (frag
, where
, size
, exp
)
12254 bfd_reloc_code_real_type type
;
12258 FIXME: @@ Should look at CPU word size. */
12262 type
= BFD_RELOC_8
;
12265 type
= BFD_RELOC_16
;
12269 type
= BFD_RELOC_32
;
12272 type
= BFD_RELOC_64
;
12276 fix_new_exp (frag
, where
, (int) size
, exp
, pcrel
, type
);
12279 /* A good place to do this, although this was probably not intended
12280 for this kind of use. We need to dump the literal pool before
12281 references are made to a null symbol pointer. */
12286 literal_pool
* pool
;
12288 for (pool
= list_of_pools
; pool
; pool
= pool
->next
)
12290 /* Put it at the end of the relevent section. */
12291 subseg_set (pool
->section
, pool
->sub_section
);
12297 arm_start_line_hook ()
12299 last_label_seen
= NULL
;
12303 arm_frob_label (sym
)
12306 last_label_seen
= sym
;
12308 ARM_SET_THUMB (sym
, thumb_mode
);
12310 #if defined OBJ_COFF || defined OBJ_ELF
12311 ARM_SET_INTERWORK (sym
, support_interwork
);
12314 /* Note - do not allow local symbols (.Lxxx) to be labeled
12315 as Thumb functions. This is because these labels, whilst
12316 they exist inside Thumb code, are not the entry points for
12317 possible ARM->Thumb calls. Also, these labels can be used
12318 as part of a computed goto or switch statement. eg gcc
12319 can generate code that looks like this:
12321 ldr r2, [pc, .Laaa]
12331 The first instruction loads the address of the jump table.
12332 The second instruction converts a table index into a byte offset.
12333 The third instruction gets the jump address out of the table.
12334 The fourth instruction performs the jump.
12336 If the address stored at .Laaa is that of a symbol which has the
12337 Thumb_Func bit set, then the linker will arrange for this address
12338 to have the bottom bit set, which in turn would mean that the
12339 address computation performed by the third instruction would end
12340 up with the bottom bit set. Since the ARM is capable of unaligned
12341 word loads, the instruction would then load the incorrect address
12342 out of the jump table, and chaos would ensue. */
12343 if (label_is_thumb_function_name
12344 && (S_GET_NAME (sym
)[0] != '.' || S_GET_NAME (sym
)[1] != 'L')
12345 && (bfd_get_section_flags (stdoutput
, now_seg
) & SEC_CODE
) != 0)
12347 /* When the address of a Thumb function is taken the bottom
12348 bit of that address should be set. This will allow
12349 interworking between Arm and Thumb functions to work
12352 THUMB_SET_FUNC (sym
, 1);
12354 label_is_thumb_function_name
= FALSE
;
12358 /* Adjust the symbol table. This marks Thumb symbols as distinct from
12362 arm_adjust_symtab ()
12367 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
12369 if (ARM_IS_THUMB (sym
))
12371 if (THUMB_IS_FUNC (sym
))
12373 /* Mark the symbol as a Thumb function. */
12374 if ( S_GET_STORAGE_CLASS (sym
) == C_STAT
12375 || S_GET_STORAGE_CLASS (sym
) == C_LABEL
) /* This can happen! */
12376 S_SET_STORAGE_CLASS (sym
, C_THUMBSTATFUNC
);
12378 else if (S_GET_STORAGE_CLASS (sym
) == C_EXT
)
12379 S_SET_STORAGE_CLASS (sym
, C_THUMBEXTFUNC
);
12381 as_bad (_("%s: unexpected function type: %d"),
12382 S_GET_NAME (sym
), S_GET_STORAGE_CLASS (sym
));
12384 else switch (S_GET_STORAGE_CLASS (sym
))
12387 S_SET_STORAGE_CLASS (sym
, C_THUMBEXT
);
12390 S_SET_STORAGE_CLASS (sym
, C_THUMBSTAT
);
12393 S_SET_STORAGE_CLASS (sym
, C_THUMBLABEL
);
12401 if (ARM_IS_INTERWORK (sym
))
12402 coffsymbol (symbol_get_bfdsym (sym
))->native
->u
.syment
.n_flags
= 0xFF;
12409 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
12411 if (ARM_IS_THUMB (sym
))
12413 elf_symbol_type
* elf_sym
;
12415 elf_sym
= elf_symbol (symbol_get_bfdsym (sym
));
12416 bind
= ELF_ST_BIND (elf_sym
);
12418 /* If it's a .thumb_func, declare it as so,
12419 otherwise tag label as .code 16. */
12420 if (THUMB_IS_FUNC (sym
))
12421 elf_sym
->internal_elf_sym
.st_info
=
12422 ELF_ST_INFO (bind
, STT_ARM_TFUNC
);
12424 elf_sym
->internal_elf_sym
.st_info
=
12425 ELF_ST_INFO (bind
, STT_ARM_16BIT
);
12432 arm_data_in_code ()
12434 if (thumb_mode
&& ! strncmp (input_line_pointer
+ 1, "data:", 5))
12436 *input_line_pointer
= '/';
12437 input_line_pointer
+= 5;
12438 *input_line_pointer
= 0;
12446 arm_canonicalize_symbol_name (name
)
12451 if (thumb_mode
&& (len
= strlen (name
)) > 5
12452 && streq (name
+ len
- 5, "/data"))
12453 *(name
+ len
- 5) = 0;
12458 #if defined OBJ_COFF || defined OBJ_ELF
12460 arm_validate_fix (fixP
)
12463 /* If the destination of the branch is a defined symbol which does not have
12464 the THUMB_FUNC attribute, then we must be calling a function which has
12465 the (interfacearm) attribute. We look for the Thumb entry point to that
12466 function and change the branch to refer to that function instead. */
12467 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
12468 && fixP
->fx_addsy
!= NULL
12469 && S_IS_DEFINED (fixP
->fx_addsy
)
12470 && ! THUMB_IS_FUNC (fixP
->fx_addsy
))
12472 fixP
->fx_addsy
= find_real_start (fixP
->fx_addsy
);
12478 arm_force_relocation (fixp
)
12481 #if defined (OBJ_COFF) && defined (TE_PE)
12482 if (fixp
->fx_r_type
== BFD_RELOC_RVA
)
12486 if (fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
12487 || fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
12488 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
12489 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
)
12493 /* Resolve these relocations even if the symbol is extern or weak. */
12494 if (fixp
->fx_r_type
== BFD_RELOC_ARM_IMMEDIATE
12495 || fixp
->fx_r_type
== BFD_RELOC_ARM_OFFSET_IMM
12496 || fixp
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
12499 return generic_force_reloc (fixp
);
12503 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
12504 local labels from being added to the output symbol table when they
12505 are used with the ADRL pseudo op. The ADRL relocation should always
12506 be resolved before the binbary is emitted, so it is safe to say that
12507 it is adjustable. */
12510 arm_fix_adjustable (fixP
)
12513 if (fixP
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
12520 /* Relocations against Thumb function names must be left unadjusted,
12521 so that the linker can use this information to correctly set the
12522 bottom bit of their addresses. The MIPS version of this function
12523 also prevents relocations that are mips-16 specific, but I do not
12524 know why it does this.
12527 There is one other problem that ought to be addressed here, but
12528 which currently is not: Taking the address of a label (rather
12529 than a function) and then later jumping to that address. Such
12530 addresses also ought to have their bottom bit set (assuming that
12531 they reside in Thumb code), but at the moment they will not. */
12534 arm_fix_adjustable (fixP
)
12537 if (fixP
->fx_addsy
== NULL
)
12540 if (THUMB_IS_FUNC (fixP
->fx_addsy
)
12541 && fixP
->fx_subsy
== NULL
)
12544 /* We need the symbol name for the VTABLE entries. */
12545 if ( fixP
->fx_r_type
== BFD_RELOC_VTABLE_INHERIT
12546 || fixP
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
12549 /* Don't allow symbols to be discarded on GOT related relocs. */
12550 if (fixP
->fx_r_type
== BFD_RELOC_ARM_PLT32
12551 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOT32
12552 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOTOFF
)
12559 elf32_arm_target_format ()
12561 if (target_big_endian
)
12564 return "elf32-bigarm-oabi";
12566 return "elf32-bigarm";
12571 return "elf32-littlearm-oabi";
12573 return "elf32-littlearm";
12578 armelf_frob_symbol (symp
, puntp
)
12582 elf_frob_symbol (symp
, puntp
);
12585 static bfd_reloc_code_real_type
12595 bfd_reloc_code_real_type reloc
;
12599 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
12600 MAP ("(got)", BFD_RELOC_ARM_GOT32
),
12601 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF
),
12602 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
12603 branch instructions generated by GCC for PLT relocs. */
12604 MAP ("(plt)", BFD_RELOC_ARM_PLT32
),
12605 { NULL
, 0, BFD_RELOC_UNUSED
}
12609 for (i
= 0, ip
= input_line_pointer
;
12610 i
< sizeof (id
) && (ISALNUM (*ip
) || ISPUNCT (*ip
));
12612 id
[i
] = TOLOWER (*ip
);
12614 for (i
= 0; reloc_map
[i
].str
; i
++)
12615 if (strncmp (id
, reloc_map
[i
].str
, reloc_map
[i
].len
) == 0)
12618 input_line_pointer
+= reloc_map
[i
].len
;
12620 return reloc_map
[i
].reloc
;
12624 s_arm_elf_cons (nbytes
)
12629 #ifdef md_flush_pending_output
12630 md_flush_pending_output ();
12633 if (is_it_end_of_statement ())
12635 demand_empty_rest_of_line ();
12639 #ifdef md_cons_align
12640 md_cons_align (nbytes
);
12645 bfd_reloc_code_real_type reloc
;
12647 expression (& exp
);
12649 if (exp
.X_op
== O_symbol
12650 && * input_line_pointer
== '('
12651 && (reloc
= arm_parse_reloc ()) != BFD_RELOC_UNUSED
)
12653 reloc_howto_type
*howto
= bfd_reloc_type_lookup (stdoutput
, reloc
);
12654 int size
= bfd_get_reloc_size (howto
);
12657 as_bad ("%s relocations do not fit in %d bytes",
12658 howto
->name
, nbytes
);
12661 register char *p
= frag_more ((int) nbytes
);
12662 int offset
= nbytes
- size
;
12664 fix_new_exp (frag_now
, p
- frag_now
->fr_literal
+ offset
, size
,
12669 emit_expr (&exp
, (unsigned int) nbytes
);
12671 while (*input_line_pointer
++ == ',');
12673 /* Put terminator back into stream. */
12674 input_line_pointer
--;
12675 demand_empty_rest_of_line ();
12678 #endif /* OBJ_ELF */
12680 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
12681 of an rs_align_code fragment. */
12684 arm_handle_align (fragP
)
12687 static char const arm_noop
[4] = { 0x00, 0x00, 0xa0, 0xe1 };
12688 static char const thumb_noop
[2] = { 0xc0, 0x46 };
12689 static char const arm_bigend_noop
[4] = { 0xe1, 0xa0, 0x00, 0x00 };
12690 static char const thumb_bigend_noop
[2] = { 0x46, 0xc0 };
12692 int bytes
, fix
, noop_size
;
12696 if (fragP
->fr_type
!= rs_align_code
)
12699 bytes
= fragP
->fr_next
->fr_address
- fragP
->fr_address
- fragP
->fr_fix
;
12700 p
= fragP
->fr_literal
+ fragP
->fr_fix
;
12703 if (bytes
> MAX_MEM_FOR_RS_ALIGN_CODE
)
12704 bytes
&= MAX_MEM_FOR_RS_ALIGN_CODE
;
12706 if (fragP
->tc_frag_data
)
12708 if (target_big_endian
)
12709 noop
= thumb_bigend_noop
;
12712 noop_size
= sizeof (thumb_noop
);
12716 if (target_big_endian
)
12717 noop
= arm_bigend_noop
;
12720 noop_size
= sizeof (arm_noop
);
12723 if (bytes
& (noop_size
- 1))
12725 fix
= bytes
& (noop_size
- 1);
12726 memset (p
, 0, fix
);
12731 while (bytes
>= noop_size
)
12733 memcpy (p
, noop
, noop_size
);
12735 bytes
-= noop_size
;
12739 fragP
->fr_fix
+= fix
;
12740 fragP
->fr_var
= noop_size
;
12743 /* Called from md_do_align. Used to create an alignment
12744 frag in a code section. */
12747 arm_frag_align_code (n
, max
)
12753 /* We assume that there will never be a requirment
12754 to support alignments greater than 32 bytes. */
12755 if (max
> MAX_MEM_FOR_RS_ALIGN_CODE
)
12756 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
12758 p
= frag_var (rs_align_code
,
12759 MAX_MEM_FOR_RS_ALIGN_CODE
,
12761 (relax_substateT
) max
,
12769 /* Perform target specific initialisation of a frag. */
12772 arm_init_frag (fragP
)
12775 /* Record whether this frag is in an ARM or a THUMB area. */
12776 fragP
->tc_frag_data
= thumb_mode
;