2004-06-29 H.J. Lu <hongjiu.lu@intel.com>
[binutils.git] / gas / config / tc-arm.c
blob3f21c84a6ce6f07b995e3b5da4d28d39cbb7f3c9
1 /* tc-arm.c -- Assemble for the ARM
2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
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)
7 Cirrus coprocessor fixes by Petko Manolov (petkan@nucleusys.com)
8 Cirrus coprocessor fixes by Vladimir Ivanov (vladitx@nucleusys.com)
10 This file is part of GAS, the GNU Assembler.
12 GAS is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2, or (at your option)
15 any later version.
17 GAS is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with GAS; see the file COPYING. If not, write to the Free
24 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
25 02111-1307, USA. */
27 #include <string.h>
28 #define NO_RELOC 0
29 #include "as.h"
30 #include "safe-ctype.h"
32 /* Need TARGET_CPU. */
33 #include "config.h"
34 #include "subsegs.h"
35 #include "obstack.h"
36 #include "symbols.h"
37 #include "listing.h"
39 #ifdef OBJ_ELF
40 #include "elf/arm.h"
41 #include "dwarf2dbg.h"
42 #endif
44 /* XXX Set this to 1 after the next binutils release */
45 #define WARN_DEPRECATED 0
47 /* The following bitmasks control CPU extensions: */
48 #define ARM_EXT_V1 0x00000001 /* All processors (core set). */
49 #define ARM_EXT_V2 0x00000002 /* Multiply instructions. */
50 #define ARM_EXT_V2S 0x00000004 /* SWP instructions. */
51 #define ARM_EXT_V3 0x00000008 /* MSR MRS. */
52 #define ARM_EXT_V3M 0x00000010 /* Allow long multiplies. */
53 #define ARM_EXT_V4 0x00000020 /* Allow half word loads. */
54 #define ARM_EXT_V4T 0x00000040 /* Thumb v1. */
55 #define ARM_EXT_V5 0x00000080 /* Allow CLZ, etc. */
56 #define ARM_EXT_V5T 0x00000100 /* Thumb v2. */
57 #define ARM_EXT_V5ExP 0x00000200 /* DSP core set. */
58 #define ARM_EXT_V5E 0x00000400 /* DSP Double transfers. */
59 #define ARM_EXT_V5J 0x00000800 /* Jazelle extension. */
60 #define ARM_EXT_V6 0x00001000 /* ARM V6. */
62 /* Co-processor space extensions. */
63 #define ARM_CEXT_XSCALE 0x00800000 /* Allow MIA etc. */
64 #define ARM_CEXT_MAVERICK 0x00400000 /* Use Cirrus/DSP coprocessor. */
65 #define ARM_CEXT_IWMMXT 0x00200000 /* Intel Wireless MMX technology coprocessor. */
67 /* Architectures are the sum of the base and extensions. The ARM ARM (rev E)
68 defines the following: ARMv3, ARMv3M, ARMv4xM, ARMv4, ARMv4TxM, ARMv4T,
69 ARMv5xM, ARMv5, ARMv5TxM, ARMv5T, ARMv5TExP, ARMv5TE. To these we add
70 three more to cover cores prior to ARM6. Finally, there are cores which
71 implement further extensions in the co-processor space. */
72 #define ARM_ARCH_V1 ARM_EXT_V1
73 #define ARM_ARCH_V2 (ARM_ARCH_V1 | ARM_EXT_V2)
74 #define ARM_ARCH_V2S (ARM_ARCH_V2 | ARM_EXT_V2S)
75 #define ARM_ARCH_V3 (ARM_ARCH_V2S | ARM_EXT_V3)
76 #define ARM_ARCH_V3M (ARM_ARCH_V3 | ARM_EXT_V3M)
77 #define ARM_ARCH_V4xM (ARM_ARCH_V3 | ARM_EXT_V4)
78 #define ARM_ARCH_V4 (ARM_ARCH_V3M | ARM_EXT_V4)
79 #define ARM_ARCH_V4TxM (ARM_ARCH_V4xM | ARM_EXT_V4T)
80 #define ARM_ARCH_V4T (ARM_ARCH_V4 | ARM_EXT_V4T)
81 #define ARM_ARCH_V5xM (ARM_ARCH_V4xM | ARM_EXT_V5)
82 #define ARM_ARCH_V5 (ARM_ARCH_V4 | ARM_EXT_V5)
83 #define ARM_ARCH_V5TxM (ARM_ARCH_V5xM | ARM_EXT_V4T | ARM_EXT_V5T)
84 #define ARM_ARCH_V5T (ARM_ARCH_V5 | ARM_EXT_V4T | ARM_EXT_V5T)
85 #define ARM_ARCH_V5TExP (ARM_ARCH_V5T | ARM_EXT_V5ExP)
86 #define ARM_ARCH_V5TE (ARM_ARCH_V5TExP | ARM_EXT_V5E)
87 #define ARM_ARCH_V5TEJ (ARM_ARCH_V5TE | ARM_EXT_V5J)
88 #define ARM_ARCH_V6 (ARM_ARCH_V5TEJ | ARM_EXT_V6)
90 /* Processors with specific extensions in the co-processor space. */
91 #define ARM_ARCH_XSCALE (ARM_ARCH_V5TE | ARM_CEXT_XSCALE)
92 #define ARM_ARCH_IWMMXT (ARM_ARCH_XSCALE | ARM_CEXT_IWMMXT)
94 /* Some useful combinations: */
95 #define ARM_ANY 0x0000ffff /* Any basic core. */
96 #define ARM_ALL 0x00ffffff /* Any core + co-processor */
97 #define CPROC_ANY 0x00ff0000 /* Any co-processor */
98 #define FPU_ANY 0xff000000 /* Note this is ~ARM_ALL. */
101 #define FPU_FPA_EXT_V1 0x80000000 /* Base FPA instruction set. */
102 #define FPU_FPA_EXT_V2 0x40000000 /* LFM/SFM. */
103 #define FPU_VFP_EXT_NONE 0x20000000 /* Use VFP word-ordering. */
104 #define FPU_VFP_EXT_V1xD 0x10000000 /* Base VFP instruction set. */
105 #define FPU_VFP_EXT_V1 0x08000000 /* Double-precision insns. */
106 #define FPU_VFP_EXT_V2 0x04000000 /* ARM10E VFPr1. */
107 #define FPU_MAVERICK 0x02000000 /* Cirrus Maverick. */
108 #define FPU_NONE 0
110 #define FPU_ARCH_FPE FPU_FPA_EXT_V1
111 #define FPU_ARCH_FPA (FPU_ARCH_FPE | FPU_FPA_EXT_V2)
113 #define FPU_ARCH_VFP FPU_VFP_EXT_NONE
114 #define FPU_ARCH_VFP_V1xD (FPU_VFP_EXT_V1xD | FPU_VFP_EXT_NONE)
115 #define FPU_ARCH_VFP_V1 (FPU_ARCH_VFP_V1xD | FPU_VFP_EXT_V1)
116 #define FPU_ARCH_VFP_V2 (FPU_ARCH_VFP_V1 | FPU_VFP_EXT_V2)
118 #define FPU_ARCH_MAVERICK FPU_MAVERICK
120 enum arm_float_abi
122 ARM_FLOAT_ABI_HARD,
123 ARM_FLOAT_ABI_SOFTFP,
124 ARM_FLOAT_ABI_SOFT
127 /* Types of processor to assemble for. */
128 #define ARM_1 ARM_ARCH_V1
129 #define ARM_2 ARM_ARCH_V2
130 #define ARM_3 ARM_ARCH_V2S
131 #define ARM_250 ARM_ARCH_V2S
132 #define ARM_6 ARM_ARCH_V3
133 #define ARM_7 ARM_ARCH_V3
134 #define ARM_8 ARM_ARCH_V4
135 #define ARM_9 ARM_ARCH_V4T
136 #define ARM_STRONG ARM_ARCH_V4
137 #define ARM_CPU_MASK 0x0000000f /* XXX? */
139 #ifndef CPU_DEFAULT
140 #if defined __XSCALE__
141 #define CPU_DEFAULT (ARM_ARCH_XSCALE)
142 #else
143 #if defined __thumb__
144 #define CPU_DEFAULT (ARM_ARCH_V5T)
145 #else
146 #define CPU_DEFAULT ARM_ANY
147 #endif
148 #endif
149 #endif
151 #ifdef TE_LINUX
152 #define FPU_DEFAULT FPU_ARCH_FPA
153 #endif
155 #ifdef TE_NetBSD
156 #ifdef OBJ_ELF
157 #define FPU_DEFAULT FPU_ARCH_VFP /* Soft-float, but VFP order. */
158 #else
159 /* Legacy a.out format. */
160 #define FPU_DEFAULT FPU_ARCH_FPA /* Soft-float, but FPA order. */
161 #endif
162 #endif
164 /* For backwards compatibility we default to the FPA. */
165 #ifndef FPU_DEFAULT
166 #define FPU_DEFAULT FPU_ARCH_FPA
167 #endif
169 #define streq(a, b) (strcmp (a, b) == 0)
170 #define skip_whitespace(str) while (*(str) == ' ') ++(str)
172 static unsigned long cpu_variant;
173 static int target_oabi = 0;
175 /* Flags stored in private area of BFD structure. */
176 static int uses_apcs_26 = FALSE;
177 static int atpcs = FALSE;
178 static int support_interwork = FALSE;
179 static int uses_apcs_float = FALSE;
180 static int pic_code = FALSE;
182 /* Variables that we set while parsing command-line options. Once all
183 options have been read we re-process these values to set the real
184 assembly flags. */
185 static int legacy_cpu = -1;
186 static int legacy_fpu = -1;
188 static int mcpu_cpu_opt = -1;
189 static int mcpu_fpu_opt = -1;
190 static int march_cpu_opt = -1;
191 static int march_fpu_opt = -1;
192 static int mfpu_opt = -1;
193 static int mfloat_abi_opt = -1;
194 #ifdef OBJ_ELF
195 static int meabi_flags = EF_ARM_EABI_UNKNOWN;
196 #endif
198 /* This array holds the chars that always start a comment. If the
199 pre-processor is disabled, these aren't very useful. */
200 const char comment_chars[] = "@";
202 /* This array holds the chars that only start a comment at the beginning of
203 a line. If the line seems to have the form '# 123 filename'
204 .line and .file directives will appear in the pre-processed output. */
205 /* Note that input_file.c hand checks for '#' at the beginning of the
206 first line of the input file. This is because the compiler outputs
207 #NO_APP at the beginning of its output. */
208 /* Also note that comments like this one will always work. */
209 const char line_comment_chars[] = "#";
211 const char line_separator_chars[] = ";";
213 /* Chars that can be used to separate mant
214 from exp in floating point numbers. */
215 const char EXP_CHARS[] = "eE";
217 /* Chars that mean this number is a floating point constant. */
218 /* As in 0f12.456 */
219 /* or 0d1.2345e12 */
221 const char FLT_CHARS[] = "rRsSfFdDxXeEpP";
223 /* Prefix characters that indicate the start of an immediate
224 value. */
225 #define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
227 #ifdef OBJ_ELF
228 /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
229 symbolS * GOT_symbol;
230 #endif
232 /* Size of relocation record. */
233 const int md_reloc_size = 8;
235 /* 0: assemble for ARM,
236 1: assemble for Thumb,
237 2: assemble for Thumb even though target CPU does not support thumb
238 instructions. */
239 static int thumb_mode = 0;
241 typedef struct arm_fix
243 int thumb_mode;
244 } arm_fix_data;
246 struct arm_it
248 const char * error;
249 unsigned long instruction;
250 int size;
251 struct
253 bfd_reloc_code_real_type type;
254 expressionS exp;
255 int pc_rel;
256 } reloc;
259 struct arm_it inst;
261 enum asm_shift_index
263 SHIFT_LSL = 0,
264 SHIFT_LSR,
265 SHIFT_ASR,
266 SHIFT_ROR,
267 SHIFT_RRX
270 struct asm_shift_properties
272 enum asm_shift_index index;
273 unsigned long bit_field;
274 unsigned int allows_0 : 1;
275 unsigned int allows_32 : 1;
278 static const struct asm_shift_properties shift_properties [] =
280 { SHIFT_LSL, 0, 1, 0},
281 { SHIFT_LSR, 0x20, 0, 1},
282 { SHIFT_ASR, 0x40, 0, 1},
283 { SHIFT_ROR, 0x60, 0, 0},
284 { SHIFT_RRX, 0x60, 0, 0}
287 struct asm_shift_name
289 const char * name;
290 const struct asm_shift_properties * properties;
293 static const struct asm_shift_name shift_names [] =
295 { "asl", shift_properties + SHIFT_LSL },
296 { "lsl", shift_properties + SHIFT_LSL },
297 { "lsr", shift_properties + SHIFT_LSR },
298 { "asr", shift_properties + SHIFT_ASR },
299 { "ror", shift_properties + SHIFT_ROR },
300 { "rrx", shift_properties + SHIFT_RRX },
301 { "ASL", shift_properties + SHIFT_LSL },
302 { "LSL", shift_properties + SHIFT_LSL },
303 { "LSR", shift_properties + SHIFT_LSR },
304 { "ASR", shift_properties + SHIFT_ASR },
305 { "ROR", shift_properties + SHIFT_ROR },
306 { "RRX", shift_properties + SHIFT_RRX }
309 /* Any kind of shift is accepted. */
310 #define NO_SHIFT_RESTRICT 1
311 /* The shift operand must be an immediate value, not a register. */
312 #define SHIFT_IMMEDIATE 0
313 /* The shift must be LSL or ASR and the operand must be an immediate. */
314 #define SHIFT_LSL_OR_ASR_IMMEDIATE 2
315 /* The shift must be ASR and the operand must be an immediate. */
316 #define SHIFT_ASR_IMMEDIATE 3
317 /* The shift must be LSL and the operand must be an immediate. */
318 #define SHIFT_LSL_IMMEDIATE 4
320 #define NUM_FLOAT_VALS 8
322 const char * fp_const[] =
324 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
327 /* Number of littlenums required to hold an extended precision number. */
328 #define MAX_LITTLENUMS 6
330 LITTLENUM_TYPE fp_values[NUM_FLOAT_VALS][MAX_LITTLENUMS];
332 #define FAIL (-1)
333 #define SUCCESS (0)
335 /* Whether a Co-processor load/store operation accepts write-back forms. */
336 #define CP_WB_OK 1
337 #define CP_NO_WB 0
339 #define SUFF_S 1
340 #define SUFF_D 2
341 #define SUFF_E 3
342 #define SUFF_P 4
344 #define CP_T_X 0x00008000
345 #define CP_T_Y 0x00400000
346 #define CP_T_Pre 0x01000000
347 #define CP_T_UD 0x00800000
348 #define CP_T_WB 0x00200000
350 #define CONDS_BIT 0x00100000
351 #define LOAD_BIT 0x00100000
353 #define DOUBLE_LOAD_FLAG 0x00000001
355 struct asm_cond
357 const char * template;
358 unsigned long value;
361 #define COND_ALWAYS 0xe0000000
362 #define COND_MASK 0xf0000000
364 static const struct asm_cond conds[] =
366 {"eq", 0x00000000},
367 {"ne", 0x10000000},
368 {"cs", 0x20000000}, {"hs", 0x20000000},
369 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
370 {"mi", 0x40000000},
371 {"pl", 0x50000000},
372 {"vs", 0x60000000},
373 {"vc", 0x70000000},
374 {"hi", 0x80000000},
375 {"ls", 0x90000000},
376 {"ge", 0xa0000000},
377 {"lt", 0xb0000000},
378 {"gt", 0xc0000000},
379 {"le", 0xd0000000},
380 {"al", 0xe0000000},
381 {"nv", 0xf0000000}
384 struct asm_psr
386 const char *template;
387 bfd_boolean cpsr;
388 unsigned long field;
391 /* The bit that distinguishes CPSR and SPSR. */
392 #define SPSR_BIT (1 << 22)
394 /* How many bits to shift the PSR_xxx bits up by. */
395 #define PSR_SHIFT 16
397 #define PSR_c (1 << 0)
398 #define PSR_x (1 << 1)
399 #define PSR_s (1 << 2)
400 #define PSR_f (1 << 3)
402 static const struct asm_psr psrs[] =
404 {"CPSR", TRUE, PSR_c | PSR_f},
405 {"CPSR_all", TRUE, PSR_c | PSR_f},
406 {"SPSR", FALSE, PSR_c | PSR_f},
407 {"SPSR_all", FALSE, PSR_c | PSR_f},
408 {"CPSR_flg", TRUE, PSR_f},
409 {"CPSR_f", TRUE, PSR_f},
410 {"SPSR_flg", FALSE, PSR_f},
411 {"SPSR_f", FALSE, PSR_f},
412 {"CPSR_c", TRUE, PSR_c},
413 {"CPSR_ctl", TRUE, PSR_c},
414 {"SPSR_c", FALSE, PSR_c},
415 {"SPSR_ctl", FALSE, PSR_c},
416 {"CPSR_x", TRUE, PSR_x},
417 {"CPSR_s", TRUE, PSR_s},
418 {"SPSR_x", FALSE, PSR_x},
419 {"SPSR_s", FALSE, PSR_s},
420 /* Combinations of flags. */
421 {"CPSR_fs", TRUE, PSR_f | PSR_s},
422 {"CPSR_fx", TRUE, PSR_f | PSR_x},
423 {"CPSR_fc", TRUE, PSR_f | PSR_c},
424 {"CPSR_sf", TRUE, PSR_s | PSR_f},
425 {"CPSR_sx", TRUE, PSR_s | PSR_x},
426 {"CPSR_sc", TRUE, PSR_s | PSR_c},
427 {"CPSR_xf", TRUE, PSR_x | PSR_f},
428 {"CPSR_xs", TRUE, PSR_x | PSR_s},
429 {"CPSR_xc", TRUE, PSR_x | PSR_c},
430 {"CPSR_cf", TRUE, PSR_c | PSR_f},
431 {"CPSR_cs", TRUE, PSR_c | PSR_s},
432 {"CPSR_cx", TRUE, PSR_c | PSR_x},
433 {"CPSR_fsx", TRUE, PSR_f | PSR_s | PSR_x},
434 {"CPSR_fsc", TRUE, PSR_f | PSR_s | PSR_c},
435 {"CPSR_fxs", TRUE, PSR_f | PSR_x | PSR_s},
436 {"CPSR_fxc", TRUE, PSR_f | PSR_x | PSR_c},
437 {"CPSR_fcs", TRUE, PSR_f | PSR_c | PSR_s},
438 {"CPSR_fcx", TRUE, PSR_f | PSR_c | PSR_x},
439 {"CPSR_sfx", TRUE, PSR_s | PSR_f | PSR_x},
440 {"CPSR_sfc", TRUE, PSR_s | PSR_f | PSR_c},
441 {"CPSR_sxf", TRUE, PSR_s | PSR_x | PSR_f},
442 {"CPSR_sxc", TRUE, PSR_s | PSR_x | PSR_c},
443 {"CPSR_scf", TRUE, PSR_s | PSR_c | PSR_f},
444 {"CPSR_scx", TRUE, PSR_s | PSR_c | PSR_x},
445 {"CPSR_xfs", TRUE, PSR_x | PSR_f | PSR_s},
446 {"CPSR_xfc", TRUE, PSR_x | PSR_f | PSR_c},
447 {"CPSR_xsf", TRUE, PSR_x | PSR_s | PSR_f},
448 {"CPSR_xsc", TRUE, PSR_x | PSR_s | PSR_c},
449 {"CPSR_xcf", TRUE, PSR_x | PSR_c | PSR_f},
450 {"CPSR_xcs", TRUE, PSR_x | PSR_c | PSR_s},
451 {"CPSR_cfs", TRUE, PSR_c | PSR_f | PSR_s},
452 {"CPSR_cfx", TRUE, PSR_c | PSR_f | PSR_x},
453 {"CPSR_csf", TRUE, PSR_c | PSR_s | PSR_f},
454 {"CPSR_csx", TRUE, PSR_c | PSR_s | PSR_x},
455 {"CPSR_cxf", TRUE, PSR_c | PSR_x | PSR_f},
456 {"CPSR_cxs", TRUE, PSR_c | PSR_x | PSR_s},
457 {"CPSR_fsxc", TRUE, PSR_f | PSR_s | PSR_x | PSR_c},
458 {"CPSR_fscx", TRUE, PSR_f | PSR_s | PSR_c | PSR_x},
459 {"CPSR_fxsc", TRUE, PSR_f | PSR_x | PSR_s | PSR_c},
460 {"CPSR_fxcs", TRUE, PSR_f | PSR_x | PSR_c | PSR_s},
461 {"CPSR_fcsx", TRUE, PSR_f | PSR_c | PSR_s | PSR_x},
462 {"CPSR_fcxs", TRUE, PSR_f | PSR_c | PSR_x | PSR_s},
463 {"CPSR_sfxc", TRUE, PSR_s | PSR_f | PSR_x | PSR_c},
464 {"CPSR_sfcx", TRUE, PSR_s | PSR_f | PSR_c | PSR_x},
465 {"CPSR_sxfc", TRUE, PSR_s | PSR_x | PSR_f | PSR_c},
466 {"CPSR_sxcf", TRUE, PSR_s | PSR_x | PSR_c | PSR_f},
467 {"CPSR_scfx", TRUE, PSR_s | PSR_c | PSR_f | PSR_x},
468 {"CPSR_scxf", TRUE, PSR_s | PSR_c | PSR_x | PSR_f},
469 {"CPSR_xfsc", TRUE, PSR_x | PSR_f | PSR_s | PSR_c},
470 {"CPSR_xfcs", TRUE, PSR_x | PSR_f | PSR_c | PSR_s},
471 {"CPSR_xsfc", TRUE, PSR_x | PSR_s | PSR_f | PSR_c},
472 {"CPSR_xscf", TRUE, PSR_x | PSR_s | PSR_c | PSR_f},
473 {"CPSR_xcfs", TRUE, PSR_x | PSR_c | PSR_f | PSR_s},
474 {"CPSR_xcsf", TRUE, PSR_x | PSR_c | PSR_s | PSR_f},
475 {"CPSR_cfsx", TRUE, PSR_c | PSR_f | PSR_s | PSR_x},
476 {"CPSR_cfxs", TRUE, PSR_c | PSR_f | PSR_x | PSR_s},
477 {"CPSR_csfx", TRUE, PSR_c | PSR_s | PSR_f | PSR_x},
478 {"CPSR_csxf", TRUE, PSR_c | PSR_s | PSR_x | PSR_f},
479 {"CPSR_cxfs", TRUE, PSR_c | PSR_x | PSR_f | PSR_s},
480 {"CPSR_cxsf", TRUE, PSR_c | PSR_x | PSR_s | PSR_f},
481 {"SPSR_fs", FALSE, PSR_f | PSR_s},
482 {"SPSR_fx", FALSE, PSR_f | PSR_x},
483 {"SPSR_fc", FALSE, PSR_f | PSR_c},
484 {"SPSR_sf", FALSE, PSR_s | PSR_f},
485 {"SPSR_sx", FALSE, PSR_s | PSR_x},
486 {"SPSR_sc", FALSE, PSR_s | PSR_c},
487 {"SPSR_xf", FALSE, PSR_x | PSR_f},
488 {"SPSR_xs", FALSE, PSR_x | PSR_s},
489 {"SPSR_xc", FALSE, PSR_x | PSR_c},
490 {"SPSR_cf", FALSE, PSR_c | PSR_f},
491 {"SPSR_cs", FALSE, PSR_c | PSR_s},
492 {"SPSR_cx", FALSE, PSR_c | PSR_x},
493 {"SPSR_fsx", FALSE, PSR_f | PSR_s | PSR_x},
494 {"SPSR_fsc", FALSE, PSR_f | PSR_s | PSR_c},
495 {"SPSR_fxs", FALSE, PSR_f | PSR_x | PSR_s},
496 {"SPSR_fxc", FALSE, PSR_f | PSR_x | PSR_c},
497 {"SPSR_fcs", FALSE, PSR_f | PSR_c | PSR_s},
498 {"SPSR_fcx", FALSE, PSR_f | PSR_c | PSR_x},
499 {"SPSR_sfx", FALSE, PSR_s | PSR_f | PSR_x},
500 {"SPSR_sfc", FALSE, PSR_s | PSR_f | PSR_c},
501 {"SPSR_sxf", FALSE, PSR_s | PSR_x | PSR_f},
502 {"SPSR_sxc", FALSE, PSR_s | PSR_x | PSR_c},
503 {"SPSR_scf", FALSE, PSR_s | PSR_c | PSR_f},
504 {"SPSR_scx", FALSE, PSR_s | PSR_c | PSR_x},
505 {"SPSR_xfs", FALSE, PSR_x | PSR_f | PSR_s},
506 {"SPSR_xfc", FALSE, PSR_x | PSR_f | PSR_c},
507 {"SPSR_xsf", FALSE, PSR_x | PSR_s | PSR_f},
508 {"SPSR_xsc", FALSE, PSR_x | PSR_s | PSR_c},
509 {"SPSR_xcf", FALSE, PSR_x | PSR_c | PSR_f},
510 {"SPSR_xcs", FALSE, PSR_x | PSR_c | PSR_s},
511 {"SPSR_cfs", FALSE, PSR_c | PSR_f | PSR_s},
512 {"SPSR_cfx", FALSE, PSR_c | PSR_f | PSR_x},
513 {"SPSR_csf", FALSE, PSR_c | PSR_s | PSR_f},
514 {"SPSR_csx", FALSE, PSR_c | PSR_s | PSR_x},
515 {"SPSR_cxf", FALSE, PSR_c | PSR_x | PSR_f},
516 {"SPSR_cxs", FALSE, PSR_c | PSR_x | PSR_s},
517 {"SPSR_fsxc", FALSE, PSR_f | PSR_s | PSR_x | PSR_c},
518 {"SPSR_fscx", FALSE, PSR_f | PSR_s | PSR_c | PSR_x},
519 {"SPSR_fxsc", FALSE, PSR_f | PSR_x | PSR_s | PSR_c},
520 {"SPSR_fxcs", FALSE, PSR_f | PSR_x | PSR_c | PSR_s},
521 {"SPSR_fcsx", FALSE, PSR_f | PSR_c | PSR_s | PSR_x},
522 {"SPSR_fcxs", FALSE, PSR_f | PSR_c | PSR_x | PSR_s},
523 {"SPSR_sfxc", FALSE, PSR_s | PSR_f | PSR_x | PSR_c},
524 {"SPSR_sfcx", FALSE, PSR_s | PSR_f | PSR_c | PSR_x},
525 {"SPSR_sxfc", FALSE, PSR_s | PSR_x | PSR_f | PSR_c},
526 {"SPSR_sxcf", FALSE, PSR_s | PSR_x | PSR_c | PSR_f},
527 {"SPSR_scfx", FALSE, PSR_s | PSR_c | PSR_f | PSR_x},
528 {"SPSR_scxf", FALSE, PSR_s | PSR_c | PSR_x | PSR_f},
529 {"SPSR_xfsc", FALSE, PSR_x | PSR_f | PSR_s | PSR_c},
530 {"SPSR_xfcs", FALSE, PSR_x | PSR_f | PSR_c | PSR_s},
531 {"SPSR_xsfc", FALSE, PSR_x | PSR_s | PSR_f | PSR_c},
532 {"SPSR_xscf", FALSE, PSR_x | PSR_s | PSR_c | PSR_f},
533 {"SPSR_xcfs", FALSE, PSR_x | PSR_c | PSR_f | PSR_s},
534 {"SPSR_xcsf", FALSE, PSR_x | PSR_c | PSR_s | PSR_f},
535 {"SPSR_cfsx", FALSE, PSR_c | PSR_f | PSR_s | PSR_x},
536 {"SPSR_cfxs", FALSE, PSR_c | PSR_f | PSR_x | PSR_s},
537 {"SPSR_csfx", FALSE, PSR_c | PSR_s | PSR_f | PSR_x},
538 {"SPSR_csxf", FALSE, PSR_c | PSR_s | PSR_x | PSR_f},
539 {"SPSR_cxfs", FALSE, PSR_c | PSR_x | PSR_f | PSR_s},
540 {"SPSR_cxsf", FALSE, PSR_c | PSR_x | PSR_s | PSR_f},
543 enum wreg_type
545 IWMMXT_REG_WR = 0,
546 IWMMXT_REG_WC = 1,
547 IWMMXT_REG_WR_OR_WC = 2,
548 IWMMXT_REG_WCG
551 enum iwmmxt_insn_type
553 check_rd,
554 check_wr,
555 check_wrwr,
556 check_wrwrwr,
557 check_wrwrwcg,
558 check_tbcst,
559 check_tmovmsk,
560 check_tmia,
561 check_tmcrr,
562 check_tmrrc,
563 check_tmcr,
564 check_tmrc,
565 check_tinsr,
566 check_textrc,
567 check_waligni,
568 check_textrm,
569 check_wshufh
572 enum vfp_dp_reg_pos
574 VFP_REG_Dd, VFP_REG_Dm, VFP_REG_Dn
577 enum vfp_sp_reg_pos
579 VFP_REG_Sd, VFP_REG_Sm, VFP_REG_Sn
582 enum vfp_ldstm_type
584 VFP_LDSTMIA, VFP_LDSTMDB, VFP_LDSTMIAX, VFP_LDSTMDBX
587 /* VFP system registers. */
588 struct vfp_reg
590 const char *name;
591 unsigned long regno;
594 static const struct vfp_reg vfp_regs[] =
596 {"fpsid", 0x00000000},
597 {"FPSID", 0x00000000},
598 {"fpscr", 0x00010000},
599 {"FPSCR", 0x00010000},
600 {"fpexc", 0x00080000},
601 {"FPEXC", 0x00080000}
604 /* Structure for a hash table entry for a register. */
605 struct reg_entry
607 const char * name;
608 int number;
609 bfd_boolean builtin;
612 /* Some well known registers that we refer to directly elsewhere. */
613 #define REG_SP 13
614 #define REG_LR 14
615 #define REG_PC 15
617 #define wr_register(reg) ((reg ^ WR_PREFIX) >= 0 && (reg ^ WR_PREFIX) <= 15)
618 #define wc_register(reg) ((reg ^ WC_PREFIX) >= 0 && (reg ^ WC_PREFIX) <= 15)
619 #define wcg_register(reg) ((reg ^ WC_PREFIX) >= 8 && (reg ^ WC_PREFIX) <= 11)
621 /* These are the standard names. Users can add aliases with .req.
622 and delete them with .unreq. */
624 /* Integer Register Numbers. */
625 static const struct reg_entry rn_table[] =
627 {"r0", 0, TRUE}, {"r1", 1, TRUE}, {"r2", 2, TRUE}, {"r3", 3, TRUE},
628 {"r4", 4, TRUE}, {"r5", 5, TRUE}, {"r6", 6, TRUE}, {"r7", 7, TRUE},
629 {"r8", 8, TRUE}, {"r9", 9, TRUE}, {"r10", 10, TRUE}, {"r11", 11, TRUE},
630 {"r12", 12, TRUE}, {"r13", REG_SP, TRUE}, {"r14", REG_LR, TRUE}, {"r15", REG_PC, TRUE},
631 /* ATPCS Synonyms. */
632 {"a1", 0, TRUE}, {"a2", 1, TRUE}, {"a3", 2, TRUE}, {"a4", 3, TRUE},
633 {"v1", 4, TRUE}, {"v2", 5, TRUE}, {"v3", 6, TRUE}, {"v4", 7, TRUE},
634 {"v5", 8, TRUE}, {"v6", 9, TRUE}, {"v7", 10, TRUE}, {"v8", 11, TRUE},
635 /* Well-known aliases. */
636 {"wr", 7, TRUE}, {"sb", 9, TRUE}, {"sl", 10, TRUE}, {"fp", 11, TRUE},
637 {"ip", 12, TRUE}, {"sp", REG_SP, TRUE}, {"lr", REG_LR, TRUE}, {"pc", REG_PC, TRUE},
638 {NULL, 0, TRUE}
641 #define WR_PREFIX 0x200
642 #define WC_PREFIX 0x400
644 static const struct reg_entry iwmmxt_table[] =
646 /* Intel Wireless MMX technology register names. */
647 { "wr0", 0x0 | WR_PREFIX, TRUE}, {"wr1", 0x1 | WR_PREFIX, TRUE},
648 { "wr2", 0x2 | WR_PREFIX, TRUE}, {"wr3", 0x3 | WR_PREFIX, TRUE},
649 { "wr4", 0x4 | WR_PREFIX, TRUE}, {"wr5", 0x5 | WR_PREFIX, TRUE},
650 { "wr6", 0x6 | WR_PREFIX, TRUE}, {"wr7", 0x7 | WR_PREFIX, TRUE},
651 { "wr8", 0x8 | WR_PREFIX, TRUE}, {"wr9", 0x9 | WR_PREFIX, TRUE},
652 { "wr10", 0xa | WR_PREFIX, TRUE}, {"wr11", 0xb | WR_PREFIX, TRUE},
653 { "wr12", 0xc | WR_PREFIX, TRUE}, {"wr13", 0xd | WR_PREFIX, TRUE},
654 { "wr14", 0xe | WR_PREFIX, TRUE}, {"wr15", 0xf | WR_PREFIX, TRUE},
655 { "wcid", 0x0 | WC_PREFIX, TRUE}, {"wcon", 0x1 | WC_PREFIX, TRUE},
656 {"wcssf", 0x2 | WC_PREFIX, TRUE}, {"wcasf", 0x3 | WC_PREFIX, TRUE},
657 {"wcgr0", 0x8 | WC_PREFIX, TRUE}, {"wcgr1", 0x9 | WC_PREFIX, TRUE},
658 {"wcgr2", 0xa | WC_PREFIX, TRUE}, {"wcgr3", 0xb | WC_PREFIX, TRUE},
660 { "wR0", 0x0 | WR_PREFIX, TRUE}, {"wR1", 0x1 | WR_PREFIX, TRUE},
661 { "wR2", 0x2 | WR_PREFIX, TRUE}, {"wR3", 0x3 | WR_PREFIX, TRUE},
662 { "wR4", 0x4 | WR_PREFIX, TRUE}, {"wR5", 0x5 | WR_PREFIX, TRUE},
663 { "wR6", 0x6 | WR_PREFIX, TRUE}, {"wR7", 0x7 | WR_PREFIX, TRUE},
664 { "wR8", 0x8 | WR_PREFIX, TRUE}, {"wR9", 0x9 | WR_PREFIX, TRUE},
665 { "wR10", 0xa | WR_PREFIX, TRUE}, {"wR11", 0xb | WR_PREFIX, TRUE},
666 { "wR12", 0xc | WR_PREFIX, TRUE}, {"wR13", 0xd | WR_PREFIX, TRUE},
667 { "wR14", 0xe | WR_PREFIX, TRUE}, {"wR15", 0xf | WR_PREFIX, TRUE},
668 { "wCID", 0x0 | WC_PREFIX, TRUE}, {"wCon", 0x1 | WC_PREFIX, TRUE},
669 {"wCSSF", 0x2 | WC_PREFIX, TRUE}, {"wCASF", 0x3 | WC_PREFIX, TRUE},
670 {"wCGR0", 0x8 | WC_PREFIX, TRUE}, {"wCGR1", 0x9 | WC_PREFIX, TRUE},
671 {"wCGR2", 0xa | WC_PREFIX, TRUE}, {"wCGR3", 0xb | WC_PREFIX, TRUE},
672 {NULL, 0, TRUE}
675 /* Co-processor Numbers. */
676 static const struct reg_entry cp_table[] =
678 {"p0", 0, TRUE}, {"p1", 1, TRUE}, {"p2", 2, TRUE}, {"p3", 3, TRUE},
679 {"p4", 4, TRUE}, {"p5", 5, TRUE}, {"p6", 6, TRUE}, {"p7", 7, TRUE},
680 {"p8", 8, TRUE}, {"p9", 9, TRUE}, {"p10", 10, TRUE}, {"p11", 11, TRUE},
681 {"p12", 12, TRUE}, {"p13", 13, TRUE}, {"p14", 14, TRUE}, {"p15", 15, TRUE},
682 {NULL, 0, TRUE}
685 /* Co-processor Register Numbers. */
686 static const struct reg_entry cn_table[] =
688 {"c0", 0, TRUE}, {"c1", 1, TRUE}, {"c2", 2, TRUE}, {"c3", 3, TRUE},
689 {"c4", 4, TRUE}, {"c5", 5, TRUE}, {"c6", 6, TRUE}, {"c7", 7, TRUE},
690 {"c8", 8, TRUE}, {"c9", 9, TRUE}, {"c10", 10, TRUE}, {"c11", 11, TRUE},
691 {"c12", 12, TRUE}, {"c13", 13, TRUE}, {"c14", 14, TRUE}, {"c15", 15, TRUE},
692 /* Not really valid, but kept for back-wards compatibility. */
693 {"cr0", 0, TRUE}, {"cr1", 1, TRUE}, {"cr2", 2, TRUE}, {"cr3", 3, TRUE},
694 {"cr4", 4, TRUE}, {"cr5", 5, TRUE}, {"cr6", 6, TRUE}, {"cr7", 7, TRUE},
695 {"cr8", 8, TRUE}, {"cr9", 9, TRUE}, {"cr10", 10, TRUE}, {"cr11", 11, TRUE},
696 {"cr12", 12, TRUE}, {"cr13", 13, TRUE}, {"cr14", 14, TRUE}, {"cr15", 15, TRUE},
697 {NULL, 0, TRUE}
700 /* FPA Registers. */
701 static const struct reg_entry fn_table[] =
703 {"f0", 0, TRUE}, {"f1", 1, TRUE}, {"f2", 2, TRUE}, {"f3", 3, TRUE},
704 {"f4", 4, TRUE}, {"f5", 5, TRUE}, {"f6", 6, TRUE}, {"f7", 7, TRUE},
705 {NULL, 0, TRUE}
708 /* VFP SP Registers. */
709 static const struct reg_entry sn_table[] =
711 {"s0", 0, TRUE}, {"s1", 1, TRUE}, {"s2", 2, TRUE}, {"s3", 3, TRUE},
712 {"s4", 4, TRUE}, {"s5", 5, TRUE}, {"s6", 6, TRUE}, {"s7", 7, TRUE},
713 {"s8", 8, TRUE}, {"s9", 9, TRUE}, {"s10", 10, TRUE}, {"s11", 11, TRUE},
714 {"s12", 12, TRUE}, {"s13", 13, TRUE}, {"s14", 14, TRUE}, {"s15", 15, TRUE},
715 {"s16", 16, TRUE}, {"s17", 17, TRUE}, {"s18", 18, TRUE}, {"s19", 19, TRUE},
716 {"s20", 20, TRUE}, {"s21", 21, TRUE}, {"s22", 22, TRUE}, {"s23", 23, TRUE},
717 {"s24", 24, TRUE}, {"s25", 25, TRUE}, {"s26", 26, TRUE}, {"s27", 27, TRUE},
718 {"s28", 28, TRUE}, {"s29", 29, TRUE}, {"s30", 30, TRUE}, {"s31", 31, TRUE},
719 {NULL, 0, TRUE}
722 /* VFP DP Registers. */
723 static const struct reg_entry dn_table[] =
725 {"d0", 0, TRUE}, {"d1", 1, TRUE}, {"d2", 2, TRUE}, {"d3", 3, TRUE},
726 {"d4", 4, TRUE}, {"d5", 5, TRUE}, {"d6", 6, TRUE}, {"d7", 7, TRUE},
727 {"d8", 8, TRUE}, {"d9", 9, TRUE}, {"d10", 10, TRUE}, {"d11", 11, TRUE},
728 {"d12", 12, TRUE}, {"d13", 13, TRUE}, {"d14", 14, TRUE}, {"d15", 15, TRUE},
729 {NULL, 0, TRUE}
732 /* Maverick DSP coprocessor registers. */
733 static const struct reg_entry mav_mvf_table[] =
735 {"mvf0", 0, TRUE}, {"mvf1", 1, TRUE}, {"mvf2", 2, TRUE}, {"mvf3", 3, TRUE},
736 {"mvf4", 4, TRUE}, {"mvf5", 5, TRUE}, {"mvf6", 6, TRUE}, {"mvf7", 7, TRUE},
737 {"mvf8", 8, TRUE}, {"mvf9", 9, TRUE}, {"mvf10", 10, TRUE}, {"mvf11", 11, TRUE},
738 {"mvf12", 12, TRUE}, {"mvf13", 13, TRUE}, {"mvf14", 14, TRUE}, {"mvf15", 15, TRUE},
739 {NULL, 0, TRUE}
742 static const struct reg_entry mav_mvd_table[] =
744 {"mvd0", 0, TRUE}, {"mvd1", 1, TRUE}, {"mvd2", 2, TRUE}, {"mvd3", 3, TRUE},
745 {"mvd4", 4, TRUE}, {"mvd5", 5, TRUE}, {"mvd6", 6, TRUE}, {"mvd7", 7, TRUE},
746 {"mvd8", 8, TRUE}, {"mvd9", 9, TRUE}, {"mvd10", 10, TRUE}, {"mvd11", 11, TRUE},
747 {"mvd12", 12, TRUE}, {"mvd13", 13, TRUE}, {"mvd14", 14, TRUE}, {"mvd15", 15, TRUE},
748 {NULL, 0, TRUE}
751 static const struct reg_entry mav_mvfx_table[] =
753 {"mvfx0", 0, TRUE}, {"mvfx1", 1, TRUE}, {"mvfx2", 2, TRUE}, {"mvfx3", 3, TRUE},
754 {"mvfx4", 4, TRUE}, {"mvfx5", 5, TRUE}, {"mvfx6", 6, TRUE}, {"mvfx7", 7, TRUE},
755 {"mvfx8", 8, TRUE}, {"mvfx9", 9, TRUE}, {"mvfx10", 10, TRUE}, {"mvfx11", 11, TRUE},
756 {"mvfx12", 12, TRUE}, {"mvfx13", 13, TRUE}, {"mvfx14", 14, TRUE}, {"mvfx15", 15, TRUE},
757 {NULL, 0, TRUE}
760 static const struct reg_entry mav_mvdx_table[] =
762 {"mvdx0", 0, TRUE}, {"mvdx1", 1, TRUE}, {"mvdx2", 2, TRUE}, {"mvdx3", 3, TRUE},
763 {"mvdx4", 4, TRUE}, {"mvdx5", 5, TRUE}, {"mvdx6", 6, TRUE}, {"mvdx7", 7, TRUE},
764 {"mvdx8", 8, TRUE}, {"mvdx9", 9, TRUE}, {"mvdx10", 10, TRUE}, {"mvdx11", 11, TRUE},
765 {"mvdx12", 12, TRUE}, {"mvdx13", 13, TRUE}, {"mvdx14", 14, TRUE}, {"mvdx15", 15, TRUE},
766 {NULL, 0, TRUE}
769 static const struct reg_entry mav_mvax_table[] =
771 {"mvax0", 0, TRUE}, {"mvax1", 1, TRUE}, {"mvax2", 2, TRUE}, {"mvax3", 3, TRUE},
772 {NULL, 0, TRUE}
775 static const struct reg_entry mav_dspsc_table[] =
777 {"dspsc", 0, TRUE},
778 {NULL, 0, TRUE}
781 struct reg_map
783 const struct reg_entry *names;
784 int max_regno;
785 struct hash_control *htab;
786 const char *expected;
789 struct reg_map all_reg_maps[] =
791 {rn_table, 15, NULL, N_("ARM register expected")},
792 {cp_table, 15, NULL, N_("bad or missing co-processor number")},
793 {cn_table, 15, NULL, N_("co-processor register expected")},
794 {fn_table, 7, NULL, N_("FPA register expected")},
795 {sn_table, 31, NULL, N_("VFP single precision register expected")},
796 {dn_table, 15, NULL, N_("VFP double precision register expected")},
797 {mav_mvf_table, 15, NULL, N_("Maverick MVF register expected")},
798 {mav_mvd_table, 15, NULL, N_("Maverick MVD register expected")},
799 {mav_mvfx_table, 15, NULL, N_("Maverick MVFX register expected")},
800 {mav_mvdx_table, 15, NULL, N_("Maverick MVDX register expected")},
801 {mav_mvax_table, 3, NULL, N_("Maverick MVAX register expected")},
802 {mav_dspsc_table, 0, NULL, N_("Maverick DSPSC register expected")},
803 {iwmmxt_table, 23, NULL, N_("Intel Wireless MMX technology register expected")},
806 /* Enumeration matching entries in table above. */
807 enum arm_reg_type
809 REG_TYPE_RN = 0,
810 #define REG_TYPE_FIRST REG_TYPE_RN
811 REG_TYPE_CP = 1,
812 REG_TYPE_CN = 2,
813 REG_TYPE_FN = 3,
814 REG_TYPE_SN = 4,
815 REG_TYPE_DN = 5,
816 REG_TYPE_MVF = 6,
817 REG_TYPE_MVD = 7,
818 REG_TYPE_MVFX = 8,
819 REG_TYPE_MVDX = 9,
820 REG_TYPE_MVAX = 10,
821 REG_TYPE_DSPSC = 11,
822 REG_TYPE_IWMMXT = 12,
824 REG_TYPE_MAX = 13
827 /* Functions called by parser. */
828 /* ARM instructions. */
829 static void do_arit PARAMS ((char *));
830 static void do_cmp PARAMS ((char *));
831 static void do_mov PARAMS ((char *));
832 static void do_ldst PARAMS ((char *));
833 static void do_ldstt PARAMS ((char *));
834 static void do_ldmstm PARAMS ((char *));
835 static void do_branch PARAMS ((char *));
836 static void do_swi PARAMS ((char *));
838 /* Pseudo Op codes. */
839 static void do_adr PARAMS ((char *));
840 static void do_adrl PARAMS ((char *));
841 static void do_empty PARAMS ((char *));
843 /* ARM v2. */
844 static void do_mul PARAMS ((char *));
845 static void do_mla PARAMS ((char *));
847 /* ARM v2S. */
848 static void do_swap PARAMS ((char *));
850 /* ARM v3. */
851 static void do_msr PARAMS ((char *));
852 static void do_mrs PARAMS ((char *));
854 /* ARM v3M. */
855 static void do_mull PARAMS ((char *));
857 /* ARM v4. */
858 static void do_ldstv4 PARAMS ((char *));
860 /* ARM v4T. */
861 static void do_bx PARAMS ((char *));
863 /* ARM v5T. */
864 static void do_blx PARAMS ((char *));
865 static void do_bkpt PARAMS ((char *));
866 static void do_clz PARAMS ((char *));
867 static void do_lstc2 PARAMS ((char *));
868 static void do_cdp2 PARAMS ((char *));
869 static void do_co_reg2 PARAMS ((char *));
871 /* ARM v5TExP. */
872 static void do_smla PARAMS ((char *));
873 static void do_smlal PARAMS ((char *));
874 static void do_smul PARAMS ((char *));
875 static void do_qadd PARAMS ((char *));
877 /* ARM v5TE. */
878 static void do_pld PARAMS ((char *));
879 static void do_ldrd PARAMS ((char *));
880 static void do_co_reg2c PARAMS ((char *));
882 /* ARM v5TEJ. */
883 static void do_bxj PARAMS ((char *));
885 /* ARM V6. */
886 static void do_cps PARAMS ((char *));
887 static void do_cpsi PARAMS ((char *));
888 static void do_ldrex PARAMS ((char *));
889 static void do_pkhbt PARAMS ((char *));
890 static void do_pkhtb PARAMS ((char *));
891 static void do_qadd16 PARAMS ((char *));
892 static void do_rev PARAMS ((char *));
893 static void do_rfe PARAMS ((char *));
894 static void do_sxtah PARAMS ((char *));
895 static void do_sxth PARAMS ((char *));
896 static void do_setend PARAMS ((char *));
897 static void do_smlad PARAMS ((char *));
898 static void do_smlald PARAMS ((char *));
899 static void do_smmul PARAMS ((char *));
900 static void do_ssat PARAMS ((char *));
901 static void do_usat PARAMS ((char *));
902 static void do_srs PARAMS ((char *));
903 static void do_ssat16 PARAMS ((char *));
904 static void do_usat16 PARAMS ((char *));
905 static void do_strex PARAMS ((char *));
906 static void do_umaal PARAMS ((char *));
908 static void do_cps_mode PARAMS ((char **));
909 static void do_cps_flags PARAMS ((char **, int));
910 static int do_endian_specifier PARAMS ((char *));
911 static void do_pkh_core PARAMS ((char *, int));
912 static void do_sat PARAMS ((char **, int));
913 static void do_sat16 PARAMS ((char **, int));
915 /* Coprocessor Instructions. */
916 static void do_cdp PARAMS ((char *));
917 static void do_lstc PARAMS ((char *));
918 static void do_co_reg PARAMS ((char *));
920 /* FPA instructions. */
921 static void do_fpa_ctrl PARAMS ((char *));
922 static void do_fpa_ldst PARAMS ((char *));
923 static void do_fpa_ldmstm PARAMS ((char *));
924 static void do_fpa_dyadic PARAMS ((char *));
925 static void do_fpa_monadic PARAMS ((char *));
926 static void do_fpa_cmp PARAMS ((char *));
927 static void do_fpa_from_reg PARAMS ((char *));
928 static void do_fpa_to_reg PARAMS ((char *));
930 /* VFP instructions. */
931 static void do_vfp_sp_monadic PARAMS ((char *));
932 static void do_vfp_dp_monadic PARAMS ((char *));
933 static void do_vfp_sp_dyadic PARAMS ((char *));
934 static void do_vfp_dp_dyadic PARAMS ((char *));
935 static void do_vfp_reg_from_sp PARAMS ((char *));
936 static void do_vfp_sp_from_reg PARAMS ((char *));
937 static void do_vfp_reg2_from_sp2 PARAMS ((char *));
938 static void do_vfp_sp2_from_reg2 PARAMS ((char *));
939 static void do_vfp_reg_from_dp PARAMS ((char *));
940 static void do_vfp_reg2_from_dp PARAMS ((char *));
941 static void do_vfp_dp_from_reg PARAMS ((char *));
942 static void do_vfp_dp_from_reg2 PARAMS ((char *));
943 static void do_vfp_reg_from_ctrl PARAMS ((char *));
944 static void do_vfp_ctrl_from_reg PARAMS ((char *));
945 static void do_vfp_sp_ldst PARAMS ((char *));
946 static void do_vfp_dp_ldst PARAMS ((char *));
947 static void do_vfp_sp_ldstmia PARAMS ((char *));
948 static void do_vfp_sp_ldstmdb PARAMS ((char *));
949 static void do_vfp_dp_ldstmia PARAMS ((char *));
950 static void do_vfp_dp_ldstmdb PARAMS ((char *));
951 static void do_vfp_xp_ldstmia PARAMS ((char *));
952 static void do_vfp_xp_ldstmdb PARAMS ((char *));
953 static void do_vfp_sp_compare_z PARAMS ((char *));
954 static void do_vfp_dp_compare_z PARAMS ((char *));
955 static void do_vfp_dp_sp_cvt PARAMS ((char *));
956 static void do_vfp_sp_dp_cvt PARAMS ((char *));
958 /* XScale. */
959 static void do_xsc_mia PARAMS ((char *));
960 static void do_xsc_mar PARAMS ((char *));
961 static void do_xsc_mra PARAMS ((char *));
963 /* Maverick. */
964 static void do_mav_binops PARAMS ((char *, int, enum arm_reg_type,
965 enum arm_reg_type));
966 static void do_mav_binops_1a PARAMS ((char *));
967 static void do_mav_binops_1b PARAMS ((char *));
968 static void do_mav_binops_1c PARAMS ((char *));
969 static void do_mav_binops_1d PARAMS ((char *));
970 static void do_mav_binops_1e PARAMS ((char *));
971 static void do_mav_binops_1f PARAMS ((char *));
972 static void do_mav_binops_1g PARAMS ((char *));
973 static void do_mav_binops_1h PARAMS ((char *));
974 static void do_mav_binops_1i PARAMS ((char *));
975 static void do_mav_binops_1j PARAMS ((char *));
976 static void do_mav_binops_1k PARAMS ((char *));
977 static void do_mav_binops_1l PARAMS ((char *));
978 static void do_mav_binops_1m PARAMS ((char *));
979 static void do_mav_binops_1n PARAMS ((char *));
980 static void do_mav_binops_1o PARAMS ((char *));
981 static void do_mav_binops_2a PARAMS ((char *));
982 static void do_mav_binops_2b PARAMS ((char *));
983 static void do_mav_binops_2c PARAMS ((char *));
984 static void do_mav_binops_3a PARAMS ((char *));
985 static void do_mav_binops_3b PARAMS ((char *));
986 static void do_mav_binops_3c PARAMS ((char *));
987 static void do_mav_binops_3d PARAMS ((char *));
988 static void do_mav_triple PARAMS ((char *, int, enum arm_reg_type,
989 enum arm_reg_type,
990 enum arm_reg_type));
991 static void do_mav_triple_4a PARAMS ((char *));
992 static void do_mav_triple_4b PARAMS ((char *));
993 static void do_mav_triple_5a PARAMS ((char *));
994 static void do_mav_triple_5b PARAMS ((char *));
995 static void do_mav_triple_5c PARAMS ((char *));
996 static void do_mav_triple_5d PARAMS ((char *));
997 static void do_mav_triple_5e PARAMS ((char *));
998 static void do_mav_triple_5f PARAMS ((char *));
999 static void do_mav_triple_5g PARAMS ((char *));
1000 static void do_mav_triple_5h PARAMS ((char *));
1001 static void do_mav_quad PARAMS ((char *, int, enum arm_reg_type,
1002 enum arm_reg_type,
1003 enum arm_reg_type,
1004 enum arm_reg_type));
1005 static void do_mav_quad_6a PARAMS ((char *));
1006 static void do_mav_quad_6b PARAMS ((char *));
1007 static void do_mav_dspsc_1 PARAMS ((char *));
1008 static void do_mav_dspsc_2 PARAMS ((char *));
1009 static void do_mav_shift PARAMS ((char *, enum arm_reg_type,
1010 enum arm_reg_type));
1011 static void do_mav_shift_1 PARAMS ((char *));
1012 static void do_mav_shift_2 PARAMS ((char *));
1013 static void do_mav_ldst PARAMS ((char *, enum arm_reg_type));
1014 static void do_mav_ldst_1 PARAMS ((char *));
1015 static void do_mav_ldst_2 PARAMS ((char *));
1016 static void do_mav_ldst_3 PARAMS ((char *));
1017 static void do_mav_ldst_4 PARAMS ((char *));
1019 static int mav_reg_required_here PARAMS ((char **, int,
1020 enum arm_reg_type));
1021 static int mav_parse_offset PARAMS ((char **, int *));
1023 static void fix_new_arm PARAMS ((fragS *, int, short, expressionS *,
1024 int, int));
1025 static int arm_reg_parse PARAMS ((char **, struct hash_control *));
1026 static enum arm_reg_type arm_reg_parse_any PARAMS ((char *));
1027 static const struct asm_psr * arm_psr_parse PARAMS ((char **));
1028 static void symbol_locate PARAMS ((symbolS *, const char *, segT, valueT,
1029 fragS *));
1030 static int add_to_lit_pool PARAMS ((void));
1031 static unsigned validate_immediate PARAMS ((unsigned));
1032 static unsigned validate_immediate_twopart PARAMS ((unsigned int,
1033 unsigned int *));
1034 static int validate_offset_imm PARAMS ((unsigned int, int));
1035 static void opcode_select PARAMS ((int));
1036 static void end_of_line PARAMS ((char *));
1037 static int reg_required_here PARAMS ((char **, int));
1038 static int psr_required_here PARAMS ((char **));
1039 static int co_proc_number PARAMS ((char **));
1040 static int cp_opc_expr PARAMS ((char **, int, int));
1041 static int cp_reg_required_here PARAMS ((char **, int));
1042 static int fp_reg_required_here PARAMS ((char **, int));
1043 static int vfp_sp_reg_required_here PARAMS ((char **, enum vfp_sp_reg_pos));
1044 static int vfp_dp_reg_required_here PARAMS ((char **, enum vfp_dp_reg_pos));
1045 static void vfp_sp_ldstm PARAMS ((char *, enum vfp_ldstm_type));
1046 static void vfp_dp_ldstm PARAMS ((char *, enum vfp_ldstm_type));
1047 static long vfp_sp_reg_list PARAMS ((char **, enum vfp_sp_reg_pos));
1048 static long vfp_dp_reg_list PARAMS ((char **));
1049 static int vfp_psr_required_here PARAMS ((char **str));
1050 static const struct vfp_reg *vfp_psr_parse PARAMS ((char **str));
1051 static int cp_address_offset PARAMS ((char **));
1052 static int cp_address_required_here PARAMS ((char **, int));
1053 static int my_get_float_expression PARAMS ((char **));
1054 static int skip_past_comma PARAMS ((char **));
1055 static int walk_no_bignums PARAMS ((symbolS *));
1056 static int negate_data_op PARAMS ((unsigned long *, unsigned long));
1057 static int data_op2 PARAMS ((char **));
1058 static int fp_op2 PARAMS ((char **));
1059 static long reg_list PARAMS ((char **));
1060 static void thumb_load_store PARAMS ((char *, int, int));
1061 static int decode_shift PARAMS ((char **, int));
1062 static int ldst_extend PARAMS ((char **));
1063 static int ldst_extend_v4 PARAMS ((char **));
1064 static void thumb_add_sub PARAMS ((char *, int));
1065 static void insert_reg PARAMS ((const struct reg_entry *,
1066 struct hash_control *));
1067 static void thumb_shift PARAMS ((char *, int));
1068 static void thumb_mov_compare PARAMS ((char *, int));
1069 static void build_arm_ops_hsh PARAMS ((void));
1070 static void set_constant_flonums PARAMS ((void));
1071 static valueT md_chars_to_number PARAMS ((char *, int));
1072 static void build_reg_hsh PARAMS ((struct reg_map *));
1073 static void insert_reg_alias PARAMS ((char *, int, struct hash_control *));
1074 static int create_register_alias PARAMS ((char *, char *));
1075 static void output_inst PARAMS ((const char *));
1076 static int accum0_required_here PARAMS ((char **));
1077 static int ld_mode_required_here PARAMS ((char **));
1078 static void do_branch25 PARAMS ((char *));
1079 static symbolS * find_real_start PARAMS ((symbolS *));
1080 #ifdef OBJ_ELF
1081 static bfd_reloc_code_real_type arm_parse_reloc PARAMS ((void));
1082 #endif
1084 static int wreg_required_here PARAMS ((char **, int, enum wreg_type));
1085 static void do_iwmmxt_byte_addr PARAMS ((char *));
1086 static void do_iwmmxt_tandc PARAMS ((char *));
1087 static void do_iwmmxt_tbcst PARAMS ((char *));
1088 static void do_iwmmxt_textrc PARAMS ((char *));
1089 static void do_iwmmxt_textrm PARAMS ((char *));
1090 static void do_iwmmxt_tinsr PARAMS ((char *));
1091 static void do_iwmmxt_tmcr PARAMS ((char *));
1092 static void do_iwmmxt_tmcrr PARAMS ((char *));
1093 static void do_iwmmxt_tmia PARAMS ((char *));
1094 static void do_iwmmxt_tmovmsk PARAMS ((char *));
1095 static void do_iwmmxt_tmrc PARAMS ((char *));
1096 static void do_iwmmxt_tmrrc PARAMS ((char *));
1097 static void do_iwmmxt_torc PARAMS ((char *));
1098 static void do_iwmmxt_waligni PARAMS ((char *));
1099 static void do_iwmmxt_wmov PARAMS ((char *));
1100 static void do_iwmmxt_word_addr PARAMS ((char *));
1101 static void do_iwmmxt_wrwr PARAMS ((char *));
1102 static void do_iwmmxt_wrwrwcg PARAMS ((char *));
1103 static void do_iwmmxt_wrwrwr PARAMS ((char *));
1104 static void do_iwmmxt_wshufh PARAMS ((char *));
1105 static void do_iwmmxt_wzero PARAMS ((char *));
1106 static int cp_byte_address_offset PARAMS ((char **));
1107 static int cp_byte_address_required_here PARAMS ((char **));
1109 /* ARM instructions take 4bytes in the object file, Thumb instructions
1110 take 2: */
1111 #define INSN_SIZE 4
1113 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
1114 #define MAV_MODE1 0x100c
1116 /* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
1117 #define MAV_MODE2 0x0c10
1119 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
1120 #define MAV_MODE3 0x100c
1122 /* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
1123 #define MAV_MODE4 0x0c0010
1125 /* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
1126 #define MAV_MODE5 0x00100c
1128 /* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
1129 #define MAV_MODE6 0x00100c05
1131 struct asm_opcode
1133 /* Basic string to match. */
1134 const char * template;
1136 /* Basic instruction code. */
1137 unsigned long value;
1139 /* Offset into the template where the condition code (if any) will be.
1140 If zero, then the instruction is never conditional. */
1141 unsigned cond_offset;
1143 /* Which architecture variant provides this instruction. */
1144 unsigned long variant;
1146 /* Function to call to parse args. */
1147 void (* parms) PARAMS ((char *));
1150 static const struct asm_opcode insns[] =
1152 /* Core ARM Instructions. */
1153 {"and", 0xe0000000, 3, ARM_EXT_V1, do_arit},
1154 {"ands", 0xe0100000, 3, ARM_EXT_V1, do_arit},
1155 {"eor", 0xe0200000, 3, ARM_EXT_V1, do_arit},
1156 {"eors", 0xe0300000, 3, ARM_EXT_V1, do_arit},
1157 {"sub", 0xe0400000, 3, ARM_EXT_V1, do_arit},
1158 {"subs", 0xe0500000, 3, ARM_EXT_V1, do_arit},
1159 {"rsb", 0xe0600000, 3, ARM_EXT_V1, do_arit},
1160 {"rsbs", 0xe0700000, 3, ARM_EXT_V1, do_arit},
1161 {"add", 0xe0800000, 3, ARM_EXT_V1, do_arit},
1162 {"adds", 0xe0900000, 3, ARM_EXT_V1, do_arit},
1163 {"adc", 0xe0a00000, 3, ARM_EXT_V1, do_arit},
1164 {"adcs", 0xe0b00000, 3, ARM_EXT_V1, do_arit},
1165 {"sbc", 0xe0c00000, 3, ARM_EXT_V1, do_arit},
1166 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1, do_arit},
1167 {"rsc", 0xe0e00000, 3, ARM_EXT_V1, do_arit},
1168 {"rscs", 0xe0f00000, 3, ARM_EXT_V1, do_arit},
1169 {"orr", 0xe1800000, 3, ARM_EXT_V1, do_arit},
1170 {"orrs", 0xe1900000, 3, ARM_EXT_V1, do_arit},
1171 {"bic", 0xe1c00000, 3, ARM_EXT_V1, do_arit},
1172 {"bics", 0xe1d00000, 3, ARM_EXT_V1, do_arit},
1174 {"tst", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
1175 {"tsts", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
1176 {"tstp", 0xe110f000, 3, ARM_EXT_V1, do_cmp},
1177 {"teq", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
1178 {"teqs", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
1179 {"teqp", 0xe130f000, 3, ARM_EXT_V1, do_cmp},
1180 {"cmp", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
1181 {"cmps", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
1182 {"cmpp", 0xe150f000, 3, ARM_EXT_V1, do_cmp},
1183 {"cmn", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
1184 {"cmns", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
1185 {"cmnp", 0xe170f000, 3, ARM_EXT_V1, do_cmp},
1187 {"mov", 0xe1a00000, 3, ARM_EXT_V1, do_mov},
1188 {"movs", 0xe1b00000, 3, ARM_EXT_V1, do_mov},
1189 {"mvn", 0xe1e00000, 3, ARM_EXT_V1, do_mov},
1190 {"mvns", 0xe1f00000, 3, ARM_EXT_V1, do_mov},
1192 {"ldr", 0xe4100000, 3, ARM_EXT_V1, do_ldst},
1193 {"ldrb", 0xe4500000, 3, ARM_EXT_V1, do_ldst},
1194 {"ldrt", 0xe4300000, 3, ARM_EXT_V1, do_ldstt},
1195 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1, do_ldstt},
1196 {"str", 0xe4000000, 3, ARM_EXT_V1, do_ldst},
1197 {"strb", 0xe4400000, 3, ARM_EXT_V1, do_ldst},
1198 {"strt", 0xe4200000, 3, ARM_EXT_V1, do_ldstt},
1199 {"strbt", 0xe4600000, 3, ARM_EXT_V1, do_ldstt},
1201 {"stmia", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
1202 {"stmib", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
1203 {"stmda", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
1204 {"stmdb", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
1205 {"stmfd", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
1206 {"stmfa", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
1207 {"stmea", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
1208 {"stmed", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
1210 {"ldmia", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
1211 {"ldmib", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
1212 {"ldmda", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
1213 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
1214 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
1215 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
1216 {"ldmea", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
1217 {"ldmed", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
1219 {"swi", 0xef000000, 3, ARM_EXT_V1, do_swi},
1220 #ifdef TE_WINCE
1221 /* XXX This is the wrong place to do this. Think multi-arch. */
1222 {"bl", 0xeb000000, 2, ARM_EXT_V1, do_branch},
1223 {"b", 0xea000000, 1, ARM_EXT_V1, do_branch},
1224 #else
1225 {"bl", 0xebfffffe, 2, ARM_EXT_V1, do_branch},
1226 {"b", 0xeafffffe, 1, ARM_EXT_V1, do_branch},
1227 #endif
1229 /* Pseudo ops. */
1230 {"adr", 0xe28f0000, 3, ARM_EXT_V1, do_adr},
1231 {"adrl", 0xe28f0000, 3, ARM_EXT_V1, do_adrl},
1232 {"nop", 0xe1a00000, 3, ARM_EXT_V1, do_empty},
1234 /* ARM 2 multiplies. */
1235 {"mul", 0xe0000090, 3, ARM_EXT_V2, do_mul},
1236 {"muls", 0xe0100090, 3, ARM_EXT_V2, do_mul},
1237 {"mla", 0xe0200090, 3, ARM_EXT_V2, do_mla},
1238 {"mlas", 0xe0300090, 3, ARM_EXT_V2, do_mla},
1240 /* Generic coprocessor instructions. */
1241 {"cdp", 0xee000000, 3, ARM_EXT_V2, do_cdp},
1242 {"ldc", 0xec100000, 3, ARM_EXT_V2, do_lstc},
1243 {"ldcl", 0xec500000, 3, ARM_EXT_V2, do_lstc},
1244 {"stc", 0xec000000, 3, ARM_EXT_V2, do_lstc},
1245 {"stcl", 0xec400000, 3, ARM_EXT_V2, do_lstc},
1246 {"mcr", 0xee000010, 3, ARM_EXT_V2, do_co_reg},
1247 {"mrc", 0xee100010, 3, ARM_EXT_V2, do_co_reg},
1249 /* ARM 3 - swp instructions. */
1250 {"swp", 0xe1000090, 3, ARM_EXT_V2S, do_swap},
1251 {"swpb", 0xe1400090, 3, ARM_EXT_V2S, do_swap},
1253 /* ARM 6 Status register instructions. */
1254 {"mrs", 0xe10f0000, 3, ARM_EXT_V3, do_mrs},
1255 {"msr", 0xe120f000, 3, ARM_EXT_V3, do_msr},
1256 /* ScottB: our code uses 0xe128f000 for msr.
1257 NickC: but this is wrong because the bits 16 through 19 are
1258 handled by the PSR_xxx defines above. */
1260 /* ARM 7M long multiplies. */
1261 {"smull", 0xe0c00090, 5, ARM_EXT_V3M, do_mull},
1262 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M, do_mull},
1263 {"umull", 0xe0800090, 5, ARM_EXT_V3M, do_mull},
1264 {"umulls", 0xe0900090, 5, ARM_EXT_V3M, do_mull},
1265 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M, do_mull},
1266 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M, do_mull},
1267 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M, do_mull},
1268 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M, do_mull},
1270 /* ARM Architecture 4. */
1271 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4, do_ldstv4},
1272 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4, do_ldstv4},
1273 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4, do_ldstv4},
1274 {"strh", 0xe00000b0, 3, ARM_EXT_V4, do_ldstv4},
1276 /* ARM Architecture 4T. */
1277 /* Note: bx (and blx) are required on V5, even if the processor does
1278 not support Thumb. */
1279 {"bx", 0xe12fff10, 2, ARM_EXT_V4T | ARM_EXT_V5, do_bx},
1281 /* ARM Architecture 5T. */
1282 /* Note: blx has 2 variants, so the .value is set dynamically.
1283 Only one of the variants has conditional execution. */
1284 {"blx", 0xe0000000, 3, ARM_EXT_V5, do_blx},
1285 {"clz", 0xe16f0f10, 3, ARM_EXT_V5, do_clz},
1286 {"bkpt", 0xe1200070, 0, ARM_EXT_V5, do_bkpt},
1287 {"ldc2", 0xfc100000, 0, ARM_EXT_V5, do_lstc2},
1288 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5, do_lstc2},
1289 {"stc2", 0xfc000000, 0, ARM_EXT_V5, do_lstc2},
1290 {"stc2l", 0xfc400000, 0, ARM_EXT_V5, do_lstc2},
1291 {"cdp2", 0xfe000000, 0, ARM_EXT_V5, do_cdp2},
1292 {"mcr2", 0xfe000010, 0, ARM_EXT_V5, do_co_reg2},
1293 {"mrc2", 0xfe100010, 0, ARM_EXT_V5, do_co_reg2},
1295 /* ARM Architecture 5TExP. */
1296 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP, do_smla},
1297 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP, do_smla},
1298 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP, do_smla},
1299 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP, do_smla},
1301 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP, do_smla},
1302 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP, do_smla},
1304 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP, do_smlal},
1305 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP, do_smlal},
1306 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP, do_smlal},
1307 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP, do_smlal},
1309 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP, do_smul},
1310 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP, do_smul},
1311 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP, do_smul},
1312 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP, do_smul},
1314 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP, do_smul},
1315 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP, do_smul},
1317 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP, do_qadd},
1318 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP, do_qadd},
1319 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP, do_qadd},
1320 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP, do_qadd},
1322 /* ARM Architecture 5TE. */
1323 {"pld", 0xf450f000, 0, ARM_EXT_V5E, do_pld},
1324 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E, do_ldrd},
1325 {"strd", 0xe00000f0, 3, ARM_EXT_V5E, do_ldrd},
1327 {"mcrr", 0xec400000, 4, ARM_EXT_V5E, do_co_reg2c},
1328 {"mrrc", 0xec500000, 4, ARM_EXT_V5E, do_co_reg2c},
1330 /* ARM Architecture 5TEJ. */
1331 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J, do_bxj},
1333 /* ARM V6. */
1334 { "cps", 0xf1020000, 0, ARM_EXT_V6, do_cps},
1335 { "cpsie", 0xf1080000, 0, ARM_EXT_V6, do_cpsi},
1336 { "cpsid", 0xf10C0000, 0, ARM_EXT_V6, do_cpsi},
1337 { "ldrex", 0xe1900f9f, 5, ARM_EXT_V6, do_ldrex},
1338 { "mcrr2", 0xfc400000, 0, ARM_EXT_V6, do_co_reg2c},
1339 { "mrrc2", 0xfc500000, 0, ARM_EXT_V6, do_co_reg2c},
1340 { "pkhbt", 0xe6800010, 5, ARM_EXT_V6, do_pkhbt},
1341 { "pkhtb", 0xe6800050, 5, ARM_EXT_V6, do_pkhtb},
1342 { "qadd16", 0xe6200f10, 6, ARM_EXT_V6, do_qadd16},
1343 { "qadd8", 0xe6200f90, 5, ARM_EXT_V6, do_qadd16},
1344 { "qaddsubx", 0xe6200f30, 8, ARM_EXT_V6, do_qadd16},
1345 { "qsub16", 0xe6200f70, 6, ARM_EXT_V6, do_qadd16},
1346 { "qsub8", 0xe6200ff0, 5, ARM_EXT_V6, do_qadd16},
1347 { "qsubaddx", 0xe6200f50, 8, ARM_EXT_V6, do_qadd16},
1348 { "sadd16", 0xe6100f10, 6, ARM_EXT_V6, do_qadd16},
1349 { "sadd8", 0xe6100f90, 5, ARM_EXT_V6, do_qadd16},
1350 { "saddsubx", 0xe6100f30, 8, ARM_EXT_V6, do_qadd16},
1351 { "shadd16", 0xe6300f10, 7, ARM_EXT_V6, do_qadd16},
1352 { "shadd8", 0xe6300f90, 6, ARM_EXT_V6, do_qadd16},
1353 { "shaddsubx", 0xe6300f30, 9, ARM_EXT_V6, do_qadd16},
1354 { "shsub16", 0xe6300f70, 7, ARM_EXT_V6, do_qadd16},
1355 { "shsub8", 0xe6300ff0, 6, ARM_EXT_V6, do_qadd16},
1356 { "shsubaddx", 0xe6300f50, 9, ARM_EXT_V6, do_qadd16},
1357 { "ssub16", 0xe6100f70, 6, ARM_EXT_V6, do_qadd16},
1358 { "ssub8", 0xe6100ff0, 5, ARM_EXT_V6, do_qadd16},
1359 { "ssubaddx", 0xe6100f50, 8, ARM_EXT_V6, do_qadd16},
1360 { "uadd16", 0xe6500f10, 6, ARM_EXT_V6, do_qadd16},
1361 { "uadd8", 0xe6500f90, 5, ARM_EXT_V6, do_qadd16},
1362 { "uaddsubx", 0xe6500f30, 8, ARM_EXT_V6, do_qadd16},
1363 { "uhadd16", 0xe6700f10, 7, ARM_EXT_V6, do_qadd16},
1364 { "uhadd8", 0xe6700f90, 6, ARM_EXT_V6, do_qadd16},
1365 { "uhaddsubx", 0xe6700f30, 9, ARM_EXT_V6, do_qadd16},
1366 { "uhsub16", 0xe6700f70, 7, ARM_EXT_V6, do_qadd16},
1367 { "uhsub8", 0xe6700ff0, 6, ARM_EXT_V6, do_qadd16},
1368 { "uhsubaddx", 0xe6700f50, 9, ARM_EXT_V6, do_qadd16},
1369 { "uqadd16", 0xe6600f10, 7, ARM_EXT_V6, do_qadd16},
1370 { "uqadd8", 0xe6600f90, 6, ARM_EXT_V6, do_qadd16},
1371 { "uqaddsubx", 0xe6600f30, 9, ARM_EXT_V6, do_qadd16},
1372 { "uqsub16", 0xe6600f70, 7, ARM_EXT_V6, do_qadd16},
1373 { "uqsub8", 0xe6600ff0, 6, ARM_EXT_V6, do_qadd16},
1374 { "uqsubaddx", 0xe6600f50, 9, ARM_EXT_V6, do_qadd16},
1375 { "usub16", 0xe6500f70, 6, ARM_EXT_V6, do_qadd16},
1376 { "usub8", 0xe6500ff0, 5, ARM_EXT_V6, do_qadd16},
1377 { "usubaddx", 0xe6500f50, 8, ARM_EXT_V6, do_qadd16},
1378 { "rev", 0xe6bf0f30, 3, ARM_EXT_V6, do_rev},
1379 { "rev16", 0xe6bf0fb0, 5, ARM_EXT_V6, do_rev},
1380 { "revsh", 0xe6ff0fb0, 5, ARM_EXT_V6, do_rev},
1381 { "rfeia", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
1382 { "rfeib", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
1383 { "rfeda", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
1384 { "rfedb", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
1385 { "rfefd", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
1386 { "rfefa", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
1387 { "rfeea", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
1388 { "rfeed", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
1389 { "sxtah", 0xe6b00070, 5, ARM_EXT_V6, do_sxtah},
1390 { "sxtab16", 0xe6800070, 7, ARM_EXT_V6, do_sxtah},
1391 { "sxtab", 0xe6a00070, 5, ARM_EXT_V6, do_sxtah},
1392 { "sxth", 0xe6bf0070, 4, ARM_EXT_V6, do_sxth},
1393 { "sxtb16", 0xe68f0070, 6, ARM_EXT_V6, do_sxth},
1394 { "sxtb", 0xe6af0070, 4, ARM_EXT_V6, do_sxth},
1395 { "uxtah", 0xe6f00070, 5, ARM_EXT_V6, do_sxtah},
1396 { "uxtab16", 0xe6c00070, 7, ARM_EXT_V6, do_sxtah},
1397 { "uxtab", 0xe6e00070, 5, ARM_EXT_V6, do_sxtah},
1398 { "uxth", 0xe6ff0070, 4, ARM_EXT_V6, do_sxth},
1399 { "uxtb16", 0xe6cf0070, 6, ARM_EXT_V6, do_sxth},
1400 { "uxtb", 0xe6ef0070, 4, ARM_EXT_V6, do_sxth},
1401 { "sel", 0xe68000b0, 3, ARM_EXT_V6, do_qadd16},
1402 { "setend", 0xf1010000, 0, ARM_EXT_V6, do_setend},
1403 { "smlad", 0xe7000010, 5, ARM_EXT_V6, do_smlad},
1404 { "smladx", 0xe7000030, 6, ARM_EXT_V6, do_smlad},
1405 { "smlald", 0xe7400010, 6, ARM_EXT_V6, do_smlald},
1406 { "smlaldx", 0xe7400030, 7, ARM_EXT_V6, do_smlald},
1407 { "smlsd", 0xe7000050, 5, ARM_EXT_V6, do_smlad},
1408 { "smlsdx", 0xe7000070, 6, ARM_EXT_V6, do_smlad},
1409 { "smlsld", 0xe7400050, 6, ARM_EXT_V6, do_smlald},
1410 { "smlsldx", 0xe7400070, 7, ARM_EXT_V6, do_smlald},
1411 { "smmla", 0xe7500010, 5, ARM_EXT_V6, do_smlad},
1412 { "smmlar", 0xe7500030, 6, ARM_EXT_V6, do_smlad},
1413 { "smmls", 0xe75000d0, 5, ARM_EXT_V6, do_smlad},
1414 { "smmlsr", 0xe75000f0, 6, ARM_EXT_V6, do_smlad},
1415 { "smmul", 0xe750f010, 5, ARM_EXT_V6, do_smmul},
1416 { "smmulr", 0xe750f030, 6, ARM_EXT_V6, do_smmul},
1417 { "smuad", 0xe700f010, 5, ARM_EXT_V6, do_smmul},
1418 { "smuadx", 0xe700f030, 6, ARM_EXT_V6, do_smmul},
1419 { "smusd", 0xe700f050, 5, ARM_EXT_V6, do_smmul},
1420 { "smusdx", 0xe700f070, 6, ARM_EXT_V6, do_smmul},
1421 { "srsia", 0xf8cd0500, 0, ARM_EXT_V6, do_srs},
1422 { "srsib", 0xf9cd0500, 0, ARM_EXT_V6, do_srs},
1423 { "srsda", 0xf84d0500, 0, ARM_EXT_V6, do_srs},
1424 { "srsdb", 0xf94d0500, 0, ARM_EXT_V6, do_srs},
1425 { "ssat", 0xe6a00010, 4, ARM_EXT_V6, do_ssat},
1426 { "ssat16", 0xe6a00f30, 6, ARM_EXT_V6, do_ssat16},
1427 { "strex", 0xe1800f90, 5, ARM_EXT_V6, do_strex},
1428 { "umaal", 0xe0400090, 5, ARM_EXT_V6, do_umaal},
1429 { "usad8", 0xe780f010, 5, ARM_EXT_V6, do_smmul},
1430 { "usada8", 0xe7800010, 6, ARM_EXT_V6, do_smlad},
1431 { "usat", 0xe6e00010, 4, ARM_EXT_V6, do_usat},
1432 { "usat16", 0xe6e00f30, 6, ARM_EXT_V6, do_usat16},
1434 /* Core FPA instruction set (V1). */
1435 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1436 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1437 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1438 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1440 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1441 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1442 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1443 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1445 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1446 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1447 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1448 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1450 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1451 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1452 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1453 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1454 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1455 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1456 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1457 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1458 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1459 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1460 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1461 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1463 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1464 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1465 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1466 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1467 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1468 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1469 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1470 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1471 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1472 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1473 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1474 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1476 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1477 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1478 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1479 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1480 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1481 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1482 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1483 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1484 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1485 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1486 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1487 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1489 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1490 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1491 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1492 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1493 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1494 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1495 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1496 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1497 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1498 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1499 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1500 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1502 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1503 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1504 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1505 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1506 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1507 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1508 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1509 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1510 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1511 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1512 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1513 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1515 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1516 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1517 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1518 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1519 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1520 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1521 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1522 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1523 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1524 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1525 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1526 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1528 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1529 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1530 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1531 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1532 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1533 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1534 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1535 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1536 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1537 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1538 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1539 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1541 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1542 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1543 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1544 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1545 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1546 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1547 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1548 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1549 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1550 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1551 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1552 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1554 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1555 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1556 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1557 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1558 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1559 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1560 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1561 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1562 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1563 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1564 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1565 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1567 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1568 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1569 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1570 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1571 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1572 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1573 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1574 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1575 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1576 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1577 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1578 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1580 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1581 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1582 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1583 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1584 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1585 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1586 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1587 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1588 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1589 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1590 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1591 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1593 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1594 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1595 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1596 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1597 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1598 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1599 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1600 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1601 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1602 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1603 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1604 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1606 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1607 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1608 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1609 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1610 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1611 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1612 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1613 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1614 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1615 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1616 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1617 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1619 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1620 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1621 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1622 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1623 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1624 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1625 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1626 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1627 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1628 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1629 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1630 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1632 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1633 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1634 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1635 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1636 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1637 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1638 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1639 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1640 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1641 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1642 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1643 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1645 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1646 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1647 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1648 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1649 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1650 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1651 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1652 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1653 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1654 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1655 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1656 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1658 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1659 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1660 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1661 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1662 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1663 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1664 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1665 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1666 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1667 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1668 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1669 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1671 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1672 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1673 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1674 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1675 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1676 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1677 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1678 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1679 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1680 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1681 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1682 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1684 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1685 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1686 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1687 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1688 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1689 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1690 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1691 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1692 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1693 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1694 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1695 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1697 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1698 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1699 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1700 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1701 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1702 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1703 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1704 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1705 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1706 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1707 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1708 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1710 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1711 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1712 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1713 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1714 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1715 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1716 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1717 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1718 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1719 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1720 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1721 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1723 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1724 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1725 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1726 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1727 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1728 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1729 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1730 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1731 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1732 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1733 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1734 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1736 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1737 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1738 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1739 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1740 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1741 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1742 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1743 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1744 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1745 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1746 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1747 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1749 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1750 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1751 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1752 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1753 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1754 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1755 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1756 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1757 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1758 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1759 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1760 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1762 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1763 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1764 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1765 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1766 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1767 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1768 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1769 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1770 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1771 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1772 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1773 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1775 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1776 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1777 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1778 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1779 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1780 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1781 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1782 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1783 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1784 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1785 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1786 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1788 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1789 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1790 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1791 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1792 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1793 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1794 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1795 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1796 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1797 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1798 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1799 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1801 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1802 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1803 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1804 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1805 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1806 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1807 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1808 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1809 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1810 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1811 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1812 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1814 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1815 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1816 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1817 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1818 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1819 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1820 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1821 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1822 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1823 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1824 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1825 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1827 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1828 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1829 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1830 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1831 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
1832 not be an optional suffix, but part of the instruction. To be
1833 compatible, we accept either. */
1834 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
1835 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
1837 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1838 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1839 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1840 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1841 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1842 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1843 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1844 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1845 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1846 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1847 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1848 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1850 /* The implementation of the FIX instruction is broken on some
1851 assemblers, in that it accepts a precision specifier as well as a
1852 rounding specifier, despite the fact that this is meaningless.
1853 To be more compatible, we accept it as well, though of course it
1854 does not set any bits. */
1855 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1856 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1857 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1858 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1859 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1860 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1861 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1862 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1863 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1864 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1865 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1866 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1867 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1869 /* Instructions that were new with the real FPA, call them V2. */
1870 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1871 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1872 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1873 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1874 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1875 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1877 /* VFP V1xD (single precision). */
1878 /* Moves and type conversions. */
1879 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1880 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_sp},
1881 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_from_reg},
1882 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD, do_empty},
1883 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1884 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1885 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1886 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1887 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1888 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1889 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_ctrl},
1890 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_ctrl_from_reg},
1892 /* Memory operations. */
1893 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
1894 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
1895 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1896 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1897 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1898 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1899 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1900 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1901 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1902 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1903 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1904 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1905 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1906 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1907 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1908 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1909 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1910 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1912 /* Monadic operations. */
1913 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1914 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1915 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1917 /* Dyadic operations. */
1918 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1919 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1920 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1921 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1922 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1923 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1924 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1925 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1926 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1928 /* Comparisons. */
1929 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1930 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
1931 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1932 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
1934 /* VFP V1 (Double precision). */
1935 /* Moves and type conversions. */
1936 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1937 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
1938 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1939 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
1940 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
1941 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
1942 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
1943 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
1944 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
1945 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1946 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1947 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1948 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1950 /* Memory operations. */
1951 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
1952 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
1953 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1954 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1955 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1956 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1957 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1958 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1959 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1960 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1962 /* Monadic operations. */
1963 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1964 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1965 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1967 /* Dyadic operations. */
1968 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1969 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1970 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1971 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1972 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1973 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1974 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1975 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1976 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1978 /* Comparisons. */
1979 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1980 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
1981 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1982 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
1984 /* VFP V2. */
1985 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2, do_vfp_sp2_from_reg2},
1986 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_sp2},
1987 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2, do_vfp_dp_from_reg2},
1988 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_dp},
1990 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
1991 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE, do_xsc_mia},
1992 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1993 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1994 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1995 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1996 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1997 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE, do_xsc_mar},
1998 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE, do_xsc_mra},
2000 /* Intel Wireless MMX technology instructions. */
2001 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
2002 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
2003 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
2004 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
2005 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
2006 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
2007 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
2008 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
2009 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
2010 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2011 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2012 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2013 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2014 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2015 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2016 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
2017 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
2018 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
2019 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmcr},
2020 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmcrr},
2021 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2022 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2023 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2024 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2025 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2026 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2027 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
2028 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
2029 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
2030 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmrc},
2031 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmrrc},
2032 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
2033 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
2034 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
2035 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2036 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2037 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2038 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2039 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2040 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2041 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2042 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2043 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2044 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2045 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2046 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2047 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT, do_iwmmxt_waligni},
2048 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2049 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2050 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2051 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2052 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2053 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2054 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2055 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2056 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2057 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2058 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2059 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2060 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2061 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2062 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2063 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2064 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2065 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2066 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2067 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
2068 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
2069 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2070 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2071 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2072 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2073 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2074 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2075 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2076 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2077 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2078 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2079 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2080 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2081 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2082 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2083 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2084 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2085 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2086 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2087 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2088 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2089 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wmov},
2090 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2091 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2092 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2093 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2094 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2095 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2096 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2097 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2098 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2099 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2100 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2101 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2102 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2103 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2104 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2105 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2106 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2107 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2108 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2109 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2110 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2111 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wshufh},
2112 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2113 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2114 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2115 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2116 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2117 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2118 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2119 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2120 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2121 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2122 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2123 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2124 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2125 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2126 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2127 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2128 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2129 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2130 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
2131 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
2132 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2133 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2134 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2135 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2136 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2137 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2138 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2139 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2140 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2141 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2142 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2143 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2144 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2145 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2146 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2147 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2148 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2149 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2150 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2151 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2152 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2153 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2154 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2155 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2156 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2157 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2158 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2159 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2160 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2161 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2162 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wzero},
2164 /* Cirrus Maverick instructions. */
2165 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
2166 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
2167 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
2168 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
2169 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
2170 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
2171 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
2172 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
2173 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK, do_mav_binops_2a},
2174 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK, do_mav_binops_1a},
2175 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
2176 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
2177 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
2178 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
2179 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
2180 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
2181 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
2182 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
2183 {"cfmval32", 0xee200440, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2184 {"cfmv32al", 0xee100440, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2185 {"cfmvam32", 0xee200460, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2186 {"cfmv32am", 0xee100460, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2187 {"cfmvah32", 0xee200480, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2188 {"cfmv32ah", 0xee100480, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2189 {"cfmva32", 0xee2004a0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2190 {"cfmv32a", 0xee1004a0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2191 {"cfmva64", 0xee2004c0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3c},
2192 {"cfmv64a", 0xee1004c0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3d},
2193 {"cfmvsc32", 0xee2004e0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_1},
2194 {"cfmv32sc", 0xee1004e0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_2},
2195 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
2196 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
2197 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK, do_mav_binops_1f},
2198 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK, do_mav_binops_1g},
2199 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK, do_mav_binops_1h},
2200 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1i},
2201 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1j},
2202 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1k},
2203 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK, do_mav_binops_1l},
2204 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1m},
2205 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1l},
2206 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1m},
2207 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK, do_mav_triple_4a},
2208 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK, do_mav_triple_4b},
2209 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK, do_mav_shift_1},
2210 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK, do_mav_shift_2},
2211 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK, do_mav_triple_5a},
2212 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5b},
2213 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK, do_mav_triple_5c},
2214 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5d},
2215 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
2216 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
2217 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
2218 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
2219 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
2220 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
2221 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
2222 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
2223 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
2224 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
2225 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
2226 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
2227 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
2228 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
2229 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2230 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
2231 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2232 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
2233 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2234 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
2235 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2236 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2237 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
2238 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
2239 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
2240 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
2243 /* Defines for various bits that we will want to toggle. */
2244 #define INST_IMMEDIATE 0x02000000
2245 #define OFFSET_REG 0x02000000
2246 #define HWOFFSET_IMM 0x00400000
2247 #define SHIFT_BY_REG 0x00000010
2248 #define PRE_INDEX 0x01000000
2249 #define INDEX_UP 0x00800000
2250 #define WRITE_BACK 0x00200000
2251 #define LDM_TYPE_2_OR_3 0x00400000
2253 #define LITERAL_MASK 0xf000f000
2254 #define OPCODE_MASK 0xfe1fffff
2255 #define V4_STR_BIT 0x00000020
2257 #define DATA_OP_SHIFT 21
2259 /* Codes to distinguish the arithmetic instructions. */
2260 #define OPCODE_AND 0
2261 #define OPCODE_EOR 1
2262 #define OPCODE_SUB 2
2263 #define OPCODE_RSB 3
2264 #define OPCODE_ADD 4
2265 #define OPCODE_ADC 5
2266 #define OPCODE_SBC 6
2267 #define OPCODE_RSC 7
2268 #define OPCODE_TST 8
2269 #define OPCODE_TEQ 9
2270 #define OPCODE_CMP 10
2271 #define OPCODE_CMN 11
2272 #define OPCODE_ORR 12
2273 #define OPCODE_MOV 13
2274 #define OPCODE_BIC 14
2275 #define OPCODE_MVN 15
2277 /* Thumb v1 (ARMv4T). */
2278 static void do_t_nop PARAMS ((char *));
2279 static void do_t_arit PARAMS ((char *));
2280 static void do_t_add PARAMS ((char *));
2281 static void do_t_asr PARAMS ((char *));
2282 static void do_t_branch9 PARAMS ((char *));
2283 static void do_t_branch12 PARAMS ((char *));
2284 static void do_t_branch23 PARAMS ((char *));
2285 static void do_t_bx PARAMS ((char *));
2286 static void do_t_compare PARAMS ((char *));
2287 static void do_t_ldmstm PARAMS ((char *));
2288 static void do_t_ldr PARAMS ((char *));
2289 static void do_t_ldrb PARAMS ((char *));
2290 static void do_t_ldrh PARAMS ((char *));
2291 static void do_t_lds PARAMS ((char *));
2292 static void do_t_lsl PARAMS ((char *));
2293 static void do_t_lsr PARAMS ((char *));
2294 static void do_t_mov PARAMS ((char *));
2295 static void do_t_push_pop PARAMS ((char *));
2296 static void do_t_str PARAMS ((char *));
2297 static void do_t_strb PARAMS ((char *));
2298 static void do_t_strh PARAMS ((char *));
2299 static void do_t_sub PARAMS ((char *));
2300 static void do_t_swi PARAMS ((char *));
2301 static void do_t_adr PARAMS ((char *));
2303 /* Thumb v2 (ARMv5T). */
2304 static void do_t_blx PARAMS ((char *));
2305 static void do_t_bkpt PARAMS ((char *));
2307 /* ARM V6. */
2308 static void do_t_cps PARAMS ((char *));
2309 static void do_t_cpy PARAMS ((char *));
2310 static void do_t_setend PARAMS ((char *));;
2312 #define T_OPCODE_MUL 0x4340
2313 #define T_OPCODE_TST 0x4200
2314 #define T_OPCODE_CMN 0x42c0
2315 #define T_OPCODE_NEG 0x4240
2316 #define T_OPCODE_MVN 0x43c0
2318 #define T_OPCODE_ADD_R3 0x1800
2319 #define T_OPCODE_SUB_R3 0x1a00
2320 #define T_OPCODE_ADD_HI 0x4400
2321 #define T_OPCODE_ADD_ST 0xb000
2322 #define T_OPCODE_SUB_ST 0xb080
2323 #define T_OPCODE_ADD_SP 0xa800
2324 #define T_OPCODE_ADD_PC 0xa000
2325 #define T_OPCODE_ADD_I8 0x3000
2326 #define T_OPCODE_SUB_I8 0x3800
2327 #define T_OPCODE_ADD_I3 0x1c00
2328 #define T_OPCODE_SUB_I3 0x1e00
2330 #define T_OPCODE_ASR_R 0x4100
2331 #define T_OPCODE_LSL_R 0x4080
2332 #define T_OPCODE_LSR_R 0x40c0
2333 #define T_OPCODE_ASR_I 0x1000
2334 #define T_OPCODE_LSL_I 0x0000
2335 #define T_OPCODE_LSR_I 0x0800
2337 #define T_OPCODE_MOV_I8 0x2000
2338 #define T_OPCODE_CMP_I8 0x2800
2339 #define T_OPCODE_CMP_LR 0x4280
2340 #define T_OPCODE_MOV_HR 0x4600
2341 #define T_OPCODE_CMP_HR 0x4500
2343 #define T_OPCODE_LDR_PC 0x4800
2344 #define T_OPCODE_LDR_SP 0x9800
2345 #define T_OPCODE_STR_SP 0x9000
2346 #define T_OPCODE_LDR_IW 0x6800
2347 #define T_OPCODE_STR_IW 0x6000
2348 #define T_OPCODE_LDR_IH 0x8800
2349 #define T_OPCODE_STR_IH 0x8000
2350 #define T_OPCODE_LDR_IB 0x7800
2351 #define T_OPCODE_STR_IB 0x7000
2352 #define T_OPCODE_LDR_RW 0x5800
2353 #define T_OPCODE_STR_RW 0x5000
2354 #define T_OPCODE_LDR_RH 0x5a00
2355 #define T_OPCODE_STR_RH 0x5200
2356 #define T_OPCODE_LDR_RB 0x5c00
2357 #define T_OPCODE_STR_RB 0x5400
2359 #define T_OPCODE_PUSH 0xb400
2360 #define T_OPCODE_POP 0xbc00
2362 #define T_OPCODE_BRANCH 0xe7fe
2364 static int thumb_reg PARAMS ((char ** str, int hi_lo));
2366 #define THUMB_SIZE 2 /* Size of thumb instruction. */
2367 #define THUMB_REG_LO 0x1
2368 #define THUMB_REG_HI 0x2
2369 #define THUMB_REG_ANY 0x3
2371 #define THUMB_H1 0x0080
2372 #define THUMB_H2 0x0040
2374 #define THUMB_ASR 0
2375 #define THUMB_LSL 1
2376 #define THUMB_LSR 2
2378 #define THUMB_MOVE 0
2379 #define THUMB_COMPARE 1
2380 #define THUMB_CPY 2
2382 #define THUMB_LOAD 0
2383 #define THUMB_STORE 1
2385 #define THUMB_PP_PC_LR 0x0100
2387 /* These three are used for immediate shifts, do not alter. */
2388 #define THUMB_WORD 2
2389 #define THUMB_HALFWORD 1
2390 #define THUMB_BYTE 0
2392 struct thumb_opcode
2394 /* Basic string to match. */
2395 const char * template;
2397 /* Basic instruction code. */
2398 unsigned long value;
2400 int size;
2402 /* Which CPU variants this exists for. */
2403 unsigned long variant;
2405 /* Function to call to parse args. */
2406 void (* parms) PARAMS ((char *));
2409 static const struct thumb_opcode tinsns[] =
2411 /* Thumb v1 (ARMv4T). */
2412 {"adc", 0x4140, 2, ARM_EXT_V4T, do_t_arit},
2413 {"add", 0x0000, 2, ARM_EXT_V4T, do_t_add},
2414 {"and", 0x4000, 2, ARM_EXT_V4T, do_t_arit},
2415 {"asr", 0x0000, 2, ARM_EXT_V4T, do_t_asr},
2416 {"b", T_OPCODE_BRANCH, 2, ARM_EXT_V4T, do_t_branch12},
2417 {"beq", 0xd0fe, 2, ARM_EXT_V4T, do_t_branch9},
2418 {"bne", 0xd1fe, 2, ARM_EXT_V4T, do_t_branch9},
2419 {"bcs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
2420 {"bhs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
2421 {"bcc", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
2422 {"bul", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
2423 {"blo", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
2424 {"bmi", 0xd4fe, 2, ARM_EXT_V4T, do_t_branch9},
2425 {"bpl", 0xd5fe, 2, ARM_EXT_V4T, do_t_branch9},
2426 {"bvs", 0xd6fe, 2, ARM_EXT_V4T, do_t_branch9},
2427 {"bvc", 0xd7fe, 2, ARM_EXT_V4T, do_t_branch9},
2428 {"bhi", 0xd8fe, 2, ARM_EXT_V4T, do_t_branch9},
2429 {"bls", 0xd9fe, 2, ARM_EXT_V4T, do_t_branch9},
2430 {"bge", 0xdafe, 2, ARM_EXT_V4T, do_t_branch9},
2431 {"blt", 0xdbfe, 2, ARM_EXT_V4T, do_t_branch9},
2432 {"bgt", 0xdcfe, 2, ARM_EXT_V4T, do_t_branch9},
2433 {"ble", 0xddfe, 2, ARM_EXT_V4T, do_t_branch9},
2434 {"bal", 0xdefe, 2, ARM_EXT_V4T, do_t_branch9},
2435 {"bic", 0x4380, 2, ARM_EXT_V4T, do_t_arit},
2436 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T, do_t_branch23},
2437 {"bx", 0x4700, 2, ARM_EXT_V4T, do_t_bx},
2438 {"cmn", T_OPCODE_CMN, 2, ARM_EXT_V4T, do_t_arit},
2439 {"cmp", 0x0000, 2, ARM_EXT_V4T, do_t_compare},
2440 {"eor", 0x4040, 2, ARM_EXT_V4T, do_t_arit},
2441 {"ldmia", 0xc800, 2, ARM_EXT_V4T, do_t_ldmstm},
2442 {"ldr", 0x0000, 2, ARM_EXT_V4T, do_t_ldr},
2443 {"ldrb", 0x0000, 2, ARM_EXT_V4T, do_t_ldrb},
2444 {"ldrh", 0x0000, 2, ARM_EXT_V4T, do_t_ldrh},
2445 {"ldrsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
2446 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
2447 {"ldsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
2448 {"ldsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
2449 {"lsl", 0x0000, 2, ARM_EXT_V4T, do_t_lsl},
2450 {"lsr", 0x0000, 2, ARM_EXT_V4T, do_t_lsr},
2451 {"mov", 0x0000, 2, ARM_EXT_V4T, do_t_mov},
2452 {"mul", T_OPCODE_MUL, 2, ARM_EXT_V4T, do_t_arit},
2453 {"mvn", T_OPCODE_MVN, 2, ARM_EXT_V4T, do_t_arit},
2454 {"neg", T_OPCODE_NEG, 2, ARM_EXT_V4T, do_t_arit},
2455 {"orr", 0x4300, 2, ARM_EXT_V4T, do_t_arit},
2456 {"pop", 0xbc00, 2, ARM_EXT_V4T, do_t_push_pop},
2457 {"push", 0xb400, 2, ARM_EXT_V4T, do_t_push_pop},
2458 {"ror", 0x41c0, 2, ARM_EXT_V4T, do_t_arit},
2459 {"sbc", 0x4180, 2, ARM_EXT_V4T, do_t_arit},
2460 {"stmia", 0xc000, 2, ARM_EXT_V4T, do_t_ldmstm},
2461 {"str", 0x0000, 2, ARM_EXT_V4T, do_t_str},
2462 {"strb", 0x0000, 2, ARM_EXT_V4T, do_t_strb},
2463 {"strh", 0x0000, 2, ARM_EXT_V4T, do_t_strh},
2464 {"swi", 0xdf00, 2, ARM_EXT_V4T, do_t_swi},
2465 {"sub", 0x0000, 2, ARM_EXT_V4T, do_t_sub},
2466 {"tst", T_OPCODE_TST, 2, ARM_EXT_V4T, do_t_arit},
2467 /* Pseudo ops: */
2468 {"adr", 0x0000, 2, ARM_EXT_V4T, do_t_adr},
2469 {"nop", 0x46C0, 2, ARM_EXT_V4T, do_t_nop}, /* mov r8,r8 */
2470 /* Thumb v2 (ARMv5T). */
2471 {"blx", 0, 0, ARM_EXT_V5T, do_t_blx},
2472 {"bkpt", 0xbe00, 2, ARM_EXT_V5T, do_t_bkpt},
2474 /* ARM V6. */
2475 {"cpsie", 0xb660, 2, ARM_EXT_V6, do_t_cps},
2476 {"cpsid", 0xb670, 2, ARM_EXT_V6, do_t_cps},
2477 {"cpy", 0x4600, 2, ARM_EXT_V6, do_t_cpy},
2478 {"rev", 0xba00, 2, ARM_EXT_V6, do_t_arit},
2479 {"rev16", 0xba40, 2, ARM_EXT_V6, do_t_arit},
2480 {"revsh", 0xbac0, 2, ARM_EXT_V6, do_t_arit},
2481 {"setend", 0xb650, 2, ARM_EXT_V6, do_t_setend},
2482 {"sxth", 0xb200, 2, ARM_EXT_V6, do_t_arit},
2483 {"sxtb", 0xb240, 2, ARM_EXT_V6, do_t_arit},
2484 {"uxth", 0xb280, 2, ARM_EXT_V6, do_t_arit},
2485 {"uxtb", 0xb2c0, 2, ARM_EXT_V6, do_t_arit},
2488 #define BAD_ARGS _("bad arguments to instruction")
2489 #define BAD_PC _("r15 not allowed here")
2490 #define BAD_COND _("instruction is not conditional")
2491 #define ERR_NO_ACCUM _("acc0 expected")
2493 static struct hash_control * arm_ops_hsh = NULL;
2494 static struct hash_control * arm_tops_hsh = NULL;
2495 static struct hash_control * arm_cond_hsh = NULL;
2496 static struct hash_control * arm_shift_hsh = NULL;
2497 static struct hash_control * arm_psr_hsh = NULL;
2499 /* This table describes all the machine specific pseudo-ops the assembler
2500 has to support. The fields are:
2501 pseudo-op name without dot
2502 function to call to execute this pseudo-op
2503 Integer arg to pass to the function. */
2505 static void s_req PARAMS ((int));
2506 static void s_unreq PARAMS ((int));
2507 static void s_align PARAMS ((int));
2508 static void s_bss PARAMS ((int));
2509 static void s_even PARAMS ((int));
2510 static void s_ltorg PARAMS ((int));
2511 static void s_arm PARAMS ((int));
2512 static void s_thumb PARAMS ((int));
2513 static void s_code PARAMS ((int));
2514 static void s_force_thumb PARAMS ((int));
2515 static void s_thumb_func PARAMS ((int));
2516 static void s_thumb_set PARAMS ((int));
2517 #ifdef OBJ_ELF
2518 static void s_arm_elf_cons PARAMS ((int));
2519 #endif
2521 static int my_get_expression PARAMS ((expressionS *, char **));
2523 const pseudo_typeS md_pseudo_table[] =
2525 /* Never called because '.req' does not start a line. */
2526 { "req", s_req, 0 },
2527 { "unreq", s_unreq, 0 },
2528 { "bss", s_bss, 0 },
2529 { "align", s_align, 0 },
2530 { "arm", s_arm, 0 },
2531 { "thumb", s_thumb, 0 },
2532 { "code", s_code, 0 },
2533 { "force_thumb", s_force_thumb, 0 },
2534 { "thumb_func", s_thumb_func, 0 },
2535 { "thumb_set", s_thumb_set, 0 },
2536 { "even", s_even, 0 },
2537 { "ltorg", s_ltorg, 0 },
2538 { "pool", s_ltorg, 0 },
2539 #ifdef OBJ_ELF
2540 { "word", s_arm_elf_cons, 4 },
2541 { "long", s_arm_elf_cons, 4 },
2542 #else
2543 { "word", cons, 4},
2544 #endif
2545 { "extend", float_cons, 'x' },
2546 { "ldouble", float_cons, 'x' },
2547 { "packed", float_cons, 'p' },
2548 { 0, 0, 0 }
2551 /* Other internal functions. */
2552 static int arm_parse_extension PARAMS ((char *, int *));
2553 static int arm_parse_cpu PARAMS ((char *));
2554 static int arm_parse_arch PARAMS ((char *));
2555 static int arm_parse_fpu PARAMS ((char *));
2556 static int arm_parse_float_abi PARAMS ((char *));
2557 #ifdef OBJ_ELF
2558 static int arm_parse_eabi PARAMS ((char *));
2559 #endif
2560 #if 0 /* Suppressed - for now. */
2561 #if defined OBJ_COFF || defined OBJ_ELF
2562 static void arm_add_note PARAMS ((const char *, const char *, unsigned int));
2563 #endif
2564 #endif
2566 /* Stuff needed to resolve the label ambiguity
2569 label: <insn>
2570 may differ from:
2572 label:
2573 <insn>
2576 symbolS * last_label_seen;
2577 static int label_is_thumb_function_name = FALSE;
2579 /* Literal Pool stuff. */
2581 #define MAX_LITERAL_POOL_SIZE 1024
2583 /* Literal pool structure. Held on a per-section
2584 and per-sub-section basis. */
2585 typedef struct literal_pool
2587 expressionS literals [MAX_LITERAL_POOL_SIZE];
2588 unsigned int next_free_entry;
2589 unsigned int id;
2590 symbolS * symbol;
2591 segT section;
2592 subsegT sub_section;
2593 struct literal_pool * next;
2594 } literal_pool;
2596 /* Pointer to a linked list of literal pools. */
2597 literal_pool * list_of_pools = NULL;
2599 static literal_pool * find_literal_pool PARAMS ((void));
2600 static literal_pool * find_or_make_literal_pool PARAMS ((void));
2602 static literal_pool *
2603 find_literal_pool ()
2605 literal_pool * pool;
2607 for (pool = list_of_pools; pool != NULL; pool = pool->next)
2609 if (pool->section == now_seg
2610 && pool->sub_section == now_subseg)
2611 break;
2614 return pool;
2617 static literal_pool *
2618 find_or_make_literal_pool ()
2620 /* Next literal pool ID number. */
2621 static unsigned int latest_pool_num = 1;
2622 literal_pool * pool;
2624 pool = find_literal_pool ();
2626 if (pool == NULL)
2628 /* Create a new pool. */
2629 pool = (literal_pool *) xmalloc (sizeof (* pool));
2630 if (! pool)
2631 return NULL;
2633 pool->next_free_entry = 0;
2634 pool->section = now_seg;
2635 pool->sub_section = now_subseg;
2636 pool->next = list_of_pools;
2637 pool->symbol = NULL;
2639 /* Add it to the list. */
2640 list_of_pools = pool;
2643 /* New pools, and emptied pools, will have a NULL symbol. */
2644 if (pool->symbol == NULL)
2646 pool->symbol = symbol_create (FAKE_LABEL_NAME, undefined_section,
2647 (valueT) 0, &zero_address_frag);
2648 pool->id = latest_pool_num ++;
2651 /* Done. */
2652 return pool;
2655 /* Add the literal in the global 'inst'
2656 structure to the relevent literal pool. */
2657 static int
2658 add_to_lit_pool ()
2660 literal_pool * pool;
2661 unsigned int entry;
2663 pool = find_or_make_literal_pool ();
2665 /* Check if this literal value is already in the pool. */
2666 for (entry = 0; entry < pool->next_free_entry; entry ++)
2668 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
2669 && (inst.reloc.exp.X_op == O_constant)
2670 && (pool->literals[entry].X_add_number
2671 == inst.reloc.exp.X_add_number)
2672 && (pool->literals[entry].X_unsigned
2673 == inst.reloc.exp.X_unsigned))
2674 break;
2676 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
2677 && (inst.reloc.exp.X_op == O_symbol)
2678 && (pool->literals[entry].X_add_number
2679 == inst.reloc.exp.X_add_number)
2680 && (pool->literals[entry].X_add_symbol
2681 == inst.reloc.exp.X_add_symbol)
2682 && (pool->literals[entry].X_op_symbol
2683 == inst.reloc.exp.X_op_symbol))
2684 break;
2687 /* Do we need to create a new entry? */
2688 if (entry == pool->next_free_entry)
2690 if (entry >= MAX_LITERAL_POOL_SIZE)
2692 inst.error = _("literal pool overflow");
2693 return FAIL;
2696 pool->literals[entry] = inst.reloc.exp;
2697 pool->next_free_entry += 1;
2700 inst.reloc.exp.X_op = O_symbol;
2701 inst.reloc.exp.X_add_number = ((int) entry) * 4 - 8;
2702 inst.reloc.exp.X_add_symbol = pool->symbol;
2704 return SUCCESS;
2707 /* Can't use symbol_new here, so have to create a symbol and then at
2708 a later date assign it a value. Thats what these functions do. */
2710 static void
2711 symbol_locate (symbolP, name, segment, valu, frag)
2712 symbolS * symbolP;
2713 const char * name; /* It is copied, the caller can modify. */
2714 segT segment; /* Segment identifier (SEG_<something>). */
2715 valueT valu; /* Symbol value. */
2716 fragS * frag; /* Associated fragment. */
2718 unsigned int name_length;
2719 char * preserved_copy_of_name;
2721 name_length = strlen (name) + 1; /* +1 for \0. */
2722 obstack_grow (&notes, name, name_length);
2723 preserved_copy_of_name = obstack_finish (&notes);
2724 #ifdef STRIP_UNDERSCORE
2725 if (preserved_copy_of_name[0] == '_')
2726 preserved_copy_of_name++;
2727 #endif
2729 #ifdef tc_canonicalize_symbol_name
2730 preserved_copy_of_name =
2731 tc_canonicalize_symbol_name (preserved_copy_of_name);
2732 #endif
2734 S_SET_NAME (symbolP, preserved_copy_of_name);
2736 S_SET_SEGMENT (symbolP, segment);
2737 S_SET_VALUE (symbolP, valu);
2738 symbol_clear_list_pointers (symbolP);
2740 symbol_set_frag (symbolP, frag);
2742 /* Link to end of symbol chain. */
2744 extern int symbol_table_frozen;
2745 if (symbol_table_frozen)
2746 abort ();
2749 symbol_append (symbolP, symbol_lastP, & symbol_rootP, & symbol_lastP);
2751 obj_symbol_new_hook (symbolP);
2753 #ifdef tc_symbol_new_hook
2754 tc_symbol_new_hook (symbolP);
2755 #endif
2757 #ifdef DEBUG_SYMS
2758 verify_symbol_chain (symbol_rootP, symbol_lastP);
2759 #endif /* DEBUG_SYMS */
2762 /* Check that an immediate is valid.
2763 If so, convert it to the right format. */
2765 static unsigned int
2766 validate_immediate (val)
2767 unsigned int val;
2769 unsigned int a;
2770 unsigned int i;
2772 #define rotate_left(v, n) (v << n | v >> (32 - n))
2774 for (i = 0; i < 32; i += 2)
2775 if ((a = rotate_left (val, i)) <= 0xff)
2776 return a | (i << 7); /* 12-bit pack: [shift-cnt,const]. */
2778 return FAIL;
2781 /* Check to see if an immediate can be computed as two separate immediate
2782 values, added together. We already know that this value cannot be
2783 computed by just one ARM instruction. */
2785 static unsigned int
2786 validate_immediate_twopart (val, highpart)
2787 unsigned int val;
2788 unsigned int * highpart;
2790 unsigned int a;
2791 unsigned int i;
2793 for (i = 0; i < 32; i += 2)
2794 if (((a = rotate_left (val, i)) & 0xff) != 0)
2796 if (a & 0xff00)
2798 if (a & ~ 0xffff)
2799 continue;
2800 * highpart = (a >> 8) | ((i + 24) << 7);
2802 else if (a & 0xff0000)
2804 if (a & 0xff000000)
2805 continue;
2806 * highpart = (a >> 16) | ((i + 16) << 7);
2808 else
2810 assert (a & 0xff000000);
2811 * highpart = (a >> 24) | ((i + 8) << 7);
2814 return (a & 0xff) | (i << 7);
2817 return FAIL;
2820 static int
2821 validate_offset_imm (val, hwse)
2822 unsigned int val;
2823 int hwse;
2825 if ((hwse && val > 255) || val > 4095)
2826 return FAIL;
2827 return val;
2831 #ifdef OBJ_ELF
2832 /* This code is to handle mapping symbols as defined in the ARM ELF spec.
2833 (This text is taken from version B-02 of the spec):
2835 4.4.7 Mapping and tagging symbols
2837 A section of an ARM ELF file can contain a mixture of ARM code,
2838 Thumb code, and data. There are inline transitions between code
2839 and data at literal pool boundaries. There can also be inline
2840 transitions between ARM code and Thumb code, for example in
2841 ARM-Thumb inter-working veneers. Linkers, machine-level
2842 debuggers, profiling tools, and disassembly tools need to map
2843 images accurately. For example, setting an ARM breakpoint on a
2844 Thumb location, or in a literal pool, can crash the program
2845 being debugged, ruining the debugging session.
2847 ARM ELF entities are mapped (see section 4.4.7.1 below) and
2848 tagged (see section 4.4.7.2 below) using local symbols (with
2849 binding STB_LOCAL). To assist consumers, mapping and tagging
2850 symbols should be collated first in the symbol table, before
2851 other symbols with binding STB_LOCAL.
2853 To allow properly collated mapping and tagging symbols to be
2854 skipped by consumers that have no interest in them, the first
2855 such symbol should have the name $m and its st_value field equal
2856 to the total number of mapping and tagging symbols (including
2857 the $m) in the symbol table.
2859 4.4.7.1 Mapping symbols
2861 $a Labels the first byte of a sequence of ARM instructions.
2862 Its type is STT_FUNC.
2864 $d Labels the first byte of a sequence of data items.
2865 Its type is STT_OBJECT.
2867 $t Labels the first byte of a sequence of Thumb instructions.
2868 Its type is STT_FUNC.
2870 This list of mapping symbols may be extended in the future.
2872 Section-relative mapping symbols
2874 Mapping symbols defined in a section define a sequence of
2875 half-open address intervals that cover the address range of the
2876 section. Each interval starts at the address defined by a
2877 mapping symbol, and continues up to, but not including, the
2878 address defined by the next (in address order) mapping symbol or
2879 the end of the section. A corollary is that there must be a
2880 mapping symbol defined at the beginning of each section.
2881 Consumers can ignore the size of a section-relative mapping
2882 symbol. Producers can set it to 0.
2884 Absolute mapping symbols
2886 Because of the need to crystallize a Thumb address with the
2887 Thumb-bit set, absolute symbol of type STT_FUNC (symbols of type
2888 STT_FUNC defined in section SHN_ABS) need to be mapped with $a
2889 or $t.
2891 The extent of a mapping symbol defined in SHN_ABS is [st_value,
2892 st_value + st_size), or [st_value, st_value + 1) if st_size = 0,
2893 where [x, y) denotes the half-open address range from x,
2894 inclusive, to y, exclusive.
2896 In the absence of a mapping symbol, a consumer can interpret a
2897 function symbol with an odd value as the Thumb code address
2898 obtained by clearing the least significant bit of the
2899 value. This interpretation is deprecated, and it may not work in
2900 the future.
2902 Note - the Tagging symbols ($b, $f, $p $m) have been dropped from
2903 the EABI (which is still under development), so they are not
2904 implemented here. */
2906 static enum mstate mapstate = MAP_UNDEFINED;
2908 static void
2909 mapping_state (enum mstate state)
2911 symbolS * symbolP;
2912 const char * symname;
2913 int type;
2915 if (mapstate == state)
2916 /* The mapping symbol has already been emitted.
2917 There is nothing else to do. */
2918 return;
2920 mapstate = state;
2922 switch (state)
2924 case MAP_DATA:
2925 symname = "$d";
2926 type = BSF_OBJECT;
2927 break;
2928 case MAP_ARM:
2929 symname = "$a";
2930 type = BSF_FUNCTION;
2931 break;
2932 case MAP_THUMB:
2933 symname = "$t";
2934 type = BSF_FUNCTION;
2935 break;
2936 case MAP_UNDEFINED:
2937 return;
2938 default:
2939 abort ();
2942 seg_info (now_seg)->tc_segment_info_data = state;
2944 symbolP = symbol_new (symname, now_seg, (valueT) frag_now_fix (), frag_now);
2945 symbol_table_insert (symbolP);
2946 symbol_get_bfdsym (symbolP)->flags |= type | BSF_LOCAL;
2948 switch (state)
2950 case MAP_ARM:
2951 THUMB_SET_FUNC (symbolP, 0);
2952 ARM_SET_THUMB (symbolP, 0);
2953 ARM_SET_INTERWORK (symbolP, support_interwork);
2954 break;
2956 case MAP_THUMB:
2957 THUMB_SET_FUNC (symbolP, 1);
2958 ARM_SET_THUMB (symbolP, 1);
2959 ARM_SET_INTERWORK (symbolP, support_interwork);
2960 break;
2962 case MAP_DATA:
2963 default:
2964 return;
2968 /* When we change sections we need to issue a new mapping symbol. */
2970 void
2971 arm_elf_change_section (void)
2973 flagword flags;
2975 if (!SEG_NORMAL (now_seg))
2976 return;
2978 flags = bfd_get_section_flags (stdoutput, now_seg);
2980 /* We can ignore sections that only contain debug info. */
2981 if ((flags & SEC_ALLOC) == 0)
2982 return;
2984 mapstate = seg_info (now_seg)->tc_segment_info_data;
2986 #else
2987 #define mapping_state(a)
2988 #endif /* OBJ_ELF */
2991 static void
2992 s_req (a)
2993 int a ATTRIBUTE_UNUSED;
2995 as_bad (_("invalid syntax for .req directive"));
2998 /* The .unreq directive deletes an alias which was previously defined
2999 by .req. For example:
3001 my_alias .req r11
3002 .unreq my_alias */
3004 static void
3005 s_unreq (int a ATTRIBUTE_UNUSED)
3007 char *name;
3008 char saved_char;
3010 skip_whitespace (input_line_pointer);
3011 name = input_line_pointer;
3013 while (*input_line_pointer != 0
3014 && *input_line_pointer != ' '
3015 && *input_line_pointer != '\n')
3016 ++input_line_pointer;
3018 saved_char = *input_line_pointer;
3019 *input_line_pointer = 0;
3021 if (*name)
3023 enum arm_reg_type req_type = arm_reg_parse_any (name);
3025 if (req_type != REG_TYPE_MAX)
3027 char *temp_name = name;
3028 int req_no = arm_reg_parse (&temp_name, all_reg_maps[req_type].htab);
3030 if (req_no != FAIL)
3032 struct reg_entry *req_entry;
3034 /* Check to see if this alias is a builtin one. */
3035 req_entry = hash_delete (all_reg_maps[req_type].htab, name);
3037 if (!req_entry)
3038 as_bad (_("unreq: missing hash entry for \"%s\""), name);
3039 else if (req_entry->builtin)
3040 /* FIXME: We are deleting a built in register alias which
3041 points to a const data structure, so we only need to
3042 free up the memory used by the key in the hash table.
3043 Unfortunately we have not recorded this value, so this
3044 is a memory leak. */
3045 /* FIXME: Should we issue a warning message ? */
3047 else
3049 /* Deleting a user defined alias. We need to free the
3050 key and the value, but fortunately the key is the same
3051 as the value->name field. */
3052 free ((char *) req_entry->name);
3053 free (req_entry);
3056 else
3057 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
3059 else
3060 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
3062 else
3063 as_bad (_("invalid syntax for .unreq directive"));
3065 *input_line_pointer = saved_char;
3066 demand_empty_rest_of_line ();
3069 static void
3070 s_bss (ignore)
3071 int ignore ATTRIBUTE_UNUSED;
3073 /* We don't support putting frags in the BSS segment, we fake it by
3074 marking in_bss, then looking at s_skip for clues. */
3075 subseg_set (bss_section, 0);
3076 demand_empty_rest_of_line ();
3077 mapping_state (MAP_DATA);
3080 static void
3081 s_even (ignore)
3082 int ignore ATTRIBUTE_UNUSED;
3084 /* Never make frag if expect extra pass. */
3085 if (!need_pass_2)
3086 frag_align (1, 0, 0);
3088 record_alignment (now_seg, 1);
3090 demand_empty_rest_of_line ();
3093 static void
3094 s_ltorg (ignored)
3095 int ignored ATTRIBUTE_UNUSED;
3097 unsigned int entry;
3098 literal_pool * pool;
3099 char sym_name[20];
3101 pool = find_literal_pool ();
3102 if (pool == NULL
3103 || pool->symbol == NULL
3104 || pool->next_free_entry == 0)
3105 return;
3107 mapping_state (MAP_DATA);
3109 /* Align pool as you have word accesses.
3110 Only make a frag if we have to. */
3111 if (!need_pass_2)
3112 frag_align (2, 0, 0);
3114 record_alignment (now_seg, 2);
3116 sprintf (sym_name, "$$lit_\002%x", pool->id);
3118 symbol_locate (pool->symbol, sym_name, now_seg,
3119 (valueT) frag_now_fix (), frag_now);
3120 symbol_table_insert (pool->symbol);
3122 ARM_SET_THUMB (pool->symbol, thumb_mode);
3124 #if defined OBJ_COFF || defined OBJ_ELF
3125 ARM_SET_INTERWORK (pool->symbol, support_interwork);
3126 #endif
3128 for (entry = 0; entry < pool->next_free_entry; entry ++)
3129 /* First output the expression in the instruction to the pool. */
3130 emit_expr (&(pool->literals[entry]), 4); /* .word */
3132 /* Mark the pool as empty. */
3133 pool->next_free_entry = 0;
3134 pool->symbol = NULL;
3137 /* Same as s_align_ptwo but align 0 => align 2. */
3139 static void
3140 s_align (unused)
3141 int unused ATTRIBUTE_UNUSED;
3143 register int temp;
3144 register long temp_fill;
3145 long max_alignment = 15;
3147 temp = get_absolute_expression ();
3148 if (temp > max_alignment)
3149 as_bad (_("alignment too large: %d assumed"), temp = max_alignment);
3150 else if (temp < 0)
3152 as_bad (_("alignment negative. 0 assumed."));
3153 temp = 0;
3156 if (*input_line_pointer == ',')
3158 input_line_pointer++;
3159 temp_fill = get_absolute_expression ();
3161 else
3162 temp_fill = 0;
3164 if (!temp)
3165 temp = 2;
3167 /* Only make a frag if we HAVE to. */
3168 if (temp && !need_pass_2)
3169 frag_align (temp, (int) temp_fill, 0);
3170 demand_empty_rest_of_line ();
3172 record_alignment (now_seg, temp);
3175 static void
3176 s_force_thumb (ignore)
3177 int ignore ATTRIBUTE_UNUSED;
3179 /* If we are not already in thumb mode go into it, EVEN if
3180 the target processor does not support thumb instructions.
3181 This is used by gcc/config/arm/lib1funcs.asm for example
3182 to compile interworking support functions even if the
3183 target processor should not support interworking. */
3184 if (! thumb_mode)
3186 thumb_mode = 2;
3188 record_alignment (now_seg, 1);
3191 demand_empty_rest_of_line ();
3194 static void
3195 s_thumb_func (ignore)
3196 int ignore ATTRIBUTE_UNUSED;
3198 if (! thumb_mode)
3199 opcode_select (16);
3201 /* The following label is the name/address of the start of a Thumb function.
3202 We need to know this for the interworking support. */
3203 label_is_thumb_function_name = TRUE;
3205 demand_empty_rest_of_line ();
3208 /* Perform a .set directive, but also mark the alias as
3209 being a thumb function. */
3211 static void
3212 s_thumb_set (equiv)
3213 int equiv;
3215 /* XXX the following is a duplicate of the code for s_set() in read.c
3216 We cannot just call that code as we need to get at the symbol that
3217 is created. */
3218 register char * name;
3219 register char delim;
3220 register char * end_name;
3221 register symbolS * symbolP;
3223 /* Especial apologies for the random logic:
3224 This just grew, and could be parsed much more simply!
3225 Dean - in haste. */
3226 name = input_line_pointer;
3227 delim = get_symbol_end ();
3228 end_name = input_line_pointer;
3229 *end_name = delim;
3231 SKIP_WHITESPACE ();
3233 if (*input_line_pointer != ',')
3235 *end_name = 0;
3236 as_bad (_("expected comma after name \"%s\""), name);
3237 *end_name = delim;
3238 ignore_rest_of_line ();
3239 return;
3242 input_line_pointer++;
3243 *end_name = 0;
3245 if (name[0] == '.' && name[1] == '\0')
3247 /* XXX - this should not happen to .thumb_set. */
3248 abort ();
3251 if ((symbolP = symbol_find (name)) == NULL
3252 && (symbolP = md_undefined_symbol (name)) == NULL)
3254 #ifndef NO_LISTING
3255 /* When doing symbol listings, play games with dummy fragments living
3256 outside the normal fragment chain to record the file and line info
3257 for this symbol. */
3258 if (listing & LISTING_SYMBOLS)
3260 extern struct list_info_struct * listing_tail;
3261 fragS * dummy_frag = (fragS *) xmalloc (sizeof (fragS));
3263 memset (dummy_frag, 0, sizeof (fragS));
3264 dummy_frag->fr_type = rs_fill;
3265 dummy_frag->line = listing_tail;
3266 symbolP = symbol_new (name, undefined_section, 0, dummy_frag);
3267 dummy_frag->fr_symbol = symbolP;
3269 else
3270 #endif
3271 symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
3273 #ifdef OBJ_COFF
3274 /* "set" symbols are local unless otherwise specified. */
3275 SF_SET_LOCAL (symbolP);
3276 #endif /* OBJ_COFF */
3277 } /* Make a new symbol. */
3279 symbol_table_insert (symbolP);
3281 * end_name = delim;
3283 if (equiv
3284 && S_IS_DEFINED (symbolP)
3285 && S_GET_SEGMENT (symbolP) != reg_section)
3286 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP));
3288 pseudo_set (symbolP);
3290 demand_empty_rest_of_line ();
3292 /* XXX Now we come to the Thumb specific bit of code. */
3294 THUMB_SET_FUNC (symbolP, 1);
3295 ARM_SET_THUMB (symbolP, 1);
3296 #if defined OBJ_ELF || defined OBJ_COFF
3297 ARM_SET_INTERWORK (symbolP, support_interwork);
3298 #endif
3301 static void
3302 opcode_select (width)
3303 int width;
3305 switch (width)
3307 case 16:
3308 if (! thumb_mode)
3310 if (! (cpu_variant & ARM_EXT_V4T))
3311 as_bad (_("selected processor does not support THUMB opcodes"));
3313 thumb_mode = 1;
3314 /* No need to force the alignment, since we will have been
3315 coming from ARM mode, which is word-aligned. */
3316 record_alignment (now_seg, 1);
3318 mapping_state (MAP_THUMB);
3319 break;
3321 case 32:
3322 if (thumb_mode)
3324 if ((cpu_variant & ARM_ALL) == ARM_EXT_V4T)
3325 as_bad (_("selected processor does not support ARM opcodes"));
3327 thumb_mode = 0;
3329 if (!need_pass_2)
3330 frag_align (2, 0, 0);
3332 record_alignment (now_seg, 1);
3334 mapping_state (MAP_ARM);
3335 break;
3337 default:
3338 as_bad (_("invalid instruction size selected (%d)"), width);
3342 static void
3343 s_arm (ignore)
3344 int ignore ATTRIBUTE_UNUSED;
3346 opcode_select (32);
3347 demand_empty_rest_of_line ();
3350 static void
3351 s_thumb (ignore)
3352 int ignore ATTRIBUTE_UNUSED;
3354 opcode_select (16);
3355 demand_empty_rest_of_line ();
3358 static void
3359 s_code (unused)
3360 int unused ATTRIBUTE_UNUSED;
3362 register int temp;
3364 temp = get_absolute_expression ();
3365 switch (temp)
3367 case 16:
3368 case 32:
3369 opcode_select (temp);
3370 break;
3372 default:
3373 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp);
3377 static void
3378 end_of_line (str)
3379 char *str;
3381 skip_whitespace (str);
3383 if (*str != '\0' && !inst.error)
3384 inst.error = _("garbage following instruction");
3387 static int
3388 skip_past_comma (str)
3389 char ** str;
3391 char * p = * str, c;
3392 int comma = 0;
3394 while ((c = *p) == ' ' || c == ',')
3396 p++;
3397 if (c == ',' && comma++)
3398 return FAIL;
3401 if (c == '\0')
3402 return FAIL;
3404 *str = p;
3405 return comma ? SUCCESS : FAIL;
3408 /* A standard register must be given at this point.
3409 SHIFT is the place to put it in inst.instruction.
3410 Restores input start point on error.
3411 Returns the reg#, or FAIL. */
3413 static int
3414 reg_required_here (str, shift)
3415 char ** str;
3416 int shift;
3418 static char buff [128]; /* XXX */
3419 int reg;
3420 char * start = * str;
3422 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_RN].htab)) != FAIL)
3424 if (shift >= 0)
3425 inst.instruction |= reg << shift;
3426 return reg;
3429 /* Restore the start point, we may have got a reg of the wrong class. */
3430 *str = start;
3432 /* In the few cases where we might be able to accept something else
3433 this error can be overridden. */
3434 sprintf (buff, _("register expected, not '%.100s'"), start);
3435 inst.error = buff;
3437 return FAIL;
3440 /* A Intel Wireless MMX technology register
3441 must be given at this point.
3442 Shift is the place to put it in inst.instruction.
3443 Restores input start point on err.
3444 Returns the reg#, or FAIL. */
3446 static int
3447 wreg_required_here (str, shift, reg_type)
3448 char ** str;
3449 int shift;
3450 enum wreg_type reg_type;
3452 static char buff [128];
3453 int reg;
3454 char * start = *str;
3456 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_IWMMXT].htab)) != FAIL)
3458 if (wr_register (reg)
3459 && (reg_type == IWMMXT_REG_WR || reg_type == IWMMXT_REG_WR_OR_WC))
3461 if (shift >= 0)
3462 inst.instruction |= (reg ^ WR_PREFIX) << shift;
3463 return reg;
3465 else if (wc_register (reg)
3466 && (reg_type == IWMMXT_REG_WC || reg_type == IWMMXT_REG_WR_OR_WC))
3468 if (shift >= 0)
3469 inst.instruction |= (reg ^ WC_PREFIX) << shift;
3470 return reg;
3472 else if ((wcg_register (reg) && reg_type == IWMMXT_REG_WCG))
3474 if (shift >= 0)
3475 inst.instruction |= ((reg ^ WC_PREFIX) - 8) << shift;
3476 return reg;
3480 /* Restore the start point, we may have got a reg of the wrong class. */
3481 *str = start;
3483 /* In the few cases where we might be able to accept
3484 something else this error can be overridden. */
3485 sprintf (buff, _("Intel Wireless MMX technology register expected, not '%.100s'"), start);
3486 inst.error = buff;
3488 return FAIL;
3491 static const struct asm_psr *
3492 arm_psr_parse (ccp)
3493 register char ** ccp;
3495 char * start = * ccp;
3496 char c;
3497 char * p;
3498 const struct asm_psr * psr;
3500 p = start;
3502 /* Skip to the end of the next word in the input stream. */
3505 c = *p++;
3507 while (ISALPHA (c) || c == '_');
3509 /* Terminate the word. */
3510 *--p = 0;
3512 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
3513 feature for ease of use and backwards compatibility. */
3514 if (!strncmp (start, "cpsr", 4))
3515 strncpy (start, "CPSR", 4);
3516 else if (!strncmp (start, "spsr", 4))
3517 strncpy (start, "SPSR", 4);
3519 /* Now locate the word in the psr hash table. */
3520 psr = (const struct asm_psr *) hash_find (arm_psr_hsh, start);
3522 /* Restore the input stream. */
3523 *p = c;
3525 /* If we found a valid match, advance the
3526 stream pointer past the end of the word. */
3527 *ccp = p;
3529 return psr;
3532 /* Parse the input looking for a PSR flag. */
3534 static int
3535 psr_required_here (str)
3536 char ** str;
3538 char * start = * str;
3539 const struct asm_psr * psr;
3541 psr = arm_psr_parse (str);
3543 if (psr)
3545 /* If this is the SPSR that is being modified, set the R bit. */
3546 if (! psr->cpsr)
3547 inst.instruction |= SPSR_BIT;
3549 /* Set the psr flags in the MSR instruction. */
3550 inst.instruction |= psr->field << PSR_SHIFT;
3552 return SUCCESS;
3555 /* In the few cases where we might be able to accept
3556 something else this error can be overridden. */
3557 inst.error = _("flag for {c}psr instruction expected");
3559 /* Restore the start point. */
3560 *str = start;
3561 return FAIL;
3564 static int
3565 co_proc_number (str)
3566 char **str;
3568 int processor, pchar;
3569 char *start;
3571 skip_whitespace (*str);
3572 start = *str;
3574 /* The data sheet seems to imply that just a number on its own is valid
3575 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
3576 accept either. */
3577 if ((processor = arm_reg_parse (str, all_reg_maps[REG_TYPE_CP].htab))
3578 == FAIL)
3580 *str = start;
3582 pchar = *(*str)++;
3583 if (pchar >= '0' && pchar <= '9')
3585 processor = pchar - '0';
3586 if (**str >= '0' && **str <= '9')
3588 processor = processor * 10 + *(*str)++ - '0';
3589 if (processor > 15)
3591 inst.error = _("illegal co-processor number");
3592 return FAIL;
3596 else
3598 inst.error = all_reg_maps[REG_TYPE_CP].expected;
3599 return FAIL;
3603 inst.instruction |= processor << 8;
3604 return SUCCESS;
3607 static int
3608 cp_opc_expr (str, where, length)
3609 char ** str;
3610 int where;
3611 int length;
3613 expressionS expr;
3615 skip_whitespace (* str);
3617 memset (&expr, '\0', sizeof (expr));
3619 if (my_get_expression (&expr, str))
3620 return FAIL;
3621 if (expr.X_op != O_constant)
3623 inst.error = _("bad or missing expression");
3624 return FAIL;
3627 if ((expr.X_add_number & ((1 << length) - 1)) != expr.X_add_number)
3629 inst.error = _("immediate co-processor expression too large");
3630 return FAIL;
3633 inst.instruction |= expr.X_add_number << where;
3634 return SUCCESS;
3637 static int
3638 cp_reg_required_here (str, where)
3639 char ** str;
3640 int where;
3642 int reg;
3643 char * start = *str;
3645 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
3647 inst.instruction |= reg << where;
3648 return reg;
3651 /* In the few cases where we might be able to accept something else
3652 this error can be overridden. */
3653 inst.error = all_reg_maps[REG_TYPE_CN].expected;
3655 /* Restore the start point. */
3656 *str = start;
3657 return FAIL;
3660 static int
3661 fp_reg_required_here (str, where)
3662 char ** str;
3663 int where;
3665 int reg;
3666 char * start = * str;
3668 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_FN].htab)) != FAIL)
3670 inst.instruction |= reg << where;
3671 return reg;
3674 /* In the few cases where we might be able to accept something else
3675 this error can be overridden. */
3676 inst.error = all_reg_maps[REG_TYPE_FN].expected;
3678 /* Restore the start point. */
3679 *str = start;
3680 return FAIL;
3683 static int
3684 cp_address_offset (str)
3685 char ** str;
3687 int offset;
3689 skip_whitespace (* str);
3691 if (! is_immediate_prefix (**str))
3693 inst.error = _("immediate expression expected");
3694 return FAIL;
3697 (*str)++;
3699 if (my_get_expression (& inst.reloc.exp, str))
3700 return FAIL;
3702 if (inst.reloc.exp.X_op == O_constant)
3704 offset = inst.reloc.exp.X_add_number;
3706 if (offset & 3)
3708 inst.error = _("co-processor address must be word aligned");
3709 return FAIL;
3712 if (offset > 1023 || offset < -1023)
3714 inst.error = _("offset too large");
3715 return FAIL;
3718 if (offset >= 0)
3719 inst.instruction |= INDEX_UP;
3720 else
3721 offset = -offset;
3723 inst.instruction |= offset >> 2;
3725 else
3726 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
3728 return SUCCESS;
3731 static int
3732 cp_address_required_here (str, wb_ok)
3733 char ** str;
3734 int wb_ok;
3736 char * p = * str;
3737 int pre_inc = 0;
3738 int write_back = 0;
3740 if (*p == '[')
3742 int reg;
3744 p++;
3745 skip_whitespace (p);
3747 if ((reg = reg_required_here (& p, 16)) == FAIL)
3748 return FAIL;
3750 skip_whitespace (p);
3752 if (*p == ']')
3754 p++;
3756 skip_whitespace (p);
3758 if (*p == '\0')
3760 /* As an extension to the official ARM syntax we allow:
3762 [Rn]
3764 as a short hand for:
3766 [Rn,#0] */
3767 inst.instruction |= PRE_INDEX | INDEX_UP;
3768 *str = p;
3769 return SUCCESS;
3772 if (skip_past_comma (& p) == FAIL)
3774 inst.error = _("comma expected after closing square bracket");
3775 return FAIL;
3778 skip_whitespace (p);
3780 if (*p == '#')
3782 if (wb_ok)
3784 /* [Rn], #expr */
3785 write_back = WRITE_BACK;
3787 if (reg == REG_PC)
3789 inst.error = _("pc may not be used in post-increment");
3790 return FAIL;
3793 if (cp_address_offset (& p) == FAIL)
3794 return FAIL;
3796 else
3797 pre_inc = PRE_INDEX | INDEX_UP;
3799 else if (*p == '{')
3801 int option;
3803 /* [Rn], {<expr>} */
3804 p++;
3806 skip_whitespace (p);
3808 if (my_get_expression (& inst.reloc.exp, & p))
3809 return FAIL;
3811 if (inst.reloc.exp.X_op == O_constant)
3813 option = inst.reloc.exp.X_add_number;
3815 if (option > 255 || option < 0)
3817 inst.error = _("'option' field too large");
3818 return FAIL;
3821 skip_whitespace (p);
3823 if (*p != '}')
3825 inst.error = _("'}' expected at end of 'option' field");
3826 return FAIL;
3828 else
3830 p++;
3831 inst.instruction |= option;
3832 inst.instruction |= INDEX_UP;
3835 else
3837 inst.error = _("non-constant expressions for 'option' field not supported");
3838 return FAIL;
3841 else
3843 inst.error = _("# or { expected after comma");
3844 return FAIL;
3847 else
3849 /* '['Rn, #expr']'[!] */
3851 if (skip_past_comma (& p) == FAIL)
3853 inst.error = _("pre-indexed expression expected");
3854 return FAIL;
3857 pre_inc = PRE_INDEX;
3859 if (cp_address_offset (& p) == FAIL)
3860 return FAIL;
3862 skip_whitespace (p);
3864 if (*p++ != ']')
3866 inst.error = _("missing ]");
3867 return FAIL;
3870 skip_whitespace (p);
3872 if (wb_ok && *p == '!')
3874 if (reg == REG_PC)
3876 inst.error = _("pc may not be used with write-back");
3877 return FAIL;
3880 p++;
3881 write_back = WRITE_BACK;
3885 else
3887 if (my_get_expression (&inst.reloc.exp, &p))
3888 return FAIL;
3890 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
3891 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
3892 inst.reloc.pc_rel = 1;
3893 inst.instruction |= (REG_PC << 16);
3894 pre_inc = PRE_INDEX;
3897 inst.instruction |= write_back | pre_inc;
3898 *str = p;
3899 return SUCCESS;
3902 static int
3903 cp_byte_address_offset (str)
3904 char ** str;
3906 int offset;
3908 skip_whitespace (* str);
3910 if (! is_immediate_prefix (**str))
3912 inst.error = _("immediate expression expected");
3913 return FAIL;
3916 (*str)++;
3918 if (my_get_expression (& inst.reloc.exp, str))
3919 return FAIL;
3921 if (inst.reloc.exp.X_op == O_constant)
3923 offset = inst.reloc.exp.X_add_number;
3925 if (offset > 255 || offset < -255)
3927 inst.error = _("offset too large");
3928 return FAIL;
3931 if (offset >= 0)
3932 inst.instruction |= INDEX_UP;
3933 else
3934 offset = -offset;
3936 inst.instruction |= offset;
3938 else
3939 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
3941 return SUCCESS;
3944 static int
3945 cp_byte_address_required_here (str)
3946 char ** str;
3948 char * p = * str;
3949 int pre_inc = 0;
3950 int write_back = 0;
3952 if (*p == '[')
3954 int reg;
3956 p++;
3957 skip_whitespace (p);
3959 if ((reg = reg_required_here (& p, 16)) == FAIL)
3960 return FAIL;
3962 skip_whitespace (p);
3964 if (*p == ']')
3966 p++;
3968 if (skip_past_comma (& p) == SUCCESS)
3970 /* [Rn], #expr */
3971 write_back = WRITE_BACK;
3973 if (reg == REG_PC)
3975 inst.error = _("pc may not be used in post-increment");
3976 return FAIL;
3979 if (cp_byte_address_offset (& p) == FAIL)
3980 return FAIL;
3982 else
3983 pre_inc = PRE_INDEX | INDEX_UP;
3985 else
3987 /* '['Rn, #expr']'[!] */
3989 if (skip_past_comma (& p) == FAIL)
3991 inst.error = _("pre-indexed expression expected");
3992 return FAIL;
3995 pre_inc = PRE_INDEX;
3997 if (cp_byte_address_offset (& p) == FAIL)
3998 return FAIL;
4000 skip_whitespace (p);
4002 if (*p++ != ']')
4004 inst.error = _("missing ]");
4005 return FAIL;
4008 skip_whitespace (p);
4010 if (*p == '!')
4012 if (reg == REG_PC)
4014 inst.error = _("pc may not be used with write-back");
4015 return FAIL;
4018 p++;
4019 write_back = WRITE_BACK;
4023 else
4025 if (my_get_expression (&inst.reloc.exp, &p))
4026 return FAIL;
4028 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
4029 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
4030 inst.reloc.pc_rel = 1;
4031 inst.instruction |= (REG_PC << 16);
4032 pre_inc = PRE_INDEX;
4035 inst.instruction |= write_back | pre_inc;
4036 *str = p;
4037 return SUCCESS;
4040 static void
4041 do_empty (str)
4042 char * str;
4044 /* Do nothing really. */
4045 end_of_line (str);
4048 static void
4049 do_mrs (str)
4050 char *str;
4052 int skip = 0;
4054 /* Only one syntax. */
4055 skip_whitespace (str);
4057 if (reg_required_here (&str, 12) == FAIL)
4059 inst.error = BAD_ARGS;
4060 return;
4063 if (skip_past_comma (&str) == FAIL)
4065 inst.error = _("comma expected after register name");
4066 return;
4069 skip_whitespace (str);
4071 if ( strcmp (str, "CPSR") == 0
4072 || strcmp (str, "SPSR") == 0
4073 /* Lower case versions for backwards compatibility. */
4074 || strcmp (str, "cpsr") == 0
4075 || strcmp (str, "spsr") == 0)
4076 skip = 4;
4078 /* This is for backwards compatibility with older toolchains. */
4079 else if ( strcmp (str, "cpsr_all") == 0
4080 || strcmp (str, "spsr_all") == 0)
4081 skip = 8;
4082 else
4084 inst.error = _("CPSR or SPSR expected");
4085 return;
4088 if (* str == 's' || * str == 'S')
4089 inst.instruction |= SPSR_BIT;
4090 str += skip;
4092 end_of_line (str);
4095 /* Two possible forms:
4096 "{C|S}PSR_<field>, Rm",
4097 "{C|S}PSR_f, #expression". */
4099 static void
4100 do_msr (str)
4101 char * str;
4103 skip_whitespace (str);
4105 if (psr_required_here (& str) == FAIL)
4106 return;
4108 if (skip_past_comma (& str) == FAIL)
4110 inst.error = _("comma missing after psr flags");
4111 return;
4114 skip_whitespace (str);
4116 if (reg_required_here (& str, 0) != FAIL)
4118 inst.error = NULL;
4119 end_of_line (str);
4120 return;
4123 if (! is_immediate_prefix (* str))
4125 inst.error =
4126 _("only a register or immediate value can follow a psr flag");
4127 return;
4130 str ++;
4131 inst.error = NULL;
4133 if (my_get_expression (& inst.reloc.exp, & str))
4135 inst.error =
4136 _("only a register or immediate value can follow a psr flag");
4137 return;
4140 #if 0 /* The first edition of the ARM architecture manual stated that
4141 writing anything other than the flags with an immediate operation
4142 had UNPREDICTABLE effects. This constraint was removed in the
4143 second edition of the specification. */
4144 if ((cpu_variant & ARM_EXT_V5) != ARM_EXT_V5
4145 && inst.instruction & ((PSR_c | PSR_x | PSR_s) << PSR_SHIFT))
4147 inst.error = _("immediate value cannot be used to set this field");
4148 return;
4150 #endif
4152 inst.instruction |= INST_IMMEDIATE;
4154 if (inst.reloc.exp.X_add_symbol)
4156 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
4157 inst.reloc.pc_rel = 0;
4159 else
4161 unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
4163 if (value == (unsigned) FAIL)
4165 inst.error = _("invalid constant");
4166 return;
4169 inst.instruction |= value;
4172 inst.error = NULL;
4173 end_of_line (str);
4176 /* Long Multiply Parser
4177 UMULL RdLo, RdHi, Rm, Rs
4178 SMULL RdLo, RdHi, Rm, Rs
4179 UMLAL RdLo, RdHi, Rm, Rs
4180 SMLAL RdLo, RdHi, Rm, Rs. */
4182 static void
4183 do_mull (str)
4184 char * str;
4186 int rdlo, rdhi, rm, rs;
4188 /* Only one format "rdlo, rdhi, rm, rs". */
4189 skip_whitespace (str);
4191 if ((rdlo = reg_required_here (&str, 12)) == FAIL)
4193 inst.error = BAD_ARGS;
4194 return;
4197 if (skip_past_comma (&str) == FAIL
4198 || (rdhi = reg_required_here (&str, 16)) == FAIL)
4200 inst.error = BAD_ARGS;
4201 return;
4204 if (skip_past_comma (&str) == FAIL
4205 || (rm = reg_required_here (&str, 0)) == FAIL)
4207 inst.error = BAD_ARGS;
4208 return;
4211 /* rdhi, rdlo and rm must all be different. */
4212 if (rdlo == rdhi || rdlo == rm || rdhi == rm)
4213 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
4215 if (skip_past_comma (&str) == FAIL
4216 || (rs = reg_required_here (&str, 8)) == FAIL)
4218 inst.error = BAD_ARGS;
4219 return;
4222 if (rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC)
4224 inst.error = BAD_PC;
4225 return;
4228 end_of_line (str);
4231 static void
4232 do_mul (str)
4233 char * str;
4235 int rd, rm;
4237 /* Only one format "rd, rm, rs". */
4238 skip_whitespace (str);
4240 if ((rd = reg_required_here (&str, 16)) == FAIL)
4242 inst.error = BAD_ARGS;
4243 return;
4246 if (rd == REG_PC)
4248 inst.error = BAD_PC;
4249 return;
4252 if (skip_past_comma (&str) == FAIL
4253 || (rm = reg_required_here (&str, 0)) == FAIL)
4255 inst.error = BAD_ARGS;
4256 return;
4259 if (rm == REG_PC)
4261 inst.error = BAD_PC;
4262 return;
4265 if (rm == rd)
4266 as_tsktsk (_("rd and rm should be different in mul"));
4268 if (skip_past_comma (&str) == FAIL
4269 || (rm = reg_required_here (&str, 8)) == FAIL)
4271 inst.error = BAD_ARGS;
4272 return;
4275 if (rm == REG_PC)
4277 inst.error = BAD_PC;
4278 return;
4281 end_of_line (str);
4284 static void
4285 do_mla (str)
4286 char * str;
4288 int rd, rm;
4290 /* Only one format "rd, rm, rs, rn". */
4291 skip_whitespace (str);
4293 if ((rd = reg_required_here (&str, 16)) == FAIL)
4295 inst.error = BAD_ARGS;
4296 return;
4299 if (rd == REG_PC)
4301 inst.error = BAD_PC;
4302 return;
4305 if (skip_past_comma (&str) == FAIL
4306 || (rm = reg_required_here (&str, 0)) == FAIL)
4308 inst.error = BAD_ARGS;
4309 return;
4312 if (rm == REG_PC)
4314 inst.error = BAD_PC;
4315 return;
4318 if (rm == rd)
4319 as_tsktsk (_("rd and rm should be different in mla"));
4321 if (skip_past_comma (&str) == FAIL
4322 || (rd = reg_required_here (&str, 8)) == FAIL
4323 || skip_past_comma (&str) == FAIL
4324 || (rm = reg_required_here (&str, 12)) == FAIL)
4326 inst.error = BAD_ARGS;
4327 return;
4330 if (rd == REG_PC || rm == REG_PC)
4332 inst.error = BAD_PC;
4333 return;
4336 end_of_line (str);
4339 /* Expects *str -> the characters "acc0", possibly with leading blanks.
4340 Advances *str to the next non-alphanumeric.
4341 Returns 0, or else FAIL (in which case sets inst.error).
4343 (In a future XScale, there may be accumulators other than zero.
4344 At that time this routine and its callers can be upgraded to suit.) */
4346 static int
4347 accum0_required_here (str)
4348 char ** str;
4350 static char buff [128]; /* Note the address is taken. Hence, static. */
4351 char * p = * str;
4352 char c;
4353 int result = 0; /* The accum number. */
4355 skip_whitespace (p);
4357 *str = p; /* Advance caller's string pointer too. */
4358 c = *p++;
4359 while (ISALNUM (c))
4360 c = *p++;
4362 *--p = 0; /* Aap nul into input buffer at non-alnum. */
4364 if (! ( streq (*str, "acc0") || streq (*str, "ACC0")))
4366 sprintf (buff, _("acc0 expected, not '%.100s'"), *str);
4367 inst.error = buff;
4368 result = FAIL;
4371 *p = c; /* Unzap. */
4372 *str = p; /* Caller's string pointer to after match. */
4373 return result;
4376 /* Expects **str -> after a comma. May be leading blanks.
4377 Advances *str, recognizing a load mode, and setting inst.instruction.
4378 Returns rn, or else FAIL (in which case may set inst.error
4379 and not advance str)
4381 Note: doesn't know Rd, so no err checks that require such knowledge. */
4383 static int
4384 ld_mode_required_here (string)
4385 char ** string;
4387 char * str = * string;
4388 int rn;
4389 int pre_inc = 0;
4391 skip_whitespace (str);
4393 if (* str == '[')
4395 str++;
4397 skip_whitespace (str);
4399 if ((rn = reg_required_here (& str, 16)) == FAIL)
4400 return FAIL;
4402 skip_whitespace (str);
4404 if (* str == ']')
4406 str ++;
4408 if (skip_past_comma (& str) == SUCCESS)
4410 /* [Rn],... (post inc) */
4411 if (ldst_extend_v4 (&str) == FAIL)
4412 return FAIL;
4414 else /* [Rn] */
4416 skip_whitespace (str);
4418 if (* str == '!')
4420 str ++;
4421 inst.instruction |= WRITE_BACK;
4424 inst.instruction |= INDEX_UP | HWOFFSET_IMM;
4425 pre_inc = 1;
4428 else /* [Rn,...] */
4430 if (skip_past_comma (& str) == FAIL)
4432 inst.error = _("pre-indexed expression expected");
4433 return FAIL;
4436 pre_inc = 1;
4438 if (ldst_extend_v4 (&str) == FAIL)
4439 return FAIL;
4441 skip_whitespace (str);
4443 if (* str ++ != ']')
4445 inst.error = _("missing ]");
4446 return FAIL;
4449 skip_whitespace (str);
4451 if (* str == '!')
4453 str ++;
4454 inst.instruction |= WRITE_BACK;
4458 else if (* str == '=') /* ldr's "r,=label" syntax */
4459 /* We should never reach here, because <text> = <expression> is
4460 caught gas/read.c read_a_source_file() as a .set operation. */
4461 return FAIL;
4462 else /* PC +- 8 bit immediate offset. */
4464 if (my_get_expression (& inst.reloc.exp, & str))
4465 return FAIL;
4467 inst.instruction |= HWOFFSET_IMM; /* The I bit. */
4468 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
4469 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
4470 inst.reloc.pc_rel = 1;
4471 inst.instruction |= (REG_PC << 16);
4473 rn = REG_PC;
4474 pre_inc = 1;
4477 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
4478 * string = str;
4480 return rn;
4483 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
4484 SMLAxy{cond} Rd,Rm,Rs,Rn
4485 SMLAWy{cond} Rd,Rm,Rs,Rn
4486 Error if any register is R15. */
4488 static void
4489 do_smla (str)
4490 char * str;
4492 int rd, rm, rs, rn;
4494 skip_whitespace (str);
4496 if ((rd = reg_required_here (& str, 16)) == FAIL
4497 || skip_past_comma (& str) == FAIL
4498 || (rm = reg_required_here (& str, 0)) == FAIL
4499 || skip_past_comma (& str) == FAIL
4500 || (rs = reg_required_here (& str, 8)) == FAIL
4501 || skip_past_comma (& str) == FAIL
4502 || (rn = reg_required_here (& str, 12)) == FAIL)
4503 inst.error = BAD_ARGS;
4505 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC || rn == REG_PC)
4506 inst.error = BAD_PC;
4508 else
4509 end_of_line (str);
4512 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
4513 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
4514 Error if any register is R15.
4515 Warning if Rdlo == Rdhi. */
4517 static void
4518 do_smlal (str)
4519 char * str;
4521 int rdlo, rdhi, rm, rs;
4523 skip_whitespace (str);
4525 if ((rdlo = reg_required_here (& str, 12)) == FAIL
4526 || skip_past_comma (& str) == FAIL
4527 || (rdhi = reg_required_here (& str, 16)) == FAIL
4528 || skip_past_comma (& str) == FAIL
4529 || (rm = reg_required_here (& str, 0)) == FAIL
4530 || skip_past_comma (& str) == FAIL
4531 || (rs = reg_required_here (& str, 8)) == FAIL)
4533 inst.error = BAD_ARGS;
4534 return;
4537 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
4539 inst.error = BAD_PC;
4540 return;
4543 if (rdlo == rdhi)
4544 as_tsktsk (_("rdhi and rdlo must be different"));
4546 end_of_line (str);
4549 /* ARM V5E (El Segundo) signed-multiply (argument parse)
4550 SMULxy{cond} Rd,Rm,Rs
4551 Error if any register is R15. */
4553 static void
4554 do_smul (str)
4555 char * str;
4557 int rd, rm, rs;
4559 skip_whitespace (str);
4561 if ((rd = reg_required_here (& str, 16)) == FAIL
4562 || skip_past_comma (& str) == FAIL
4563 || (rm = reg_required_here (& str, 0)) == FAIL
4564 || skip_past_comma (& str) == FAIL
4565 || (rs = reg_required_here (& str, 8)) == FAIL)
4566 inst.error = BAD_ARGS;
4568 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC)
4569 inst.error = BAD_PC;
4571 else
4572 end_of_line (str);
4575 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
4576 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
4577 Error if any register is R15. */
4579 static void
4580 do_qadd (str)
4581 char * str;
4583 int rd, rm, rn;
4585 skip_whitespace (str);
4587 if ((rd = reg_required_here (& str, 12)) == FAIL
4588 || skip_past_comma (& str) == FAIL
4589 || (rm = reg_required_here (& str, 0)) == FAIL
4590 || skip_past_comma (& str) == FAIL
4591 || (rn = reg_required_here (& str, 16)) == FAIL)
4592 inst.error = BAD_ARGS;
4594 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
4595 inst.error = BAD_PC;
4597 else
4598 end_of_line (str);
4601 /* ARM V5E (el Segundo)
4602 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4603 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4605 These are equivalent to the XScale instructions MAR and MRA,
4606 respectively, when coproc == 0, opcode == 0, and CRm == 0.
4608 Result unpredicatable if Rd or Rn is R15. */
4610 static void
4611 do_co_reg2c (str)
4612 char * str;
4614 int rd, rn;
4616 skip_whitespace (str);
4618 if (co_proc_number (& str) == FAIL)
4620 if (!inst.error)
4621 inst.error = BAD_ARGS;
4622 return;
4625 if (skip_past_comma (& str) == FAIL
4626 || cp_opc_expr (& str, 4, 4) == FAIL)
4628 if (!inst.error)
4629 inst.error = BAD_ARGS;
4630 return;
4633 if (skip_past_comma (& str) == FAIL
4634 || (rd = reg_required_here (& str, 12)) == FAIL)
4636 if (!inst.error)
4637 inst.error = BAD_ARGS;
4638 return;
4641 if (skip_past_comma (& str) == FAIL
4642 || (rn = reg_required_here (& str, 16)) == FAIL)
4644 if (!inst.error)
4645 inst.error = BAD_ARGS;
4646 return;
4649 /* Unpredictable result if rd or rn is R15. */
4650 if (rd == REG_PC || rn == REG_PC)
4651 as_tsktsk
4652 (_("Warning: instruction unpredictable when using r15"));
4654 if (skip_past_comma (& str) == FAIL
4655 || cp_reg_required_here (& str, 0) == FAIL)
4657 if (!inst.error)
4658 inst.error = BAD_ARGS;
4659 return;
4662 end_of_line (str);
4665 /* ARM V5 count-leading-zeroes instruction (argument parse)
4666 CLZ{<cond>} <Rd>, <Rm>
4667 Condition defaults to COND_ALWAYS.
4668 Error if Rd or Rm are R15. */
4670 static void
4671 do_clz (str)
4672 char * str;
4674 int rd, rm;
4676 skip_whitespace (str);
4678 if (((rd = reg_required_here (& str, 12)) == FAIL)
4679 || (skip_past_comma (& str) == FAIL)
4680 || ((rm = reg_required_here (& str, 0)) == FAIL))
4681 inst.error = BAD_ARGS;
4683 else if (rd == REG_PC || rm == REG_PC )
4684 inst.error = BAD_PC;
4686 else
4687 end_of_line (str);
4690 /* ARM V5 (argument parse)
4691 LDC2{L} <coproc>, <CRd>, <addressing mode>
4692 STC2{L} <coproc>, <CRd>, <addressing mode>
4693 Instruction is not conditional, and has 0xf in the condition field.
4694 Otherwise, it's the same as LDC/STC. */
4696 static void
4697 do_lstc2 (str)
4698 char * str;
4700 skip_whitespace (str);
4702 if (co_proc_number (& str) == FAIL)
4704 if (!inst.error)
4705 inst.error = BAD_ARGS;
4707 else if (skip_past_comma (& str) == FAIL
4708 || cp_reg_required_here (& str, 12) == FAIL)
4710 if (!inst.error)
4711 inst.error = BAD_ARGS;
4713 else if (skip_past_comma (& str) == FAIL
4714 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
4716 if (! inst.error)
4717 inst.error = BAD_ARGS;
4719 else
4720 end_of_line (str);
4723 /* ARM V5 (argument parse)
4724 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
4725 Instruction is not conditional, and has 0xf in the condition field.
4726 Otherwise, it's the same as CDP. */
4728 static void
4729 do_cdp2 (str)
4730 char * str;
4732 skip_whitespace (str);
4734 if (co_proc_number (& str) == FAIL)
4736 if (!inst.error)
4737 inst.error = BAD_ARGS;
4738 return;
4741 if (skip_past_comma (& str) == FAIL
4742 || cp_opc_expr (& str, 20,4) == FAIL)
4744 if (!inst.error)
4745 inst.error = BAD_ARGS;
4746 return;
4749 if (skip_past_comma (& str) == FAIL
4750 || cp_reg_required_here (& str, 12) == FAIL)
4752 if (!inst.error)
4753 inst.error = BAD_ARGS;
4754 return;
4757 if (skip_past_comma (& str) == FAIL
4758 || cp_reg_required_here (& str, 16) == FAIL)
4760 if (!inst.error)
4761 inst.error = BAD_ARGS;
4762 return;
4765 if (skip_past_comma (& str) == FAIL
4766 || cp_reg_required_here (& str, 0) == FAIL)
4768 if (!inst.error)
4769 inst.error = BAD_ARGS;
4770 return;
4773 if (skip_past_comma (& str) == SUCCESS)
4775 if (cp_opc_expr (& str, 5, 3) == FAIL)
4777 if (!inst.error)
4778 inst.error = BAD_ARGS;
4779 return;
4783 end_of_line (str);
4786 /* ARM V5 (argument parse)
4787 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4788 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4789 Instruction is not conditional, and has 0xf in the condition field.
4790 Otherwise, it's the same as MCR/MRC. */
4792 static void
4793 do_co_reg2 (str)
4794 char * str;
4796 skip_whitespace (str);
4798 if (co_proc_number (& str) == FAIL)
4800 if (!inst.error)
4801 inst.error = BAD_ARGS;
4802 return;
4805 if (skip_past_comma (& str) == FAIL
4806 || cp_opc_expr (& str, 21, 3) == FAIL)
4808 if (!inst.error)
4809 inst.error = BAD_ARGS;
4810 return;
4813 if (skip_past_comma (& str) == FAIL
4814 || reg_required_here (& str, 12) == FAIL)
4816 if (!inst.error)
4817 inst.error = BAD_ARGS;
4818 return;
4821 if (skip_past_comma (& str) == FAIL
4822 || cp_reg_required_here (& str, 16) == FAIL)
4824 if (!inst.error)
4825 inst.error = BAD_ARGS;
4826 return;
4829 if (skip_past_comma (& str) == FAIL
4830 || cp_reg_required_here (& str, 0) == FAIL)
4832 if (!inst.error)
4833 inst.error = BAD_ARGS;
4834 return;
4837 if (skip_past_comma (& str) == SUCCESS)
4839 if (cp_opc_expr (& str, 5, 3) == FAIL)
4841 if (!inst.error)
4842 inst.error = BAD_ARGS;
4843 return;
4847 end_of_line (str);
4850 /* ARM v5TEJ. Jump to Jazelle code. */
4851 static void
4852 do_bxj (str)
4853 char * str;
4855 int reg;
4857 skip_whitespace (str);
4859 if ((reg = reg_required_here (&str, 0)) == FAIL)
4861 inst.error = BAD_ARGS;
4862 return;
4865 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
4866 if (reg == REG_PC)
4867 as_tsktsk (_("use of r15 in bxj is not really useful"));
4869 end_of_line (str);
4872 /* ARM V6 umaal (argument parse). */
4874 static void
4875 do_umaal (str)
4876 char *str;
4879 int rdlo, rdhi, rm, rs;
4881 skip_whitespace (str);
4882 if ((rdlo = reg_required_here (& str, 12)) == FAIL
4883 || skip_past_comma (& str) == FAIL
4884 || (rdhi = reg_required_here (& str, 16)) == FAIL
4885 || skip_past_comma (& str) == FAIL
4886 || (rm = reg_required_here (& str, 0)) == FAIL
4887 || skip_past_comma (& str) == FAIL
4888 || (rs = reg_required_here (& str, 8)) == FAIL)
4890 inst.error = BAD_ARGS;
4891 return;
4894 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
4896 inst.error = BAD_PC;
4897 return;
4900 end_of_line (str);
4903 /* ARM V6 strex (argument parse). */
4905 static void
4906 do_strex (str)
4907 char *str;
4909 int rd, rm, rn;
4911 /* Parse Rd, Rm,. */
4912 skip_whitespace (str);
4913 if ((rd = reg_required_here (& str, 12)) == FAIL
4914 || skip_past_comma (& str) == FAIL
4915 || (rm = reg_required_here (& str, 0)) == FAIL
4916 || skip_past_comma (& str) == FAIL)
4918 inst.error = BAD_ARGS;
4919 return;
4921 if (rd == REG_PC || rm == REG_PC)
4923 inst.error = BAD_PC;
4924 return;
4926 if (rd == rm)
4928 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
4929 return;
4932 /* Skip past '['. */
4933 if ((strlen (str) >= 1)
4934 && strncmp (str, "[", 1) == 0)
4935 str+=1;
4936 skip_whitespace (str);
4938 /* Parse Rn. */
4939 if ((rn = reg_required_here (& str, 16)) == FAIL)
4941 inst.error = BAD_ARGS;
4942 return;
4944 else if (rn == REG_PC)
4946 inst.error = BAD_PC;
4947 return;
4949 if (rd == rn)
4951 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
4952 return;
4954 skip_whitespace (str);
4956 /* Skip past ']'. */
4957 if ((strlen (str) >= 1)
4958 && strncmp (str, "]", 1) == 0)
4959 str+=1;
4961 end_of_line (str);
4964 /* ARM V6 ssat (argument parse). */
4966 static void
4967 do_ssat (str)
4968 char* str;
4970 do_sat (&str, /*bias=*/-1);
4971 end_of_line (str);
4974 /* ARM V6 usat (argument parse). */
4976 static void
4977 do_usat (str)
4978 char* str;
4980 do_sat (&str, /*bias=*/0);
4981 end_of_line (str);
4984 static void
4985 do_sat (str, bias)
4986 char **str;
4987 int bias;
4989 int rd, rm;
4990 expressionS expr;
4992 skip_whitespace (*str);
4994 /* Parse <Rd>, field. */
4995 if ((rd = reg_required_here (str, 12)) == FAIL
4996 || skip_past_comma (str) == FAIL)
4998 inst.error = BAD_ARGS;
4999 return;
5001 if (rd == REG_PC)
5003 inst.error = BAD_PC;
5004 return;
5007 /* Parse #<immed>, field. */
5008 if (is_immediate_prefix (**str))
5009 (*str)++;
5010 else
5012 inst.error = _("immediate expression expected");
5013 return;
5015 if (my_get_expression (&expr, str))
5017 inst.error = _("bad expression");
5018 return;
5020 if (expr.X_op != O_constant)
5022 inst.error = _("constant expression expected");
5023 return;
5025 if (expr.X_add_number + bias < 0
5026 || expr.X_add_number + bias > 31)
5028 inst.error = _("immediate value out of range");
5029 return;
5031 inst.instruction |= (expr.X_add_number + bias) << 16;
5032 if (skip_past_comma (str) == FAIL)
5034 inst.error = BAD_ARGS;
5035 return;
5038 /* Parse <Rm> field. */
5039 if ((rm = reg_required_here (str, 0)) == FAIL)
5041 inst.error = BAD_ARGS;
5042 return;
5044 if (rm == REG_PC)
5046 inst.error = BAD_PC;
5047 return;
5050 if (skip_past_comma (str) == SUCCESS)
5051 decode_shift (str, SHIFT_LSL_OR_ASR_IMMEDIATE);
5054 /* ARM V6 ssat16 (argument parse). */
5056 static void
5057 do_ssat16 (str)
5058 char *str;
5060 do_sat16 (&str, /*bias=*/-1);
5061 end_of_line (str);
5064 static void
5065 do_usat16 (str)
5066 char *str;
5068 do_sat16 (&str, /*bias=*/0);
5069 end_of_line (str);
5072 static void
5073 do_sat16 (str, bias)
5074 char **str;
5075 int bias;
5077 int rd, rm;
5078 expressionS expr;
5080 skip_whitespace (*str);
5082 /* Parse the <Rd> field. */
5083 if ((rd = reg_required_here (str, 12)) == FAIL
5084 || skip_past_comma (str) == FAIL)
5086 inst.error = BAD_ARGS;
5087 return;
5089 if (rd == REG_PC)
5091 inst.error = BAD_PC;
5092 return;
5095 /* Parse #<immed>, field. */
5096 if (is_immediate_prefix (**str))
5097 (*str)++;
5098 else
5100 inst.error = _("immediate expression expected");
5101 return;
5103 if (my_get_expression (&expr, str))
5105 inst.error = _("bad expression");
5106 return;
5108 if (expr.X_op != O_constant)
5110 inst.error = _("constant expression expected");
5111 return;
5113 if (expr.X_add_number + bias < 0
5114 || expr.X_add_number + bias > 15)
5116 inst.error = _("immediate value out of range");
5117 return;
5119 inst.instruction |= (expr.X_add_number + bias) << 16;
5120 if (skip_past_comma (str) == FAIL)
5122 inst.error = BAD_ARGS;
5123 return;
5126 /* Parse <Rm> field. */
5127 if ((rm = reg_required_here (str, 0)) == FAIL)
5129 inst.error = BAD_ARGS;
5130 return;
5132 if (rm == REG_PC)
5134 inst.error = BAD_PC;
5135 return;
5139 /* ARM V6 srs (argument parse). */
5141 static void
5142 do_srs (str)
5143 char* str;
5145 char *exclam;
5146 skip_whitespace (str);
5147 exclam = strchr (str, '!');
5148 if (exclam)
5149 *exclam = '\0';
5150 do_cps_mode (&str);
5151 if (exclam)
5152 *exclam = '!';
5153 if (*str == '!')
5155 inst.instruction |= WRITE_BACK;
5156 str++;
5158 end_of_line (str);
5161 /* ARM V6 SMMUL (argument parse). */
5163 static void
5164 do_smmul (str)
5165 char* str;
5167 int rd, rm, rs;
5169 skip_whitespace (str);
5170 if ((rd = reg_required_here (&str, 16)) == FAIL
5171 || skip_past_comma (&str) == FAIL
5172 || (rm = reg_required_here (&str, 0)) == FAIL
5173 || skip_past_comma (&str) == FAIL
5174 || (rs = reg_required_here (&str, 8)) == FAIL)
5176 inst.error = BAD_ARGS;
5177 return;
5180 if (rd == REG_PC
5181 || rm == REG_PC
5182 || rs == REG_PC)
5184 inst.error = BAD_PC;
5185 return;
5188 end_of_line (str);
5192 /* ARM V6 SMLALD (argument parse). */
5194 static void
5195 do_smlald (str)
5196 char* str;
5198 int rdlo, rdhi, rm, rs;
5199 skip_whitespace (str);
5200 if ((rdlo = reg_required_here (&str, 12)) == FAIL
5201 || skip_past_comma (&str) == FAIL
5202 || (rdhi = reg_required_here (&str, 16)) == FAIL
5203 || skip_past_comma (&str) == FAIL
5204 || (rm = reg_required_here (&str, 0)) == FAIL
5205 || skip_past_comma (&str) == FAIL
5206 || (rs = reg_required_here (&str, 8)) == FAIL)
5208 inst.error = BAD_ARGS;
5209 return;
5212 if (rdlo == REG_PC
5213 || rdhi == REG_PC
5214 || rm == REG_PC
5215 || rs == REG_PC)
5217 inst.error = BAD_PC;
5218 return;
5221 end_of_line (str);
5224 /* ARM V6 SMLAD (argument parse). Signed multiply accumulate dual.
5225 smlad{x}{<cond>} Rd, Rm, Rs, Rn */
5227 static void
5228 do_smlad (str)
5229 char *str;
5231 int rd, rm, rs, rn;
5233 skip_whitespace (str);
5234 if ((rd = reg_required_here (&str, 16)) == FAIL
5235 || skip_past_comma (&str) == FAIL
5236 || (rm = reg_required_here (&str, 0)) == FAIL
5237 || skip_past_comma (&str) == FAIL
5238 || (rs = reg_required_here (&str, 8)) == FAIL
5239 || skip_past_comma (&str) == FAIL
5240 || (rn = reg_required_here (&str, 12)) == FAIL)
5242 inst.error = BAD_ARGS;
5243 return;
5246 if (rd == REG_PC
5247 || rn == REG_PC
5248 || rs == REG_PC
5249 || rm == REG_PC)
5251 inst.error = BAD_PC;
5252 return;
5255 end_of_line (str);
5258 /* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
5259 preserving the other bits.
5261 setend <endian_specifier>, where <endian_specifier> is either
5262 BE or LE. */
5264 static void
5265 do_setend (str)
5266 char *str;
5268 if (do_endian_specifier (str))
5269 inst.instruction |= 0x200;
5272 /* Returns true if the endian-specifier indicates big-endianness. */
5274 static int
5275 do_endian_specifier (str)
5276 char *str;
5278 int big_endian = 0;
5280 skip_whitespace (str);
5281 if (strlen (str) < 2)
5282 inst.error = _("missing endian specifier");
5283 else if (strncasecmp (str, "BE", 2) == 0)
5285 str += 2;
5286 big_endian = 1;
5288 else if (strncasecmp (str, "LE", 2) == 0)
5289 str += 2;
5290 else
5291 inst.error = _("valid endian specifiers are be or le");
5293 end_of_line (str);
5295 return big_endian;
5298 /* ARM V6 SXTH.
5300 SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
5301 Condition defaults to COND_ALWAYS.
5302 Error if any register uses R15. */
5304 static void
5305 do_sxth (str)
5306 char *str;
5308 int rd, rm;
5309 expressionS expr;
5310 int rotation_clear_mask = 0xfffff3ff;
5311 int rotation_eight_mask = 0x00000400;
5312 int rotation_sixteen_mask = 0x00000800;
5313 int rotation_twenty_four_mask = 0x00000c00;
5315 skip_whitespace (str);
5316 if ((rd = reg_required_here (&str, 12)) == FAIL
5317 || skip_past_comma (&str) == FAIL
5318 || (rm = reg_required_here (&str, 0)) == FAIL)
5320 inst.error = BAD_ARGS;
5321 return;
5324 else if (rd == REG_PC || rm == REG_PC)
5326 inst.error = BAD_PC;
5327 return;
5330 /* Zero out the rotation field. */
5331 inst.instruction &= rotation_clear_mask;
5333 /* Check for lack of optional rotation field. */
5334 if (skip_past_comma (&str) == FAIL)
5336 end_of_line (str);
5337 return;
5340 /* Move past 'ROR'. */
5341 skip_whitespace (str);
5342 if (strncasecmp (str, "ROR", 3) == 0)
5343 str+=3;
5344 else
5346 inst.error = _("missing rotation field after comma");
5347 return;
5350 /* Get the immediate constant. */
5351 skip_whitespace (str);
5352 if (is_immediate_prefix (* str))
5353 str++;
5354 else
5356 inst.error = _("immediate expression expected");
5357 return;
5360 if (my_get_expression (&expr, &str))
5362 inst.error = _("bad expression");
5363 return;
5366 if (expr.X_op != O_constant)
5368 inst.error = _("constant expression expected");
5369 return;
5372 switch (expr.X_add_number)
5374 case 0:
5375 /* Rotation field has already been zeroed. */
5376 break;
5377 case 8:
5378 inst.instruction |= rotation_eight_mask;
5379 break;
5381 case 16:
5382 inst.instruction |= rotation_sixteen_mask;
5383 break;
5385 case 24:
5386 inst.instruction |= rotation_twenty_four_mask;
5387 break;
5389 default:
5390 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
5391 break;
5394 end_of_line (str);
5398 /* ARM V6 SXTAH extracts a 16-bit value from a register, sign
5399 extends it to 32-bits, and adds the result to a value in another
5400 register. You can specify a rotation by 0, 8, 16, or 24 bits
5401 before extracting the 16-bit value.
5402 SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
5403 Condition defaults to COND_ALWAYS.
5404 Error if any register uses R15. */
5406 static void
5407 do_sxtah (str)
5408 char *str;
5410 int rd, rn, rm;
5411 expressionS expr;
5412 int rotation_clear_mask = 0xfffff3ff;
5413 int rotation_eight_mask = 0x00000400;
5414 int rotation_sixteen_mask = 0x00000800;
5415 int rotation_twenty_four_mask = 0x00000c00;
5417 skip_whitespace (str);
5418 if ((rd = reg_required_here (&str, 12)) == FAIL
5419 || skip_past_comma (&str) == FAIL
5420 || (rn = reg_required_here (&str, 16)) == FAIL
5421 || skip_past_comma (&str) == FAIL
5422 || (rm = reg_required_here (&str, 0)) == FAIL)
5424 inst.error = BAD_ARGS;
5425 return;
5428 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
5430 inst.error = BAD_PC;
5431 return;
5434 /* Zero out the rotation field. */
5435 inst.instruction &= rotation_clear_mask;
5437 /* Check for lack of optional rotation field. */
5438 if (skip_past_comma (&str) == FAIL)
5440 end_of_line (str);
5441 return;
5444 /* Move past 'ROR'. */
5445 skip_whitespace (str);
5446 if (strncasecmp (str, "ROR", 3) == 0)
5447 str+=3;
5448 else
5450 inst.error = _("missing rotation field after comma");
5451 return;
5454 /* Get the immediate constant. */
5455 skip_whitespace (str);
5456 if (is_immediate_prefix (* str))
5457 str++;
5458 else
5460 inst.error = _("immediate expression expected");
5461 return;
5464 if (my_get_expression (&expr, &str))
5466 inst.error = _("bad expression");
5467 return;
5470 if (expr.X_op != O_constant)
5472 inst.error = _("constant expression expected");
5473 return;
5476 switch (expr.X_add_number)
5478 case 0:
5479 /* Rotation field has already been zeroed. */
5480 break;
5482 case 8:
5483 inst.instruction |= rotation_eight_mask;
5484 break;
5486 case 16:
5487 inst.instruction |= rotation_sixteen_mask;
5488 break;
5490 case 24:
5491 inst.instruction |= rotation_twenty_four_mask;
5492 break;
5494 default:
5495 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
5496 break;
5499 end_of_line (str);
5504 /* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
5505 word at the specified address and the following word
5506 respectively.
5507 Unconditionally executed.
5508 Error if Rn is R15.
5511 static void
5512 do_rfe (str)
5513 char *str;
5515 int rn;
5517 skip_whitespace (str);
5519 if ((rn = reg_required_here (&str, 16)) == FAIL)
5520 return;
5522 if (rn == REG_PC)
5524 inst.error = BAD_PC;
5525 return;
5528 skip_whitespace (str);
5530 if (*str == '!')
5532 inst.instruction |= WRITE_BACK;
5533 str++;
5535 end_of_line (str);
5538 /* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
5539 register (argument parse).
5540 REV{<cond>} Rd, Rm.
5541 Condition defaults to COND_ALWAYS.
5542 Error if Rd or Rm are R15. */
5544 static void
5545 do_rev (str)
5546 char* str;
5548 int rd, rm;
5550 skip_whitespace (str);
5552 if ((rd = reg_required_here (&str, 12)) == FAIL
5553 || skip_past_comma (&str) == FAIL
5554 || (rm = reg_required_here (&str, 0)) == FAIL)
5555 inst.error = BAD_ARGS;
5557 else if (rd == REG_PC || rm == REG_PC)
5558 inst.error = BAD_PC;
5560 else
5561 end_of_line (str);
5564 /* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
5565 QADD16{<cond>} <Rd>, <Rn>, <Rm>
5566 Condition defaults to COND_ALWAYS.
5567 Error if Rd, Rn or Rm are R15. */
5569 static void
5570 do_qadd16 (str)
5571 char* str;
5573 int rd, rm, rn;
5575 skip_whitespace (str);
5577 if ((rd = reg_required_here (&str, 12)) == FAIL
5578 || skip_past_comma (&str) == FAIL
5579 || (rn = reg_required_here (&str, 16)) == FAIL
5580 || skip_past_comma (&str) == FAIL
5581 || (rm = reg_required_here (&str, 0)) == FAIL)
5582 inst.error = BAD_ARGS;
5584 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
5585 inst.error = BAD_PC;
5587 else
5588 end_of_line (str);
5591 /* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
5592 PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
5593 Condition defaults to COND_ALWAYS.
5594 Error if Rd, Rn or Rm are R15. */
5596 static void
5597 do_pkhbt (str)
5598 char* str;
5600 do_pkh_core (str, SHIFT_LSL_IMMEDIATE);
5603 /* ARM V6 PKHTB (Argument Parse). */
5605 static void
5606 do_pkhtb (str)
5607 char* str;
5609 do_pkh_core (str, SHIFT_ASR_IMMEDIATE);
5612 static void
5613 do_pkh_core (str, shift)
5614 char* str;
5615 int shift;
5617 int rd, rn, rm;
5619 skip_whitespace (str);
5620 if (((rd = reg_required_here (&str, 12)) == FAIL)
5621 || (skip_past_comma (&str) == FAIL)
5622 || ((rn = reg_required_here (&str, 16)) == FAIL)
5623 || (skip_past_comma (&str) == FAIL)
5624 || ((rm = reg_required_here (&str, 0)) == FAIL))
5626 inst.error = BAD_ARGS;
5627 return;
5630 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
5632 inst.error = BAD_PC;
5633 return;
5636 /* Check for optional shift immediate constant. */
5637 if (skip_past_comma (&str) == FAIL)
5639 if (shift == SHIFT_ASR_IMMEDIATE)
5641 /* If the shift specifier is ommited, turn the instruction
5642 into pkhbt rd, rm, rn. First, switch the instruction
5643 code, and clear the rn and rm fields. */
5644 inst.instruction &= 0xfff0f010;
5645 /* Now, re-encode the registers. */
5646 inst.instruction |= (rm << 16) | rn;
5648 return;
5651 decode_shift (&str, shift);
5654 /* ARM V6 Load Register Exclusive instruction (argument parse).
5655 LDREX{<cond>} <Rd, [<Rn>]
5656 Condition defaults to COND_ALWAYS.
5657 Error if Rd or Rn are R15.
5658 See ARMARMv6 A4.1.27: LDREX. */
5661 static void
5662 do_ldrex (str)
5663 char * str;
5665 int rd, rn;
5667 skip_whitespace (str);
5669 /* Parse Rd. */
5670 if (((rd = reg_required_here (&str, 12)) == FAIL)
5671 || (skip_past_comma (&str) == FAIL))
5673 inst.error = BAD_ARGS;
5674 return;
5676 else if (rd == REG_PC)
5678 inst.error = BAD_PC;
5679 return;
5681 skip_whitespace (str);
5683 /* Skip past '['. */
5684 if ((strlen (str) >= 1)
5685 &&strncmp (str, "[", 1) == 0)
5686 str+=1;
5687 skip_whitespace (str);
5689 /* Parse Rn. */
5690 if ((rn = reg_required_here (&str, 16)) == FAIL)
5692 inst.error = BAD_ARGS;
5693 return;
5695 else if (rn == REG_PC)
5697 inst.error = BAD_PC;
5698 return;
5700 skip_whitespace (str);
5702 /* Skip past ']'. */
5703 if ((strlen (str) >= 1)
5704 && strncmp (str, "]", 1) == 0)
5705 str+=1;
5707 end_of_line (str);
5710 /* ARM V6 change processor state instruction (argument parse)
5711 CPS, CPSIE, CSPID . */
5713 static void
5714 do_cps (str)
5715 char * str;
5717 do_cps_mode (&str);
5718 end_of_line (str);
5721 static void
5722 do_cpsi (str)
5723 char * str;
5725 do_cps_flags (&str, /*thumb_p=*/0);
5727 if (skip_past_comma (&str) == SUCCESS)
5729 skip_whitespace (str);
5730 do_cps_mode (&str);
5732 end_of_line (str);
5735 static void
5736 do_cps_mode (str)
5737 char **str;
5739 expressionS expr;
5741 skip_whitespace (*str);
5743 if (! is_immediate_prefix (**str))
5745 inst.error = _("immediate expression expected");
5746 return;
5749 (*str)++; /* Strip off the immediate signifier. */
5750 if (my_get_expression (&expr, str))
5752 inst.error = _("bad expression");
5753 return;
5756 if (expr.X_op != O_constant)
5758 inst.error = _("constant expression expected");
5759 return;
5762 /* The mode is a 5 bit field. Valid values are 0-31. */
5763 if (((unsigned) expr.X_add_number) > 31
5764 || (inst.reloc.exp.X_add_number) < 0)
5766 inst.error = _("invalid constant");
5767 return;
5770 inst.instruction |= expr.X_add_number;
5773 static void
5774 do_cps_flags (str, thumb_p)
5775 char **str;
5776 int thumb_p;
5778 struct cps_flag {
5779 char character;
5780 unsigned long arm_value;
5781 unsigned long thumb_value;
5783 static struct cps_flag flag_table[] = {
5784 {'a', 0x100, 0x4 },
5785 {'i', 0x080, 0x2 },
5786 {'f', 0x040, 0x1 }
5789 int saw_a_flag = 0;
5791 skip_whitespace (*str);
5793 /* Get the a, f and i flags. */
5794 while (**str && **str != ',')
5796 struct cps_flag *p;
5797 struct cps_flag *q = flag_table + sizeof (flag_table)/sizeof (*p);
5798 for (p = flag_table; p < q; ++p)
5799 if (strncasecmp (*str, &p->character, 1) == 0)
5801 inst.instruction |= (thumb_p ? p->thumb_value : p->arm_value);
5802 saw_a_flag = 1;
5803 break;
5805 if (p == q)
5807 inst.error = _("unrecognized flag");
5808 return;
5810 (*str)++;
5812 if (!saw_a_flag)
5813 inst.error = _("no 'a', 'i', or 'f' flags for 'cps'");
5816 /* THUMB V5 breakpoint instruction (argument parse)
5817 BKPT <immed_8>. */
5819 static void
5820 do_t_bkpt (str)
5821 char * str;
5823 expressionS expr;
5824 unsigned long number;
5826 skip_whitespace (str);
5828 /* Allow optional leading '#'. */
5829 if (is_immediate_prefix (*str))
5830 str ++;
5832 memset (& expr, '\0', sizeof (expr));
5833 if (my_get_expression (& expr, & str)
5834 || (expr.X_op != O_constant
5835 /* As a convenience we allow 'bkpt' without an operand. */
5836 && expr.X_op != O_absent))
5838 inst.error = _("bad expression");
5839 return;
5842 number = expr.X_add_number;
5844 /* Check it fits an 8 bit unsigned. */
5845 if (number != (number & 0xff))
5847 inst.error = _("immediate value out of range");
5848 return;
5851 inst.instruction |= number;
5853 end_of_line (str);
5856 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
5857 Expects inst.instruction is set for BLX(1).
5858 Note: this is cloned from do_branch, and the reloc changed to be a
5859 new one that can cope with setting one extra bit (the H bit). */
5861 static void
5862 do_branch25 (str)
5863 char * str;
5865 if (my_get_expression (& inst.reloc.exp, & str))
5866 return;
5868 #ifdef OBJ_ELF
5870 char * save_in;
5872 /* ScottB: February 5, 1998 */
5873 /* Check to see of PLT32 reloc required for the instruction. */
5875 /* arm_parse_reloc() works on input_line_pointer.
5876 We actually want to parse the operands to the branch instruction
5877 passed in 'str'. Save the input pointer and restore it later. */
5878 save_in = input_line_pointer;
5879 input_line_pointer = str;
5881 if (inst.reloc.exp.X_op == O_symbol
5882 && *str == '('
5883 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
5885 inst.reloc.type = BFD_RELOC_ARM_PLT32;
5886 inst.reloc.pc_rel = 0;
5887 /* Modify str to point to after parsed operands, otherwise
5888 end_of_line() will complain about the (PLT) left in str. */
5889 str = input_line_pointer;
5891 else
5893 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
5894 inst.reloc.pc_rel = 1;
5897 input_line_pointer = save_in;
5899 #else
5900 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
5901 inst.reloc.pc_rel = 1;
5902 #endif /* OBJ_ELF */
5904 end_of_line (str);
5907 /* ARM V5 branch-link-exchange instruction (argument parse)
5908 BLX <target_addr> ie BLX(1)
5909 BLX{<condition>} <Rm> ie BLX(2)
5910 Unfortunately, there are two different opcodes for this mnemonic.
5911 So, the insns[].value is not used, and the code here zaps values
5912 into inst.instruction.
5913 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
5915 static void
5916 do_blx (str)
5917 char * str;
5919 char * mystr = str;
5920 int rm;
5922 skip_whitespace (mystr);
5923 rm = reg_required_here (& mystr, 0);
5925 /* The above may set inst.error. Ignore his opinion. */
5926 inst.error = 0;
5928 if (rm != FAIL)
5930 /* Arg is a register.
5931 Use the condition code our caller put in inst.instruction.
5932 Pass ourselves off as a BX with a funny opcode. */
5933 inst.instruction |= 0x012fff30;
5934 do_bx (str);
5936 else
5938 /* This must be is BLX <target address>, no condition allowed. */
5939 if (inst.instruction != COND_ALWAYS)
5941 inst.error = BAD_COND;
5942 return;
5945 inst.instruction = 0xfafffffe;
5947 /* Process like a B/BL, but with a different reloc.
5948 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
5949 do_branch25 (str);
5953 /* ARM V5 Thumb BLX (argument parse)
5954 BLX <target_addr> which is BLX(1)
5955 BLX <Rm> which is BLX(2)
5956 Unfortunately, there are two different opcodes for this mnemonic.
5957 So, the tinsns[].value is not used, and the code here zaps values
5958 into inst.instruction. */
5960 static void
5961 do_t_blx (str)
5962 char * str;
5964 char * mystr = str;
5965 int rm;
5967 skip_whitespace (mystr);
5968 inst.instruction = 0x4780;
5970 /* Note that this call is to the ARM register recognizer. BLX(2)
5971 uses the ARM register space, not the Thumb one, so a call to
5972 thumb_reg() would be wrong. */
5973 rm = reg_required_here (& mystr, 3);
5974 inst.error = 0;
5976 if (rm != FAIL)
5978 /* It's BLX(2). The .instruction was zapped with rm & is final. */
5979 inst.size = 2;
5981 else
5983 /* No ARM register. This must be BLX(1). Change the .instruction. */
5984 inst.instruction = 0xf7ffeffe;
5985 inst.size = 4;
5987 if (my_get_expression (& inst.reloc.exp, & mystr))
5988 return;
5990 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BLX;
5991 inst.reloc.pc_rel = 1;
5994 end_of_line (mystr);
5997 /* ARM V5 breakpoint instruction (argument parse)
5998 BKPT <16 bit unsigned immediate>
5999 Instruction is not conditional.
6000 The bit pattern given in insns[] has the COND_ALWAYS condition,
6001 and it is an error if the caller tried to override that. */
6003 static void
6004 do_bkpt (str)
6005 char * str;
6007 expressionS expr;
6008 unsigned long number;
6010 skip_whitespace (str);
6012 /* Allow optional leading '#'. */
6013 if (is_immediate_prefix (* str))
6014 str++;
6016 memset (& expr, '\0', sizeof (expr));
6018 if (my_get_expression (& expr, & str)
6019 || (expr.X_op != O_constant
6020 /* As a convenience we allow 'bkpt' without an operand. */
6021 && expr.X_op != O_absent))
6023 inst.error = _("bad expression");
6024 return;
6027 number = expr.X_add_number;
6029 /* Check it fits a 16 bit unsigned. */
6030 if (number != (number & 0xffff))
6032 inst.error = _("immediate value out of range");
6033 return;
6036 /* Top 12 of 16 bits to bits 19:8. */
6037 inst.instruction |= (number & 0xfff0) << 4;
6039 /* Bottom 4 of 16 bits to bits 3:0. */
6040 inst.instruction |= number & 0xf;
6042 end_of_line (str);
6045 /* THUMB CPS instruction (argument parse). */
6047 static void
6048 do_t_cps (str)
6049 char *str;
6051 do_cps_flags (&str, /*thumb_p=*/1);
6052 end_of_line (str);
6055 /* THUMB CPY instruction (argument parse). */
6057 static void
6058 do_t_cpy (str)
6059 char *str;
6061 thumb_mov_compare (str, THUMB_CPY);
6064 /* THUMB SETEND instruction (argument parse). */
6066 static void
6067 do_t_setend (str)
6068 char *str;
6070 if (do_endian_specifier (str))
6071 inst.instruction |= 0x8;
6074 static unsigned long check_iwmmxt_insn PARAMS ((char *, enum iwmmxt_insn_type, int));
6076 /* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
6078 static unsigned long
6079 check_iwmmxt_insn (str, insn_type, immediate_size)
6080 char * str;
6081 enum iwmmxt_insn_type insn_type;
6082 int immediate_size;
6084 int reg = 0;
6085 const char * inst_error;
6086 expressionS expr;
6087 unsigned long number;
6089 inst_error = inst.error;
6090 if (!inst.error)
6091 inst.error = BAD_ARGS;
6092 skip_whitespace (str);
6094 switch (insn_type)
6096 case check_rd:
6097 if ((reg = reg_required_here (&str, 12)) == FAIL)
6098 return FAIL;
6099 break;
6101 case check_wr:
6102 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR)) == FAIL)
6103 return FAIL;
6104 break;
6106 case check_wrwr:
6107 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6108 || skip_past_comma (&str) == FAIL
6109 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
6110 return FAIL;
6111 break;
6113 case check_wrwrwr:
6114 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6115 || skip_past_comma (&str) == FAIL
6116 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6117 || skip_past_comma (&str) == FAIL
6118 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
6119 return FAIL;
6120 break;
6122 case check_wrwrwcg:
6123 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6124 || skip_past_comma (&str) == FAIL
6125 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6126 || skip_past_comma (&str) == FAIL
6127 || wreg_required_here (&str, 0, IWMMXT_REG_WCG) == FAIL))
6128 return FAIL;
6129 break;
6131 case check_tbcst:
6132 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6133 || skip_past_comma (&str) == FAIL
6134 || reg_required_here (&str, 12) == FAIL))
6135 return FAIL;
6136 break;
6138 case check_tmovmsk:
6139 if ((reg_required_here (&str, 12) == FAIL
6140 || skip_past_comma (&str) == FAIL
6141 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
6142 return FAIL;
6143 break;
6145 case check_tmia:
6146 if ((wreg_required_here (&str, 5, IWMMXT_REG_WR) == FAIL
6147 || skip_past_comma (&str) == FAIL
6148 || reg_required_here (&str, 0) == FAIL
6149 || skip_past_comma (&str) == FAIL
6150 || reg_required_here (&str, 12) == FAIL))
6151 return FAIL;
6152 break;
6154 case check_tmcrr:
6155 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
6156 || skip_past_comma (&str) == FAIL
6157 || reg_required_here (&str, 12) == FAIL
6158 || skip_past_comma (&str) == FAIL
6159 || reg_required_here (&str, 16) == FAIL))
6160 return FAIL;
6161 break;
6163 case check_tmrrc:
6164 if ((reg_required_here (&str, 12) == FAIL
6165 || skip_past_comma (&str) == FAIL
6166 || reg_required_here (&str, 16) == FAIL
6167 || skip_past_comma (&str) == FAIL
6168 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
6169 return FAIL;
6170 break;
6172 case check_tmcr:
6173 if ((wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL
6174 || skip_past_comma (&str) == FAIL
6175 || reg_required_here (&str, 12) == FAIL))
6176 return FAIL;
6177 break;
6179 case check_tmrc:
6180 if ((reg_required_here (&str, 12) == FAIL
6181 || skip_past_comma (&str) == FAIL
6182 || wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL))
6183 return FAIL;
6184 break;
6186 case check_tinsr:
6187 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6188 || skip_past_comma (&str) == FAIL
6189 || reg_required_here (&str, 12) == FAIL
6190 || skip_past_comma (&str) == FAIL))
6191 return FAIL;
6192 break;
6194 case check_textrc:
6195 if ((reg_required_here (&str, 12) == FAIL
6196 || skip_past_comma (&str) == FAIL))
6197 return FAIL;
6198 break;
6200 case check_waligni:
6201 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6202 || skip_past_comma (&str) == FAIL
6203 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6204 || skip_past_comma (&str) == FAIL
6205 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
6206 || skip_past_comma (&str) == FAIL))
6207 return FAIL;
6208 break;
6210 case check_textrm:
6211 if ((reg_required_here (&str, 12) == FAIL
6212 || skip_past_comma (&str) == FAIL
6213 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6214 || skip_past_comma (&str) == FAIL))
6215 return FAIL;
6216 break;
6218 case check_wshufh:
6219 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6220 || skip_past_comma (&str) == FAIL
6221 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6222 || skip_past_comma (&str) == FAIL))
6223 return FAIL;
6224 break;
6227 if (immediate_size == 0)
6229 end_of_line (str);
6230 inst.error = inst_error;
6231 return reg;
6233 else
6235 skip_whitespace (str);
6237 /* Allow optional leading '#'. */
6238 if (is_immediate_prefix (* str))
6239 str++;
6241 memset (& expr, '\0', sizeof (expr));
6243 if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
6245 inst.error = _("bad or missing expression");
6246 return FAIL;
6249 number = expr.X_add_number;
6251 if (number != (number & immediate_size))
6253 inst.error = _("immediate value out of range");
6254 return FAIL;
6256 end_of_line (str);
6257 inst.error = inst_error;
6258 return number;
6262 static void
6263 do_iwmmxt_byte_addr (str)
6264 char * str;
6266 int op = (inst.instruction & 0x300) >> 8;
6267 int reg;
6269 inst.instruction &= ~0x300;
6270 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
6272 skip_whitespace (str);
6274 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
6275 || skip_past_comma (& str) == FAIL
6276 || cp_byte_address_required_here (&str) == FAIL)
6278 if (! inst.error)
6279 inst.error = BAD_ARGS;
6281 else
6282 end_of_line (str);
6284 if (wc_register (reg))
6286 as_bad (_("non-word size not supported with control register"));
6287 inst.instruction |= 0xf0000100;
6288 inst.instruction &= ~0x00400000;
6292 static void
6293 do_iwmmxt_tandc (str)
6294 char * str;
6296 int reg;
6298 reg = check_iwmmxt_insn (str, check_rd, 0);
6300 if (reg != REG_PC && !inst.error)
6301 inst.error = _("only r15 allowed here");
6304 static void
6305 do_iwmmxt_tbcst (str)
6306 char * str;
6308 check_iwmmxt_insn (str, check_tbcst, 0);
6311 static void
6312 do_iwmmxt_textrc (str)
6313 char * str;
6315 unsigned long number;
6317 if ((number = check_iwmmxt_insn (str, check_textrc, 7)) == (unsigned long) FAIL)
6318 return;
6320 inst.instruction |= number & 0x7;
6323 static void
6324 do_iwmmxt_textrm (str)
6325 char * str;
6327 unsigned long number;
6329 if ((number = check_iwmmxt_insn (str, check_textrm, 7)) == (unsigned long) FAIL)
6330 return;
6332 inst.instruction |= number & 0x7;
6335 static void
6336 do_iwmmxt_tinsr (str)
6337 char * str;
6339 unsigned long number;
6341 if ((number = check_iwmmxt_insn (str, check_tinsr, 7)) == (unsigned long) FAIL)
6342 return;
6344 inst.instruction |= number & 0x7;
6347 static void
6348 do_iwmmxt_tmcr (str)
6349 char * str;
6351 check_iwmmxt_insn (str, check_tmcr, 0);
6354 static void
6355 do_iwmmxt_tmcrr (str)
6356 char * str;
6358 check_iwmmxt_insn (str, check_tmcrr, 0);
6361 static void
6362 do_iwmmxt_tmia (str)
6363 char * str;
6365 check_iwmmxt_insn (str, check_tmia, 0);
6368 static void
6369 do_iwmmxt_tmovmsk (str)
6370 char * str;
6372 check_iwmmxt_insn (str, check_tmovmsk, 0);
6375 static void
6376 do_iwmmxt_tmrc (str)
6377 char * str;
6379 check_iwmmxt_insn (str, check_tmrc, 0);
6382 static void
6383 do_iwmmxt_tmrrc (str)
6384 char * str;
6386 check_iwmmxt_insn (str, check_tmrrc, 0);
6389 static void
6390 do_iwmmxt_torc (str)
6391 char * str;
6393 check_iwmmxt_insn (str, check_rd, 0);
6396 static void
6397 do_iwmmxt_waligni (str)
6398 char * str;
6400 unsigned long number;
6402 if ((number = check_iwmmxt_insn (str, check_waligni, 7)) == (unsigned long) FAIL)
6403 return;
6405 inst.instruction |= ((number & 0x7) << 20);
6408 static void
6409 do_iwmmxt_wmov (str)
6410 char * str;
6412 if (check_iwmmxt_insn (str, check_wrwr, 0) == (unsigned long) FAIL)
6413 return;
6415 inst.instruction |= ((inst.instruction >> 16) & 0xf);
6418 static void
6419 do_iwmmxt_word_addr (str)
6420 char * str;
6422 int op = (inst.instruction & 0x300) >> 8;
6423 int reg;
6425 inst.instruction &= ~0x300;
6426 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
6428 skip_whitespace (str);
6430 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
6431 || skip_past_comma (& str) == FAIL
6432 || cp_address_required_here (& str, CP_WB_OK) == FAIL)
6434 if (! inst.error)
6435 inst.error = BAD_ARGS;
6437 else
6438 end_of_line (str);
6440 if (wc_register (reg))
6442 if ((inst.instruction & COND_MASK) != COND_ALWAYS)
6443 as_bad (_("conditional execution not supported with control register"));
6444 if (op != 2)
6445 as_bad (_("non-word size not supported with control register"));
6446 inst.instruction |= 0xf0000100;
6447 inst.instruction &= ~0x00400000;
6451 static void
6452 do_iwmmxt_wrwr (str)
6453 char * str;
6455 check_iwmmxt_insn (str, check_wrwr, 0);
6458 static void
6459 do_iwmmxt_wrwrwcg (str)
6460 char * str;
6462 check_iwmmxt_insn (str, check_wrwrwcg, 0);
6465 static void
6466 do_iwmmxt_wrwrwr (str)
6467 char * str;
6469 check_iwmmxt_insn (str, check_wrwrwr, 0);
6472 static void
6473 do_iwmmxt_wshufh (str)
6474 char * str;
6476 unsigned long number;
6478 if ((number = check_iwmmxt_insn (str, check_wshufh, 0xff)) == (unsigned long) FAIL)
6479 return;
6481 inst.instruction |= ((number & 0xf0) << 16) | (number & 0xf);
6484 static void
6485 do_iwmmxt_wzero (str)
6486 char * str;
6488 if (check_iwmmxt_insn (str, check_wr, 0) == (unsigned long) FAIL)
6489 return;
6491 inst.instruction |= ((inst.instruction & 0xf) << 12) | ((inst.instruction & 0xf) << 16);
6494 /* Xscale multiply-accumulate (argument parse)
6495 MIAcc acc0,Rm,Rs
6496 MIAPHcc acc0,Rm,Rs
6497 MIAxycc acc0,Rm,Rs. */
6499 static void
6500 do_xsc_mia (str)
6501 char * str;
6503 int rs;
6504 int rm;
6506 if (accum0_required_here (& str) == FAIL)
6507 inst.error = ERR_NO_ACCUM;
6509 else if (skip_past_comma (& str) == FAIL
6510 || (rm = reg_required_here (& str, 0)) == FAIL)
6511 inst.error = BAD_ARGS;
6513 else if (skip_past_comma (& str) == FAIL
6514 || (rs = reg_required_here (& str, 12)) == FAIL)
6515 inst.error = BAD_ARGS;
6517 /* inst.instruction has now been zapped with both rm and rs. */
6518 else if (rm == REG_PC || rs == REG_PC)
6519 inst.error = BAD_PC; /* Undefined result if rm or rs is R15. */
6521 else
6522 end_of_line (str);
6525 /* Xscale move-accumulator-register (argument parse)
6527 MARcc acc0,RdLo,RdHi. */
6529 static void
6530 do_xsc_mar (str)
6531 char * str;
6533 int rdlo, rdhi;
6535 if (accum0_required_here (& str) == FAIL)
6536 inst.error = ERR_NO_ACCUM;
6538 else if (skip_past_comma (& str) == FAIL
6539 || (rdlo = reg_required_here (& str, 12)) == FAIL)
6540 inst.error = BAD_ARGS;
6542 else if (skip_past_comma (& str) == FAIL
6543 || (rdhi = reg_required_here (& str, 16)) == FAIL)
6544 inst.error = BAD_ARGS;
6546 /* inst.instruction has now been zapped with both rdlo and rdhi. */
6547 else if (rdlo == REG_PC || rdhi == REG_PC)
6548 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
6550 else
6551 end_of_line (str);
6554 /* Xscale move-register-accumulator (argument parse)
6556 MRAcc RdLo,RdHi,acc0. */
6558 static void
6559 do_xsc_mra (str)
6560 char * str;
6562 int rdlo;
6563 int rdhi;
6565 skip_whitespace (str);
6567 if ((rdlo = reg_required_here (& str, 12)) == FAIL)
6568 inst.error = BAD_ARGS;
6570 else if (skip_past_comma (& str) == FAIL
6571 || (rdhi = reg_required_here (& str, 16)) == FAIL)
6572 inst.error = BAD_ARGS;
6574 else if (skip_past_comma (& str) == FAIL
6575 || accum0_required_here (& str) == FAIL)
6576 inst.error = ERR_NO_ACCUM;
6578 /* inst.instruction has now been zapped with both rdlo and rdhi. */
6579 else if (rdlo == rdhi)
6580 inst.error = BAD_ARGS; /* Undefined result if 2 writes to same reg. */
6582 else if (rdlo == REG_PC || rdhi == REG_PC)
6583 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
6584 else
6585 end_of_line (str);
6588 /* ARMv5TE: Preload-Cache
6590 PLD <addr_mode>
6592 Syntactically, like LDR with B=1, W=0, L=1. */
6594 static void
6595 do_pld (str)
6596 char * str;
6598 int rd;
6600 skip_whitespace (str);
6602 if (* str != '[')
6604 inst.error = _("'[' expected after PLD mnemonic");
6605 return;
6608 ++str;
6609 skip_whitespace (str);
6611 if ((rd = reg_required_here (& str, 16)) == FAIL)
6612 return;
6614 skip_whitespace (str);
6616 if (*str == ']')
6618 /* [Rn], ... ? */
6619 ++str;
6620 skip_whitespace (str);
6622 /* Post-indexed addressing is not allowed with PLD. */
6623 if (skip_past_comma (&str) == SUCCESS)
6625 inst.error
6626 = _("post-indexed expression used in preload instruction");
6627 return;
6629 else if (*str == '!') /* [Rn]! */
6631 inst.error = _("writeback used in preload instruction");
6632 ++str;
6634 else /* [Rn] */
6635 inst.instruction |= INDEX_UP | PRE_INDEX;
6637 else /* [Rn, ...] */
6639 if (skip_past_comma (& str) == FAIL)
6641 inst.error = _("pre-indexed expression expected");
6642 return;
6645 if (ldst_extend (&str) == FAIL)
6646 return;
6648 skip_whitespace (str);
6650 if (* str != ']')
6652 inst.error = _("missing ]");
6653 return;
6656 ++ str;
6657 skip_whitespace (str);
6659 if (* str == '!') /* [Rn]! */
6661 inst.error = _("writeback used in preload instruction");
6662 ++ str;
6665 inst.instruction |= PRE_INDEX;
6668 end_of_line (str);
6671 /* ARMv5TE load-consecutive (argument parse)
6672 Mode is like LDRH.
6674 LDRccD R, mode
6675 STRccD R, mode. */
6677 static void
6678 do_ldrd (str)
6679 char * str;
6681 int rd;
6682 int rn;
6684 skip_whitespace (str);
6686 if ((rd = reg_required_here (& str, 12)) == FAIL)
6688 inst.error = BAD_ARGS;
6689 return;
6692 if (skip_past_comma (& str) == FAIL
6693 || (rn = ld_mode_required_here (& str)) == FAIL)
6695 if (!inst.error)
6696 inst.error = BAD_ARGS;
6697 return;
6700 /* inst.instruction has now been zapped with Rd and the addressing mode. */
6701 if (rd & 1) /* Unpredictable result if Rd is odd. */
6703 inst.error = _("destination register must be even");
6704 return;
6707 if (rd == REG_LR)
6709 inst.error = _("r14 not allowed here");
6710 return;
6713 if (((rd == rn) || (rd + 1 == rn))
6714 && ((inst.instruction & WRITE_BACK)
6715 || (!(inst.instruction & PRE_INDEX))))
6716 as_warn (_("pre/post-indexing used when modified address register is destination"));
6718 /* For an index-register load, the index register must not overlap the
6719 destination (even if not write-back). */
6720 if ((inst.instruction & V4_STR_BIT) == 0
6721 && (inst.instruction & HWOFFSET_IMM) == 0)
6723 int rm = inst.instruction & 0x0000000f;
6725 if (rm == rd || (rm == rd + 1))
6726 as_warn (_("ldrd destination registers must not overlap index register"));
6729 end_of_line (str);
6732 /* Returns the index into fp_values of a floating point number,
6733 or -1 if not in the table. */
6735 static int
6736 my_get_float_expression (str)
6737 char ** str;
6739 LITTLENUM_TYPE words[MAX_LITTLENUMS];
6740 char * save_in;
6741 expressionS exp;
6742 int i;
6743 int j;
6745 memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE));
6747 /* Look for a raw floating point number. */
6748 if ((save_in = atof_ieee (*str, 'x', words)) != NULL
6749 && is_end_of_line[(unsigned char) *save_in])
6751 for (i = 0; i < NUM_FLOAT_VALS; i++)
6753 for (j = 0; j < MAX_LITTLENUMS; j++)
6755 if (words[j] != fp_values[i][j])
6756 break;
6759 if (j == MAX_LITTLENUMS)
6761 *str = save_in;
6762 return i;
6767 /* Try and parse a more complex expression, this will probably fail
6768 unless the code uses a floating point prefix (eg "0f"). */
6769 save_in = input_line_pointer;
6770 input_line_pointer = *str;
6771 if (expression (&exp) == absolute_section
6772 && exp.X_op == O_big
6773 && exp.X_add_number < 0)
6775 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
6776 Ditto for 15. */
6777 if (gen_to_words (words, 5, (long) 15) == 0)
6779 for (i = 0; i < NUM_FLOAT_VALS; i++)
6781 for (j = 0; j < MAX_LITTLENUMS; j++)
6783 if (words[j] != fp_values[i][j])
6784 break;
6787 if (j == MAX_LITTLENUMS)
6789 *str = input_line_pointer;
6790 input_line_pointer = save_in;
6791 return i;
6797 *str = input_line_pointer;
6798 input_line_pointer = save_in;
6799 return -1;
6802 /* Return TRUE if anything in the expression is a bignum. */
6804 static int
6805 walk_no_bignums (sp)
6806 symbolS * sp;
6808 if (symbol_get_value_expression (sp)->X_op == O_big)
6809 return 1;
6811 if (symbol_get_value_expression (sp)->X_add_symbol)
6813 return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
6814 || (symbol_get_value_expression (sp)->X_op_symbol
6815 && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
6818 return 0;
6821 static int in_my_get_expression = 0;
6823 static int
6824 my_get_expression (ep, str)
6825 expressionS * ep;
6826 char ** str;
6828 char * save_in;
6829 segT seg;
6831 save_in = input_line_pointer;
6832 input_line_pointer = *str;
6833 in_my_get_expression = 1;
6834 seg = expression (ep);
6835 in_my_get_expression = 0;
6837 if (ep->X_op == O_illegal)
6839 /* We found a bad expression in md_operand(). */
6840 *str = input_line_pointer;
6841 input_line_pointer = save_in;
6842 return 1;
6845 #ifdef OBJ_AOUT
6846 if (seg != absolute_section
6847 && seg != text_section
6848 && seg != data_section
6849 && seg != bss_section
6850 && seg != undefined_section)
6852 inst.error = _("bad_segment");
6853 *str = input_line_pointer;
6854 input_line_pointer = save_in;
6855 return 1;
6857 #endif
6859 /* Get rid of any bignums now, so that we don't generate an error for which
6860 we can't establish a line number later on. Big numbers are never valid
6861 in instructions, which is where this routine is always called. */
6862 if (ep->X_op == O_big
6863 || (ep->X_add_symbol
6864 && (walk_no_bignums (ep->X_add_symbol)
6865 || (ep->X_op_symbol
6866 && walk_no_bignums (ep->X_op_symbol)))))
6868 inst.error = _("invalid constant");
6869 *str = input_line_pointer;
6870 input_line_pointer = save_in;
6871 return 1;
6874 *str = input_line_pointer;
6875 input_line_pointer = save_in;
6876 return 0;
6879 /* We handle all bad expressions here, so that we can report the faulty
6880 instruction in the error message. */
6881 void
6882 md_operand (expr)
6883 expressionS *expr;
6885 if (in_my_get_expression)
6887 expr->X_op = O_illegal;
6888 if (inst.error == NULL)
6889 inst.error = _("bad expression");
6893 /* KIND indicates what kind of shifts are accepted. */
6895 static int
6896 decode_shift (str, kind)
6897 char ** str;
6898 int kind;
6900 const struct asm_shift_name * shift;
6901 char * p;
6902 char c;
6904 skip_whitespace (* str);
6906 for (p = * str; ISALPHA (* p); p ++)
6909 if (p == * str)
6911 inst.error = _("shift expression expected");
6912 return FAIL;
6915 c = * p;
6916 * p = '\0';
6917 shift = (const struct asm_shift_name *) hash_find (arm_shift_hsh, * str);
6918 * p = c;
6920 if (shift == NULL)
6922 inst.error = _("shift expression expected");
6923 return FAIL;
6926 assert (shift->properties->index == shift_properties[shift->properties->index].index);
6928 if (kind == SHIFT_LSL_OR_ASR_IMMEDIATE
6929 && shift->properties->index != SHIFT_LSL
6930 && shift->properties->index != SHIFT_ASR)
6932 inst.error = _("'LSL' or 'ASR' required");
6933 return FAIL;
6935 else if (kind == SHIFT_LSL_IMMEDIATE
6936 && shift->properties->index != SHIFT_LSL)
6938 inst.error = _("'LSL' required");
6939 return FAIL;
6941 else if (kind == SHIFT_ASR_IMMEDIATE
6942 && shift->properties->index != SHIFT_ASR)
6944 inst.error = _("'ASR' required");
6945 return FAIL;
6948 if (shift->properties->index == SHIFT_RRX)
6950 * str = p;
6951 inst.instruction |= shift->properties->bit_field;
6952 return SUCCESS;
6955 skip_whitespace (p);
6957 if (kind == NO_SHIFT_RESTRICT && reg_required_here (& p, 8) != FAIL)
6959 inst.instruction |= shift->properties->bit_field | SHIFT_BY_REG;
6960 * str = p;
6961 return SUCCESS;
6963 else if (! is_immediate_prefix (* p))
6965 inst.error = (NO_SHIFT_RESTRICT
6966 ? _("shift requires register or #expression")
6967 : _("shift requires #expression"));
6968 * str = p;
6969 return FAIL;
6972 inst.error = NULL;
6973 p ++;
6975 if (my_get_expression (& inst.reloc.exp, & p))
6976 return FAIL;
6978 /* Validate some simple #expressions. */
6979 if (inst.reloc.exp.X_op == O_constant)
6981 unsigned num = inst.reloc.exp.X_add_number;
6983 /* Reject operations greater than 32. */
6984 if (num > 32
6985 /* Reject a shift of 0 unless the mode allows it. */
6986 || (num == 0 && shift->properties->allows_0 == 0)
6987 /* Reject a shift of 32 unless the mode allows it. */
6988 || (num == 32 && shift->properties->allows_32 == 0)
6991 /* As a special case we allow a shift of zero for
6992 modes that do not support it to be recoded as an
6993 logical shift left of zero (ie nothing). We warn
6994 about this though. */
6995 if (num == 0)
6997 as_warn (_("shift of 0 ignored."));
6998 shift = & shift_names[0];
6999 assert (shift->properties->index == SHIFT_LSL);
7001 else
7003 inst.error = _("invalid immediate shift");
7004 return FAIL;
7008 /* Shifts of 32 are encoded as 0, for those shifts that
7009 support it. */
7010 if (num == 32)
7011 num = 0;
7013 inst.instruction |= (num << 7) | shift->properties->bit_field;
7015 else
7017 inst.reloc.type = BFD_RELOC_ARM_SHIFT_IMM;
7018 inst.reloc.pc_rel = 0;
7019 inst.instruction |= shift->properties->bit_field;
7022 * str = p;
7023 return SUCCESS;
7026 /* Do those data_ops which can take a negative immediate constant
7027 by altering the instruction. A bit of a hack really.
7028 MOV <-> MVN
7029 AND <-> BIC
7030 ADC <-> SBC
7031 by inverting the second operand, and
7032 ADD <-> SUB
7033 CMP <-> CMN
7034 by negating the second operand. */
7036 static int
7037 negate_data_op (instruction, value)
7038 unsigned long * instruction;
7039 unsigned long value;
7041 int op, new_inst;
7042 unsigned long negated, inverted;
7044 negated = validate_immediate (-value);
7045 inverted = validate_immediate (~value);
7047 op = (*instruction >> DATA_OP_SHIFT) & 0xf;
7048 switch (op)
7050 /* First negates. */
7051 case OPCODE_SUB: /* ADD <-> SUB */
7052 new_inst = OPCODE_ADD;
7053 value = negated;
7054 break;
7056 case OPCODE_ADD:
7057 new_inst = OPCODE_SUB;
7058 value = negated;
7059 break;
7061 case OPCODE_CMP: /* CMP <-> CMN */
7062 new_inst = OPCODE_CMN;
7063 value = negated;
7064 break;
7066 case OPCODE_CMN:
7067 new_inst = OPCODE_CMP;
7068 value = negated;
7069 break;
7071 /* Now Inverted ops. */
7072 case OPCODE_MOV: /* MOV <-> MVN */
7073 new_inst = OPCODE_MVN;
7074 value = inverted;
7075 break;
7077 case OPCODE_MVN:
7078 new_inst = OPCODE_MOV;
7079 value = inverted;
7080 break;
7082 case OPCODE_AND: /* AND <-> BIC */
7083 new_inst = OPCODE_BIC;
7084 value = inverted;
7085 break;
7087 case OPCODE_BIC:
7088 new_inst = OPCODE_AND;
7089 value = inverted;
7090 break;
7092 case OPCODE_ADC: /* ADC <-> SBC */
7093 new_inst = OPCODE_SBC;
7094 value = inverted;
7095 break;
7097 case OPCODE_SBC:
7098 new_inst = OPCODE_ADC;
7099 value = inverted;
7100 break;
7102 /* We cannot do anything. */
7103 default:
7104 return FAIL;
7107 if (value == (unsigned) FAIL)
7108 return FAIL;
7110 *instruction &= OPCODE_MASK;
7111 *instruction |= new_inst << DATA_OP_SHIFT;
7112 return value;
7115 static int
7116 data_op2 (str)
7117 char ** str;
7119 int value;
7120 expressionS expr;
7122 skip_whitespace (* str);
7124 if (reg_required_here (str, 0) != FAIL)
7126 if (skip_past_comma (str) == SUCCESS)
7127 /* Shift operation on register. */
7128 return decode_shift (str, NO_SHIFT_RESTRICT);
7130 return SUCCESS;
7132 else
7134 /* Immediate expression. */
7135 if (is_immediate_prefix (**str))
7137 (*str)++;
7138 inst.error = NULL;
7140 if (my_get_expression (&inst.reloc.exp, str))
7141 return FAIL;
7143 if (inst.reloc.exp.X_add_symbol)
7145 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
7146 inst.reloc.pc_rel = 0;
7148 else
7150 if (skip_past_comma (str) == SUCCESS)
7152 /* #x, y -- ie explicit rotation by Y. */
7153 if (my_get_expression (&expr, str))
7154 return FAIL;
7156 if (expr.X_op != O_constant)
7158 inst.error = _("constant expression expected");
7159 return FAIL;
7162 /* Rotate must be a multiple of 2. */
7163 if (((unsigned) expr.X_add_number) > 30
7164 || (expr.X_add_number & 1) != 0
7165 || ((unsigned) inst.reloc.exp.X_add_number) > 255)
7167 inst.error = _("invalid constant");
7168 return FAIL;
7170 inst.instruction |= INST_IMMEDIATE;
7171 inst.instruction |= inst.reloc.exp.X_add_number;
7172 inst.instruction |= expr.X_add_number << 7;
7173 return SUCCESS;
7176 /* Implicit rotation, select a suitable one. */
7177 value = validate_immediate (inst.reloc.exp.X_add_number);
7179 if (value == FAIL)
7181 /* Can't be done. Perhaps the code reads something like
7182 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
7183 if ((value = negate_data_op (&inst.instruction,
7184 inst.reloc.exp.X_add_number))
7185 == FAIL)
7187 inst.error = _("invalid constant");
7188 return FAIL;
7192 inst.instruction |= value;
7195 inst.instruction |= INST_IMMEDIATE;
7196 return SUCCESS;
7199 (*str)++;
7200 inst.error = _("register or shift expression expected");
7201 return FAIL;
7205 static int
7206 fp_op2 (str)
7207 char ** str;
7209 skip_whitespace (* str);
7211 if (fp_reg_required_here (str, 0) != FAIL)
7212 return SUCCESS;
7213 else
7215 /* Immediate expression. */
7216 if (*((*str)++) == '#')
7218 int i;
7220 inst.error = NULL;
7222 skip_whitespace (* str);
7224 /* First try and match exact strings, this is to guarantee
7225 that some formats will work even for cross assembly. */
7227 for (i = 0; fp_const[i]; i++)
7229 if (strncmp (*str, fp_const[i], strlen (fp_const[i])) == 0)
7231 char *start = *str;
7233 *str += strlen (fp_const[i]);
7234 if (is_end_of_line[(unsigned char) **str])
7236 inst.instruction |= i + 8;
7237 return SUCCESS;
7239 *str = start;
7243 /* Just because we didn't get a match doesn't mean that the
7244 constant isn't valid, just that it is in a format that we
7245 don't automatically recognize. Try parsing it with
7246 the standard expression routines. */
7247 if ((i = my_get_float_expression (str)) >= 0)
7249 inst.instruction |= i + 8;
7250 return SUCCESS;
7253 inst.error = _("invalid floating point immediate expression");
7254 return FAIL;
7256 inst.error =
7257 _("floating point register or immediate expression expected");
7258 return FAIL;
7262 static void
7263 do_arit (str)
7264 char * str;
7266 skip_whitespace (str);
7268 if (reg_required_here (&str, 12) == FAIL
7269 || skip_past_comma (&str) == FAIL
7270 || reg_required_here (&str, 16) == FAIL
7271 || skip_past_comma (&str) == FAIL
7272 || data_op2 (&str) == FAIL)
7274 if (!inst.error)
7275 inst.error = BAD_ARGS;
7276 return;
7279 end_of_line (str);
7282 static void
7283 do_adr (str)
7284 char * str;
7286 /* This is a pseudo-op of the form "adr rd, label" to be converted
7287 into a relative address of the form "add rd, pc, #label-.-8". */
7288 skip_whitespace (str);
7290 if (reg_required_here (&str, 12) == FAIL
7291 || skip_past_comma (&str) == FAIL
7292 || my_get_expression (&inst.reloc.exp, &str))
7294 if (!inst.error)
7295 inst.error = BAD_ARGS;
7296 return;
7299 /* Frag hacking will turn this into a sub instruction if the offset turns
7300 out to be negative. */
7301 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
7302 #ifndef TE_WINCE
7303 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust. */
7304 #endif
7305 inst.reloc.pc_rel = 1;
7307 end_of_line (str);
7310 static void
7311 do_adrl (str)
7312 char * str;
7314 /* This is a pseudo-op of the form "adrl rd, label" to be converted
7315 into a relative address of the form:
7316 add rd, pc, #low(label-.-8)"
7317 add rd, rd, #high(label-.-8)" */
7319 skip_whitespace (str);
7321 if (reg_required_here (&str, 12) == FAIL
7322 || skip_past_comma (&str) == FAIL
7323 || my_get_expression (&inst.reloc.exp, &str))
7325 if (!inst.error)
7326 inst.error = BAD_ARGS;
7328 return;
7331 end_of_line (str);
7332 /* Frag hacking will turn this into a sub instruction if the offset turns
7333 out to be negative. */
7334 inst.reloc.type = BFD_RELOC_ARM_ADRL_IMMEDIATE;
7335 #ifndef TE_WINCE
7336 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust */
7337 #endif
7338 inst.reloc.pc_rel = 1;
7339 inst.size = INSN_SIZE * 2;
7342 static void
7343 do_cmp (str)
7344 char * str;
7346 skip_whitespace (str);
7348 if (reg_required_here (&str, 16) == FAIL)
7350 if (!inst.error)
7351 inst.error = BAD_ARGS;
7352 return;
7355 if (skip_past_comma (&str) == FAIL
7356 || data_op2 (&str) == FAIL)
7358 if (!inst.error)
7359 inst.error = BAD_ARGS;
7360 return;
7363 end_of_line (str);
7366 static void
7367 do_mov (str)
7368 char * str;
7370 skip_whitespace (str);
7372 if (reg_required_here (&str, 12) == FAIL)
7374 if (!inst.error)
7375 inst.error = BAD_ARGS;
7376 return;
7379 if (skip_past_comma (&str) == FAIL
7380 || data_op2 (&str) == FAIL)
7382 if (!inst.error)
7383 inst.error = BAD_ARGS;
7384 return;
7387 end_of_line (str);
7390 static int
7391 ldst_extend (str)
7392 char ** str;
7394 int add = INDEX_UP;
7396 switch (**str)
7398 case '#':
7399 case '$':
7400 (*str)++;
7401 if (my_get_expression (& inst.reloc.exp, str))
7402 return FAIL;
7404 if (inst.reloc.exp.X_op == O_constant)
7406 int value = inst.reloc.exp.X_add_number;
7408 if (value < -4095 || value > 4095)
7410 inst.error = _("address offset too large");
7411 return FAIL;
7414 if (value < 0)
7416 value = -value;
7417 add = 0;
7420 inst.instruction |= add | value;
7422 else
7424 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
7425 inst.reloc.pc_rel = 0;
7427 return SUCCESS;
7429 case '-':
7430 add = 0;
7431 /* Fall through. */
7433 case '+':
7434 (*str)++;
7435 /* Fall through. */
7437 default:
7438 if (reg_required_here (str, 0) == FAIL)
7439 return FAIL;
7441 inst.instruction |= add | OFFSET_REG;
7442 if (skip_past_comma (str) == SUCCESS)
7443 return decode_shift (str, SHIFT_IMMEDIATE);
7445 return SUCCESS;
7449 static void
7450 do_ldst (str)
7451 char * str;
7453 int pre_inc = 0;
7454 int conflict_reg;
7455 int value;
7457 skip_whitespace (str);
7459 if ((conflict_reg = reg_required_here (&str, 12)) == FAIL)
7461 if (!inst.error)
7462 inst.error = BAD_ARGS;
7463 return;
7466 if (skip_past_comma (&str) == FAIL)
7468 inst.error = _("address expected");
7469 return;
7472 if (*str == '[')
7474 int reg;
7476 str++;
7478 skip_whitespace (str);
7480 if ((reg = reg_required_here (&str, 16)) == FAIL)
7481 return;
7483 /* Conflicts can occur on stores as well as loads. */
7484 conflict_reg = (conflict_reg == reg);
7486 skip_whitespace (str);
7488 if (*str == ']')
7490 str ++;
7492 if (skip_past_comma (&str) == SUCCESS)
7494 /* [Rn],... (post inc) */
7495 if (ldst_extend (&str) == FAIL)
7496 return;
7497 if (conflict_reg)
7498 as_warn (_("%s register same as write-back base"),
7499 ((inst.instruction & LOAD_BIT)
7500 ? _("destination") : _("source")));
7502 else
7504 /* [Rn] */
7505 skip_whitespace (str);
7507 if (*str == '!')
7509 if (conflict_reg)
7510 as_warn (_("%s register same as write-back base"),
7511 ((inst.instruction & LOAD_BIT)
7512 ? _("destination") : _("source")));
7513 str++;
7514 inst.instruction |= WRITE_BACK;
7517 inst.instruction |= INDEX_UP;
7518 pre_inc = 1;
7521 else
7523 /* [Rn,...] */
7524 if (skip_past_comma (&str) == FAIL)
7526 inst.error = _("pre-indexed expression expected");
7527 return;
7530 pre_inc = 1;
7531 if (ldst_extend (&str) == FAIL)
7532 return;
7534 skip_whitespace (str);
7536 if (*str++ != ']')
7538 inst.error = _("missing ]");
7539 return;
7542 skip_whitespace (str);
7544 if (*str == '!')
7546 if (conflict_reg)
7547 as_warn (_("%s register same as write-back base"),
7548 ((inst.instruction & LOAD_BIT)
7549 ? _("destination") : _("source")));
7550 str++;
7551 inst.instruction |= WRITE_BACK;
7555 else if (*str == '=')
7557 if ((inst.instruction & LOAD_BIT) == 0)
7559 inst.error = _("invalid pseudo operation");
7560 return;
7563 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
7564 str++;
7566 skip_whitespace (str);
7568 if (my_get_expression (&inst.reloc.exp, &str))
7569 return;
7571 if (inst.reloc.exp.X_op != O_constant
7572 && inst.reloc.exp.X_op != O_symbol)
7574 inst.error = _("constant expression expected");
7575 return;
7578 if (inst.reloc.exp.X_op == O_constant)
7580 value = validate_immediate (inst.reloc.exp.X_add_number);
7582 if (value != FAIL)
7584 /* This can be done with a mov instruction. */
7585 inst.instruction &= LITERAL_MASK;
7586 inst.instruction |= (INST_IMMEDIATE
7587 | (OPCODE_MOV << DATA_OP_SHIFT));
7588 inst.instruction |= value & 0xfff;
7589 end_of_line (str);
7590 return;
7593 value = validate_immediate (~inst.reloc.exp.X_add_number);
7595 if (value != FAIL)
7597 /* This can be done with a mvn instruction. */
7598 inst.instruction &= LITERAL_MASK;
7599 inst.instruction |= (INST_IMMEDIATE
7600 | (OPCODE_MVN << DATA_OP_SHIFT));
7601 inst.instruction |= value & 0xfff;
7602 end_of_line (str);
7603 return;
7607 /* Insert into literal pool. */
7608 if (add_to_lit_pool () == FAIL)
7610 if (!inst.error)
7611 inst.error = _("literal pool insertion failed");
7612 return;
7615 /* Change the instruction exp to point to the pool. */
7616 inst.reloc.type = BFD_RELOC_ARM_LITERAL;
7617 inst.reloc.pc_rel = 1;
7618 inst.instruction |= (REG_PC << 16);
7619 pre_inc = 1;
7621 else
7623 if (my_get_expression (&inst.reloc.exp, &str))
7624 return;
7626 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
7627 #ifndef TE_WINCE
7628 /* PC rel adjust. */
7629 inst.reloc.exp.X_add_number -= 8;
7630 #endif
7631 inst.reloc.pc_rel = 1;
7632 inst.instruction |= (REG_PC << 16);
7633 pre_inc = 1;
7636 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
7637 end_of_line (str);
7640 static void
7641 do_ldstt (str)
7642 char * str;
7644 int conflict_reg;
7646 skip_whitespace (str);
7648 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
7650 if (!inst.error)
7651 inst.error = BAD_ARGS;
7652 return;
7655 if (skip_past_comma (& str) == FAIL)
7657 inst.error = _("address expected");
7658 return;
7661 if (*str == '[')
7663 int reg;
7665 str++;
7667 skip_whitespace (str);
7669 if ((reg = reg_required_here (&str, 16)) == FAIL)
7670 return;
7672 /* ldrt/strt always use post-indexed addressing, so if the base is
7673 the same as Rd, we warn. */
7674 if (conflict_reg == reg)
7675 as_warn (_("%s register same as write-back base"),
7676 ((inst.instruction & LOAD_BIT)
7677 ? _("destination") : _("source")));
7679 skip_whitespace (str);
7681 if (*str == ']')
7683 str ++;
7685 if (skip_past_comma (&str) == SUCCESS)
7687 /* [Rn],... (post inc) */
7688 if (ldst_extend (&str) == FAIL)
7689 return;
7691 else
7693 /* [Rn] */
7694 skip_whitespace (str);
7696 /* Skip a write-back '!'. */
7697 if (*str == '!')
7698 str++;
7700 inst.instruction |= INDEX_UP;
7703 else
7705 inst.error = _("post-indexed expression expected");
7706 return;
7709 else
7711 inst.error = _("post-indexed expression expected");
7712 return;
7715 end_of_line (str);
7718 static int
7719 ldst_extend_v4 (str)
7720 char ** str;
7722 int add = INDEX_UP;
7724 switch (**str)
7726 case '#':
7727 case '$':
7728 (*str)++;
7729 if (my_get_expression (& inst.reloc.exp, str))
7730 return FAIL;
7732 if (inst.reloc.exp.X_op == O_constant)
7734 int value = inst.reloc.exp.X_add_number;
7736 if (value < -255 || value > 255)
7738 inst.error = _("address offset too large");
7739 return FAIL;
7742 if (value < 0)
7744 value = -value;
7745 add = 0;
7748 /* Halfword and signextension instructions have the
7749 immediate value split across bits 11..8 and bits 3..0. */
7750 inst.instruction |= (add | HWOFFSET_IMM
7751 | ((value >> 4) << 8) | (value & 0xF));
7753 else
7755 inst.instruction |= HWOFFSET_IMM;
7756 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
7757 inst.reloc.pc_rel = 0;
7759 return SUCCESS;
7761 case '-':
7762 add = 0;
7763 /* Fall through. */
7765 case '+':
7766 (*str)++;
7767 /* Fall through. */
7769 default:
7770 if (reg_required_here (str, 0) == FAIL)
7771 return FAIL;
7773 inst.instruction |= add;
7774 return SUCCESS;
7778 /* Halfword and signed-byte load/store operations. */
7779 static void
7780 do_ldstv4 (str)
7781 char * str;
7783 int pre_inc = 0;
7784 int conflict_reg;
7785 int value;
7787 skip_whitespace (str);
7789 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
7791 if (!inst.error)
7792 inst.error = BAD_ARGS;
7793 return;
7796 if (skip_past_comma (& str) == FAIL)
7798 inst.error = _("address expected");
7799 return;
7802 if (*str == '[')
7804 int reg;
7806 str++;
7808 skip_whitespace (str);
7810 if ((reg = reg_required_here (&str, 16)) == FAIL)
7811 return;
7813 /* Conflicts can occur on stores as well as loads. */
7814 conflict_reg = (conflict_reg == reg);
7816 skip_whitespace (str);
7818 if (*str == ']')
7820 str ++;
7822 if (skip_past_comma (&str) == SUCCESS)
7824 /* [Rn],... (post inc) */
7825 if (ldst_extend_v4 (&str) == FAIL)
7826 return;
7827 if (conflict_reg)
7828 as_warn (_("%s register same as write-back base"),
7829 ((inst.instruction & LOAD_BIT)
7830 ? _("destination") : _("source")));
7832 else
7834 /* [Rn] */
7835 inst.instruction |= HWOFFSET_IMM;
7837 skip_whitespace (str);
7839 if (*str == '!')
7841 if (conflict_reg)
7842 as_warn (_("%s register same as write-back base"),
7843 ((inst.instruction & LOAD_BIT)
7844 ? _("destination") : _("source")));
7845 str++;
7846 inst.instruction |= WRITE_BACK;
7849 inst.instruction |= INDEX_UP;
7850 pre_inc = 1;
7853 else
7855 /* [Rn,...] */
7856 if (skip_past_comma (&str) == FAIL)
7858 inst.error = _("pre-indexed expression expected");
7859 return;
7862 pre_inc = 1;
7863 if (ldst_extend_v4 (&str) == FAIL)
7864 return;
7866 skip_whitespace (str);
7868 if (*str++ != ']')
7870 inst.error = _("missing ]");
7871 return;
7874 skip_whitespace (str);
7876 if (*str == '!')
7878 if (conflict_reg)
7879 as_warn (_("%s register same as write-back base"),
7880 ((inst.instruction & LOAD_BIT)
7881 ? _("destination") : _("source")));
7882 str++;
7883 inst.instruction |= WRITE_BACK;
7887 else if (*str == '=')
7889 if ((inst.instruction & LOAD_BIT) == 0)
7891 inst.error = _("invalid pseudo operation");
7892 return;
7895 /* XXX Does this work correctly for half-word/byte ops? */
7896 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
7897 str++;
7899 skip_whitespace (str);
7901 if (my_get_expression (&inst.reloc.exp, &str))
7902 return;
7904 if (inst.reloc.exp.X_op != O_constant
7905 && inst.reloc.exp.X_op != O_symbol)
7907 inst.error = _("constant expression expected");
7908 return;
7911 if (inst.reloc.exp.X_op == O_constant)
7913 value = validate_immediate (inst.reloc.exp.X_add_number);
7915 if (value != FAIL)
7917 /* This can be done with a mov instruction. */
7918 inst.instruction &= LITERAL_MASK;
7919 inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
7920 inst.instruction |= value & 0xfff;
7921 end_of_line (str);
7922 return;
7925 value = validate_immediate (~ inst.reloc.exp.X_add_number);
7927 if (value != FAIL)
7929 /* This can be done with a mvn instruction. */
7930 inst.instruction &= LITERAL_MASK;
7931 inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT);
7932 inst.instruction |= value & 0xfff;
7933 end_of_line (str);
7934 return;
7938 /* Insert into literal pool. */
7939 if (add_to_lit_pool () == FAIL)
7941 if (!inst.error)
7942 inst.error = _("literal pool insertion failed");
7943 return;
7946 /* Change the instruction exp to point to the pool. */
7947 inst.instruction |= HWOFFSET_IMM;
7948 inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
7949 inst.reloc.pc_rel = 1;
7950 inst.instruction |= (REG_PC << 16);
7951 pre_inc = 1;
7953 else
7955 if (my_get_expression (&inst.reloc.exp, &str))
7956 return;
7958 inst.instruction |= HWOFFSET_IMM;
7959 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
7960 #ifndef TE_WINCE
7961 /* PC rel adjust. */
7962 inst.reloc.exp.X_add_number -= 8;
7963 #endif
7964 inst.reloc.pc_rel = 1;
7965 inst.instruction |= (REG_PC << 16);
7966 pre_inc = 1;
7969 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
7970 end_of_line (str);
7973 static long
7974 reg_list (strp)
7975 char ** strp;
7977 char * str = * strp;
7978 long range = 0;
7979 int another_range;
7981 /* We come back here if we get ranges concatenated by '+' or '|'. */
7984 another_range = 0;
7986 if (*str == '{')
7988 int in_range = 0;
7989 int cur_reg = -1;
7991 str++;
7994 int reg;
7996 skip_whitespace (str);
7998 if ((reg = reg_required_here (& str, -1)) == FAIL)
7999 return FAIL;
8001 if (in_range)
8003 int i;
8005 if (reg <= cur_reg)
8007 inst.error = _("bad range in register list");
8008 return FAIL;
8011 for (i = cur_reg + 1; i < reg; i++)
8013 if (range & (1 << i))
8014 as_tsktsk
8015 (_("Warning: duplicated register (r%d) in register list"),
8017 else
8018 range |= 1 << i;
8020 in_range = 0;
8023 if (range & (1 << reg))
8024 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
8025 reg);
8026 else if (reg <= cur_reg)
8027 as_tsktsk (_("Warning: register range not in ascending order"));
8029 range |= 1 << reg;
8030 cur_reg = reg;
8032 while (skip_past_comma (&str) != FAIL
8033 || (in_range = 1, *str++ == '-'));
8034 str--;
8035 skip_whitespace (str);
8037 if (*str++ != '}')
8039 inst.error = _("missing `}'");
8040 return FAIL;
8043 else
8045 expressionS expr;
8047 if (my_get_expression (&expr, &str))
8048 return FAIL;
8050 if (expr.X_op == O_constant)
8052 if (expr.X_add_number
8053 != (expr.X_add_number & 0x0000ffff))
8055 inst.error = _("invalid register mask");
8056 return FAIL;
8059 if ((range & expr.X_add_number) != 0)
8061 int regno = range & expr.X_add_number;
8063 regno &= -regno;
8064 regno = (1 << regno) - 1;
8065 as_tsktsk
8066 (_("Warning: duplicated register (r%d) in register list"),
8067 regno);
8070 range |= expr.X_add_number;
8072 else
8074 if (inst.reloc.type != 0)
8076 inst.error = _("expression too complex");
8077 return FAIL;
8080 memcpy (&inst.reloc.exp, &expr, sizeof (expressionS));
8081 inst.reloc.type = BFD_RELOC_ARM_MULTI;
8082 inst.reloc.pc_rel = 0;
8086 skip_whitespace (str);
8088 if (*str == '|' || *str == '+')
8090 str++;
8091 another_range = 1;
8094 while (another_range);
8096 *strp = str;
8097 return range;
8100 static void
8101 do_ldmstm (str)
8102 char * str;
8104 int base_reg;
8105 long range;
8107 skip_whitespace (str);
8109 if ((base_reg = reg_required_here (&str, 16)) == FAIL)
8110 return;
8112 if (base_reg == REG_PC)
8114 inst.error = _("r15 not allowed as base register");
8115 return;
8118 skip_whitespace (str);
8120 if (*str == '!')
8122 inst.instruction |= WRITE_BACK;
8123 str++;
8126 if (skip_past_comma (&str) == FAIL
8127 || (range = reg_list (&str)) == FAIL)
8129 if (! inst.error)
8130 inst.error = BAD_ARGS;
8131 return;
8134 if (*str == '^')
8136 str++;
8137 inst.instruction |= LDM_TYPE_2_OR_3;
8140 if (inst.instruction & WRITE_BACK)
8142 /* Check for unpredictable uses of writeback. */
8143 if (inst.instruction & LOAD_BIT)
8145 /* Not allowed in LDM type 2. */
8146 if ((inst.instruction & LDM_TYPE_2_OR_3)
8147 && ((range & (1 << REG_PC)) == 0))
8148 as_warn (_("writeback of base register is UNPREDICTABLE"));
8149 /* Only allowed if base reg not in list for other types. */
8150 else if (range & (1 << base_reg))
8151 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
8153 else /* STM. */
8155 /* Not allowed for type 2. */
8156 if (inst.instruction & LDM_TYPE_2_OR_3)
8157 as_warn (_("writeback of base register is UNPREDICTABLE"));
8158 /* Only allowed if base reg not in list, or first in list. */
8159 else if ((range & (1 << base_reg))
8160 && (range & ((1 << base_reg) - 1)))
8161 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
8165 inst.instruction |= range;
8166 end_of_line (str);
8169 static void
8170 do_swi (str)
8171 char * str;
8173 skip_whitespace (str);
8175 /* Allow optional leading '#'. */
8176 if (is_immediate_prefix (*str))
8177 str++;
8179 if (my_get_expression (& inst.reloc.exp, & str))
8180 return;
8182 inst.reloc.type = BFD_RELOC_ARM_SWI;
8183 inst.reloc.pc_rel = 0;
8184 end_of_line (str);
8187 static void
8188 do_swap (str)
8189 char * str;
8191 int reg;
8193 skip_whitespace (str);
8195 if ((reg = reg_required_here (&str, 12)) == FAIL)
8196 return;
8198 if (reg == REG_PC)
8200 inst.error = _("r15 not allowed in swap");
8201 return;
8204 if (skip_past_comma (&str) == FAIL
8205 || (reg = reg_required_here (&str, 0)) == FAIL)
8207 if (!inst.error)
8208 inst.error = BAD_ARGS;
8209 return;
8212 if (reg == REG_PC)
8214 inst.error = _("r15 not allowed in swap");
8215 return;
8218 if (skip_past_comma (&str) == FAIL
8219 || *str++ != '[')
8221 inst.error = BAD_ARGS;
8222 return;
8225 skip_whitespace (str);
8227 if ((reg = reg_required_here (&str, 16)) == FAIL)
8228 return;
8230 if (reg == REG_PC)
8232 inst.error = BAD_PC;
8233 return;
8236 skip_whitespace (str);
8238 if (*str++ != ']')
8240 inst.error = _("missing ]");
8241 return;
8244 end_of_line (str);
8247 static void
8248 do_branch (str)
8249 char * str;
8251 if (my_get_expression (&inst.reloc.exp, &str))
8252 return;
8254 #ifdef OBJ_ELF
8256 char * save_in;
8258 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
8259 required for the instruction. */
8261 /* arm_parse_reloc () works on input_line_pointer.
8262 We actually want to parse the operands to the branch instruction
8263 passed in 'str'. Save the input pointer and restore it later. */
8264 save_in = input_line_pointer;
8265 input_line_pointer = str;
8266 if (inst.reloc.exp.X_op == O_symbol
8267 && *str == '('
8268 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
8270 inst.reloc.type = BFD_RELOC_ARM_PLT32;
8271 inst.reloc.pc_rel = 0;
8272 /* Modify str to point to after parsed operands, otherwise
8273 end_of_line() will complain about the (PLT) left in str. */
8274 str = input_line_pointer;
8276 else
8278 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
8279 inst.reloc.pc_rel = 1;
8281 input_line_pointer = save_in;
8283 #else
8284 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
8285 inst.reloc.pc_rel = 1;
8286 #endif /* OBJ_ELF */
8288 end_of_line (str);
8291 static void
8292 do_bx (str)
8293 char * str;
8295 int reg;
8297 skip_whitespace (str);
8299 if ((reg = reg_required_here (&str, 0)) == FAIL)
8301 inst.error = BAD_ARGS;
8302 return;
8305 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
8306 if (reg == REG_PC)
8307 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
8309 end_of_line (str);
8312 static void
8313 do_cdp (str)
8314 char * str;
8316 /* Co-processor data operation.
8317 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
8318 skip_whitespace (str);
8320 if (co_proc_number (&str) == FAIL)
8322 if (!inst.error)
8323 inst.error = BAD_ARGS;
8324 return;
8327 if (skip_past_comma (&str) == FAIL
8328 || cp_opc_expr (&str, 20,4) == FAIL)
8330 if (!inst.error)
8331 inst.error = BAD_ARGS;
8332 return;
8335 if (skip_past_comma (&str) == FAIL
8336 || cp_reg_required_here (&str, 12) == FAIL)
8338 if (!inst.error)
8339 inst.error = BAD_ARGS;
8340 return;
8343 if (skip_past_comma (&str) == FAIL
8344 || cp_reg_required_here (&str, 16) == FAIL)
8346 if (!inst.error)
8347 inst.error = BAD_ARGS;
8348 return;
8351 if (skip_past_comma (&str) == FAIL
8352 || cp_reg_required_here (&str, 0) == FAIL)
8354 if (!inst.error)
8355 inst.error = BAD_ARGS;
8356 return;
8359 if (skip_past_comma (&str) == SUCCESS)
8361 if (cp_opc_expr (&str, 5, 3) == FAIL)
8363 if (!inst.error)
8364 inst.error = BAD_ARGS;
8365 return;
8369 end_of_line (str);
8372 static void
8373 do_lstc (str)
8374 char * str;
8376 /* Co-processor register load/store.
8377 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
8379 skip_whitespace (str);
8381 if (co_proc_number (&str) == FAIL)
8383 if (!inst.error)
8384 inst.error = BAD_ARGS;
8385 return;
8388 if (skip_past_comma (&str) == FAIL
8389 || cp_reg_required_here (&str, 12) == FAIL)
8391 if (!inst.error)
8392 inst.error = BAD_ARGS;
8393 return;
8396 if (skip_past_comma (&str) == FAIL
8397 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
8399 if (! inst.error)
8400 inst.error = BAD_ARGS;
8401 return;
8404 end_of_line (str);
8407 static void
8408 do_co_reg (str)
8409 char * str;
8411 /* Co-processor register transfer.
8412 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
8414 skip_whitespace (str);
8416 if (co_proc_number (&str) == FAIL)
8418 if (!inst.error)
8419 inst.error = BAD_ARGS;
8420 return;
8423 if (skip_past_comma (&str) == FAIL
8424 || cp_opc_expr (&str, 21, 3) == FAIL)
8426 if (!inst.error)
8427 inst.error = BAD_ARGS;
8428 return;
8431 if (skip_past_comma (&str) == FAIL
8432 || reg_required_here (&str, 12) == FAIL)
8434 if (!inst.error)
8435 inst.error = BAD_ARGS;
8436 return;
8439 if (skip_past_comma (&str) == FAIL
8440 || cp_reg_required_here (&str, 16) == FAIL)
8442 if (!inst.error)
8443 inst.error = BAD_ARGS;
8444 return;
8447 if (skip_past_comma (&str) == FAIL
8448 || cp_reg_required_here (&str, 0) == FAIL)
8450 if (!inst.error)
8451 inst.error = BAD_ARGS;
8452 return;
8455 if (skip_past_comma (&str) == SUCCESS)
8457 if (cp_opc_expr (&str, 5, 3) == FAIL)
8459 if (!inst.error)
8460 inst.error = BAD_ARGS;
8461 return;
8465 end_of_line (str);
8468 static void
8469 do_fpa_ctrl (str)
8470 char * str;
8472 /* FP control registers.
8473 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
8475 skip_whitespace (str);
8477 if (reg_required_here (&str, 12) == FAIL)
8479 if (!inst.error)
8480 inst.error = BAD_ARGS;
8481 return;
8484 end_of_line (str);
8487 static void
8488 do_fpa_ldst (str)
8489 char * str;
8491 skip_whitespace (str);
8493 if (fp_reg_required_here (&str, 12) == FAIL)
8495 if (!inst.error)
8496 inst.error = BAD_ARGS;
8497 return;
8500 if (skip_past_comma (&str) == FAIL
8501 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
8503 if (!inst.error)
8504 inst.error = BAD_ARGS;
8505 return;
8508 end_of_line (str);
8511 static void
8512 do_fpa_ldmstm (str)
8513 char * str;
8515 int num_regs;
8517 skip_whitespace (str);
8519 if (fp_reg_required_here (&str, 12) == FAIL)
8521 if (! inst.error)
8522 inst.error = BAD_ARGS;
8523 return;
8526 /* Get Number of registers to transfer. */
8527 if (skip_past_comma (&str) == FAIL
8528 || my_get_expression (&inst.reloc.exp, &str))
8530 if (! inst.error)
8531 inst.error = _("constant expression expected");
8532 return;
8535 if (inst.reloc.exp.X_op != O_constant)
8537 inst.error = _("constant value required for number of registers");
8538 return;
8541 num_regs = inst.reloc.exp.X_add_number;
8543 if (num_regs < 1 || num_regs > 4)
8545 inst.error = _("number of registers must be in the range [1:4]");
8546 return;
8549 switch (num_regs)
8551 case 1:
8552 inst.instruction |= CP_T_X;
8553 break;
8554 case 2:
8555 inst.instruction |= CP_T_Y;
8556 break;
8557 case 3:
8558 inst.instruction |= CP_T_Y | CP_T_X;
8559 break;
8560 case 4:
8561 break;
8562 default:
8563 abort ();
8566 if (inst.instruction & (CP_T_Pre | CP_T_UD)) /* ea/fd format. */
8568 int reg;
8569 int write_back;
8570 int offset;
8572 /* The instruction specified "ea" or "fd", so we can only accept
8573 [Rn]{!}. The instruction does not really support stacking or
8574 unstacking, so we have to emulate these by setting appropriate
8575 bits and offsets. */
8576 if (skip_past_comma (&str) == FAIL
8577 || *str != '[')
8579 if (! inst.error)
8580 inst.error = BAD_ARGS;
8581 return;
8584 str++;
8585 skip_whitespace (str);
8587 if ((reg = reg_required_here (&str, 16)) == FAIL)
8588 return;
8590 skip_whitespace (str);
8592 if (*str != ']')
8594 inst.error = BAD_ARGS;
8595 return;
8598 str++;
8599 if (*str == '!')
8601 write_back = 1;
8602 str++;
8603 if (reg == REG_PC)
8605 inst.error =
8606 _("r15 not allowed as base register with write-back");
8607 return;
8610 else
8611 write_back = 0;
8613 if (inst.instruction & CP_T_Pre)
8615 /* Pre-decrement. */
8616 offset = 3 * num_regs;
8617 if (write_back)
8618 inst.instruction |= CP_T_WB;
8620 else
8622 /* Post-increment. */
8623 if (write_back)
8625 inst.instruction |= CP_T_WB;
8626 offset = 3 * num_regs;
8628 else
8630 /* No write-back, so convert this into a standard pre-increment
8631 instruction -- aesthetically more pleasing. */
8632 inst.instruction |= CP_T_Pre | CP_T_UD;
8633 offset = 0;
8637 inst.instruction |= offset;
8639 else if (skip_past_comma (&str) == FAIL
8640 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
8642 if (! inst.error)
8643 inst.error = BAD_ARGS;
8644 return;
8647 end_of_line (str);
8650 static void
8651 do_fpa_dyadic (str)
8652 char * str;
8654 skip_whitespace (str);
8656 if (fp_reg_required_here (&str, 12) == FAIL)
8658 if (! inst.error)
8659 inst.error = BAD_ARGS;
8660 return;
8663 if (skip_past_comma (&str) == FAIL
8664 || fp_reg_required_here (&str, 16) == FAIL)
8666 if (! inst.error)
8667 inst.error = BAD_ARGS;
8668 return;
8671 if (skip_past_comma (&str) == FAIL
8672 || fp_op2 (&str) == FAIL)
8674 if (! inst.error)
8675 inst.error = BAD_ARGS;
8676 return;
8679 end_of_line (str);
8682 static void
8683 do_fpa_monadic (str)
8684 char * str;
8686 skip_whitespace (str);
8688 if (fp_reg_required_here (&str, 12) == FAIL)
8690 if (! inst.error)
8691 inst.error = BAD_ARGS;
8692 return;
8695 if (skip_past_comma (&str) == FAIL
8696 || fp_op2 (&str) == FAIL)
8698 if (! inst.error)
8699 inst.error = BAD_ARGS;
8700 return;
8703 end_of_line (str);
8706 static void
8707 do_fpa_cmp (str)
8708 char * str;
8710 skip_whitespace (str);
8712 if (fp_reg_required_here (&str, 16) == FAIL)
8714 if (! inst.error)
8715 inst.error = BAD_ARGS;
8716 return;
8719 if (skip_past_comma (&str) == FAIL
8720 || fp_op2 (&str) == FAIL)
8722 if (! inst.error)
8723 inst.error = BAD_ARGS;
8724 return;
8727 end_of_line (str);
8730 static void
8731 do_fpa_from_reg (str)
8732 char * str;
8734 skip_whitespace (str);
8736 if (fp_reg_required_here (&str, 16) == FAIL)
8738 if (! inst.error)
8739 inst.error = BAD_ARGS;
8740 return;
8743 if (skip_past_comma (&str) == FAIL
8744 || reg_required_here (&str, 12) == FAIL)
8746 if (! inst.error)
8747 inst.error = BAD_ARGS;
8748 return;
8751 end_of_line (str);
8754 static void
8755 do_fpa_to_reg (str)
8756 char * str;
8758 skip_whitespace (str);
8760 if (reg_required_here (&str, 12) == FAIL)
8761 return;
8763 if (skip_past_comma (&str) == FAIL
8764 || fp_reg_required_here (&str, 0) == FAIL)
8766 if (! inst.error)
8767 inst.error = BAD_ARGS;
8768 return;
8771 end_of_line (str);
8774 static int
8775 vfp_sp_reg_required_here (str, pos)
8776 char **str;
8777 enum vfp_sp_reg_pos pos;
8779 int reg;
8780 char *start = *str;
8782 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab)) != FAIL)
8784 switch (pos)
8786 case VFP_REG_Sd:
8787 inst.instruction |= ((reg >> 1) << 12) | ((reg & 1) << 22);
8788 break;
8790 case VFP_REG_Sn:
8791 inst.instruction |= ((reg >> 1) << 16) | ((reg & 1) << 7);
8792 break;
8794 case VFP_REG_Sm:
8795 inst.instruction |= ((reg >> 1) << 0) | ((reg & 1) << 5);
8796 break;
8798 default:
8799 abort ();
8801 return reg;
8804 /* In the few cases where we might be able to accept something else
8805 this error can be overridden. */
8806 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
8808 /* Restore the start point. */
8809 *str = start;
8810 return FAIL;
8813 static int
8814 vfp_dp_reg_required_here (str, pos)
8815 char **str;
8816 enum vfp_dp_reg_pos pos;
8818 int reg;
8819 char *start = *str;
8821 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab)) != FAIL)
8823 switch (pos)
8825 case VFP_REG_Dd:
8826 inst.instruction |= reg << 12;
8827 break;
8829 case VFP_REG_Dn:
8830 inst.instruction |= reg << 16;
8831 break;
8833 case VFP_REG_Dm:
8834 inst.instruction |= reg << 0;
8835 break;
8837 default:
8838 abort ();
8840 return reg;
8843 /* In the few cases where we might be able to accept something else
8844 this error can be overridden. */
8845 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
8847 /* Restore the start point. */
8848 *str = start;
8849 return FAIL;
8852 static void
8853 do_vfp_sp_monadic (str)
8854 char *str;
8856 skip_whitespace (str);
8858 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8859 return;
8861 if (skip_past_comma (&str) == FAIL
8862 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
8864 if (! inst.error)
8865 inst.error = BAD_ARGS;
8866 return;
8869 end_of_line (str);
8872 static void
8873 do_vfp_dp_monadic (str)
8874 char *str;
8876 skip_whitespace (str);
8878 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8879 return;
8881 if (skip_past_comma (&str) == FAIL
8882 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8884 if (! inst.error)
8885 inst.error = BAD_ARGS;
8886 return;
8889 end_of_line (str);
8892 static void
8893 do_vfp_sp_dyadic (str)
8894 char *str;
8896 skip_whitespace (str);
8898 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8899 return;
8901 if (skip_past_comma (&str) == FAIL
8902 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL
8903 || skip_past_comma (&str) == FAIL
8904 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
8906 if (! inst.error)
8907 inst.error = BAD_ARGS;
8908 return;
8911 end_of_line (str);
8914 static void
8915 do_vfp_dp_dyadic (str)
8916 char *str;
8918 skip_whitespace (str);
8920 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8921 return;
8923 if (skip_past_comma (&str) == FAIL
8924 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL
8925 || skip_past_comma (&str) == FAIL
8926 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8928 if (! inst.error)
8929 inst.error = BAD_ARGS;
8930 return;
8933 end_of_line (str);
8936 static void
8937 do_vfp_reg_from_sp (str)
8938 char *str;
8940 skip_whitespace (str);
8942 if (reg_required_here (&str, 12) == FAIL)
8943 return;
8945 if (skip_past_comma (&str) == FAIL
8946 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
8948 if (! inst.error)
8949 inst.error = BAD_ARGS;
8950 return;
8953 end_of_line (str);
8956 static void
8957 do_vfp_reg2_from_sp2 (str)
8958 char *str;
8960 skip_whitespace (str);
8962 if (reg_required_here (&str, 12) == FAIL
8963 || skip_past_comma (&str) == FAIL
8964 || reg_required_here (&str, 16) == FAIL
8965 || skip_past_comma (&str) == FAIL)
8967 if (! inst.error)
8968 inst.error = BAD_ARGS;
8969 return;
8972 /* We require exactly two consecutive SP registers. */
8973 if (vfp_sp_reg_list (&str, VFP_REG_Sm) != 2)
8975 if (! inst.error)
8976 inst.error = _("only two consecutive VFP SP registers allowed here");
8979 end_of_line (str);
8982 static void
8983 do_vfp_sp_from_reg (str)
8984 char *str;
8986 skip_whitespace (str);
8988 if (vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
8989 return;
8991 if (skip_past_comma (&str) == FAIL
8992 || reg_required_here (&str, 12) == FAIL)
8994 if (! inst.error)
8995 inst.error = BAD_ARGS;
8996 return;
8999 end_of_line (str);
9002 static void
9003 do_vfp_sp2_from_reg2 (str)
9004 char *str;
9006 skip_whitespace (str);
9008 /* We require exactly two consecutive SP registers. */
9009 if (vfp_sp_reg_list (&str, VFP_REG_Sm) != 2)
9011 if (! inst.error)
9012 inst.error = _("only two consecutive VFP SP registers allowed here");
9015 if (skip_past_comma (&str) == FAIL
9016 || reg_required_here (&str, 12) == FAIL
9017 || skip_past_comma (&str) == FAIL
9018 || reg_required_here (&str, 16) == FAIL)
9020 if (! inst.error)
9021 inst.error = BAD_ARGS;
9022 return;
9025 end_of_line (str);
9028 static void
9029 do_vfp_reg_from_dp (str)
9030 char *str;
9032 skip_whitespace (str);
9034 if (reg_required_here (&str, 12) == FAIL)
9035 return;
9037 if (skip_past_comma (&str) == FAIL
9038 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
9040 if (! inst.error)
9041 inst.error = BAD_ARGS;
9042 return;
9045 end_of_line (str);
9048 static void
9049 do_vfp_reg2_from_dp (str)
9050 char *str;
9052 skip_whitespace (str);
9054 if (reg_required_here (&str, 12) == FAIL)
9055 return;
9057 if (skip_past_comma (&str) == FAIL
9058 || reg_required_here (&str, 16) == FAIL
9059 || skip_past_comma (&str) == FAIL
9060 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
9062 if (! inst.error)
9063 inst.error = BAD_ARGS;
9064 return;
9067 end_of_line (str);
9070 static void
9071 do_vfp_dp_from_reg (str)
9072 char *str;
9074 skip_whitespace (str);
9076 if (vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
9077 return;
9079 if (skip_past_comma (&str) == FAIL
9080 || reg_required_here (&str, 12) == FAIL)
9082 if (! inst.error)
9083 inst.error = BAD_ARGS;
9084 return;
9087 end_of_line (str);
9090 static void
9091 do_vfp_dp_from_reg2 (str)
9092 char *str;
9094 skip_whitespace (str);
9096 if (vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
9097 return;
9099 if (skip_past_comma (&str) == FAIL
9100 || reg_required_here (&str, 12) == FAIL
9101 || skip_past_comma (&str) == FAIL
9102 || reg_required_here (&str, 16) == FAIL)
9104 if (! inst.error)
9105 inst.error = BAD_ARGS;
9106 return;
9109 end_of_line (str);
9112 static const struct vfp_reg *
9113 vfp_psr_parse (str)
9114 char **str;
9116 char *start = *str;
9117 char c;
9118 char *p;
9119 const struct vfp_reg *vreg;
9121 p = start;
9123 /* Find the end of the current token. */
9126 c = *p++;
9128 while (ISALPHA (c));
9130 /* Mark it. */
9131 *--p = 0;
9133 for (vreg = vfp_regs + 0;
9134 vreg < vfp_regs + sizeof (vfp_regs) / sizeof (struct vfp_reg);
9135 vreg++)
9137 if (strcmp (start, vreg->name) == 0)
9139 *p = c;
9140 *str = p;
9141 return vreg;
9145 *p = c;
9146 return NULL;
9149 static int
9150 vfp_psr_required_here (str)
9151 char **str;
9153 char *start = *str;
9154 const struct vfp_reg *vreg;
9156 vreg = vfp_psr_parse (str);
9158 if (vreg)
9160 inst.instruction |= vreg->regno;
9161 return SUCCESS;
9164 inst.error = _("VFP system register expected");
9166 *str = start;
9167 return FAIL;
9170 static void
9171 do_vfp_reg_from_ctrl (str)
9172 char *str;
9174 skip_whitespace (str);
9176 if (reg_required_here (&str, 12) == FAIL)
9177 return;
9179 if (skip_past_comma (&str) == FAIL
9180 || vfp_psr_required_here (&str) == FAIL)
9182 if (! inst.error)
9183 inst.error = BAD_ARGS;
9184 return;
9187 end_of_line (str);
9190 static void
9191 do_vfp_ctrl_from_reg (str)
9192 char *str;
9194 skip_whitespace (str);
9196 if (vfp_psr_required_here (&str) == FAIL)
9197 return;
9199 if (skip_past_comma (&str) == FAIL
9200 || reg_required_here (&str, 12) == FAIL)
9202 if (! inst.error)
9203 inst.error = BAD_ARGS;
9204 return;
9207 end_of_line (str);
9210 static void
9211 do_vfp_sp_ldst (str)
9212 char *str;
9214 skip_whitespace (str);
9216 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
9218 if (!inst.error)
9219 inst.error = BAD_ARGS;
9220 return;
9223 if (skip_past_comma (&str) == FAIL
9224 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
9226 if (!inst.error)
9227 inst.error = BAD_ARGS;
9228 return;
9231 end_of_line (str);
9234 static void
9235 do_vfp_dp_ldst (str)
9236 char *str;
9238 skip_whitespace (str);
9240 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
9242 if (!inst.error)
9243 inst.error = BAD_ARGS;
9244 return;
9247 if (skip_past_comma (&str) == FAIL
9248 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
9250 if (!inst.error)
9251 inst.error = BAD_ARGS;
9252 return;
9255 end_of_line (str);
9258 /* Parse and encode a VFP SP register list, storing the initial
9259 register in position POS and returning the range as the result. If
9260 the string is invalid return FAIL (an invalid range). */
9261 static long
9262 vfp_sp_reg_list (str, pos)
9263 char **str;
9264 enum vfp_sp_reg_pos pos;
9266 long range = 0;
9267 int base_reg = 0;
9268 int new_base;
9269 long base_bits = 0;
9270 int count = 0;
9271 long tempinst;
9272 unsigned long mask = 0;
9273 int warned = 0;
9275 if (**str != '{')
9276 return FAIL;
9278 (*str)++;
9279 skip_whitespace (*str);
9281 tempinst = inst.instruction;
9285 inst.instruction = 0;
9287 if ((new_base = vfp_sp_reg_required_here (str, pos)) == FAIL)
9288 return FAIL;
9290 if (count == 0 || base_reg > new_base)
9292 base_reg = new_base;
9293 base_bits = inst.instruction;
9296 if (mask & (1 << new_base))
9298 inst.error = _("invalid register list");
9299 return FAIL;
9302 if ((mask >> new_base) != 0 && ! warned)
9304 as_tsktsk (_("register list not in ascending order"));
9305 warned = 1;
9308 mask |= 1 << new_base;
9309 count++;
9311 skip_whitespace (*str);
9313 if (**str == '-') /* We have the start of a range expression */
9315 int high_range;
9317 (*str)++;
9319 if ((high_range
9320 = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab))
9321 == FAIL)
9323 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
9324 return FAIL;
9327 if (high_range <= new_base)
9329 inst.error = _("register range not in ascending order");
9330 return FAIL;
9333 for (new_base++; new_base <= high_range; new_base++)
9335 if (mask & (1 << new_base))
9337 inst.error = _("invalid register list");
9338 return FAIL;
9341 mask |= 1 << new_base;
9342 count++;
9346 while (skip_past_comma (str) != FAIL);
9348 if (**str != '}')
9350 inst.error = _("invalid register list");
9351 return FAIL;
9354 (*str)++;
9356 range = count;
9358 /* Sanity check -- should have raised a parse error above. */
9359 if (count == 0 || count > 32)
9360 abort ();
9362 /* Final test -- the registers must be consecutive. */
9363 while (count--)
9365 if ((mask & (1 << base_reg++)) == 0)
9367 inst.error = _("non-contiguous register range");
9368 return FAIL;
9372 inst.instruction = tempinst | base_bits;
9373 return range;
9376 static long
9377 vfp_dp_reg_list (str)
9378 char **str;
9380 long range = 0;
9381 int base_reg = 0;
9382 int new_base;
9383 int count = 0;
9384 long tempinst;
9385 unsigned long mask = 0;
9386 int warned = 0;
9388 if (**str != '{')
9389 return FAIL;
9391 (*str)++;
9392 skip_whitespace (*str);
9394 tempinst = inst.instruction;
9398 inst.instruction = 0;
9400 if ((new_base = vfp_dp_reg_required_here (str, VFP_REG_Dd)) == FAIL)
9401 return FAIL;
9403 if (count == 0 || base_reg > new_base)
9405 base_reg = new_base;
9406 range = inst.instruction;
9409 if (mask & (1 << new_base))
9411 inst.error = _("invalid register list");
9412 return FAIL;
9415 if ((mask >> new_base) != 0 && ! warned)
9417 as_tsktsk (_("register list not in ascending order"));
9418 warned = 1;
9421 mask |= 1 << new_base;
9422 count++;
9424 skip_whitespace (*str);
9426 if (**str == '-') /* We have the start of a range expression */
9428 int high_range;
9430 (*str)++;
9432 if ((high_range
9433 = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab))
9434 == FAIL)
9436 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
9437 return FAIL;
9440 if (high_range <= new_base)
9442 inst.error = _("register range not in ascending order");
9443 return FAIL;
9446 for (new_base++; new_base <= high_range; new_base++)
9448 if (mask & (1 << new_base))
9450 inst.error = _("invalid register list");
9451 return FAIL;
9454 mask |= 1 << new_base;
9455 count++;
9459 while (skip_past_comma (str) != FAIL);
9461 if (**str != '}')
9463 inst.error = _("invalid register list");
9464 return FAIL;
9467 (*str)++;
9469 range |= 2 * count;
9471 /* Sanity check -- should have raised a parse error above. */
9472 if (count == 0 || count > 16)
9473 abort ();
9475 /* Final test -- the registers must be consecutive. */
9476 while (count--)
9478 if ((mask & (1 << base_reg++)) == 0)
9480 inst.error = _("non-contiguous register range");
9481 return FAIL;
9485 inst.instruction = tempinst;
9486 return range;
9489 static void
9490 vfp_sp_ldstm (str, ldstm_type)
9491 char *str;
9492 enum vfp_ldstm_type ldstm_type;
9494 long range;
9496 skip_whitespace (str);
9498 if (reg_required_here (&str, 16) == FAIL)
9499 return;
9501 skip_whitespace (str);
9503 if (*str == '!')
9505 inst.instruction |= WRITE_BACK;
9506 str++;
9508 else if (ldstm_type != VFP_LDSTMIA)
9510 inst.error = _("this addressing mode requires base-register writeback");
9511 return;
9514 if (skip_past_comma (&str) == FAIL
9515 || (range = vfp_sp_reg_list (&str, VFP_REG_Sd)) == FAIL)
9517 if (!inst.error)
9518 inst.error = BAD_ARGS;
9519 return;
9522 inst.instruction |= range;
9523 end_of_line (str);
9526 static void
9527 vfp_dp_ldstm (str, ldstm_type)
9528 char *str;
9529 enum vfp_ldstm_type ldstm_type;
9531 long range;
9533 skip_whitespace (str);
9535 if (reg_required_here (&str, 16) == FAIL)
9536 return;
9538 skip_whitespace (str);
9540 if (*str == '!')
9542 inst.instruction |= WRITE_BACK;
9543 str++;
9545 else if (ldstm_type != VFP_LDSTMIA && ldstm_type != VFP_LDSTMIAX)
9547 inst.error = _("this addressing mode requires base-register writeback");
9548 return;
9551 if (skip_past_comma (&str) == FAIL
9552 || (range = vfp_dp_reg_list (&str)) == FAIL)
9554 if (!inst.error)
9555 inst.error = BAD_ARGS;
9556 return;
9559 if (ldstm_type == VFP_LDSTMIAX || ldstm_type == VFP_LDSTMDBX)
9560 range += 1;
9562 inst.instruction |= range;
9563 end_of_line (str);
9566 static void
9567 do_vfp_sp_ldstmia (str)
9568 char *str;
9570 vfp_sp_ldstm (str, VFP_LDSTMIA);
9573 static void
9574 do_vfp_sp_ldstmdb (str)
9575 char *str;
9577 vfp_sp_ldstm (str, VFP_LDSTMDB);
9580 static void
9581 do_vfp_dp_ldstmia (str)
9582 char *str;
9584 vfp_dp_ldstm (str, VFP_LDSTMIA);
9587 static void
9588 do_vfp_dp_ldstmdb (str)
9589 char *str;
9591 vfp_dp_ldstm (str, VFP_LDSTMDB);
9594 static void
9595 do_vfp_xp_ldstmia (str)
9596 char *str;
9598 vfp_dp_ldstm (str, VFP_LDSTMIAX);
9601 static void
9602 do_vfp_xp_ldstmdb (str)
9603 char *str;
9605 vfp_dp_ldstm (str, VFP_LDSTMDBX);
9608 static void
9609 do_vfp_sp_compare_z (str)
9610 char *str;
9612 skip_whitespace (str);
9614 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
9616 if (!inst.error)
9617 inst.error = BAD_ARGS;
9618 return;
9621 end_of_line (str);
9624 static void
9625 do_vfp_dp_compare_z (str)
9626 char *str;
9628 skip_whitespace (str);
9630 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
9632 if (!inst.error)
9633 inst.error = BAD_ARGS;
9634 return;
9637 end_of_line (str);
9640 static void
9641 do_vfp_dp_sp_cvt (str)
9642 char *str;
9644 skip_whitespace (str);
9646 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
9647 return;
9649 if (skip_past_comma (&str) == FAIL
9650 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
9652 if (! inst.error)
9653 inst.error = BAD_ARGS;
9654 return;
9657 end_of_line (str);
9660 static void
9661 do_vfp_sp_dp_cvt (str)
9662 char *str;
9664 skip_whitespace (str);
9666 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
9667 return;
9669 if (skip_past_comma (&str) == FAIL
9670 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
9672 if (! inst.error)
9673 inst.error = BAD_ARGS;
9674 return;
9677 end_of_line (str);
9680 /* Thumb specific routines. */
9682 /* Parse and validate that a register is of the right form, this saves
9683 repeated checking of this information in many similar cases.
9684 Unlike the 32-bit case we do not insert the register into the opcode
9685 here, since the position is often unknown until the full instruction
9686 has been parsed. */
9688 static int
9689 thumb_reg (strp, hi_lo)
9690 char ** strp;
9691 int hi_lo;
9693 int reg;
9695 if ((reg = reg_required_here (strp, -1)) == FAIL)
9696 return FAIL;
9698 switch (hi_lo)
9700 case THUMB_REG_LO:
9701 if (reg > 7)
9703 inst.error = _("lo register required");
9704 return FAIL;
9706 break;
9708 case THUMB_REG_HI:
9709 if (reg < 8)
9711 inst.error = _("hi register required");
9712 return FAIL;
9714 break;
9716 default:
9717 break;
9720 return reg;
9723 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
9724 was SUB. */
9726 static void
9727 thumb_add_sub (str, subtract)
9728 char * str;
9729 int subtract;
9731 int Rd, Rs, Rn = FAIL;
9733 skip_whitespace (str);
9735 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
9736 || skip_past_comma (&str) == FAIL)
9738 if (! inst.error)
9739 inst.error = BAD_ARGS;
9740 return;
9743 if (is_immediate_prefix (*str))
9745 Rs = Rd;
9746 str++;
9747 if (my_get_expression (&inst.reloc.exp, &str))
9748 return;
9750 else
9752 if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9753 return;
9755 if (skip_past_comma (&str) == FAIL)
9757 /* Two operand format, shuffle the registers
9758 and pretend there are 3. */
9759 Rn = Rs;
9760 Rs = Rd;
9762 else if (is_immediate_prefix (*str))
9764 str++;
9765 if (my_get_expression (&inst.reloc.exp, &str))
9766 return;
9768 else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9769 return;
9772 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
9773 for the latter case, EXPR contains the immediate that was found. */
9774 if (Rn != FAIL)
9776 /* All register format. */
9777 if (Rd > 7 || Rs > 7 || Rn > 7)
9779 if (Rs != Rd)
9781 inst.error = _("dest and source1 must be the same register");
9782 return;
9785 /* Can't do this for SUB. */
9786 if (subtract)
9788 inst.error = _("subtract valid only on lo regs");
9789 return;
9792 inst.instruction = (T_OPCODE_ADD_HI
9793 | (Rd > 7 ? THUMB_H1 : 0)
9794 | (Rn > 7 ? THUMB_H2 : 0));
9795 inst.instruction |= (Rd & 7) | ((Rn & 7) << 3);
9797 else
9799 inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3;
9800 inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
9803 else
9805 /* Immediate expression, now things start to get nasty. */
9807 /* First deal with HI regs, only very restricted cases allowed:
9808 Adjusting SP, and using PC or SP to get an address. */
9809 if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP))
9810 || (Rs > 7 && Rs != REG_SP && Rs != REG_PC))
9812 inst.error = _("invalid Hi register with immediate");
9813 return;
9816 if (inst.reloc.exp.X_op != O_constant)
9818 /* Value isn't known yet, all we can do is store all the fragments
9819 we know about in the instruction and let the reloc hacking
9820 work it all out. */
9821 inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs;
9822 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
9824 else
9826 int offset = inst.reloc.exp.X_add_number;
9828 if (subtract)
9829 offset = - offset;
9831 if (offset < 0)
9833 offset = - offset;
9834 subtract = 1;
9836 /* Quick check, in case offset is MIN_INT. */
9837 if (offset < 0)
9839 inst.error = _("immediate value out of range");
9840 return;
9843 /* Note - you cannot convert a subtract of 0 into an
9844 add of 0 because the carry flag is set differently. */
9845 else if (offset > 0)
9846 subtract = 0;
9848 if (Rd == REG_SP)
9850 if (offset & ~0x1fc)
9852 inst.error = _("invalid immediate value for stack adjust");
9853 return;
9855 inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
9856 inst.instruction |= offset >> 2;
9858 else if (Rs == REG_PC || Rs == REG_SP)
9860 if (subtract
9861 || (offset & ~0x3fc))
9863 inst.error = _("invalid immediate for address calculation");
9864 return;
9866 inst.instruction = (Rs == REG_PC ? T_OPCODE_ADD_PC
9867 : T_OPCODE_ADD_SP);
9868 inst.instruction |= (Rd << 8) | (offset >> 2);
9870 else if (Rs == Rd)
9872 if (offset & ~0xff)
9874 inst.error = _("immediate value out of range");
9875 return;
9877 inst.instruction = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
9878 inst.instruction |= (Rd << 8) | offset;
9880 else
9882 if (offset & ~0x7)
9884 inst.error = _("immediate value out of range");
9885 return;
9887 inst.instruction = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
9888 inst.instruction |= Rd | (Rs << 3) | (offset << 6);
9893 end_of_line (str);
9896 static void
9897 thumb_shift (str, shift)
9898 char * str;
9899 int shift;
9901 int Rd, Rs, Rn = FAIL;
9903 skip_whitespace (str);
9905 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9906 || skip_past_comma (&str) == FAIL)
9908 if (! inst.error)
9909 inst.error = BAD_ARGS;
9910 return;
9913 if (is_immediate_prefix (*str))
9915 /* Two operand immediate format, set Rs to Rd. */
9916 Rs = Rd;
9917 str ++;
9918 if (my_get_expression (&inst.reloc.exp, &str))
9919 return;
9921 else
9923 if ((Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9924 return;
9926 if (skip_past_comma (&str) == FAIL)
9928 /* Two operand format, shuffle the registers
9929 and pretend there are 3. */
9930 Rn = Rs;
9931 Rs = Rd;
9933 else if (is_immediate_prefix (*str))
9935 str++;
9936 if (my_get_expression (&inst.reloc.exp, &str))
9937 return;
9939 else if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9940 return;
9943 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
9944 for the latter case, EXPR contains the immediate that was found. */
9946 if (Rn != FAIL)
9948 if (Rs != Rd)
9950 inst.error = _("source1 and dest must be same register");
9951 return;
9954 switch (shift)
9956 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_R; break;
9957 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_R; break;
9958 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_R; break;
9961 inst.instruction |= Rd | (Rn << 3);
9963 else
9965 switch (shift)
9967 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_I; break;
9968 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_I; break;
9969 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_I; break;
9972 if (inst.reloc.exp.X_op != O_constant)
9974 /* Value isn't known yet, create a dummy reloc and let reloc
9975 hacking fix it up. */
9976 inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
9978 else
9980 unsigned shift_value = inst.reloc.exp.X_add_number;
9982 if (shift_value > 32 || (shift_value == 32 && shift == THUMB_LSL))
9984 inst.error = _("invalid immediate for shift");
9985 return;
9988 /* Shifts of zero are handled by converting to LSL. */
9989 if (shift_value == 0)
9990 inst.instruction = T_OPCODE_LSL_I;
9992 /* Shifts of 32 are encoded as a shift of zero. */
9993 if (shift_value == 32)
9994 shift_value = 0;
9996 inst.instruction |= shift_value << 6;
9999 inst.instruction |= Rd | (Rs << 3);
10002 end_of_line (str);
10005 static void
10006 thumb_mov_compare (str, move)
10007 char * str;
10008 int move;
10010 int Rd, Rs = FAIL;
10012 skip_whitespace (str);
10014 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
10015 || skip_past_comma (&str) == FAIL)
10017 if (! inst.error)
10018 inst.error = BAD_ARGS;
10019 return;
10022 if (move != THUMB_CPY && is_immediate_prefix (*str))
10024 str++;
10025 if (my_get_expression (&inst.reloc.exp, &str))
10026 return;
10028 else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
10029 return;
10031 if (Rs != FAIL)
10033 if (move != THUMB_CPY && Rs < 8 && Rd < 8)
10035 if (move == THUMB_MOVE)
10036 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
10037 since a MOV instruction produces unpredictable results. */
10038 inst.instruction = T_OPCODE_ADD_I3;
10039 else
10040 inst.instruction = T_OPCODE_CMP_LR;
10041 inst.instruction |= Rd | (Rs << 3);
10043 else
10045 if (move == THUMB_MOVE)
10046 inst.instruction = T_OPCODE_MOV_HR;
10047 else if (move != THUMB_CPY)
10048 inst.instruction = T_OPCODE_CMP_HR;
10050 if (Rd > 7)
10051 inst.instruction |= THUMB_H1;
10053 if (Rs > 7)
10054 inst.instruction |= THUMB_H2;
10056 inst.instruction |= (Rd & 7) | ((Rs & 7) << 3);
10059 else
10061 if (Rd > 7)
10063 inst.error = _("only lo regs allowed with immediate");
10064 return;
10067 if (move == THUMB_MOVE)
10068 inst.instruction = T_OPCODE_MOV_I8;
10069 else
10070 inst.instruction = T_OPCODE_CMP_I8;
10072 inst.instruction |= Rd << 8;
10074 if (inst.reloc.exp.X_op != O_constant)
10075 inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
10076 else
10078 unsigned value = inst.reloc.exp.X_add_number;
10080 if (value > 255)
10082 inst.error = _("invalid immediate");
10083 return;
10086 inst.instruction |= value;
10090 end_of_line (str);
10093 static void
10094 thumb_load_store (str, load_store, size)
10095 char * str;
10096 int load_store;
10097 int size;
10099 int Rd, Rb, Ro = FAIL;
10101 skip_whitespace (str);
10103 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
10104 || skip_past_comma (&str) == FAIL)
10106 if (! inst.error)
10107 inst.error = BAD_ARGS;
10108 return;
10111 if (*str == '[')
10113 str++;
10114 if ((Rb = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
10115 return;
10117 if (skip_past_comma (&str) != FAIL)
10119 if (is_immediate_prefix (*str))
10121 str++;
10122 if (my_get_expression (&inst.reloc.exp, &str))
10123 return;
10125 else if ((Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
10126 return;
10128 else
10130 inst.reloc.exp.X_op = O_constant;
10131 inst.reloc.exp.X_add_number = 0;
10134 if (*str != ']')
10136 inst.error = _("expected ']'");
10137 return;
10139 str++;
10141 else if (*str == '=')
10143 if (load_store != THUMB_LOAD)
10145 inst.error = _("invalid pseudo operation");
10146 return;
10149 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
10150 str++;
10152 skip_whitespace (str);
10154 if (my_get_expression (& inst.reloc.exp, & str))
10155 return;
10157 end_of_line (str);
10159 if ( inst.reloc.exp.X_op != O_constant
10160 && inst.reloc.exp.X_op != O_symbol)
10162 inst.error = "Constant expression expected";
10163 return;
10166 if (inst.reloc.exp.X_op == O_constant
10167 && ((inst.reloc.exp.X_add_number & ~0xFF) == 0))
10169 /* This can be done with a mov instruction. */
10171 inst.instruction = T_OPCODE_MOV_I8 | (Rd << 8);
10172 inst.instruction |= inst.reloc.exp.X_add_number;
10173 return;
10176 /* Insert into literal pool. */
10177 if (add_to_lit_pool () == FAIL)
10179 if (!inst.error)
10180 inst.error = "literal pool insertion failed";
10181 return;
10184 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10185 inst.reloc.pc_rel = 1;
10186 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
10187 /* Adjust ARM pipeline offset to Thumb. */
10188 inst.reloc.exp.X_add_number += 4;
10190 return;
10192 else
10194 if (my_get_expression (&inst.reloc.exp, &str))
10195 return;
10197 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
10198 inst.reloc.pc_rel = 1;
10199 inst.reloc.exp.X_add_number -= 4; /* Pipeline offset. */
10200 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10201 end_of_line (str);
10202 return;
10205 if (Rb == REG_PC || Rb == REG_SP)
10207 if (size != THUMB_WORD)
10209 inst.error = _("byte or halfword not valid for base register");
10210 return;
10212 else if (Rb == REG_PC && load_store != THUMB_LOAD)
10214 inst.error = _("r15 based store not allowed");
10215 return;
10217 else if (Ro != FAIL)
10219 inst.error = _("invalid base register for register offset");
10220 return;
10223 if (Rb == REG_PC)
10224 inst.instruction = T_OPCODE_LDR_PC;
10225 else if (load_store == THUMB_LOAD)
10226 inst.instruction = T_OPCODE_LDR_SP;
10227 else
10228 inst.instruction = T_OPCODE_STR_SP;
10230 inst.instruction |= Rd << 8;
10231 if (inst.reloc.exp.X_op == O_constant)
10233 unsigned offset = inst.reloc.exp.X_add_number;
10235 if (offset & ~0x3fc)
10237 inst.error = _("invalid offset");
10238 return;
10241 inst.instruction |= offset >> 2;
10243 else
10244 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10246 else if (Rb > 7)
10248 inst.error = _("invalid base register in load/store");
10249 return;
10251 else if (Ro == FAIL)
10253 /* Immediate offset. */
10254 if (size == THUMB_WORD)
10255 inst.instruction = (load_store == THUMB_LOAD
10256 ? T_OPCODE_LDR_IW : T_OPCODE_STR_IW);
10257 else if (size == THUMB_HALFWORD)
10258 inst.instruction = (load_store == THUMB_LOAD
10259 ? T_OPCODE_LDR_IH : T_OPCODE_STR_IH);
10260 else
10261 inst.instruction = (load_store == THUMB_LOAD
10262 ? T_OPCODE_LDR_IB : T_OPCODE_STR_IB);
10264 inst.instruction |= Rd | (Rb << 3);
10266 if (inst.reloc.exp.X_op == O_constant)
10268 unsigned offset = inst.reloc.exp.X_add_number;
10270 if (offset & ~(0x1f << size))
10272 inst.error = _("invalid offset");
10273 return;
10275 inst.instruction |= (offset >> size) << 6;
10277 else
10278 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10280 else
10282 /* Register offset. */
10283 if (size == THUMB_WORD)
10284 inst.instruction = (load_store == THUMB_LOAD
10285 ? T_OPCODE_LDR_RW : T_OPCODE_STR_RW);
10286 else if (size == THUMB_HALFWORD)
10287 inst.instruction = (load_store == THUMB_LOAD
10288 ? T_OPCODE_LDR_RH : T_OPCODE_STR_RH);
10289 else
10290 inst.instruction = (load_store == THUMB_LOAD
10291 ? T_OPCODE_LDR_RB : T_OPCODE_STR_RB);
10293 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
10296 end_of_line (str);
10299 /* A register must be given at this point.
10301 Shift is the place to put it in inst.instruction.
10303 Restores input start point on err.
10304 Returns the reg#, or FAIL. */
10306 static int
10307 mav_reg_required_here (str, shift, regtype)
10308 char ** str;
10309 int shift;
10310 enum arm_reg_type regtype;
10312 int reg;
10313 char *start = *str;
10315 if ((reg = arm_reg_parse (str, all_reg_maps[regtype].htab)) != FAIL)
10317 if (shift >= 0)
10318 inst.instruction |= reg << shift;
10320 return reg;
10323 /* Restore the start point. */
10324 *str = start;
10326 /* In the few cases where we might be able to accept something else
10327 this error can be overridden. */
10328 inst.error = _(all_reg_maps[regtype].expected);
10330 return FAIL;
10333 /* Cirrus Maverick Instructions. */
10335 /* Wrapper functions. */
10337 static void
10338 do_mav_binops_1a (str)
10339 char * str;
10341 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVF);
10344 static void
10345 do_mav_binops_1b (str)
10346 char * str;
10348 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVD);
10351 static void
10352 do_mav_binops_1c (str)
10353 char * str;
10355 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVDX);
10358 static void
10359 do_mav_binops_1d (str)
10360 char * str;
10362 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVF);
10365 static void
10366 do_mav_binops_1e (str)
10367 char * str;
10369 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVD);
10372 static void
10373 do_mav_binops_1f (str)
10374 char * str;
10376 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVF);
10379 static void
10380 do_mav_binops_1g (str)
10381 char * str;
10383 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVD);
10386 static void
10387 do_mav_binops_1h (str)
10388 char * str;
10390 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVFX);
10393 static void
10394 do_mav_binops_1i (str)
10395 char * str;
10397 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVFX);
10400 static void
10401 do_mav_binops_1j (str)
10402 char * str;
10404 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVDX);
10407 static void
10408 do_mav_binops_1k (str)
10409 char * str;
10411 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVDX);
10414 static void
10415 do_mav_binops_1l (str)
10416 char * str;
10418 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVF);
10421 static void
10422 do_mav_binops_1m (str)
10423 char * str;
10425 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVD);
10428 static void
10429 do_mav_binops_1n (str)
10430 char * str;
10432 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVFX);
10435 static void
10436 do_mav_binops_1o (str)
10437 char * str;
10439 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVDX, REG_TYPE_MVDX);
10442 static void
10443 do_mav_binops_2a (str)
10444 char * str;
10446 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVF, REG_TYPE_RN);
10449 static void
10450 do_mav_binops_2b (str)
10451 char * str;
10453 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVD, REG_TYPE_RN);
10456 static void
10457 do_mav_binops_2c (str)
10458 char * str;
10460 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVDX, REG_TYPE_RN);
10463 static void
10464 do_mav_binops_3a (str)
10465 char * str;
10467 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVFX);
10470 static void
10471 do_mav_binops_3b (str)
10472 char * str;
10474 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVFX, REG_TYPE_MVAX);
10477 static void
10478 do_mav_binops_3c (str)
10479 char * str;
10481 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVDX);
10484 static void
10485 do_mav_binops_3d (str)
10486 char * str;
10488 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVDX, REG_TYPE_MVAX);
10491 static void
10492 do_mav_triple_4a (str)
10493 char * str;
10495 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_RN);
10498 static void
10499 do_mav_triple_4b (str)
10500 char * str;
10502 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_RN);
10505 static void
10506 do_mav_triple_5a (str)
10507 char * str;
10509 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVF, REG_TYPE_MVF);
10512 static void
10513 do_mav_triple_5b (str)
10514 char * str;
10516 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVD, REG_TYPE_MVD);
10519 static void
10520 do_mav_triple_5c (str)
10521 char * str;
10523 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVFX, REG_TYPE_MVFX);
10526 static void
10527 do_mav_triple_5d (str)
10528 char * str;
10530 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVDX, REG_TYPE_MVDX);
10533 static void
10534 do_mav_triple_5e (str)
10535 char * str;
10537 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVF, REG_TYPE_MVF, REG_TYPE_MVF);
10540 static void
10541 do_mav_triple_5f (str)
10542 char * str;
10544 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVD, REG_TYPE_MVD, REG_TYPE_MVD);
10547 static void
10548 do_mav_triple_5g (str)
10549 char * str;
10551 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_MVFX);
10554 static void
10555 do_mav_triple_5h (str)
10556 char * str;
10558 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_MVDX);
10561 static void
10562 do_mav_quad_6a (str)
10563 char * str;
10565 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVFX, REG_TYPE_MVFX,
10566 REG_TYPE_MVFX);
10569 static void
10570 do_mav_quad_6b (str)
10571 char * str;
10573 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVAX, REG_TYPE_MVFX,
10574 REG_TYPE_MVFX);
10577 /* cfmvsc32<cond> DSPSC,MVDX[15:0]. */
10578 static void
10579 do_mav_dspsc_1 (str)
10580 char * str;
10582 skip_whitespace (str);
10584 /* cfmvsc32. */
10585 if (mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL
10586 || skip_past_comma (&str) == FAIL
10587 || mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL)
10589 if (!inst.error)
10590 inst.error = BAD_ARGS;
10592 return;
10595 end_of_line (str);
10598 /* cfmv32sc<cond> MVDX[15:0],DSPSC. */
10599 static void
10600 do_mav_dspsc_2 (str)
10601 char * str;
10603 skip_whitespace (str);
10605 /* cfmv32sc. */
10606 if (mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL
10607 || skip_past_comma (&str) == FAIL
10608 || mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL)
10610 if (!inst.error)
10611 inst.error = BAD_ARGS;
10613 return;
10616 end_of_line (str);
10619 static void
10620 do_mav_shift_1 (str)
10621 char * str;
10623 do_mav_shift (str, REG_TYPE_MVFX, REG_TYPE_MVFX);
10626 static void
10627 do_mav_shift_2 (str)
10628 char * str;
10630 do_mav_shift (str, REG_TYPE_MVDX, REG_TYPE_MVDX);
10633 static void
10634 do_mav_ldst_1 (str)
10635 char * str;
10637 do_mav_ldst (str, REG_TYPE_MVF);
10640 static void
10641 do_mav_ldst_2 (str)
10642 char * str;
10644 do_mav_ldst (str, REG_TYPE_MVD);
10647 static void
10648 do_mav_ldst_3 (str)
10649 char * str;
10651 do_mav_ldst (str, REG_TYPE_MVFX);
10654 static void
10655 do_mav_ldst_4 (str)
10656 char * str;
10658 do_mav_ldst (str, REG_TYPE_MVDX);
10661 /* Isnsn like "foo X,Y". */
10663 static void
10664 do_mav_binops (str, mode, reg0, reg1)
10665 char * str;
10666 int mode;
10667 enum arm_reg_type reg0;
10668 enum arm_reg_type reg1;
10670 int shift0, shift1;
10672 shift0 = mode & 0xff;
10673 shift1 = (mode >> 8) & 0xff;
10675 skip_whitespace (str);
10677 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
10678 || skip_past_comma (&str) == FAIL
10679 || mav_reg_required_here (&str, shift1, reg1) == FAIL)
10681 if (!inst.error)
10682 inst.error = BAD_ARGS;
10684 else
10685 end_of_line (str);
10688 /* Isnsn like "foo X,Y,Z". */
10690 static void
10691 do_mav_triple (str, mode, reg0, reg1, reg2)
10692 char * str;
10693 int mode;
10694 enum arm_reg_type reg0;
10695 enum arm_reg_type reg1;
10696 enum arm_reg_type reg2;
10698 int shift0, shift1, shift2;
10700 shift0 = mode & 0xff;
10701 shift1 = (mode >> 8) & 0xff;
10702 shift2 = (mode >> 16) & 0xff;
10704 skip_whitespace (str);
10706 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
10707 || skip_past_comma (&str) == FAIL
10708 || mav_reg_required_here (&str, shift1, reg1) == FAIL
10709 || skip_past_comma (&str) == FAIL
10710 || mav_reg_required_here (&str, shift2, reg2) == FAIL)
10712 if (!inst.error)
10713 inst.error = BAD_ARGS;
10715 else
10716 end_of_line (str);
10719 /* Isnsn like "foo W,X,Y,Z".
10720 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
10722 static void
10723 do_mav_quad (str, mode, reg0, reg1, reg2, reg3)
10724 char * str;
10725 int mode;
10726 enum arm_reg_type reg0;
10727 enum arm_reg_type reg1;
10728 enum arm_reg_type reg2;
10729 enum arm_reg_type reg3;
10731 int shift0, shift1, shift2, shift3;
10733 shift0= mode & 0xff;
10734 shift1 = (mode >> 8) & 0xff;
10735 shift2 = (mode >> 16) & 0xff;
10736 shift3 = (mode >> 24) & 0xff;
10738 skip_whitespace (str);
10740 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
10741 || skip_past_comma (&str) == FAIL
10742 || mav_reg_required_here (&str, shift1, reg1) == FAIL
10743 || skip_past_comma (&str) == FAIL
10744 || mav_reg_required_here (&str, shift2, reg2) == FAIL
10745 || skip_past_comma (&str) == FAIL
10746 || mav_reg_required_here (&str, shift3, reg3) == FAIL)
10748 if (!inst.error)
10749 inst.error = BAD_ARGS;
10751 else
10752 end_of_line (str);
10755 /* Maverick shift immediate instructions.
10756 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
10757 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
10759 static void
10760 do_mav_shift (str, reg0, reg1)
10761 char * str;
10762 enum arm_reg_type reg0;
10763 enum arm_reg_type reg1;
10765 int error;
10766 int imm, neg = 0;
10768 skip_whitespace (str);
10770 error = 0;
10772 if (mav_reg_required_here (&str, 12, reg0) == FAIL
10773 || skip_past_comma (&str) == FAIL
10774 || mav_reg_required_here (&str, 16, reg1) == FAIL
10775 || skip_past_comma (&str) == FAIL)
10777 if (!inst.error)
10778 inst.error = BAD_ARGS;
10779 return;
10782 /* Calculate the immediate operand.
10783 The operand is a 7bit signed number. */
10784 skip_whitespace (str);
10786 if (*str == '#')
10787 ++str;
10789 if (!ISDIGIT (*str) && *str != '-')
10791 inst.error = _("expecting immediate, 7bit operand");
10792 return;
10795 if (*str == '-')
10797 neg = 1;
10798 ++str;
10801 for (imm = 0; *str && ISDIGIT (*str); ++str)
10802 imm = imm * 10 + *str - '0';
10804 if (imm > 64)
10806 inst.error = _("immediate out of range");
10807 return;
10810 /* Make negative imm's into 7bit signed numbers. */
10811 if (neg)
10813 imm = -imm;
10814 imm &= 0x0000007f;
10817 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
10818 Bits 5-7 of the insn should have bits 4-6 of the immediate.
10819 Bit 4 should be 0. */
10820 imm = (imm & 0xf) | ((imm & 0x70) << 1);
10822 inst.instruction |= imm;
10823 end_of_line (str);
10826 static int
10827 mav_parse_offset (str, negative)
10828 char ** str;
10829 int *negative;
10831 char * p = *str;
10832 int offset;
10834 *negative = 0;
10836 skip_whitespace (p);
10838 if (*p == '#')
10839 ++p;
10841 if (*p == '-')
10843 *negative = 1;
10844 ++p;
10847 if (!ISDIGIT (*p))
10849 inst.error = _("offset expected");
10850 return 0;
10853 for (offset = 0; *p && ISDIGIT (*p); ++p)
10854 offset = offset * 10 + *p - '0';
10856 if (offset > 0x3fc)
10858 inst.error = _("offset out of range");
10859 return 0;
10861 if (offset & 0x3)
10863 inst.error = _("offset not a multiple of 4");
10864 return 0;
10867 *str = p;
10869 return *negative ? -offset : offset;
10872 /* Maverick load/store instructions.
10873 <insn><cond> CRd,[Rn,<offset>]{!}.
10874 <insn><cond> CRd,[Rn],<offset>. */
10876 static void
10877 do_mav_ldst (str, reg0)
10878 char * str;
10879 enum arm_reg_type reg0;
10881 int offset, negative;
10883 skip_whitespace (str);
10885 if (mav_reg_required_here (&str, 12, reg0) == FAIL
10886 || skip_past_comma (&str) == FAIL
10887 || *str++ != '['
10888 || reg_required_here (&str, 16) == FAIL)
10889 goto fail_ldst;
10891 if (skip_past_comma (&str) == SUCCESS)
10893 /* You are here: "<offset>]{!}". */
10894 inst.instruction |= PRE_INDEX;
10896 offset = mav_parse_offset (&str, &negative);
10898 if (inst.error)
10899 return;
10901 if (*str++ != ']')
10903 inst.error = _("missing ]");
10904 return;
10907 if (*str == '!')
10909 inst.instruction |= WRITE_BACK;
10910 ++str;
10913 else
10915 /* You are here: "], <offset>". */
10916 if (*str++ != ']')
10918 inst.error = _("missing ]");
10919 return;
10922 if (skip_past_comma (&str) == FAIL
10923 || (offset = mav_parse_offset (&str, &negative), inst.error))
10924 goto fail_ldst;
10926 inst.instruction |= CP_T_WB; /* Post indexed, set bit W. */
10929 if (negative)
10930 offset = -offset;
10931 else
10932 inst.instruction |= CP_T_UD; /* Positive, so set bit U. */
10934 inst.instruction |= offset >> 2;
10935 end_of_line (str);
10936 return;
10938 fail_ldst:
10939 if (!inst.error)
10940 inst.error = BAD_ARGS;
10943 static void
10944 do_t_nop (str)
10945 char * str;
10947 /* Do nothing. */
10948 end_of_line (str);
10951 /* Handle the Format 4 instructions that do not have equivalents in other
10952 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
10953 BIC and MVN. */
10955 static void
10956 do_t_arit (str)
10957 char * str;
10959 int Rd, Rs, Rn;
10961 skip_whitespace (str);
10963 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
10964 || skip_past_comma (&str) == FAIL
10965 || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
10967 inst.error = BAD_ARGS;
10968 return;
10971 if (skip_past_comma (&str) != FAIL)
10973 /* Three operand format not allowed for TST, CMN, NEG and MVN.
10974 (It isn't allowed for CMP either, but that isn't handled by this
10975 function.) */
10976 if (inst.instruction == T_OPCODE_TST
10977 || inst.instruction == T_OPCODE_CMN
10978 || inst.instruction == T_OPCODE_NEG
10979 || inst.instruction == T_OPCODE_MVN)
10981 inst.error = BAD_ARGS;
10982 return;
10985 if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
10986 return;
10988 if (Rs != Rd)
10990 inst.error = _("dest and source1 must be the same register");
10991 return;
10993 Rs = Rn;
10996 if (inst.instruction == T_OPCODE_MUL
10997 && Rs == Rd)
10998 as_tsktsk (_("Rs and Rd must be different in MUL"));
11000 inst.instruction |= Rd | (Rs << 3);
11001 end_of_line (str);
11004 static void
11005 do_t_add (str)
11006 char * str;
11008 thumb_add_sub (str, 0);
11011 static void
11012 do_t_asr (str)
11013 char * str;
11015 thumb_shift (str, THUMB_ASR);
11018 static void
11019 do_t_branch9 (str)
11020 char * str;
11022 if (my_get_expression (&inst.reloc.exp, &str))
11023 return;
11024 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
11025 inst.reloc.pc_rel = 1;
11026 end_of_line (str);
11029 static void
11030 do_t_branch12 (str)
11031 char * str;
11033 if (my_get_expression (&inst.reloc.exp, &str))
11034 return;
11035 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
11036 inst.reloc.pc_rel = 1;
11037 end_of_line (str);
11040 /* Find the real, Thumb encoded start of a Thumb function. */
11042 static symbolS *
11043 find_real_start (symbolP)
11044 symbolS * symbolP;
11046 char * real_start;
11047 const char * name = S_GET_NAME (symbolP);
11048 symbolS * new_target;
11050 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
11051 #define STUB_NAME ".real_start_of"
11053 if (name == NULL)
11054 abort ();
11056 /* Names that start with '.' are local labels, not function entry points.
11057 The compiler may generate BL instructions to these labels because it
11058 needs to perform a branch to a far away location. */
11059 if (name[0] == '.')
11060 return symbolP;
11062 real_start = malloc (strlen (name) + strlen (STUB_NAME) + 1);
11063 sprintf (real_start, "%s%s", STUB_NAME, name);
11065 new_target = symbol_find (real_start);
11067 if (new_target == NULL)
11069 as_warn ("Failed to find real start of function: %s\n", name);
11070 new_target = symbolP;
11073 free (real_start);
11075 return new_target;
11078 static void
11079 do_t_branch23 (str)
11080 char * str;
11082 if (my_get_expression (& inst.reloc.exp, & str))
11083 return;
11085 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH23;
11086 inst.reloc.pc_rel = 1;
11087 end_of_line (str);
11089 /* If the destination of the branch is a defined symbol which does not have
11090 the THUMB_FUNC attribute, then we must be calling a function which has
11091 the (interfacearm) attribute. We look for the Thumb entry point to that
11092 function and change the branch to refer to that function instead. */
11093 if ( inst.reloc.exp.X_op == O_symbol
11094 && inst.reloc.exp.X_add_symbol != NULL
11095 && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
11096 && ! THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
11097 inst.reloc.exp.X_add_symbol =
11098 find_real_start (inst.reloc.exp.X_add_symbol);
11101 static void
11102 do_t_bx (str)
11103 char * str;
11105 int reg;
11107 skip_whitespace (str);
11109 if ((reg = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
11110 return;
11112 /* This sets THUMB_H2 from the top bit of reg. */
11113 inst.instruction |= reg << 3;
11115 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
11116 should cause the alignment to be checked once it is known. This is
11117 because BX PC only works if the instruction is word aligned. */
11119 end_of_line (str);
11122 static void
11123 do_t_compare (str)
11124 char * str;
11126 thumb_mov_compare (str, THUMB_COMPARE);
11129 static void
11130 do_t_ldmstm (str)
11131 char * str;
11133 int Rb;
11134 long range;
11136 skip_whitespace (str);
11138 if ((Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
11139 return;
11141 if (*str != '!')
11142 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
11143 else
11144 str++;
11146 if (skip_past_comma (&str) == FAIL
11147 || (range = reg_list (&str)) == FAIL)
11149 if (! inst.error)
11150 inst.error = BAD_ARGS;
11151 return;
11154 if (inst.reloc.type != BFD_RELOC_NONE)
11156 /* This really doesn't seem worth it. */
11157 inst.reloc.type = BFD_RELOC_NONE;
11158 inst.error = _("expression too complex");
11159 return;
11162 if (range & ~0xff)
11164 inst.error = _("only lo-regs valid in load/store multiple");
11165 return;
11168 inst.instruction |= (Rb << 8) | range;
11169 end_of_line (str);
11172 static void
11173 do_t_ldr (str)
11174 char * str;
11176 thumb_load_store (str, THUMB_LOAD, THUMB_WORD);
11179 static void
11180 do_t_ldrb (str)
11181 char * str;
11183 thumb_load_store (str, THUMB_LOAD, THUMB_BYTE);
11186 static void
11187 do_t_ldrh (str)
11188 char * str;
11190 thumb_load_store (str, THUMB_LOAD, THUMB_HALFWORD);
11193 static void
11194 do_t_lds (str)
11195 char * str;
11197 int Rd, Rb, Ro;
11199 skip_whitespace (str);
11201 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
11202 || skip_past_comma (&str) == FAIL
11203 || *str++ != '['
11204 || (Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL
11205 || skip_past_comma (&str) == FAIL
11206 || (Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL
11207 || *str++ != ']')
11209 if (! inst.error)
11210 inst.error = _("syntax: ldrs[b] Rd, [Rb, Ro]");
11211 return;
11214 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
11215 end_of_line (str);
11218 static void
11219 do_t_lsl (str)
11220 char * str;
11222 thumb_shift (str, THUMB_LSL);
11225 static void
11226 do_t_lsr (str)
11227 char * str;
11229 thumb_shift (str, THUMB_LSR);
11232 static void
11233 do_t_mov (str)
11234 char * str;
11236 thumb_mov_compare (str, THUMB_MOVE);
11239 static void
11240 do_t_push_pop (str)
11241 char * str;
11243 long range;
11245 skip_whitespace (str);
11247 if ((range = reg_list (&str)) == FAIL)
11249 if (! inst.error)
11250 inst.error = BAD_ARGS;
11251 return;
11254 if (inst.reloc.type != BFD_RELOC_NONE)
11256 /* This really doesn't seem worth it. */
11257 inst.reloc.type = BFD_RELOC_NONE;
11258 inst.error = _("expression too complex");
11259 return;
11262 if (range & ~0xff)
11264 if ((inst.instruction == T_OPCODE_PUSH
11265 && (range & ~0xff) == 1 << REG_LR)
11266 || (inst.instruction == T_OPCODE_POP
11267 && (range & ~0xff) == 1 << REG_PC))
11269 inst.instruction |= THUMB_PP_PC_LR;
11270 range &= 0xff;
11272 else
11274 inst.error = _("invalid register list to push/pop instruction");
11275 return;
11279 inst.instruction |= range;
11280 end_of_line (str);
11283 static void
11284 do_t_str (str)
11285 char * str;
11287 thumb_load_store (str, THUMB_STORE, THUMB_WORD);
11290 static void
11291 do_t_strb (str)
11292 char * str;
11294 thumb_load_store (str, THUMB_STORE, THUMB_BYTE);
11297 static void
11298 do_t_strh (str)
11299 char * str;
11301 thumb_load_store (str, THUMB_STORE, THUMB_HALFWORD);
11304 static void
11305 do_t_sub (str)
11306 char * str;
11308 thumb_add_sub (str, 1);
11311 static void
11312 do_t_swi (str)
11313 char * str;
11315 skip_whitespace (str);
11317 if (my_get_expression (&inst.reloc.exp, &str))
11318 return;
11320 inst.reloc.type = BFD_RELOC_ARM_SWI;
11321 end_of_line (str);
11324 static void
11325 do_t_adr (str)
11326 char * str;
11328 int reg;
11330 /* This is a pseudo-op of the form "adr rd, label" to be converted
11331 into a relative address of the form "add rd, pc, #label-.-4". */
11332 skip_whitespace (str);
11334 /* Store Rd in temporary location inside instruction. */
11335 if ((reg = reg_required_here (&str, 4)) == FAIL
11336 || (reg > 7) /* For Thumb reg must be r0..r7. */
11337 || skip_past_comma (&str) == FAIL
11338 || my_get_expression (&inst.reloc.exp, &str))
11340 if (!inst.error)
11341 inst.error = BAD_ARGS;
11342 return;
11345 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
11346 inst.reloc.exp.X_add_number -= 4; /* PC relative adjust. */
11347 inst.reloc.pc_rel = 1;
11348 inst.instruction |= REG_PC; /* Rd is already placed into the instruction. */
11350 end_of_line (str);
11353 static void
11354 insert_reg (r, htab)
11355 const struct reg_entry *r;
11356 struct hash_control *htab;
11358 int len = strlen (r->name) + 2;
11359 char * buf = (char *) xmalloc (len);
11360 char * buf2 = (char *) xmalloc (len);
11361 int i = 0;
11363 #ifdef REGISTER_PREFIX
11364 buf[i++] = REGISTER_PREFIX;
11365 #endif
11367 strcpy (buf + i, r->name);
11369 for (i = 0; buf[i]; i++)
11370 buf2[i] = TOUPPER (buf[i]);
11372 buf2[i] = '\0';
11374 hash_insert (htab, buf, (PTR) r);
11375 hash_insert (htab, buf2, (PTR) r);
11378 static void
11379 build_reg_hsh (map)
11380 struct reg_map *map;
11382 const struct reg_entry *r;
11384 if ((map->htab = hash_new ()) == NULL)
11385 as_fatal (_("virtual memory exhausted"));
11387 for (r = map->names; r->name != NULL; r++)
11388 insert_reg (r, map->htab);
11391 static void
11392 insert_reg_alias (str, regnum, htab)
11393 char *str;
11394 int regnum;
11395 struct hash_control *htab;
11397 const char *error;
11398 struct reg_entry *new = xmalloc (sizeof (struct reg_entry));
11399 const char *name = xmalloc (strlen (str) + 1);
11401 strcpy ((char *) name, str);
11403 new->name = name;
11404 new->number = regnum;
11405 new->builtin = FALSE;
11407 error = hash_insert (htab, name, (PTR) new);
11408 if (error)
11410 as_bad (_("failed to create an alias for %s, reason: %s"),
11411 str, error);
11412 free ((char *) name);
11413 free (new);
11417 /* Look for the .req directive. This is of the form:
11419 new_register_name .req existing_register_name
11421 If we find one, or if it looks sufficiently like one that we want to
11422 handle any error here, return non-zero. Otherwise return zero. */
11423 static int
11424 create_register_alias (newname, p)
11425 char *newname;
11426 char *p;
11428 char *q;
11429 char c;
11431 q = p;
11432 skip_whitespace (q);
11434 c = *p;
11435 *p = '\0';
11437 if (*q && !strncmp (q, ".req ", 5))
11439 char *copy_of_str;
11440 char *r;
11442 #ifndef IGNORE_OPCODE_CASE
11443 newname = original_case_string;
11444 #endif
11445 copy_of_str = newname;
11447 q += 4;
11448 skip_whitespace (q);
11450 for (r = q; *r != '\0'; r++)
11451 if (*r == ' ')
11452 break;
11454 if (r != q)
11456 enum arm_reg_type new_type, old_type;
11457 int old_regno;
11458 char d = *r;
11460 *r = '\0';
11461 old_type = arm_reg_parse_any (q);
11462 *r = d;
11464 new_type = arm_reg_parse_any (newname);
11466 if (new_type == REG_TYPE_MAX)
11468 if (old_type != REG_TYPE_MAX)
11470 old_regno = arm_reg_parse (&q, all_reg_maps[old_type].htab);
11471 insert_reg_alias (newname, old_regno,
11472 all_reg_maps[old_type].htab);
11474 else
11475 as_warn (_("register '%s' does not exist\n"), q);
11477 else if (old_type == REG_TYPE_MAX)
11479 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
11480 copy_of_str, q);
11482 else
11484 /* Do not warn about redefinitions to the same alias. */
11485 if (new_type != old_type
11486 || (arm_reg_parse (&q, all_reg_maps[old_type].htab)
11487 != arm_reg_parse (&q, all_reg_maps[new_type].htab)))
11488 as_warn (_("ignoring redefinition of register alias '%s'"),
11489 copy_of_str);
11493 else
11494 as_warn (_("ignoring incomplete .req pseuso op"));
11496 *p = c;
11497 return 1;
11500 *p = c;
11501 return 0;
11504 static void
11505 set_constant_flonums ()
11507 int i;
11509 for (i = 0; i < NUM_FLOAT_VALS; i++)
11510 if (atof_ieee ((char *) fp_const[i], 'x', fp_values[i]) == NULL)
11511 abort ();
11514 /* Iterate over the base tables to create the instruction patterns. */
11515 static void
11516 build_arm_ops_hsh ()
11518 unsigned int i;
11519 unsigned int j;
11520 static struct obstack insn_obstack;
11522 obstack_begin (&insn_obstack, 4000);
11524 for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
11526 const struct asm_opcode *insn = insns + i;
11528 if (insn->cond_offset != 0)
11530 /* Insn supports conditional execution. Build the varaints
11531 and insert them in the hash table. */
11532 for (j = 0; j < sizeof (conds) / sizeof (struct asm_cond); j++)
11534 unsigned len = strlen (insn->template);
11535 struct asm_opcode *new;
11536 char *template;
11538 new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
11539 /* All condition codes are two characters. */
11540 template = obstack_alloc (&insn_obstack, len + 3);
11542 strncpy (template, insn->template, insn->cond_offset);
11543 strcpy (template + insn->cond_offset, conds[j].template);
11544 if (len > insn->cond_offset)
11545 strcpy (template + insn->cond_offset + 2,
11546 insn->template + insn->cond_offset);
11547 new->template = template;
11548 new->cond_offset = 0;
11549 new->variant = insn->variant;
11550 new->parms = insn->parms;
11551 new->value = (insn->value & ~COND_MASK) | conds[j].value;
11553 hash_insert (arm_ops_hsh, new->template, (PTR) new);
11556 /* Finally, insert the unconditional insn in the table directly;
11557 no need to build a copy. */
11558 hash_insert (arm_ops_hsh, insn->template, (PTR) insn);
11562 #if 0 /* Suppressed - for now. */
11563 #if defined OBJ_ELF || defined OBJ_COFF
11565 #ifdef OBJ_ELF
11566 #define arm_Note Elf_External_Note
11567 #else
11568 typedef struct
11570 unsigned char namesz[4]; /* Size of entry's owner string. */
11571 unsigned char descsz[4]; /* Size of the note descriptor. */
11572 unsigned char type[4]; /* Interpretation of the descriptor. */
11573 char name[1]; /* Start of the name+desc data. */
11574 } arm_Note;
11575 #endif
11577 /* The description is kept to a fix sized in order to make updating
11578 it and merging it easier. */
11579 #define ARM_NOTE_DESCRIPTION_LENGTH 8
11581 static void
11582 arm_add_note (name, description, type)
11583 const char * name;
11584 const char * description;
11585 unsigned int type;
11587 arm_Note note ATTRIBUTE_UNUSED;
11588 char * p;
11589 unsigned int name_len;
11591 name_len = (strlen (name) + 1 + 3) & ~3;
11593 p = frag_more (sizeof (note.namesz));
11594 md_number_to_chars (p, (valueT) name_len, sizeof (note.namesz));
11596 p = frag_more (sizeof (note.descsz));
11597 md_number_to_chars (p, (valueT) ARM_NOTE_DESCRIPTION_LENGTH, sizeof (note.descsz));
11599 p = frag_more (sizeof (note.type));
11600 md_number_to_chars (p, (valueT) type, sizeof (note.type));
11602 p = frag_more (name_len);
11603 strcpy (p, name);
11605 p = frag_more (ARM_NOTE_DESCRIPTION_LENGTH);
11606 strncpy (p, description, ARM_NOTE_DESCRIPTION_LENGTH);
11607 frag_align (2, 0, 0);
11609 #endif
11610 #endif
11612 void
11613 md_begin ()
11615 unsigned mach;
11616 unsigned int i;
11618 if ( (arm_ops_hsh = hash_new ()) == NULL
11619 || (arm_tops_hsh = hash_new ()) == NULL
11620 || (arm_cond_hsh = hash_new ()) == NULL
11621 || (arm_shift_hsh = hash_new ()) == NULL
11622 || (arm_psr_hsh = hash_new ()) == NULL)
11623 as_fatal (_("virtual memory exhausted"));
11625 build_arm_ops_hsh ();
11626 for (i = 0; i < sizeof (tinsns) / sizeof (struct thumb_opcode); i++)
11627 hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
11628 for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
11629 hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
11630 for (i = 0; i < sizeof (shift_names) / sizeof (struct asm_shift_name); i++)
11631 hash_insert (arm_shift_hsh, shift_names[i].name, (PTR) (shift_names + i));
11632 for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
11633 hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
11635 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
11636 build_reg_hsh (all_reg_maps + i);
11638 set_constant_flonums ();
11640 /* Set the cpu variant based on the command-line options. We prefer
11641 -mcpu= over -march= if both are set (as for GCC); and we prefer
11642 -mfpu= over any other way of setting the floating point unit.
11643 Use of legacy options with new options are faulted. */
11644 if (legacy_cpu != -1)
11646 if (mcpu_cpu_opt != -1 || march_cpu_opt != -1)
11647 as_bad (_("use of old and new-style options to set CPU type"));
11649 mcpu_cpu_opt = legacy_cpu;
11651 else if (mcpu_cpu_opt == -1)
11652 mcpu_cpu_opt = march_cpu_opt;
11654 if (legacy_fpu != -1)
11656 if (mfpu_opt != -1)
11657 as_bad (_("use of old and new-style options to set FPU type"));
11659 mfpu_opt = legacy_fpu;
11661 else if (mfpu_opt == -1)
11663 #if !(defined (TE_LINUX) || defined (TE_NetBSD))
11664 /* Some environments specify a default FPU. If they don't, infer it
11665 from the processor. */
11666 if (mcpu_fpu_opt != -1)
11667 mfpu_opt = mcpu_fpu_opt;
11668 else
11669 mfpu_opt = march_fpu_opt;
11670 #else
11671 mfpu_opt = FPU_DEFAULT;
11672 #endif
11675 if (mfpu_opt == -1)
11677 if (mcpu_cpu_opt == -1)
11678 mfpu_opt = FPU_DEFAULT;
11679 else if (mcpu_cpu_opt & ARM_EXT_V5)
11680 mfpu_opt = FPU_ARCH_VFP_V2;
11681 else
11682 mfpu_opt = FPU_ARCH_FPA;
11685 if (mcpu_cpu_opt == -1)
11686 mcpu_cpu_opt = CPU_DEFAULT;
11688 cpu_variant = mcpu_cpu_opt | mfpu_opt;
11691 unsigned int flags = 0;
11693 #if defined OBJ_ELF
11694 flags = meabi_flags;
11696 switch (meabi_flags)
11698 case EF_ARM_EABI_UNKNOWN:
11699 #endif
11700 #if defined OBJ_COFF || defined OBJ_ELF
11701 /* Set the flags in the private structure. */
11702 if (uses_apcs_26) flags |= F_APCS26;
11703 if (support_interwork) flags |= F_INTERWORK;
11704 if (uses_apcs_float) flags |= F_APCS_FLOAT;
11705 if (pic_code) flags |= F_PIC;
11706 if ((cpu_variant & FPU_ANY) == FPU_NONE
11707 || (cpu_variant & FPU_ANY) == FPU_ARCH_VFP) /* VFP layout only. */
11708 flags |= F_SOFT_FLOAT;
11710 switch (mfloat_abi_opt)
11712 case ARM_FLOAT_ABI_SOFT:
11713 case ARM_FLOAT_ABI_SOFTFP:
11714 flags |= F_SOFT_FLOAT;
11715 break;
11717 case ARM_FLOAT_ABI_HARD:
11718 if (flags & F_SOFT_FLOAT)
11719 as_bad (_("hard-float conflicts with specified fpu"));
11720 break;
11723 /* Using VFP conventions (even if soft-float). */
11724 if (cpu_variant & FPU_VFP_EXT_NONE)
11725 flags |= F_VFP_FLOAT;
11726 #endif
11727 #if defined OBJ_ELF
11728 if (cpu_variant & FPU_ARCH_MAVERICK)
11729 flags |= EF_ARM_MAVERICK_FLOAT;
11730 break;
11732 case EF_ARM_EABI_VER3:
11733 /* No additional flags to set. */
11734 break;
11736 default:
11737 abort ();
11739 #endif
11740 #if defined OBJ_COFF || defined OBJ_ELF
11741 bfd_set_private_flags (stdoutput, flags);
11743 /* We have run out flags in the COFF header to encode the
11744 status of ATPCS support, so instead we create a dummy,
11745 empty, debug section called .arm.atpcs. */
11746 if (atpcs)
11748 asection * sec;
11750 sec = bfd_make_section (stdoutput, ".arm.atpcs");
11752 if (sec != NULL)
11754 bfd_set_section_flags
11755 (stdoutput, sec, SEC_READONLY | SEC_DEBUGGING /* | SEC_HAS_CONTENTS */);
11756 bfd_set_section_size (stdoutput, sec, 0);
11757 bfd_set_section_contents (stdoutput, sec, NULL, 0, 0);
11760 #endif
11763 /* Record the CPU type as well. */
11764 switch (cpu_variant & ARM_CPU_MASK)
11766 case ARM_2:
11767 mach = bfd_mach_arm_2;
11768 break;
11770 case ARM_3: /* Also ARM_250. */
11771 mach = bfd_mach_arm_2a;
11772 break;
11774 case ARM_6: /* Also ARM_7. */
11775 mach = bfd_mach_arm_3;
11776 break;
11778 default:
11779 mach = bfd_mach_arm_unknown;
11780 break;
11783 /* Catch special cases. */
11784 if (cpu_variant & ARM_CEXT_IWMMXT)
11785 mach = bfd_mach_arm_iWMMXt;
11786 else if (cpu_variant & ARM_CEXT_XSCALE)
11787 mach = bfd_mach_arm_XScale;
11788 else if (cpu_variant & ARM_CEXT_MAVERICK)
11789 mach = bfd_mach_arm_ep9312;
11790 else if (cpu_variant & ARM_EXT_V5E)
11791 mach = bfd_mach_arm_5TE;
11792 else if (cpu_variant & ARM_EXT_V5)
11794 if (cpu_variant & ARM_EXT_V4T)
11795 mach = bfd_mach_arm_5T;
11796 else
11797 mach = bfd_mach_arm_5;
11799 else if (cpu_variant & ARM_EXT_V4)
11801 if (cpu_variant & ARM_EXT_V4T)
11802 mach = bfd_mach_arm_4T;
11803 else
11804 mach = bfd_mach_arm_4;
11806 else if (cpu_variant & ARM_EXT_V3M)
11807 mach = bfd_mach_arm_3M;
11809 #if 0 /* Suppressed - for now. */
11810 #if defined (OBJ_ELF) || defined (OBJ_COFF)
11812 /* Create a .note section to fully identify this arm binary. */
11814 #define NOTE_ARCH_STRING "arch: "
11816 #if defined OBJ_COFF && ! defined NT_VERSION
11817 #define NT_VERSION 1
11818 #define NT_ARCH 2
11819 #endif
11822 segT current_seg = now_seg;
11823 subsegT current_subseg = now_subseg;
11824 asection * arm_arch;
11825 const char * arch_string;
11827 arm_arch = bfd_make_section_old_way (stdoutput, ARM_NOTE_SECTION);
11829 #ifdef OBJ_COFF
11830 bfd_set_section_flags (stdoutput, arm_arch,
11831 SEC_DATA | SEC_ALLOC | SEC_LOAD | SEC_LINK_ONCE \
11832 | SEC_HAS_CONTENTS);
11833 #else
11834 bfd_set_section_flags (stdoutput, arm_arch,
11835 SEC_READONLY | SEC_HAS_CONTENTS);
11836 #endif
11837 arm_arch->output_section = arm_arch;
11838 subseg_set (arm_arch, 0);
11840 switch (mach)
11842 default:
11843 case bfd_mach_arm_unknown: arch_string = "unknown"; break;
11844 case bfd_mach_arm_2: arch_string = "armv2"; break;
11845 case bfd_mach_arm_2a: arch_string = "armv2a"; break;
11846 case bfd_mach_arm_3: arch_string = "armv3"; break;
11847 case bfd_mach_arm_3M: arch_string = "armv3M"; break;
11848 case bfd_mach_arm_4: arch_string = "armv4"; break;
11849 case bfd_mach_arm_4T: arch_string = "armv4t"; break;
11850 case bfd_mach_arm_5: arch_string = "armv5"; break;
11851 case bfd_mach_arm_5T: arch_string = "armv5t"; break;
11852 case bfd_mach_arm_5TE: arch_string = "armv5te"; break;
11853 case bfd_mach_arm_XScale: arch_string = "XScale"; break;
11854 case bfd_mach_arm_ep9312: arch_string = "ep9312"; break;
11855 case bfd_mach_arm_iWMMXt: arch_string = "iWMMXt"; break;
11858 arm_add_note (NOTE_ARCH_STRING, arch_string, NT_ARCH);
11860 subseg_set (current_seg, current_subseg);
11862 #endif
11863 #endif /* Suppressed code. */
11865 bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
11868 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11869 for use in the a.out file, and stores them in the array pointed to by buf.
11870 This knows about the endian-ness of the target machine and does
11871 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11872 2 (short) and 4 (long) Floating numbers are put out as a series of
11873 LITTLENUMS (shorts, here at least). */
11875 void
11876 md_number_to_chars (buf, val, n)
11877 char * buf;
11878 valueT val;
11879 int n;
11881 if (target_big_endian)
11882 number_to_chars_bigendian (buf, val, n);
11883 else
11884 number_to_chars_littleendian (buf, val, n);
11887 static valueT
11888 md_chars_to_number (buf, n)
11889 char * buf;
11890 int n;
11892 valueT result = 0;
11893 unsigned char * where = (unsigned char *) buf;
11895 if (target_big_endian)
11897 while (n--)
11899 result <<= 8;
11900 result |= (*where++ & 255);
11903 else
11905 while (n--)
11907 result <<= 8;
11908 result |= (where[n] & 255);
11912 return result;
11915 /* Turn a string in input_line_pointer into a floating point constant
11916 of type TYPE, and store the appropriate bytes in *LITP. The number
11917 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11918 returned, or NULL on OK.
11920 Note that fp constants aren't represent in the normal way on the ARM.
11921 In big endian mode, things are as expected. However, in little endian
11922 mode fp constants are big-endian word-wise, and little-endian byte-wise
11923 within the words. For example, (double) 1.1 in big endian mode is
11924 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11925 the byte sequence 99 99 f1 3f 9a 99 99 99.
11927 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11929 char *
11930 md_atof (type, litP, sizeP)
11931 char type;
11932 char * litP;
11933 int * sizeP;
11935 int prec;
11936 LITTLENUM_TYPE words[MAX_LITTLENUMS];
11937 char *t;
11938 int i;
11940 switch (type)
11942 case 'f':
11943 case 'F':
11944 case 's':
11945 case 'S':
11946 prec = 2;
11947 break;
11949 case 'd':
11950 case 'D':
11951 case 'r':
11952 case 'R':
11953 prec = 4;
11954 break;
11956 case 'x':
11957 case 'X':
11958 prec = 6;
11959 break;
11961 case 'p':
11962 case 'P':
11963 prec = 6;
11964 break;
11966 default:
11967 *sizeP = 0;
11968 return _("bad call to MD_ATOF()");
11971 t = atof_ieee (input_line_pointer, type, words);
11972 if (t)
11973 input_line_pointer = t;
11974 *sizeP = prec * 2;
11976 if (target_big_endian)
11978 for (i = 0; i < prec; i++)
11980 md_number_to_chars (litP, (valueT) words[i], 2);
11981 litP += 2;
11984 else
11986 if (cpu_variant & FPU_ARCH_VFP)
11987 for (i = prec - 1; i >= 0; i--)
11989 md_number_to_chars (litP, (valueT) words[i], 2);
11990 litP += 2;
11992 else
11993 /* For a 4 byte float the order of elements in `words' is 1 0.
11994 For an 8 byte float the order is 1 0 3 2. */
11995 for (i = 0; i < prec; i += 2)
11997 md_number_to_chars (litP, (valueT) words[i + 1], 2);
11998 md_number_to_chars (litP + 2, (valueT) words[i], 2);
11999 litP += 4;
12003 return 0;
12006 /* The knowledge of the PC's pipeline offset is built into the insns
12007 themselves. */
12009 long
12010 md_pcrel_from (fixP)
12011 fixS * fixP;
12013 if (fixP->fx_addsy
12014 && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section
12015 && fixP->fx_subsy == NULL)
12016 return 0;
12018 if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD))
12020 /* PC relative addressing on the Thumb is slightly odd
12021 as the bottom two bits of the PC are forced to zero
12022 for the calculation. */
12023 return (fixP->fx_where + fixP->fx_frag->fr_address) & ~3;
12026 #ifdef TE_WINCE
12027 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
12028 so we un-adjust here to compensate for the accommodation. */
12029 return fixP->fx_where + fixP->fx_frag->fr_address + 8;
12030 #else
12031 return fixP->fx_where + fixP->fx_frag->fr_address;
12032 #endif
12035 /* Round up a section size to the appropriate boundary. */
12037 valueT
12038 md_section_align (segment, size)
12039 segT segment ATTRIBUTE_UNUSED;
12040 valueT size;
12042 #ifdef OBJ_ELF
12043 return size;
12044 #else
12045 /* Round all sects to multiple of 4. */
12046 return (size + 3) & ~3;
12047 #endif
12050 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
12051 Otherwise we have no need to default values of symbols. */
12053 symbolS *
12054 md_undefined_symbol (name)
12055 char * name ATTRIBUTE_UNUSED;
12057 #ifdef OBJ_ELF
12058 if (name[0] == '_' && name[1] == 'G'
12059 && streq (name, GLOBAL_OFFSET_TABLE_NAME))
12061 if (!GOT_symbol)
12063 if (symbol_find (name))
12064 as_bad ("GOT already in the symbol table");
12066 GOT_symbol = symbol_new (name, undefined_section,
12067 (valueT) 0, & zero_address_frag);
12070 return GOT_symbol;
12072 #endif
12074 return 0;
12077 /* arm_reg_parse () := if it looks like a register, return its token and
12078 advance the pointer. */
12080 static int
12081 arm_reg_parse (ccp, htab)
12082 register char ** ccp;
12083 struct hash_control *htab;
12085 char * start = * ccp;
12086 char c;
12087 char * p;
12088 struct reg_entry * reg;
12090 #ifdef REGISTER_PREFIX
12091 if (*start != REGISTER_PREFIX)
12092 return FAIL;
12093 p = start + 1;
12094 #else
12095 p = start;
12096 #ifdef OPTIONAL_REGISTER_PREFIX
12097 if (*p == OPTIONAL_REGISTER_PREFIX)
12098 p++, start++;
12099 #endif
12100 #endif
12101 if (!ISALPHA (*p) || !is_name_beginner (*p))
12102 return FAIL;
12104 c = *p++;
12105 while (ISALPHA (c) || ISDIGIT (c) || c == '_')
12106 c = *p++;
12108 *--p = 0;
12109 reg = (struct reg_entry *) hash_find (htab, start);
12110 *p = c;
12112 if (reg)
12114 *ccp = p;
12115 return reg->number;
12118 return FAIL;
12121 /* Search for the following register name in each of the possible reg name
12122 tables. Return the classification if found, or REG_TYPE_MAX if not
12123 present. */
12124 static enum arm_reg_type
12125 arm_reg_parse_any (cp)
12126 char *cp;
12128 int i;
12130 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
12131 if (arm_reg_parse (&cp, all_reg_maps[i].htab) != FAIL)
12132 return (enum arm_reg_type) i;
12134 return REG_TYPE_MAX;
12137 void
12138 md_apply_fix3 (fixP, valP, seg)
12139 fixS * fixP;
12140 valueT * valP;
12141 segT seg;
12143 offsetT value = * valP;
12144 offsetT newval;
12145 unsigned int newimm;
12146 unsigned long temp;
12147 int sign;
12148 char * buf = fixP->fx_where + fixP->fx_frag->fr_literal;
12149 arm_fix_data * arm_data = (arm_fix_data *) fixP->tc_fix_data;
12151 assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
12153 /* Note whether this will delete the relocation. */
12154 #if 0
12155 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
12156 doesn't work fully.) */
12157 if ((fixP->fx_addsy == 0 || symbol_constant_p (fixP->fx_addsy))
12158 && !fixP->fx_pcrel)
12159 #else
12160 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
12161 #endif
12162 fixP->fx_done = 1;
12164 /* If this symbol is in a different section then we need to leave it for
12165 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
12166 so we have to undo it's effects here. */
12167 if (fixP->fx_pcrel)
12169 if (fixP->fx_addsy != NULL
12170 && S_IS_DEFINED (fixP->fx_addsy)
12171 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
12173 if (target_oabi
12174 && (fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
12175 || fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
12177 value = 0;
12178 else
12179 value += md_pcrel_from (fixP);
12183 /* Remember value for emit_reloc. */
12184 fixP->fx_addnumber = value;
12186 switch (fixP->fx_r_type)
12188 case BFD_RELOC_ARM_IMMEDIATE:
12189 newimm = validate_immediate (value);
12190 temp = md_chars_to_number (buf, INSN_SIZE);
12192 /* If the instruction will fail, see if we can fix things up by
12193 changing the opcode. */
12194 if (newimm == (unsigned int) FAIL
12195 && (newimm = negate_data_op (&temp, value)) == (unsigned int) FAIL)
12197 as_bad_where (fixP->fx_file, fixP->fx_line,
12198 _("invalid constant (%lx) after fixup"),
12199 (unsigned long) value);
12200 break;
12203 newimm |= (temp & 0xfffff000);
12204 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
12205 fixP->fx_done = 1;
12206 break;
12208 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
12210 unsigned int highpart = 0;
12211 unsigned int newinsn = 0xe1a00000; /* nop. */
12213 newimm = validate_immediate (value);
12214 temp = md_chars_to_number (buf, INSN_SIZE);
12216 /* If the instruction will fail, see if we can fix things up by
12217 changing the opcode. */
12218 if (newimm == (unsigned int) FAIL
12219 && (newimm = negate_data_op (& temp, value)) == (unsigned int) FAIL)
12221 /* No ? OK - try using two ADD instructions to generate
12222 the value. */
12223 newimm = validate_immediate_twopart (value, & highpart);
12225 /* Yes - then make sure that the second instruction is
12226 also an add. */
12227 if (newimm != (unsigned int) FAIL)
12228 newinsn = temp;
12229 /* Still No ? Try using a negated value. */
12230 else if ((newimm = validate_immediate_twopart (- value, & highpart)) != (unsigned int) FAIL)
12231 temp = newinsn = (temp & OPCODE_MASK) | OPCODE_SUB << DATA_OP_SHIFT;
12232 /* Otherwise - give up. */
12233 else
12235 as_bad_where (fixP->fx_file, fixP->fx_line,
12236 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
12237 (long) value);
12238 break;
12241 /* Replace the first operand in the 2nd instruction (which
12242 is the PC) with the destination register. We have
12243 already added in the PC in the first instruction and we
12244 do not want to do it again. */
12245 newinsn &= ~ 0xf0000;
12246 newinsn |= ((newinsn & 0x0f000) << 4);
12249 newimm |= (temp & 0xfffff000);
12250 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
12252 highpart |= (newinsn & 0xfffff000);
12253 md_number_to_chars (buf + INSN_SIZE, (valueT) highpart, INSN_SIZE);
12255 break;
12257 case BFD_RELOC_ARM_OFFSET_IMM:
12258 sign = value >= 0;
12260 if (value < 0)
12261 value = - value;
12263 if (validate_offset_imm (value, 0) == FAIL)
12265 as_bad_where (fixP->fx_file, fixP->fx_line,
12266 _("bad immediate value for offset (%ld)"),
12267 (long) value);
12268 break;
12271 newval = md_chars_to_number (buf, INSN_SIZE);
12272 newval &= 0xff7ff000;
12273 newval |= value | (sign ? INDEX_UP : 0);
12274 md_number_to_chars (buf, newval, INSN_SIZE);
12275 break;
12277 case BFD_RELOC_ARM_OFFSET_IMM8:
12278 case BFD_RELOC_ARM_HWLITERAL:
12279 sign = value >= 0;
12281 if (value < 0)
12282 value = - value;
12284 if (validate_offset_imm (value, 1) == FAIL)
12286 if (fixP->fx_r_type == BFD_RELOC_ARM_HWLITERAL)
12287 as_bad_where (fixP->fx_file, fixP->fx_line,
12288 _("invalid literal constant: pool needs to be closer"));
12289 else
12290 as_bad (_("bad immediate value for half-word offset (%ld)"),
12291 (long) value);
12292 break;
12295 newval = md_chars_to_number (buf, INSN_SIZE);
12296 newval &= 0xff7ff0f0;
12297 newval |= ((value >> 4) << 8) | (value & 0xf) | (sign ? INDEX_UP : 0);
12298 md_number_to_chars (buf, newval, INSN_SIZE);
12299 break;
12301 case BFD_RELOC_ARM_LITERAL:
12302 sign = value >= 0;
12304 if (value < 0)
12305 value = - value;
12307 if (validate_offset_imm (value, 0) == FAIL)
12309 as_bad_where (fixP->fx_file, fixP->fx_line,
12310 _("invalid literal constant: pool needs to be closer"));
12311 break;
12314 newval = md_chars_to_number (buf, INSN_SIZE);
12315 newval &= 0xff7ff000;
12316 newval |= value | (sign ? INDEX_UP : 0);
12317 md_number_to_chars (buf, newval, INSN_SIZE);
12318 break;
12320 case BFD_RELOC_ARM_SHIFT_IMM:
12321 newval = md_chars_to_number (buf, INSN_SIZE);
12322 if (((unsigned long) value) > 32
12323 || (value == 32
12324 && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60)))
12326 as_bad_where (fixP->fx_file, fixP->fx_line,
12327 _("shift expression is too large"));
12328 break;
12331 if (value == 0)
12332 /* Shifts of zero must be done as lsl. */
12333 newval &= ~0x60;
12334 else if (value == 32)
12335 value = 0;
12336 newval &= 0xfffff07f;
12337 newval |= (value & 0x1f) << 7;
12338 md_number_to_chars (buf, newval, INSN_SIZE);
12339 break;
12341 case BFD_RELOC_ARM_SWI:
12342 if (arm_data->thumb_mode)
12344 if (((unsigned long) value) > 0xff)
12345 as_bad_where (fixP->fx_file, fixP->fx_line,
12346 _("invalid swi expression"));
12347 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xff00;
12348 newval |= value;
12349 md_number_to_chars (buf, newval, THUMB_SIZE);
12351 else
12353 if (((unsigned long) value) > 0x00ffffff)
12354 as_bad_where (fixP->fx_file, fixP->fx_line,
12355 _("invalid swi expression"));
12356 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
12357 newval |= value;
12358 md_number_to_chars (buf, newval, INSN_SIZE);
12360 break;
12362 case BFD_RELOC_ARM_MULTI:
12363 if (((unsigned long) value) > 0xffff)
12364 as_bad_where (fixP->fx_file, fixP->fx_line,
12365 _("invalid expression in load/store multiple"));
12366 newval = value | md_chars_to_number (buf, INSN_SIZE);
12367 md_number_to_chars (buf, newval, INSN_SIZE);
12368 break;
12370 case BFD_RELOC_ARM_PCREL_BRANCH:
12371 newval = md_chars_to_number (buf, INSN_SIZE);
12373 /* Sign-extend a 24-bit number. */
12374 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
12376 #ifdef OBJ_ELF
12377 if (! target_oabi)
12378 value = fixP->fx_offset;
12379 #endif
12381 /* We are going to store value (shifted right by two) in the
12382 instruction, in a 24 bit, signed field. Thus we need to check
12383 that none of the top 8 bits of the shifted value (top 7 bits of
12384 the unshifted, unsigned value) are set, or that they are all set. */
12385 if ((value & ~ ((offsetT) 0x1ffffff)) != 0
12386 && ((value & ~ ((offsetT) 0x1ffffff)) != ~ ((offsetT) 0x1ffffff)))
12388 #ifdef OBJ_ELF
12389 /* Normally we would be stuck at this point, since we cannot store
12390 the absolute address that is the destination of the branch in the
12391 24 bits of the branch instruction. If however, we happen to know
12392 that the destination of the branch is in the same section as the
12393 branch instruction itself, then we can compute the relocation for
12394 ourselves and not have to bother the linker with it.
12396 FIXME: The tests for OBJ_ELF and ! target_oabi are only here
12397 because I have not worked out how to do this for OBJ_COFF or
12398 target_oabi. */
12399 if (! target_oabi
12400 && fixP->fx_addsy != NULL
12401 && S_IS_DEFINED (fixP->fx_addsy)
12402 && S_GET_SEGMENT (fixP->fx_addsy) == seg)
12404 /* Get pc relative value to go into the branch. */
12405 value = * valP;
12407 /* Permit a backward branch provided that enough bits
12408 are set. Allow a forwards branch, provided that
12409 enough bits are clear. */
12410 if ( (value & ~ ((offsetT) 0x1ffffff)) == ~ ((offsetT) 0x1ffffff)
12411 || (value & ~ ((offsetT) 0x1ffffff)) == 0)
12412 fixP->fx_done = 1;
12415 if (! fixP->fx_done)
12416 #endif
12417 as_bad_where (fixP->fx_file, fixP->fx_line,
12418 _("GAS can't handle same-section branch dest >= 0x04000000"));
12421 value >>= 2;
12422 value += SEXT24 (newval);
12424 if ( (value & ~ ((offsetT) 0xffffff)) != 0
12425 && ((value & ~ ((offsetT) 0xffffff)) != ~ ((offsetT) 0xffffff)))
12426 as_bad_where (fixP->fx_file, fixP->fx_line,
12427 _("out of range branch"));
12429 newval = (value & 0x00ffffff) | (newval & 0xff000000);
12430 md_number_to_chars (buf, newval, INSN_SIZE);
12431 break;
12433 case BFD_RELOC_ARM_PCREL_BLX:
12435 offsetT hbit;
12436 newval = md_chars_to_number (buf, INSN_SIZE);
12438 #ifdef OBJ_ELF
12439 if (! target_oabi)
12440 value = fixP->fx_offset;
12441 #endif
12442 hbit = (value >> 1) & 1;
12443 value = (value >> 2) & 0x00ffffff;
12444 value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
12445 newval = value | (newval & 0xfe000000) | (hbit << 24);
12446 md_number_to_chars (buf, newval, INSN_SIZE);
12448 break;
12450 case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch. */
12451 newval = md_chars_to_number (buf, THUMB_SIZE);
12453 addressT diff = (newval & 0xff) << 1;
12454 if (diff & 0x100)
12455 diff |= ~0xff;
12457 value += diff;
12458 if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
12459 as_bad_where (fixP->fx_file, fixP->fx_line,
12460 _("branch out of range"));
12461 newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
12463 md_number_to_chars (buf, newval, THUMB_SIZE);
12464 break;
12466 case BFD_RELOC_THUMB_PCREL_BRANCH12: /* Unconditional branch. */
12467 newval = md_chars_to_number (buf, THUMB_SIZE);
12469 addressT diff = (newval & 0x7ff) << 1;
12470 if (diff & 0x800)
12471 diff |= ~0x7ff;
12473 value += diff;
12474 if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
12475 as_bad_where (fixP->fx_file, fixP->fx_line,
12476 _("branch out of range"));
12477 newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
12479 md_number_to_chars (buf, newval, THUMB_SIZE);
12480 break;
12482 case BFD_RELOC_THUMB_PCREL_BLX:
12483 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12485 offsetT newval2;
12486 addressT diff;
12488 newval = md_chars_to_number (buf, THUMB_SIZE);
12489 newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
12490 diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
12491 if (diff & 0x400000)
12492 diff |= ~0x3fffff;
12493 #ifdef OBJ_ELF
12494 value = fixP->fx_offset;
12495 #endif
12496 value += diff;
12498 if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
12499 as_bad_where (fixP->fx_file, fixP->fx_line,
12500 _("branch with link out of range"));
12502 newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12);
12503 newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
12504 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
12505 /* For a BLX instruction, make sure that the relocation is rounded up
12506 to a word boundary. This follows the semantics of the instruction
12507 which specifies that bit 1 of the target address will come from bit
12508 1 of the base address. */
12509 newval2 = (newval2 + 1) & ~ 1;
12510 md_number_to_chars (buf, newval, THUMB_SIZE);
12511 md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
12513 break;
12515 case BFD_RELOC_8:
12516 if (fixP->fx_done || fixP->fx_pcrel)
12517 md_number_to_chars (buf, value, 1);
12518 #ifdef OBJ_ELF
12519 else if (!target_oabi)
12521 value = fixP->fx_offset;
12522 md_number_to_chars (buf, value, 1);
12524 #endif
12525 break;
12527 case BFD_RELOC_16:
12528 if (fixP->fx_done || fixP->fx_pcrel)
12529 md_number_to_chars (buf, value, 2);
12530 #ifdef OBJ_ELF
12531 else if (!target_oabi)
12533 value = fixP->fx_offset;
12534 md_number_to_chars (buf, value, 2);
12536 #endif
12537 break;
12539 #ifdef OBJ_ELF
12540 case BFD_RELOC_ARM_GOT32:
12541 case BFD_RELOC_ARM_GOTOFF:
12542 md_number_to_chars (buf, 0, 4);
12543 break;
12544 #endif
12546 case BFD_RELOC_RVA:
12547 case BFD_RELOC_32:
12548 if (fixP->fx_done || fixP->fx_pcrel)
12549 md_number_to_chars (buf, value, 4);
12550 #ifdef OBJ_ELF
12551 else if (!target_oabi)
12553 value = fixP->fx_offset;
12554 md_number_to_chars (buf, value, 4);
12556 #endif
12557 break;
12559 #ifdef OBJ_ELF
12560 case BFD_RELOC_ARM_PLT32:
12561 /* It appears the instruction is fully prepared at this point. */
12562 break;
12563 #endif
12565 case BFD_RELOC_ARM_CP_OFF_IMM:
12566 sign = value >= 0;
12567 if (value < -1023 || value > 1023 || (value & 3))
12568 as_bad_where (fixP->fx_file, fixP->fx_line,
12569 _("illegal value for co-processor offset"));
12570 if (value < 0)
12571 value = -value;
12572 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
12573 newval |= (value >> 2) | (sign ? INDEX_UP : 0);
12574 md_number_to_chars (buf, newval, INSN_SIZE);
12575 break;
12577 case BFD_RELOC_ARM_CP_OFF_IMM_S2:
12578 sign = value >= 0;
12579 if (value < -255 || value > 255)
12580 as_bad_where (fixP->fx_file, fixP->fx_line,
12581 _("Illegal value for co-processor offset"));
12582 if (value < 0)
12583 value = -value;
12584 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
12585 newval |= value | (sign ? INDEX_UP : 0);
12586 md_number_to_chars (buf, newval , INSN_SIZE);
12587 break;
12589 case BFD_RELOC_ARM_THUMB_OFFSET:
12590 newval = md_chars_to_number (buf, THUMB_SIZE);
12591 /* Exactly what ranges, and where the offset is inserted depends
12592 on the type of instruction, we can establish this from the
12593 top 4 bits. */
12594 switch (newval >> 12)
12596 case 4: /* PC load. */
12597 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
12598 forced to zero for these loads, so we will need to round
12599 up the offset if the instruction address is not word
12600 aligned (since the final address produced must be, and
12601 we can only describe word-aligned immediate offsets). */
12603 if ((fixP->fx_frag->fr_address + fixP->fx_where + value) & 3)
12604 as_bad_where (fixP->fx_file, fixP->fx_line,
12605 _("invalid offset, target not word aligned (0x%08X)"),
12606 (unsigned int) (fixP->fx_frag->fr_address
12607 + fixP->fx_where + value));
12609 if ((value + 2) & ~0x3fe)
12610 as_bad_where (fixP->fx_file, fixP->fx_line,
12611 _("invalid offset, value too big (0x%08lX)"),
12612 (long) value);
12614 /* Round up, since pc will be rounded down. */
12615 newval |= (value + 2) >> 2;
12616 break;
12618 case 9: /* SP load/store. */
12619 if (value & ~0x3fc)
12620 as_bad_where (fixP->fx_file, fixP->fx_line,
12621 _("invalid offset, value too big (0x%08lX)"),
12622 (long) value);
12623 newval |= value >> 2;
12624 break;
12626 case 6: /* Word load/store. */
12627 if (value & ~0x7c)
12628 as_bad_where (fixP->fx_file, fixP->fx_line,
12629 _("invalid offset, value too big (0x%08lX)"),
12630 (long) value);
12631 newval |= value << 4; /* 6 - 2. */
12632 break;
12634 case 7: /* Byte load/store. */
12635 if (value & ~0x1f)
12636 as_bad_where (fixP->fx_file, fixP->fx_line,
12637 _("invalid offset, value too big (0x%08lX)"),
12638 (long) value);
12639 newval |= value << 6;
12640 break;
12642 case 8: /* Halfword load/store. */
12643 if (value & ~0x3e)
12644 as_bad_where (fixP->fx_file, fixP->fx_line,
12645 _("invalid offset, value too big (0x%08lX)"),
12646 (long) value);
12647 newval |= value << 5; /* 6 - 1. */
12648 break;
12650 default:
12651 as_bad_where (fixP->fx_file, fixP->fx_line,
12652 "Unable to process relocation for thumb opcode: %lx",
12653 (unsigned long) newval);
12654 break;
12656 md_number_to_chars (buf, newval, THUMB_SIZE);
12657 break;
12659 case BFD_RELOC_ARM_THUMB_ADD:
12660 /* This is a complicated relocation, since we use it for all of
12661 the following immediate relocations:
12663 3bit ADD/SUB
12664 8bit ADD/SUB
12665 9bit ADD/SUB SP word-aligned
12666 10bit ADD PC/SP word-aligned
12668 The type of instruction being processed is encoded in the
12669 instruction field:
12671 0x8000 SUB
12672 0x00F0 Rd
12673 0x000F Rs
12675 newval = md_chars_to_number (buf, THUMB_SIZE);
12677 int rd = (newval >> 4) & 0xf;
12678 int rs = newval & 0xf;
12679 int subtract = newval & 0x8000;
12681 if (rd == REG_SP)
12683 if (value & ~0x1fc)
12684 as_bad_where (fixP->fx_file, fixP->fx_line,
12685 _("invalid immediate for stack address calculation"));
12686 newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
12687 newval |= value >> 2;
12689 else if (rs == REG_PC || rs == REG_SP)
12691 if (subtract ||
12692 value & ~0x3fc)
12693 as_bad_where (fixP->fx_file, fixP->fx_line,
12694 _("invalid immediate for address calculation (value = 0x%08lX)"),
12695 (unsigned long) value);
12696 newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP);
12697 newval |= rd << 8;
12698 newval |= value >> 2;
12700 else if (rs == rd)
12702 if (value & ~0xff)
12703 as_bad_where (fixP->fx_file, fixP->fx_line,
12704 _("invalid 8bit immediate"));
12705 newval = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
12706 newval |= (rd << 8) | value;
12708 else
12710 if (value & ~0x7)
12711 as_bad_where (fixP->fx_file, fixP->fx_line,
12712 _("invalid 3bit immediate"));
12713 newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
12714 newval |= rd | (rs << 3) | (value << 6);
12717 md_number_to_chars (buf, newval, THUMB_SIZE);
12718 break;
12720 case BFD_RELOC_ARM_THUMB_IMM:
12721 newval = md_chars_to_number (buf, THUMB_SIZE);
12722 switch (newval >> 11)
12724 case 0x04: /* 8bit immediate MOV. */
12725 case 0x05: /* 8bit immediate CMP. */
12726 if (value < 0 || value > 255)
12727 as_bad_where (fixP->fx_file, fixP->fx_line,
12728 _("invalid immediate: %ld is too large"),
12729 (long) value);
12730 newval |= value;
12731 break;
12733 default:
12734 abort ();
12736 md_number_to_chars (buf, newval, THUMB_SIZE);
12737 break;
12739 case BFD_RELOC_ARM_THUMB_SHIFT:
12740 /* 5bit shift value (0..31). */
12741 if (value < 0 || value > 31)
12742 as_bad_where (fixP->fx_file, fixP->fx_line,
12743 _("illegal Thumb shift value: %ld"), (long) value);
12744 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xf03f;
12745 newval |= value << 6;
12746 md_number_to_chars (buf, newval, THUMB_SIZE);
12747 break;
12749 case BFD_RELOC_VTABLE_INHERIT:
12750 case BFD_RELOC_VTABLE_ENTRY:
12751 fixP->fx_done = 0;
12752 return;
12754 case BFD_RELOC_NONE:
12755 default:
12756 as_bad_where (fixP->fx_file, fixP->fx_line,
12757 _("bad relocation fixup type (%d)"), fixP->fx_r_type);
12761 /* Translate internal representation of relocation info to BFD target
12762 format. */
12764 arelent *
12765 tc_gen_reloc (section, fixp)
12766 asection * section ATTRIBUTE_UNUSED;
12767 fixS * fixp;
12769 arelent * reloc;
12770 bfd_reloc_code_real_type code;
12772 reloc = (arelent *) xmalloc (sizeof (arelent));
12774 reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
12775 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
12776 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
12778 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12779 #ifndef OBJ_ELF
12780 if (fixp->fx_pcrel == 0)
12781 reloc->addend = fixp->fx_offset;
12782 else
12783 reloc->addend = fixp->fx_offset = reloc->address;
12784 #else /* OBJ_ELF */
12785 reloc->addend = fixp->fx_offset;
12786 #endif
12788 switch (fixp->fx_r_type)
12790 case BFD_RELOC_8:
12791 if (fixp->fx_pcrel)
12793 code = BFD_RELOC_8_PCREL;
12794 break;
12797 case BFD_RELOC_16:
12798 if (fixp->fx_pcrel)
12800 code = BFD_RELOC_16_PCREL;
12801 break;
12804 case BFD_RELOC_32:
12805 if (fixp->fx_pcrel)
12807 code = BFD_RELOC_32_PCREL;
12808 break;
12811 case BFD_RELOC_ARM_PCREL_BRANCH:
12812 case BFD_RELOC_ARM_PCREL_BLX:
12813 case BFD_RELOC_RVA:
12814 case BFD_RELOC_THUMB_PCREL_BRANCH9:
12815 case BFD_RELOC_THUMB_PCREL_BRANCH12:
12816 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12817 case BFD_RELOC_THUMB_PCREL_BLX:
12818 case BFD_RELOC_VTABLE_ENTRY:
12819 case BFD_RELOC_VTABLE_INHERIT:
12820 code = fixp->fx_r_type;
12821 break;
12823 case BFD_RELOC_ARM_LITERAL:
12824 case BFD_RELOC_ARM_HWLITERAL:
12825 /* If this is called then the a literal has
12826 been referenced across a section boundary. */
12827 as_bad_where (fixp->fx_file, fixp->fx_line,
12828 _("literal referenced across section boundary"));
12829 return NULL;
12831 #ifdef OBJ_ELF
12832 case BFD_RELOC_ARM_GOT32:
12833 case BFD_RELOC_ARM_GOTOFF:
12834 case BFD_RELOC_ARM_PLT32:
12835 code = fixp->fx_r_type;
12836 break;
12837 #endif
12839 case BFD_RELOC_ARM_IMMEDIATE:
12840 as_bad_where (fixp->fx_file, fixp->fx_line,
12841 _("internal relocation (type: IMMEDIATE) not fixed up"));
12842 return NULL;
12844 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
12845 as_bad_where (fixp->fx_file, fixp->fx_line,
12846 _("ADRL used for a symbol not defined in the same file"));
12847 return NULL;
12849 case BFD_RELOC_ARM_OFFSET_IMM:
12850 if (fixp->fx_addsy != NULL
12851 && !S_IS_DEFINED (fixp->fx_addsy)
12852 && S_IS_LOCAL (fixp->fx_addsy))
12854 as_bad_where (fixp->fx_file, fixp->fx_line,
12855 _("undefined local label `%s'"),
12856 S_GET_NAME (fixp->fx_addsy));
12857 return NULL;
12860 as_bad_where (fixp->fx_file, fixp->fx_line,
12861 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
12862 return NULL;
12864 default:
12866 char * type;
12868 switch (fixp->fx_r_type)
12870 case BFD_RELOC_ARM_OFFSET_IMM8: type = "OFFSET_IMM8"; break;
12871 case BFD_RELOC_ARM_SHIFT_IMM: type = "SHIFT_IMM"; break;
12872 case BFD_RELOC_ARM_SWI: type = "SWI"; break;
12873 case BFD_RELOC_ARM_MULTI: type = "MULTI"; break;
12874 case BFD_RELOC_ARM_CP_OFF_IMM: type = "CP_OFF_IMM"; break;
12875 case BFD_RELOC_ARM_THUMB_ADD: type = "THUMB_ADD"; break;
12876 case BFD_RELOC_ARM_THUMB_SHIFT: type = "THUMB_SHIFT"; break;
12877 case BFD_RELOC_ARM_THUMB_IMM: type = "THUMB_IMM"; break;
12878 case BFD_RELOC_ARM_THUMB_OFFSET: type = "THUMB_OFFSET"; break;
12879 default: type = _("<unknown>"); break;
12881 as_bad_where (fixp->fx_file, fixp->fx_line,
12882 _("cannot represent %s relocation in this object file format"),
12883 type);
12884 return NULL;
12888 #ifdef OBJ_ELF
12889 if ((code == BFD_RELOC_32_PCREL || code == BFD_RELOC_32)
12890 && GOT_symbol
12891 && fixp->fx_addsy == GOT_symbol)
12893 code = BFD_RELOC_ARM_GOTPC;
12894 reloc->addend = fixp->fx_offset = reloc->address;
12896 #endif
12898 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
12900 if (reloc->howto == NULL)
12902 as_bad_where (fixp->fx_file, fixp->fx_line,
12903 _("cannot represent %s relocation in this object file format"),
12904 bfd_get_reloc_code_name (code));
12905 return NULL;
12908 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12909 vtable entry to be used in the relocation's section offset. */
12910 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
12911 reloc->address = fixp->fx_offset;
12913 return reloc;
12917 md_estimate_size_before_relax (fragP, segtype)
12918 fragS * fragP ATTRIBUTE_UNUSED;
12919 segT segtype ATTRIBUTE_UNUSED;
12921 as_fatal (_("md_estimate_size_before_relax\n"));
12922 return 1;
12925 static void
12926 output_inst (str)
12927 const char *str;
12929 char * to = NULL;
12931 if (inst.error)
12933 as_bad ("%s -- `%s'", inst.error, str);
12934 return;
12937 to = frag_more (inst.size);
12939 if (thumb_mode && (inst.size > THUMB_SIZE))
12941 assert (inst.size == (2 * THUMB_SIZE));
12942 md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE);
12943 md_number_to_chars (to + THUMB_SIZE, inst.instruction, THUMB_SIZE);
12945 else if (inst.size > INSN_SIZE)
12947 assert (inst.size == (2 * INSN_SIZE));
12948 md_number_to_chars (to, inst.instruction, INSN_SIZE);
12949 md_number_to_chars (to + INSN_SIZE, inst.instruction, INSN_SIZE);
12951 else
12952 md_number_to_chars (to, inst.instruction, inst.size);
12954 if (inst.reloc.type != BFD_RELOC_NONE)
12955 fix_new_arm (frag_now, to - frag_now->fr_literal,
12956 inst.size, & inst.reloc.exp, inst.reloc.pc_rel,
12957 inst.reloc.type);
12959 #ifdef OBJ_ELF
12960 dwarf2_emit_insn (inst.size);
12961 #endif
12964 void
12965 md_assemble (str)
12966 char * str;
12968 char c;
12969 char *p;
12970 char *start;
12972 /* Align the instruction.
12973 This may not be the right thing to do but ... */
12974 #if 0
12975 arm_align (2, 0);
12976 #endif
12978 /* Align the previous label if needed. */
12979 if (last_label_seen != NULL)
12981 symbol_set_frag (last_label_seen, frag_now);
12982 S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ());
12983 S_SET_SEGMENT (last_label_seen, now_seg);
12986 memset (&inst, '\0', sizeof (inst));
12987 inst.reloc.type = BFD_RELOC_NONE;
12989 skip_whitespace (str);
12991 /* Scan up to the end of the op-code, which must end in white space or
12992 end of string. */
12993 for (start = p = str; *p != '\0'; p++)
12994 if (*p == ' ')
12995 break;
12997 if (p == str)
12999 as_bad (_("no operator -- statement `%s'\n"), str);
13000 return;
13003 if (thumb_mode)
13005 const struct thumb_opcode * opcode;
13007 c = *p;
13008 *p = '\0';
13009 opcode = (const struct thumb_opcode *) hash_find (arm_tops_hsh, str);
13010 *p = c;
13012 if (opcode)
13014 /* Check that this instruction is supported for this CPU. */
13015 if (thumb_mode == 1 && (opcode->variant & cpu_variant) == 0)
13017 as_bad (_("selected processor does not support `%s'"), str);
13018 return;
13021 mapping_state (MAP_THUMB);
13022 inst.instruction = opcode->value;
13023 inst.size = opcode->size;
13024 (*opcode->parms) (p);
13025 output_inst (str);
13026 return;
13029 else
13031 const struct asm_opcode * opcode;
13033 c = *p;
13034 *p = '\0';
13035 opcode = (const struct asm_opcode *) hash_find (arm_ops_hsh, str);
13036 *p = c;
13038 if (opcode)
13040 /* Check that this instruction is supported for this CPU. */
13041 if ((opcode->variant & cpu_variant) == 0)
13043 as_bad (_("selected processor does not support `%s'"), str);
13044 return;
13047 mapping_state (MAP_ARM);
13048 inst.instruction = opcode->value;
13049 inst.size = INSN_SIZE;
13050 (*opcode->parms) (p);
13051 output_inst (str);
13052 return;
13056 /* It wasn't an instruction, but it might be a register alias of the form
13057 alias .req reg. */
13058 if (create_register_alias (str, p))
13059 return;
13061 as_bad (_("bad instruction `%s'"), start);
13064 /* md_parse_option
13065 Invocation line includes a switch not recognized by the base assembler.
13066 See if it's a processor-specific option.
13068 This routine is somewhat complicated by the need for backwards
13069 compatibility (since older releases of gcc can't be changed).
13070 The new options try to make the interface as compatible as
13071 possible with GCC.
13073 New options (supported) are:
13075 -mcpu=<cpu name> Assemble for selected processor
13076 -march=<architecture name> Assemble for selected architecture
13077 -mfpu=<fpu architecture> Assemble for selected FPU.
13078 -EB/-mbig-endian Big-endian
13079 -EL/-mlittle-endian Little-endian
13080 -k Generate PIC code
13081 -mthumb Start in Thumb mode
13082 -mthumb-interwork Code supports ARM/Thumb interworking
13084 For now we will also provide support for:
13086 -mapcs-32 32-bit Program counter
13087 -mapcs-26 26-bit Program counter
13088 -macps-float Floats passed in FP registers
13089 -mapcs-reentrant Reentrant code
13090 -matpcs
13091 (sometime these will probably be replaced with -mapcs=<list of options>
13092 and -matpcs=<list of options>)
13094 The remaining options are only supported for back-wards compatibility.
13095 Cpu variants, the arm part is optional:
13096 -m[arm]1 Currently not supported.
13097 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
13098 -m[arm]3 Arm 3 processor
13099 -m[arm]6[xx], Arm 6 processors
13100 -m[arm]7[xx][t][[d]m] Arm 7 processors
13101 -m[arm]8[10] Arm 8 processors
13102 -m[arm]9[20][tdmi] Arm 9 processors
13103 -mstrongarm[110[0]] StrongARM processors
13104 -mxscale XScale processors
13105 -m[arm]v[2345[t[e]]] Arm architectures
13106 -mall All (except the ARM1)
13107 FP variants:
13108 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
13109 -mfpe-old (No float load/store multiples)
13110 -mvfpxd VFP Single precision
13111 -mvfp All VFP
13112 -mno-fpu Disable all floating point instructions
13114 The following CPU names are recognized:
13115 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
13116 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
13117 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
13118 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
13119 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
13120 arm10t arm10e, arm1020t, arm1020e, arm10200e,
13121 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
13125 const char * md_shortopts = "m:k";
13127 #ifdef ARM_BI_ENDIAN
13128 #define OPTION_EB (OPTION_MD_BASE + 0)
13129 #define OPTION_EL (OPTION_MD_BASE + 1)
13130 #else
13131 #if TARGET_BYTES_BIG_ENDIAN
13132 #define OPTION_EB (OPTION_MD_BASE + 0)
13133 #else
13134 #define OPTION_EL (OPTION_MD_BASE + 1)
13135 #endif
13136 #endif
13138 struct option md_longopts[] =
13140 #ifdef OPTION_EB
13141 {"EB", no_argument, NULL, OPTION_EB},
13142 #endif
13143 #ifdef OPTION_EL
13144 {"EL", no_argument, NULL, OPTION_EL},
13145 #endif
13146 {NULL, no_argument, NULL, 0}
13149 size_t md_longopts_size = sizeof (md_longopts);
13151 struct arm_option_table
13153 char *option; /* Option name to match. */
13154 char *help; /* Help information. */
13155 int *var; /* Variable to change. */
13156 int value; /* What to change it to. */
13157 char *deprecated; /* If non-null, print this message. */
13160 struct arm_option_table arm_opts[] =
13162 {"k", N_("generate PIC code"), &pic_code, 1, NULL},
13163 {"mthumb", N_("assemble Thumb code"), &thumb_mode, 1, NULL},
13164 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
13165 &support_interwork, 1, NULL},
13166 {"moabi", N_("use old ABI (ELF only)"), &target_oabi, 1, NULL},
13167 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26, 0, NULL},
13168 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26, 1, NULL},
13169 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float,
13170 1, NULL},
13171 {"mapcs-reentrant", N_("re-entrant code"), &pic_code, 1, NULL},
13172 {"matpcs", N_("code is ATPCS conformant"), &atpcs, 1, NULL},
13173 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian, 1, NULL},
13174 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian, 1,
13175 NULL},
13177 /* These are recognized by the assembler, but have no affect on code. */
13178 {"mapcs-frame", N_("use frame pointer"), NULL, 0, NULL},
13179 {"mapcs-stack-check", N_("use stack size checking"), NULL, 0, NULL},
13181 /* DON'T add any new processors to this list -- we want the whole list
13182 to go away... Add them to the processors table instead. */
13183 {"marm1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
13184 {"m1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
13185 {"marm2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
13186 {"m2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
13187 {"marm250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
13188 {"m250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
13189 {"marm3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
13190 {"m3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
13191 {"marm6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
13192 {"m6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
13193 {"marm600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
13194 {"m600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
13195 {"marm610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
13196 {"m610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
13197 {"marm620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
13198 {"m620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
13199 {"marm7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
13200 {"m7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
13201 {"marm70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
13202 {"m70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
13203 {"marm700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
13204 {"m700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
13205 {"marm700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
13206 {"m700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
13207 {"marm710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
13208 {"m710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
13209 {"marm710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
13210 {"m710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
13211 {"marm720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
13212 {"m720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
13213 {"marm7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
13214 {"m7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
13215 {"marm7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
13216 {"m7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
13217 {"marm7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
13218 {"m7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
13219 {"marm7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
13220 {"m7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
13221 {"marm7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
13222 {"m7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
13223 {"marm7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
13224 {"m7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
13225 {"marm7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
13226 {"m7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
13227 {"marm7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
13228 {"m7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
13229 {"marm7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13230 {"m7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13231 {"marm7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13232 {"m7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13233 {"marm710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
13234 {"m710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
13235 {"marm720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
13236 {"m720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
13237 {"marm740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
13238 {"m740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
13239 {"marm8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
13240 {"m8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
13241 {"marm810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
13242 {"m810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
13243 {"marm9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
13244 {"m9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
13245 {"marm9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
13246 {"m9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
13247 {"marm920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
13248 {"m920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
13249 {"marm940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
13250 {"m940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
13251 {"mstrongarm", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=strongarm")},
13252 {"mstrongarm110", NULL, &legacy_cpu, ARM_ARCH_V4,
13253 N_("use -mcpu=strongarm110")},
13254 {"mstrongarm1100", NULL, &legacy_cpu, ARM_ARCH_V4,
13255 N_("use -mcpu=strongarm1100")},
13256 {"mstrongarm1110", NULL, &legacy_cpu, ARM_ARCH_V4,
13257 N_("use -mcpu=strongarm1110")},
13258 {"mxscale", NULL, &legacy_cpu, ARM_ARCH_XSCALE, N_("use -mcpu=xscale")},
13259 {"miwmmxt", NULL, &legacy_cpu, ARM_ARCH_IWMMXT, N_("use -mcpu=iwmmxt")},
13260 {"mall", NULL, &legacy_cpu, ARM_ANY, N_("use -mcpu=all")},
13262 /* Architecture variants -- don't add any more to this list either. */
13263 {"mv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
13264 {"marmv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
13265 {"mv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
13266 {"marmv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
13267 {"mv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
13268 {"marmv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
13269 {"mv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
13270 {"marmv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
13271 {"mv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
13272 {"marmv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
13273 {"mv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
13274 {"marmv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
13275 {"mv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
13276 {"marmv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
13277 {"mv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
13278 {"marmv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
13279 {"mv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
13280 {"marmv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
13282 /* Floating point variants -- don't add any more to this list either. */
13283 {"mfpe-old", NULL, &legacy_fpu, FPU_ARCH_FPE, N_("use -mfpu=fpe")},
13284 {"mfpa10", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa10")},
13285 {"mfpa11", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa11")},
13286 {"mno-fpu", NULL, &legacy_fpu, 0,
13287 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
13289 {NULL, NULL, NULL, 0, NULL}
13292 struct arm_cpu_option_table
13294 char *name;
13295 int value;
13296 /* For some CPUs we assume an FPU unless the user explicitly sets
13297 -mfpu=... */
13298 int default_fpu;
13301 /* This list should, at a minimum, contain all the cpu names
13302 recognized by GCC. */
13303 static struct arm_cpu_option_table arm_cpus[] =
13305 {"all", ARM_ANY, FPU_ARCH_FPA},
13306 {"arm1", ARM_ARCH_V1, FPU_ARCH_FPA},
13307 {"arm2", ARM_ARCH_V2, FPU_ARCH_FPA},
13308 {"arm250", ARM_ARCH_V2S, FPU_ARCH_FPA},
13309 {"arm3", ARM_ARCH_V2S, FPU_ARCH_FPA},
13310 {"arm6", ARM_ARCH_V3, FPU_ARCH_FPA},
13311 {"arm60", ARM_ARCH_V3, FPU_ARCH_FPA},
13312 {"arm600", ARM_ARCH_V3, FPU_ARCH_FPA},
13313 {"arm610", ARM_ARCH_V3, FPU_ARCH_FPA},
13314 {"arm620", ARM_ARCH_V3, FPU_ARCH_FPA},
13315 {"arm7", ARM_ARCH_V3, FPU_ARCH_FPA},
13316 {"arm7m", ARM_ARCH_V3M, FPU_ARCH_FPA},
13317 {"arm7d", ARM_ARCH_V3, FPU_ARCH_FPA},
13318 {"arm7dm", ARM_ARCH_V3M, FPU_ARCH_FPA},
13319 {"arm7di", ARM_ARCH_V3, FPU_ARCH_FPA},
13320 {"arm7dmi", ARM_ARCH_V3M, FPU_ARCH_FPA},
13321 {"arm70", ARM_ARCH_V3, FPU_ARCH_FPA},
13322 {"arm700", ARM_ARCH_V3, FPU_ARCH_FPA},
13323 {"arm700i", ARM_ARCH_V3, FPU_ARCH_FPA},
13324 {"arm710", ARM_ARCH_V3, FPU_ARCH_FPA},
13325 {"arm710t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13326 {"arm720", ARM_ARCH_V3, FPU_ARCH_FPA},
13327 {"arm720t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13328 {"arm740t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13329 {"arm710c", ARM_ARCH_V3, FPU_ARCH_FPA},
13330 {"arm7100", ARM_ARCH_V3, FPU_ARCH_FPA},
13331 {"arm7500", ARM_ARCH_V3, FPU_ARCH_FPA},
13332 {"arm7500fe", ARM_ARCH_V3, FPU_ARCH_FPA},
13333 {"arm7t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13334 {"arm7tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
13335 {"arm8", ARM_ARCH_V4, FPU_ARCH_FPA},
13336 {"arm810", ARM_ARCH_V4, FPU_ARCH_FPA},
13337 {"strongarm", ARM_ARCH_V4, FPU_ARCH_FPA},
13338 {"strongarm1", ARM_ARCH_V4, FPU_ARCH_FPA},
13339 {"strongarm110", ARM_ARCH_V4, FPU_ARCH_FPA},
13340 {"strongarm1100", ARM_ARCH_V4, FPU_ARCH_FPA},
13341 {"strongarm1110", ARM_ARCH_V4, FPU_ARCH_FPA},
13342 {"arm9", ARM_ARCH_V4T, FPU_ARCH_FPA},
13343 {"arm920", ARM_ARCH_V4T, FPU_ARCH_FPA},
13344 {"arm920t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13345 {"arm922t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13346 {"arm940t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13347 {"arm9tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
13348 /* For V5 or later processors we default to using VFP; but the user
13349 should really set the FPU type explicitly. */
13350 {"arm9e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13351 {"arm9e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13352 {"arm926ej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
13353 {"arm926ejs", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
13354 {"arm946e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13355 {"arm946e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13356 {"arm966e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13357 {"arm966e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13358 {"arm10t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
13359 {"arm10e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13360 {"arm1020", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13361 {"arm1020t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
13362 {"arm1020e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13363 {"arm1026ejs", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13364 {"arm1136js", ARM_ARCH_V6, FPU_NONE},
13365 {"arm1136jfs", ARM_ARCH_V6, FPU_ARCH_VFP_V2},
13366 /* ??? XSCALE is really an architecture. */
13367 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
13368 /* ??? iwmmxt is not a processor. */
13369 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP_V2},
13370 {"i80200", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
13371 /* Maverick */
13372 {"ep9312", ARM_ARCH_V4T | ARM_CEXT_MAVERICK, FPU_ARCH_MAVERICK},
13373 {NULL, 0, 0}
13376 struct arm_arch_option_table
13378 char *name;
13379 int value;
13380 int default_fpu;
13383 /* This list should, at a minimum, contain all the architecture names
13384 recognized by GCC. */
13385 static struct arm_arch_option_table arm_archs[] =
13387 {"all", ARM_ANY, FPU_ARCH_FPA},
13388 {"armv1", ARM_ARCH_V1, FPU_ARCH_FPA},
13389 {"armv2", ARM_ARCH_V2, FPU_ARCH_FPA},
13390 {"armv2a", ARM_ARCH_V2S, FPU_ARCH_FPA},
13391 {"armv2s", ARM_ARCH_V2S, FPU_ARCH_FPA},
13392 {"armv3", ARM_ARCH_V3, FPU_ARCH_FPA},
13393 {"armv3m", ARM_ARCH_V3M, FPU_ARCH_FPA},
13394 {"armv4", ARM_ARCH_V4, FPU_ARCH_FPA},
13395 {"armv4xm", ARM_ARCH_V4xM, FPU_ARCH_FPA},
13396 {"armv4t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13397 {"armv4txm", ARM_ARCH_V4TxM, FPU_ARCH_FPA},
13398 {"armv5", ARM_ARCH_V5, FPU_ARCH_VFP},
13399 {"armv5t", ARM_ARCH_V5T, FPU_ARCH_VFP},
13400 {"armv5txm", ARM_ARCH_V5TxM, FPU_ARCH_VFP},
13401 {"armv5te", ARM_ARCH_V5TE, FPU_ARCH_VFP},
13402 {"armv5texp", ARM_ARCH_V5TExP, FPU_ARCH_VFP},
13403 {"armv5tej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP},
13404 {"armv6", ARM_ARCH_V6, FPU_ARCH_VFP},
13405 {"armv6j", ARM_ARCH_V6, FPU_ARCH_VFP},
13406 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP},
13407 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP},
13408 {NULL, 0, 0}
13411 /* ISA extensions in the co-processor space. */
13412 struct arm_arch_extension_table
13414 char *name;
13415 int value;
13418 static struct arm_arch_extension_table arm_extensions[] =
13420 {"maverick", ARM_CEXT_MAVERICK},
13421 {"xscale", ARM_CEXT_XSCALE},
13422 {"iwmmxt", ARM_CEXT_IWMMXT},
13423 {NULL, 0}
13426 struct arm_fpu_option_table
13428 char *name;
13429 int value;
13432 /* This list should, at a minimum, contain all the fpu names
13433 recognized by GCC. */
13434 static struct arm_fpu_option_table arm_fpus[] =
13436 {"softfpa", FPU_NONE},
13437 {"fpe", FPU_ARCH_FPE},
13438 {"fpe2", FPU_ARCH_FPE},
13439 {"fpe3", FPU_ARCH_FPA}, /* Third release supports LFM/SFM. */
13440 {"fpa", FPU_ARCH_FPA},
13441 {"fpa10", FPU_ARCH_FPA},
13442 {"fpa11", FPU_ARCH_FPA},
13443 {"arm7500fe", FPU_ARCH_FPA},
13444 {"softvfp", FPU_ARCH_VFP},
13445 {"softvfp+vfp", FPU_ARCH_VFP_V2},
13446 {"vfp", FPU_ARCH_VFP_V2},
13447 {"vfp9", FPU_ARCH_VFP_V2},
13448 {"vfp10", FPU_ARCH_VFP_V2},
13449 {"vfp10-r0", FPU_ARCH_VFP_V1},
13450 {"vfpxd", FPU_ARCH_VFP_V1xD},
13451 {"arm1020t", FPU_ARCH_VFP_V1},
13452 {"arm1020e", FPU_ARCH_VFP_V2},
13453 {"arm1136jfs", FPU_ARCH_VFP_V2},
13454 {"maverick", FPU_ARCH_MAVERICK},
13455 {NULL, 0}
13458 struct arm_float_abi_option_table
13460 char *name;
13461 int value;
13464 static struct arm_float_abi_option_table arm_float_abis[] =
13466 {"hard", ARM_FLOAT_ABI_HARD},
13467 {"softfp", ARM_FLOAT_ABI_SOFTFP},
13468 {"soft", ARM_FLOAT_ABI_SOFT},
13469 {NULL, 0}
13472 struct arm_eabi_option_table
13474 char *name;
13475 unsigned int value;
13478 #ifdef OBJ_ELF
13479 /* We only know hot to output GNU and ver 3 (AAELF) formats. */
13480 static struct arm_eabi_option_table arm_eabis[] =
13482 {"gnu", EF_ARM_EABI_UNKNOWN},
13483 {"3", EF_ARM_EABI_VER3},
13484 {NULL, 0}
13486 #endif
13488 struct arm_long_option_table
13490 char *option; /* Substring to match. */
13491 char *help; /* Help information. */
13492 int (*func) PARAMS ((char *subopt)); /* Function to decode sub-option. */
13493 char *deprecated; /* If non-null, print this message. */
13496 static int
13497 arm_parse_extension (str, opt_p)
13498 char *str;
13499 int *opt_p;
13501 while (str != NULL && *str != 0)
13503 struct arm_arch_extension_table *opt;
13504 char *ext;
13505 int optlen;
13507 if (*str != '+')
13509 as_bad (_("invalid architectural extension"));
13510 return 0;
13513 str++;
13514 ext = strchr (str, '+');
13516 if (ext != NULL)
13517 optlen = ext - str;
13518 else
13519 optlen = strlen (str);
13521 if (optlen == 0)
13523 as_bad (_("missing architectural extension"));
13524 return 0;
13527 for (opt = arm_extensions; opt->name != NULL; opt++)
13528 if (strncmp (opt->name, str, optlen) == 0)
13530 *opt_p |= opt->value;
13531 break;
13534 if (opt->name == NULL)
13536 as_bad (_("unknown architectural extnsion `%s'"), str);
13537 return 0;
13540 str = ext;
13543 return 1;
13546 static int
13547 arm_parse_cpu (str)
13548 char *str;
13550 struct arm_cpu_option_table *opt;
13551 char *ext = strchr (str, '+');
13552 int optlen;
13554 if (ext != NULL)
13555 optlen = ext - str;
13556 else
13557 optlen = strlen (str);
13559 if (optlen == 0)
13561 as_bad (_("missing cpu name `%s'"), str);
13562 return 0;
13565 for (opt = arm_cpus; opt->name != NULL; opt++)
13566 if (strncmp (opt->name, str, optlen) == 0)
13568 mcpu_cpu_opt = opt->value;
13569 mcpu_fpu_opt = opt->default_fpu;
13571 if (ext != NULL)
13572 return arm_parse_extension (ext, &mcpu_cpu_opt);
13574 return 1;
13577 as_bad (_("unknown cpu `%s'"), str);
13578 return 0;
13581 static int
13582 arm_parse_arch (str)
13583 char *str;
13585 struct arm_arch_option_table *opt;
13586 char *ext = strchr (str, '+');
13587 int optlen;
13589 if (ext != NULL)
13590 optlen = ext - str;
13591 else
13592 optlen = strlen (str);
13594 if (optlen == 0)
13596 as_bad (_("missing architecture name `%s'"), str);
13597 return 0;
13601 for (opt = arm_archs; opt->name != NULL; opt++)
13602 if (strcmp (opt->name, str) == 0)
13604 march_cpu_opt = opt->value;
13605 march_fpu_opt = opt->default_fpu;
13607 if (ext != NULL)
13608 return arm_parse_extension (ext, &march_cpu_opt);
13610 return 1;
13613 as_bad (_("unknown architecture `%s'\n"), str);
13614 return 0;
13617 static int
13618 arm_parse_fpu (str)
13619 char *str;
13621 struct arm_fpu_option_table *opt;
13623 for (opt = arm_fpus; opt->name != NULL; opt++)
13624 if (strcmp (opt->name, str) == 0)
13626 mfpu_opt = opt->value;
13627 return 1;
13630 as_bad (_("unknown floating point format `%s'\n"), str);
13631 return 0;
13634 static int
13635 arm_parse_float_abi (str)
13636 char * str;
13638 struct arm_float_abi_option_table *opt;
13640 for (opt = arm_float_abis; opt->name != NULL; opt++)
13641 if (strcmp (opt->name, str) == 0)
13643 mfloat_abi_opt = opt->value;
13644 return 1;
13647 as_bad (_("unknown floating point abi `%s'\n"), str);
13648 return 0;
13651 #ifdef OBJ_ELF
13652 static int
13653 arm_parse_eabi (str)
13654 char * str;
13656 struct arm_eabi_option_table *opt;
13658 for (opt = arm_eabis; opt->name != NULL; opt++)
13659 if (strcmp (opt->name, str) == 0)
13661 meabi_flags = opt->value;
13662 return 1;
13664 as_bad (_("unknown EABI `%s'\n"), str);
13665 return 0;
13667 #endif
13669 struct arm_long_option_table arm_long_opts[] =
13671 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13672 arm_parse_cpu, NULL},
13673 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13674 arm_parse_arch, NULL},
13675 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13676 arm_parse_fpu, NULL},
13677 {"mfloat-abi=", N_("<abi>\t assemble for floating point ABI <abi>"),
13678 arm_parse_float_abi, NULL},
13679 #ifdef OBJ_ELF
13680 {"meabi=", N_("<ver>\t assemble for eabi version <ver>"),
13681 arm_parse_eabi, NULL},
13682 #endif
13683 {NULL, NULL, 0, NULL}
13687 md_parse_option (c, arg)
13688 int c;
13689 char * arg;
13691 struct arm_option_table *opt;
13692 struct arm_long_option_table *lopt;
13694 switch (c)
13696 #ifdef OPTION_EB
13697 case OPTION_EB:
13698 target_big_endian = 1;
13699 break;
13700 #endif
13702 #ifdef OPTION_EL
13703 case OPTION_EL:
13704 target_big_endian = 0;
13705 break;
13706 #endif
13708 case 'a':
13709 /* Listing option. Just ignore these, we don't support additional
13710 ones. */
13711 return 0;
13713 default:
13714 for (opt = arm_opts; opt->option != NULL; opt++)
13716 if (c == opt->option[0]
13717 && ((arg == NULL && opt->option[1] == 0)
13718 || strcmp (arg, opt->option + 1) == 0))
13720 #if WARN_DEPRECATED
13721 /* If the option is deprecated, tell the user. */
13722 if (opt->deprecated != NULL)
13723 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c,
13724 arg ? arg : "", _(opt->deprecated));
13725 #endif
13727 if (opt->var != NULL)
13728 *opt->var = opt->value;
13730 return 1;
13734 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13736 /* These options are expected to have an argument. */
13737 if (c == lopt->option[0]
13738 && arg != NULL
13739 && strncmp (arg, lopt->option + 1,
13740 strlen (lopt->option + 1)) == 0)
13742 #if WARN_DEPRECATED
13743 /* If the option is deprecated, tell the user. */
13744 if (lopt->deprecated != NULL)
13745 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c, arg,
13746 _(lopt->deprecated));
13747 #endif
13749 /* Call the sup-option parser. */
13750 return (*lopt->func)(arg + strlen (lopt->option) - 1);
13754 as_bad (_("unrecognized option `-%c%s'"), c, arg ? arg : "");
13755 return 0;
13758 return 1;
13761 void
13762 md_show_usage (fp)
13763 FILE * fp;
13765 struct arm_option_table *opt;
13766 struct arm_long_option_table *lopt;
13768 fprintf (fp, _(" ARM-specific assembler options:\n"));
13770 for (opt = arm_opts; opt->option != NULL; opt++)
13771 if (opt->help != NULL)
13772 fprintf (fp, " -%-23s%s\n", opt->option, _(opt->help));
13774 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13775 if (lopt->help != NULL)
13776 fprintf (fp, " -%s%s\n", lopt->option, _(lopt->help));
13778 #ifdef OPTION_EB
13779 fprintf (fp, _("\
13780 -EB assemble code for a big-endian cpu\n"));
13781 #endif
13783 #ifdef OPTION_EL
13784 fprintf (fp, _("\
13785 -EL assemble code for a little-endian cpu\n"));
13786 #endif
13789 /* We need to be able to fix up arbitrary expressions in some statements.
13790 This is so that we can handle symbols that are an arbitrary distance from
13791 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
13792 which returns part of an address in a form which will be valid for
13793 a data instruction. We do this by pushing the expression into a symbol
13794 in the expr_section, and creating a fix for that. */
13796 static void
13797 fix_new_arm (frag, where, size, exp, pc_rel, reloc)
13798 fragS * frag;
13799 int where;
13800 short int size;
13801 expressionS * exp;
13802 int pc_rel;
13803 int reloc;
13805 fixS * new_fix;
13806 arm_fix_data * arm_data;
13808 switch (exp->X_op)
13810 case O_constant:
13811 case O_symbol:
13812 case O_add:
13813 case O_subtract:
13814 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
13815 break;
13817 default:
13818 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0,
13819 pc_rel, reloc);
13820 break;
13823 /* Mark whether the fix is to a THUMB instruction, or an ARM
13824 instruction. */
13825 arm_data = (arm_fix_data *) obstack_alloc (& notes, sizeof (arm_fix_data));
13826 new_fix->tc_fix_data = (PTR) arm_data;
13827 arm_data->thumb_mode = thumb_mode;
13830 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13832 void
13833 cons_fix_new_arm (frag, where, size, exp)
13834 fragS * frag;
13835 int where;
13836 int size;
13837 expressionS * exp;
13839 bfd_reloc_code_real_type type;
13840 int pcrel = 0;
13842 /* Pick a reloc.
13843 FIXME: @@ Should look at CPU word size. */
13844 switch (size)
13846 case 1:
13847 type = BFD_RELOC_8;
13848 break;
13849 case 2:
13850 type = BFD_RELOC_16;
13851 break;
13852 case 4:
13853 default:
13854 type = BFD_RELOC_32;
13855 break;
13856 case 8:
13857 type = BFD_RELOC_64;
13858 break;
13861 fix_new_exp (frag, where, (int) size, exp, pcrel, type);
13864 /* A good place to do this, although this was probably not intended
13865 for this kind of use. We need to dump the literal pool before
13866 references are made to a null symbol pointer. */
13868 void
13869 arm_cleanup ()
13871 literal_pool * pool;
13873 for (pool = list_of_pools; pool; pool = pool->next)
13875 /* Put it at the end of the relevent section. */
13876 subseg_set (pool->section, pool->sub_section);
13877 #ifdef OBJ_ELF
13878 arm_elf_change_section ();
13879 #endif
13880 s_ltorg (0);
13884 void
13885 arm_start_line_hook ()
13887 last_label_seen = NULL;
13890 void
13891 arm_frob_label (sym)
13892 symbolS * sym;
13894 last_label_seen = sym;
13896 ARM_SET_THUMB (sym, thumb_mode);
13898 #if defined OBJ_COFF || defined OBJ_ELF
13899 ARM_SET_INTERWORK (sym, support_interwork);
13900 #endif
13902 /* Note - do not allow local symbols (.Lxxx) to be labeled
13903 as Thumb functions. This is because these labels, whilst
13904 they exist inside Thumb code, are not the entry points for
13905 possible ARM->Thumb calls. Also, these labels can be used
13906 as part of a computed goto or switch statement. eg gcc
13907 can generate code that looks like this:
13909 ldr r2, [pc, .Laaa]
13910 lsl r3, r3, #2
13911 ldr r2, [r3, r2]
13912 mov pc, r2
13914 .Lbbb: .word .Lxxx
13915 .Lccc: .word .Lyyy
13916 ..etc...
13917 .Laaa: .word Lbbb
13919 The first instruction loads the address of the jump table.
13920 The second instruction converts a table index into a byte offset.
13921 The third instruction gets the jump address out of the table.
13922 The fourth instruction performs the jump.
13924 If the address stored at .Laaa is that of a symbol which has the
13925 Thumb_Func bit set, then the linker will arrange for this address
13926 to have the bottom bit set, which in turn would mean that the
13927 address computation performed by the third instruction would end
13928 up with the bottom bit set. Since the ARM is capable of unaligned
13929 word loads, the instruction would then load the incorrect address
13930 out of the jump table, and chaos would ensue. */
13931 if (label_is_thumb_function_name
13932 && (S_GET_NAME (sym)[0] != '.' || S_GET_NAME (sym)[1] != 'L')
13933 && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
13935 /* When the address of a Thumb function is taken the bottom
13936 bit of that address should be set. This will allow
13937 interworking between Arm and Thumb functions to work
13938 correctly. */
13940 THUMB_SET_FUNC (sym, 1);
13942 label_is_thumb_function_name = FALSE;
13946 /* Adjust the symbol table. This marks Thumb symbols as distinct from
13947 ARM ones. */
13949 void
13950 arm_adjust_symtab ()
13952 #ifdef OBJ_COFF
13953 symbolS * sym;
13955 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13957 if (ARM_IS_THUMB (sym))
13959 if (THUMB_IS_FUNC (sym))
13961 /* Mark the symbol as a Thumb function. */
13962 if ( S_GET_STORAGE_CLASS (sym) == C_STAT
13963 || S_GET_STORAGE_CLASS (sym) == C_LABEL) /* This can happen! */
13964 S_SET_STORAGE_CLASS (sym, C_THUMBSTATFUNC);
13966 else if (S_GET_STORAGE_CLASS (sym) == C_EXT)
13967 S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC);
13968 else
13969 as_bad (_("%s: unexpected function type: %d"),
13970 S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym));
13972 else switch (S_GET_STORAGE_CLASS (sym))
13974 case C_EXT:
13975 S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
13976 break;
13977 case C_STAT:
13978 S_SET_STORAGE_CLASS (sym, C_THUMBSTAT);
13979 break;
13980 case C_LABEL:
13981 S_SET_STORAGE_CLASS (sym, C_THUMBLABEL);
13982 break;
13983 default:
13984 /* Do nothing. */
13985 break;
13989 if (ARM_IS_INTERWORK (sym))
13990 coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_flags = 0xFF;
13992 #endif
13993 #ifdef OBJ_ELF
13994 symbolS * sym;
13995 char bind;
13997 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13999 if (ARM_IS_THUMB (sym))
14001 elf_symbol_type * elf_sym;
14003 elf_sym = elf_symbol (symbol_get_bfdsym (sym));
14004 bind = ELF_ST_BIND (elf_sym);
14006 /* If it's a .thumb_func, declare it as so,
14007 otherwise tag label as .code 16. */
14008 if (THUMB_IS_FUNC (sym))
14009 elf_sym->internal_elf_sym.st_info =
14010 ELF_ST_INFO (bind, STT_ARM_TFUNC);
14011 else
14012 elf_sym->internal_elf_sym.st_info =
14013 ELF_ST_INFO (bind, STT_ARM_16BIT);
14016 #endif
14020 arm_data_in_code ()
14022 if (thumb_mode && ! strncmp (input_line_pointer + 1, "data:", 5))
14024 *input_line_pointer = '/';
14025 input_line_pointer += 5;
14026 *input_line_pointer = 0;
14027 return 1;
14030 return 0;
14033 char *
14034 arm_canonicalize_symbol_name (name)
14035 char * name;
14037 int len;
14039 if (thumb_mode && (len = strlen (name)) > 5
14040 && streq (name + len - 5, "/data"))
14041 *(name + len - 5) = 0;
14043 return name;
14046 #if defined OBJ_COFF || defined OBJ_ELF
14047 void
14048 arm_validate_fix (fixP)
14049 fixS * fixP;
14051 /* If the destination of the branch is a defined symbol which does not have
14052 the THUMB_FUNC attribute, then we must be calling a function which has
14053 the (interfacearm) attribute. We look for the Thumb entry point to that
14054 function and change the branch to refer to that function instead. */
14055 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23
14056 && fixP->fx_addsy != NULL
14057 && S_IS_DEFINED (fixP->fx_addsy)
14058 && ! THUMB_IS_FUNC (fixP->fx_addsy))
14060 fixP->fx_addsy = find_real_start (fixP->fx_addsy);
14063 #endif
14066 arm_force_relocation (fixp)
14067 struct fix * fixp;
14069 #if defined (OBJ_COFF) && defined (TE_PE)
14070 if (fixp->fx_r_type == BFD_RELOC_RVA)
14071 return 1;
14072 #endif
14073 #ifdef OBJ_ELF
14074 if (fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
14075 || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
14076 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX
14077 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23)
14078 return 1;
14079 #endif
14081 /* Resolve these relocations even if the symbol is extern or weak. */
14082 if (fixp->fx_r_type == BFD_RELOC_ARM_IMMEDIATE
14083 || fixp->fx_r_type == BFD_RELOC_ARM_OFFSET_IMM
14084 || fixp->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
14085 return 0;
14087 return generic_force_reloc (fixp);
14090 #ifdef OBJ_COFF
14091 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
14092 local labels from being added to the output symbol table when they
14093 are used with the ADRL pseudo op. The ADRL relocation should always
14094 be resolved before the binbary is emitted, so it is safe to say that
14095 it is adjustable. */
14097 bfd_boolean
14098 arm_fix_adjustable (fixP)
14099 fixS * fixP;
14101 if (fixP->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
14102 return 1;
14103 return 0;
14105 #endif
14107 #ifdef OBJ_ELF
14108 /* Relocations against Thumb function names must be left unadjusted,
14109 so that the linker can use this information to correctly set the
14110 bottom bit of their addresses. The MIPS version of this function
14111 also prevents relocations that are mips-16 specific, but I do not
14112 know why it does this.
14114 FIXME:
14115 There is one other problem that ought to be addressed here, but
14116 which currently is not: Taking the address of a label (rather
14117 than a function) and then later jumping to that address. Such
14118 addresses also ought to have their bottom bit set (assuming that
14119 they reside in Thumb code), but at the moment they will not. */
14121 bfd_boolean
14122 arm_fix_adjustable (fixP)
14123 fixS * fixP;
14125 if (fixP->fx_addsy == NULL)
14126 return 1;
14128 if (THUMB_IS_FUNC (fixP->fx_addsy)
14129 && fixP->fx_subsy == NULL)
14130 return 0;
14132 /* We need the symbol name for the VTABLE entries. */
14133 if ( fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
14134 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
14135 return 0;
14137 /* Don't allow symbols to be discarded on GOT related relocs. */
14138 if (fixP->fx_r_type == BFD_RELOC_ARM_PLT32
14139 || fixP->fx_r_type == BFD_RELOC_ARM_GOT32
14140 || fixP->fx_r_type == BFD_RELOC_ARM_GOTOFF)
14141 return 0;
14143 return 1;
14146 const char *
14147 elf32_arm_target_format ()
14149 if (target_big_endian)
14151 if (target_oabi)
14152 return "elf32-bigarm-oabi";
14153 else
14154 return "elf32-bigarm";
14156 else
14158 if (target_oabi)
14159 return "elf32-littlearm-oabi";
14160 else
14161 return "elf32-littlearm";
14165 void
14166 armelf_frob_symbol (symp, puntp)
14167 symbolS * symp;
14168 int * puntp;
14170 elf_frob_symbol (symp, puntp);
14173 static bfd_reloc_code_real_type
14174 arm_parse_reloc ()
14176 char id [16];
14177 char * ip;
14178 unsigned int i;
14179 static struct
14181 char * str;
14182 int len;
14183 bfd_reloc_code_real_type reloc;
14185 reloc_map[] =
14187 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
14188 MAP ("(got)", BFD_RELOC_ARM_GOT32),
14189 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF),
14190 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
14191 branch instructions generated by GCC for PLT relocs. */
14192 MAP ("(plt)", BFD_RELOC_ARM_PLT32),
14193 { NULL, 0, BFD_RELOC_UNUSED }
14194 #undef MAP
14197 for (i = 0, ip = input_line_pointer;
14198 i < sizeof (id) && (ISALNUM (*ip) || ISPUNCT (*ip));
14199 i++, ip++)
14200 id[i] = TOLOWER (*ip);
14202 for (i = 0; reloc_map[i].str; i++)
14203 if (strncmp (id, reloc_map[i].str, reloc_map[i].len) == 0)
14204 break;
14206 input_line_pointer += reloc_map[i].len;
14208 return reloc_map[i].reloc;
14211 static void
14212 s_arm_elf_cons (nbytes)
14213 int nbytes;
14215 expressionS exp;
14217 #ifdef md_flush_pending_output
14218 md_flush_pending_output ();
14219 #endif
14221 if (is_it_end_of_statement ())
14223 demand_empty_rest_of_line ();
14224 return;
14227 #ifdef md_cons_align
14228 md_cons_align (nbytes);
14229 #endif
14231 mapping_state (MAP_DATA);
14234 bfd_reloc_code_real_type reloc;
14236 expression (& exp);
14238 if (exp.X_op == O_symbol
14239 && * input_line_pointer == '('
14240 && (reloc = arm_parse_reloc ()) != BFD_RELOC_UNUSED)
14242 reloc_howto_type *howto = bfd_reloc_type_lookup (stdoutput, reloc);
14243 int size = bfd_get_reloc_size (howto);
14245 if (size > nbytes)
14246 as_bad ("%s relocations do not fit in %d bytes",
14247 howto->name, nbytes);
14248 else
14250 register char *p = frag_more ((int) nbytes);
14251 int offset = nbytes - size;
14253 fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size,
14254 &exp, 0, reloc);
14257 else
14258 emit_expr (&exp, (unsigned int) nbytes);
14260 while (*input_line_pointer++ == ',');
14262 /* Put terminator back into stream. */
14263 input_line_pointer --;
14264 demand_empty_rest_of_line ();
14267 #endif /* OBJ_ELF */
14269 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
14270 of an rs_align_code fragment. */
14272 void
14273 arm_handle_align (fragP)
14274 fragS *fragP;
14276 static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 };
14277 static char const thumb_noop[2] = { 0xc0, 0x46 };
14278 static char const arm_bigend_noop[4] = { 0xe1, 0xa0, 0x00, 0x00 };
14279 static char const thumb_bigend_noop[2] = { 0x46, 0xc0 };
14281 int bytes, fix, noop_size;
14282 char * p;
14283 const char * noop;
14285 if (fragP->fr_type != rs_align_code)
14286 return;
14288 bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
14289 p = fragP->fr_literal + fragP->fr_fix;
14290 fix = 0;
14292 if (bytes > MAX_MEM_FOR_RS_ALIGN_CODE)
14293 bytes &= MAX_MEM_FOR_RS_ALIGN_CODE;
14295 if (fragP->tc_frag_data)
14297 if (target_big_endian)
14298 noop = thumb_bigend_noop;
14299 else
14300 noop = thumb_noop;
14301 noop_size = sizeof (thumb_noop);
14303 else
14305 if (target_big_endian)
14306 noop = arm_bigend_noop;
14307 else
14308 noop = arm_noop;
14309 noop_size = sizeof (arm_noop);
14312 if (bytes & (noop_size - 1))
14314 fix = bytes & (noop_size - 1);
14315 memset (p, 0, fix);
14316 p += fix;
14317 bytes -= fix;
14320 while (bytes >= noop_size)
14322 memcpy (p, noop, noop_size);
14323 p += noop_size;
14324 bytes -= noop_size;
14325 fix += noop_size;
14328 fragP->fr_fix += fix;
14329 fragP->fr_var = noop_size;
14332 /* Called from md_do_align. Used to create an alignment
14333 frag in a code section. */
14335 void
14336 arm_frag_align_code (n, max)
14337 int n;
14338 int max;
14340 char * p;
14342 /* We assume that there will never be a requirement
14343 to support alignments greater than 32 bytes. */
14344 if (max > MAX_MEM_FOR_RS_ALIGN_CODE)
14345 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
14347 p = frag_var (rs_align_code,
14348 MAX_MEM_FOR_RS_ALIGN_CODE,
14350 (relax_substateT) max,
14351 (symbolS *) NULL,
14352 (offsetT) n,
14353 (char *) NULL);
14354 *p = 0;
14358 /* Perform target specific initialisation of a frag. */
14360 void
14361 arm_init_frag (fragP)
14362 fragS *fragP;
14364 /* Record whether this frag is in an ARM or a THUMB area. */
14365 fragP->tc_frag_data = thumb_mode;