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 distinguishes CPSR and SPSR. */
366 #define SPSR_BIT (1 << 22)
368 /* How many bits to shift the PSR_xxx bits up by. */
371 #define PSR_c (1 << 0)
372 #define PSR_x (1 << 1)
373 #define PSR_s (1 << 2)
374 #define PSR_f (1 << 3)
376 static const struct asm_psr psrs
[] =
378 {"CPSR", TRUE
, PSR_c
| PSR_f
},
379 {"CPSR_all", TRUE
, PSR_c
| PSR_f
},
380 {"SPSR", FALSE
, PSR_c
| PSR_f
},
381 {"SPSR_all", FALSE
, PSR_c
| PSR_f
},
382 {"CPSR_flg", TRUE
, PSR_f
},
383 {"CPSR_f", TRUE
, PSR_f
},
384 {"SPSR_flg", FALSE
, PSR_f
},
385 {"SPSR_f", FALSE
, PSR_f
},
386 {"CPSR_c", TRUE
, PSR_c
},
387 {"CPSR_ctl", TRUE
, PSR_c
},
388 {"SPSR_c", FALSE
, PSR_c
},
389 {"SPSR_ctl", FALSE
, PSR_c
},
390 {"CPSR_x", TRUE
, PSR_x
},
391 {"CPSR_s", TRUE
, PSR_s
},
392 {"SPSR_x", FALSE
, PSR_x
},
393 {"SPSR_s", FALSE
, PSR_s
},
394 /* Combinations of flags. */
395 {"CPSR_fs", TRUE
, PSR_f
| PSR_s
},
396 {"CPSR_fx", TRUE
, PSR_f
| PSR_x
},
397 {"CPSR_fc", TRUE
, PSR_f
| PSR_c
},
398 {"CPSR_sf", TRUE
, PSR_s
| PSR_f
},
399 {"CPSR_sx", TRUE
, PSR_s
| PSR_x
},
400 {"CPSR_sc", TRUE
, PSR_s
| PSR_c
},
401 {"CPSR_xf", TRUE
, PSR_x
| PSR_f
},
402 {"CPSR_xs", TRUE
, PSR_x
| PSR_s
},
403 {"CPSR_xc", TRUE
, PSR_x
| PSR_c
},
404 {"CPSR_cf", TRUE
, PSR_c
| PSR_f
},
405 {"CPSR_cs", TRUE
, PSR_c
| PSR_s
},
406 {"CPSR_cx", TRUE
, PSR_c
| PSR_x
},
407 {"CPSR_fsx", TRUE
, PSR_f
| PSR_s
| PSR_x
},
408 {"CPSR_fsc", TRUE
, PSR_f
| PSR_s
| PSR_c
},
409 {"CPSR_fxs", TRUE
, PSR_f
| PSR_x
| PSR_s
},
410 {"CPSR_fxc", TRUE
, PSR_f
| PSR_x
| PSR_c
},
411 {"CPSR_fcs", TRUE
, PSR_f
| PSR_c
| PSR_s
},
412 {"CPSR_fcx", TRUE
, PSR_f
| PSR_c
| PSR_x
},
413 {"CPSR_sfx", TRUE
, PSR_s
| PSR_f
| PSR_x
},
414 {"CPSR_sfc", TRUE
, PSR_s
| PSR_f
| PSR_c
},
415 {"CPSR_sxf", TRUE
, PSR_s
| PSR_x
| PSR_f
},
416 {"CPSR_sxc", TRUE
, PSR_s
| PSR_x
| PSR_c
},
417 {"CPSR_scf", TRUE
, PSR_s
| PSR_c
| PSR_f
},
418 {"CPSR_scx", TRUE
, PSR_s
| PSR_c
| PSR_x
},
419 {"CPSR_xfs", TRUE
, PSR_x
| PSR_f
| PSR_s
},
420 {"CPSR_xfc", TRUE
, PSR_x
| PSR_f
| PSR_c
},
421 {"CPSR_xsf", TRUE
, PSR_x
| PSR_s
| PSR_f
},
422 {"CPSR_xsc", TRUE
, PSR_x
| PSR_s
| PSR_c
},
423 {"CPSR_xcf", TRUE
, PSR_x
| PSR_c
| PSR_f
},
424 {"CPSR_xcs", TRUE
, PSR_x
| PSR_c
| PSR_s
},
425 {"CPSR_cfs", TRUE
, PSR_c
| PSR_f
| PSR_s
},
426 {"CPSR_cfx", TRUE
, PSR_c
| PSR_f
| PSR_x
},
427 {"CPSR_csf", TRUE
, PSR_c
| PSR_s
| PSR_f
},
428 {"CPSR_csx", TRUE
, PSR_c
| PSR_s
| PSR_x
},
429 {"CPSR_cxf", TRUE
, PSR_c
| PSR_x
| PSR_f
},
430 {"CPSR_cxs", TRUE
, PSR_c
| PSR_x
| PSR_s
},
431 {"CPSR_fsxc", TRUE
, PSR_f
| PSR_s
| PSR_x
| PSR_c
},
432 {"CPSR_fscx", TRUE
, PSR_f
| PSR_s
| PSR_c
| PSR_x
},
433 {"CPSR_fxsc", TRUE
, PSR_f
| PSR_x
| PSR_s
| PSR_c
},
434 {"CPSR_fxcs", TRUE
, PSR_f
| PSR_x
| PSR_c
| PSR_s
},
435 {"CPSR_fcsx", TRUE
, PSR_f
| PSR_c
| PSR_s
| PSR_x
},
436 {"CPSR_fcxs", TRUE
, PSR_f
| PSR_c
| PSR_x
| PSR_s
},
437 {"CPSR_sfxc", TRUE
, PSR_s
| PSR_f
| PSR_x
| PSR_c
},
438 {"CPSR_sfcx", TRUE
, PSR_s
| PSR_f
| PSR_c
| PSR_x
},
439 {"CPSR_sxfc", TRUE
, PSR_s
| PSR_x
| PSR_f
| PSR_c
},
440 {"CPSR_sxcf", TRUE
, PSR_s
| PSR_x
| PSR_c
| PSR_f
},
441 {"CPSR_scfx", TRUE
, PSR_s
| PSR_c
| PSR_f
| PSR_x
},
442 {"CPSR_scxf", TRUE
, PSR_s
| PSR_c
| PSR_x
| PSR_f
},
443 {"CPSR_xfsc", TRUE
, PSR_x
| PSR_f
| PSR_s
| PSR_c
},
444 {"CPSR_xfcs", TRUE
, PSR_x
| PSR_f
| PSR_c
| PSR_s
},
445 {"CPSR_xsfc", TRUE
, PSR_x
| PSR_s
| PSR_f
| PSR_c
},
446 {"CPSR_xscf", TRUE
, PSR_x
| PSR_s
| PSR_c
| PSR_f
},
447 {"CPSR_xcfs", TRUE
, PSR_x
| PSR_c
| PSR_f
| PSR_s
},
448 {"CPSR_xcsf", TRUE
, PSR_x
| PSR_c
| PSR_s
| PSR_f
},
449 {"CPSR_cfsx", TRUE
, PSR_c
| PSR_f
| PSR_s
| PSR_x
},
450 {"CPSR_cfxs", TRUE
, PSR_c
| PSR_f
| PSR_x
| PSR_s
},
451 {"CPSR_csfx", TRUE
, PSR_c
| PSR_s
| PSR_f
| PSR_x
},
452 {"CPSR_csxf", TRUE
, PSR_c
| PSR_s
| PSR_x
| PSR_f
},
453 {"CPSR_cxfs", TRUE
, PSR_c
| PSR_x
| PSR_f
| PSR_s
},
454 {"CPSR_cxsf", TRUE
, PSR_c
| PSR_x
| PSR_s
| PSR_f
},
455 {"SPSR_fs", FALSE
, PSR_f
| PSR_s
},
456 {"SPSR_fx", FALSE
, PSR_f
| PSR_x
},
457 {"SPSR_fc", FALSE
, PSR_f
| PSR_c
},
458 {"SPSR_sf", FALSE
, PSR_s
| PSR_f
},
459 {"SPSR_sx", FALSE
, PSR_s
| PSR_x
},
460 {"SPSR_sc", FALSE
, PSR_s
| PSR_c
},
461 {"SPSR_xf", FALSE
, PSR_x
| PSR_f
},
462 {"SPSR_xs", FALSE
, PSR_x
| PSR_s
},
463 {"SPSR_xc", FALSE
, PSR_x
| PSR_c
},
464 {"SPSR_cf", FALSE
, PSR_c
| PSR_f
},
465 {"SPSR_cs", FALSE
, PSR_c
| PSR_s
},
466 {"SPSR_cx", FALSE
, PSR_c
| PSR_x
},
467 {"SPSR_fsx", FALSE
, PSR_f
| PSR_s
| PSR_x
},
468 {"SPSR_fsc", FALSE
, PSR_f
| PSR_s
| PSR_c
},
469 {"SPSR_fxs", FALSE
, PSR_f
| PSR_x
| PSR_s
},
470 {"SPSR_fxc", FALSE
, PSR_f
| PSR_x
| PSR_c
},
471 {"SPSR_fcs", FALSE
, PSR_f
| PSR_c
| PSR_s
},
472 {"SPSR_fcx", FALSE
, PSR_f
| PSR_c
| PSR_x
},
473 {"SPSR_sfx", FALSE
, PSR_s
| PSR_f
| PSR_x
},
474 {"SPSR_sfc", FALSE
, PSR_s
| PSR_f
| PSR_c
},
475 {"SPSR_sxf", FALSE
, PSR_s
| PSR_x
| PSR_f
},
476 {"SPSR_sxc", FALSE
, PSR_s
| PSR_x
| PSR_c
},
477 {"SPSR_scf", FALSE
, PSR_s
| PSR_c
| PSR_f
},
478 {"SPSR_scx", FALSE
, PSR_s
| PSR_c
| PSR_x
},
479 {"SPSR_xfs", FALSE
, PSR_x
| PSR_f
| PSR_s
},
480 {"SPSR_xfc", FALSE
, PSR_x
| PSR_f
| PSR_c
},
481 {"SPSR_xsf", FALSE
, PSR_x
| PSR_s
| PSR_f
},
482 {"SPSR_xsc", FALSE
, PSR_x
| PSR_s
| PSR_c
},
483 {"SPSR_xcf", FALSE
, PSR_x
| PSR_c
| PSR_f
},
484 {"SPSR_xcs", FALSE
, PSR_x
| PSR_c
| PSR_s
},
485 {"SPSR_cfs", FALSE
, PSR_c
| PSR_f
| PSR_s
},
486 {"SPSR_cfx", FALSE
, PSR_c
| PSR_f
| PSR_x
},
487 {"SPSR_csf", FALSE
, PSR_c
| PSR_s
| PSR_f
},
488 {"SPSR_csx", FALSE
, PSR_c
| PSR_s
| PSR_x
},
489 {"SPSR_cxf", FALSE
, PSR_c
| PSR_x
| PSR_f
},
490 {"SPSR_cxs", FALSE
, PSR_c
| PSR_x
| PSR_s
},
491 {"SPSR_fsxc", FALSE
, PSR_f
| PSR_s
| PSR_x
| PSR_c
},
492 {"SPSR_fscx", FALSE
, PSR_f
| PSR_s
| PSR_c
| PSR_x
},
493 {"SPSR_fxsc", FALSE
, PSR_f
| PSR_x
| PSR_s
| PSR_c
},
494 {"SPSR_fxcs", FALSE
, PSR_f
| PSR_x
| PSR_c
| PSR_s
},
495 {"SPSR_fcsx", FALSE
, PSR_f
| PSR_c
| PSR_s
| PSR_x
},
496 {"SPSR_fcxs", FALSE
, PSR_f
| PSR_c
| PSR_x
| PSR_s
},
497 {"SPSR_sfxc", FALSE
, PSR_s
| PSR_f
| PSR_x
| PSR_c
},
498 {"SPSR_sfcx", FALSE
, PSR_s
| PSR_f
| PSR_c
| PSR_x
},
499 {"SPSR_sxfc", FALSE
, PSR_s
| PSR_x
| PSR_f
| PSR_c
},
500 {"SPSR_sxcf", FALSE
, PSR_s
| PSR_x
| PSR_c
| PSR_f
},
501 {"SPSR_scfx", FALSE
, PSR_s
| PSR_c
| PSR_f
| PSR_x
},
502 {"SPSR_scxf", FALSE
, PSR_s
| PSR_c
| PSR_x
| PSR_f
},
503 {"SPSR_xfsc", FALSE
, PSR_x
| PSR_f
| PSR_s
| PSR_c
},
504 {"SPSR_xfcs", FALSE
, PSR_x
| PSR_f
| PSR_c
| PSR_s
},
505 {"SPSR_xsfc", FALSE
, PSR_x
| PSR_s
| PSR_f
| PSR_c
},
506 {"SPSR_xscf", FALSE
, PSR_x
| PSR_s
| PSR_c
| PSR_f
},
507 {"SPSR_xcfs", FALSE
, PSR_x
| PSR_c
| PSR_f
| PSR_s
},
508 {"SPSR_xcsf", FALSE
, PSR_x
| PSR_c
| PSR_s
| PSR_f
},
509 {"SPSR_cfsx", FALSE
, PSR_c
| PSR_f
| PSR_s
| PSR_x
},
510 {"SPSR_cfxs", FALSE
, PSR_c
| PSR_f
| PSR_x
| PSR_s
},
511 {"SPSR_csfx", FALSE
, PSR_c
| PSR_s
| PSR_f
| PSR_x
},
512 {"SPSR_csxf", FALSE
, PSR_c
| PSR_s
| PSR_x
| PSR_f
},
513 {"SPSR_cxfs", FALSE
, PSR_c
| PSR_x
| PSR_f
| PSR_s
},
514 {"SPSR_cxsf", FALSE
, PSR_c
| PSR_x
| PSR_s
| PSR_f
},
521 IWMMXT_REG_WR_OR_WC
= 2,
525 enum iwmmxt_insn_type
548 VFP_REG_Dd
, VFP_REG_Dm
, VFP_REG_Dn
553 VFP_REG_Sd
, VFP_REG_Sm
, VFP_REG_Sn
558 VFP_LDSTMIA
, VFP_LDSTMDB
, VFP_LDSTMIAX
, VFP_LDSTMDBX
561 /* VFP system registers. */
568 static const struct vfp_reg vfp_regs
[] =
570 {"fpsid", 0x00000000},
571 {"FPSID", 0x00000000},
572 {"fpscr", 0x00010000},
573 {"FPSCR", 0x00010000},
574 {"fpexc", 0x00080000},
575 {"FPEXC", 0x00080000}
578 /* Structure for a hash table entry for a register. */
586 /* Some well known registers that we refer to directly elsewhere. */
591 #define wr_register(reg) ((reg ^ WR_PREFIX) >= 0 && (reg ^ WR_PREFIX) <= 15)
592 #define wc_register(reg) ((reg ^ WC_PREFIX) >= 0 && (reg ^ WC_PREFIX) <= 15)
593 #define wcg_register(reg) ((reg ^ WC_PREFIX) >= 8 && (reg ^ WC_PREFIX) <= 11)
595 /* These are the standard names. Users can add aliases with .req.
596 and delete them with .unreq. */
598 /* Integer Register Numbers. */
599 static const struct reg_entry rn_table
[] =
601 {"r0", 0, TRUE
}, {"r1", 1, TRUE
}, {"r2", 2, TRUE
}, {"r3", 3, TRUE
},
602 {"r4", 4, TRUE
}, {"r5", 5, TRUE
}, {"r6", 6, TRUE
}, {"r7", 7, TRUE
},
603 {"r8", 8, TRUE
}, {"r9", 9, TRUE
}, {"r10", 10, TRUE
}, {"r11", 11, TRUE
},
604 {"r12", 12, TRUE
}, {"r13", REG_SP
, TRUE
}, {"r14", REG_LR
, TRUE
}, {"r15", REG_PC
, TRUE
},
605 /* ATPCS Synonyms. */
606 {"a1", 0, TRUE
}, {"a2", 1, TRUE
}, {"a3", 2, TRUE
}, {"a4", 3, TRUE
},
607 {"v1", 4, TRUE
}, {"v2", 5, TRUE
}, {"v3", 6, TRUE
}, {"v4", 7, TRUE
},
608 {"v5", 8, TRUE
}, {"v6", 9, TRUE
}, {"v7", 10, TRUE
}, {"v8", 11, TRUE
},
609 /* Well-known aliases. */
610 {"wr", 7, TRUE
}, {"sb", 9, TRUE
}, {"sl", 10, TRUE
}, {"fp", 11, TRUE
},
611 {"ip", 12, TRUE
}, {"sp", REG_SP
, TRUE
}, {"lr", REG_LR
, TRUE
}, {"pc", REG_PC
, TRUE
},
615 #define WR_PREFIX 0x200
616 #define WC_PREFIX 0x400
618 static const struct reg_entry iwmmxt_table
[] =
620 /* Intel Wireless MMX technology register names. */
621 { "wr0", 0x0 | WR_PREFIX
, TRUE
}, {"wr1", 0x1 | WR_PREFIX
, TRUE
},
622 { "wr2", 0x2 | WR_PREFIX
, TRUE
}, {"wr3", 0x3 | WR_PREFIX
, TRUE
},
623 { "wr4", 0x4 | WR_PREFIX
, TRUE
}, {"wr5", 0x5 | WR_PREFIX
, TRUE
},
624 { "wr6", 0x6 | WR_PREFIX
, TRUE
}, {"wr7", 0x7 | WR_PREFIX
, TRUE
},
625 { "wr8", 0x8 | WR_PREFIX
, TRUE
}, {"wr9", 0x9 | WR_PREFIX
, TRUE
},
626 { "wr10", 0xa | WR_PREFIX
, TRUE
}, {"wr11", 0xb | WR_PREFIX
, TRUE
},
627 { "wr12", 0xc | WR_PREFIX
, TRUE
}, {"wr13", 0xd | WR_PREFIX
, TRUE
},
628 { "wr14", 0xe | WR_PREFIX
, TRUE
}, {"wr15", 0xf | WR_PREFIX
, TRUE
},
629 { "wcid", 0x0 | WC_PREFIX
, TRUE
}, {"wcon", 0x1 | WC_PREFIX
, TRUE
},
630 {"wcssf", 0x2 | WC_PREFIX
, TRUE
}, {"wcasf", 0x3 | WC_PREFIX
, TRUE
},
631 {"wcgr0", 0x8 | WC_PREFIX
, TRUE
}, {"wcgr1", 0x9 | WC_PREFIX
, TRUE
},
632 {"wcgr2", 0xa | WC_PREFIX
, TRUE
}, {"wcgr3", 0xb | WC_PREFIX
, TRUE
},
634 { "wR0", 0x0 | WR_PREFIX
, TRUE
}, {"wR1", 0x1 | WR_PREFIX
, TRUE
},
635 { "wR2", 0x2 | WR_PREFIX
, TRUE
}, {"wR3", 0x3 | WR_PREFIX
, TRUE
},
636 { "wR4", 0x4 | WR_PREFIX
, TRUE
}, {"wR5", 0x5 | WR_PREFIX
, TRUE
},
637 { "wR6", 0x6 | WR_PREFIX
, TRUE
}, {"wR7", 0x7 | WR_PREFIX
, TRUE
},
638 { "wR8", 0x8 | WR_PREFIX
, TRUE
}, {"wR9", 0x9 | WR_PREFIX
, TRUE
},
639 { "wR10", 0xa | WR_PREFIX
, TRUE
}, {"wR11", 0xb | WR_PREFIX
, TRUE
},
640 { "wR12", 0xc | WR_PREFIX
, TRUE
}, {"wR13", 0xd | WR_PREFIX
, TRUE
},
641 { "wR14", 0xe | WR_PREFIX
, TRUE
}, {"wR15", 0xf | WR_PREFIX
, TRUE
},
642 { "wCID", 0x0 | WC_PREFIX
, TRUE
}, {"wCon", 0x1 | WC_PREFIX
, TRUE
},
643 {"wCSSF", 0x2 | WC_PREFIX
, TRUE
}, {"wCASF", 0x3 | WC_PREFIX
, TRUE
},
644 {"wCGR0", 0x8 | WC_PREFIX
, TRUE
}, {"wCGR1", 0x9 | WC_PREFIX
, TRUE
},
645 {"wCGR2", 0xa | WC_PREFIX
, TRUE
}, {"wCGR3", 0xb | WC_PREFIX
, TRUE
},
649 /* Co-processor Numbers. */
650 static const struct reg_entry cp_table
[] =
652 {"p0", 0, TRUE
}, {"p1", 1, TRUE
}, {"p2", 2, TRUE
}, {"p3", 3, TRUE
},
653 {"p4", 4, TRUE
}, {"p5", 5, TRUE
}, {"p6", 6, TRUE
}, {"p7", 7, TRUE
},
654 {"p8", 8, TRUE
}, {"p9", 9, TRUE
}, {"p10", 10, TRUE
}, {"p11", 11, TRUE
},
655 {"p12", 12, TRUE
}, {"p13", 13, TRUE
}, {"p14", 14, TRUE
}, {"p15", 15, TRUE
},
659 /* Co-processor Register Numbers. */
660 static const struct reg_entry cn_table
[] =
662 {"c0", 0, TRUE
}, {"c1", 1, TRUE
}, {"c2", 2, TRUE
}, {"c3", 3, TRUE
},
663 {"c4", 4, TRUE
}, {"c5", 5, TRUE
}, {"c6", 6, TRUE
}, {"c7", 7, TRUE
},
664 {"c8", 8, TRUE
}, {"c9", 9, TRUE
}, {"c10", 10, TRUE
}, {"c11", 11, TRUE
},
665 {"c12", 12, TRUE
}, {"c13", 13, TRUE
}, {"c14", 14, TRUE
}, {"c15", 15, TRUE
},
666 /* Not really valid, but kept for back-wards compatibility. */
667 {"cr0", 0, TRUE
}, {"cr1", 1, TRUE
}, {"cr2", 2, TRUE
}, {"cr3", 3, TRUE
},
668 {"cr4", 4, TRUE
}, {"cr5", 5, TRUE
}, {"cr6", 6, TRUE
}, {"cr7", 7, TRUE
},
669 {"cr8", 8, TRUE
}, {"cr9", 9, TRUE
}, {"cr10", 10, TRUE
}, {"cr11", 11, TRUE
},
670 {"cr12", 12, TRUE
}, {"cr13", 13, TRUE
}, {"cr14", 14, TRUE
}, {"cr15", 15, TRUE
},
675 static const struct reg_entry fn_table
[] =
677 {"f0", 0, TRUE
}, {"f1", 1, TRUE
}, {"f2", 2, TRUE
}, {"f3", 3, TRUE
},
678 {"f4", 4, TRUE
}, {"f5", 5, TRUE
}, {"f6", 6, TRUE
}, {"f7", 7, TRUE
},
682 /* VFP SP Registers. */
683 static const struct reg_entry sn_table
[] =
685 {"s0", 0, TRUE
}, {"s1", 1, TRUE
}, {"s2", 2, TRUE
}, {"s3", 3, TRUE
},
686 {"s4", 4, TRUE
}, {"s5", 5, TRUE
}, {"s6", 6, TRUE
}, {"s7", 7, TRUE
},
687 {"s8", 8, TRUE
}, {"s9", 9, TRUE
}, {"s10", 10, TRUE
}, {"s11", 11, TRUE
},
688 {"s12", 12, TRUE
}, {"s13", 13, TRUE
}, {"s14", 14, TRUE
}, {"s15", 15, TRUE
},
689 {"s16", 16, TRUE
}, {"s17", 17, TRUE
}, {"s18", 18, TRUE
}, {"s19", 19, TRUE
},
690 {"s20", 20, TRUE
}, {"s21", 21, TRUE
}, {"s22", 22, TRUE
}, {"s23", 23, TRUE
},
691 {"s24", 24, TRUE
}, {"s25", 25, TRUE
}, {"s26", 26, TRUE
}, {"s27", 27, TRUE
},
692 {"s28", 28, TRUE
}, {"s29", 29, TRUE
}, {"s30", 30, TRUE
}, {"s31", 31, TRUE
},
696 /* VFP DP Registers. */
697 static const struct reg_entry dn_table
[] =
699 {"d0", 0, TRUE
}, {"d1", 1, TRUE
}, {"d2", 2, TRUE
}, {"d3", 3, TRUE
},
700 {"d4", 4, TRUE
}, {"d5", 5, TRUE
}, {"d6", 6, TRUE
}, {"d7", 7, TRUE
},
701 {"d8", 8, TRUE
}, {"d9", 9, TRUE
}, {"d10", 10, TRUE
}, {"d11", 11, TRUE
},
702 {"d12", 12, TRUE
}, {"d13", 13, TRUE
}, {"d14", 14, TRUE
}, {"d15", 15, TRUE
},
706 /* Maverick DSP coprocessor registers. */
707 static const struct reg_entry mav_mvf_table
[] =
709 {"mvf0", 0, TRUE
}, {"mvf1", 1, TRUE
}, {"mvf2", 2, TRUE
}, {"mvf3", 3, TRUE
},
710 {"mvf4", 4, TRUE
}, {"mvf5", 5, TRUE
}, {"mvf6", 6, TRUE
}, {"mvf7", 7, TRUE
},
711 {"mvf8", 8, TRUE
}, {"mvf9", 9, TRUE
}, {"mvf10", 10, TRUE
}, {"mvf11", 11, TRUE
},
712 {"mvf12", 12, TRUE
}, {"mvf13", 13, TRUE
}, {"mvf14", 14, TRUE
}, {"mvf15", 15, TRUE
},
716 static const struct reg_entry mav_mvd_table
[] =
718 {"mvd0", 0, TRUE
}, {"mvd1", 1, TRUE
}, {"mvd2", 2, TRUE
}, {"mvd3", 3, TRUE
},
719 {"mvd4", 4, TRUE
}, {"mvd5", 5, TRUE
}, {"mvd6", 6, TRUE
}, {"mvd7", 7, TRUE
},
720 {"mvd8", 8, TRUE
}, {"mvd9", 9, TRUE
}, {"mvd10", 10, TRUE
}, {"mvd11", 11, TRUE
},
721 {"mvd12", 12, TRUE
}, {"mvd13", 13, TRUE
}, {"mvd14", 14, TRUE
}, {"mvd15", 15, TRUE
},
725 static const struct reg_entry mav_mvfx_table
[] =
727 {"mvfx0", 0, TRUE
}, {"mvfx1", 1, TRUE
}, {"mvfx2", 2, TRUE
}, {"mvfx3", 3, TRUE
},
728 {"mvfx4", 4, TRUE
}, {"mvfx5", 5, TRUE
}, {"mvfx6", 6, TRUE
}, {"mvfx7", 7, TRUE
},
729 {"mvfx8", 8, TRUE
}, {"mvfx9", 9, TRUE
}, {"mvfx10", 10, TRUE
}, {"mvfx11", 11, TRUE
},
730 {"mvfx12", 12, TRUE
}, {"mvfx13", 13, TRUE
}, {"mvfx14", 14, TRUE
}, {"mvfx15", 15, TRUE
},
734 static const struct reg_entry mav_mvdx_table
[] =
736 {"mvdx0", 0, TRUE
}, {"mvdx1", 1, TRUE
}, {"mvdx2", 2, TRUE
}, {"mvdx3", 3, TRUE
},
737 {"mvdx4", 4, TRUE
}, {"mvdx5", 5, TRUE
}, {"mvdx6", 6, TRUE
}, {"mvdx7", 7, TRUE
},
738 {"mvdx8", 8, TRUE
}, {"mvdx9", 9, TRUE
}, {"mvdx10", 10, TRUE
}, {"mvdx11", 11, TRUE
},
739 {"mvdx12", 12, TRUE
}, {"mvdx13", 13, TRUE
}, {"mvdx14", 14, TRUE
}, {"mvdx15", 15, TRUE
},
743 static const struct reg_entry mav_mvax_table
[] =
745 {"mvax0", 0, TRUE
}, {"mvax1", 1, TRUE
}, {"mvax2", 2, TRUE
}, {"mvax3", 3, TRUE
},
749 static const struct reg_entry mav_dspsc_table
[] =
757 const struct reg_entry
*names
;
759 struct hash_control
*htab
;
760 const char *expected
;
763 struct reg_map all_reg_maps
[] =
765 {rn_table
, 15, NULL
, N_("ARM register expected")},
766 {cp_table
, 15, NULL
, N_("bad or missing co-processor number")},
767 {cn_table
, 15, NULL
, N_("co-processor register expected")},
768 {fn_table
, 7, NULL
, N_("FPA register expected")},
769 {sn_table
, 31, NULL
, N_("VFP single precision register expected")},
770 {dn_table
, 15, NULL
, N_("VFP double precision register expected")},
771 {mav_mvf_table
, 15, NULL
, N_("Maverick MVF register expected")},
772 {mav_mvd_table
, 15, NULL
, N_("Maverick MVD register expected")},
773 {mav_mvfx_table
, 15, NULL
, N_("Maverick MVFX register expected")},
774 {mav_mvdx_table
, 15, NULL
, N_("Maverick MVDX register expected")},
775 {mav_mvax_table
, 3, NULL
, N_("Maverick MVAX register expected")},
776 {mav_dspsc_table
, 0, NULL
, N_("Maverick DSPSC register expected")},
777 {iwmmxt_table
, 23, NULL
, N_("Intel Wireless MMX technology register expected")},
780 /* Enumeration matching entries in table above. */
784 #define REG_TYPE_FIRST REG_TYPE_RN
796 REG_TYPE_IWMMXT
= 12,
801 /* Functions called by parser. */
802 /* ARM instructions. */
803 static void do_arit
PARAMS ((char *));
804 static void do_cmp
PARAMS ((char *));
805 static void do_mov
PARAMS ((char *));
806 static void do_ldst
PARAMS ((char *));
807 static void do_ldstt
PARAMS ((char *));
808 static void do_ldmstm
PARAMS ((char *));
809 static void do_branch
PARAMS ((char *));
810 static void do_swi
PARAMS ((char *));
812 /* Pseudo Op codes. */
813 static void do_adr
PARAMS ((char *));
814 static void do_adrl
PARAMS ((char *));
815 static void do_empty
PARAMS ((char *));
818 static void do_mul
PARAMS ((char *));
819 static void do_mla
PARAMS ((char *));
822 static void do_swap
PARAMS ((char *));
825 static void do_msr
PARAMS ((char *));
826 static void do_mrs
PARAMS ((char *));
829 static void do_mull
PARAMS ((char *));
832 static void do_ldstv4
PARAMS ((char *));
835 static void do_bx
PARAMS ((char *));
838 static void do_blx
PARAMS ((char *));
839 static void do_bkpt
PARAMS ((char *));
840 static void do_clz
PARAMS ((char *));
841 static void do_lstc2
PARAMS ((char *));
842 static void do_cdp2
PARAMS ((char *));
843 static void do_co_reg2
PARAMS ((char *));
846 static void do_smla
PARAMS ((char *));
847 static void do_smlal
PARAMS ((char *));
848 static void do_smul
PARAMS ((char *));
849 static void do_qadd
PARAMS ((char *));
852 static void do_pld
PARAMS ((char *));
853 static void do_ldrd
PARAMS ((char *));
854 static void do_co_reg2c
PARAMS ((char *));
857 static void do_bxj
PARAMS ((char *));
859 /* Coprocessor Instructions. */
860 static void do_cdp
PARAMS ((char *));
861 static void do_lstc
PARAMS ((char *));
862 static void do_co_reg
PARAMS ((char *));
864 /* FPA instructions. */
865 static void do_fpa_ctrl
PARAMS ((char *));
866 static void do_fpa_ldst
PARAMS ((char *));
867 static void do_fpa_ldmstm
PARAMS ((char *));
868 static void do_fpa_dyadic
PARAMS ((char *));
869 static void do_fpa_monadic
PARAMS ((char *));
870 static void do_fpa_cmp
PARAMS ((char *));
871 static void do_fpa_from_reg
PARAMS ((char *));
872 static void do_fpa_to_reg
PARAMS ((char *));
874 /* VFP instructions. */
875 static void do_vfp_sp_monadic
PARAMS ((char *));
876 static void do_vfp_dp_monadic
PARAMS ((char *));
877 static void do_vfp_sp_dyadic
PARAMS ((char *));
878 static void do_vfp_dp_dyadic
PARAMS ((char *));
879 static void do_vfp_reg_from_sp
PARAMS ((char *));
880 static void do_vfp_sp_from_reg
PARAMS ((char *));
881 static void do_vfp_sp_reg2
PARAMS ((char *));
882 static void do_vfp_reg_from_dp
PARAMS ((char *));
883 static void do_vfp_reg2_from_dp
PARAMS ((char *));
884 static void do_vfp_dp_from_reg
PARAMS ((char *));
885 static void do_vfp_dp_from_reg2
PARAMS ((char *));
886 static void do_vfp_reg_from_ctrl
PARAMS ((char *));
887 static void do_vfp_ctrl_from_reg
PARAMS ((char *));
888 static void do_vfp_sp_ldst
PARAMS ((char *));
889 static void do_vfp_dp_ldst
PARAMS ((char *));
890 static void do_vfp_sp_ldstmia
PARAMS ((char *));
891 static void do_vfp_sp_ldstmdb
PARAMS ((char *));
892 static void do_vfp_dp_ldstmia
PARAMS ((char *));
893 static void do_vfp_dp_ldstmdb
PARAMS ((char *));
894 static void do_vfp_xp_ldstmia
PARAMS ((char *));
895 static void do_vfp_xp_ldstmdb
PARAMS ((char *));
896 static void do_vfp_sp_compare_z
PARAMS ((char *));
897 static void do_vfp_dp_compare_z
PARAMS ((char *));
898 static void do_vfp_dp_sp_cvt
PARAMS ((char *));
899 static void do_vfp_sp_dp_cvt
PARAMS ((char *));
902 static void do_xsc_mia
PARAMS ((char *));
903 static void do_xsc_mar
PARAMS ((char *));
904 static void do_xsc_mra
PARAMS ((char *));
907 static void do_mav_binops
PARAMS ((char *, int, enum arm_reg_type
,
909 static void do_mav_binops_1a
PARAMS ((char *));
910 static void do_mav_binops_1b
PARAMS ((char *));
911 static void do_mav_binops_1c
PARAMS ((char *));
912 static void do_mav_binops_1d
PARAMS ((char *));
913 static void do_mav_binops_1e
PARAMS ((char *));
914 static void do_mav_binops_1f
PARAMS ((char *));
915 static void do_mav_binops_1g
PARAMS ((char *));
916 static void do_mav_binops_1h
PARAMS ((char *));
917 static void do_mav_binops_1i
PARAMS ((char *));
918 static void do_mav_binops_1j
PARAMS ((char *));
919 static void do_mav_binops_1k
PARAMS ((char *));
920 static void do_mav_binops_1l
PARAMS ((char *));
921 static void do_mav_binops_1m
PARAMS ((char *));
922 static void do_mav_binops_1n
PARAMS ((char *));
923 static void do_mav_binops_1o
PARAMS ((char *));
924 static void do_mav_binops_2a
PARAMS ((char *));
925 static void do_mav_binops_2b
PARAMS ((char *));
926 static void do_mav_binops_2c
PARAMS ((char *));
927 static void do_mav_binops_3a
PARAMS ((char *));
928 static void do_mav_binops_3b
PARAMS ((char *));
929 static void do_mav_binops_3c
PARAMS ((char *));
930 static void do_mav_binops_3d
PARAMS ((char *));
931 static void do_mav_triple
PARAMS ((char *, int, enum arm_reg_type
,
934 static void do_mav_triple_4a
PARAMS ((char *));
935 static void do_mav_triple_4b
PARAMS ((char *));
936 static void do_mav_triple_5a
PARAMS ((char *));
937 static void do_mav_triple_5b
PARAMS ((char *));
938 static void do_mav_triple_5c
PARAMS ((char *));
939 static void do_mav_triple_5d
PARAMS ((char *));
940 static void do_mav_triple_5e
PARAMS ((char *));
941 static void do_mav_triple_5f
PARAMS ((char *));
942 static void do_mav_triple_5g
PARAMS ((char *));
943 static void do_mav_triple_5h
PARAMS ((char *));
944 static void do_mav_quad
PARAMS ((char *, int, enum arm_reg_type
,
948 static void do_mav_quad_6a
PARAMS ((char *));
949 static void do_mav_quad_6b
PARAMS ((char *));
950 static void do_mav_dspsc_1
PARAMS ((char *));
951 static void do_mav_dspsc_2
PARAMS ((char *));
952 static void do_mav_shift
PARAMS ((char *, enum arm_reg_type
,
954 static void do_mav_shift_1
PARAMS ((char *));
955 static void do_mav_shift_2
PARAMS ((char *));
956 static void do_mav_ldst
PARAMS ((char *, enum arm_reg_type
));
957 static void do_mav_ldst_1
PARAMS ((char *));
958 static void do_mav_ldst_2
PARAMS ((char *));
959 static void do_mav_ldst_3
PARAMS ((char *));
960 static void do_mav_ldst_4
PARAMS ((char *));
962 static int mav_reg_required_here
PARAMS ((char **, int,
964 static int mav_parse_offset
PARAMS ((char **, int *));
966 static void fix_new_arm
PARAMS ((fragS
*, int, short, expressionS
*,
968 static int arm_reg_parse
PARAMS ((char **, struct hash_control
*));
969 static enum arm_reg_type arm_reg_parse_any
PARAMS ((char *));
970 static const struct asm_psr
* arm_psr_parse
PARAMS ((char **));
971 static void symbol_locate
PARAMS ((symbolS
*, const char *, segT
, valueT
,
973 static int add_to_lit_pool
PARAMS ((void));
974 static unsigned validate_immediate
PARAMS ((unsigned));
975 static unsigned validate_immediate_twopart
PARAMS ((unsigned int,
977 static int validate_offset_imm
PARAMS ((unsigned int, int));
978 static void opcode_select
PARAMS ((int));
979 static void end_of_line
PARAMS ((char *));
980 static int reg_required_here
PARAMS ((char **, int));
981 static int psr_required_here
PARAMS ((char **));
982 static int co_proc_number
PARAMS ((char **));
983 static int cp_opc_expr
PARAMS ((char **, int, int));
984 static int cp_reg_required_here
PARAMS ((char **, int));
985 static int fp_reg_required_here
PARAMS ((char **, int));
986 static int vfp_sp_reg_required_here
PARAMS ((char **, enum vfp_sp_reg_pos
));
987 static int vfp_dp_reg_required_here
PARAMS ((char **, enum vfp_dp_reg_pos
));
988 static void vfp_sp_ldstm
PARAMS ((char *, enum vfp_ldstm_type
));
989 static void vfp_dp_ldstm
PARAMS ((char *, enum vfp_ldstm_type
));
990 static long vfp_sp_reg_list
PARAMS ((char **, enum vfp_sp_reg_pos
));
991 static long vfp_dp_reg_list
PARAMS ((char **));
992 static int vfp_psr_required_here
PARAMS ((char **str
));
993 static const struct vfp_reg
*vfp_psr_parse
PARAMS ((char **str
));
994 static int cp_address_offset
PARAMS ((char **));
995 static int cp_address_required_here
PARAMS ((char **, int));
996 static int my_get_float_expression
PARAMS ((char **));
997 static int skip_past_comma
PARAMS ((char **));
998 static int walk_no_bignums
PARAMS ((symbolS
*));
999 static int negate_data_op
PARAMS ((unsigned long *, unsigned long));
1000 static int data_op2
PARAMS ((char **));
1001 static int fp_op2
PARAMS ((char **));
1002 static long reg_list
PARAMS ((char **));
1003 static void thumb_load_store
PARAMS ((char *, int, int));
1004 static int decode_shift
PARAMS ((char **, int));
1005 static int ldst_extend
PARAMS ((char **));
1006 static int ldst_extend_v4
PARAMS ((char **));
1007 static void thumb_add_sub
PARAMS ((char *, int));
1008 static void insert_reg
PARAMS ((const struct reg_entry
*,
1009 struct hash_control
*));
1010 static void thumb_shift
PARAMS ((char *, int));
1011 static void thumb_mov_compare
PARAMS ((char *, int));
1012 static void build_arm_ops_hsh
PARAMS ((void));
1013 static void set_constant_flonums
PARAMS ((void));
1014 static valueT md_chars_to_number
PARAMS ((char *, int));
1015 static void build_reg_hsh
PARAMS ((struct reg_map
*));
1016 static void insert_reg_alias
PARAMS ((char *, int, struct hash_control
*));
1017 static int create_register_alias
PARAMS ((char *, char *));
1018 static void output_inst
PARAMS ((const char *));
1019 static int accum0_required_here
PARAMS ((char **));
1020 static int ld_mode_required_here
PARAMS ((char **));
1021 static void do_branch25
PARAMS ((char *));
1022 static symbolS
* find_real_start
PARAMS ((symbolS
*));
1024 static bfd_reloc_code_real_type arm_parse_reloc
PARAMS ((void));
1027 static int wreg_required_here
PARAMS ((char **, int, enum wreg_type
));
1028 static void do_iwmmxt_byte_addr
PARAMS ((char *));
1029 static void do_iwmmxt_tandc
PARAMS ((char *));
1030 static void do_iwmmxt_tbcst
PARAMS ((char *));
1031 static void do_iwmmxt_textrc
PARAMS ((char *));
1032 static void do_iwmmxt_textrm
PARAMS ((char *));
1033 static void do_iwmmxt_tinsr
PARAMS ((char *));
1034 static void do_iwmmxt_tmcr
PARAMS ((char *));
1035 static void do_iwmmxt_tmcrr
PARAMS ((char *));
1036 static void do_iwmmxt_tmia
PARAMS ((char *));
1037 static void do_iwmmxt_tmovmsk
PARAMS ((char *));
1038 static void do_iwmmxt_tmrc
PARAMS ((char *));
1039 static void do_iwmmxt_tmrrc
PARAMS ((char *));
1040 static void do_iwmmxt_torc
PARAMS ((char *));
1041 static void do_iwmmxt_waligni
PARAMS ((char *));
1042 static void do_iwmmxt_wmov
PARAMS ((char *));
1043 static void do_iwmmxt_word_addr
PARAMS ((char *));
1044 static void do_iwmmxt_wrwr
PARAMS ((char *));
1045 static void do_iwmmxt_wrwrwcg
PARAMS ((char *));
1046 static void do_iwmmxt_wrwrwr
PARAMS ((char *));
1047 static void do_iwmmxt_wshufh
PARAMS ((char *));
1048 static void do_iwmmxt_wzero
PARAMS ((char *));
1049 static int cp_byte_address_offset
PARAMS ((char **));
1050 static int cp_byte_address_required_here
PARAMS ((char **));
1052 /* ARM instructions take 4bytes in the object file, Thumb instructions
1056 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
1057 #define MAV_MODE1 0x100c
1059 /* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
1060 #define MAV_MODE2 0x0c10
1062 /* "INSN<cond> X,Y" where X:0, Y:bit16. */
1063 #define MAV_MODE3 0x1000
1065 /* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
1066 #define MAV_MODE4 0x0c0010
1068 /* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
1069 #define MAV_MODE5 0x00100c
1071 /* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
1072 #define MAV_MODE6 0x00100c05
1076 /* Basic string to match. */
1077 const char * template;
1079 /* Basic instruction code. */
1080 unsigned long value
;
1082 /* Offset into the template where the condition code (if any) will be.
1083 If zero, then the instruction is never conditional. */
1084 unsigned cond_offset
;
1086 /* Which architecture variant provides this instruction. */
1087 unsigned long variant
;
1089 /* Function to call to parse args. */
1090 void (* parms
) PARAMS ((char *));
1093 static const struct asm_opcode insns
[] =
1095 /* Core ARM Instructions. */
1096 {"and", 0xe0000000, 3, ARM_EXT_V1
, do_arit
},
1097 {"ands", 0xe0100000, 3, ARM_EXT_V1
, do_arit
},
1098 {"eor", 0xe0200000, 3, ARM_EXT_V1
, do_arit
},
1099 {"eors", 0xe0300000, 3, ARM_EXT_V1
, do_arit
},
1100 {"sub", 0xe0400000, 3, ARM_EXT_V1
, do_arit
},
1101 {"subs", 0xe0500000, 3, ARM_EXT_V1
, do_arit
},
1102 {"rsb", 0xe0600000, 3, ARM_EXT_V1
, do_arit
},
1103 {"rsbs", 0xe0700000, 3, ARM_EXT_V1
, do_arit
},
1104 {"add", 0xe0800000, 3, ARM_EXT_V1
, do_arit
},
1105 {"adds", 0xe0900000, 3, ARM_EXT_V1
, do_arit
},
1106 {"adc", 0xe0a00000, 3, ARM_EXT_V1
, do_arit
},
1107 {"adcs", 0xe0b00000, 3, ARM_EXT_V1
, do_arit
},
1108 {"sbc", 0xe0c00000, 3, ARM_EXT_V1
, do_arit
},
1109 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1
, do_arit
},
1110 {"rsc", 0xe0e00000, 3, ARM_EXT_V1
, do_arit
},
1111 {"rscs", 0xe0f00000, 3, ARM_EXT_V1
, do_arit
},
1112 {"orr", 0xe1800000, 3, ARM_EXT_V1
, do_arit
},
1113 {"orrs", 0xe1900000, 3, ARM_EXT_V1
, do_arit
},
1114 {"bic", 0xe1c00000, 3, ARM_EXT_V1
, do_arit
},
1115 {"bics", 0xe1d00000, 3, ARM_EXT_V1
, do_arit
},
1117 {"tst", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
1118 {"tsts", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
1119 {"tstp", 0xe110f000, 3, ARM_EXT_V1
, do_cmp
},
1120 {"teq", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
1121 {"teqs", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
1122 {"teqp", 0xe130f000, 3, ARM_EXT_V1
, do_cmp
},
1123 {"cmp", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
1124 {"cmps", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
1125 {"cmpp", 0xe150f000, 3, ARM_EXT_V1
, do_cmp
},
1126 {"cmn", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
1127 {"cmns", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
1128 {"cmnp", 0xe170f000, 3, ARM_EXT_V1
, do_cmp
},
1130 {"mov", 0xe1a00000, 3, ARM_EXT_V1
, do_mov
},
1131 {"movs", 0xe1b00000, 3, ARM_EXT_V1
, do_mov
},
1132 {"mvn", 0xe1e00000, 3, ARM_EXT_V1
, do_mov
},
1133 {"mvns", 0xe1f00000, 3, ARM_EXT_V1
, do_mov
},
1135 {"ldr", 0xe4100000, 3, ARM_EXT_V1
, do_ldst
},
1136 {"ldrb", 0xe4500000, 3, ARM_EXT_V1
, do_ldst
},
1137 {"ldrt", 0xe4300000, 3, ARM_EXT_V1
, do_ldstt
},
1138 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1
, do_ldstt
},
1139 {"str", 0xe4000000, 3, ARM_EXT_V1
, do_ldst
},
1140 {"strb", 0xe4400000, 3, ARM_EXT_V1
, do_ldst
},
1141 {"strt", 0xe4200000, 3, ARM_EXT_V1
, do_ldstt
},
1142 {"strbt", 0xe4600000, 3, ARM_EXT_V1
, do_ldstt
},
1144 {"stmia", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
1145 {"stmib", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
1146 {"stmda", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
1147 {"stmdb", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
1148 {"stmfd", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
1149 {"stmfa", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
1150 {"stmea", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
1151 {"stmed", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
1153 {"ldmia", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
1154 {"ldmib", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
1155 {"ldmda", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
1156 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
1157 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
1158 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
1159 {"ldmea", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
1160 {"ldmed", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
1162 {"swi", 0xef000000, 3, ARM_EXT_V1
, do_swi
},
1164 /* XXX This is the wrong place to do this. Think multi-arch. */
1165 {"bl", 0xeb000000, 2, ARM_EXT_V1
, do_branch
},
1166 {"b", 0xea000000, 1, ARM_EXT_V1
, do_branch
},
1168 {"bl", 0xebfffffe, 2, ARM_EXT_V1
, do_branch
},
1169 {"b", 0xeafffffe, 1, ARM_EXT_V1
, do_branch
},
1173 {"adr", 0xe28f0000, 3, ARM_EXT_V1
, do_adr
},
1174 {"adrl", 0xe28f0000, 3, ARM_EXT_V1
, do_adrl
},
1175 {"nop", 0xe1a00000, 3, ARM_EXT_V1
, do_empty
},
1177 /* ARM 2 multiplies. */
1178 {"mul", 0xe0000090, 3, ARM_EXT_V2
, do_mul
},
1179 {"muls", 0xe0100090, 3, ARM_EXT_V2
, do_mul
},
1180 {"mla", 0xe0200090, 3, ARM_EXT_V2
, do_mla
},
1181 {"mlas", 0xe0300090, 3, ARM_EXT_V2
, do_mla
},
1183 /* Generic copressor instructions. */
1184 {"cdp", 0xee000000, 3, ARM_EXT_V2
, do_cdp
},
1185 {"ldc", 0xec100000, 3, ARM_EXT_V2
, do_lstc
},
1186 {"ldcl", 0xec500000, 3, ARM_EXT_V2
, do_lstc
},
1187 {"stc", 0xec000000, 3, ARM_EXT_V2
, do_lstc
},
1188 {"stcl", 0xec400000, 3, ARM_EXT_V2
, do_lstc
},
1189 {"mcr", 0xee000010, 3, ARM_EXT_V2
, do_co_reg
},
1190 {"mrc", 0xee100010, 3, ARM_EXT_V2
, do_co_reg
},
1192 /* ARM 3 - swp instructions. */
1193 {"swp", 0xe1000090, 3, ARM_EXT_V2S
, do_swap
},
1194 {"swpb", 0xe1400090, 3, ARM_EXT_V2S
, do_swap
},
1196 /* ARM 6 Status register instructions. */
1197 {"mrs", 0xe10f0000, 3, ARM_EXT_V3
, do_mrs
},
1198 {"msr", 0xe120f000, 3, ARM_EXT_V3
, do_msr
},
1199 /* ScottB: our code uses 0xe128f000 for msr.
1200 NickC: but this is wrong because the bits 16 through 19 are
1201 handled by the PSR_xxx defines above. */
1203 /* ARM 7M long multiplies. */
1204 {"smull", 0xe0c00090, 5, ARM_EXT_V3M
, do_mull
},
1205 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M
, do_mull
},
1206 {"umull", 0xe0800090, 5, ARM_EXT_V3M
, do_mull
},
1207 {"umulls", 0xe0900090, 5, ARM_EXT_V3M
, do_mull
},
1208 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M
, do_mull
},
1209 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M
, do_mull
},
1210 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M
, do_mull
},
1211 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M
, do_mull
},
1213 /* ARM Architecture 4. */
1214 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4
, do_ldstv4
},
1215 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4
, do_ldstv4
},
1216 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4
, do_ldstv4
},
1217 {"strh", 0xe00000b0, 3, ARM_EXT_V4
, do_ldstv4
},
1219 /* ARM Architecture 4T. */
1220 /* Note: bx (and blx) are required on V5, even if the processor does
1221 not support Thumb. */
1222 {"bx", 0xe12fff10, 2, ARM_EXT_V4T
| ARM_EXT_V5
, do_bx
},
1224 /* ARM Architecture 5T. */
1225 /* Note: blx has 2 variants, so the .value is set dynamically.
1226 Only one of the variants has conditional execution. */
1227 {"blx", 0xe0000000, 3, ARM_EXT_V5
, do_blx
},
1228 {"clz", 0xe16f0f10, 3, ARM_EXT_V5
, do_clz
},
1229 {"bkpt", 0xe1200070, 0, ARM_EXT_V5
, do_bkpt
},
1230 {"ldc2", 0xfc100000, 0, ARM_EXT_V5
, do_lstc2
},
1231 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5
, do_lstc2
},
1232 {"stc2", 0xfc000000, 0, ARM_EXT_V5
, do_lstc2
},
1233 {"stc2l", 0xfc400000, 0, ARM_EXT_V5
, do_lstc2
},
1234 {"cdp2", 0xfe000000, 0, ARM_EXT_V5
, do_cdp2
},
1235 {"mcr2", 0xfe000010, 0, ARM_EXT_V5
, do_co_reg2
},
1236 {"mrc2", 0xfe100010, 0, ARM_EXT_V5
, do_co_reg2
},
1238 /* ARM Architecture 5TExP. */
1239 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP
, do_smla
},
1240 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP
, do_smla
},
1241 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP
, do_smla
},
1242 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP
, do_smla
},
1244 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP
, do_smla
},
1245 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP
, do_smla
},
1247 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP
, do_smlal
},
1248 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP
, do_smlal
},
1249 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP
, do_smlal
},
1250 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP
, do_smlal
},
1252 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP
, do_smul
},
1253 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP
, do_smul
},
1254 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP
, do_smul
},
1255 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP
, do_smul
},
1257 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP
, do_smul
},
1258 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP
, do_smul
},
1260 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP
, do_qadd
},
1261 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP
, do_qadd
},
1262 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP
, do_qadd
},
1263 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP
, do_qadd
},
1265 /* ARM Architecture 5TE. */
1266 {"pld", 0xf450f000, 0, ARM_EXT_V5E
, do_pld
},
1267 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E
, do_ldrd
},
1268 {"strd", 0xe00000f0, 3, ARM_EXT_V5E
, do_ldrd
},
1270 {"mcrr", 0xec400000, 4, ARM_EXT_V5E
, do_co_reg2c
},
1271 {"mrrc", 0xec500000, 4, ARM_EXT_V5E
, do_co_reg2c
},
1273 /* ARM Architecture 5TEJ. */
1274 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J
, do_bxj
},
1276 /* Core FPA instruction set (V1). */
1277 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1278 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1279 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1280 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1282 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1283 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1284 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1285 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1287 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1288 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1289 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1290 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1292 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1293 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1294 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1295 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1296 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1297 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1298 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1299 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1300 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1301 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1302 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1303 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1305 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1306 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1307 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1308 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1309 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1310 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1311 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1312 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1313 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1314 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1315 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1316 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1318 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1319 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1320 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1321 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1322 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1323 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1324 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1325 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1326 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1327 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1328 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1329 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1331 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1332 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1333 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1334 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1335 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1336 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1337 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1338 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1339 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1340 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1341 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1342 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1344 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1345 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1346 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1347 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1348 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1349 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1350 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1351 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1352 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1353 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1354 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1355 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1357 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1358 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1359 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1360 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1361 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1362 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1363 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1364 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1365 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1366 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1367 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1368 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1370 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1371 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1372 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1373 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1374 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1375 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1376 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1377 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1378 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1379 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1380 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1381 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1383 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1384 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1385 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1386 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1387 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1388 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1389 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1390 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1391 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1392 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1393 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1394 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1396 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1397 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1398 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1399 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1400 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1401 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1402 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1403 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1404 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1405 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1406 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1407 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1409 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1410 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1411 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1412 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1413 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1414 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1415 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1416 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1417 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1418 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1419 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1420 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1422 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1423 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1424 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1425 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1426 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1427 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1428 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1429 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1430 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1431 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1432 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1433 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1435 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1436 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1437 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1438 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1439 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1440 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1441 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1442 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1443 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1444 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1445 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1446 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1448 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1449 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1450 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1451 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1452 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1453 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1454 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1455 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1456 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1457 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1458 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1459 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1461 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1462 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1463 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1464 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1465 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1466 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1467 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1468 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1469 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1470 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1471 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1472 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1474 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1475 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1476 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1477 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1478 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1479 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1480 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1481 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1482 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1483 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1484 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1485 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1487 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1488 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1489 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1490 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1491 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1492 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1493 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1494 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1495 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1496 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1497 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1498 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1500 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1501 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1502 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1503 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1504 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1505 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1506 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1507 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1508 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1509 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1510 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1511 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1513 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1514 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1515 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1516 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1517 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1518 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1519 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1520 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1521 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1522 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1523 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1524 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1526 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1527 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1528 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1529 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1530 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1531 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1532 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1533 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1534 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1535 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1536 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1537 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1539 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1540 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1541 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1542 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1543 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1544 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1545 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1546 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1547 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1548 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1549 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1550 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1552 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1553 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1554 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1555 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1556 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1557 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1558 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1559 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1560 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1561 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1562 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1563 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1565 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1566 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1567 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1568 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1569 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1570 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1571 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1572 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1573 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1574 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1575 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1576 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1578 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1579 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1580 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1581 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1582 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1583 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1584 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1585 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1586 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1587 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1588 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1589 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1591 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1592 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1593 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1594 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1595 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1596 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1597 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1598 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1599 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1600 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1601 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1602 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1604 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1605 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1606 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1607 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1608 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1609 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1610 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1611 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1612 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1613 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1614 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1615 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1617 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1618 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1619 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1620 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1621 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1622 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1623 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1624 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1625 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1626 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1627 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1628 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1630 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1631 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1632 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1633 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1634 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1635 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1636 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1637 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1638 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1639 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1640 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1641 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1643 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1644 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1645 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1646 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1647 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1648 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1649 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1650 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1651 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1652 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1653 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1654 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1656 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1657 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1658 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1659 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1660 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1661 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1662 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1663 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1664 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1665 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1666 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1667 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1669 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1670 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1671 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1672 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1673 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
1674 not be an optional suffix, but part of the instruction. To be
1675 compatible, we accept either. */
1676 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1677 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1679 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1680 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1681 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1682 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1683 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1684 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1685 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1686 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1687 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1688 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1689 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1690 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1692 /* The implementation of the FIX instruction is broken on some
1693 assemblers, in that it accepts a precision specifier as well as a
1694 rounding specifier, despite the fact that this is meaningless.
1695 To be more compatible, we accept it as well, though of course it
1696 does not set any bits. */
1697 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1698 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1699 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1700 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1701 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1702 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1703 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1704 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1705 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1706 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1707 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1708 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1709 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1711 /* Instructions that were new with the real FPA, call them V2. */
1712 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1713 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1714 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1715 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1716 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1717 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1719 /* VFP V1xD (single precision). */
1720 /* Moves and type conversions. */
1721 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1722 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_reg_from_sp
},
1723 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_from_reg
},
1724 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD
, do_empty
},
1725 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1726 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1727 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1728 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1729 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1730 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1731 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_reg_from_ctrl
},
1732 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_ctrl_from_reg
},
1734 /* Memory operations. */
1735 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldst
},
1736 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldst
},
1737 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1738 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1739 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1740 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1741 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1742 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1743 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1744 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1745 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1746 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1747 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1748 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1749 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1750 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1751 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1752 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1754 /* Monadic operations. */
1755 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1756 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1757 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1759 /* Dyadic operations. */
1760 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1761 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1762 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1763 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1764 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1765 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1766 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1767 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1768 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1771 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1772 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_compare_z
},
1773 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1774 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_compare_z
},
1776 /* VFP V1 (Double precision). */
1777 /* Moves and type conversions. */
1778 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1779 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
1780 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1781 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1
, do_vfp_dp_from_reg
},
1782 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1
, do_vfp_dp_from_reg
},
1783 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1
, do_vfp_reg_from_dp
},
1784 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1
, do_vfp_reg_from_dp
},
1785 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
1786 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
1787 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1788 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1789 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1790 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1792 /* Memory operations. */
1793 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1
, do_vfp_dp_ldst
},
1794 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1
, do_vfp_dp_ldst
},
1795 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1796 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1797 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1798 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1799 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1800 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1801 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1802 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1804 /* Monadic operations. */
1805 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1806 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1807 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1809 /* Dyadic operations. */
1810 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1811 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1812 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1813 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1814 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1815 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1816 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1817 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1818 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1821 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1822 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_compare_z
},
1823 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1824 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1
, do_vfp_dp_compare_z
},
1827 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2
, do_vfp_sp_reg2
},
1828 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2
, do_vfp_sp_reg2
},
1829 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2
, do_vfp_dp_from_reg2
},
1830 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2
, do_vfp_reg2_from_dp
},
1832 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
1833 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE
, do_xsc_mia
},
1834 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1835 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1836 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1837 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1838 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1839 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE
, do_xsc_mar
},
1840 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE
, do_xsc_mra
},
1842 /* Intel Wireless MMX technology instructions. */
1843 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
1844 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
1845 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
1846 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
1847 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
1848 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
1849 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
1850 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
1851 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
1852 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
1853 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
1854 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
1855 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
1856 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
1857 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
1858 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
1859 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
1860 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
1861 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmcr
},
1862 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_tmcrr
},
1863 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
1864 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
1865 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
1866 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
1867 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
1868 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
1869 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
1870 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
1871 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
1872 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmrc
},
1873 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_tmrrc
},
1874 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
1875 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
1876 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
1877 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1878 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1879 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1880 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1881 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1882 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1883 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1884 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1885 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1886 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1887 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1888 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1889 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_waligni
},
1890 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1891 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1892 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1893 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1894 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1895 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1896 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1897 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1898 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1899 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1900 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1901 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1902 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1903 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1904 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1905 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1906 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1907 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1908 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1909 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
1910 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
1911 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
1912 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
1913 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1914 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1915 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1916 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1917 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1918 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1919 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1920 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1921 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1922 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1923 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1924 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1925 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1926 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1927 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1928 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1929 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1930 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1931 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wmov
},
1932 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1933 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1934 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1935 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1936 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1937 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1938 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1939 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1940 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1941 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1942 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1943 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1944 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1945 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1946 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1947 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1948 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1949 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1950 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1951 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1952 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1953 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wshufh
},
1954 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1955 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1956 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1957 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1958 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1959 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1960 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1961 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1962 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1963 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1964 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1965 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1966 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1967 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1968 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1969 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1970 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1971 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1972 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
1973 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
1974 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
1975 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
1976 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1977 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1978 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1979 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1980 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1981 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1982 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1983 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1984 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1985 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1986 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1987 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1988 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1989 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1990 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1991 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1992 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1993 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1994 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1995 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1996 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1997 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1998 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1999 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2000 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2001 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2002 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2003 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2004 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wzero
},
2006 /* Cirrus Maverick instructions. */
2007 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_1
},
2008 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_2
},
2009 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_3
},
2010 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_4
},
2011 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_1
},
2012 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_2
},
2013 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_3
},
2014 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_4
},
2015 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK
, do_mav_binops_2a
},
2016 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1a
},
2017 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK
, do_mav_binops_2b
},
2018 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1b
},
2019 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK
, do_mav_binops_2b
},
2020 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1b
},
2021 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK
, do_mav_binops_2c
},
2022 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1c
},
2023 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK
, do_mav_binops_2c
},
2024 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1c
},
2025 {"cfmval32", 0xee100610, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
2026 {"cfmv32al", 0xee000610, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
2027 {"cfmvam32", 0xee100630, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
2028 {"cfmv32am", 0xee000630, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
2029 {"cfmvah32", 0xee100650, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
2030 {"cfmv32ah", 0xee000650, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
2031 {"cfmva32", 0xee100670, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
2032 {"cfmv32a", 0xee000670, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
2033 {"cfmva64", 0xee100690, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3c
},
2034 {"cfmv64a", 0xee000690, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3d
},
2035 {"cfmvsc32", 0xee1006b0, 8, ARM_CEXT_MAVERICK
, do_mav_dspsc_1
},
2036 {"cfmv32sc", 0xee0006b0, 8, ARM_CEXT_MAVERICK
, do_mav_dspsc_2
},
2037 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
2038 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
2039 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1f
},
2040 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1g
},
2041 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1h
},
2042 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1i
},
2043 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1j
},
2044 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1k
},
2045 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1l
},
2046 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1m
},
2047 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK
, do_mav_binops_1l
},
2048 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK
, do_mav_binops_1m
},
2049 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK
, do_mav_triple_4a
},
2050 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK
, do_mav_triple_4b
},
2051 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK
, do_mav_shift_1
},
2052 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK
, do_mav_shift_2
},
2053 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5a
},
2054 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5b
},
2055 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5c
},
2056 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5d
},
2057 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
2058 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
2059 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
2060 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
2061 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
2062 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
2063 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
2064 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
2065 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
2066 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
2067 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1n
},
2068 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1o
},
2069 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1n
},
2070 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1o
},
2071 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2072 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
2073 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2074 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
2075 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2076 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
2077 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2078 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2079 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK
, do_mav_quad_6a
},
2080 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK
, do_mav_quad_6a
},
2081 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK
, do_mav_quad_6b
},
2082 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK
, do_mav_quad_6b
},
2085 /* Defines for various bits that we will want to toggle. */
2086 #define INST_IMMEDIATE 0x02000000
2087 #define OFFSET_REG 0x02000000
2088 #define HWOFFSET_IMM 0x00400000
2089 #define SHIFT_BY_REG 0x00000010
2090 #define PRE_INDEX 0x01000000
2091 #define INDEX_UP 0x00800000
2092 #define WRITE_BACK 0x00200000
2093 #define LDM_TYPE_2_OR_3 0x00400000
2095 #define LITERAL_MASK 0xf000f000
2096 #define OPCODE_MASK 0xfe1fffff
2097 #define V4_STR_BIT 0x00000020
2099 #define DATA_OP_SHIFT 21
2101 /* Codes to distinguish the arithmetic instructions. */
2102 #define OPCODE_AND 0
2103 #define OPCODE_EOR 1
2104 #define OPCODE_SUB 2
2105 #define OPCODE_RSB 3
2106 #define OPCODE_ADD 4
2107 #define OPCODE_ADC 5
2108 #define OPCODE_SBC 6
2109 #define OPCODE_RSC 7
2110 #define OPCODE_TST 8
2111 #define OPCODE_TEQ 9
2112 #define OPCODE_CMP 10
2113 #define OPCODE_CMN 11
2114 #define OPCODE_ORR 12
2115 #define OPCODE_MOV 13
2116 #define OPCODE_BIC 14
2117 #define OPCODE_MVN 15
2119 /* Thumb v1 (ARMv4T). */
2120 static void do_t_nop
PARAMS ((char *));
2121 static void do_t_arit
PARAMS ((char *));
2122 static void do_t_add
PARAMS ((char *));
2123 static void do_t_asr
PARAMS ((char *));
2124 static void do_t_branch9
PARAMS ((char *));
2125 static void do_t_branch12
PARAMS ((char *));
2126 static void do_t_branch23
PARAMS ((char *));
2127 static void do_t_bx
PARAMS ((char *));
2128 static void do_t_compare
PARAMS ((char *));
2129 static void do_t_ldmstm
PARAMS ((char *));
2130 static void do_t_ldr
PARAMS ((char *));
2131 static void do_t_ldrb
PARAMS ((char *));
2132 static void do_t_ldrh
PARAMS ((char *));
2133 static void do_t_lds
PARAMS ((char *));
2134 static void do_t_lsl
PARAMS ((char *));
2135 static void do_t_lsr
PARAMS ((char *));
2136 static void do_t_mov
PARAMS ((char *));
2137 static void do_t_push_pop
PARAMS ((char *));
2138 static void do_t_str
PARAMS ((char *));
2139 static void do_t_strb
PARAMS ((char *));
2140 static void do_t_strh
PARAMS ((char *));
2141 static void do_t_sub
PARAMS ((char *));
2142 static void do_t_swi
PARAMS ((char *));
2143 static void do_t_adr
PARAMS ((char *));
2145 /* Thumb v2 (ARMv5T). */
2146 static void do_t_blx
PARAMS ((char *));
2147 static void do_t_bkpt
PARAMS ((char *));
2149 #define T_OPCODE_MUL 0x4340
2150 #define T_OPCODE_TST 0x4200
2151 #define T_OPCODE_CMN 0x42c0
2152 #define T_OPCODE_NEG 0x4240
2153 #define T_OPCODE_MVN 0x43c0
2155 #define T_OPCODE_ADD_R3 0x1800
2156 #define T_OPCODE_SUB_R3 0x1a00
2157 #define T_OPCODE_ADD_HI 0x4400
2158 #define T_OPCODE_ADD_ST 0xb000
2159 #define T_OPCODE_SUB_ST 0xb080
2160 #define T_OPCODE_ADD_SP 0xa800
2161 #define T_OPCODE_ADD_PC 0xa000
2162 #define T_OPCODE_ADD_I8 0x3000
2163 #define T_OPCODE_SUB_I8 0x3800
2164 #define T_OPCODE_ADD_I3 0x1c00
2165 #define T_OPCODE_SUB_I3 0x1e00
2167 #define T_OPCODE_ASR_R 0x4100
2168 #define T_OPCODE_LSL_R 0x4080
2169 #define T_OPCODE_LSR_R 0x40c0
2170 #define T_OPCODE_ASR_I 0x1000
2171 #define T_OPCODE_LSL_I 0x0000
2172 #define T_OPCODE_LSR_I 0x0800
2174 #define T_OPCODE_MOV_I8 0x2000
2175 #define T_OPCODE_CMP_I8 0x2800
2176 #define T_OPCODE_CMP_LR 0x4280
2177 #define T_OPCODE_MOV_HR 0x4600
2178 #define T_OPCODE_CMP_HR 0x4500
2180 #define T_OPCODE_LDR_PC 0x4800
2181 #define T_OPCODE_LDR_SP 0x9800
2182 #define T_OPCODE_STR_SP 0x9000
2183 #define T_OPCODE_LDR_IW 0x6800
2184 #define T_OPCODE_STR_IW 0x6000
2185 #define T_OPCODE_LDR_IH 0x8800
2186 #define T_OPCODE_STR_IH 0x8000
2187 #define T_OPCODE_LDR_IB 0x7800
2188 #define T_OPCODE_STR_IB 0x7000
2189 #define T_OPCODE_LDR_RW 0x5800
2190 #define T_OPCODE_STR_RW 0x5000
2191 #define T_OPCODE_LDR_RH 0x5a00
2192 #define T_OPCODE_STR_RH 0x5200
2193 #define T_OPCODE_LDR_RB 0x5c00
2194 #define T_OPCODE_STR_RB 0x5400
2196 #define T_OPCODE_PUSH 0xb400
2197 #define T_OPCODE_POP 0xbc00
2199 #define T_OPCODE_BRANCH 0xe7fe
2201 static int thumb_reg
PARAMS ((char ** str
, int hi_lo
));
2203 #define THUMB_SIZE 2 /* Size of thumb instruction. */
2204 #define THUMB_REG_LO 0x1
2205 #define THUMB_REG_HI 0x2
2206 #define THUMB_REG_ANY 0x3
2208 #define THUMB_H1 0x0080
2209 #define THUMB_H2 0x0040
2215 #define THUMB_MOVE 0
2216 #define THUMB_COMPARE 1
2218 #define THUMB_LOAD 0
2219 #define THUMB_STORE 1
2221 #define THUMB_PP_PC_LR 0x0100
2223 /* These three are used for immediate shifts, do not alter. */
2224 #define THUMB_WORD 2
2225 #define THUMB_HALFWORD 1
2226 #define THUMB_BYTE 0
2230 /* Basic string to match. */
2231 const char * template;
2233 /* Basic instruction code. */
2234 unsigned long value
;
2238 /* Which CPU variants this exists for. */
2239 unsigned long variant
;
2241 /* Function to call to parse args. */
2242 void (* parms
) PARAMS ((char *));
2245 static const struct thumb_opcode tinsns
[] =
2247 /* Thumb v1 (ARMv4T). */
2248 {"adc", 0x4140, 2, ARM_EXT_V4T
, do_t_arit
},
2249 {"add", 0x0000, 2, ARM_EXT_V4T
, do_t_add
},
2250 {"and", 0x4000, 2, ARM_EXT_V4T
, do_t_arit
},
2251 {"asr", 0x0000, 2, ARM_EXT_V4T
, do_t_asr
},
2252 {"b", T_OPCODE_BRANCH
, 2, ARM_EXT_V4T
, do_t_branch12
},
2253 {"beq", 0xd0fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2254 {"bne", 0xd1fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2255 {"bcs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2256 {"bhs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2257 {"bcc", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2258 {"bul", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2259 {"blo", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2260 {"bmi", 0xd4fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2261 {"bpl", 0xd5fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2262 {"bvs", 0xd6fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2263 {"bvc", 0xd7fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2264 {"bhi", 0xd8fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2265 {"bls", 0xd9fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2266 {"bge", 0xdafe, 2, ARM_EXT_V4T
, do_t_branch9
},
2267 {"blt", 0xdbfe, 2, ARM_EXT_V4T
, do_t_branch9
},
2268 {"bgt", 0xdcfe, 2, ARM_EXT_V4T
, do_t_branch9
},
2269 {"ble", 0xddfe, 2, ARM_EXT_V4T
, do_t_branch9
},
2270 {"bal", 0xdefe, 2, ARM_EXT_V4T
, do_t_branch9
},
2271 {"bic", 0x4380, 2, ARM_EXT_V4T
, do_t_arit
},
2272 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T
, do_t_branch23
},
2273 {"bx", 0x4700, 2, ARM_EXT_V4T
, do_t_bx
},
2274 {"cmn", T_OPCODE_CMN
, 2, ARM_EXT_V4T
, do_t_arit
},
2275 {"cmp", 0x0000, 2, ARM_EXT_V4T
, do_t_compare
},
2276 {"eor", 0x4040, 2, ARM_EXT_V4T
, do_t_arit
},
2277 {"ldmia", 0xc800, 2, ARM_EXT_V4T
, do_t_ldmstm
},
2278 {"ldr", 0x0000, 2, ARM_EXT_V4T
, do_t_ldr
},
2279 {"ldrb", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrb
},
2280 {"ldrh", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrh
},
2281 {"ldrsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
2282 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
2283 {"ldsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
2284 {"ldsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
2285 {"lsl", 0x0000, 2, ARM_EXT_V4T
, do_t_lsl
},
2286 {"lsr", 0x0000, 2, ARM_EXT_V4T
, do_t_lsr
},
2287 {"mov", 0x0000, 2, ARM_EXT_V4T
, do_t_mov
},
2288 {"mul", T_OPCODE_MUL
, 2, ARM_EXT_V4T
, do_t_arit
},
2289 {"mvn", T_OPCODE_MVN
, 2, ARM_EXT_V4T
, do_t_arit
},
2290 {"neg", T_OPCODE_NEG
, 2, ARM_EXT_V4T
, do_t_arit
},
2291 {"orr", 0x4300, 2, ARM_EXT_V4T
, do_t_arit
},
2292 {"pop", 0xbc00, 2, ARM_EXT_V4T
, do_t_push_pop
},
2293 {"push", 0xb400, 2, ARM_EXT_V4T
, do_t_push_pop
},
2294 {"ror", 0x41c0, 2, ARM_EXT_V4T
, do_t_arit
},
2295 {"sbc", 0x4180, 2, ARM_EXT_V4T
, do_t_arit
},
2296 {"stmia", 0xc000, 2, ARM_EXT_V4T
, do_t_ldmstm
},
2297 {"str", 0x0000, 2, ARM_EXT_V4T
, do_t_str
},
2298 {"strb", 0x0000, 2, ARM_EXT_V4T
, do_t_strb
},
2299 {"strh", 0x0000, 2, ARM_EXT_V4T
, do_t_strh
},
2300 {"swi", 0xdf00, 2, ARM_EXT_V4T
, do_t_swi
},
2301 {"sub", 0x0000, 2, ARM_EXT_V4T
, do_t_sub
},
2302 {"tst", T_OPCODE_TST
, 2, ARM_EXT_V4T
, do_t_arit
},
2304 {"adr", 0x0000, 2, ARM_EXT_V4T
, do_t_adr
},
2305 {"nop", 0x46C0, 2, ARM_EXT_V4T
, do_t_nop
}, /* mov r8,r8 */
2306 /* Thumb v2 (ARMv5T). */
2307 {"blx", 0, 0, ARM_EXT_V5T
, do_t_blx
},
2308 {"bkpt", 0xbe00, 2, ARM_EXT_V5T
, do_t_bkpt
},
2311 #define BAD_ARGS _("bad arguments to instruction")
2312 #define BAD_PC _("r15 not allowed here")
2313 #define BAD_COND _("instruction is not conditional")
2314 #define ERR_NO_ACCUM _("acc0 expected")
2316 static struct hash_control
* arm_ops_hsh
= NULL
;
2317 static struct hash_control
* arm_tops_hsh
= NULL
;
2318 static struct hash_control
* arm_cond_hsh
= NULL
;
2319 static struct hash_control
* arm_shift_hsh
= NULL
;
2320 static struct hash_control
* arm_psr_hsh
= NULL
;
2322 /* This table describes all the machine specific pseudo-ops the assembler
2323 has to support. The fields are:
2324 pseudo-op name without dot
2325 function to call to execute this pseudo-op
2326 Integer arg to pass to the function. */
2328 static void s_req
PARAMS ((int));
2329 static void s_unreq
PARAMS ((int));
2330 static void s_align
PARAMS ((int));
2331 static void s_bss
PARAMS ((int));
2332 static void s_even
PARAMS ((int));
2333 static void s_ltorg
PARAMS ((int));
2334 static void s_arm
PARAMS ((int));
2335 static void s_thumb
PARAMS ((int));
2336 static void s_code
PARAMS ((int));
2337 static void s_force_thumb
PARAMS ((int));
2338 static void s_thumb_func
PARAMS ((int));
2339 static void s_thumb_set
PARAMS ((int));
2341 static void s_arm_elf_cons
PARAMS ((int));
2344 static int my_get_expression
PARAMS ((expressionS
*, char **));
2346 const pseudo_typeS md_pseudo_table
[] =
2348 /* Never called because '.req' does not start a line. */
2349 { "req", s_req
, 0 },
2350 { "unreq", s_unreq
, 0 },
2351 { "bss", s_bss
, 0 },
2352 { "align", s_align
, 0 },
2353 { "arm", s_arm
, 0 },
2354 { "thumb", s_thumb
, 0 },
2355 { "code", s_code
, 0 },
2356 { "force_thumb", s_force_thumb
, 0 },
2357 { "thumb_func", s_thumb_func
, 0 },
2358 { "thumb_set", s_thumb_set
, 0 },
2359 { "even", s_even
, 0 },
2360 { "ltorg", s_ltorg
, 0 },
2361 { "pool", s_ltorg
, 0 },
2363 { "word", s_arm_elf_cons
, 4 },
2364 { "long", s_arm_elf_cons
, 4 },
2368 { "extend", float_cons
, 'x' },
2369 { "ldouble", float_cons
, 'x' },
2370 { "packed", float_cons
, 'p' },
2374 /* Other internal functions. */
2375 static int arm_parse_extension
PARAMS ((char *, int *));
2376 static int arm_parse_cpu
PARAMS ((char *));
2377 static int arm_parse_arch
PARAMS ((char *));
2378 static int arm_parse_fpu
PARAMS ((char *));
2379 #if 0 /* Suppressed - for now. */
2380 #if defined OBJ_COFF || defined OBJ_ELF
2381 static void arm_add_note
PARAMS ((const char *, const char *, unsigned int));
2385 /* Stuff needed to resolve the label ambiguity
2395 symbolS
* last_label_seen
;
2396 static int label_is_thumb_function_name
= FALSE
;
2398 /* Literal Pool stuff. */
2400 #define MAX_LITERAL_POOL_SIZE 1024
2402 /* Literal pool structure. Held on a per-section
2403 and per-sub-section basis. */
2404 typedef struct literal_pool
2406 expressionS literals
[MAX_LITERAL_POOL_SIZE
];
2407 unsigned int next_free_entry
;
2411 subsegT sub_section
;
2412 struct literal_pool
* next
;
2415 /* Pointer to a linked list of literal pools. */
2416 literal_pool
* list_of_pools
= NULL
;
2418 static literal_pool
* find_literal_pool
PARAMS ((void));
2419 static literal_pool
* find_or_make_literal_pool
PARAMS ((void));
2421 static literal_pool
*
2422 find_literal_pool ()
2424 literal_pool
* pool
;
2426 for (pool
= list_of_pools
; pool
!= NULL
; pool
= pool
->next
)
2428 if (pool
->section
== now_seg
2429 && pool
->sub_section
== now_subseg
)
2436 static literal_pool
*
2437 find_or_make_literal_pool ()
2439 /* Next literal pool ID number. */
2440 static unsigned int latest_pool_num
= 1;
2441 literal_pool
* pool
;
2443 pool
= find_literal_pool ();
2447 /* Create a new pool. */
2448 pool
= (literal_pool
*) xmalloc (sizeof (* pool
));
2452 pool
->next_free_entry
= 0;
2453 pool
->section
= now_seg
;
2454 pool
->sub_section
= now_subseg
;
2455 pool
->next
= list_of_pools
;
2456 pool
->symbol
= NULL
;
2458 /* Add it to the list. */
2459 list_of_pools
= pool
;
2462 /* New pools, and emptied pools, will have a NULL symbol. */
2463 if (pool
->symbol
== NULL
)
2465 pool
->symbol
= symbol_create (FAKE_LABEL_NAME
, undefined_section
,
2466 (valueT
) 0, &zero_address_frag
);
2467 pool
->id
= latest_pool_num
++;
2474 /* Add the literal in the global 'inst'
2475 structure to the relevent literal pool. */
2479 literal_pool
* pool
;
2482 pool
= find_or_make_literal_pool ();
2484 /* Check if this literal value is already in the pool. */
2485 for (entry
= 0; entry
< pool
->next_free_entry
; entry
++)
2487 if ((pool
->literals
[entry
].X_op
== inst
.reloc
.exp
.X_op
)
2488 && (inst
.reloc
.exp
.X_op
== O_constant
)
2489 && (pool
->literals
[entry
].X_add_number
2490 == inst
.reloc
.exp
.X_add_number
)
2491 && (pool
->literals
[entry
].X_unsigned
2492 == inst
.reloc
.exp
.X_unsigned
))
2495 if ((pool
->literals
[entry
].X_op
== inst
.reloc
.exp
.X_op
)
2496 && (inst
.reloc
.exp
.X_op
== O_symbol
)
2497 && (pool
->literals
[entry
].X_add_number
2498 == inst
.reloc
.exp
.X_add_number
)
2499 && (pool
->literals
[entry
].X_add_symbol
2500 == inst
.reloc
.exp
.X_add_symbol
)
2501 && (pool
->literals
[entry
].X_op_symbol
2502 == inst
.reloc
.exp
.X_op_symbol
))
2506 /* Do we need to create a new entry? */
2507 if (entry
== pool
->next_free_entry
)
2509 if (entry
>= MAX_LITERAL_POOL_SIZE
)
2511 inst
.error
= _("literal pool overflow");
2515 pool
->literals
[entry
] = inst
.reloc
.exp
;
2516 pool
->next_free_entry
+= 1;
2519 inst
.reloc
.exp
.X_op
= O_symbol
;
2520 inst
.reloc
.exp
.X_add_number
= ((int) entry
) * 4 - 8;
2521 inst
.reloc
.exp
.X_add_symbol
= pool
->symbol
;
2526 /* Can't use symbol_new here, so have to create a symbol and then at
2527 a later date assign it a value. Thats what these functions do. */
2530 symbol_locate (symbolP
, name
, segment
, valu
, frag
)
2532 const char * name
; /* It is copied, the caller can modify. */
2533 segT segment
; /* Segment identifier (SEG_<something>). */
2534 valueT valu
; /* Symbol value. */
2535 fragS
* frag
; /* Associated fragment. */
2537 unsigned int name_length
;
2538 char * preserved_copy_of_name
;
2540 name_length
= strlen (name
) + 1; /* +1 for \0. */
2541 obstack_grow (¬es
, name
, name_length
);
2542 preserved_copy_of_name
= obstack_finish (¬es
);
2543 #ifdef STRIP_UNDERSCORE
2544 if (preserved_copy_of_name
[0] == '_')
2545 preserved_copy_of_name
++;
2548 #ifdef tc_canonicalize_symbol_name
2549 preserved_copy_of_name
=
2550 tc_canonicalize_symbol_name (preserved_copy_of_name
);
2553 S_SET_NAME (symbolP
, preserved_copy_of_name
);
2555 S_SET_SEGMENT (symbolP
, segment
);
2556 S_SET_VALUE (symbolP
, valu
);
2557 symbol_clear_list_pointers (symbolP
);
2559 symbol_set_frag (symbolP
, frag
);
2561 /* Link to end of symbol chain. */
2563 extern int symbol_table_frozen
;
2564 if (symbol_table_frozen
)
2568 symbol_append (symbolP
, symbol_lastP
, & symbol_rootP
, & symbol_lastP
);
2570 obj_symbol_new_hook (symbolP
);
2572 #ifdef tc_symbol_new_hook
2573 tc_symbol_new_hook (symbolP
);
2577 verify_symbol_chain (symbol_rootP
, symbol_lastP
);
2578 #endif /* DEBUG_SYMS */
2581 /* Check that an immediate is valid.
2582 If so, convert it to the right format. */
2585 validate_immediate (val
)
2591 #define rotate_left(v, n) (v << n | v >> (32 - n))
2593 for (i
= 0; i
< 32; i
+= 2)
2594 if ((a
= rotate_left (val
, i
)) <= 0xff)
2595 return a
| (i
<< 7); /* 12-bit pack: [shift-cnt,const]. */
2600 /* Check to see if an immediate can be computed as two separate immediate
2601 values, added together. We already know that this value cannot be
2602 computed by just one ARM instruction. */
2605 validate_immediate_twopart (val
, highpart
)
2607 unsigned int * highpart
;
2612 for (i
= 0; i
< 32; i
+= 2)
2613 if (((a
= rotate_left (val
, i
)) & 0xff) != 0)
2619 * highpart
= (a
>> 8) | ((i
+ 24) << 7);
2621 else if (a
& 0xff0000)
2625 * highpart
= (a
>> 16) | ((i
+ 16) << 7);
2629 assert (a
& 0xff000000);
2630 * highpart
= (a
>> 24) | ((i
+ 8) << 7);
2633 return (a
& 0xff) | (i
<< 7);
2640 validate_offset_imm (val
, hwse
)
2644 if ((hwse
&& val
> 255) || val
> 4095)
2658 /* This code is to handle mapping symbols as defined in the ARM ELF spec.
2659 (This text is taken from version B-02 of the spec):
2661 4.4.7 Mapping and tagging symbols
2663 A section of an ARM ELF file can contain a mixture of ARM code,
2664 Thumb code, and data. There are inline transitions between code
2665 and data at literal pool boundaries. There can also be inline
2666 transitions between ARM code and Thumb code, for example in
2667 ARM-Thumb inter-working veneers. Linkers, machine-level
2668 debuggers, profiling tools, and disassembly tools need to map
2669 images accurately. For example, setting an ARM breakpoint on a
2670 Thumb location, or in a literal pool, can crash the program
2671 being debugged, ruining the debugging session.
2673 ARM ELF entities are mapped (see section 4.4.7.1 below) and
2674 tagged (see section 4.4.7.2 below) using local symbols (with
2675 binding STB_LOCAL). To assist consumers, mapping and tagging
2676 symbols should be collated first in the symbol table, before
2677 other symbols with binding STB_LOCAL.
2679 To allow properly collated mapping and tagging symbols to be
2680 skipped by consumers that have no interest in them, the first
2681 such symbol should have the name $m and its st_value field equal
2682 to the total number of mapping and tagging symbols (including
2683 the $m) in the symbol table.
2685 4.4.7.1 Mapping symbols
2687 $a Labels the first byte of a sequence of ARM instructions.
2688 Its type is STT_FUNC.
2690 $d Labels the first byte of a sequence of data items.
2691 Its type is STT_OBJECT.
2693 $t Labels the first byte of a sequence of Thumb instructions.
2694 Its type is STT_FUNC.
2696 This list of mapping symbols may be extended in the future.
2698 Section-relative mapping symbols
2700 Mapping symbols defined in a section define a sequence of
2701 half-open address intervals that cover the address range of the
2702 section. Each interval starts at the address defined by a
2703 mapping symbol, and continues up to, but not including, the
2704 address defined by the next (in address order) mapping symbol or
2705 the end of the section. A corollary is that there must be a
2706 mapping symbol defined at the beginning of each section.
2707 Consumers can ignore the size of a section-relative mapping
2708 symbol. Producers can set it to 0.
2710 Absolute mapping symbols
2712 Because of the need to crystallize a Thumb address with the
2713 Thumb-bit set, absolute symbol of type STT_FUNC (symbols of type
2714 STT_FUNC defined in section SHN_ABS) need to be mapped with $a
2717 The extent of a mapping symbol defined in SHN_ABS is [st_value,
2718 st_value + st_size), or [st_value, st_value + 1) if st_size = 0,
2719 where [x, y) denotes the half-open address range from x,
2720 inclusive, to y, exclusive.
2722 In the absence of a mapping symbol, a consumer can interpret a
2723 function symbol with an odd value as the Thumb code address
2724 obtained by clearing the least significant bit of the
2725 value. This interpretation is deprecated, and it may not work in
2728 Note - the Tagging symbols ($b, $f, $p $m) have been dropped from
2729 the EABI (which is still under development), so they are not
2730 implemented here. */
2733 mapping_state (enum mstate state
)
2735 static enum mstate mapstate
= MAP_DATA
;
2737 const char * symname
;
2740 if (mapstate
== state
)
2741 /* The mapping symbol has already been emitted.
2742 There is nothing else to do. */
2755 type
= BSF_FUNCTION
;
2759 type
= BSF_FUNCTION
;
2765 symbolP
= symbol_new (symname
, now_seg
, (valueT
) frag_now_fix (), frag_now
);
2766 symbol_table_insert (symbolP
);
2767 symbol_get_bfdsym (symbolP
)->flags
|= type
| BSF_LOCAL
;
2772 THUMB_SET_FUNC (symbolP
, 0);
2773 ARM_SET_THUMB (symbolP
, 0);
2774 ARM_SET_INTERWORK (symbolP
, support_interwork
);
2778 THUMB_SET_FUNC (symbolP
, 1);
2779 ARM_SET_THUMB (symbolP
, 1);
2780 ARM_SET_INTERWORK (symbolP
, support_interwork
);
2789 /* When we change sections we need to issue a new mapping symbol. */
2792 arm_elf_change_section (void)
2796 if (!SEG_NORMAL (now_seg
))
2799 flags
= bfd_get_section_flags (stdoutput
, now_seg
);
2801 /* We can ignore sections that only contain debug info. */
2802 if ((flags
& SEC_ALLOC
) == 0)
2805 if (flags
& SEC_CODE
)
2808 mapping_state (MAP_THUMB
);
2810 mapping_state (MAP_ARM
);
2813 /* This section does not contain code. Therefore it must contain data. */
2814 mapping_state (MAP_DATA
);
2817 #define mapping_state(a)
2818 #endif /* OBJ_ELF */
2823 int a ATTRIBUTE_UNUSED
;
2825 as_bad (_("invalid syntax for .req directive"));
2828 /* The .unreq directive deletes an alias which was previously defined
2829 by .req. For example:
2835 s_unreq (int a ATTRIBUTE_UNUSED
)
2840 skip_whitespace (input_line_pointer
);
2841 name
= input_line_pointer
;
2843 while (*input_line_pointer
!= 0
2844 && *input_line_pointer
!= ' '
2845 && *input_line_pointer
!= '\n')
2846 ++input_line_pointer
;
2848 saved_char
= *input_line_pointer
;
2849 *input_line_pointer
= 0;
2853 enum arm_reg_type req_type
= arm_reg_parse_any (name
);
2855 if (req_type
!= REG_TYPE_MAX
)
2857 char *temp_name
= name
;
2858 int req_no
= arm_reg_parse (&temp_name
, all_reg_maps
[req_type
].htab
);
2862 struct reg_entry
*req_entry
;
2864 /* Check to see if this alias is a builtin one. */
2865 req_entry
= hash_delete (all_reg_maps
[req_type
].htab
, name
);
2868 as_bad (_("unreq: missing hash entry for \"%s\""), name
);
2869 else if (req_entry
->builtin
)
2870 /* FIXME: We are deleteing a built in register alias which
2871 points to a const data structure, so we only need to
2872 free up the memory used by the key in the hash table.
2873 Unfortunately we have not recorded this value, so this
2874 is a memory leak. */
2875 /* FIXME: Should we issue a warning message ? */
2879 /* Deleteing a user defined alias. We need to free the
2880 key and the value, but fortunately the key is the same
2881 as the value->name field. */
2882 free ((char *) req_entry
->name
);
2887 as_bad (_(".unreq: unrecognized symbol \"%s\""), name
);
2890 as_bad (_(".unreq: unrecognized symbol \"%s\""), name
);
2893 as_bad (_("invalid syntax for .unreq directive"));
2895 *input_line_pointer
= saved_char
;
2896 demand_empty_rest_of_line ();
2901 int ignore ATTRIBUTE_UNUSED
;
2903 /* We don't support putting frags in the BSS segment, we fake it by
2904 marking in_bss, then looking at s_skip for clues. */
2905 subseg_set (bss_section
, 0);
2906 demand_empty_rest_of_line ();
2907 mapping_state (MAP_DATA
);
2912 int ignore ATTRIBUTE_UNUSED
;
2914 /* Never make frag if expect extra pass. */
2916 frag_align (1, 0, 0);
2918 record_alignment (now_seg
, 1);
2920 demand_empty_rest_of_line ();
2925 int ignored ATTRIBUTE_UNUSED
;
2928 literal_pool
* pool
;
2931 pool
= find_literal_pool ();
2933 || pool
->symbol
== NULL
2934 || pool
->next_free_entry
== 0)
2937 /* Align pool as you have word accesses.
2938 Only make a frag if we have to. */
2940 frag_align (2, 0, 0);
2942 record_alignment (now_seg
, 2);
2944 sprintf (sym_name
, "$$lit_\002%x", pool
->id
);
2946 symbol_locate (pool
->symbol
, sym_name
, now_seg
,
2947 (valueT
) frag_now_fix (), frag_now
);
2948 symbol_table_insert (pool
->symbol
);
2950 ARM_SET_THUMB (pool
->symbol
, thumb_mode
);
2952 #if defined OBJ_COFF || defined OBJ_ELF
2953 ARM_SET_INTERWORK (pool
->symbol
, support_interwork
);
2956 for (entry
= 0; entry
< pool
->next_free_entry
; entry
++)
2957 /* First output the expression in the instruction to the pool. */
2958 emit_expr (&(pool
->literals
[entry
]), 4); /* .word */
2960 /* Mark the pool as empty. */
2961 pool
->next_free_entry
= 0;
2962 pool
->symbol
= NULL
;
2965 /* Same as s_align_ptwo but align 0 => align 2. */
2969 int unused ATTRIBUTE_UNUSED
;
2972 register long temp_fill
;
2973 long max_alignment
= 15;
2975 temp
= get_absolute_expression ();
2976 if (temp
> max_alignment
)
2977 as_bad (_("alignment too large: %d assumed"), temp
= max_alignment
);
2980 as_bad (_("alignment negative. 0 assumed."));
2984 if (*input_line_pointer
== ',')
2986 input_line_pointer
++;
2987 temp_fill
= get_absolute_expression ();
2995 /* Only make a frag if we HAVE to. */
2996 if (temp
&& !need_pass_2
)
2997 frag_align (temp
, (int) temp_fill
, 0);
2998 demand_empty_rest_of_line ();
3000 record_alignment (now_seg
, temp
);
3004 s_force_thumb (ignore
)
3005 int ignore ATTRIBUTE_UNUSED
;
3007 /* If we are not already in thumb mode go into it, EVEN if
3008 the target processor does not support thumb instructions.
3009 This is used by gcc/config/arm/lib1funcs.asm for example
3010 to compile interworking support functions even if the
3011 target processor should not support interworking. */
3016 record_alignment (now_seg
, 1);
3019 demand_empty_rest_of_line ();
3023 s_thumb_func (ignore
)
3024 int ignore ATTRIBUTE_UNUSED
;
3029 /* The following label is the name/address of the start of a Thumb function.
3030 We need to know this for the interworking support. */
3031 label_is_thumb_function_name
= TRUE
;
3033 demand_empty_rest_of_line ();
3036 /* Perform a .set directive, but also mark the alias as
3037 being a thumb function. */
3043 /* XXX the following is a duplicate of the code for s_set() in read.c
3044 We cannot just call that code as we need to get at the symbol that
3046 register char * name
;
3047 register char delim
;
3048 register char * end_name
;
3049 register symbolS
* symbolP
;
3051 /* Especial apologies for the random logic:
3052 This just grew, and could be parsed much more simply!
3054 name
= input_line_pointer
;
3055 delim
= get_symbol_end ();
3056 end_name
= input_line_pointer
;
3061 if (*input_line_pointer
!= ',')
3064 as_bad (_("expected comma after name \"%s\""), name
);
3066 ignore_rest_of_line ();
3070 input_line_pointer
++;
3073 if (name
[0] == '.' && name
[1] == '\0')
3075 /* XXX - this should not happen to .thumb_set. */
3079 if ((symbolP
= symbol_find (name
)) == NULL
3080 && (symbolP
= md_undefined_symbol (name
)) == NULL
)
3083 /* When doing symbol listings, play games with dummy fragments living
3084 outside the normal fragment chain to record the file and line info
3086 if (listing
& LISTING_SYMBOLS
)
3088 extern struct list_info_struct
* listing_tail
;
3089 fragS
* dummy_frag
= (fragS
*) xmalloc (sizeof (fragS
));
3091 memset (dummy_frag
, 0, sizeof (fragS
));
3092 dummy_frag
->fr_type
= rs_fill
;
3093 dummy_frag
->line
= listing_tail
;
3094 symbolP
= symbol_new (name
, undefined_section
, 0, dummy_frag
);
3095 dummy_frag
->fr_symbol
= symbolP
;
3099 symbolP
= symbol_new (name
, undefined_section
, 0, &zero_address_frag
);
3102 /* "set" symbols are local unless otherwise specified. */
3103 SF_SET_LOCAL (symbolP
);
3104 #endif /* OBJ_COFF */
3105 } /* Make a new symbol. */
3107 symbol_table_insert (symbolP
);
3112 && S_IS_DEFINED (symbolP
)
3113 && S_GET_SEGMENT (symbolP
) != reg_section
)
3114 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP
));
3116 pseudo_set (symbolP
);
3118 demand_empty_rest_of_line ();
3120 /* XXX Now we come to the Thumb specific bit of code. */
3122 THUMB_SET_FUNC (symbolP
, 1);
3123 ARM_SET_THUMB (symbolP
, 1);
3124 #if defined OBJ_ELF || defined OBJ_COFF
3125 ARM_SET_INTERWORK (symbolP
, support_interwork
);
3130 opcode_select (width
)
3138 if (! (cpu_variant
& ARM_EXT_V4T
))
3139 as_bad (_("selected processor does not support THUMB opcodes"));
3142 /* No need to force the alignment, since we will have been
3143 coming from ARM mode, which is word-aligned. */
3144 record_alignment (now_seg
, 1);
3146 mapping_state (MAP_THUMB
);
3152 if ((cpu_variant
& ARM_ALL
) == ARM_EXT_V4T
)
3153 as_bad (_("selected processor does not support ARM opcodes"));
3158 frag_align (2, 0, 0);
3160 record_alignment (now_seg
, 1);
3162 mapping_state (MAP_ARM
);
3166 as_bad (_("invalid instruction size selected (%d)"), width
);
3172 int ignore ATTRIBUTE_UNUSED
;
3175 demand_empty_rest_of_line ();
3180 int ignore ATTRIBUTE_UNUSED
;
3183 demand_empty_rest_of_line ();
3188 int unused ATTRIBUTE_UNUSED
;
3192 temp
= get_absolute_expression ();
3197 opcode_select (temp
);
3201 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp
);
3209 skip_whitespace (str
);
3211 if (*str
!= '\0' && !inst
.error
)
3212 inst
.error
= _("garbage following instruction");
3216 skip_past_comma (str
)
3219 char * p
= * str
, c
;
3222 while ((c
= *p
) == ' ' || c
== ',')
3225 if (c
== ',' && comma
++)
3233 return comma
? SUCCESS
: FAIL
;
3236 /* A standard register must be given at this point.
3237 SHIFT is the place to put it in inst.instruction.
3238 Restores input start point on error.
3239 Returns the reg#, or FAIL. */
3242 reg_required_here (str
, shift
)
3246 static char buff
[128]; /* XXX */
3248 char * start
= * str
;
3250 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_RN
].htab
)) != FAIL
)
3253 inst
.instruction
|= reg
<< shift
;
3257 /* Restore the start point, we may have got a reg of the wrong class. */
3260 /* In the few cases where we might be able to accept something else
3261 this error can be overridden. */
3262 sprintf (buff
, _("register expected, not '%.100s'"), start
);
3268 /* A Intel Wireless MMX technology register
3269 must be given at this point.
3270 Shift is the place to put it in inst.instruction.
3271 Restores input start point on err.
3272 Returns the reg#, or FAIL. */
3275 wreg_required_here (str
, shift
, reg_type
)
3278 enum wreg_type reg_type
;
3280 static char buff
[128];
3282 char * start
= *str
;
3284 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_IWMMXT
].htab
)) != FAIL
)
3286 if (wr_register (reg
)
3287 && (reg_type
== IWMMXT_REG_WR
|| reg_type
== IWMMXT_REG_WR_OR_WC
))
3290 inst
.instruction
|= (reg
^ WR_PREFIX
) << shift
;
3293 else if (wc_register (reg
)
3294 && (reg_type
== IWMMXT_REG_WC
|| reg_type
== IWMMXT_REG_WR_OR_WC
))
3297 inst
.instruction
|= (reg
^ WC_PREFIX
) << shift
;
3300 else if ((wcg_register (reg
) && reg_type
== IWMMXT_REG_WCG
))
3303 inst
.instruction
|= ((reg
^ WC_PREFIX
) - 8) << shift
;
3308 /* Restore the start point, we may have got a reg of the wrong class. */
3311 /* In the few cases where we might be able to accept
3312 something else this error can be overridden. */
3313 sprintf (buff
, _("Intel Wireless MMX technology register expected, not '%.100s'"), start
);
3319 static const struct asm_psr
*
3321 register char ** ccp
;
3323 char * start
= * ccp
;
3326 const struct asm_psr
* psr
;
3330 /* Skip to the end of the next word in the input stream. */
3335 while (ISALPHA (c
) || c
== '_');
3337 /* Terminate the word. */
3340 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
3341 feature for ease of use and backwards compatibility. */
3342 if (!strncmp (start
, "cpsr", 4))
3343 strncpy (start
, "CPSR", 4);
3344 else if (!strncmp (start
, "spsr", 4))
3345 strncpy (start
, "SPSR", 4);
3347 /* Now locate the word in the psr hash table. */
3348 psr
= (const struct asm_psr
*) hash_find (arm_psr_hsh
, start
);
3350 /* Restore the input stream. */
3353 /* If we found a valid match, advance the
3354 stream pointer past the end of the word. */
3360 /* Parse the input looking for a PSR flag. */
3363 psr_required_here (str
)
3366 char * start
= * str
;
3367 const struct asm_psr
* psr
;
3369 psr
= arm_psr_parse (str
);
3373 /* If this is the SPSR that is being modified, set the R bit. */
3375 inst
.instruction
|= SPSR_BIT
;
3377 /* Set the psr flags in the MSR instruction. */
3378 inst
.instruction
|= psr
->field
<< PSR_SHIFT
;
3383 /* In the few cases where we might be able to accept
3384 something else this error can be overridden. */
3385 inst
.error
= _("flag for {c}psr instruction expected");
3387 /* Restore the start point. */
3393 co_proc_number (str
)
3396 int processor
, pchar
;
3399 skip_whitespace (*str
);
3402 /* The data sheet seems to imply that just a number on its own is valid
3403 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
3405 if ((processor
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CP
].htab
))
3411 if (pchar
>= '0' && pchar
<= '9')
3413 processor
= pchar
- '0';
3414 if (**str
>= '0' && **str
<= '9')
3416 processor
= processor
* 10 + *(*str
)++ - '0';
3419 inst
.error
= _("illegal co-processor number");
3426 inst
.error
= _("bad or missing co-processor number");
3431 inst
.instruction
|= processor
<< 8;
3436 cp_opc_expr (str
, where
, length
)
3443 skip_whitespace (* str
);
3445 memset (&expr
, '\0', sizeof (expr
));
3447 if (my_get_expression (&expr
, str
))
3449 if (expr
.X_op
!= O_constant
)
3451 inst
.error
= _("bad or missing expression");
3455 if ((expr
.X_add_number
& ((1 << length
) - 1)) != expr
.X_add_number
)
3457 inst
.error
= _("immediate co-processor expression too large");
3461 inst
.instruction
|= expr
.X_add_number
<< where
;
3466 cp_reg_required_here (str
, where
)
3471 char * start
= *str
;
3473 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CN
].htab
)) != FAIL
)
3475 inst
.instruction
|= reg
<< where
;
3479 /* In the few cases where we might be able to accept something else
3480 this error can be overridden. */
3481 inst
.error
= _("co-processor register expected");
3483 /* Restore the start point. */
3489 fp_reg_required_here (str
, where
)
3494 char * start
= * str
;
3496 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_FN
].htab
)) != FAIL
)
3498 inst
.instruction
|= reg
<< where
;
3502 /* In the few cases where we might be able to accept something else
3503 this error can be overridden. */
3504 inst
.error
= _("floating point register expected");
3506 /* Restore the start point. */
3512 cp_address_offset (str
)
3517 skip_whitespace (* str
);
3519 if (! is_immediate_prefix (**str
))
3521 inst
.error
= _("immediate expression expected");
3527 if (my_get_expression (& inst
.reloc
.exp
, str
))
3530 if (inst
.reloc
.exp
.X_op
== O_constant
)
3532 offset
= inst
.reloc
.exp
.X_add_number
;
3536 inst
.error
= _("co-processor address must be word aligned");
3540 if (offset
> 1023 || offset
< -1023)
3542 inst
.error
= _("offset too large");
3547 inst
.instruction
|= INDEX_UP
;
3551 inst
.instruction
|= offset
>> 2;
3554 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
3560 cp_address_required_here (str
, wb_ok
)
3573 skip_whitespace (p
);
3575 if ((reg
= reg_required_here (& p
, 16)) == FAIL
)
3578 skip_whitespace (p
);
3584 skip_whitespace (p
);
3588 /* As an extension to the official ARM syntax we allow:
3592 as a short hand for:
3595 inst
.instruction
|= PRE_INDEX
| INDEX_UP
;
3600 if (skip_past_comma (& p
) == FAIL
)
3602 inst
.error
= _("comma expected after closing square bracket");
3606 skip_whitespace (p
);
3613 write_back
= WRITE_BACK
;
3617 inst
.error
= _("pc may not be used in post-increment");
3621 if (cp_address_offset (& p
) == FAIL
)
3625 pre_inc
= PRE_INDEX
| INDEX_UP
;
3631 /* [Rn], {<expr>} */
3634 skip_whitespace (p
);
3636 if (my_get_expression (& inst
.reloc
.exp
, & p
))
3639 if (inst
.reloc
.exp
.X_op
== O_constant
)
3641 option
= inst
.reloc
.exp
.X_add_number
;
3643 if (option
> 255 || option
< 0)
3645 inst
.error
= _("'option' field too large");
3649 skip_whitespace (p
);
3653 inst
.error
= _("'}' expected at end of 'option' field");
3659 inst
.instruction
|= option
;
3660 inst
.instruction
|= INDEX_UP
;
3665 inst
.error
= _("non-constant expressions for 'option' field not supported");
3671 inst
.error
= _("# or { expected after comma");
3677 /* '['Rn, #expr']'[!] */
3679 if (skip_past_comma (& p
) == FAIL
)
3681 inst
.error
= _("pre-indexed expression expected");
3685 pre_inc
= PRE_INDEX
;
3687 if (cp_address_offset (& p
) == FAIL
)
3690 skip_whitespace (p
);
3694 inst
.error
= _("missing ]");
3698 skip_whitespace (p
);
3700 if (wb_ok
&& *p
== '!')
3704 inst
.error
= _("pc may not be used with write-back");
3709 write_back
= WRITE_BACK
;
3715 if (my_get_expression (&inst
.reloc
.exp
, &p
))
3718 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
3719 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
3720 inst
.reloc
.pc_rel
= 1;
3721 inst
.instruction
|= (REG_PC
<< 16);
3722 pre_inc
= PRE_INDEX
;
3725 inst
.instruction
|= write_back
| pre_inc
;
3731 cp_byte_address_offset (str
)
3736 skip_whitespace (* str
);
3738 if (! is_immediate_prefix (**str
))
3740 inst
.error
= _("immediate expression expected");
3746 if (my_get_expression (& inst
.reloc
.exp
, str
))
3749 if (inst
.reloc
.exp
.X_op
== O_constant
)
3751 offset
= inst
.reloc
.exp
.X_add_number
;
3753 if (offset
> 255 || offset
< -255)
3755 inst
.error
= _("offset too large");
3760 inst
.instruction
|= INDEX_UP
;
3764 inst
.instruction
|= offset
;
3767 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM_S2
;
3773 cp_byte_address_required_here (str
)
3785 skip_whitespace (p
);
3787 if ((reg
= reg_required_here (& p
, 16)) == FAIL
)
3790 skip_whitespace (p
);
3796 if (skip_past_comma (& p
) == SUCCESS
)
3799 write_back
= WRITE_BACK
;
3803 inst
.error
= _("pc may not be used in post-increment");
3807 if (cp_byte_address_offset (& p
) == FAIL
)
3811 pre_inc
= PRE_INDEX
| INDEX_UP
;
3815 /* '['Rn, #expr']'[!] */
3817 if (skip_past_comma (& p
) == FAIL
)
3819 inst
.error
= _("pre-indexed expression expected");
3823 pre_inc
= PRE_INDEX
;
3825 if (cp_byte_address_offset (& p
) == FAIL
)
3828 skip_whitespace (p
);
3832 inst
.error
= _("missing ]");
3836 skip_whitespace (p
);
3842 inst
.error
= _("pc may not be used with write-back");
3847 write_back
= WRITE_BACK
;
3853 if (my_get_expression (&inst
.reloc
.exp
, &p
))
3856 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM_S2
;
3857 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
3858 inst
.reloc
.pc_rel
= 1;
3859 inst
.instruction
|= (REG_PC
<< 16);
3860 pre_inc
= PRE_INDEX
;
3863 inst
.instruction
|= write_back
| pre_inc
;
3872 /* Do nothing really. */
3883 /* Only one syntax. */
3884 skip_whitespace (str
);
3886 if (reg_required_here (&str
, 12) == FAIL
)
3888 inst
.error
= BAD_ARGS
;
3892 if (skip_past_comma (&str
) == FAIL
)
3894 inst
.error
= _("comma expected after register name");
3898 skip_whitespace (str
);
3900 if ( strcmp (str
, "CPSR") == 0
3901 || strcmp (str
, "SPSR") == 0
3902 /* Lower case versions for backwards compatibility. */
3903 || strcmp (str
, "cpsr") == 0
3904 || strcmp (str
, "spsr") == 0)
3907 /* This is for backwards compatibility with older toolchains. */
3908 else if ( strcmp (str
, "cpsr_all") == 0
3909 || strcmp (str
, "spsr_all") == 0)
3913 inst
.error
= _("CPSR or SPSR expected");
3917 if (* str
== 's' || * str
== 'S')
3918 inst
.instruction
|= SPSR_BIT
;
3924 /* Two possible forms:
3925 "{C|S}PSR_<field>, Rm",
3926 "{C|S}PSR_f, #expression". */
3932 skip_whitespace (str
);
3934 if (psr_required_here (& str
) == FAIL
)
3937 if (skip_past_comma (& str
) == FAIL
)
3939 inst
.error
= _("comma missing after psr flags");
3943 skip_whitespace (str
);
3945 if (reg_required_here (& str
, 0) != FAIL
)
3952 if (! is_immediate_prefix (* str
))
3955 _("only a register or immediate value can follow a psr flag");
3962 if (my_get_expression (& inst
.reloc
.exp
, & str
))
3965 _("only a register or immediate value can follow a psr flag");
3969 #if 0 /* The first edition of the ARM architecture manual stated that
3970 writing anything other than the flags with an immediate operation
3971 had UNPREDICTABLE effects. This constraint was removed in the
3972 second edition of the specification. */
3973 if ((cpu_variant
& ARM_EXT_V5
) != ARM_EXT_V5
3974 && inst
.instruction
& ((PSR_c
| PSR_x
| PSR_s
) << PSR_SHIFT
))
3976 inst
.error
= _("immediate value cannot be used to set this field");
3981 inst
.instruction
|= INST_IMMEDIATE
;
3983 if (inst
.reloc
.exp
.X_add_symbol
)
3985 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
3986 inst
.reloc
.pc_rel
= 0;
3990 unsigned value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
3992 if (value
== (unsigned) FAIL
)
3994 inst
.error
= _("invalid constant");
3998 inst
.instruction
|= value
;
4005 /* Long Multiply Parser
4006 UMULL RdLo, RdHi, Rm, Rs
4007 SMULL RdLo, RdHi, Rm, Rs
4008 UMLAL RdLo, RdHi, Rm, Rs
4009 SMLAL RdLo, RdHi, Rm, Rs. */
4015 int rdlo
, rdhi
, rm
, rs
;
4017 /* Only one format "rdlo, rdhi, rm, rs". */
4018 skip_whitespace (str
);
4020 if ((rdlo
= reg_required_here (&str
, 12)) == FAIL
)
4022 inst
.error
= BAD_ARGS
;
4026 if (skip_past_comma (&str
) == FAIL
4027 || (rdhi
= reg_required_here (&str
, 16)) == FAIL
)
4029 inst
.error
= BAD_ARGS
;
4033 if (skip_past_comma (&str
) == FAIL
4034 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4036 inst
.error
= BAD_ARGS
;
4040 /* rdhi, rdlo and rm must all be different. */
4041 if (rdlo
== rdhi
|| rdlo
== rm
|| rdhi
== rm
)
4042 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
4044 if (skip_past_comma (&str
) == FAIL
4045 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
4047 inst
.error
= BAD_ARGS
;
4051 if (rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
)
4053 inst
.error
= BAD_PC
;
4067 /* Only one format "rd, rm, rs". */
4068 skip_whitespace (str
);
4070 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
4072 inst
.error
= BAD_ARGS
;
4078 inst
.error
= BAD_PC
;
4082 if (skip_past_comma (&str
) == FAIL
4083 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4085 inst
.error
= BAD_ARGS
;
4091 inst
.error
= BAD_PC
;
4096 as_tsktsk (_("rd and rm should be different in mul"));
4098 if (skip_past_comma (&str
) == FAIL
4099 || (rm
= reg_required_here (&str
, 8)) == FAIL
)
4101 inst
.error
= BAD_ARGS
;
4107 inst
.error
= BAD_PC
;
4121 /* Only one format "rd, rm, rs, rn". */
4122 skip_whitespace (str
);
4124 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
4126 inst
.error
= BAD_ARGS
;
4132 inst
.error
= BAD_PC
;
4136 if (skip_past_comma (&str
) == FAIL
4137 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4139 inst
.error
= BAD_ARGS
;
4145 inst
.error
= BAD_PC
;
4150 as_tsktsk (_("rd and rm should be different in mla"));
4152 if (skip_past_comma (&str
) == FAIL
4153 || (rd
= reg_required_here (&str
, 8)) == FAIL
4154 || skip_past_comma (&str
) == FAIL
4155 || (rm
= reg_required_here (&str
, 12)) == FAIL
)
4157 inst
.error
= BAD_ARGS
;
4161 if (rd
== REG_PC
|| rm
== REG_PC
)
4163 inst
.error
= BAD_PC
;
4171 /* Expects *str -> the characters "acc0", possibly with leading blanks.
4172 Advances *str to the next non-alphanumeric.
4173 Returns 0, or else FAIL (in which case sets inst.error).
4175 (In a future XScale, there may be accumulators other than zero.
4176 At that time this routine and its callers can be upgraded to suit.) */
4179 accum0_required_here (str
)
4182 static char buff
[128]; /* Note the address is taken. Hence, static. */
4185 int result
= 0; /* The accum number. */
4187 skip_whitespace (p
);
4189 *str
= p
; /* Advance caller's string pointer too. */
4194 *--p
= 0; /* Aap nul into input buffer at non-alnum. */
4196 if (! ( streq (*str
, "acc0") || streq (*str
, "ACC0")))
4198 sprintf (buff
, _("acc0 expected, not '%.100s'"), *str
);
4203 *p
= c
; /* Unzap. */
4204 *str
= p
; /* Caller's string pointer to after match. */
4208 /* Expects **str -> after a comma. May be leading blanks.
4209 Advances *str, recognizing a load mode, and setting inst.instruction.
4210 Returns rn, or else FAIL (in which case may set inst.error
4211 and not advance str)
4213 Note: doesn't know Rd, so no err checks that require such knowledge. */
4216 ld_mode_required_here (string
)
4219 char * str
= * string
;
4223 skip_whitespace (str
);
4229 skip_whitespace (str
);
4231 if ((rn
= reg_required_here (& str
, 16)) == FAIL
)
4234 skip_whitespace (str
);
4240 if (skip_past_comma (& str
) == SUCCESS
)
4242 /* [Rn],... (post inc) */
4243 if (ldst_extend_v4 (&str
) == FAIL
)
4248 skip_whitespace (str
);
4253 inst
.instruction
|= WRITE_BACK
;
4256 inst
.instruction
|= INDEX_UP
| HWOFFSET_IMM
;
4262 if (skip_past_comma (& str
) == FAIL
)
4264 inst
.error
= _("pre-indexed expression expected");
4270 if (ldst_extend_v4 (&str
) == FAIL
)
4273 skip_whitespace (str
);
4275 if (* str
++ != ']')
4277 inst
.error
= _("missing ]");
4281 skip_whitespace (str
);
4286 inst
.instruction
|= WRITE_BACK
;
4290 else if (* str
== '=') /* ldr's "r,=label" syntax */
4291 /* We should never reach here, because <text> = <expression> is
4292 caught gas/read.c read_a_source_file() as a .set operation. */
4294 else /* PC +- 8 bit immediate offset. */
4296 if (my_get_expression (& inst
.reloc
.exp
, & str
))
4299 inst
.instruction
|= HWOFFSET_IMM
; /* The I bit. */
4300 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
4301 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
4302 inst
.reloc
.pc_rel
= 1;
4303 inst
.instruction
|= (REG_PC
<< 16);
4309 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
4315 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
4316 SMLAxy{cond} Rd,Rm,Rs,Rn
4317 SMLAWy{cond} Rd,Rm,Rs,Rn
4318 Error if any register is R15. */
4326 skip_whitespace (str
);
4328 if ((rd
= reg_required_here (& str
, 16)) == FAIL
4329 || skip_past_comma (& str
) == FAIL
4330 || (rm
= reg_required_here (& str
, 0)) == FAIL
4331 || skip_past_comma (& str
) == FAIL
4332 || (rs
= reg_required_here (& str
, 8)) == FAIL
4333 || skip_past_comma (& str
) == FAIL
4334 || (rn
= reg_required_here (& str
, 12)) == FAIL
)
4335 inst
.error
= BAD_ARGS
;
4337 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
|| rn
== REG_PC
)
4338 inst
.error
= BAD_PC
;
4344 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
4345 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
4346 Error if any register is R15.
4347 Warning if Rdlo == Rdhi. */
4353 int rdlo
, rdhi
, rm
, rs
;
4355 skip_whitespace (str
);
4357 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
4358 || skip_past_comma (& str
) == FAIL
4359 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
4360 || skip_past_comma (& str
) == FAIL
4361 || (rm
= reg_required_here (& str
, 0)) == FAIL
4362 || skip_past_comma (& str
) == FAIL
4363 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
4365 inst
.error
= BAD_ARGS
;
4369 if (rdlo
== REG_PC
|| rdhi
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
4371 inst
.error
= BAD_PC
;
4376 as_tsktsk (_("rdhi and rdlo must be different"));
4381 /* ARM V5E (El Segundo) signed-multiply (argument parse)
4382 SMULxy{cond} Rd,Rm,Rs
4383 Error if any register is R15. */
4391 skip_whitespace (str
);
4393 if ((rd
= reg_required_here (& str
, 16)) == FAIL
4394 || skip_past_comma (& str
) == FAIL
4395 || (rm
= reg_required_here (& str
, 0)) == FAIL
4396 || skip_past_comma (& str
) == FAIL
4397 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
4398 inst
.error
= BAD_ARGS
;
4400 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
4401 inst
.error
= BAD_PC
;
4407 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
4408 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
4409 Error if any register is R15. */
4417 skip_whitespace (str
);
4419 if ((rd
= reg_required_here (& str
, 12)) == FAIL
4420 || skip_past_comma (& str
) == FAIL
4421 || (rm
= reg_required_here (& str
, 0)) == FAIL
4422 || skip_past_comma (& str
) == FAIL
4423 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
4424 inst
.error
= BAD_ARGS
;
4426 else if (rd
== REG_PC
|| rm
== REG_PC
|| rn
== REG_PC
)
4427 inst
.error
= BAD_PC
;
4433 /* ARM V5E (el Segundo)
4434 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4435 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4437 These are equivalent to the XScale instructions MAR and MRA,
4438 respectively, when coproc == 0, opcode == 0, and CRm == 0.
4440 Result unpredicatable if Rd or Rn is R15. */
4448 skip_whitespace (str
);
4450 if (co_proc_number (& str
) == FAIL
)
4453 inst
.error
= BAD_ARGS
;
4457 if (skip_past_comma (& str
) == FAIL
4458 || cp_opc_expr (& str
, 4, 4) == FAIL
)
4461 inst
.error
= BAD_ARGS
;
4465 if (skip_past_comma (& str
) == FAIL
4466 || (rd
= reg_required_here (& str
, 12)) == FAIL
)
4469 inst
.error
= BAD_ARGS
;
4473 if (skip_past_comma (& str
) == FAIL
4474 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
4477 inst
.error
= BAD_ARGS
;
4481 /* Unpredictable result if rd or rn is R15. */
4482 if (rd
== REG_PC
|| rn
== REG_PC
)
4484 (_("Warning: instruction unpredictable when using r15"));
4486 if (skip_past_comma (& str
) == FAIL
4487 || cp_reg_required_here (& str
, 0) == FAIL
)
4490 inst
.error
= BAD_ARGS
;
4497 /* ARM V5 count-leading-zeroes instruction (argument parse)
4498 CLZ{<cond>} <Rd>, <Rm>
4499 Condition defaults to COND_ALWAYS.
4500 Error if Rd or Rm are R15. */
4508 skip_whitespace (str
);
4510 if (((rd
= reg_required_here (& str
, 12)) == FAIL
)
4511 || (skip_past_comma (& str
) == FAIL
)
4512 || ((rm
= reg_required_here (& str
, 0)) == FAIL
))
4513 inst
.error
= BAD_ARGS
;
4515 else if (rd
== REG_PC
|| rm
== REG_PC
)
4516 inst
.error
= BAD_PC
;
4522 /* ARM V5 (argument parse)
4523 LDC2{L} <coproc>, <CRd>, <addressing mode>
4524 STC2{L} <coproc>, <CRd>, <addressing mode>
4525 Instruction is not conditional, and has 0xf in the condition field.
4526 Otherwise, it's the same as LDC/STC. */
4532 skip_whitespace (str
);
4534 if (co_proc_number (& str
) == FAIL
)
4537 inst
.error
= BAD_ARGS
;
4539 else if (skip_past_comma (& str
) == FAIL
4540 || cp_reg_required_here (& str
, 12) == FAIL
)
4543 inst
.error
= BAD_ARGS
;
4545 else if (skip_past_comma (& str
) == FAIL
4546 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
4549 inst
.error
= BAD_ARGS
;
4555 /* ARM V5 (argument parse)
4556 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
4557 Instruction is not conditional, and has 0xf in the condition field.
4558 Otherwise, it's the same as CDP. */
4564 skip_whitespace (str
);
4566 if (co_proc_number (& str
) == FAIL
)
4569 inst
.error
= BAD_ARGS
;
4573 if (skip_past_comma (& str
) == FAIL
4574 || cp_opc_expr (& str
, 20,4) == FAIL
)
4577 inst
.error
= BAD_ARGS
;
4581 if (skip_past_comma (& str
) == FAIL
4582 || cp_reg_required_here (& str
, 12) == FAIL
)
4585 inst
.error
= BAD_ARGS
;
4589 if (skip_past_comma (& str
) == FAIL
4590 || cp_reg_required_here (& str
, 16) == FAIL
)
4593 inst
.error
= BAD_ARGS
;
4597 if (skip_past_comma (& str
) == FAIL
4598 || cp_reg_required_here (& str
, 0) == FAIL
)
4601 inst
.error
= BAD_ARGS
;
4605 if (skip_past_comma (& str
) == SUCCESS
)
4607 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
4610 inst
.error
= BAD_ARGS
;
4618 /* ARM V5 (argument parse)
4619 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4620 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4621 Instruction is not conditional, and has 0xf in the condition field.
4622 Otherwise, it's the same as MCR/MRC. */
4628 skip_whitespace (str
);
4630 if (co_proc_number (& str
) == FAIL
)
4633 inst
.error
= BAD_ARGS
;
4637 if (skip_past_comma (& str
) == FAIL
4638 || cp_opc_expr (& str
, 21, 3) == FAIL
)
4641 inst
.error
= BAD_ARGS
;
4645 if (skip_past_comma (& str
) == FAIL
4646 || reg_required_here (& str
, 12) == FAIL
)
4649 inst
.error
= BAD_ARGS
;
4653 if (skip_past_comma (& str
) == FAIL
4654 || cp_reg_required_here (& str
, 16) == FAIL
)
4657 inst
.error
= BAD_ARGS
;
4661 if (skip_past_comma (& str
) == FAIL
4662 || cp_reg_required_here (& str
, 0) == FAIL
)
4665 inst
.error
= BAD_ARGS
;
4669 if (skip_past_comma (& str
) == SUCCESS
)
4671 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
4674 inst
.error
= BAD_ARGS
;
4682 /* ARM v5TEJ. Jump to Jazelle code. */
4689 skip_whitespace (str
);
4691 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
4693 inst
.error
= BAD_ARGS
;
4697 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
4699 as_tsktsk (_("use of r15 in bxj is not really useful"));
4704 /* THUMB V5 breakpoint instruction (argument parse)
4712 unsigned long number
;
4714 skip_whitespace (str
);
4716 /* Allow optional leading '#'. */
4717 if (is_immediate_prefix (*str
))
4720 memset (& expr
, '\0', sizeof (expr
));
4721 if (my_get_expression (& expr
, & str
)
4722 || (expr
.X_op
!= O_constant
4723 /* As a convenience we allow 'bkpt' without an operand. */
4724 && expr
.X_op
!= O_absent
))
4726 inst
.error
= _("bad expression");
4730 number
= expr
.X_add_number
;
4732 /* Check it fits an 8 bit unsigned. */
4733 if (number
!= (number
& 0xff))
4735 inst
.error
= _("immediate value out of range");
4739 inst
.instruction
|= number
;
4744 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
4745 Expects inst.instruction is set for BLX(1).
4746 Note: this is cloned from do_branch, and the reloc changed to be a
4747 new one that can cope with setting one extra bit (the H bit). */
4753 if (my_get_expression (& inst
.reloc
.exp
, & str
))
4760 /* ScottB: February 5, 1998 */
4761 /* Check to see of PLT32 reloc required for the instruction. */
4763 /* arm_parse_reloc() works on input_line_pointer.
4764 We actually want to parse the operands to the branch instruction
4765 passed in 'str'. Save the input pointer and restore it later. */
4766 save_in
= input_line_pointer
;
4767 input_line_pointer
= str
;
4769 if (inst
.reloc
.exp
.X_op
== O_symbol
4771 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
4773 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
4774 inst
.reloc
.pc_rel
= 0;
4775 /* Modify str to point to after parsed operands, otherwise
4776 end_of_line() will complain about the (PLT) left in str. */
4777 str
= input_line_pointer
;
4781 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
4782 inst
.reloc
.pc_rel
= 1;
4785 input_line_pointer
= save_in
;
4788 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
4789 inst
.reloc
.pc_rel
= 1;
4790 #endif /* OBJ_ELF */
4795 /* ARM V5 branch-link-exchange instruction (argument parse)
4796 BLX <target_addr> ie BLX(1)
4797 BLX{<condition>} <Rm> ie BLX(2)
4798 Unfortunately, there are two different opcodes for this mnemonic.
4799 So, the insns[].value is not used, and the code here zaps values
4800 into inst.instruction.
4801 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
4810 skip_whitespace (mystr
);
4811 rm
= reg_required_here (& mystr
, 0);
4813 /* The above may set inst.error. Ignore his opinion. */
4818 /* Arg is a register.
4819 Use the condition code our caller put in inst.instruction.
4820 Pass ourselves off as a BX with a funny opcode. */
4821 inst
.instruction
|= 0x012fff30;
4826 /* This must be is BLX <target address>, no condition allowed. */
4827 if (inst
.instruction
!= COND_ALWAYS
)
4829 inst
.error
= BAD_COND
;
4833 inst
.instruction
= 0xfafffffe;
4835 /* Process like a B/BL, but with a different reloc.
4836 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
4841 /* ARM V5 Thumb BLX (argument parse)
4842 BLX <target_addr> which is BLX(1)
4843 BLX <Rm> which is BLX(2)
4844 Unfortunately, there are two different opcodes for this mnemonic.
4845 So, the tinsns[].value is not used, and the code here zaps values
4846 into inst.instruction. */
4855 skip_whitespace (mystr
);
4856 inst
.instruction
= 0x4780;
4858 /* Note that this call is to the ARM register recognizer. BLX(2)
4859 uses the ARM register space, not the Thumb one, so a call to
4860 thumb_reg() would be wrong. */
4861 rm
= reg_required_here (& mystr
, 3);
4866 /* It's BLX(2). The .instruction was zapped with rm & is final. */
4871 /* No ARM register. This must be BLX(1). Change the .instruction. */
4872 inst
.instruction
= 0xf7ffeffe;
4875 if (my_get_expression (& inst
.reloc
.exp
, & mystr
))
4878 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BLX
;
4879 inst
.reloc
.pc_rel
= 1;
4882 end_of_line (mystr
);
4885 /* ARM V5 breakpoint instruction (argument parse)
4886 BKPT <16 bit unsigned immediate>
4887 Instruction is not conditional.
4888 The bit pattern given in insns[] has the COND_ALWAYS condition,
4889 and it is an error if the caller tried to override that. */
4896 unsigned long number
;
4898 skip_whitespace (str
);
4900 /* Allow optional leading '#'. */
4901 if (is_immediate_prefix (* str
))
4904 memset (& expr
, '\0', sizeof (expr
));
4906 if (my_get_expression (& expr
, & str
)
4907 || (expr
.X_op
!= O_constant
4908 /* As a convenience we allow 'bkpt' without an operand. */
4909 && expr
.X_op
!= O_absent
))
4911 inst
.error
= _("bad expression");
4915 number
= expr
.X_add_number
;
4917 /* Check it fits a 16 bit unsigned. */
4918 if (number
!= (number
& 0xffff))
4920 inst
.error
= _("immediate value out of range");
4924 /* Top 12 of 16 bits to bits 19:8. */
4925 inst
.instruction
|= (number
& 0xfff0) << 4;
4927 /* Bottom 4 of 16 bits to bits 3:0. */
4928 inst
.instruction
|= number
& 0xf;
4933 static unsigned long check_iwmmxt_insn
PARAMS ((char *, enum iwmmxt_insn_type
, int));
4935 /* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
4937 static unsigned long
4938 check_iwmmxt_insn (str
, insn_type
, immediate_size
)
4940 enum iwmmxt_insn_type insn_type
;
4944 const char * inst_error
;
4946 unsigned long number
;
4948 inst_error
= inst
.error
;
4950 inst
.error
= BAD_ARGS
;
4951 skip_whitespace (str
);
4956 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
4961 if ((wreg_required_here (&str
, 0, IWMMXT_REG_WR
)) == FAIL
)
4966 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
4967 || skip_past_comma (&str
) == FAIL
4968 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
))
4973 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
4974 || skip_past_comma (&str
) == FAIL
4975 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4976 || skip_past_comma (&str
) == FAIL
4977 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
))
4982 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
4983 || skip_past_comma (&str
) == FAIL
4984 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4985 || skip_past_comma (&str
) == FAIL
4986 || wreg_required_here (&str
, 0, IWMMXT_REG_WCG
) == FAIL
))
4991 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4992 || skip_past_comma (&str
) == FAIL
4993 || reg_required_here (&str
, 12) == FAIL
))
4998 if ((reg_required_here (&str
, 12) == FAIL
4999 || skip_past_comma (&str
) == FAIL
5000 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
))
5005 if ((wreg_required_here (&str
, 5, IWMMXT_REG_WR
) == FAIL
5006 || skip_past_comma (&str
) == FAIL
5007 || reg_required_here (&str
, 0) == FAIL
5008 || skip_past_comma (&str
) == FAIL
5009 || reg_required_here (&str
, 12) == FAIL
))
5014 if ((wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
5015 || skip_past_comma (&str
) == FAIL
5016 || reg_required_here (&str
, 12) == FAIL
5017 || skip_past_comma (&str
) == FAIL
5018 || reg_required_here (&str
, 16) == FAIL
))
5023 if ((reg_required_here (&str
, 12) == FAIL
5024 || skip_past_comma (&str
) == FAIL
5025 || reg_required_here (&str
, 16) == FAIL
5026 || skip_past_comma (&str
) == FAIL
5027 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
))
5032 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WC
) == FAIL
5033 || skip_past_comma (&str
) == FAIL
5034 || reg_required_here (&str
, 12) == FAIL
))
5039 if ((reg_required_here (&str
, 12) == FAIL
5040 || skip_past_comma (&str
) == FAIL
5041 || wreg_required_here (&str
, 16, IWMMXT_REG_WC
) == FAIL
))
5046 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5047 || skip_past_comma (&str
) == FAIL
5048 || reg_required_here (&str
, 12) == FAIL
5049 || skip_past_comma (&str
) == FAIL
))
5054 if ((reg_required_here (&str
, 12) == FAIL
5055 || skip_past_comma (&str
) == FAIL
))
5060 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
5061 || skip_past_comma (&str
) == FAIL
5062 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5063 || skip_past_comma (&str
) == FAIL
5064 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
5065 || skip_past_comma (&str
) == FAIL
))
5070 if ((reg_required_here (&str
, 12) == FAIL
5071 || skip_past_comma (&str
) == FAIL
5072 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5073 || skip_past_comma (&str
) == FAIL
))
5078 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
5079 || skip_past_comma (&str
) == FAIL
5080 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5081 || skip_past_comma (&str
) == FAIL
))
5086 if (immediate_size
== 0)
5089 inst
.error
= inst_error
;
5094 skip_whitespace (str
);
5096 /* Allow optional leading '#'. */
5097 if (is_immediate_prefix (* str
))
5100 memset (& expr
, '\0', sizeof (expr
));
5102 if (my_get_expression (& expr
, & str
) || (expr
.X_op
!= O_constant
))
5104 inst
.error
= _("bad or missing expression");
5108 number
= expr
.X_add_number
;
5110 if (number
!= (number
& immediate_size
))
5112 inst
.error
= _("immediate value out of range");
5116 inst
.error
= inst_error
;
5122 do_iwmmxt_byte_addr (str
)
5125 int op
= (inst
.instruction
& 0x300) >> 8;
5128 inst
.instruction
&= ~0x300;
5129 inst
.instruction
|= (op
& 1) << 22 | (op
& 2) << 7;
5131 skip_whitespace (str
);
5133 if ((reg
= wreg_required_here (&str
, 12, IWMMXT_REG_WR_OR_WC
)) == FAIL
5134 || skip_past_comma (& str
) == FAIL
5135 || cp_byte_address_required_here (&str
) == FAIL
)
5138 inst
.error
= BAD_ARGS
;
5143 if (wc_register (reg
))
5145 as_bad (_("non-word size not supported with control register"));
5146 inst
.instruction
|= 0xf0000100;
5147 inst
.instruction
&= ~0x00400000;
5152 do_iwmmxt_tandc (str
)
5157 reg
= check_iwmmxt_insn (str
, check_rd
, 0);
5159 if (reg
!= REG_PC
&& !inst
.error
)
5160 inst
.error
= _("only r15 allowed here");
5165 do_iwmmxt_tbcst (str
)
5168 check_iwmmxt_insn (str
, check_tbcst
, 0);
5174 do_iwmmxt_textrc (str
)
5177 unsigned long number
;
5179 if ((number
= check_iwmmxt_insn (str
, check_textrc
, 7)) == (unsigned long) FAIL
)
5182 inst
.instruction
|= number
& 0x7;
5187 do_iwmmxt_textrm (str
)
5190 unsigned long number
;
5192 if ((number
= check_iwmmxt_insn (str
, check_textrm
, 7)) == (unsigned long) FAIL
)
5195 inst
.instruction
|= number
& 0x7;
5199 do_iwmmxt_tinsr (str
)
5202 unsigned long number
;
5204 if ((number
= check_iwmmxt_insn (str
, check_tinsr
, 7)) == (unsigned long) FAIL
)
5207 inst
.instruction
|= number
& 0x7;
5212 do_iwmmxt_tmcr (str
)
5215 check_iwmmxt_insn (str
, check_tmcr
, 0);
5221 do_iwmmxt_tmcrr (str
)
5224 check_iwmmxt_insn (str
, check_tmcrr
, 0);
5230 do_iwmmxt_tmia (str
)
5233 check_iwmmxt_insn (str
, check_tmia
, 0);
5239 do_iwmmxt_tmovmsk (str
)
5242 check_iwmmxt_insn (str
, check_tmovmsk
, 0);
5248 do_iwmmxt_tmrc (str
)
5251 check_iwmmxt_insn (str
, check_tmrc
, 0);
5257 do_iwmmxt_tmrrc (str
)
5260 check_iwmmxt_insn (str
, check_tmrrc
, 0);
5266 do_iwmmxt_torc (str
)
5269 check_iwmmxt_insn (str
, check_rd
, 0);
5274 do_iwmmxt_waligni (str
)
5277 unsigned long number
;
5279 if ((number
= check_iwmmxt_insn (str
, check_waligni
, 7)) == (unsigned long) FAIL
)
5282 inst
.instruction
|= ((number
& 0x7) << 20);
5287 do_iwmmxt_wmov (str
)
5290 if (check_iwmmxt_insn (str
, check_wrwr
, 0) == (unsigned long) FAIL
)
5293 inst
.instruction
|= ((inst
.instruction
>> 16) & 0xf);
5298 do_iwmmxt_word_addr (str
)
5301 int op
= (inst
.instruction
& 0x300) >> 8;
5304 inst
.instruction
&= ~0x300;
5305 inst
.instruction
|= (op
& 1) << 22 | (op
& 2) << 7;
5307 skip_whitespace (str
);
5309 if ((reg
= wreg_required_here (&str
, 12, IWMMXT_REG_WR_OR_WC
)) == FAIL
5310 || skip_past_comma (& str
) == FAIL
5311 || cp_address_required_here (& str
, CP_WB_OK
) == FAIL
)
5314 inst
.error
= BAD_ARGS
;
5319 if (wc_register (reg
))
5321 if ((inst
.instruction
& COND_MASK
) != COND_ALWAYS
)
5322 as_bad (_("conditional execution not supported with control register"));
5324 as_bad (_("non-word size not supported with control register"));
5325 inst
.instruction
|= 0xf0000100;
5326 inst
.instruction
&= ~0x00400000;
5331 do_iwmmxt_wrwr (str
)
5334 check_iwmmxt_insn (str
, check_wrwr
, 0);
5340 do_iwmmxt_wrwrwcg (str
)
5343 check_iwmmxt_insn (str
, check_wrwrwcg
, 0);
5349 do_iwmmxt_wrwrwr (str
)
5352 check_iwmmxt_insn (str
, check_wrwrwr
, 0);
5358 do_iwmmxt_wshufh (str
)
5361 unsigned long number
;
5363 if ((number
= check_iwmmxt_insn (str
, check_wshufh
, 0xff)) == (unsigned long) FAIL
)
5366 inst
.instruction
|= ((number
& 0xf0) << 16) | (number
& 0xf);
5371 do_iwmmxt_wzero (str
)
5374 if (check_iwmmxt_insn (str
, check_wr
, 0) == (unsigned long) FAIL
)
5377 inst
.instruction
|= ((inst
.instruction
& 0xf) << 12) | ((inst
.instruction
& 0xf) << 16);
5381 /* Xscale multiply-accumulate (argument parse)
5384 MIAxycc acc0,Rm,Rs. */
5393 if (accum0_required_here (& str
) == FAIL
)
5394 inst
.error
= ERR_NO_ACCUM
;
5396 else if (skip_past_comma (& str
) == FAIL
5397 || (rm
= reg_required_here (& str
, 0)) == FAIL
)
5398 inst
.error
= BAD_ARGS
;
5400 else if (skip_past_comma (& str
) == FAIL
5401 || (rs
= reg_required_here (& str
, 12)) == FAIL
)
5402 inst
.error
= BAD_ARGS
;
5404 /* inst.instruction has now been zapped with both rm and rs. */
5405 else if (rm
== REG_PC
|| rs
== REG_PC
)
5406 inst
.error
= BAD_PC
; /* Undefined result if rm or rs is R15. */
5412 /* Xscale move-accumulator-register (argument parse)
5414 MARcc acc0,RdLo,RdHi. */
5422 if (accum0_required_here (& str
) == FAIL
)
5423 inst
.error
= ERR_NO_ACCUM
;
5425 else if (skip_past_comma (& str
) == FAIL
5426 || (rdlo
= reg_required_here (& str
, 12)) == FAIL
)
5427 inst
.error
= BAD_ARGS
;
5429 else if (skip_past_comma (& str
) == FAIL
5430 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
5431 inst
.error
= BAD_ARGS
;
5433 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5434 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
5435 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
5441 /* Xscale move-register-accumulator (argument parse)
5443 MRAcc RdLo,RdHi,acc0. */
5452 skip_whitespace (str
);
5454 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
)
5455 inst
.error
= BAD_ARGS
;
5457 else if (skip_past_comma (& str
) == FAIL
5458 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
5459 inst
.error
= BAD_ARGS
;
5461 else if (skip_past_comma (& str
) == FAIL
5462 || accum0_required_here (& str
) == FAIL
)
5463 inst
.error
= ERR_NO_ACCUM
;
5465 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5466 else if (rdlo
== rdhi
)
5467 inst
.error
= BAD_ARGS
; /* Undefined result if 2 writes to same reg. */
5469 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
5470 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
5475 /* ARMv5TE: Preload-Cache
5479 Syntactically, like LDR with B=1, W=0, L=1. */
5487 skip_whitespace (str
);
5491 inst
.error
= _("'[' expected after PLD mnemonic");
5496 skip_whitespace (str
);
5498 if ((rd
= reg_required_here (& str
, 16)) == FAIL
)
5501 skip_whitespace (str
);
5507 skip_whitespace (str
);
5509 /* Post-indexed addressing is not allowed with PLD. */
5510 if (skip_past_comma (&str
) == SUCCESS
)
5513 = _("post-indexed expression used in preload instruction");
5516 else if (*str
== '!') /* [Rn]! */
5518 inst
.error
= _("writeback used in preload instruction");
5522 inst
.instruction
|= INDEX_UP
| PRE_INDEX
;
5524 else /* [Rn, ...] */
5526 if (skip_past_comma (& str
) == FAIL
)
5528 inst
.error
= _("pre-indexed expression expected");
5532 if (ldst_extend (&str
) == FAIL
)
5535 skip_whitespace (str
);
5539 inst
.error
= _("missing ]");
5544 skip_whitespace (str
);
5546 if (* str
== '!') /* [Rn]! */
5548 inst
.error
= _("writeback used in preload instruction");
5552 inst
.instruction
|= PRE_INDEX
;
5558 /* ARMv5TE load-consecutive (argument parse)
5571 skip_whitespace (str
);
5573 if ((rd
= reg_required_here (& str
, 12)) == FAIL
)
5575 inst
.error
= BAD_ARGS
;
5579 if (skip_past_comma (& str
) == FAIL
5580 || (rn
= ld_mode_required_here (& str
)) == FAIL
)
5583 inst
.error
= BAD_ARGS
;
5587 /* inst.instruction has now been zapped with Rd and the addressing mode. */
5588 if (rd
& 1) /* Unpredictable result if Rd is odd. */
5590 inst
.error
= _("destination register must be even");
5596 inst
.error
= _("r14 not allowed here");
5600 if (((rd
== rn
) || (rd
+ 1 == rn
))
5601 && ((inst
.instruction
& WRITE_BACK
)
5602 || (!(inst
.instruction
& PRE_INDEX
))))
5603 as_warn (_("pre/post-indexing used when modified address register is destination"));
5605 /* For an index-register load, the index register must not overlap the
5606 destination (even if not write-back). */
5607 if ((inst
.instruction
& V4_STR_BIT
) == 0
5608 && (inst
.instruction
& HWOFFSET_IMM
) == 0)
5610 int rm
= inst
.instruction
& 0x0000000f;
5612 if (rm
== rd
|| (rm
== rd
+ 1))
5613 as_warn (_("ldrd destination registers must not overlap index register"));
5619 /* Returns the index into fp_values of a floating point number,
5620 or -1 if not in the table. */
5623 my_get_float_expression (str
)
5626 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
5632 memset (words
, 0, MAX_LITTLENUMS
* sizeof (LITTLENUM_TYPE
));
5634 /* Look for a raw floating point number. */
5635 if ((save_in
= atof_ieee (*str
, 'x', words
)) != NULL
5636 && is_end_of_line
[(unsigned char) *save_in
])
5638 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
5640 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
5642 if (words
[j
] != fp_values
[i
][j
])
5646 if (j
== MAX_LITTLENUMS
)
5654 /* Try and parse a more complex expression, this will probably fail
5655 unless the code uses a floating point prefix (eg "0f"). */
5656 save_in
= input_line_pointer
;
5657 input_line_pointer
= *str
;
5658 if (expression (&exp
) == absolute_section
5659 && exp
.X_op
== O_big
5660 && exp
.X_add_number
< 0)
5662 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
5664 if (gen_to_words (words
, 5, (long) 15) == 0)
5666 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
5668 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
5670 if (words
[j
] != fp_values
[i
][j
])
5674 if (j
== MAX_LITTLENUMS
)
5676 *str
= input_line_pointer
;
5677 input_line_pointer
= save_in
;
5684 *str
= input_line_pointer
;
5685 input_line_pointer
= save_in
;
5689 /* Return TRUE if anything in the expression is a bignum. */
5692 walk_no_bignums (sp
)
5695 if (symbol_get_value_expression (sp
)->X_op
== O_big
)
5698 if (symbol_get_value_expression (sp
)->X_add_symbol
)
5700 return (walk_no_bignums (symbol_get_value_expression (sp
)->X_add_symbol
)
5701 || (symbol_get_value_expression (sp
)->X_op_symbol
5702 && walk_no_bignums (symbol_get_value_expression (sp
)->X_op_symbol
)));
5708 static int in_my_get_expression
= 0;
5711 my_get_expression (ep
, str
)
5718 save_in
= input_line_pointer
;
5719 input_line_pointer
= *str
;
5720 in_my_get_expression
= 1;
5721 seg
= expression (ep
);
5722 in_my_get_expression
= 0;
5724 if (ep
->X_op
== O_illegal
)
5726 /* We found a bad expression in md_operand(). */
5727 *str
= input_line_pointer
;
5728 input_line_pointer
= save_in
;
5733 if (seg
!= absolute_section
5734 && seg
!= text_section
5735 && seg
!= data_section
5736 && seg
!= bss_section
5737 && seg
!= undefined_section
)
5739 inst
.error
= _("bad_segment");
5740 *str
= input_line_pointer
;
5741 input_line_pointer
= save_in
;
5746 /* Get rid of any bignums now, so that we don't generate an error for which
5747 we can't establish a line number later on. Big numbers are never valid
5748 in instructions, which is where this routine is always called. */
5749 if (ep
->X_op
== O_big
5750 || (ep
->X_add_symbol
5751 && (walk_no_bignums (ep
->X_add_symbol
)
5753 && walk_no_bignums (ep
->X_op_symbol
)))))
5755 inst
.error
= _("invalid constant");
5756 *str
= input_line_pointer
;
5757 input_line_pointer
= save_in
;
5761 *str
= input_line_pointer
;
5762 input_line_pointer
= save_in
;
5766 /* We handle all bad expressions here, so that we can report the faulty
5767 instruction in the error message. */
5772 if (in_my_get_expression
)
5774 expr
->X_op
= O_illegal
;
5775 if (inst
.error
== NULL
)
5776 inst
.error
= _("bad expression");
5780 /* UNRESTRICT should be one if <shift> <register> is permitted for this
5784 decode_shift (str
, unrestrict
)
5788 const struct asm_shift_name
* shift
;
5792 skip_whitespace (* str
);
5794 for (p
= * str
; ISALPHA (* p
); p
++)
5799 inst
.error
= _("shift expression expected");
5805 shift
= (const struct asm_shift_name
*) hash_find (arm_shift_hsh
, * str
);
5810 inst
.error
= _("shift expression expected");
5814 assert (shift
->properties
->index
== shift_properties
[shift
->properties
->index
].index
);
5816 if (shift
->properties
->index
== SHIFT_RRX
)
5819 inst
.instruction
|= shift
->properties
->bit_field
;
5823 skip_whitespace (p
);
5825 if (unrestrict
&& reg_required_here (& p
, 8) != FAIL
)
5827 inst
.instruction
|= shift
->properties
->bit_field
| SHIFT_BY_REG
;
5831 else if (! is_immediate_prefix (* p
))
5833 inst
.error
= (unrestrict
5834 ? _("shift requires register or #expression")
5835 : _("shift requires #expression"));
5843 if (my_get_expression (& inst
.reloc
.exp
, & p
))
5846 /* Validate some simple #expressions. */
5847 if (inst
.reloc
.exp
.X_op
== O_constant
)
5849 unsigned num
= inst
.reloc
.exp
.X_add_number
;
5851 /* Reject operations greater than 32. */
5853 /* Reject a shift of 0 unless the mode allows it. */
5854 || (num
== 0 && shift
->properties
->allows_0
== 0)
5855 /* Reject a shift of 32 unless the mode allows it. */
5856 || (num
== 32 && shift
->properties
->allows_32
== 0)
5859 /* As a special case we allow a shift of zero for
5860 modes that do not support it to be recoded as an
5861 logical shift left of zero (ie nothing). We warn
5862 about this though. */
5865 as_warn (_("shift of 0 ignored."));
5866 shift
= & shift_names
[0];
5867 assert (shift
->properties
->index
== SHIFT_LSL
);
5871 inst
.error
= _("invalid immediate shift");
5876 /* Shifts of 32 are encoded as 0, for those shifts that
5881 inst
.instruction
|= (num
<< 7) | shift
->properties
->bit_field
;
5885 inst
.reloc
.type
= BFD_RELOC_ARM_SHIFT_IMM
;
5886 inst
.reloc
.pc_rel
= 0;
5887 inst
.instruction
|= shift
->properties
->bit_field
;
5894 /* Do those data_ops which can take a negative immediate constant
5895 by altering the instruction. A bit of a hack really.
5899 by inverting the second operand, and
5902 by negating the second operand. */
5905 negate_data_op (instruction
, value
)
5906 unsigned long * instruction
;
5907 unsigned long value
;
5910 unsigned long negated
, inverted
;
5912 negated
= validate_immediate (-value
);
5913 inverted
= validate_immediate (~value
);
5915 op
= (*instruction
>> DATA_OP_SHIFT
) & 0xf;
5918 /* First negates. */
5919 case OPCODE_SUB
: /* ADD <-> SUB */
5920 new_inst
= OPCODE_ADD
;
5925 new_inst
= OPCODE_SUB
;
5929 case OPCODE_CMP
: /* CMP <-> CMN */
5930 new_inst
= OPCODE_CMN
;
5935 new_inst
= OPCODE_CMP
;
5939 /* Now Inverted ops. */
5940 case OPCODE_MOV
: /* MOV <-> MVN */
5941 new_inst
= OPCODE_MVN
;
5946 new_inst
= OPCODE_MOV
;
5950 case OPCODE_AND
: /* AND <-> BIC */
5951 new_inst
= OPCODE_BIC
;
5956 new_inst
= OPCODE_AND
;
5960 case OPCODE_ADC
: /* ADC <-> SBC */
5961 new_inst
= OPCODE_SBC
;
5966 new_inst
= OPCODE_ADC
;
5970 /* We cannot do anything. */
5975 if (value
== (unsigned) FAIL
)
5978 *instruction
&= OPCODE_MASK
;
5979 *instruction
|= new_inst
<< DATA_OP_SHIFT
;
5990 skip_whitespace (* str
);
5992 if (reg_required_here (str
, 0) != FAIL
)
5994 if (skip_past_comma (str
) == SUCCESS
)
5995 /* Shift operation on register. */
5996 return decode_shift (str
, NO_SHIFT_RESTRICT
);
6002 /* Immediate expression. */
6003 if (is_immediate_prefix (**str
))
6008 if (my_get_expression (&inst
.reloc
.exp
, str
))
6011 if (inst
.reloc
.exp
.X_add_symbol
)
6013 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
6014 inst
.reloc
.pc_rel
= 0;
6018 if (skip_past_comma (str
) == SUCCESS
)
6020 /* #x, y -- ie explicit rotation by Y. */
6021 if (my_get_expression (&expr
, str
))
6024 if (expr
.X_op
!= O_constant
)
6026 inst
.error
= _("constant expression expected");
6030 /* Rotate must be a multiple of 2. */
6031 if (((unsigned) expr
.X_add_number
) > 30
6032 || (expr
.X_add_number
& 1) != 0
6033 || ((unsigned) inst
.reloc
.exp
.X_add_number
) > 255)
6035 inst
.error
= _("invalid constant");
6038 inst
.instruction
|= INST_IMMEDIATE
;
6039 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
6040 inst
.instruction
|= expr
.X_add_number
<< 7;
6044 /* Implicit rotation, select a suitable one. */
6045 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
6049 /* Can't be done. Perhaps the code reads something like
6050 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
6051 if ((value
= negate_data_op (&inst
.instruction
,
6052 inst
.reloc
.exp
.X_add_number
))
6055 inst
.error
= _("invalid constant");
6060 inst
.instruction
|= value
;
6063 inst
.instruction
|= INST_IMMEDIATE
;
6068 inst
.error
= _("register or shift expression expected");
6077 skip_whitespace (* str
);
6079 if (fp_reg_required_here (str
, 0) != FAIL
)
6083 /* Immediate expression. */
6084 if (*((*str
)++) == '#')
6090 skip_whitespace (* str
);
6092 /* First try and match exact strings, this is to guarantee
6093 that some formats will work even for cross assembly. */
6095 for (i
= 0; fp_const
[i
]; i
++)
6097 if (strncmp (*str
, fp_const
[i
], strlen (fp_const
[i
])) == 0)
6101 *str
+= strlen (fp_const
[i
]);
6102 if (is_end_of_line
[(unsigned char) **str
])
6104 inst
.instruction
|= i
+ 8;
6111 /* Just because we didn't get a match doesn't mean that the
6112 constant isn't valid, just that it is in a format that we
6113 don't automatically recognize. Try parsing it with
6114 the standard expression routines. */
6115 if ((i
= my_get_float_expression (str
)) >= 0)
6117 inst
.instruction
|= i
+ 8;
6121 inst
.error
= _("invalid floating point immediate expression");
6125 _("floating point register or immediate expression expected");
6134 skip_whitespace (str
);
6136 if (reg_required_here (&str
, 12) == FAIL
6137 || skip_past_comma (&str
) == FAIL
6138 || reg_required_here (&str
, 16) == FAIL
6139 || skip_past_comma (&str
) == FAIL
6140 || data_op2 (&str
) == FAIL
)
6143 inst
.error
= BAD_ARGS
;
6155 /* This is a pseudo-op of the form "adr rd, label" to be converted
6156 into a relative address of the form "add rd, pc, #label-.-8". */
6157 skip_whitespace (str
);
6159 if (reg_required_here (&str
, 12) == FAIL
6160 || skip_past_comma (&str
) == FAIL
6161 || my_get_expression (&inst
.reloc
.exp
, &str
))
6164 inst
.error
= BAD_ARGS
;
6168 /* Frag hacking will turn this into a sub instruction if the offset turns
6169 out to be negative. */
6170 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
6171 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust. */
6172 inst
.reloc
.pc_rel
= 1;
6181 /* This is a pseudo-op of the form "adrl rd, label" to be converted
6182 into a relative address of the form:
6183 add rd, pc, #low(label-.-8)"
6184 add rd, rd, #high(label-.-8)" */
6186 skip_whitespace (str
);
6188 if (reg_required_here (&str
, 12) == FAIL
6189 || skip_past_comma (&str
) == FAIL
6190 || my_get_expression (&inst
.reloc
.exp
, &str
))
6193 inst
.error
= BAD_ARGS
;
6199 /* Frag hacking will turn this into a sub instruction if the offset turns
6200 out to be negative. */
6201 inst
.reloc
.type
= BFD_RELOC_ARM_ADRL_IMMEDIATE
;
6202 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust */
6203 inst
.reloc
.pc_rel
= 1;
6204 inst
.size
= INSN_SIZE
* 2;
6213 skip_whitespace (str
);
6215 if (reg_required_here (&str
, 16) == FAIL
)
6218 inst
.error
= BAD_ARGS
;
6222 if (skip_past_comma (&str
) == FAIL
6223 || data_op2 (&str
) == FAIL
)
6226 inst
.error
= BAD_ARGS
;
6238 skip_whitespace (str
);
6240 if (reg_required_here (&str
, 12) == FAIL
)
6243 inst
.error
= BAD_ARGS
;
6247 if (skip_past_comma (&str
) == FAIL
6248 || data_op2 (&str
) == FAIL
)
6251 inst
.error
= BAD_ARGS
;
6270 if (my_get_expression (& inst
.reloc
.exp
, str
))
6273 if (inst
.reloc
.exp
.X_op
== O_constant
)
6275 int value
= inst
.reloc
.exp
.X_add_number
;
6277 if (value
< -4095 || value
> 4095)
6279 inst
.error
= _("address offset too large");
6289 inst
.instruction
|= add
| value
;
6293 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
6294 inst
.reloc
.pc_rel
= 0;
6307 if (reg_required_here (str
, 0) == FAIL
)
6310 inst
.instruction
|= add
| OFFSET_REG
;
6311 if (skip_past_comma (str
) == SUCCESS
)
6312 return decode_shift (str
, SHIFT_RESTRICT
);
6326 skip_whitespace (str
);
6328 if ((conflict_reg
= reg_required_here (&str
, 12)) == FAIL
)
6331 inst
.error
= BAD_ARGS
;
6335 if (skip_past_comma (&str
) == FAIL
)
6337 inst
.error
= _("address expected");
6347 skip_whitespace (str
);
6349 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6352 /* Conflicts can occur on stores as well as loads. */
6353 conflict_reg
= (conflict_reg
== reg
);
6355 skip_whitespace (str
);
6361 if (skip_past_comma (&str
) == SUCCESS
)
6363 /* [Rn],... (post inc) */
6364 if (ldst_extend (&str
) == FAIL
)
6367 as_warn (_("%s register same as write-back base"),
6368 ((inst
.instruction
& LOAD_BIT
)
6369 ? _("destination") : _("source")));
6374 skip_whitespace (str
);
6379 as_warn (_("%s register same as write-back base"),
6380 ((inst
.instruction
& LOAD_BIT
)
6381 ? _("destination") : _("source")));
6383 inst
.instruction
|= WRITE_BACK
;
6386 inst
.instruction
|= INDEX_UP
;
6393 if (skip_past_comma (&str
) == FAIL
)
6395 inst
.error
= _("pre-indexed expression expected");
6400 if (ldst_extend (&str
) == FAIL
)
6403 skip_whitespace (str
);
6407 inst
.error
= _("missing ]");
6411 skip_whitespace (str
);
6416 as_warn (_("%s register same as write-back base"),
6417 ((inst
.instruction
& LOAD_BIT
)
6418 ? _("destination") : _("source")));
6420 inst
.instruction
|= WRITE_BACK
;
6424 else if (*str
== '=')
6426 if ((inst
.instruction
& LOAD_BIT
) == 0)
6428 inst
.error
= _("invalid pseudo operation");
6432 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6435 skip_whitespace (str
);
6437 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6440 if (inst
.reloc
.exp
.X_op
!= O_constant
6441 && inst
.reloc
.exp
.X_op
!= O_symbol
)
6443 inst
.error
= _("constant expression expected");
6447 if (inst
.reloc
.exp
.X_op
== O_constant
)
6449 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
6453 /* This can be done with a mov instruction. */
6454 inst
.instruction
&= LITERAL_MASK
;
6455 inst
.instruction
|= (INST_IMMEDIATE
6456 | (OPCODE_MOV
<< DATA_OP_SHIFT
));
6457 inst
.instruction
|= value
& 0xfff;
6462 value
= validate_immediate (~inst
.reloc
.exp
.X_add_number
);
6466 /* This can be done with a mvn instruction. */
6467 inst
.instruction
&= LITERAL_MASK
;
6468 inst
.instruction
|= (INST_IMMEDIATE
6469 | (OPCODE_MVN
<< DATA_OP_SHIFT
));
6470 inst
.instruction
|= value
& 0xfff;
6476 /* Insert into literal pool. */
6477 if (add_to_lit_pool () == FAIL
)
6480 inst
.error
= _("literal pool insertion failed");
6484 /* Change the instruction exp to point to the pool. */
6485 inst
.reloc
.type
= BFD_RELOC_ARM_LITERAL
;
6486 inst
.reloc
.pc_rel
= 1;
6487 inst
.instruction
|= (REG_PC
<< 16);
6492 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6495 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
6497 /* PC rel adjust. */
6498 inst
.reloc
.exp
.X_add_number
-= 8;
6500 inst
.reloc
.pc_rel
= 1;
6501 inst
.instruction
|= (REG_PC
<< 16);
6505 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
6516 skip_whitespace (str
);
6518 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
6521 inst
.error
= BAD_ARGS
;
6525 if (skip_past_comma (& str
) == FAIL
)
6527 inst
.error
= _("address expected");
6537 skip_whitespace (str
);
6539 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6542 /* ldrt/strt always use post-indexed addressing, so if the base is
6543 the same as Rd, we warn. */
6544 if (conflict_reg
== reg
)
6545 as_warn (_("%s register same as write-back base"),
6546 ((inst
.instruction
& LOAD_BIT
)
6547 ? _("destination") : _("source")));
6549 skip_whitespace (str
);
6555 if (skip_past_comma (&str
) == SUCCESS
)
6557 /* [Rn],... (post inc) */
6558 if (ldst_extend (&str
) == FAIL
)
6564 skip_whitespace (str
);
6566 /* Skip a write-back '!'. */
6570 inst
.instruction
|= INDEX_UP
;
6575 inst
.error
= _("post-indexed expression expected");
6581 inst
.error
= _("post-indexed expression expected");
6590 ldst_extend_v4 (str
)
6600 if (my_get_expression (& inst
.reloc
.exp
, str
))
6603 if (inst
.reloc
.exp
.X_op
== O_constant
)
6605 int value
= inst
.reloc
.exp
.X_add_number
;
6607 if (value
< -255 || value
> 255)
6609 inst
.error
= _("address offset too large");
6619 /* Halfword and signextension instructions have the
6620 immediate value split across bits 11..8 and bits 3..0. */
6621 inst
.instruction
|= (add
| HWOFFSET_IMM
6622 | ((value
>> 4) << 8) | (value
& 0xF));
6626 inst
.instruction
|= HWOFFSET_IMM
;
6627 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
6628 inst
.reloc
.pc_rel
= 0;
6641 if (reg_required_here (str
, 0) == FAIL
)
6644 inst
.instruction
|= add
;
6649 /* Halfword and signed-byte load/store operations. */
6658 skip_whitespace (str
);
6660 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
6663 inst
.error
= BAD_ARGS
;
6667 if (skip_past_comma (& str
) == FAIL
)
6669 inst
.error
= _("address expected");
6679 skip_whitespace (str
);
6681 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6684 /* Conflicts can occur on stores as well as loads. */
6685 conflict_reg
= (conflict_reg
== reg
);
6687 skip_whitespace (str
);
6693 if (skip_past_comma (&str
) == SUCCESS
)
6695 /* [Rn],... (post inc) */
6696 if (ldst_extend_v4 (&str
) == FAIL
)
6699 as_warn (_("%s register same as write-back base"),
6700 ((inst
.instruction
& LOAD_BIT
)
6701 ? _("destination") : _("source")));
6706 inst
.instruction
|= HWOFFSET_IMM
;
6708 skip_whitespace (str
);
6713 as_warn (_("%s register same as write-back base"),
6714 ((inst
.instruction
& LOAD_BIT
)
6715 ? _("destination") : _("source")));
6717 inst
.instruction
|= WRITE_BACK
;
6720 inst
.instruction
|= INDEX_UP
;
6727 if (skip_past_comma (&str
) == FAIL
)
6729 inst
.error
= _("pre-indexed expression expected");
6734 if (ldst_extend_v4 (&str
) == FAIL
)
6737 skip_whitespace (str
);
6741 inst
.error
= _("missing ]");
6745 skip_whitespace (str
);
6750 as_warn (_("%s register same as write-back base"),
6751 ((inst
.instruction
& LOAD_BIT
)
6752 ? _("destination") : _("source")));
6754 inst
.instruction
|= WRITE_BACK
;
6758 else if (*str
== '=')
6760 if ((inst
.instruction
& LOAD_BIT
) == 0)
6762 inst
.error
= _("invalid pseudo operation");
6766 /* XXX Does this work correctly for half-word/byte ops? */
6767 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6770 skip_whitespace (str
);
6772 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6775 if (inst
.reloc
.exp
.X_op
!= O_constant
6776 && inst
.reloc
.exp
.X_op
!= O_symbol
)
6778 inst
.error
= _("constant expression expected");
6782 if (inst
.reloc
.exp
.X_op
== O_constant
)
6784 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
6788 /* This can be done with a mov instruction. */
6789 inst
.instruction
&= LITERAL_MASK
;
6790 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MOV
<< DATA_OP_SHIFT
);
6791 inst
.instruction
|= value
& 0xfff;
6796 value
= validate_immediate (~ inst
.reloc
.exp
.X_add_number
);
6800 /* This can be done with a mvn instruction. */
6801 inst
.instruction
&= LITERAL_MASK
;
6802 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MVN
<< DATA_OP_SHIFT
);
6803 inst
.instruction
|= value
& 0xfff;
6809 /* Insert into literal pool. */
6810 if (add_to_lit_pool () == FAIL
)
6813 inst
.error
= _("literal pool insertion failed");
6817 /* Change the instruction exp to point to the pool. */
6818 inst
.instruction
|= HWOFFSET_IMM
;
6819 inst
.reloc
.type
= BFD_RELOC_ARM_HWLITERAL
;
6820 inst
.reloc
.pc_rel
= 1;
6821 inst
.instruction
|= (REG_PC
<< 16);
6826 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6829 inst
.instruction
|= HWOFFSET_IMM
;
6830 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
6832 /* PC rel adjust. */
6833 inst
.reloc
.exp
.X_add_number
-= 8;
6835 inst
.reloc
.pc_rel
= 1;
6836 inst
.instruction
|= (REG_PC
<< 16);
6840 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
6849 char * str
= * strp
;
6853 /* We come back here if we get ranges concatenated by '+' or '|'. */
6868 skip_whitespace (str
);
6870 if ((reg
= reg_required_here (& str
, -1)) == FAIL
)
6879 inst
.error
= _("bad range in register list");
6883 for (i
= cur_reg
+ 1; i
< reg
; i
++)
6885 if (range
& (1 << i
))
6887 (_("Warning: duplicated register (r%d) in register list"),
6895 if (range
& (1 << reg
))
6896 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
6898 else if (reg
<= cur_reg
)
6899 as_tsktsk (_("Warning: register range not in ascending order"));
6904 while (skip_past_comma (&str
) != FAIL
6905 || (in_range
= 1, *str
++ == '-'));
6907 skip_whitespace (str
);
6911 inst
.error
= _("missing `}'");
6919 if (my_get_expression (&expr
, &str
))
6922 if (expr
.X_op
== O_constant
)
6924 if (expr
.X_add_number
6925 != (expr
.X_add_number
& 0x0000ffff))
6927 inst
.error
= _("invalid register mask");
6931 if ((range
& expr
.X_add_number
) != 0)
6933 int regno
= range
& expr
.X_add_number
;
6936 regno
= (1 << regno
) - 1;
6938 (_("Warning: duplicated register (r%d) in register list"),
6942 range
|= expr
.X_add_number
;
6946 if (inst
.reloc
.type
!= 0)
6948 inst
.error
= _("expression too complex");
6952 memcpy (&inst
.reloc
.exp
, &expr
, sizeof (expressionS
));
6953 inst
.reloc
.type
= BFD_RELOC_ARM_MULTI
;
6954 inst
.reloc
.pc_rel
= 0;
6958 skip_whitespace (str
);
6960 if (*str
== '|' || *str
== '+')
6966 while (another_range
);
6979 skip_whitespace (str
);
6981 if ((base_reg
= reg_required_here (&str
, 16)) == FAIL
)
6984 if (base_reg
== REG_PC
)
6986 inst
.error
= _("r15 not allowed as base register");
6990 skip_whitespace (str
);
6994 inst
.instruction
|= WRITE_BACK
;
6998 if (skip_past_comma (&str
) == FAIL
6999 || (range
= reg_list (&str
)) == FAIL
)
7002 inst
.error
= BAD_ARGS
;
7009 inst
.instruction
|= LDM_TYPE_2_OR_3
;
7012 if (inst
.instruction
& WRITE_BACK
)
7014 /* Check for unpredictable uses of writeback. */
7015 if (inst
.instruction
& LOAD_BIT
)
7017 /* Not allowed in LDM type 2. */
7018 if ((inst
.instruction
& LDM_TYPE_2_OR_3
)
7019 && ((range
& (1 << REG_PC
)) == 0))
7020 as_warn (_("writeback of base register is UNPREDICTABLE"));
7021 /* Only allowed if base reg not in list for other types. */
7022 else if (range
& (1 << base_reg
))
7023 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
7027 /* Not allowed for type 2. */
7028 if (inst
.instruction
& LDM_TYPE_2_OR_3
)
7029 as_warn (_("writeback of base register is UNPREDICTABLE"));
7030 /* Only allowed if base reg not in list, or first in list. */
7031 else if ((range
& (1 << base_reg
))
7032 && (range
& ((1 << base_reg
) - 1)))
7033 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
7037 inst
.instruction
|= range
;
7046 skip_whitespace (str
);
7048 /* Allow optional leading '#'. */
7049 if (is_immediate_prefix (*str
))
7052 if (my_get_expression (& inst
.reloc
.exp
, & str
))
7055 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
7056 inst
.reloc
.pc_rel
= 0;
7068 skip_whitespace (str
);
7070 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
7075 inst
.error
= _("r15 not allowed in swap");
7079 if (skip_past_comma (&str
) == FAIL
7080 || (reg
= reg_required_here (&str
, 0)) == FAIL
)
7083 inst
.error
= BAD_ARGS
;
7089 inst
.error
= _("r15 not allowed in swap");
7093 if (skip_past_comma (&str
) == FAIL
7096 inst
.error
= BAD_ARGS
;
7100 skip_whitespace (str
);
7102 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
7107 inst
.error
= BAD_PC
;
7111 skip_whitespace (str
);
7115 inst
.error
= _("missing ]");
7127 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7134 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
7135 required for the instruction. */
7137 /* arm_parse_reloc () works on input_line_pointer.
7138 We actually want to parse the operands to the branch instruction
7139 passed in 'str'. Save the input pointer and restore it later. */
7140 save_in
= input_line_pointer
;
7141 input_line_pointer
= str
;
7142 if (inst
.reloc
.exp
.X_op
== O_symbol
7144 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
7146 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
7147 inst
.reloc
.pc_rel
= 0;
7148 /* Modify str to point to after parsed operands, otherwise
7149 end_of_line() will complain about the (PLT) left in str. */
7150 str
= input_line_pointer
;
7154 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
7155 inst
.reloc
.pc_rel
= 1;
7157 input_line_pointer
= save_in
;
7160 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
7161 inst
.reloc
.pc_rel
= 1;
7162 #endif /* OBJ_ELF */
7174 skip_whitespace (str
);
7176 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
7178 inst
.error
= BAD_ARGS
;
7182 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
7184 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
7193 /* Co-processor data operation.
7194 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
7195 skip_whitespace (str
);
7197 if (co_proc_number (&str
) == FAIL
)
7200 inst
.error
= BAD_ARGS
;
7204 if (skip_past_comma (&str
) == FAIL
7205 || cp_opc_expr (&str
, 20,4) == FAIL
)
7208 inst
.error
= BAD_ARGS
;
7212 if (skip_past_comma (&str
) == FAIL
7213 || cp_reg_required_here (&str
, 12) == FAIL
)
7216 inst
.error
= BAD_ARGS
;
7220 if (skip_past_comma (&str
) == FAIL
7221 || cp_reg_required_here (&str
, 16) == FAIL
)
7224 inst
.error
= BAD_ARGS
;
7228 if (skip_past_comma (&str
) == FAIL
7229 || cp_reg_required_here (&str
, 0) == FAIL
)
7232 inst
.error
= BAD_ARGS
;
7236 if (skip_past_comma (&str
) == SUCCESS
)
7238 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
7241 inst
.error
= BAD_ARGS
;
7254 /* Co-processor register load/store.
7255 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
7257 skip_whitespace (str
);
7259 if (co_proc_number (&str
) == FAIL
)
7262 inst
.error
= BAD_ARGS
;
7266 if (skip_past_comma (&str
) == FAIL
7267 || cp_reg_required_here (&str
, 12) == FAIL
)
7270 inst
.error
= BAD_ARGS
;
7274 if (skip_past_comma (&str
) == FAIL
7275 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
7278 inst
.error
= BAD_ARGS
;
7290 /* Co-processor register transfer.
7291 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
7293 skip_whitespace (str
);
7295 if (co_proc_number (&str
) == FAIL
)
7298 inst
.error
= BAD_ARGS
;
7302 if (skip_past_comma (&str
) == FAIL
7303 || cp_opc_expr (&str
, 21, 3) == FAIL
)
7306 inst
.error
= BAD_ARGS
;
7310 if (skip_past_comma (&str
) == FAIL
7311 || reg_required_here (&str
, 12) == FAIL
)
7314 inst
.error
= BAD_ARGS
;
7318 if (skip_past_comma (&str
) == FAIL
7319 || cp_reg_required_here (&str
, 16) == FAIL
)
7322 inst
.error
= BAD_ARGS
;
7326 if (skip_past_comma (&str
) == FAIL
7327 || cp_reg_required_here (&str
, 0) == FAIL
)
7330 inst
.error
= BAD_ARGS
;
7334 if (skip_past_comma (&str
) == SUCCESS
)
7336 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
7339 inst
.error
= BAD_ARGS
;
7352 /* FP control registers.
7353 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
7355 skip_whitespace (str
);
7357 if (reg_required_here (&str
, 12) == FAIL
)
7360 inst
.error
= BAD_ARGS
;
7372 skip_whitespace (str
);
7374 if (fp_reg_required_here (&str
, 12) == FAIL
)
7377 inst
.error
= BAD_ARGS
;
7381 if (skip_past_comma (&str
) == FAIL
7382 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
7385 inst
.error
= BAD_ARGS
;
7398 skip_whitespace (str
);
7400 if (fp_reg_required_here (&str
, 12) == FAIL
)
7403 inst
.error
= BAD_ARGS
;
7407 /* Get Number of registers to transfer. */
7408 if (skip_past_comma (&str
) == FAIL
7409 || my_get_expression (&inst
.reloc
.exp
, &str
))
7412 inst
.error
= _("constant expression expected");
7416 if (inst
.reloc
.exp
.X_op
!= O_constant
)
7418 inst
.error
= _("constant value required for number of registers");
7422 num_regs
= inst
.reloc
.exp
.X_add_number
;
7424 if (num_regs
< 1 || num_regs
> 4)
7426 inst
.error
= _("number of registers must be in the range [1:4]");
7433 inst
.instruction
|= CP_T_X
;
7436 inst
.instruction
|= CP_T_Y
;
7439 inst
.instruction
|= CP_T_Y
| CP_T_X
;
7447 if (inst
.instruction
& (CP_T_Pre
| CP_T_UD
)) /* ea/fd format. */
7453 /* The instruction specified "ea" or "fd", so we can only accept
7454 [Rn]{!}. The instruction does not really support stacking or
7455 unstacking, so we have to emulate these by setting appropriate
7456 bits and offsets. */
7457 if (skip_past_comma (&str
) == FAIL
7461 inst
.error
= BAD_ARGS
;
7466 skip_whitespace (str
);
7468 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
7471 skip_whitespace (str
);
7475 inst
.error
= BAD_ARGS
;
7487 _("r15 not allowed as base register with write-back");
7494 if (inst
.instruction
& CP_T_Pre
)
7496 /* Pre-decrement. */
7497 offset
= 3 * num_regs
;
7499 inst
.instruction
|= CP_T_WB
;
7503 /* Post-increment. */
7506 inst
.instruction
|= CP_T_WB
;
7507 offset
= 3 * num_regs
;
7511 /* No write-back, so convert this into a standard pre-increment
7512 instruction -- aesthetically more pleasing. */
7513 inst
.instruction
|= CP_T_Pre
| CP_T_UD
;
7518 inst
.instruction
|= offset
;
7520 else if (skip_past_comma (&str
) == FAIL
7521 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
7524 inst
.error
= BAD_ARGS
;
7535 skip_whitespace (str
);
7537 if (fp_reg_required_here (&str
, 12) == FAIL
)
7540 inst
.error
= BAD_ARGS
;
7544 if (skip_past_comma (&str
) == FAIL
7545 || fp_reg_required_here (&str
, 16) == FAIL
)
7548 inst
.error
= BAD_ARGS
;
7552 if (skip_past_comma (&str
) == FAIL
7553 || fp_op2 (&str
) == FAIL
)
7556 inst
.error
= BAD_ARGS
;
7565 do_fpa_monadic (str
)
7568 skip_whitespace (str
);
7570 if (fp_reg_required_here (&str
, 12) == FAIL
)
7573 inst
.error
= BAD_ARGS
;
7577 if (skip_past_comma (&str
) == FAIL
7578 || fp_op2 (&str
) == FAIL
)
7581 inst
.error
= BAD_ARGS
;
7593 skip_whitespace (str
);
7595 if (fp_reg_required_here (&str
, 16) == FAIL
)
7598 inst
.error
= BAD_ARGS
;
7602 if (skip_past_comma (&str
) == FAIL
7603 || fp_op2 (&str
) == FAIL
)
7606 inst
.error
= BAD_ARGS
;
7615 do_fpa_from_reg (str
)
7618 skip_whitespace (str
);
7620 if (fp_reg_required_here (&str
, 16) == FAIL
)
7623 inst
.error
= BAD_ARGS
;
7627 if (skip_past_comma (&str
) == FAIL
7628 || reg_required_here (&str
, 12) == FAIL
)
7631 inst
.error
= BAD_ARGS
;
7643 skip_whitespace (str
);
7645 if (reg_required_here (&str
, 12) == FAIL
)
7648 if (skip_past_comma (&str
) == FAIL
7649 || fp_reg_required_here (&str
, 0) == FAIL
)
7652 inst
.error
= BAD_ARGS
;
7661 vfp_sp_reg_required_here (str
, pos
)
7663 enum vfp_sp_reg_pos pos
;
7668 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_SN
].htab
)) != FAIL
)
7673 inst
.instruction
|= ((reg
>> 1) << 12) | ((reg
& 1) << 22);
7677 inst
.instruction
|= ((reg
>> 1) << 16) | ((reg
& 1) << 7);
7681 inst
.instruction
|= ((reg
>> 1) << 0) | ((reg
& 1) << 5);
7690 /* In the few cases where we might be able to accept something else
7691 this error can be overridden. */
7692 inst
.error
= _(all_reg_maps
[REG_TYPE_SN
].expected
);
7694 /* Restore the start point. */
7700 vfp_dp_reg_required_here (str
, pos
)
7702 enum vfp_dp_reg_pos pos
;
7707 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_DN
].htab
)) != FAIL
)
7712 inst
.instruction
|= reg
<< 12;
7716 inst
.instruction
|= reg
<< 16;
7720 inst
.instruction
|= reg
<< 0;
7729 /* In the few cases where we might be able to accept something else
7730 this error can be overridden. */
7731 inst
.error
= _(all_reg_maps
[REG_TYPE_DN
].expected
);
7733 /* Restore the start point. */
7739 do_vfp_sp_monadic (str
)
7742 skip_whitespace (str
);
7744 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7747 if (skip_past_comma (&str
) == FAIL
7748 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
7751 inst
.error
= BAD_ARGS
;
7760 do_vfp_dp_monadic (str
)
7763 skip_whitespace (str
);
7765 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7768 if (skip_past_comma (&str
) == FAIL
7769 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7772 inst
.error
= BAD_ARGS
;
7781 do_vfp_sp_dyadic (str
)
7784 skip_whitespace (str
);
7786 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7789 if (skip_past_comma (&str
) == FAIL
7790 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
7791 || skip_past_comma (&str
) == FAIL
7792 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
7795 inst
.error
= BAD_ARGS
;
7804 do_vfp_dp_dyadic (str
)
7807 skip_whitespace (str
);
7809 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7812 if (skip_past_comma (&str
) == FAIL
7813 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
7814 || skip_past_comma (&str
) == FAIL
7815 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7818 inst
.error
= BAD_ARGS
;
7827 do_vfp_reg_from_sp (str
)
7830 skip_whitespace (str
);
7832 if (reg_required_here (&str
, 12) == FAIL
)
7835 if (skip_past_comma (&str
) == FAIL
7836 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
7839 inst
.error
= BAD_ARGS
;
7848 do_vfp_sp_reg2 (str
)
7851 skip_whitespace (str
);
7853 if (reg_required_here (&str
, 12) == FAIL
)
7856 if (skip_past_comma (&str
) == FAIL
7857 || reg_required_here (&str
, 16) == FAIL
7858 || skip_past_comma (&str
) == FAIL
)
7861 inst
.error
= BAD_ARGS
;
7865 /* We require exactly two consecutive SP registers. */
7866 if (vfp_sp_reg_list (&str
, VFP_REG_Sm
) != 2)
7869 inst
.error
= _("only two consecutive VFP SP registers allowed here");
7877 do_vfp_sp_from_reg (str
)
7880 skip_whitespace (str
);
7882 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
7885 if (skip_past_comma (&str
) == FAIL
7886 || reg_required_here (&str
, 12) == FAIL
)
7889 inst
.error
= BAD_ARGS
;
7898 do_vfp_reg_from_dp (str
)
7901 skip_whitespace (str
);
7903 if (reg_required_here (&str
, 12) == FAIL
)
7906 if (skip_past_comma (&str
) == FAIL
7907 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
7910 inst
.error
= BAD_ARGS
;
7919 do_vfp_reg2_from_dp (str
)
7922 skip_whitespace (str
);
7924 if (reg_required_here (&str
, 12) == FAIL
)
7927 if (skip_past_comma (&str
) == FAIL
7928 || reg_required_here (&str
, 16) == FAIL
7929 || skip_past_comma (&str
) == FAIL
7930 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7933 inst
.error
= BAD_ARGS
;
7942 do_vfp_dp_from_reg (str
)
7945 skip_whitespace (str
);
7947 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
7950 if (skip_past_comma (&str
) == FAIL
7951 || reg_required_here (&str
, 12) == FAIL
)
7954 inst
.error
= BAD_ARGS
;
7963 do_vfp_dp_from_reg2 (str
)
7966 skip_whitespace (str
);
7968 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7971 if (skip_past_comma (&str
) == FAIL
7972 || reg_required_here (&str
, 12) == FAIL
7973 || skip_past_comma (&str
) == FAIL
7974 || reg_required_here (&str
, 16))
7977 inst
.error
= BAD_ARGS
;
7985 static const struct vfp_reg
*
7992 const struct vfp_reg
*vreg
;
7996 /* Find the end of the current token. */
8001 while (ISALPHA (c
));
8006 for (vreg
= vfp_regs
+ 0;
8007 vreg
< vfp_regs
+ sizeof (vfp_regs
) / sizeof (struct vfp_reg
);
8010 if (strcmp (start
, vreg
->name
) == 0)
8023 vfp_psr_required_here (str
)
8027 const struct vfp_reg
*vreg
;
8029 vreg
= vfp_psr_parse (str
);
8033 inst
.instruction
|= vreg
->regno
;
8037 inst
.error
= _("VFP system register expected");
8044 do_vfp_reg_from_ctrl (str
)
8047 skip_whitespace (str
);
8049 if (reg_required_here (&str
, 12) == FAIL
)
8052 if (skip_past_comma (&str
) == FAIL
8053 || vfp_psr_required_here (&str
) == FAIL
)
8056 inst
.error
= BAD_ARGS
;
8065 do_vfp_ctrl_from_reg (str
)
8068 skip_whitespace (str
);
8070 if (vfp_psr_required_here (&str
) == FAIL
)
8073 if (skip_past_comma (&str
) == FAIL
8074 || reg_required_here (&str
, 12) == FAIL
)
8077 inst
.error
= BAD_ARGS
;
8086 do_vfp_sp_ldst (str
)
8089 skip_whitespace (str
);
8091 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8094 inst
.error
= BAD_ARGS
;
8098 if (skip_past_comma (&str
) == FAIL
8099 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
8102 inst
.error
= BAD_ARGS
;
8111 do_vfp_dp_ldst (str
)
8114 skip_whitespace (str
);
8116 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8119 inst
.error
= BAD_ARGS
;
8123 if (skip_past_comma (&str
) == FAIL
8124 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
8127 inst
.error
= BAD_ARGS
;
8135 /* Parse and encode a VFP SP register list, storing the initial
8136 register in position POS and returning the range as the result. If
8137 the string is invalid return FAIL (an invalid range). */
8139 vfp_sp_reg_list (str
, pos
)
8141 enum vfp_sp_reg_pos pos
;
8149 unsigned long mask
= 0;
8156 skip_whitespace (*str
);
8158 tempinst
= inst
.instruction
;
8162 inst
.instruction
= 0;
8164 if ((new_base
= vfp_sp_reg_required_here (str
, pos
)) == FAIL
)
8167 if (count
== 0 || base_reg
> new_base
)
8169 base_reg
= new_base
;
8170 base_bits
= inst
.instruction
;
8173 if (mask
& (1 << new_base
))
8175 inst
.error
= _("invalid register list");
8179 if ((mask
>> new_base
) != 0 && ! warned
)
8181 as_tsktsk (_("register list not in ascending order"));
8185 mask
|= 1 << new_base
;
8188 skip_whitespace (*str
);
8190 if (**str
== '-') /* We have the start of a range expression */
8197 = arm_reg_parse (str
, all_reg_maps
[REG_TYPE_SN
].htab
))
8200 inst
.error
= _(all_reg_maps
[REG_TYPE_SN
].expected
);
8204 if (high_range
<= new_base
)
8206 inst
.error
= _("register range not in ascending order");
8210 for (new_base
++; new_base
<= high_range
; new_base
++)
8212 if (mask
& (1 << new_base
))
8214 inst
.error
= _("invalid register list");
8218 mask
|= 1 << new_base
;
8223 while (skip_past_comma (str
) != FAIL
);
8227 inst
.error
= _("invalid register list");
8235 /* Sanity check -- should have raised a parse error above. */
8236 if (count
== 0 || count
> 32)
8239 /* Final test -- the registers must be consecutive. */
8242 if ((mask
& (1 << base_reg
++)) == 0)
8244 inst
.error
= _("non-contiguous register range");
8249 inst
.instruction
= tempinst
| base_bits
;
8254 vfp_dp_reg_list (str
)
8262 unsigned long mask
= 0;
8269 skip_whitespace (*str
);
8271 tempinst
= inst
.instruction
;
8275 inst
.instruction
= 0;
8277 if ((new_base
= vfp_dp_reg_required_here (str
, VFP_REG_Dd
)) == FAIL
)
8280 if (count
== 0 || base_reg
> new_base
)
8282 base_reg
= new_base
;
8283 range
= inst
.instruction
;
8286 if (mask
& (1 << new_base
))
8288 inst
.error
= _("invalid register list");
8292 if ((mask
>> new_base
) != 0 && ! warned
)
8294 as_tsktsk (_("register list not in ascending order"));
8298 mask
|= 1 << new_base
;
8301 skip_whitespace (*str
);
8303 if (**str
== '-') /* We have the start of a range expression */
8310 = arm_reg_parse (str
, all_reg_maps
[REG_TYPE_DN
].htab
))
8313 inst
.error
= _(all_reg_maps
[REG_TYPE_DN
].expected
);
8317 if (high_range
<= new_base
)
8319 inst
.error
= _("register range not in ascending order");
8323 for (new_base
++; new_base
<= high_range
; new_base
++)
8325 if (mask
& (1 << new_base
))
8327 inst
.error
= _("invalid register list");
8331 mask
|= 1 << new_base
;
8336 while (skip_past_comma (str
) != FAIL
);
8340 inst
.error
= _("invalid register list");
8348 /* Sanity check -- should have raised a parse error above. */
8349 if (count
== 0 || count
> 16)
8352 /* Final test -- the registers must be consecutive. */
8355 if ((mask
& (1 << base_reg
++)) == 0)
8357 inst
.error
= _("non-contiguous register range");
8362 inst
.instruction
= tempinst
;
8367 vfp_sp_ldstm (str
, ldstm_type
)
8369 enum vfp_ldstm_type ldstm_type
;
8373 skip_whitespace (str
);
8375 if (reg_required_here (&str
, 16) == FAIL
)
8378 skip_whitespace (str
);
8382 inst
.instruction
|= WRITE_BACK
;
8385 else if (ldstm_type
!= VFP_LDSTMIA
)
8387 inst
.error
= _("this addressing mode requires base-register writeback");
8391 if (skip_past_comma (&str
) == FAIL
8392 || (range
= vfp_sp_reg_list (&str
, VFP_REG_Sd
)) == FAIL
)
8395 inst
.error
= BAD_ARGS
;
8399 inst
.instruction
|= range
;
8404 vfp_dp_ldstm (str
, ldstm_type
)
8406 enum vfp_ldstm_type ldstm_type
;
8410 skip_whitespace (str
);
8412 if (reg_required_here (&str
, 16) == FAIL
)
8415 skip_whitespace (str
);
8419 inst
.instruction
|= WRITE_BACK
;
8422 else if (ldstm_type
!= VFP_LDSTMIA
&& ldstm_type
!= VFP_LDSTMIAX
)
8424 inst
.error
= _("this addressing mode requires base-register writeback");
8428 if (skip_past_comma (&str
) == FAIL
8429 || (range
= vfp_dp_reg_list (&str
)) == FAIL
)
8432 inst
.error
= BAD_ARGS
;
8436 if (ldstm_type
== VFP_LDSTMIAX
|| ldstm_type
== VFP_LDSTMDBX
)
8439 inst
.instruction
|= range
;
8444 do_vfp_sp_ldstmia (str
)
8447 vfp_sp_ldstm (str
, VFP_LDSTMIA
);
8451 do_vfp_sp_ldstmdb (str
)
8454 vfp_sp_ldstm (str
, VFP_LDSTMDB
);
8458 do_vfp_dp_ldstmia (str
)
8461 vfp_dp_ldstm (str
, VFP_LDSTMIA
);
8465 do_vfp_dp_ldstmdb (str
)
8468 vfp_dp_ldstm (str
, VFP_LDSTMDB
);
8472 do_vfp_xp_ldstmia (str
)
8475 vfp_dp_ldstm (str
, VFP_LDSTMIAX
);
8479 do_vfp_xp_ldstmdb (str
)
8482 vfp_dp_ldstm (str
, VFP_LDSTMDBX
);
8486 do_vfp_sp_compare_z (str
)
8489 skip_whitespace (str
);
8491 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8494 inst
.error
= BAD_ARGS
;
8503 do_vfp_dp_compare_z (str
)
8506 skip_whitespace (str
);
8508 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8511 inst
.error
= BAD_ARGS
;
8520 do_vfp_dp_sp_cvt (str
)
8523 skip_whitespace (str
);
8525 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8528 if (skip_past_comma (&str
) == FAIL
8529 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
8532 inst
.error
= BAD_ARGS
;
8541 do_vfp_sp_dp_cvt (str
)
8544 skip_whitespace (str
);
8546 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8549 if (skip_past_comma (&str
) == FAIL
8550 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
8553 inst
.error
= BAD_ARGS
;
8561 /* Thumb specific routines. */
8563 /* Parse and validate that a register is of the right form, this saves
8564 repeated checking of this information in many similar cases.
8565 Unlike the 32-bit case we do not insert the register into the opcode
8566 here, since the position is often unknown until the full instruction
8570 thumb_reg (strp
, hi_lo
)
8576 if ((reg
= reg_required_here (strp
, -1)) == FAIL
)
8584 inst
.error
= _("lo register required");
8592 inst
.error
= _("hi register required");
8604 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
8608 thumb_add_sub (str
, subtract
)
8612 int Rd
, Rs
, Rn
= FAIL
;
8614 skip_whitespace (str
);
8616 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
8617 || skip_past_comma (&str
) == FAIL
)
8620 inst
.error
= BAD_ARGS
;
8624 if (is_immediate_prefix (*str
))
8628 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8633 if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8636 if (skip_past_comma (&str
) == FAIL
)
8638 /* Two operand format, shuffle the registers
8639 and pretend there are 3. */
8643 else if (is_immediate_prefix (*str
))
8646 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8649 else if ((Rn
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8653 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8654 for the latter case, EXPR contains the immediate that was found. */
8657 /* All register format. */
8658 if (Rd
> 7 || Rs
> 7 || Rn
> 7)
8662 inst
.error
= _("dest and source1 must be the same register");
8666 /* Can't do this for SUB. */
8669 inst
.error
= _("subtract valid only on lo regs");
8673 inst
.instruction
= (T_OPCODE_ADD_HI
8674 | (Rd
> 7 ? THUMB_H1
: 0)
8675 | (Rn
> 7 ? THUMB_H2
: 0));
8676 inst
.instruction
|= (Rd
& 7) | ((Rn
& 7) << 3);
8680 inst
.instruction
= subtract
? T_OPCODE_SUB_R3
: T_OPCODE_ADD_R3
;
8681 inst
.instruction
|= Rd
| (Rs
<< 3) | (Rn
<< 6);
8686 /* Immediate expression, now things start to get nasty. */
8688 /* First deal with HI regs, only very restricted cases allowed:
8689 Adjusting SP, and using PC or SP to get an address. */
8690 if ((Rd
> 7 && (Rd
!= REG_SP
|| Rs
!= REG_SP
))
8691 || (Rs
> 7 && Rs
!= REG_SP
&& Rs
!= REG_PC
))
8693 inst
.error
= _("invalid Hi register with immediate");
8697 if (inst
.reloc
.exp
.X_op
!= O_constant
)
8699 /* Value isn't known yet, all we can do is store all the fragments
8700 we know about in the instruction and let the reloc hacking
8702 inst
.instruction
= (subtract
? 0x8000 : 0) | (Rd
<< 4) | Rs
;
8703 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
8707 int offset
= inst
.reloc
.exp
.X_add_number
;
8717 /* Quick check, in case offset is MIN_INT. */
8720 inst
.error
= _("immediate value out of range");
8724 /* Note - you cannot convert a subtract of 0 into an
8725 add of 0 because the carry flag is set differently. */
8726 else if (offset
> 0)
8731 if (offset
& ~0x1fc)
8733 inst
.error
= _("invalid immediate value for stack adjust");
8736 inst
.instruction
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
8737 inst
.instruction
|= offset
>> 2;
8739 else if (Rs
== REG_PC
|| Rs
== REG_SP
)
8742 || (offset
& ~0x3fc))
8744 inst
.error
= _("invalid immediate for address calculation");
8747 inst
.instruction
= (Rs
== REG_PC
? T_OPCODE_ADD_PC
8749 inst
.instruction
|= (Rd
<< 8) | (offset
>> 2);
8755 inst
.error
= _("immediate value out of range");
8758 inst
.instruction
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
8759 inst
.instruction
|= (Rd
<< 8) | offset
;
8765 inst
.error
= _("immediate value out of range");
8768 inst
.instruction
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
8769 inst
.instruction
|= Rd
| (Rs
<< 3) | (offset
<< 6);
8778 thumb_shift (str
, shift
)
8782 int Rd
, Rs
, Rn
= FAIL
;
8784 skip_whitespace (str
);
8786 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
8787 || skip_past_comma (&str
) == FAIL
)
8790 inst
.error
= BAD_ARGS
;
8794 if (is_immediate_prefix (*str
))
8796 /* Two operand immediate format, set Rs to Rd. */
8799 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8804 if ((Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8807 if (skip_past_comma (&str
) == FAIL
)
8809 /* Two operand format, shuffle the registers
8810 and pretend there are 3. */
8814 else if (is_immediate_prefix (*str
))
8817 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8820 else if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8824 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8825 for the latter case, EXPR contains the immediate that was found. */
8831 inst
.error
= _("source1 and dest must be same register");
8837 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_R
; break;
8838 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_R
; break;
8839 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_R
; break;
8842 inst
.instruction
|= Rd
| (Rn
<< 3);
8848 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_I
; break;
8849 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_I
; break;
8850 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_I
; break;
8853 if (inst
.reloc
.exp
.X_op
!= O_constant
)
8855 /* Value isn't known yet, create a dummy reloc and let reloc
8856 hacking fix it up. */
8857 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_SHIFT
;
8861 unsigned shift_value
= inst
.reloc
.exp
.X_add_number
;
8863 if (shift_value
> 32 || (shift_value
== 32 && shift
== THUMB_LSL
))
8865 inst
.error
= _("invalid immediate for shift");
8869 /* Shifts of zero are handled by converting to LSL. */
8870 if (shift_value
== 0)
8871 inst
.instruction
= T_OPCODE_LSL_I
;
8873 /* Shifts of 32 are encoded as a shift of zero. */
8874 if (shift_value
== 32)
8877 inst
.instruction
|= shift_value
<< 6;
8880 inst
.instruction
|= Rd
| (Rs
<< 3);
8887 thumb_mov_compare (str
, move
)
8893 skip_whitespace (str
);
8895 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
8896 || skip_past_comma (&str
) == FAIL
)
8899 inst
.error
= BAD_ARGS
;
8903 if (is_immediate_prefix (*str
))
8906 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8909 else if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8914 if (Rs
< 8 && Rd
< 8)
8916 if (move
== THUMB_MOVE
)
8917 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
8918 since a MOV instruction produces unpredictable results. */
8919 inst
.instruction
= T_OPCODE_ADD_I3
;
8921 inst
.instruction
= T_OPCODE_CMP_LR
;
8922 inst
.instruction
|= Rd
| (Rs
<< 3);
8926 if (move
== THUMB_MOVE
)
8927 inst
.instruction
= T_OPCODE_MOV_HR
;
8929 inst
.instruction
= T_OPCODE_CMP_HR
;
8932 inst
.instruction
|= THUMB_H1
;
8935 inst
.instruction
|= THUMB_H2
;
8937 inst
.instruction
|= (Rd
& 7) | ((Rs
& 7) << 3);
8944 inst
.error
= _("only lo regs allowed with immediate");
8948 if (move
== THUMB_MOVE
)
8949 inst
.instruction
= T_OPCODE_MOV_I8
;
8951 inst
.instruction
= T_OPCODE_CMP_I8
;
8953 inst
.instruction
|= Rd
<< 8;
8955 if (inst
.reloc
.exp
.X_op
!= O_constant
)
8956 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_IMM
;
8959 unsigned value
= inst
.reloc
.exp
.X_add_number
;
8963 inst
.error
= _("invalid immediate");
8967 inst
.instruction
|= value
;
8975 thumb_load_store (str
, load_store
, size
)
8980 int Rd
, Rb
, Ro
= FAIL
;
8982 skip_whitespace (str
);
8984 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
8985 || skip_past_comma (&str
) == FAIL
)
8988 inst
.error
= BAD_ARGS
;
8995 if ((Rb
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8998 if (skip_past_comma (&str
) != FAIL
)
9000 if (is_immediate_prefix (*str
))
9003 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9006 else if ((Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9011 inst
.reloc
.exp
.X_op
= O_constant
;
9012 inst
.reloc
.exp
.X_add_number
= 0;
9017 inst
.error
= _("expected ']'");
9022 else if (*str
== '=')
9024 if (load_store
!= THUMB_LOAD
)
9026 inst
.error
= _("invalid pseudo operation");
9030 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
9033 skip_whitespace (str
);
9035 if (my_get_expression (& inst
.reloc
.exp
, & str
))
9040 if ( inst
.reloc
.exp
.X_op
!= O_constant
9041 && inst
.reloc
.exp
.X_op
!= O_symbol
)
9043 inst
.error
= "Constant expression expected";
9047 if (inst
.reloc
.exp
.X_op
== O_constant
9048 && ((inst
.reloc
.exp
.X_add_number
& ~0xFF) == 0))
9050 /* This can be done with a mov instruction. */
9052 inst
.instruction
= T_OPCODE_MOV_I8
| (Rd
<< 8);
9053 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
9057 /* Insert into literal pool. */
9058 if (add_to_lit_pool () == FAIL
)
9061 inst
.error
= "literal pool insertion failed";
9065 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
9066 inst
.reloc
.pc_rel
= 1;
9067 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
9068 /* Adjust ARM pipeline offset to Thumb. */
9069 inst
.reloc
.exp
.X_add_number
+= 4;
9075 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9078 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
9079 inst
.reloc
.pc_rel
= 1;
9080 inst
.reloc
.exp
.X_add_number
-= 4; /* Pipeline offset. */
9081 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
9086 if (Rb
== REG_PC
|| Rb
== REG_SP
)
9088 if (size
!= THUMB_WORD
)
9090 inst
.error
= _("byte or halfword not valid for base register");
9093 else if (Rb
== REG_PC
&& load_store
!= THUMB_LOAD
)
9095 inst
.error
= _("r15 based store not allowed");
9098 else if (Ro
!= FAIL
)
9100 inst
.error
= _("invalid base register for register offset");
9105 inst
.instruction
= T_OPCODE_LDR_PC
;
9106 else if (load_store
== THUMB_LOAD
)
9107 inst
.instruction
= T_OPCODE_LDR_SP
;
9109 inst
.instruction
= T_OPCODE_STR_SP
;
9111 inst
.instruction
|= Rd
<< 8;
9112 if (inst
.reloc
.exp
.X_op
== O_constant
)
9114 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
9116 if (offset
& ~0x3fc)
9118 inst
.error
= _("invalid offset");
9122 inst
.instruction
|= offset
>> 2;
9125 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
9129 inst
.error
= _("invalid base register in load/store");
9132 else if (Ro
== FAIL
)
9134 /* Immediate offset. */
9135 if (size
== THUMB_WORD
)
9136 inst
.instruction
= (load_store
== THUMB_LOAD
9137 ? T_OPCODE_LDR_IW
: T_OPCODE_STR_IW
);
9138 else if (size
== THUMB_HALFWORD
)
9139 inst
.instruction
= (load_store
== THUMB_LOAD
9140 ? T_OPCODE_LDR_IH
: T_OPCODE_STR_IH
);
9142 inst
.instruction
= (load_store
== THUMB_LOAD
9143 ? T_OPCODE_LDR_IB
: T_OPCODE_STR_IB
);
9145 inst
.instruction
|= Rd
| (Rb
<< 3);
9147 if (inst
.reloc
.exp
.X_op
== O_constant
)
9149 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
9151 if (offset
& ~(0x1f << size
))
9153 inst
.error
= _("invalid offset");
9156 inst
.instruction
|= (offset
>> size
) << 6;
9159 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
9163 /* Register offset. */
9164 if (size
== THUMB_WORD
)
9165 inst
.instruction
= (load_store
== THUMB_LOAD
9166 ? T_OPCODE_LDR_RW
: T_OPCODE_STR_RW
);
9167 else if (size
== THUMB_HALFWORD
)
9168 inst
.instruction
= (load_store
== THUMB_LOAD
9169 ? T_OPCODE_LDR_RH
: T_OPCODE_STR_RH
);
9171 inst
.instruction
= (load_store
== THUMB_LOAD
9172 ? T_OPCODE_LDR_RB
: T_OPCODE_STR_RB
);
9174 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
9180 /* A register must be given at this point.
9182 Shift is the place to put it in inst.instruction.
9184 Restores input start point on err.
9185 Returns the reg#, or FAIL. */
9188 mav_reg_required_here (str
, shift
, regtype
)
9191 enum arm_reg_type regtype
;
9196 if ((reg
= arm_reg_parse (str
, all_reg_maps
[regtype
].htab
)) != FAIL
)
9199 inst
.instruction
|= reg
<< shift
;
9204 /* Restore the start point. */
9207 /* In the few cases where we might be able to accept something else
9208 this error can be overridden. */
9209 inst
.error
= _(all_reg_maps
[regtype
].expected
);
9214 /* Cirrus Maverick Instructions. */
9216 /* Wrapper functions. */
9219 do_mav_binops_1a (str
)
9222 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVF
);
9226 do_mav_binops_1b (str
)
9229 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVD
);
9233 do_mav_binops_1c (str
)
9236 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVDX
);
9240 do_mav_binops_1d (str
)
9243 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVF
);
9247 do_mav_binops_1e (str
)
9250 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVD
);
9254 do_mav_binops_1f (str
)
9257 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVF
);
9261 do_mav_binops_1g (str
)
9264 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVD
);
9268 do_mav_binops_1h (str
)
9271 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVFX
);
9275 do_mav_binops_1i (str
)
9278 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVFX
);
9282 do_mav_binops_1j (str
)
9285 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVDX
);
9289 do_mav_binops_1k (str
)
9292 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVDX
);
9296 do_mav_binops_1l (str
)
9299 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVF
);
9303 do_mav_binops_1m (str
)
9306 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVD
);
9310 do_mav_binops_1n (str
)
9313 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
9317 do_mav_binops_1o (str
)
9320 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
9324 do_mav_binops_2a (str
)
9327 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVF
, REG_TYPE_RN
);
9331 do_mav_binops_2b (str
)
9334 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVD
, REG_TYPE_RN
);
9338 do_mav_binops_2c (str
)
9341 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVDX
, REG_TYPE_RN
);
9345 do_mav_binops_3a (str
)
9348 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVFX
);
9352 do_mav_binops_3b (str
)
9355 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVFX
, REG_TYPE_MVAX
);
9359 do_mav_binops_3c (str
)
9362 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVDX
);
9366 do_mav_binops_3d (str
)
9369 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVDX
, REG_TYPE_MVAX
);
9373 do_mav_triple_4a (str
)
9376 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_RN
);
9380 do_mav_triple_4b (str
)
9383 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_RN
);
9387 do_mav_triple_5a (str
)
9390 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVF
, REG_TYPE_MVF
);
9394 do_mav_triple_5b (str
)
9397 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVD
, REG_TYPE_MVD
);
9401 do_mav_triple_5c (str
)
9404 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
9408 do_mav_triple_5d (str
)
9411 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
9415 do_mav_triple_5e (str
)
9418 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVF
, REG_TYPE_MVF
, REG_TYPE_MVF
);
9422 do_mav_triple_5f (str
)
9425 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVD
, REG_TYPE_MVD
, REG_TYPE_MVD
);
9429 do_mav_triple_5g (str
)
9432 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
9436 do_mav_triple_5h (str
)
9439 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
9443 do_mav_quad_6a (str
)
9446 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
,
9451 do_mav_quad_6b (str
)
9454 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVAX
, REG_TYPE_MVFX
,
9458 /* cfmvsc32<cond> DSPSC,MVFX[15:0]. */
9460 do_mav_dspsc_1 (str
)
9463 skip_whitespace (str
);
9466 if (mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
9467 || skip_past_comma (&str
) == FAIL
9468 || mav_reg_required_here (&str
, 16, REG_TYPE_MVFX
) == FAIL
)
9471 inst
.error
= BAD_ARGS
;
9479 /* cfmv32sc<cond> MVFX[15:0],DSPSC. */
9481 do_mav_dspsc_2 (str
)
9484 skip_whitespace (str
);
9487 if (mav_reg_required_here (&str
, 0, REG_TYPE_MVFX
) == FAIL
9488 || skip_past_comma (&str
) == FAIL
9489 || mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
)
9492 inst
.error
= BAD_ARGS
;
9501 do_mav_shift_1 (str
)
9504 do_mav_shift (str
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
9508 do_mav_shift_2 (str
)
9511 do_mav_shift (str
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
9518 do_mav_ldst (str
, REG_TYPE_MVF
);
9525 do_mav_ldst (str
, REG_TYPE_MVD
);
9532 do_mav_ldst (str
, REG_TYPE_MVFX
);
9539 do_mav_ldst (str
, REG_TYPE_MVDX
);
9542 /* Isnsn like "foo X,Y". */
9545 do_mav_binops (str
, mode
, reg0
, reg1
)
9548 enum arm_reg_type reg0
;
9549 enum arm_reg_type reg1
;
9553 shift0
= mode
& 0xff;
9554 shift1
= (mode
>> 8) & 0xff;
9556 skip_whitespace (str
);
9558 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
9559 || skip_past_comma (&str
) == FAIL
9560 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
)
9563 inst
.error
= BAD_ARGS
;
9569 /* Isnsn like "foo X,Y,Z". */
9572 do_mav_triple (str
, mode
, reg0
, reg1
, reg2
)
9575 enum arm_reg_type reg0
;
9576 enum arm_reg_type reg1
;
9577 enum arm_reg_type reg2
;
9579 int shift0
, shift1
, shift2
;
9581 shift0
= mode
& 0xff;
9582 shift1
= (mode
>> 8) & 0xff;
9583 shift2
= (mode
>> 16) & 0xff;
9585 skip_whitespace (str
);
9587 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
9588 || skip_past_comma (&str
) == FAIL
9589 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
9590 || skip_past_comma (&str
) == FAIL
9591 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
)
9594 inst
.error
= BAD_ARGS
;
9600 /* Isnsn like "foo W,X,Y,Z".
9601 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
9604 do_mav_quad (str
, mode
, reg0
, reg1
, reg2
, reg3
)
9607 enum arm_reg_type reg0
;
9608 enum arm_reg_type reg1
;
9609 enum arm_reg_type reg2
;
9610 enum arm_reg_type reg3
;
9612 int shift0
, shift1
, shift2
, shift3
;
9614 shift0
= mode
& 0xff;
9615 shift1
= (mode
>> 8) & 0xff;
9616 shift2
= (mode
>> 16) & 0xff;
9617 shift3
= (mode
>> 24) & 0xff;
9619 skip_whitespace (str
);
9621 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
9622 || skip_past_comma (&str
) == FAIL
9623 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
9624 || skip_past_comma (&str
) == FAIL
9625 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
9626 || skip_past_comma (&str
) == FAIL
9627 || mav_reg_required_here (&str
, shift3
, reg3
) == FAIL
)
9630 inst
.error
= BAD_ARGS
;
9636 /* Maverick shift immediate instructions.
9637 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
9638 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
9641 do_mav_shift (str
, reg0
, reg1
)
9643 enum arm_reg_type reg0
;
9644 enum arm_reg_type reg1
;
9649 skip_whitespace (str
);
9653 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
9654 || skip_past_comma (&str
) == FAIL
9655 || mav_reg_required_here (&str
, 16, reg1
) == FAIL
9656 || skip_past_comma (&str
) == FAIL
)
9659 inst
.error
= BAD_ARGS
;
9663 /* Calculate the immediate operand.
9664 The operand is a 7bit signed number. */
9665 skip_whitespace (str
);
9670 if (!ISDIGIT (*str
) && *str
!= '-')
9672 inst
.error
= _("expecting immediate, 7bit operand");
9682 for (imm
= 0; *str
&& ISDIGIT (*str
); ++str
)
9683 imm
= imm
* 10 + *str
- '0';
9687 inst
.error
= _("immediate out of range");
9691 /* Make negative imm's into 7bit signed numbers. */
9698 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
9699 Bits 5-7 of the insn should have bits 4-6 of the immediate.
9700 Bit 4 should be 0. */
9701 imm
= (imm
& 0xf) | ((imm
& 0x70) << 1);
9703 inst
.instruction
|= imm
;
9708 mav_parse_offset (str
, negative
)
9717 skip_whitespace (p
);
9730 inst
.error
= _("offset expected");
9734 for (offset
= 0; *p
&& ISDIGIT (*p
); ++p
)
9735 offset
= offset
* 10 + *p
- '0';
9739 inst
.error
= _("offset out of range");
9745 return *negative
? -offset
: offset
;
9748 /* Maverick load/store instructions.
9749 <insn><cond> CRd,[Rn,<offset>]{!}.
9750 <insn><cond> CRd,[Rn],<offset>. */
9753 do_mav_ldst (str
, reg0
)
9755 enum arm_reg_type reg0
;
9757 int offset
, negative
;
9759 skip_whitespace (str
);
9761 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
9762 || skip_past_comma (&str
) == FAIL
9764 || reg_required_here (&str
, 16) == FAIL
)
9767 if (skip_past_comma (&str
) == SUCCESS
)
9769 /* You are here: "<offset>]{!}". */
9770 inst
.instruction
|= PRE_INDEX
;
9772 offset
= mav_parse_offset (&str
, &negative
);
9779 inst
.error
= _("missing ]");
9785 inst
.instruction
|= WRITE_BACK
;
9791 /* You are here: "], <offset>". */
9794 inst
.error
= _("missing ]");
9798 if (skip_past_comma (&str
) == FAIL
9799 || (offset
= mav_parse_offset (&str
, &negative
), inst
.error
))
9802 inst
.instruction
|= CP_T_WB
; /* Post indexed, set bit W. */
9808 inst
.instruction
|= CP_T_UD
; /* Positive, so set bit U. */
9810 inst
.instruction
|= offset
>> 2;
9816 inst
.error
= BAD_ARGS
;
9829 /* Handle the Format 4 instructions that do not have equivalents in other
9830 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
9839 skip_whitespace (str
);
9841 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9842 || skip_past_comma (&str
) == FAIL
9843 || (Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9845 inst
.error
= BAD_ARGS
;
9849 if (skip_past_comma (&str
) != FAIL
)
9851 /* Three operand format not allowed for TST, CMN, NEG and MVN.
9852 (It isn't allowed for CMP either, but that isn't handled by this
9854 if (inst
.instruction
== T_OPCODE_TST
9855 || inst
.instruction
== T_OPCODE_CMN
9856 || inst
.instruction
== T_OPCODE_NEG
9857 || inst
.instruction
== T_OPCODE_MVN
)
9859 inst
.error
= BAD_ARGS
;
9863 if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9868 inst
.error
= _("dest and source1 must be the same register");
9874 if (inst
.instruction
== T_OPCODE_MUL
9876 as_tsktsk (_("Rs and Rd must be different in MUL"));
9878 inst
.instruction
|= Rd
| (Rs
<< 3);
9886 thumb_add_sub (str
, 0);
9893 thumb_shift (str
, THUMB_ASR
);
9900 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9902 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH9
;
9903 inst
.reloc
.pc_rel
= 1;
9911 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9913 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH12
;
9914 inst
.reloc
.pc_rel
= 1;
9918 /* Find the real, Thumb encoded start of a Thumb function. */
9921 find_real_start (symbolP
)
9925 const char * name
= S_GET_NAME (symbolP
);
9926 symbolS
* new_target
;
9928 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
9929 #define STUB_NAME ".real_start_of"
9934 /* Names that start with '.' are local labels, not function entry points.
9935 The compiler may generate BL instructions to these labels because it
9936 needs to perform a branch to a far away location. */
9940 real_start
= malloc (strlen (name
) + strlen (STUB_NAME
) + 1);
9941 sprintf (real_start
, "%s%s", STUB_NAME
, name
);
9943 new_target
= symbol_find (real_start
);
9945 if (new_target
== NULL
)
9947 as_warn ("Failed to find real start of function: %s\n", name
);
9948 new_target
= symbolP
;
9960 if (my_get_expression (& inst
.reloc
.exp
, & str
))
9963 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH23
;
9964 inst
.reloc
.pc_rel
= 1;
9967 /* If the destination of the branch is a defined symbol which does not have
9968 the THUMB_FUNC attribute, then we must be calling a function which has
9969 the (interfacearm) attribute. We look for the Thumb entry point to that
9970 function and change the branch to refer to that function instead. */
9971 if ( inst
.reloc
.exp
.X_op
== O_symbol
9972 && inst
.reloc
.exp
.X_add_symbol
!= NULL
9973 && S_IS_DEFINED (inst
.reloc
.exp
.X_add_symbol
)
9974 && ! THUMB_IS_FUNC (inst
.reloc
.exp
.X_add_symbol
))
9975 inst
.reloc
.exp
.X_add_symbol
=
9976 find_real_start (inst
.reloc
.exp
.X_add_symbol
);
9985 skip_whitespace (str
);
9987 if ((reg
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
9990 /* This sets THUMB_H2 from the top bit of reg. */
9991 inst
.instruction
|= reg
<< 3;
9993 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
9994 should cause the alignment to be checked once it is known. This is
9995 because BX PC only works if the instruction is word aligned. */
10004 thumb_mov_compare (str
, THUMB_COMPARE
);
10014 skip_whitespace (str
);
10016 if ((Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
10020 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
10024 if (skip_past_comma (&str
) == FAIL
10025 || (range
= reg_list (&str
)) == FAIL
)
10028 inst
.error
= BAD_ARGS
;
10032 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
10034 /* This really doesn't seem worth it. */
10035 inst
.reloc
.type
= BFD_RELOC_NONE
;
10036 inst
.error
= _("expression too complex");
10042 inst
.error
= _("only lo-regs valid in load/store multiple");
10046 inst
.instruction
|= (Rb
<< 8) | range
;
10054 thumb_load_store (str
, THUMB_LOAD
, THUMB_WORD
);
10061 thumb_load_store (str
, THUMB_LOAD
, THUMB_BYTE
);
10068 thumb_load_store (str
, THUMB_LOAD
, THUMB_HALFWORD
);
10077 skip_whitespace (str
);
10079 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
10080 || skip_past_comma (&str
) == FAIL
10082 || (Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
10083 || skip_past_comma (&str
) == FAIL
10084 || (Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
10088 inst
.error
= _("syntax: ldrs[b] Rd, [Rb, Ro]");
10092 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
10100 thumb_shift (str
, THUMB_LSL
);
10107 thumb_shift (str
, THUMB_LSR
);
10114 thumb_mov_compare (str
, THUMB_MOVE
);
10118 do_t_push_pop (str
)
10123 skip_whitespace (str
);
10125 if ((range
= reg_list (&str
)) == FAIL
)
10128 inst
.error
= BAD_ARGS
;
10132 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
10134 /* This really doesn't seem worth it. */
10135 inst
.reloc
.type
= BFD_RELOC_NONE
;
10136 inst
.error
= _("expression too complex");
10142 if ((inst
.instruction
== T_OPCODE_PUSH
10143 && (range
& ~0xff) == 1 << REG_LR
)
10144 || (inst
.instruction
== T_OPCODE_POP
10145 && (range
& ~0xff) == 1 << REG_PC
))
10147 inst
.instruction
|= THUMB_PP_PC_LR
;
10152 inst
.error
= _("invalid register list to push/pop instruction");
10157 inst
.instruction
|= range
;
10165 thumb_load_store (str
, THUMB_STORE
, THUMB_WORD
);
10172 thumb_load_store (str
, THUMB_STORE
, THUMB_BYTE
);
10179 thumb_load_store (str
, THUMB_STORE
, THUMB_HALFWORD
);
10186 thumb_add_sub (str
, 1);
10193 skip_whitespace (str
);
10195 if (my_get_expression (&inst
.reloc
.exp
, &str
))
10198 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
10209 /* This is a pseudo-op of the form "adr rd, label" to be converted
10210 into a relative address of the form "add rd, pc, #label-.-4". */
10211 skip_whitespace (str
);
10213 /* Store Rd in temporary location inside instruction. */
10214 if ((reg
= reg_required_here (&str
, 4)) == FAIL
10215 || (reg
> 7) /* For Thumb reg must be r0..r7. */
10216 || skip_past_comma (&str
) == FAIL
10217 || my_get_expression (&inst
.reloc
.exp
, &str
))
10220 inst
.error
= BAD_ARGS
;
10224 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
10225 inst
.reloc
.exp
.X_add_number
-= 4; /* PC relative adjust. */
10226 inst
.reloc
.pc_rel
= 1;
10227 inst
.instruction
|= REG_PC
; /* Rd is already placed into the instruction. */
10233 insert_reg (r
, htab
)
10234 const struct reg_entry
*r
;
10235 struct hash_control
*htab
;
10237 int len
= strlen (r
->name
) + 2;
10238 char * buf
= (char *) xmalloc (len
);
10239 char * buf2
= (char *) xmalloc (len
);
10242 #ifdef REGISTER_PREFIX
10243 buf
[i
++] = REGISTER_PREFIX
;
10246 strcpy (buf
+ i
, r
->name
);
10248 for (i
= 0; buf
[i
]; i
++)
10249 buf2
[i
] = TOUPPER (buf
[i
]);
10253 hash_insert (htab
, buf
, (PTR
) r
);
10254 hash_insert (htab
, buf2
, (PTR
) r
);
10258 build_reg_hsh (map
)
10259 struct reg_map
*map
;
10261 const struct reg_entry
*r
;
10263 if ((map
->htab
= hash_new ()) == NULL
)
10264 as_fatal (_("virtual memory exhausted"));
10266 for (r
= map
->names
; r
->name
!= NULL
; r
++)
10267 insert_reg (r
, map
->htab
);
10271 insert_reg_alias (str
, regnum
, htab
)
10274 struct hash_control
*htab
;
10277 struct reg_entry
*new = xmalloc (sizeof (struct reg_entry
));
10278 const char *name
= xmalloc (strlen (str
) + 1);
10280 strcpy ((char *) name
, str
);
10283 new->number
= regnum
;
10284 new->builtin
= FALSE
;
10286 error
= hash_insert (htab
, name
, (PTR
) new);
10289 as_bad (_("failed to create an alias for %s, reason: %s"),
10291 free ((char *) name
);
10296 /* Look for the .req directive. This is of the form:
10298 new_register_name .req existing_register_name
10300 If we find one, or if it looks sufficiently like one that we want to
10301 handle any error here, return non-zero. Otherwise return zero. */
10303 create_register_alias (newname
, p
)
10311 skip_whitespace (q
);
10316 if (*q
&& !strncmp (q
, ".req ", 5))
10321 #ifdef IGNORE_OPCODE_CASE
10322 newname
= original_case_string
;
10324 copy_of_str
= newname
;
10327 skip_whitespace (q
);
10329 for (r
= q
; *r
!= '\0'; r
++)
10335 enum arm_reg_type new_type
, old_type
;
10340 old_type
= arm_reg_parse_any (q
);
10343 new_type
= arm_reg_parse_any (newname
);
10345 if (new_type
== REG_TYPE_MAX
)
10347 if (old_type
!= REG_TYPE_MAX
)
10349 old_regno
= arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
);
10350 insert_reg_alias (newname
, old_regno
,
10351 all_reg_maps
[old_type
].htab
);
10354 as_warn (_("register '%s' does not exist\n"), q
);
10356 else if (old_type
== REG_TYPE_MAX
)
10358 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
10363 /* Do not warn about redefinitions to the same alias. */
10364 if (new_type
!= old_type
10365 || (arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
)
10366 != arm_reg_parse (&q
, all_reg_maps
[new_type
].htab
)))
10367 as_warn (_("ignoring redefinition of register alias '%s'"),
10373 as_warn (_("ignoring incomplete .req pseuso op"));
10384 set_constant_flonums ()
10388 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
10389 if (atof_ieee ((char *) fp_const
[i
], 'x', fp_values
[i
]) == NULL
)
10393 /* Iterate over the base tables to create the instruction patterns. */
10395 build_arm_ops_hsh ()
10399 static struct obstack insn_obstack
;
10401 obstack_begin (&insn_obstack
, 4000);
10403 for (i
= 0; i
< sizeof (insns
) / sizeof (struct asm_opcode
); i
++)
10405 const struct asm_opcode
*insn
= insns
+ i
;
10407 if (insn
->cond_offset
!= 0)
10409 /* Insn supports conditional execution. Build the varaints
10410 and insert them in the hash table. */
10411 for (j
= 0; j
< sizeof (conds
) / sizeof (struct asm_cond
); j
++)
10413 unsigned len
= strlen (insn
->template);
10414 struct asm_opcode
*new;
10417 new = obstack_alloc (&insn_obstack
, sizeof (struct asm_opcode
));
10418 /* All condition codes are two characters. */
10419 template = obstack_alloc (&insn_obstack
, len
+ 3);
10421 strncpy (template, insn
->template, insn
->cond_offset
);
10422 strcpy (template + insn
->cond_offset
, conds
[j
].template);
10423 if (len
> insn
->cond_offset
)
10424 strcpy (template + insn
->cond_offset
+ 2,
10425 insn
->template + insn
->cond_offset
);
10426 new->template = template;
10427 new->cond_offset
= 0;
10428 new->variant
= insn
->variant
;
10429 new->parms
= insn
->parms
;
10430 new->value
= (insn
->value
& ~COND_MASK
) | conds
[j
].value
;
10432 hash_insert (arm_ops_hsh
, new->template, (PTR
) new);
10435 /* Finally, insert the unconditional insn in the table directly;
10436 no need to build a copy. */
10437 hash_insert (arm_ops_hsh
, insn
->template, (PTR
) insn
);
10441 #if 0 /* Suppressed - for now. */
10442 #if defined OBJ_ELF || defined OBJ_COFF
10445 #define arm_Note Elf_External_Note
10449 unsigned char namesz
[4]; /* Size of entry's owner string. */
10450 unsigned char descsz
[4]; /* Size of the note descriptor. */
10451 unsigned char type
[4]; /* Interpretation of the descriptor. */
10452 char name
[1]; /* Start of the name+desc data. */
10456 /* The description is kept to a fix sized in order to make updating
10457 it and merging it easier. */
10458 #define ARM_NOTE_DESCRIPTION_LENGTH 8
10461 arm_add_note (name
, description
, type
)
10463 const char * description
;
10466 arm_Note note ATTRIBUTE_UNUSED
;
10468 unsigned int name_len
;
10470 name_len
= (strlen (name
) + 1 + 3) & ~3;
10472 p
= frag_more (sizeof (note
.namesz
));
10473 md_number_to_chars (p
, (valueT
) name_len
, sizeof (note
.namesz
));
10475 p
= frag_more (sizeof (note
.descsz
));
10476 md_number_to_chars (p
, (valueT
) ARM_NOTE_DESCRIPTION_LENGTH
, sizeof (note
.descsz
));
10478 p
= frag_more (sizeof (note
.type
));
10479 md_number_to_chars (p
, (valueT
) type
, sizeof (note
.type
));
10481 p
= frag_more (name_len
);
10484 p
= frag_more (ARM_NOTE_DESCRIPTION_LENGTH
);
10485 strncpy (p
, description
, ARM_NOTE_DESCRIPTION_LENGTH
);
10486 frag_align (2, 0, 0);
10497 if ( (arm_ops_hsh
= hash_new ()) == NULL
10498 || (arm_tops_hsh
= hash_new ()) == NULL
10499 || (arm_cond_hsh
= hash_new ()) == NULL
10500 || (arm_shift_hsh
= hash_new ()) == NULL
10501 || (arm_psr_hsh
= hash_new ()) == NULL
)
10502 as_fatal (_("virtual memory exhausted"));
10504 build_arm_ops_hsh ();
10505 for (i
= 0; i
< sizeof (tinsns
) / sizeof (struct thumb_opcode
); i
++)
10506 hash_insert (arm_tops_hsh
, tinsns
[i
].template, (PTR
) (tinsns
+ i
));
10507 for (i
= 0; i
< sizeof (conds
) / sizeof (struct asm_cond
); i
++)
10508 hash_insert (arm_cond_hsh
, conds
[i
].template, (PTR
) (conds
+ i
));
10509 for (i
= 0; i
< sizeof (shift_names
) / sizeof (struct asm_shift_name
); i
++)
10510 hash_insert (arm_shift_hsh
, shift_names
[i
].name
, (PTR
) (shift_names
+ i
));
10511 for (i
= 0; i
< sizeof (psrs
) / sizeof (struct asm_psr
); i
++)
10512 hash_insert (arm_psr_hsh
, psrs
[i
].template, (PTR
) (psrs
+ i
));
10514 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
10515 build_reg_hsh (all_reg_maps
+ i
);
10517 set_constant_flonums ();
10519 /* Set the cpu variant based on the command-line options. We prefer
10520 -mcpu= over -march= if both are set (as for GCC); and we prefer
10521 -mfpu= over any other way of setting the floating point unit.
10522 Use of legacy options with new options are faulted. */
10523 if (legacy_cpu
!= -1)
10525 if (mcpu_cpu_opt
!= -1 || march_cpu_opt
!= -1)
10526 as_bad (_("use of old and new-style options to set CPU type"));
10528 mcpu_cpu_opt
= legacy_cpu
;
10530 else if (mcpu_cpu_opt
== -1)
10531 mcpu_cpu_opt
= march_cpu_opt
;
10533 if (legacy_fpu
!= -1)
10535 if (mfpu_opt
!= -1)
10536 as_bad (_("use of old and new-style options to set FPU type"));
10538 mfpu_opt
= legacy_fpu
;
10540 else if (mfpu_opt
== -1)
10542 #if !(defined (TE_LINUX) || defined (TE_NetBSD))
10543 /* Some environments specify a default FPU. If they don't, infer it
10544 from the processor. */
10545 if (mcpu_fpu_opt
!= -1)
10546 mfpu_opt
= mcpu_fpu_opt
;
10548 mfpu_opt
= march_fpu_opt
;
10550 mfpu_opt
= FPU_DEFAULT
;
10554 if (mfpu_opt
== -1)
10556 if (mcpu_cpu_opt
== -1)
10557 mfpu_opt
= FPU_DEFAULT
;
10558 else if (mcpu_cpu_opt
& ARM_EXT_V5
)
10559 mfpu_opt
= FPU_ARCH_VFP_V2
;
10561 mfpu_opt
= FPU_ARCH_FPA
;
10564 if (mcpu_cpu_opt
== -1)
10565 mcpu_cpu_opt
= CPU_DEFAULT
;
10567 cpu_variant
= mcpu_cpu_opt
| mfpu_opt
;
10569 #if defined OBJ_COFF || defined OBJ_ELF
10571 unsigned int flags
= 0;
10573 /* Set the flags in the private structure. */
10574 if (uses_apcs_26
) flags
|= F_APCS26
;
10575 if (support_interwork
) flags
|= F_INTERWORK
;
10576 if (uses_apcs_float
) flags
|= F_APCS_FLOAT
;
10577 if (pic_code
) flags
|= F_PIC
;
10578 if ((cpu_variant
& FPU_ANY
) == FPU_NONE
10579 || (cpu_variant
& FPU_ANY
) == FPU_ARCH_VFP
) /* VFP layout only. */
10580 flags
|= F_SOFT_FLOAT
;
10581 /* Using VFP conventions (even if soft-float). */
10582 if (cpu_variant
& FPU_VFP_EXT_NONE
) flags
|= F_VFP_FLOAT
;
10584 #if defined OBJ_ELF
10585 if (cpu_variant
& ARM_CEXT_MAVERICK
)
10587 flags
&= ~ F_SOFT_FLOAT
;
10588 flags
|= EF_ARM_MAVERICK_FLOAT
;
10592 bfd_set_private_flags (stdoutput
, flags
);
10594 /* We have run out flags in the COFF header to encode the
10595 status of ATPCS support, so instead we create a dummy,
10596 empty, debug section called .arm.atpcs. */
10601 sec
= bfd_make_section (stdoutput
, ".arm.atpcs");
10605 bfd_set_section_flags
10606 (stdoutput
, sec
, SEC_READONLY
| SEC_DEBUGGING
/* | SEC_HAS_CONTENTS */);
10607 bfd_set_section_size (stdoutput
, sec
, 0);
10608 bfd_set_section_contents (stdoutput
, sec
, NULL
, 0, 0);
10614 /* Record the CPU type as well. */
10615 switch (cpu_variant
& ARM_CPU_MASK
)
10618 mach
= bfd_mach_arm_2
;
10621 case ARM_3
: /* Also ARM_250. */
10622 mach
= bfd_mach_arm_2a
;
10625 case ARM_6
: /* Also ARM_7. */
10626 mach
= bfd_mach_arm_3
;
10630 mach
= bfd_mach_arm_unknown
;
10634 /* Catch special cases. */
10635 if (cpu_variant
& ARM_CEXT_IWMMXT
)
10636 mach
= bfd_mach_arm_iWMMXt
;
10637 else if (cpu_variant
& ARM_CEXT_XSCALE
)
10638 mach
= bfd_mach_arm_XScale
;
10639 else if (cpu_variant
& ARM_CEXT_MAVERICK
)
10640 mach
= bfd_mach_arm_ep9312
;
10641 else if (cpu_variant
& ARM_EXT_V5E
)
10642 mach
= bfd_mach_arm_5TE
;
10643 else if (cpu_variant
& ARM_EXT_V5
)
10645 if (cpu_variant
& ARM_EXT_V4T
)
10646 mach
= bfd_mach_arm_5T
;
10648 mach
= bfd_mach_arm_5
;
10650 else if (cpu_variant
& ARM_EXT_V4
)
10652 if (cpu_variant
& ARM_EXT_V4T
)
10653 mach
= bfd_mach_arm_4T
;
10655 mach
= bfd_mach_arm_4
;
10657 else if (cpu_variant
& ARM_EXT_V3M
)
10658 mach
= bfd_mach_arm_3M
;
10660 #if 0 /* Suppressed - for now. */
10661 #if defined (OBJ_ELF) || defined (OBJ_COFF)
10663 /* Create a .note section to fully identify this arm binary. */
10665 #define NOTE_ARCH_STRING "arch: "
10667 #if defined OBJ_COFF && ! defined NT_VERSION
10668 #define NT_VERSION 1
10673 segT current_seg
= now_seg
;
10674 subsegT current_subseg
= now_subseg
;
10675 asection
* arm_arch
;
10676 const char * arch_string
;
10678 arm_arch
= bfd_make_section_old_way (stdoutput
, ARM_NOTE_SECTION
);
10681 bfd_set_section_flags (stdoutput
, arm_arch
,
10682 SEC_DATA
| SEC_ALLOC
| SEC_LOAD
| SEC_LINK_ONCE \
10683 | SEC_HAS_CONTENTS
);
10685 arm_arch
->output_section
= arm_arch
;
10686 subseg_set (arm_arch
, 0);
10691 case bfd_mach_arm_unknown
: arch_string
= "unknown"; break;
10692 case bfd_mach_arm_2
: arch_string
= "armv2"; break;
10693 case bfd_mach_arm_2a
: arch_string
= "armv2a"; break;
10694 case bfd_mach_arm_3
: arch_string
= "armv3"; break;
10695 case bfd_mach_arm_3M
: arch_string
= "armv3M"; break;
10696 case bfd_mach_arm_4
: arch_string
= "armv4"; break;
10697 case bfd_mach_arm_4T
: arch_string
= "armv4t"; break;
10698 case bfd_mach_arm_5
: arch_string
= "armv5"; break;
10699 case bfd_mach_arm_5T
: arch_string
= "armv5t"; break;
10700 case bfd_mach_arm_5TE
: arch_string
= "armv5te"; break;
10701 case bfd_mach_arm_XScale
: arch_string
= "XScale"; break;
10702 case bfd_mach_arm_ep9312
: arch_string
= "ep9312"; break;
10703 case bfd_mach_arm_iWMMXt
: arch_string
= "iWMMXt"; break;
10706 arm_add_note (NOTE_ARCH_STRING
, arch_string
, NT_ARCH
);
10708 subseg_set (current_seg
, current_subseg
);
10711 #endif /* Suppressed code. */
10713 bfd_set_arch_mach (stdoutput
, TARGET_ARCH
, mach
);
10716 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
10717 for use in the a.out file, and stores them in the array pointed to by buf.
10718 This knows about the endian-ness of the target machine and does
10719 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
10720 2 (short) and 4 (long) Floating numbers are put out as a series of
10721 LITTLENUMS (shorts, here at least). */
10724 md_number_to_chars (buf
, val
, n
)
10729 if (target_big_endian
)
10730 number_to_chars_bigendian (buf
, val
, n
);
10732 number_to_chars_littleendian (buf
, val
, n
);
10736 md_chars_to_number (buf
, n
)
10741 unsigned char * where
= (unsigned char *) buf
;
10743 if (target_big_endian
)
10748 result
|= (*where
++ & 255);
10756 result
|= (where
[n
] & 255);
10763 /* Turn a string in input_line_pointer into a floating point constant
10764 of type TYPE, and store the appropriate bytes in *LITP. The number
10765 of LITTLENUMS emitted is stored in *SIZEP. An error message is
10766 returned, or NULL on OK.
10768 Note that fp constants aren't represent in the normal way on the ARM.
10769 In big endian mode, things are as expected. However, in little endian
10770 mode fp constants are big-endian word-wise, and little-endian byte-wise
10771 within the words. For example, (double) 1.1 in big endian mode is
10772 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
10773 the byte sequence 99 99 f1 3f 9a 99 99 99.
10775 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
10778 md_atof (type
, litP
, sizeP
)
10784 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
10816 return _("bad call to MD_ATOF()");
10819 t
= atof_ieee (input_line_pointer
, type
, words
);
10821 input_line_pointer
= t
;
10824 if (target_big_endian
)
10826 for (i
= 0; i
< prec
; i
++)
10828 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
10834 if (cpu_variant
& FPU_ARCH_VFP
)
10835 for (i
= prec
- 1; i
>= 0; i
--)
10837 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
10841 /* For a 4 byte float the order of elements in `words' is 1 0.
10842 For an 8 byte float the order is 1 0 3 2. */
10843 for (i
= 0; i
< prec
; i
+= 2)
10845 md_number_to_chars (litP
, (valueT
) words
[i
+ 1], 2);
10846 md_number_to_chars (litP
+ 2, (valueT
) words
[i
], 2);
10854 /* The knowledge of the PC's pipeline offset is built into the insns
10858 md_pcrel_from (fixP
)
10862 && S_GET_SEGMENT (fixP
->fx_addsy
) == undefined_section
10863 && fixP
->fx_subsy
== NULL
)
10866 if (fixP
->fx_pcrel
&& (fixP
->fx_r_type
== BFD_RELOC_ARM_THUMB_ADD
))
10868 /* PC relative addressing on the Thumb is slightly odd
10869 as the bottom two bits of the PC are forced to zero
10870 for the calculation. */
10871 return (fixP
->fx_where
+ fixP
->fx_frag
->fr_address
) & ~3;
10875 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
10876 so we un-adjust here to compensate for the accommodation. */
10877 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
+ 8;
10879 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
10883 /* Round up a section size to the appropriate boundary. */
10886 md_section_align (segment
, size
)
10887 segT segment ATTRIBUTE_UNUSED
;
10893 /* Round all sects to multiple of 4. */
10894 return (size
+ 3) & ~3;
10898 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
10899 Otherwise we have no need to default values of symbols. */
10902 md_undefined_symbol (name
)
10903 char * name ATTRIBUTE_UNUSED
;
10906 if (name
[0] == '_' && name
[1] == 'G'
10907 && streq (name
, GLOBAL_OFFSET_TABLE_NAME
))
10911 if (symbol_find (name
))
10912 as_bad ("GOT already in the symbol table");
10914 GOT_symbol
= symbol_new (name
, undefined_section
,
10915 (valueT
) 0, & zero_address_frag
);
10925 /* arm_reg_parse () := if it looks like a register, return its token and
10926 advance the pointer. */
10929 arm_reg_parse (ccp
, htab
)
10930 register char ** ccp
;
10931 struct hash_control
*htab
;
10933 char * start
= * ccp
;
10936 struct reg_entry
* reg
;
10938 #ifdef REGISTER_PREFIX
10939 if (*start
!= REGISTER_PREFIX
)
10944 #ifdef OPTIONAL_REGISTER_PREFIX
10945 if (*p
== OPTIONAL_REGISTER_PREFIX
)
10949 if (!ISALPHA (*p
) || !is_name_beginner (*p
))
10953 while (ISALPHA (c
) || ISDIGIT (c
) || c
== '_')
10957 reg
= (struct reg_entry
*) hash_find (htab
, start
);
10963 return reg
->number
;
10969 /* Search for the following register name in each of the possible reg name
10970 tables. Return the classification if found, or REG_TYPE_MAX if not
10972 static enum arm_reg_type
10973 arm_reg_parse_any (cp
)
10978 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
10979 if (arm_reg_parse (&cp
, all_reg_maps
[i
].htab
) != FAIL
)
10980 return (enum arm_reg_type
) i
;
10982 return REG_TYPE_MAX
;
10986 md_apply_fix3 (fixP
, valP
, seg
)
10991 offsetT value
= * valP
;
10993 unsigned int newimm
;
10994 unsigned long temp
;
10996 char * buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
10997 arm_fix_data
* arm_data
= (arm_fix_data
*) fixP
->tc_fix_data
;
10999 assert (fixP
->fx_r_type
< BFD_RELOC_UNUSED
);
11001 /* Note whether this will delete the relocation. */
11003 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
11004 doesn't work fully.) */
11005 if ((fixP
->fx_addsy
== 0 || symbol_constant_p (fixP
->fx_addsy
))
11006 && !fixP
->fx_pcrel
)
11008 if (fixP
->fx_addsy
== 0 && !fixP
->fx_pcrel
)
11012 /* If this symbol is in a different section then we need to leave it for
11013 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
11014 so we have to undo it's effects here. */
11015 if (fixP
->fx_pcrel
)
11017 if (fixP
->fx_addsy
!= NULL
11018 && S_IS_DEFINED (fixP
->fx_addsy
)
11019 && S_GET_SEGMENT (fixP
->fx_addsy
) != seg
)
11022 && (fixP
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
11023 || fixP
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
11027 value
+= md_pcrel_from (fixP
);
11031 /* Remember value for emit_reloc. */
11032 fixP
->fx_addnumber
= value
;
11034 switch (fixP
->fx_r_type
)
11036 case BFD_RELOC_ARM_IMMEDIATE
:
11037 newimm
= validate_immediate (value
);
11038 temp
= md_chars_to_number (buf
, INSN_SIZE
);
11040 /* If the instruction will fail, see if we can fix things up by
11041 changing the opcode. */
11042 if (newimm
== (unsigned int) FAIL
11043 && (newimm
= negate_data_op (&temp
, value
)) == (unsigned int) FAIL
)
11045 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11046 _("invalid constant (%lx) after fixup"),
11047 (unsigned long) value
);
11051 newimm
|= (temp
& 0xfffff000);
11052 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
11056 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
11058 unsigned int highpart
= 0;
11059 unsigned int newinsn
= 0xe1a00000; /* nop. */
11061 newimm
= validate_immediate (value
);
11062 temp
= md_chars_to_number (buf
, INSN_SIZE
);
11064 /* If the instruction will fail, see if we can fix things up by
11065 changing the opcode. */
11066 if (newimm
== (unsigned int) FAIL
11067 && (newimm
= negate_data_op (& temp
, value
)) == (unsigned int) FAIL
)
11069 /* No ? OK - try using two ADD instructions to generate
11071 newimm
= validate_immediate_twopart (value
, & highpart
);
11073 /* Yes - then make sure that the second instruction is
11075 if (newimm
!= (unsigned int) FAIL
)
11077 /* Still No ? Try using a negated value. */
11078 else if ((newimm
= validate_immediate_twopart (- value
, & highpart
)) != (unsigned int) FAIL
)
11079 temp
= newinsn
= (temp
& OPCODE_MASK
) | OPCODE_SUB
<< DATA_OP_SHIFT
;
11080 /* Otherwise - give up. */
11083 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11084 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
11089 /* Replace the first operand in the 2nd instruction (which
11090 is the PC) with the destination register. We have
11091 already added in the PC in the first instruction and we
11092 do not want to do it again. */
11093 newinsn
&= ~ 0xf0000;
11094 newinsn
|= ((newinsn
& 0x0f000) << 4);
11097 newimm
|= (temp
& 0xfffff000);
11098 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
11100 highpart
|= (newinsn
& 0xfffff000);
11101 md_number_to_chars (buf
+ INSN_SIZE
, (valueT
) highpart
, INSN_SIZE
);
11105 case BFD_RELOC_ARM_OFFSET_IMM
:
11111 if (validate_offset_imm (value
, 0) == FAIL
)
11113 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11114 _("bad immediate value for offset (%ld)"),
11119 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11120 newval
&= 0xff7ff000;
11121 newval
|= value
| (sign
? INDEX_UP
: 0);
11122 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11125 case BFD_RELOC_ARM_OFFSET_IMM8
:
11126 case BFD_RELOC_ARM_HWLITERAL
:
11132 if (validate_offset_imm (value
, 1) == FAIL
)
11134 if (fixP
->fx_r_type
== BFD_RELOC_ARM_HWLITERAL
)
11135 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11136 _("invalid literal constant: pool needs to be closer"));
11138 as_bad (_("bad immediate value for half-word offset (%ld)"),
11143 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11144 newval
&= 0xff7ff0f0;
11145 newval
|= ((value
>> 4) << 8) | (value
& 0xf) | (sign
? INDEX_UP
: 0);
11146 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11149 case BFD_RELOC_ARM_LITERAL
:
11155 if (validate_offset_imm (value
, 0) == FAIL
)
11157 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11158 _("invalid literal constant: pool needs to be closer"));
11162 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11163 newval
&= 0xff7ff000;
11164 newval
|= value
| (sign
? INDEX_UP
: 0);
11165 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11168 case BFD_RELOC_ARM_SHIFT_IMM
:
11169 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11170 if (((unsigned long) value
) > 32
11172 && (((newval
& 0x60) == 0) || (newval
& 0x60) == 0x60)))
11174 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11175 _("shift expression is too large"));
11180 /* Shifts of zero must be done as lsl. */
11182 else if (value
== 32)
11184 newval
&= 0xfffff07f;
11185 newval
|= (value
& 0x1f) << 7;
11186 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11189 case BFD_RELOC_ARM_SWI
:
11190 if (arm_data
->thumb_mode
)
11192 if (((unsigned long) value
) > 0xff)
11193 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11194 _("invalid swi expression"));
11195 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xff00;
11197 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11201 if (((unsigned long) value
) > 0x00ffffff)
11202 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11203 _("invalid swi expression"));
11204 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff000000;
11206 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11210 case BFD_RELOC_ARM_MULTI
:
11211 if (((unsigned long) value
) > 0xffff)
11212 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11213 _("invalid expression in load/store multiple"));
11214 newval
= value
| md_chars_to_number (buf
, INSN_SIZE
);
11215 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11218 case BFD_RELOC_ARM_PCREL_BRANCH
:
11219 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11221 /* Sign-extend a 24-bit number. */
11222 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
11226 value
= fixP
->fx_offset
;
11229 /* We are going to store value (shifted right by two) in the
11230 instruction, in a 24 bit, signed field. Thus we need to check
11231 that none of the top 8 bits of the shifted value (top 7 bits of
11232 the unshifted, unsigned value) are set, or that they are all set. */
11233 if ((value
& ~ ((offsetT
) 0x1ffffff)) != 0
11234 && ((value
& ~ ((offsetT
) 0x1ffffff)) != ~ ((offsetT
) 0x1ffffff)))
11237 /* Normally we would be stuck at this point, since we cannot store
11238 the absolute address that is the destination of the branch in the
11239 24 bits of the branch instruction. If however, we happen to know
11240 that the destination of the branch is in the same section as the
11241 branch instruction itself, then we can compute the relocation for
11242 ourselves and not have to bother the linker with it.
11244 FIXME: The tests for OBJ_ELF and ! target_oabi are only here
11245 because I have not worked out how to do this for OBJ_COFF or
11248 && fixP
->fx_addsy
!= NULL
11249 && S_IS_DEFINED (fixP
->fx_addsy
)
11250 && S_GET_SEGMENT (fixP
->fx_addsy
) == seg
)
11252 /* Get pc relative value to go into the branch. */
11255 /* Permit a backward branch provided that enough bits
11256 are set. Allow a forwards branch, provided that
11257 enough bits are clear. */
11258 if ( (value
& ~ ((offsetT
) 0x1ffffff)) == ~ ((offsetT
) 0x1ffffff)
11259 || (value
& ~ ((offsetT
) 0x1ffffff)) == 0)
11263 if (! fixP
->fx_done
)
11265 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11266 _("GAS can't handle same-section branch dest >= 0x04000000"));
11270 value
+= SEXT24 (newval
);
11272 if ( (value
& ~ ((offsetT
) 0xffffff)) != 0
11273 && ((value
& ~ ((offsetT
) 0xffffff)) != ~ ((offsetT
) 0xffffff)))
11274 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11275 _("out of range branch"));
11277 newval
= (value
& 0x00ffffff) | (newval
& 0xff000000);
11278 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11281 case BFD_RELOC_ARM_PCREL_BLX
:
11284 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11288 value
= fixP
->fx_offset
;
11290 hbit
= (value
>> 1) & 1;
11291 value
= (value
>> 2) & 0x00ffffff;
11292 value
= (value
+ (newval
& 0x00ffffff)) & 0x00ffffff;
11293 newval
= value
| (newval
& 0xfe000000) | (hbit
<< 24);
11294 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11298 case BFD_RELOC_THUMB_PCREL_BRANCH9
: /* Conditional branch. */
11299 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11301 addressT diff
= (newval
& 0xff) << 1;
11306 if ((value
& ~0xff) && ((value
& ~0xff) != ~0xff))
11307 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11308 _("branch out of range"));
11309 newval
= (newval
& 0xff00) | ((value
& 0x1ff) >> 1);
11311 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11314 case BFD_RELOC_THUMB_PCREL_BRANCH12
: /* Unconditional branch. */
11315 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11317 addressT diff
= (newval
& 0x7ff) << 1;
11322 if ((value
& ~0x7ff) && ((value
& ~0x7ff) != ~0x7ff))
11323 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11324 _("branch out of range"));
11325 newval
= (newval
& 0xf800) | ((value
& 0xfff) >> 1);
11327 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11330 case BFD_RELOC_THUMB_PCREL_BLX
:
11331 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
11336 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11337 newval2
= md_chars_to_number (buf
+ THUMB_SIZE
, THUMB_SIZE
);
11338 diff
= ((newval
& 0x7ff) << 12) | ((newval2
& 0x7ff) << 1);
11339 if (diff
& 0x400000)
11342 value
= fixP
->fx_offset
;
11346 if ((value
& ~0x3fffff) && ((value
& ~0x3fffff) != ~0x3fffff))
11347 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11348 _("branch with link out of range"));
11350 newval
= (newval
& 0xf800) | ((value
& 0x7fffff) >> 12);
11351 newval2
= (newval2
& 0xf800) | ((value
& 0xfff) >> 1);
11352 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
)
11353 /* For a BLX instruction, make sure that the relocation is rounded up
11354 to a word boundary. This follows the semantics of the instruction
11355 which specifies that bit 1 of the target address will come from bit
11356 1 of the base address. */
11357 newval2
= (newval2
+ 1) & ~ 1;
11358 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11359 md_number_to_chars (buf
+ THUMB_SIZE
, newval2
, THUMB_SIZE
);
11364 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11365 md_number_to_chars (buf
, value
, 1);
11367 else if (!target_oabi
)
11369 value
= fixP
->fx_offset
;
11370 md_number_to_chars (buf
, value
, 1);
11376 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11377 md_number_to_chars (buf
, value
, 2);
11379 else if (!target_oabi
)
11381 value
= fixP
->fx_offset
;
11382 md_number_to_chars (buf
, value
, 2);
11388 case BFD_RELOC_ARM_GOT32
:
11389 case BFD_RELOC_ARM_GOTOFF
:
11390 md_number_to_chars (buf
, 0, 4);
11394 case BFD_RELOC_RVA
:
11396 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11397 md_number_to_chars (buf
, value
, 4);
11399 else if (!target_oabi
)
11401 value
= fixP
->fx_offset
;
11402 md_number_to_chars (buf
, value
, 4);
11408 case BFD_RELOC_ARM_PLT32
:
11409 /* It appears the instruction is fully prepared at this point. */
11413 case BFD_RELOC_ARM_CP_OFF_IMM
:
11415 if (value
< -1023 || value
> 1023 || (value
& 3))
11416 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11417 _("illegal value for co-processor offset"));
11420 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
11421 newval
|= (value
>> 2) | (sign
? INDEX_UP
: 0);
11422 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11425 case BFD_RELOC_ARM_CP_OFF_IMM_S2
:
11427 if (value
< -255 || value
> 255)
11428 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11429 _("Illegal value for co-processor offset"));
11432 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
11433 newval
|= value
| (sign
? INDEX_UP
: 0);
11434 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11437 case BFD_RELOC_ARM_THUMB_OFFSET
:
11438 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11439 /* Exactly what ranges, and where the offset is inserted depends
11440 on the type of instruction, we can establish this from the
11442 switch (newval
>> 12)
11444 case 4: /* PC load. */
11445 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
11446 forced to zero for these loads, so we will need to round
11447 up the offset if the instruction address is not word
11448 aligned (since the final address produced must be, and
11449 we can only describe word-aligned immediate offsets). */
11451 if ((fixP
->fx_frag
->fr_address
+ fixP
->fx_where
+ value
) & 3)
11452 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11453 _("invalid offset, target not word aligned (0x%08X)"),
11454 (unsigned int) (fixP
->fx_frag
->fr_address
11455 + fixP
->fx_where
+ value
));
11457 if ((value
+ 2) & ~0x3fe)
11458 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11459 _("invalid offset, value too big (0x%08lX)"),
11462 /* Round up, since pc will be rounded down. */
11463 newval
|= (value
+ 2) >> 2;
11466 case 9: /* SP load/store. */
11467 if (value
& ~0x3fc)
11468 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11469 _("invalid offset, value too big (0x%08lX)"),
11471 newval
|= value
>> 2;
11474 case 6: /* Word load/store. */
11476 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11477 _("invalid offset, value too big (0x%08lX)"),
11479 newval
|= value
<< 4; /* 6 - 2. */
11482 case 7: /* Byte load/store. */
11484 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11485 _("invalid offset, value too big (0x%08lX)"),
11487 newval
|= value
<< 6;
11490 case 8: /* Halfword load/store. */
11492 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11493 _("invalid offset, value too big (0x%08lX)"),
11495 newval
|= value
<< 5; /* 6 - 1. */
11499 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11500 "Unable to process relocation for thumb opcode: %lx",
11501 (unsigned long) newval
);
11504 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11507 case BFD_RELOC_ARM_THUMB_ADD
:
11508 /* This is a complicated relocation, since we use it for all of
11509 the following immediate relocations:
11513 9bit ADD/SUB SP word-aligned
11514 10bit ADD PC/SP word-aligned
11516 The type of instruction being processed is encoded in the
11523 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11525 int rd
= (newval
>> 4) & 0xf;
11526 int rs
= newval
& 0xf;
11527 int subtract
= newval
& 0x8000;
11531 if (value
& ~0x1fc)
11532 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11533 _("invalid immediate for stack address calculation"));
11534 newval
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
11535 newval
|= value
>> 2;
11537 else if (rs
== REG_PC
|| rs
== REG_SP
)
11541 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11542 _("invalid immediate for address calculation (value = 0x%08lX)"),
11543 (unsigned long) value
);
11544 newval
= (rs
== REG_PC
? T_OPCODE_ADD_PC
: T_OPCODE_ADD_SP
);
11546 newval
|= value
>> 2;
11551 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11552 _("invalid 8bit immediate"));
11553 newval
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
11554 newval
|= (rd
<< 8) | value
;
11559 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11560 _("invalid 3bit immediate"));
11561 newval
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
11562 newval
|= rd
| (rs
<< 3) | (value
<< 6);
11565 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11568 case BFD_RELOC_ARM_THUMB_IMM
:
11569 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11570 switch (newval
>> 11)
11572 case 0x04: /* 8bit immediate MOV. */
11573 case 0x05: /* 8bit immediate CMP. */
11574 if (value
< 0 || value
> 255)
11575 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11576 _("invalid immediate: %ld is too large"),
11584 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11587 case BFD_RELOC_ARM_THUMB_SHIFT
:
11588 /* 5bit shift value (0..31). */
11589 if (value
< 0 || value
> 31)
11590 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11591 _("illegal Thumb shift value: %ld"), (long) value
);
11592 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xf03f;
11593 newval
|= value
<< 6;
11594 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11597 case BFD_RELOC_VTABLE_INHERIT
:
11598 case BFD_RELOC_VTABLE_ENTRY
:
11602 case BFD_RELOC_NONE
:
11604 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11605 _("bad relocation fixup type (%d)"), fixP
->fx_r_type
);
11609 /* Translate internal representation of relocation info to BFD target
11613 tc_gen_reloc (section
, fixp
)
11614 asection
* section ATTRIBUTE_UNUSED
;
11618 bfd_reloc_code_real_type code
;
11620 reloc
= (arelent
*) xmalloc (sizeof (arelent
));
11622 reloc
->sym_ptr_ptr
= (asymbol
**) xmalloc (sizeof (asymbol
*));
11623 *reloc
->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
11624 reloc
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
11626 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
11628 if (fixp
->fx_pcrel
== 0)
11629 reloc
->addend
= fixp
->fx_offset
;
11631 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
11632 #else /* OBJ_ELF */
11633 reloc
->addend
= fixp
->fx_offset
;
11636 switch (fixp
->fx_r_type
)
11639 if (fixp
->fx_pcrel
)
11641 code
= BFD_RELOC_8_PCREL
;
11646 if (fixp
->fx_pcrel
)
11648 code
= BFD_RELOC_16_PCREL
;
11653 if (fixp
->fx_pcrel
)
11655 code
= BFD_RELOC_32_PCREL
;
11659 case BFD_RELOC_ARM_PCREL_BRANCH
:
11660 case BFD_RELOC_ARM_PCREL_BLX
:
11661 case BFD_RELOC_RVA
:
11662 case BFD_RELOC_THUMB_PCREL_BRANCH9
:
11663 case BFD_RELOC_THUMB_PCREL_BRANCH12
:
11664 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
11665 case BFD_RELOC_THUMB_PCREL_BLX
:
11666 case BFD_RELOC_VTABLE_ENTRY
:
11667 case BFD_RELOC_VTABLE_INHERIT
:
11668 code
= fixp
->fx_r_type
;
11671 case BFD_RELOC_ARM_LITERAL
:
11672 case BFD_RELOC_ARM_HWLITERAL
:
11673 /* If this is called then the a literal has
11674 been referenced across a section boundary. */
11675 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
11676 _("literal referenced across section boundary"));
11680 case BFD_RELOC_ARM_GOT32
:
11681 case BFD_RELOC_ARM_GOTOFF
:
11682 case BFD_RELOC_ARM_PLT32
:
11683 code
= fixp
->fx_r_type
;
11687 case BFD_RELOC_ARM_IMMEDIATE
:
11688 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
11689 _("internal relocation (type: IMMEDIATE) not fixed up"));
11692 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
11693 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
11694 _("ADRL used for a symbol not defined in the same file"));
11697 case BFD_RELOC_ARM_OFFSET_IMM
:
11698 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
11699 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
11706 switch (fixp
->fx_r_type
)
11708 case BFD_RELOC_ARM_OFFSET_IMM8
: type
= "OFFSET_IMM8"; break;
11709 case BFD_RELOC_ARM_SHIFT_IMM
: type
= "SHIFT_IMM"; break;
11710 case BFD_RELOC_ARM_SWI
: type
= "SWI"; break;
11711 case BFD_RELOC_ARM_MULTI
: type
= "MULTI"; break;
11712 case BFD_RELOC_ARM_CP_OFF_IMM
: type
= "CP_OFF_IMM"; break;
11713 case BFD_RELOC_ARM_THUMB_ADD
: type
= "THUMB_ADD"; break;
11714 case BFD_RELOC_ARM_THUMB_SHIFT
: type
= "THUMB_SHIFT"; break;
11715 case BFD_RELOC_ARM_THUMB_IMM
: type
= "THUMB_IMM"; break;
11716 case BFD_RELOC_ARM_THUMB_OFFSET
: type
= "THUMB_OFFSET"; break;
11717 default: type
= _("<unknown>"); break;
11719 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
11720 _("cannot represent %s relocation in this object file format"),
11727 if ((code
== BFD_RELOC_32_PCREL
|| code
== BFD_RELOC_32
)
11729 && fixp
->fx_addsy
== GOT_symbol
)
11731 code
= BFD_RELOC_ARM_GOTPC
;
11732 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
11736 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, code
);
11738 if (reloc
->howto
== NULL
)
11740 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
11741 _("cannot represent %s relocation in this object file format"),
11742 bfd_get_reloc_code_name (code
));
11746 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
11747 vtable entry to be used in the relocation's section offset. */
11748 if (fixp
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
11749 reloc
->address
= fixp
->fx_offset
;
11755 md_estimate_size_before_relax (fragP
, segtype
)
11756 fragS
* fragP ATTRIBUTE_UNUSED
;
11757 segT segtype ATTRIBUTE_UNUSED
;
11759 as_fatal (_("md_estimate_size_before_relax\n"));
11771 as_bad ("%s -- `%s'", inst
.error
, str
);
11775 to
= frag_more (inst
.size
);
11777 if (thumb_mode
&& (inst
.size
> THUMB_SIZE
))
11779 assert (inst
.size
== (2 * THUMB_SIZE
));
11780 md_number_to_chars (to
, inst
.instruction
>> 16, THUMB_SIZE
);
11781 md_number_to_chars (to
+ THUMB_SIZE
, inst
.instruction
, THUMB_SIZE
);
11783 else if (inst
.size
> INSN_SIZE
)
11785 assert (inst
.size
== (2 * INSN_SIZE
));
11786 md_number_to_chars (to
, inst
.instruction
, INSN_SIZE
);
11787 md_number_to_chars (to
+ INSN_SIZE
, inst
.instruction
, INSN_SIZE
);
11790 md_number_to_chars (to
, inst
.instruction
, inst
.size
);
11792 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
11793 fix_new_arm (frag_now
, to
- frag_now
->fr_literal
,
11794 inst
.size
, & inst
.reloc
.exp
, inst
.reloc
.pc_rel
,
11798 dwarf2_emit_insn (inst
.size
);
11810 /* Align the instruction.
11811 This may not be the right thing to do but ... */
11816 /* Align the previous label if needed. */
11817 if (last_label_seen
!= NULL
)
11819 symbol_set_frag (last_label_seen
, frag_now
);
11820 S_SET_VALUE (last_label_seen
, (valueT
) frag_now_fix ());
11821 S_SET_SEGMENT (last_label_seen
, now_seg
);
11824 memset (&inst
, '\0', sizeof (inst
));
11825 inst
.reloc
.type
= BFD_RELOC_NONE
;
11827 skip_whitespace (str
);
11829 /* Scan up to the end of the op-code, which must end in white space or
11831 for (start
= p
= str
; *p
!= '\0'; p
++)
11837 as_bad (_("no operator -- statement `%s'\n"), str
);
11843 const struct thumb_opcode
* opcode
;
11847 opcode
= (const struct thumb_opcode
*) hash_find (arm_tops_hsh
, str
);
11852 /* Check that this instruction is supported for this CPU. */
11853 if (thumb_mode
== 1 && (opcode
->variant
& cpu_variant
) == 0)
11855 as_bad (_("selected processor does not support `%s'"), str
);
11859 mapping_state (MAP_THUMB
);
11860 inst
.instruction
= opcode
->value
;
11861 inst
.size
= opcode
->size
;
11862 (*opcode
->parms
) (p
);
11869 const struct asm_opcode
* opcode
;
11873 opcode
= (const struct asm_opcode
*) hash_find (arm_ops_hsh
, str
);
11878 /* Check that this instruction is supported for this CPU. */
11879 if ((opcode
->variant
& cpu_variant
) == 0)
11881 as_bad (_("selected processor does not support `%s'"), str
);
11885 mapping_state (MAP_ARM
);
11886 inst
.instruction
= opcode
->value
;
11887 inst
.size
= INSN_SIZE
;
11888 (*opcode
->parms
) (p
);
11894 /* It wasn't an instruction, but it might be a register alias of the form
11896 if (create_register_alias (str
, p
))
11899 as_bad (_("bad instruction `%s'"), start
);
11903 Invocation line includes a switch not recognized by the base assembler.
11904 See if it's a processor-specific option.
11906 This routine is somewhat complicated by the need for backwards
11907 compatibility (since older releases of gcc can't be changed).
11908 The new options try to make the interface as compatible as
11911 New options (supported) are:
11913 -mcpu=<cpu name> Assemble for selected processor
11914 -march=<architecture name> Assemble for selected architecture
11915 -mfpu=<fpu architecture> Assemble for selected FPU.
11916 -EB/-mbig-endian Big-endian
11917 -EL/-mlittle-endian Little-endian
11918 -k Generate PIC code
11919 -mthumb Start in Thumb mode
11920 -mthumb-interwork Code supports ARM/Thumb interworking
11922 For now we will also provide support for:
11924 -mapcs-32 32-bit Program counter
11925 -mapcs-26 26-bit Program counter
11926 -macps-float Floats passed in FP registers
11927 -mapcs-reentrant Reentrant code
11929 (sometime these will probably be replaced with -mapcs=<list of options>
11930 and -matpcs=<list of options>)
11932 The remaining options are only supported for back-wards compatibility.
11933 Cpu variants, the arm part is optional:
11934 -m[arm]1 Currently not supported.
11935 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
11936 -m[arm]3 Arm 3 processor
11937 -m[arm]6[xx], Arm 6 processors
11938 -m[arm]7[xx][t][[d]m] Arm 7 processors
11939 -m[arm]8[10] Arm 8 processors
11940 -m[arm]9[20][tdmi] Arm 9 processors
11941 -mstrongarm[110[0]] StrongARM processors
11942 -mxscale XScale processors
11943 -m[arm]v[2345[t[e]]] Arm architectures
11944 -mall All (except the ARM1)
11946 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
11947 -mfpe-old (No float load/store multiples)
11948 -mvfpxd VFP Single precision
11950 -mno-fpu Disable all floating point instructions
11952 The following CPU names are recognized:
11953 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
11954 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
11955 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
11956 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
11957 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
11958 arm10t arm10e, arm1020t, arm1020e, arm10200e,
11959 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
11963 const char * md_shortopts
= "m:k";
11965 #ifdef ARM_BI_ENDIAN
11966 #define OPTION_EB (OPTION_MD_BASE + 0)
11967 #define OPTION_EL (OPTION_MD_BASE + 1)
11969 #if TARGET_BYTES_BIG_ENDIAN
11970 #define OPTION_EB (OPTION_MD_BASE + 0)
11972 #define OPTION_EL (OPTION_MD_BASE + 1)
11976 struct option md_longopts
[] =
11979 {"EB", no_argument
, NULL
, OPTION_EB
},
11982 {"EL", no_argument
, NULL
, OPTION_EL
},
11984 {NULL
, no_argument
, NULL
, 0}
11987 size_t md_longopts_size
= sizeof (md_longopts
);
11989 struct arm_option_table
11991 char *option
; /* Option name to match. */
11992 char *help
; /* Help information. */
11993 int *var
; /* Variable to change. */
11994 int value
; /* What to change it to. */
11995 char *deprecated
; /* If non-null, print this message. */
11998 struct arm_option_table arm_opts
[] =
12000 {"k", N_("generate PIC code"), &pic_code
, 1, NULL
},
12001 {"mthumb", N_("assemble Thumb code"), &thumb_mode
, 1, NULL
},
12002 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
12003 &support_interwork
, 1, NULL
},
12004 {"moabi", N_("use old ABI (ELF only)"), &target_oabi
, 1, NULL
},
12005 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26
, 0, NULL
},
12006 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26
, 1, NULL
},
12007 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float
,
12009 {"mapcs-reentrant", N_("re-entrant code"), &pic_code
, 1, NULL
},
12010 {"matpcs", N_("code is ATPCS conformant"), &atpcs
, 1, NULL
},
12011 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian
, 1, NULL
},
12012 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian
, 1,
12015 /* These are recognized by the assembler, but have no affect on code. */
12016 {"mapcs-frame", N_("use frame pointer"), NULL
, 0, NULL
},
12017 {"mapcs-stack-check", N_("use stack size checking"), NULL
, 0, NULL
},
12019 /* DON'T add any new processors to this list -- we want the whole list
12020 to go away... Add them to the processors table instead. */
12021 {"marm1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
12022 {"m1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
12023 {"marm2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
12024 {"m2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
12025 {"marm250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
12026 {"m250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
12027 {"marm3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
12028 {"m3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
12029 {"marm6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
12030 {"m6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
12031 {"marm600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
12032 {"m600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
12033 {"marm610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
12034 {"m610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
12035 {"marm620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
12036 {"m620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
12037 {"marm7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
12038 {"m7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
12039 {"marm70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
12040 {"m70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
12041 {"marm700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
12042 {"m700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
12043 {"marm700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
12044 {"m700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
12045 {"marm710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
12046 {"m710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
12047 {"marm710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
12048 {"m710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
12049 {"marm720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
12050 {"m720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
12051 {"marm7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
12052 {"m7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
12053 {"marm7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
12054 {"m7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
12055 {"marm7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
12056 {"m7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
12057 {"marm7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
12058 {"m7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
12059 {"marm7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
12060 {"m7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
12061 {"marm7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
12062 {"m7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
12063 {"marm7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
12064 {"m7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
12065 {"marm7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
12066 {"m7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
12067 {"marm7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12068 {"m7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12069 {"marm7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12070 {"m7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12071 {"marm710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
12072 {"m710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
12073 {"marm720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
12074 {"m720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
12075 {"marm740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
12076 {"m740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
12077 {"marm8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
12078 {"m8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
12079 {"marm810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
12080 {"m810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
12081 {"marm9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
12082 {"m9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
12083 {"marm9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
12084 {"m9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
12085 {"marm920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
12086 {"m920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
12087 {"marm940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
12088 {"m940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
12089 {"mstrongarm", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=strongarm")},
12090 {"mstrongarm110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
12091 N_("use -mcpu=strongarm110")},
12092 {"mstrongarm1100", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
12093 N_("use -mcpu=strongarm1100")},
12094 {"mstrongarm1110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
12095 N_("use -mcpu=strongarm1110")},
12096 {"mxscale", NULL
, &legacy_cpu
, ARM_ARCH_XSCALE
, N_("use -mcpu=xscale")},
12097 {"miwmmxt", NULL
, &legacy_cpu
, ARM_ARCH_IWMMXT
, N_("use -mcpu=iwmmxt")},
12098 {"mall", NULL
, &legacy_cpu
, ARM_ANY
, N_("use -mcpu=all")},
12100 /* Architecture variants -- don't add any more to this list either. */
12101 {"mv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
12102 {"marmv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
12103 {"mv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
12104 {"marmv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
12105 {"mv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
12106 {"marmv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
12107 {"mv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
12108 {"marmv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
12109 {"mv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
12110 {"marmv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
12111 {"mv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
12112 {"marmv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
12113 {"mv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
12114 {"marmv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
12115 {"mv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
12116 {"marmv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
12117 {"mv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
12118 {"marmv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
12120 /* Floating point variants -- don't add any more to this list either. */
12121 {"mfpe-old", NULL
, &legacy_fpu
, FPU_ARCH_FPE
, N_("use -mfpu=fpe")},
12122 {"mfpa10", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa10")},
12123 {"mfpa11", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa11")},
12124 {"mno-fpu", NULL
, &legacy_fpu
, 0,
12125 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
12127 {NULL
, NULL
, NULL
, 0, NULL
}
12130 struct arm_cpu_option_table
12134 /* For some CPUs we assume an FPU unless the user explicitly sets
12139 /* This list should, at a minimum, contain all the cpu names
12140 recognized by GCC. */
12141 static struct arm_cpu_option_table arm_cpus
[] =
12143 {"all", ARM_ANY
, FPU_ARCH_FPA
},
12144 {"arm1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
12145 {"arm2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
12146 {"arm250", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
12147 {"arm3", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
12148 {"arm6", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12149 {"arm60", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12150 {"arm600", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12151 {"arm610", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12152 {"arm620", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12153 {"arm7", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12154 {"arm7m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
12155 {"arm7d", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12156 {"arm7dm", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
12157 {"arm7di", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12158 {"arm7dmi", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
12159 {"arm70", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12160 {"arm700", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12161 {"arm700i", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12162 {"arm710", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12163 {"arm710t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12164 {"arm720", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12165 {"arm720t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12166 {"arm740t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12167 {"arm710c", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12168 {"arm7100", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12169 {"arm7500", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12170 {"arm7500fe", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12171 {"arm7t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12172 {"arm7tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12173 {"arm8", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12174 {"arm810", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12175 {"strongarm", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12176 {"strongarm1", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12177 {"strongarm110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12178 {"strongarm1100", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12179 {"strongarm1110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12180 {"arm9", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12181 {"arm920", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12182 {"arm920t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12183 {"arm922t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12184 {"arm940t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12185 {"arm9tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12186 /* For V5 or later processors we default to using VFP; but the user
12187 should really set the FPU type explicitly. */
12188 {"arm9e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
12189 {"arm9e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12190 {"arm926ej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
12191 {"arm946e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
12192 {"arm946e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12193 {"arm966e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
12194 {"arm966e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12195 {"arm10t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
12196 {"arm10e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12197 {"arm1020", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12198 {"arm1020t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
12199 {"arm1020e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12200 /* ??? XSCALE is really an architecture. */
12201 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
12202 /* ??? iwmmxt is not a processor. */
12203 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP_V2
},
12204 {"i80200", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
12206 {"ep9312", ARM_ARCH_V4T
| ARM_CEXT_MAVERICK
, FPU_NONE
},
12210 struct arm_arch_option_table
12217 /* This list should, at a minimum, contain all the architecture names
12218 recognized by GCC. */
12219 static struct arm_arch_option_table arm_archs
[] =
12221 {"all", ARM_ANY
, FPU_ARCH_FPA
},
12222 {"armv1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
12223 {"armv2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
12224 {"armv2a", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
12225 {"armv2s", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
12226 {"armv3", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12227 {"armv3m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
12228 {"armv4", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12229 {"armv4xm", ARM_ARCH_V4xM
, FPU_ARCH_FPA
},
12230 {"armv4t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12231 {"armv4txm", ARM_ARCH_V4TxM
, FPU_ARCH_FPA
},
12232 {"armv5", ARM_ARCH_V5
, FPU_ARCH_VFP
},
12233 {"armv5t", ARM_ARCH_V5T
, FPU_ARCH_VFP
},
12234 {"armv5txm", ARM_ARCH_V5TxM
, FPU_ARCH_VFP
},
12235 {"armv5te", ARM_ARCH_V5TE
, FPU_ARCH_VFP
},
12236 {"armv5texp", ARM_ARCH_V5TExP
, FPU_ARCH_VFP
},
12237 {"armv5tej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP
},
12238 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP
},
12239 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP
},
12243 /* ISA extensions in the co-processor space. */
12244 struct arm_arch_extension_table
12250 static struct arm_arch_extension_table arm_extensions
[] =
12252 {"maverick", ARM_CEXT_MAVERICK
},
12253 {"xscale", ARM_CEXT_XSCALE
},
12254 {"iwmmxt", ARM_CEXT_IWMMXT
},
12258 struct arm_fpu_option_table
12264 /* This list should, at a minimum, contain all the fpu names
12265 recognized by GCC. */
12266 static struct arm_fpu_option_table arm_fpus
[] =
12268 {"softfpa", FPU_NONE
},
12269 {"fpe", FPU_ARCH_FPE
},
12270 {"fpe2", FPU_ARCH_FPE
},
12271 {"fpe3", FPU_ARCH_FPA
}, /* Third release supports LFM/SFM. */
12272 {"fpa", FPU_ARCH_FPA
},
12273 {"fpa10", FPU_ARCH_FPA
},
12274 {"fpa11", FPU_ARCH_FPA
},
12275 {"arm7500fe", FPU_ARCH_FPA
},
12276 {"softvfp", FPU_ARCH_VFP
},
12277 {"softvfp+vfp", FPU_ARCH_VFP_V2
},
12278 {"vfp", FPU_ARCH_VFP_V2
},
12279 {"vfp9", FPU_ARCH_VFP_V2
},
12280 {"vfp10", FPU_ARCH_VFP_V2
},
12281 {"vfp10-r0", FPU_ARCH_VFP_V1
},
12282 {"vfpxd", FPU_ARCH_VFP_V1xD
},
12283 {"arm1020t", FPU_ARCH_VFP_V1
},
12284 {"arm1020e", FPU_ARCH_VFP_V2
},
12288 struct arm_long_option_table
12290 char *option
; /* Substring to match. */
12291 char *help
; /* Help information. */
12292 int (*func
) PARAMS ((char *subopt
)); /* Function to decode sub-option. */
12293 char *deprecated
; /* If non-null, print this message. */
12297 arm_parse_extension (str
, opt_p
)
12301 while (str
!= NULL
&& *str
!= 0)
12303 struct arm_arch_extension_table
*opt
;
12309 as_bad (_("invalid architectural extension"));
12314 ext
= strchr (str
, '+');
12317 optlen
= ext
- str
;
12319 optlen
= strlen (str
);
12323 as_bad (_("missing architectural extension"));
12327 for (opt
= arm_extensions
; opt
->name
!= NULL
; opt
++)
12328 if (strncmp (opt
->name
, str
, optlen
) == 0)
12330 *opt_p
|= opt
->value
;
12334 if (opt
->name
== NULL
)
12336 as_bad (_("unknown architectural extnsion `%s'"), str
);
12347 arm_parse_cpu (str
)
12350 struct arm_cpu_option_table
*opt
;
12351 char *ext
= strchr (str
, '+');
12355 optlen
= ext
- str
;
12357 optlen
= strlen (str
);
12361 as_bad (_("missing cpu name `%s'"), str
);
12365 for (opt
= arm_cpus
; opt
->name
!= NULL
; opt
++)
12366 if (strncmp (opt
->name
, str
, optlen
) == 0)
12368 mcpu_cpu_opt
= opt
->value
;
12369 mcpu_fpu_opt
= opt
->default_fpu
;
12372 return arm_parse_extension (ext
, &mcpu_cpu_opt
);
12377 as_bad (_("unknown cpu `%s'"), str
);
12382 arm_parse_arch (str
)
12385 struct arm_arch_option_table
*opt
;
12386 char *ext
= strchr (str
, '+');
12390 optlen
= ext
- str
;
12392 optlen
= strlen (str
);
12396 as_bad (_("missing architecture name `%s'"), str
);
12401 for (opt
= arm_archs
; opt
->name
!= NULL
; opt
++)
12402 if (strcmp (opt
->name
, str
) == 0)
12404 march_cpu_opt
= opt
->value
;
12405 march_fpu_opt
= opt
->default_fpu
;
12408 return arm_parse_extension (ext
, &march_cpu_opt
);
12413 as_bad (_("unknown architecture `%s'\n"), str
);
12418 arm_parse_fpu (str
)
12421 struct arm_fpu_option_table
*opt
;
12423 for (opt
= arm_fpus
; opt
->name
!= NULL
; opt
++)
12424 if (strcmp (opt
->name
, str
) == 0)
12426 mfpu_opt
= opt
->value
;
12430 as_bad (_("unknown floating point format `%s'\n"), str
);
12434 struct arm_long_option_table arm_long_opts
[] =
12436 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
12437 arm_parse_cpu
, NULL
},
12438 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
12439 arm_parse_arch
, NULL
},
12440 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
12441 arm_parse_fpu
, NULL
},
12442 {NULL
, NULL
, 0, NULL
}
12446 md_parse_option (c
, arg
)
12450 struct arm_option_table
*opt
;
12451 struct arm_long_option_table
*lopt
;
12457 target_big_endian
= 1;
12463 target_big_endian
= 0;
12468 /* Listing option. Just ignore these, we don't support additional
12473 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
12475 if (c
== opt
->option
[0]
12476 && ((arg
== NULL
&& opt
->option
[1] == 0)
12477 || strcmp (arg
, opt
->option
+ 1) == 0))
12479 #if WARN_DEPRECATED
12480 /* If the option is deprecated, tell the user. */
12481 if (opt
->deprecated
!= NULL
)
12482 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
,
12483 arg
? arg
: "", _(opt
->deprecated
));
12486 if (opt
->var
!= NULL
)
12487 *opt
->var
= opt
->value
;
12493 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
12495 /* These options are expected to have an argument. */
12496 if (c
== lopt
->option
[0]
12498 && strncmp (arg
, lopt
->option
+ 1,
12499 strlen (lopt
->option
+ 1)) == 0)
12501 #if WARN_DEPRECATED
12502 /* If the option is deprecated, tell the user. */
12503 if (lopt
->deprecated
!= NULL
)
12504 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
, arg
,
12505 _(lopt
->deprecated
));
12508 /* Call the sup-option parser. */
12509 return (*lopt
->func
)(arg
+ strlen (lopt
->option
) - 1);
12513 as_bad (_("unrecognized option `-%c%s'"), c
, arg
? arg
: "");
12524 struct arm_option_table
*opt
;
12525 struct arm_long_option_table
*lopt
;
12527 fprintf (fp
, _(" ARM-specific assembler options:\n"));
12529 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
12530 if (opt
->help
!= NULL
)
12531 fprintf (fp
, " -%-23s%s\n", opt
->option
, _(opt
->help
));
12533 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
12534 if (lopt
->help
!= NULL
)
12535 fprintf (fp
, " -%s%s\n", lopt
->option
, _(lopt
->help
));
12539 -EB assemble code for a big-endian cpu\n"));
12544 -EL assemble code for a little-endian cpu\n"));
12548 /* We need to be able to fix up arbitrary expressions in some statements.
12549 This is so that we can handle symbols that are an arbitrary distance from
12550 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
12551 which returns part of an address in a form which will be valid for
12552 a data instruction. We do this by pushing the expression into a symbol
12553 in the expr_section, and creating a fix for that. */
12556 fix_new_arm (frag
, where
, size
, exp
, pc_rel
, reloc
)
12565 arm_fix_data
* arm_data
;
12573 new_fix
= fix_new_exp (frag
, where
, size
, exp
, pc_rel
, reloc
);
12577 new_fix
= fix_new (frag
, where
, size
, make_expr_symbol (exp
), 0,
12582 /* Mark whether the fix is to a THUMB instruction, or an ARM
12584 arm_data
= (arm_fix_data
*) obstack_alloc (& notes
, sizeof (arm_fix_data
));
12585 new_fix
->tc_fix_data
= (PTR
) arm_data
;
12586 arm_data
->thumb_mode
= thumb_mode
;
12591 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
12594 cons_fix_new_arm (frag
, where
, size
, exp
)
12600 bfd_reloc_code_real_type type
;
12604 FIXME: @@ Should look at CPU word size. */
12608 type
= BFD_RELOC_8
;
12611 type
= BFD_RELOC_16
;
12615 type
= BFD_RELOC_32
;
12618 type
= BFD_RELOC_64
;
12622 fix_new_exp (frag
, where
, (int) size
, exp
, pcrel
, type
);
12625 /* A good place to do this, although this was probably not intended
12626 for this kind of use. We need to dump the literal pool before
12627 references are made to a null symbol pointer. */
12632 literal_pool
* pool
;
12634 for (pool
= list_of_pools
; pool
; pool
= pool
->next
)
12636 /* Put it at the end of the relevent section. */
12637 subseg_set (pool
->section
, pool
->sub_section
);
12643 arm_start_line_hook ()
12645 last_label_seen
= NULL
;
12649 arm_frob_label (sym
)
12652 last_label_seen
= sym
;
12654 ARM_SET_THUMB (sym
, thumb_mode
);
12656 #if defined OBJ_COFF || defined OBJ_ELF
12657 ARM_SET_INTERWORK (sym
, support_interwork
);
12660 /* Note - do not allow local symbols (.Lxxx) to be labeled
12661 as Thumb functions. This is because these labels, whilst
12662 they exist inside Thumb code, are not the entry points for
12663 possible ARM->Thumb calls. Also, these labels can be used
12664 as part of a computed goto or switch statement. eg gcc
12665 can generate code that looks like this:
12667 ldr r2, [pc, .Laaa]
12677 The first instruction loads the address of the jump table.
12678 The second instruction converts a table index into a byte offset.
12679 The third instruction gets the jump address out of the table.
12680 The fourth instruction performs the jump.
12682 If the address stored at .Laaa is that of a symbol which has the
12683 Thumb_Func bit set, then the linker will arrange for this address
12684 to have the bottom bit set, which in turn would mean that the
12685 address computation performed by the third instruction would end
12686 up with the bottom bit set. Since the ARM is capable of unaligned
12687 word loads, the instruction would then load the incorrect address
12688 out of the jump table, and chaos would ensue. */
12689 if (label_is_thumb_function_name
12690 && (S_GET_NAME (sym
)[0] != '.' || S_GET_NAME (sym
)[1] != 'L')
12691 && (bfd_get_section_flags (stdoutput
, now_seg
) & SEC_CODE
) != 0)
12693 /* When the address of a Thumb function is taken the bottom
12694 bit of that address should be set. This will allow
12695 interworking between Arm and Thumb functions to work
12698 THUMB_SET_FUNC (sym
, 1);
12700 label_is_thumb_function_name
= FALSE
;
12704 /* Adjust the symbol table. This marks Thumb symbols as distinct from
12708 arm_adjust_symtab ()
12713 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
12715 if (ARM_IS_THUMB (sym
))
12717 if (THUMB_IS_FUNC (sym
))
12719 /* Mark the symbol as a Thumb function. */
12720 if ( S_GET_STORAGE_CLASS (sym
) == C_STAT
12721 || S_GET_STORAGE_CLASS (sym
) == C_LABEL
) /* This can happen! */
12722 S_SET_STORAGE_CLASS (sym
, C_THUMBSTATFUNC
);
12724 else if (S_GET_STORAGE_CLASS (sym
) == C_EXT
)
12725 S_SET_STORAGE_CLASS (sym
, C_THUMBEXTFUNC
);
12727 as_bad (_("%s: unexpected function type: %d"),
12728 S_GET_NAME (sym
), S_GET_STORAGE_CLASS (sym
));
12730 else switch (S_GET_STORAGE_CLASS (sym
))
12733 S_SET_STORAGE_CLASS (sym
, C_THUMBEXT
);
12736 S_SET_STORAGE_CLASS (sym
, C_THUMBSTAT
);
12739 S_SET_STORAGE_CLASS (sym
, C_THUMBLABEL
);
12747 if (ARM_IS_INTERWORK (sym
))
12748 coffsymbol (symbol_get_bfdsym (sym
))->native
->u
.syment
.n_flags
= 0xFF;
12755 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
12757 if (ARM_IS_THUMB (sym
))
12759 elf_symbol_type
* elf_sym
;
12761 elf_sym
= elf_symbol (symbol_get_bfdsym (sym
));
12762 bind
= ELF_ST_BIND (elf_sym
);
12764 /* If it's a .thumb_func, declare it as so,
12765 otherwise tag label as .code 16. */
12766 if (THUMB_IS_FUNC (sym
))
12767 elf_sym
->internal_elf_sym
.st_info
=
12768 ELF_ST_INFO (bind
, STT_ARM_TFUNC
);
12770 elf_sym
->internal_elf_sym
.st_info
=
12771 ELF_ST_INFO (bind
, STT_ARM_16BIT
);
12778 arm_data_in_code ()
12780 if (thumb_mode
&& ! strncmp (input_line_pointer
+ 1, "data:", 5))
12782 *input_line_pointer
= '/';
12783 input_line_pointer
+= 5;
12784 *input_line_pointer
= 0;
12792 arm_canonicalize_symbol_name (name
)
12797 if (thumb_mode
&& (len
= strlen (name
)) > 5
12798 && streq (name
+ len
- 5, "/data"))
12799 *(name
+ len
- 5) = 0;
12804 #if defined OBJ_COFF || defined OBJ_ELF
12806 arm_validate_fix (fixP
)
12809 /* If the destination of the branch is a defined symbol which does not have
12810 the THUMB_FUNC attribute, then we must be calling a function which has
12811 the (interfacearm) attribute. We look for the Thumb entry point to that
12812 function and change the branch to refer to that function instead. */
12813 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
12814 && fixP
->fx_addsy
!= NULL
12815 && S_IS_DEFINED (fixP
->fx_addsy
)
12816 && ! THUMB_IS_FUNC (fixP
->fx_addsy
))
12818 fixP
->fx_addsy
= find_real_start (fixP
->fx_addsy
);
12824 arm_force_relocation (fixp
)
12827 #if defined (OBJ_COFF) && defined (TE_PE)
12828 if (fixp
->fx_r_type
== BFD_RELOC_RVA
)
12832 if (fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
12833 || fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
12834 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
12835 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
)
12839 /* Resolve these relocations even if the symbol is extern or weak. */
12840 if (fixp
->fx_r_type
== BFD_RELOC_ARM_IMMEDIATE
12841 || fixp
->fx_r_type
== BFD_RELOC_ARM_OFFSET_IMM
12842 || fixp
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
12845 return generic_force_reloc (fixp
);
12849 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
12850 local labels from being added to the output symbol table when they
12851 are used with the ADRL pseudo op. The ADRL relocation should always
12852 be resolved before the binbary is emitted, so it is safe to say that
12853 it is adjustable. */
12856 arm_fix_adjustable (fixP
)
12859 if (fixP
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
12866 /* Relocations against Thumb function names must be left unadjusted,
12867 so that the linker can use this information to correctly set the
12868 bottom bit of their addresses. The MIPS version of this function
12869 also prevents relocations that are mips-16 specific, but I do not
12870 know why it does this.
12873 There is one other problem that ought to be addressed here, but
12874 which currently is not: Taking the address of a label (rather
12875 than a function) and then later jumping to that address. Such
12876 addresses also ought to have their bottom bit set (assuming that
12877 they reside in Thumb code), but at the moment they will not. */
12880 arm_fix_adjustable (fixP
)
12883 if (fixP
->fx_addsy
== NULL
)
12886 if (THUMB_IS_FUNC (fixP
->fx_addsy
)
12887 && fixP
->fx_subsy
== NULL
)
12890 /* We need the symbol name for the VTABLE entries. */
12891 if ( fixP
->fx_r_type
== BFD_RELOC_VTABLE_INHERIT
12892 || fixP
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
12895 /* Don't allow symbols to be discarded on GOT related relocs. */
12896 if (fixP
->fx_r_type
== BFD_RELOC_ARM_PLT32
12897 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOT32
12898 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOTOFF
)
12905 elf32_arm_target_format ()
12907 if (target_big_endian
)
12910 return "elf32-bigarm-oabi";
12912 return "elf32-bigarm";
12917 return "elf32-littlearm-oabi";
12919 return "elf32-littlearm";
12924 armelf_frob_symbol (symp
, puntp
)
12928 elf_frob_symbol (symp
, puntp
);
12931 static bfd_reloc_code_real_type
12941 bfd_reloc_code_real_type reloc
;
12945 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
12946 MAP ("(got)", BFD_RELOC_ARM_GOT32
),
12947 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF
),
12948 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
12949 branch instructions generated by GCC for PLT relocs. */
12950 MAP ("(plt)", BFD_RELOC_ARM_PLT32
),
12951 { NULL
, 0, BFD_RELOC_UNUSED
}
12955 for (i
= 0, ip
= input_line_pointer
;
12956 i
< sizeof (id
) && (ISALNUM (*ip
) || ISPUNCT (*ip
));
12958 id
[i
] = TOLOWER (*ip
);
12960 for (i
= 0; reloc_map
[i
].str
; i
++)
12961 if (strncmp (id
, reloc_map
[i
].str
, reloc_map
[i
].len
) == 0)
12964 input_line_pointer
+= reloc_map
[i
].len
;
12966 return reloc_map
[i
].reloc
;
12970 s_arm_elf_cons (nbytes
)
12975 #ifdef md_flush_pending_output
12976 md_flush_pending_output ();
12979 if (is_it_end_of_statement ())
12981 demand_empty_rest_of_line ();
12985 #ifdef md_cons_align
12986 md_cons_align (nbytes
);
12989 mapping_state (MAP_DATA
);
12992 bfd_reloc_code_real_type reloc
;
12994 expression (& exp
);
12996 if (exp
.X_op
== O_symbol
12997 && * input_line_pointer
== '('
12998 && (reloc
= arm_parse_reloc ()) != BFD_RELOC_UNUSED
)
13000 reloc_howto_type
*howto
= bfd_reloc_type_lookup (stdoutput
, reloc
);
13001 int size
= bfd_get_reloc_size (howto
);
13004 as_bad ("%s relocations do not fit in %d bytes",
13005 howto
->name
, nbytes
);
13008 register char *p
= frag_more ((int) nbytes
);
13009 int offset
= nbytes
- size
;
13011 fix_new_exp (frag_now
, p
- frag_now
->fr_literal
+ offset
, size
,
13016 emit_expr (&exp
, (unsigned int) nbytes
);
13018 while (*input_line_pointer
++ == ',');
13020 /* Put terminator back into stream. */
13021 input_line_pointer
--;
13022 demand_empty_rest_of_line ();
13025 #endif /* OBJ_ELF */
13027 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
13028 of an rs_align_code fragment. */
13031 arm_handle_align (fragP
)
13034 static char const arm_noop
[4] = { 0x00, 0x00, 0xa0, 0xe1 };
13035 static char const thumb_noop
[2] = { 0xc0, 0x46 };
13036 static char const arm_bigend_noop
[4] = { 0xe1, 0xa0, 0x00, 0x00 };
13037 static char const thumb_bigend_noop
[2] = { 0x46, 0xc0 };
13039 int bytes
, fix
, noop_size
;
13043 if (fragP
->fr_type
!= rs_align_code
)
13046 bytes
= fragP
->fr_next
->fr_address
- fragP
->fr_address
- fragP
->fr_fix
;
13047 p
= fragP
->fr_literal
+ fragP
->fr_fix
;
13050 if (bytes
> MAX_MEM_FOR_RS_ALIGN_CODE
)
13051 bytes
&= MAX_MEM_FOR_RS_ALIGN_CODE
;
13053 if (fragP
->tc_frag_data
)
13055 if (target_big_endian
)
13056 noop
= thumb_bigend_noop
;
13059 noop_size
= sizeof (thumb_noop
);
13063 if (target_big_endian
)
13064 noop
= arm_bigend_noop
;
13067 noop_size
= sizeof (arm_noop
);
13070 if (bytes
& (noop_size
- 1))
13072 fix
= bytes
& (noop_size
- 1);
13073 memset (p
, 0, fix
);
13078 while (bytes
>= noop_size
)
13080 memcpy (p
, noop
, noop_size
);
13082 bytes
-= noop_size
;
13086 fragP
->fr_fix
+= fix
;
13087 fragP
->fr_var
= noop_size
;
13090 /* Called from md_do_align. Used to create an alignment
13091 frag in a code section. */
13094 arm_frag_align_code (n
, max
)
13100 /* We assume that there will never be a requirement
13101 to support alignments greater than 32 bytes. */
13102 if (max
> MAX_MEM_FOR_RS_ALIGN_CODE
)
13103 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
13105 p
= frag_var (rs_align_code
,
13106 MAX_MEM_FOR_RS_ALIGN_CODE
,
13108 (relax_substateT
) max
,
13116 /* Perform target specific initialisation of a frag. */
13119 arm_init_frag (fragP
)
13122 /* Record whether this frag is in an ARM or a THUMB area. */
13123 fragP
->tc_frag_data
= thumb_mode
;