* config/tc-arm.c (do_umaal): Fix typo.
[binutils.git] / gas / config / tc-arm.c
blobf1ea372a55b0dfc55341f235d858b95988aa65fd
1 /* tc-arm.c -- Assemble for the ARM
2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
3 Free Software Foundation, Inc.
4 Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
5 Modified by David Taylor (dtaylor@armltd.co.uk)
6 Cirrus coprocessor mods by Aldy Hernandez (aldyh@redhat.com)
8 This file is part of GAS, the GNU Assembler.
10 GAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
13 any later version.
15 GAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with GAS; see the file COPYING. If not, write to the Free
22 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
23 02111-1307, USA. */
25 #include <string.h>
26 #define NO_RELOC 0
27 #include "as.h"
28 #include "safe-ctype.h"
30 /* Need TARGET_CPU. */
31 #include "config.h"
32 #include "subsegs.h"
33 #include "obstack.h"
34 #include "symbols.h"
35 #include "listing.h"
37 #ifdef OBJ_ELF
38 #include "elf/arm.h"
39 #include "dwarf2dbg.h"
40 #endif
42 /* XXX Set this to 1 after the next binutils release */
43 #define WARN_DEPRECATED 0
45 /* The following bitmasks control CPU extensions: */
46 #define ARM_EXT_V1 0x00000001 /* All processors (core set). */
47 #define ARM_EXT_V2 0x00000002 /* Multiply instructions. */
48 #define ARM_EXT_V2S 0x00000004 /* SWP instructions. */
49 #define ARM_EXT_V3 0x00000008 /* MSR MRS. */
50 #define ARM_EXT_V3M 0x00000010 /* Allow long multiplies. */
51 #define ARM_EXT_V4 0x00000020 /* Allow half word loads. */
52 #define ARM_EXT_V4T 0x00000040 /* Thumb v1. */
53 #define ARM_EXT_V5 0x00000080 /* Allow CLZ, etc. */
54 #define ARM_EXT_V5T 0x00000100 /* Thumb v2. */
55 #define ARM_EXT_V5ExP 0x00000200 /* DSP core set. */
56 #define ARM_EXT_V5E 0x00000400 /* DSP Double transfers. */
57 #define ARM_EXT_V5J 0x00000800 /* Jazelle extension. */
58 #define ARM_EXT_V6 0x00001000 /* ARM V6. */
60 /* Co-processor space extensions. */
61 #define ARM_CEXT_XSCALE 0x00800000 /* Allow MIA etc. */
62 #define ARM_CEXT_MAVERICK 0x00400000 /* Use Cirrus/DSP coprocessor. */
63 #define ARM_CEXT_IWMMXT 0x00200000 /* Intel Wireless MMX technology coprocessor. */
65 /* Architectures are the sum of the base and extensions. The ARM ARM (rev E)
66 defines the following: ARMv3, ARMv3M, ARMv4xM, ARMv4, ARMv4TxM, ARMv4T,
67 ARMv5xM, ARMv5, ARMv5TxM, ARMv5T, ARMv5TExP, ARMv5TE. To these we add
68 three more to cover cores prior to ARM6. Finally, there are cores which
69 implement further extensions in the co-processor space. */
70 #define ARM_ARCH_V1 ARM_EXT_V1
71 #define ARM_ARCH_V2 (ARM_ARCH_V1 | ARM_EXT_V2)
72 #define ARM_ARCH_V2S (ARM_ARCH_V2 | ARM_EXT_V2S)
73 #define ARM_ARCH_V3 (ARM_ARCH_V2S | ARM_EXT_V3)
74 #define ARM_ARCH_V3M (ARM_ARCH_V3 | ARM_EXT_V3M)
75 #define ARM_ARCH_V4xM (ARM_ARCH_V3 | ARM_EXT_V4)
76 #define ARM_ARCH_V4 (ARM_ARCH_V3M | ARM_EXT_V4)
77 #define ARM_ARCH_V4TxM (ARM_ARCH_V4xM | ARM_EXT_V4T)
78 #define ARM_ARCH_V4T (ARM_ARCH_V4 | ARM_EXT_V4T)
79 #define ARM_ARCH_V5xM (ARM_ARCH_V4xM | ARM_EXT_V5)
80 #define ARM_ARCH_V5 (ARM_ARCH_V4 | ARM_EXT_V5)
81 #define ARM_ARCH_V5TxM (ARM_ARCH_V5xM | ARM_EXT_V4T | ARM_EXT_V5T)
82 #define ARM_ARCH_V5T (ARM_ARCH_V5 | ARM_EXT_V4T | ARM_EXT_V5T)
83 #define ARM_ARCH_V5TExP (ARM_ARCH_V5T | ARM_EXT_V5ExP)
84 #define ARM_ARCH_V5TE (ARM_ARCH_V5TExP | ARM_EXT_V5E)
85 #define ARM_ARCH_V5TEJ (ARM_ARCH_V5TE | ARM_EXT_V5J)
86 #define ARM_ARCH_V6 (ARM_ARCH_V5TEJ | ARM_EXT_V6)
88 /* Processors with specific extensions in the co-processor space. */
89 #define ARM_ARCH_XSCALE (ARM_ARCH_V5TE | ARM_CEXT_XSCALE)
90 #define ARM_ARCH_IWMMXT (ARM_ARCH_XSCALE | ARM_CEXT_IWMMXT)
92 /* Some useful combinations: */
93 #define ARM_ANY 0x0000ffff /* Any basic core. */
94 #define ARM_ALL 0x00ffffff /* Any core + co-processor */
95 #define CPROC_ANY 0x00ff0000 /* Any co-processor */
96 #define FPU_ANY 0xff000000 /* Note this is ~ARM_ALL. */
99 #define FPU_FPA_EXT_V1 0x80000000 /* Base FPA instruction set. */
100 #define FPU_FPA_EXT_V2 0x40000000 /* LFM/SFM. */
101 #define FPU_VFP_EXT_NONE 0x20000000 /* Use VFP word-ordering. */
102 #define FPU_VFP_EXT_V1xD 0x10000000 /* Base VFP instruction set. */
103 #define FPU_VFP_EXT_V1 0x08000000 /* Double-precision insns. */
104 #define FPU_VFP_EXT_V2 0x04000000 /* ARM10E VFPr1. */
105 #define FPU_NONE 0
107 #define FPU_ARCH_FPE FPU_FPA_EXT_V1
108 #define FPU_ARCH_FPA (FPU_ARCH_FPE | FPU_FPA_EXT_V2)
110 #define FPU_ARCH_VFP FPU_VFP_EXT_NONE
111 #define FPU_ARCH_VFP_V1xD (FPU_VFP_EXT_V1xD | FPU_VFP_EXT_NONE)
112 #define FPU_ARCH_VFP_V1 (FPU_ARCH_VFP_V1xD | FPU_VFP_EXT_V1)
113 #define FPU_ARCH_VFP_V2 (FPU_ARCH_VFP_V1 | FPU_VFP_EXT_V2)
115 /* Types of processor to assemble for. */
116 #define ARM_1 ARM_ARCH_V1
117 #define ARM_2 ARM_ARCH_V2
118 #define ARM_3 ARM_ARCH_V2S
119 #define ARM_250 ARM_ARCH_V2S
120 #define ARM_6 ARM_ARCH_V3
121 #define ARM_7 ARM_ARCH_V3
122 #define ARM_8 ARM_ARCH_V4
123 #define ARM_9 ARM_ARCH_V4T
124 #define ARM_STRONG ARM_ARCH_V4
125 #define ARM_CPU_MASK 0x0000000f /* XXX? */
127 #ifndef CPU_DEFAULT
128 #if defined __XSCALE__
129 #define CPU_DEFAULT (ARM_ARCH_XSCALE)
130 #else
131 #if defined __thumb__
132 #define CPU_DEFAULT (ARM_ARCH_V5T)
133 #else
134 #define CPU_DEFAULT ARM_ANY
135 #endif
136 #endif
137 #endif
139 #ifdef TE_LINUX
140 #define FPU_DEFAULT FPU_ARCH_FPA
141 #endif
143 #ifdef TE_NetBSD
144 #ifdef OBJ_ELF
145 #define FPU_DEFAULT FPU_ARCH_VFP /* Soft-float, but VFP order. */
146 #else
147 /* Legacy a.out format. */
148 #define FPU_DEFAULT FPU_ARCH_FPA /* Soft-float, but FPA order. */
149 #endif
150 #endif
152 /* For backwards compatibility we default to the FPA. */
153 #ifndef FPU_DEFAULT
154 #define FPU_DEFAULT FPU_ARCH_FPA
155 #endif
157 #define streq(a, b) (strcmp (a, b) == 0)
158 #define skip_whitespace(str) while (*(str) == ' ') ++(str)
160 static unsigned long cpu_variant;
161 static int target_oabi = 0;
163 /* Flags stored in private area of BFD structure. */
164 static int uses_apcs_26 = FALSE;
165 static int atpcs = FALSE;
166 static int support_interwork = FALSE;
167 static int uses_apcs_float = FALSE;
168 static int pic_code = FALSE;
170 /* Variables that we set while parsing command-line options. Once all
171 options have been read we re-process these values to set the real
172 assembly flags. */
173 static int legacy_cpu = -1;
174 static int legacy_fpu = -1;
176 static int mcpu_cpu_opt = -1;
177 static int mcpu_fpu_opt = -1;
178 static int march_cpu_opt = -1;
179 static int march_fpu_opt = -1;
180 static int mfpu_opt = -1;
182 /* This array holds the chars that always start a comment. If the
183 pre-processor is disabled, these aren't very useful. */
184 const char comment_chars[] = "@";
186 /* This array holds the chars that only start a comment at the beginning of
187 a line. If the line seems to have the form '# 123 filename'
188 .line and .file directives will appear in the pre-processed output. */
189 /* Note that input_file.c hand checks for '#' at the beginning of the
190 first line of the input file. This is because the compiler outputs
191 #NO_APP at the beginning of its output. */
192 /* Also note that comments like this one will always work. */
193 const char line_comment_chars[] = "#";
195 const char line_separator_chars[] = ";";
197 /* Chars that can be used to separate mant
198 from exp in floating point numbers. */
199 const char EXP_CHARS[] = "eE";
201 /* Chars that mean this number is a floating point constant. */
202 /* As in 0f12.456 */
203 /* or 0d1.2345e12 */
205 const char FLT_CHARS[] = "rRsSfFdDxXeEpP";
207 /* Prefix characters that indicate the start of an immediate
208 value. */
209 #define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
211 #ifdef OBJ_ELF
212 /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
213 symbolS * GOT_symbol;
214 #endif
216 /* Size of relocation record. */
217 const int md_reloc_size = 8;
219 /* 0: assemble for ARM,
220 1: assemble for Thumb,
221 2: assemble for Thumb even though target CPU does not support thumb
222 instructions. */
223 static int thumb_mode = 0;
225 typedef struct arm_fix
227 int thumb_mode;
228 } arm_fix_data;
230 struct arm_it
232 const char * error;
233 unsigned long instruction;
234 int size;
235 struct
237 bfd_reloc_code_real_type type;
238 expressionS exp;
239 int pc_rel;
240 } reloc;
243 struct arm_it inst;
245 enum asm_shift_index
247 SHIFT_LSL = 0,
248 SHIFT_LSR,
249 SHIFT_ASR,
250 SHIFT_ROR,
251 SHIFT_RRX
254 struct asm_shift_properties
256 enum asm_shift_index index;
257 unsigned long bit_field;
258 unsigned int allows_0 : 1;
259 unsigned int allows_32 : 1;
262 static const struct asm_shift_properties shift_properties [] =
264 { SHIFT_LSL, 0, 1, 0},
265 { SHIFT_LSR, 0x20, 0, 1},
266 { SHIFT_ASR, 0x40, 0, 1},
267 { SHIFT_ROR, 0x60, 0, 0},
268 { SHIFT_RRX, 0x60, 0, 0}
271 struct asm_shift_name
273 const char * name;
274 const struct asm_shift_properties * properties;
277 static const struct asm_shift_name shift_names [] =
279 { "asl", shift_properties + SHIFT_LSL },
280 { "lsl", shift_properties + SHIFT_LSL },
281 { "lsr", shift_properties + SHIFT_LSR },
282 { "asr", shift_properties + SHIFT_ASR },
283 { "ror", shift_properties + SHIFT_ROR },
284 { "rrx", shift_properties + SHIFT_RRX },
285 { "ASL", shift_properties + SHIFT_LSL },
286 { "LSL", shift_properties + SHIFT_LSL },
287 { "LSR", shift_properties + SHIFT_LSR },
288 { "ASR", shift_properties + SHIFT_ASR },
289 { "ROR", shift_properties + SHIFT_ROR },
290 { "RRX", shift_properties + SHIFT_RRX }
293 /* Any kind of shift is accepted. */
294 #define NO_SHIFT_RESTRICT 1
295 /* The shift operand must be an immediate value, not a register. */
296 #define SHIFT_IMMEDIATE 0
297 /* The shift must be LSL or ASR and the operand must be an immediate. */
298 #define SHIFT_LSL_OR_ASR_IMMEDIATE 2
299 /* The shift must be ASR and the operand must be an immediate. */
300 #define SHIFT_ASR_IMMEDIATE 3
301 /* The shift must be LSL and the operand must be an immediate. */
302 #define SHIFT_LSL_IMMEDIATE 4
304 #define NUM_FLOAT_VALS 8
306 const char * fp_const[] =
308 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
311 /* Number of littlenums required to hold an extended precision number. */
312 #define MAX_LITTLENUMS 6
314 LITTLENUM_TYPE fp_values[NUM_FLOAT_VALS][MAX_LITTLENUMS];
316 #define FAIL (-1)
317 #define SUCCESS (0)
319 /* Whether a Co-processor load/store operation accepts write-back forms. */
320 #define CP_WB_OK 1
321 #define CP_NO_WB 0
323 #define SUFF_S 1
324 #define SUFF_D 2
325 #define SUFF_E 3
326 #define SUFF_P 4
328 #define CP_T_X 0x00008000
329 #define CP_T_Y 0x00400000
330 #define CP_T_Pre 0x01000000
331 #define CP_T_UD 0x00800000
332 #define CP_T_WB 0x00200000
334 #define CONDS_BIT 0x00100000
335 #define LOAD_BIT 0x00100000
337 #define DOUBLE_LOAD_FLAG 0x00000001
339 struct asm_cond
341 const char * template;
342 unsigned long value;
345 #define COND_ALWAYS 0xe0000000
346 #define COND_MASK 0xf0000000
348 static const struct asm_cond conds[] =
350 {"eq", 0x00000000},
351 {"ne", 0x10000000},
352 {"cs", 0x20000000}, {"hs", 0x20000000},
353 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
354 {"mi", 0x40000000},
355 {"pl", 0x50000000},
356 {"vs", 0x60000000},
357 {"vc", 0x70000000},
358 {"hi", 0x80000000},
359 {"ls", 0x90000000},
360 {"ge", 0xa0000000},
361 {"lt", 0xb0000000},
362 {"gt", 0xc0000000},
363 {"le", 0xd0000000},
364 {"al", 0xe0000000},
365 {"nv", 0xf0000000}
368 struct asm_psr
370 const char *template;
371 bfd_boolean cpsr;
372 unsigned long field;
375 /* The bit that distinguishes CPSR and SPSR. */
376 #define SPSR_BIT (1 << 22)
378 /* How many bits to shift the PSR_xxx bits up by. */
379 #define PSR_SHIFT 16
381 #define PSR_c (1 << 0)
382 #define PSR_x (1 << 1)
383 #define PSR_s (1 << 2)
384 #define PSR_f (1 << 3)
386 static const struct asm_psr psrs[] =
388 {"CPSR", TRUE, PSR_c | PSR_f},
389 {"CPSR_all", TRUE, PSR_c | PSR_f},
390 {"SPSR", FALSE, PSR_c | PSR_f},
391 {"SPSR_all", FALSE, PSR_c | PSR_f},
392 {"CPSR_flg", TRUE, PSR_f},
393 {"CPSR_f", TRUE, PSR_f},
394 {"SPSR_flg", FALSE, PSR_f},
395 {"SPSR_f", FALSE, PSR_f},
396 {"CPSR_c", TRUE, PSR_c},
397 {"CPSR_ctl", TRUE, PSR_c},
398 {"SPSR_c", FALSE, PSR_c},
399 {"SPSR_ctl", FALSE, PSR_c},
400 {"CPSR_x", TRUE, PSR_x},
401 {"CPSR_s", TRUE, PSR_s},
402 {"SPSR_x", FALSE, PSR_x},
403 {"SPSR_s", FALSE, PSR_s},
404 /* Combinations of flags. */
405 {"CPSR_fs", TRUE, PSR_f | PSR_s},
406 {"CPSR_fx", TRUE, PSR_f | PSR_x},
407 {"CPSR_fc", TRUE, PSR_f | PSR_c},
408 {"CPSR_sf", TRUE, PSR_s | PSR_f},
409 {"CPSR_sx", TRUE, PSR_s | PSR_x},
410 {"CPSR_sc", TRUE, PSR_s | PSR_c},
411 {"CPSR_xf", TRUE, PSR_x | PSR_f},
412 {"CPSR_xs", TRUE, PSR_x | PSR_s},
413 {"CPSR_xc", TRUE, PSR_x | PSR_c},
414 {"CPSR_cf", TRUE, PSR_c | PSR_f},
415 {"CPSR_cs", TRUE, PSR_c | PSR_s},
416 {"CPSR_cx", TRUE, PSR_c | PSR_x},
417 {"CPSR_fsx", TRUE, PSR_f | PSR_s | PSR_x},
418 {"CPSR_fsc", TRUE, PSR_f | PSR_s | PSR_c},
419 {"CPSR_fxs", TRUE, PSR_f | PSR_x | PSR_s},
420 {"CPSR_fxc", TRUE, PSR_f | PSR_x | PSR_c},
421 {"CPSR_fcs", TRUE, PSR_f | PSR_c | PSR_s},
422 {"CPSR_fcx", TRUE, PSR_f | PSR_c | PSR_x},
423 {"CPSR_sfx", TRUE, PSR_s | PSR_f | PSR_x},
424 {"CPSR_sfc", TRUE, PSR_s | PSR_f | PSR_c},
425 {"CPSR_sxf", TRUE, PSR_s | PSR_x | PSR_f},
426 {"CPSR_sxc", TRUE, PSR_s | PSR_x | PSR_c},
427 {"CPSR_scf", TRUE, PSR_s | PSR_c | PSR_f},
428 {"CPSR_scx", TRUE, PSR_s | PSR_c | PSR_x},
429 {"CPSR_xfs", TRUE, PSR_x | PSR_f | PSR_s},
430 {"CPSR_xfc", TRUE, PSR_x | PSR_f | PSR_c},
431 {"CPSR_xsf", TRUE, PSR_x | PSR_s | PSR_f},
432 {"CPSR_xsc", TRUE, PSR_x | PSR_s | PSR_c},
433 {"CPSR_xcf", TRUE, PSR_x | PSR_c | PSR_f},
434 {"CPSR_xcs", TRUE, PSR_x | PSR_c | PSR_s},
435 {"CPSR_cfs", TRUE, PSR_c | PSR_f | PSR_s},
436 {"CPSR_cfx", TRUE, PSR_c | PSR_f | PSR_x},
437 {"CPSR_csf", TRUE, PSR_c | PSR_s | PSR_f},
438 {"CPSR_csx", TRUE, PSR_c | PSR_s | PSR_x},
439 {"CPSR_cxf", TRUE, PSR_c | PSR_x | PSR_f},
440 {"CPSR_cxs", TRUE, PSR_c | PSR_x | PSR_s},
441 {"CPSR_fsxc", TRUE, PSR_f | PSR_s | PSR_x | PSR_c},
442 {"CPSR_fscx", TRUE, PSR_f | PSR_s | PSR_c | PSR_x},
443 {"CPSR_fxsc", TRUE, PSR_f | PSR_x | PSR_s | PSR_c},
444 {"CPSR_fxcs", TRUE, PSR_f | PSR_x | PSR_c | PSR_s},
445 {"CPSR_fcsx", TRUE, PSR_f | PSR_c | PSR_s | PSR_x},
446 {"CPSR_fcxs", TRUE, PSR_f | PSR_c | PSR_x | PSR_s},
447 {"CPSR_sfxc", TRUE, PSR_s | PSR_f | PSR_x | PSR_c},
448 {"CPSR_sfcx", TRUE, PSR_s | PSR_f | PSR_c | PSR_x},
449 {"CPSR_sxfc", TRUE, PSR_s | PSR_x | PSR_f | PSR_c},
450 {"CPSR_sxcf", TRUE, PSR_s | PSR_x | PSR_c | PSR_f},
451 {"CPSR_scfx", TRUE, PSR_s | PSR_c | PSR_f | PSR_x},
452 {"CPSR_scxf", TRUE, PSR_s | PSR_c | PSR_x | PSR_f},
453 {"CPSR_xfsc", TRUE, PSR_x | PSR_f | PSR_s | PSR_c},
454 {"CPSR_xfcs", TRUE, PSR_x | PSR_f | PSR_c | PSR_s},
455 {"CPSR_xsfc", TRUE, PSR_x | PSR_s | PSR_f | PSR_c},
456 {"CPSR_xscf", TRUE, PSR_x | PSR_s | PSR_c | PSR_f},
457 {"CPSR_xcfs", TRUE, PSR_x | PSR_c | PSR_f | PSR_s},
458 {"CPSR_xcsf", TRUE, PSR_x | PSR_c | PSR_s | PSR_f},
459 {"CPSR_cfsx", TRUE, PSR_c | PSR_f | PSR_s | PSR_x},
460 {"CPSR_cfxs", TRUE, PSR_c | PSR_f | PSR_x | PSR_s},
461 {"CPSR_csfx", TRUE, PSR_c | PSR_s | PSR_f | PSR_x},
462 {"CPSR_csxf", TRUE, PSR_c | PSR_s | PSR_x | PSR_f},
463 {"CPSR_cxfs", TRUE, PSR_c | PSR_x | PSR_f | PSR_s},
464 {"CPSR_cxsf", TRUE, PSR_c | PSR_x | PSR_s | PSR_f},
465 {"SPSR_fs", FALSE, PSR_f | PSR_s},
466 {"SPSR_fx", FALSE, PSR_f | PSR_x},
467 {"SPSR_fc", FALSE, PSR_f | PSR_c},
468 {"SPSR_sf", FALSE, PSR_s | PSR_f},
469 {"SPSR_sx", FALSE, PSR_s | PSR_x},
470 {"SPSR_sc", FALSE, PSR_s | PSR_c},
471 {"SPSR_xf", FALSE, PSR_x | PSR_f},
472 {"SPSR_xs", FALSE, PSR_x | PSR_s},
473 {"SPSR_xc", FALSE, PSR_x | PSR_c},
474 {"SPSR_cf", FALSE, PSR_c | PSR_f},
475 {"SPSR_cs", FALSE, PSR_c | PSR_s},
476 {"SPSR_cx", FALSE, PSR_c | PSR_x},
477 {"SPSR_fsx", FALSE, PSR_f | PSR_s | PSR_x},
478 {"SPSR_fsc", FALSE, PSR_f | PSR_s | PSR_c},
479 {"SPSR_fxs", FALSE, PSR_f | PSR_x | PSR_s},
480 {"SPSR_fxc", FALSE, PSR_f | PSR_x | PSR_c},
481 {"SPSR_fcs", FALSE, PSR_f | PSR_c | PSR_s},
482 {"SPSR_fcx", FALSE, PSR_f | PSR_c | PSR_x},
483 {"SPSR_sfx", FALSE, PSR_s | PSR_f | PSR_x},
484 {"SPSR_sfc", FALSE, PSR_s | PSR_f | PSR_c},
485 {"SPSR_sxf", FALSE, PSR_s | PSR_x | PSR_f},
486 {"SPSR_sxc", FALSE, PSR_s | PSR_x | PSR_c},
487 {"SPSR_scf", FALSE, PSR_s | PSR_c | PSR_f},
488 {"SPSR_scx", FALSE, PSR_s | PSR_c | PSR_x},
489 {"SPSR_xfs", FALSE, PSR_x | PSR_f | PSR_s},
490 {"SPSR_xfc", FALSE, PSR_x | PSR_f | PSR_c},
491 {"SPSR_xsf", FALSE, PSR_x | PSR_s | PSR_f},
492 {"SPSR_xsc", FALSE, PSR_x | PSR_s | PSR_c},
493 {"SPSR_xcf", FALSE, PSR_x | PSR_c | PSR_f},
494 {"SPSR_xcs", FALSE, PSR_x | PSR_c | PSR_s},
495 {"SPSR_cfs", FALSE, PSR_c | PSR_f | PSR_s},
496 {"SPSR_cfx", FALSE, PSR_c | PSR_f | PSR_x},
497 {"SPSR_csf", FALSE, PSR_c | PSR_s | PSR_f},
498 {"SPSR_csx", FALSE, PSR_c | PSR_s | PSR_x},
499 {"SPSR_cxf", FALSE, PSR_c | PSR_x | PSR_f},
500 {"SPSR_cxs", FALSE, PSR_c | PSR_x | PSR_s},
501 {"SPSR_fsxc", FALSE, PSR_f | PSR_s | PSR_x | PSR_c},
502 {"SPSR_fscx", FALSE, PSR_f | PSR_s | PSR_c | PSR_x},
503 {"SPSR_fxsc", FALSE, PSR_f | PSR_x | PSR_s | PSR_c},
504 {"SPSR_fxcs", FALSE, PSR_f | PSR_x | PSR_c | PSR_s},
505 {"SPSR_fcsx", FALSE, PSR_f | PSR_c | PSR_s | PSR_x},
506 {"SPSR_fcxs", FALSE, PSR_f | PSR_c | PSR_x | PSR_s},
507 {"SPSR_sfxc", FALSE, PSR_s | PSR_f | PSR_x | PSR_c},
508 {"SPSR_sfcx", FALSE, PSR_s | PSR_f | PSR_c | PSR_x},
509 {"SPSR_sxfc", FALSE, PSR_s | PSR_x | PSR_f | PSR_c},
510 {"SPSR_sxcf", FALSE, PSR_s | PSR_x | PSR_c | PSR_f},
511 {"SPSR_scfx", FALSE, PSR_s | PSR_c | PSR_f | PSR_x},
512 {"SPSR_scxf", FALSE, PSR_s | PSR_c | PSR_x | PSR_f},
513 {"SPSR_xfsc", FALSE, PSR_x | PSR_f | PSR_s | PSR_c},
514 {"SPSR_xfcs", FALSE, PSR_x | PSR_f | PSR_c | PSR_s},
515 {"SPSR_xsfc", FALSE, PSR_x | PSR_s | PSR_f | PSR_c},
516 {"SPSR_xscf", FALSE, PSR_x | PSR_s | PSR_c | PSR_f},
517 {"SPSR_xcfs", FALSE, PSR_x | PSR_c | PSR_f | PSR_s},
518 {"SPSR_xcsf", FALSE, PSR_x | PSR_c | PSR_s | PSR_f},
519 {"SPSR_cfsx", FALSE, PSR_c | PSR_f | PSR_s | PSR_x},
520 {"SPSR_cfxs", FALSE, PSR_c | PSR_f | PSR_x | PSR_s},
521 {"SPSR_csfx", FALSE, PSR_c | PSR_s | PSR_f | PSR_x},
522 {"SPSR_csxf", FALSE, PSR_c | PSR_s | PSR_x | PSR_f},
523 {"SPSR_cxfs", FALSE, PSR_c | PSR_x | PSR_f | PSR_s},
524 {"SPSR_cxsf", FALSE, PSR_c | PSR_x | PSR_s | PSR_f},
527 enum wreg_type
529 IWMMXT_REG_WR = 0,
530 IWMMXT_REG_WC = 1,
531 IWMMXT_REG_WR_OR_WC = 2,
532 IWMMXT_REG_WCG
535 enum iwmmxt_insn_type
537 check_rd,
538 check_wr,
539 check_wrwr,
540 check_wrwrwr,
541 check_wrwrwcg,
542 check_tbcst,
543 check_tmovmsk,
544 check_tmia,
545 check_tmcrr,
546 check_tmrrc,
547 check_tmcr,
548 check_tmrc,
549 check_tinsr,
550 check_textrc,
551 check_waligni,
552 check_textrm,
553 check_wshufh
556 enum vfp_dp_reg_pos
558 VFP_REG_Dd, VFP_REG_Dm, VFP_REG_Dn
561 enum vfp_sp_reg_pos
563 VFP_REG_Sd, VFP_REG_Sm, VFP_REG_Sn
566 enum vfp_ldstm_type
568 VFP_LDSTMIA, VFP_LDSTMDB, VFP_LDSTMIAX, VFP_LDSTMDBX
571 /* VFP system registers. */
572 struct vfp_reg
574 const char *name;
575 unsigned long regno;
578 static const struct vfp_reg vfp_regs[] =
580 {"fpsid", 0x00000000},
581 {"FPSID", 0x00000000},
582 {"fpscr", 0x00010000},
583 {"FPSCR", 0x00010000},
584 {"fpexc", 0x00080000},
585 {"FPEXC", 0x00080000}
588 /* Structure for a hash table entry for a register. */
589 struct reg_entry
591 const char * name;
592 int number;
593 bfd_boolean builtin;
596 /* Some well known registers that we refer to directly elsewhere. */
597 #define REG_SP 13
598 #define REG_LR 14
599 #define REG_PC 15
601 #define wr_register(reg) ((reg ^ WR_PREFIX) >= 0 && (reg ^ WR_PREFIX) <= 15)
602 #define wc_register(reg) ((reg ^ WC_PREFIX) >= 0 && (reg ^ WC_PREFIX) <= 15)
603 #define wcg_register(reg) ((reg ^ WC_PREFIX) >= 8 && (reg ^ WC_PREFIX) <= 11)
605 /* These are the standard names. Users can add aliases with .req.
606 and delete them with .unreq. */
608 /* Integer Register Numbers. */
609 static const struct reg_entry rn_table[] =
611 {"r0", 0, TRUE}, {"r1", 1, TRUE}, {"r2", 2, TRUE}, {"r3", 3, TRUE},
612 {"r4", 4, TRUE}, {"r5", 5, TRUE}, {"r6", 6, TRUE}, {"r7", 7, TRUE},
613 {"r8", 8, TRUE}, {"r9", 9, TRUE}, {"r10", 10, TRUE}, {"r11", 11, TRUE},
614 {"r12", 12, TRUE}, {"r13", REG_SP, TRUE}, {"r14", REG_LR, TRUE}, {"r15", REG_PC, TRUE},
615 /* ATPCS Synonyms. */
616 {"a1", 0, TRUE}, {"a2", 1, TRUE}, {"a3", 2, TRUE}, {"a4", 3, TRUE},
617 {"v1", 4, TRUE}, {"v2", 5, TRUE}, {"v3", 6, TRUE}, {"v4", 7, TRUE},
618 {"v5", 8, TRUE}, {"v6", 9, TRUE}, {"v7", 10, TRUE}, {"v8", 11, TRUE},
619 /* Well-known aliases. */
620 {"wr", 7, TRUE}, {"sb", 9, TRUE}, {"sl", 10, TRUE}, {"fp", 11, TRUE},
621 {"ip", 12, TRUE}, {"sp", REG_SP, TRUE}, {"lr", REG_LR, TRUE}, {"pc", REG_PC, TRUE},
622 {NULL, 0, TRUE}
625 #define WR_PREFIX 0x200
626 #define WC_PREFIX 0x400
628 static const struct reg_entry iwmmxt_table[] =
630 /* Intel Wireless MMX technology register names. */
631 { "wr0", 0x0 | WR_PREFIX, TRUE}, {"wr1", 0x1 | WR_PREFIX, TRUE},
632 { "wr2", 0x2 | WR_PREFIX, TRUE}, {"wr3", 0x3 | WR_PREFIX, TRUE},
633 { "wr4", 0x4 | WR_PREFIX, TRUE}, {"wr5", 0x5 | WR_PREFIX, TRUE},
634 { "wr6", 0x6 | WR_PREFIX, TRUE}, {"wr7", 0x7 | WR_PREFIX, TRUE},
635 { "wr8", 0x8 | WR_PREFIX, TRUE}, {"wr9", 0x9 | WR_PREFIX, TRUE},
636 { "wr10", 0xa | WR_PREFIX, TRUE}, {"wr11", 0xb | WR_PREFIX, TRUE},
637 { "wr12", 0xc | WR_PREFIX, TRUE}, {"wr13", 0xd | WR_PREFIX, TRUE},
638 { "wr14", 0xe | WR_PREFIX, TRUE}, {"wr15", 0xf | WR_PREFIX, TRUE},
639 { "wcid", 0x0 | WC_PREFIX, TRUE}, {"wcon", 0x1 | WC_PREFIX, TRUE},
640 {"wcssf", 0x2 | WC_PREFIX, TRUE}, {"wcasf", 0x3 | WC_PREFIX, TRUE},
641 {"wcgr0", 0x8 | WC_PREFIX, TRUE}, {"wcgr1", 0x9 | WC_PREFIX, TRUE},
642 {"wcgr2", 0xa | WC_PREFIX, TRUE}, {"wcgr3", 0xb | WC_PREFIX, TRUE},
644 { "wR0", 0x0 | WR_PREFIX, TRUE}, {"wR1", 0x1 | WR_PREFIX, TRUE},
645 { "wR2", 0x2 | WR_PREFIX, TRUE}, {"wR3", 0x3 | WR_PREFIX, TRUE},
646 { "wR4", 0x4 | WR_PREFIX, TRUE}, {"wR5", 0x5 | WR_PREFIX, TRUE},
647 { "wR6", 0x6 | WR_PREFIX, TRUE}, {"wR7", 0x7 | WR_PREFIX, TRUE},
648 { "wR8", 0x8 | WR_PREFIX, TRUE}, {"wR9", 0x9 | WR_PREFIX, TRUE},
649 { "wR10", 0xa | WR_PREFIX, TRUE}, {"wR11", 0xb | WR_PREFIX, TRUE},
650 { "wR12", 0xc | WR_PREFIX, TRUE}, {"wR13", 0xd | WR_PREFIX, TRUE},
651 { "wR14", 0xe | WR_PREFIX, TRUE}, {"wR15", 0xf | WR_PREFIX, TRUE},
652 { "wCID", 0x0 | WC_PREFIX, TRUE}, {"wCon", 0x1 | WC_PREFIX, TRUE},
653 {"wCSSF", 0x2 | WC_PREFIX, TRUE}, {"wCASF", 0x3 | WC_PREFIX, TRUE},
654 {"wCGR0", 0x8 | WC_PREFIX, TRUE}, {"wCGR1", 0x9 | WC_PREFIX, TRUE},
655 {"wCGR2", 0xa | WC_PREFIX, TRUE}, {"wCGR3", 0xb | WC_PREFIX, TRUE},
656 {NULL, 0, TRUE}
659 /* Co-processor Numbers. */
660 static const struct reg_entry cp_table[] =
662 {"p0", 0, TRUE}, {"p1", 1, TRUE}, {"p2", 2, TRUE}, {"p3", 3, TRUE},
663 {"p4", 4, TRUE}, {"p5", 5, TRUE}, {"p6", 6, TRUE}, {"p7", 7, TRUE},
664 {"p8", 8, TRUE}, {"p9", 9, TRUE}, {"p10", 10, TRUE}, {"p11", 11, TRUE},
665 {"p12", 12, TRUE}, {"p13", 13, TRUE}, {"p14", 14, TRUE}, {"p15", 15, TRUE},
666 {NULL, 0, TRUE}
669 /* Co-processor Register Numbers. */
670 static const struct reg_entry cn_table[] =
672 {"c0", 0, TRUE}, {"c1", 1, TRUE}, {"c2", 2, TRUE}, {"c3", 3, TRUE},
673 {"c4", 4, TRUE}, {"c5", 5, TRUE}, {"c6", 6, TRUE}, {"c7", 7, TRUE},
674 {"c8", 8, TRUE}, {"c9", 9, TRUE}, {"c10", 10, TRUE}, {"c11", 11, TRUE},
675 {"c12", 12, TRUE}, {"c13", 13, TRUE}, {"c14", 14, TRUE}, {"c15", 15, TRUE},
676 /* Not really valid, but kept for back-wards compatibility. */
677 {"cr0", 0, TRUE}, {"cr1", 1, TRUE}, {"cr2", 2, TRUE}, {"cr3", 3, TRUE},
678 {"cr4", 4, TRUE}, {"cr5", 5, TRUE}, {"cr6", 6, TRUE}, {"cr7", 7, TRUE},
679 {"cr8", 8, TRUE}, {"cr9", 9, TRUE}, {"cr10", 10, TRUE}, {"cr11", 11, TRUE},
680 {"cr12", 12, TRUE}, {"cr13", 13, TRUE}, {"cr14", 14, TRUE}, {"cr15", 15, TRUE},
681 {NULL, 0, TRUE}
684 /* FPA Registers. */
685 static const struct reg_entry fn_table[] =
687 {"f0", 0, TRUE}, {"f1", 1, TRUE}, {"f2", 2, TRUE}, {"f3", 3, TRUE},
688 {"f4", 4, TRUE}, {"f5", 5, TRUE}, {"f6", 6, TRUE}, {"f7", 7, TRUE},
689 {NULL, 0, TRUE}
692 /* VFP SP Registers. */
693 static const struct reg_entry sn_table[] =
695 {"s0", 0, TRUE}, {"s1", 1, TRUE}, {"s2", 2, TRUE}, {"s3", 3, TRUE},
696 {"s4", 4, TRUE}, {"s5", 5, TRUE}, {"s6", 6, TRUE}, {"s7", 7, TRUE},
697 {"s8", 8, TRUE}, {"s9", 9, TRUE}, {"s10", 10, TRUE}, {"s11", 11, TRUE},
698 {"s12", 12, TRUE}, {"s13", 13, TRUE}, {"s14", 14, TRUE}, {"s15", 15, TRUE},
699 {"s16", 16, TRUE}, {"s17", 17, TRUE}, {"s18", 18, TRUE}, {"s19", 19, TRUE},
700 {"s20", 20, TRUE}, {"s21", 21, TRUE}, {"s22", 22, TRUE}, {"s23", 23, TRUE},
701 {"s24", 24, TRUE}, {"s25", 25, TRUE}, {"s26", 26, TRUE}, {"s27", 27, TRUE},
702 {"s28", 28, TRUE}, {"s29", 29, TRUE}, {"s30", 30, TRUE}, {"s31", 31, TRUE},
703 {NULL, 0, TRUE}
706 /* VFP DP Registers. */
707 static const struct reg_entry dn_table[] =
709 {"d0", 0, TRUE}, {"d1", 1, TRUE}, {"d2", 2, TRUE}, {"d3", 3, TRUE},
710 {"d4", 4, TRUE}, {"d5", 5, TRUE}, {"d6", 6, TRUE}, {"d7", 7, TRUE},
711 {"d8", 8, TRUE}, {"d9", 9, TRUE}, {"d10", 10, TRUE}, {"d11", 11, TRUE},
712 {"d12", 12, TRUE}, {"d13", 13, TRUE}, {"d14", 14, TRUE}, {"d15", 15, TRUE},
713 {NULL, 0, TRUE}
716 /* Maverick DSP coprocessor registers. */
717 static const struct reg_entry mav_mvf_table[] =
719 {"mvf0", 0, TRUE}, {"mvf1", 1, TRUE}, {"mvf2", 2, TRUE}, {"mvf3", 3, TRUE},
720 {"mvf4", 4, TRUE}, {"mvf5", 5, TRUE}, {"mvf6", 6, TRUE}, {"mvf7", 7, TRUE},
721 {"mvf8", 8, TRUE}, {"mvf9", 9, TRUE}, {"mvf10", 10, TRUE}, {"mvf11", 11, TRUE},
722 {"mvf12", 12, TRUE}, {"mvf13", 13, TRUE}, {"mvf14", 14, TRUE}, {"mvf15", 15, TRUE},
723 {NULL, 0, TRUE}
726 static const struct reg_entry mav_mvd_table[] =
728 {"mvd0", 0, TRUE}, {"mvd1", 1, TRUE}, {"mvd2", 2, TRUE}, {"mvd3", 3, TRUE},
729 {"mvd4", 4, TRUE}, {"mvd5", 5, TRUE}, {"mvd6", 6, TRUE}, {"mvd7", 7, TRUE},
730 {"mvd8", 8, TRUE}, {"mvd9", 9, TRUE}, {"mvd10", 10, TRUE}, {"mvd11", 11, TRUE},
731 {"mvd12", 12, TRUE}, {"mvd13", 13, TRUE}, {"mvd14", 14, TRUE}, {"mvd15", 15, TRUE},
732 {NULL, 0, TRUE}
735 static const struct reg_entry mav_mvfx_table[] =
737 {"mvfx0", 0, TRUE}, {"mvfx1", 1, TRUE}, {"mvfx2", 2, TRUE}, {"mvfx3", 3, TRUE},
738 {"mvfx4", 4, TRUE}, {"mvfx5", 5, TRUE}, {"mvfx6", 6, TRUE}, {"mvfx7", 7, TRUE},
739 {"mvfx8", 8, TRUE}, {"mvfx9", 9, TRUE}, {"mvfx10", 10, TRUE}, {"mvfx11", 11, TRUE},
740 {"mvfx12", 12, TRUE}, {"mvfx13", 13, TRUE}, {"mvfx14", 14, TRUE}, {"mvfx15", 15, TRUE},
741 {NULL, 0, TRUE}
744 static const struct reg_entry mav_mvdx_table[] =
746 {"mvdx0", 0, TRUE}, {"mvdx1", 1, TRUE}, {"mvdx2", 2, TRUE}, {"mvdx3", 3, TRUE},
747 {"mvdx4", 4, TRUE}, {"mvdx5", 5, TRUE}, {"mvdx6", 6, TRUE}, {"mvdx7", 7, TRUE},
748 {"mvdx8", 8, TRUE}, {"mvdx9", 9, TRUE}, {"mvdx10", 10, TRUE}, {"mvdx11", 11, TRUE},
749 {"mvdx12", 12, TRUE}, {"mvdx13", 13, TRUE}, {"mvdx14", 14, TRUE}, {"mvdx15", 15, TRUE},
750 {NULL, 0, TRUE}
753 static const struct reg_entry mav_mvax_table[] =
755 {"mvax0", 0, TRUE}, {"mvax1", 1, TRUE}, {"mvax2", 2, TRUE}, {"mvax3", 3, TRUE},
756 {NULL, 0, TRUE}
759 static const struct reg_entry mav_dspsc_table[] =
761 {"dspsc", 0, TRUE},
762 {NULL, 0, TRUE}
765 struct reg_map
767 const struct reg_entry *names;
768 int max_regno;
769 struct hash_control *htab;
770 const char *expected;
773 struct reg_map all_reg_maps[] =
775 {rn_table, 15, NULL, N_("ARM register expected")},
776 {cp_table, 15, NULL, N_("bad or missing co-processor number")},
777 {cn_table, 15, NULL, N_("co-processor register expected")},
778 {fn_table, 7, NULL, N_("FPA register expected")},
779 {sn_table, 31, NULL, N_("VFP single precision register expected")},
780 {dn_table, 15, NULL, N_("VFP double precision register expected")},
781 {mav_mvf_table, 15, NULL, N_("Maverick MVF register expected")},
782 {mav_mvd_table, 15, NULL, N_("Maverick MVD register expected")},
783 {mav_mvfx_table, 15, NULL, N_("Maverick MVFX register expected")},
784 {mav_mvdx_table, 15, NULL, N_("Maverick MVDX register expected")},
785 {mav_mvax_table, 3, NULL, N_("Maverick MVAX register expected")},
786 {mav_dspsc_table, 0, NULL, N_("Maverick DSPSC register expected")},
787 {iwmmxt_table, 23, NULL, N_("Intel Wireless MMX technology register expected")},
790 /* Enumeration matching entries in table above. */
791 enum arm_reg_type
793 REG_TYPE_RN = 0,
794 #define REG_TYPE_FIRST REG_TYPE_RN
795 REG_TYPE_CP = 1,
796 REG_TYPE_CN = 2,
797 REG_TYPE_FN = 3,
798 REG_TYPE_SN = 4,
799 REG_TYPE_DN = 5,
800 REG_TYPE_MVF = 6,
801 REG_TYPE_MVD = 7,
802 REG_TYPE_MVFX = 8,
803 REG_TYPE_MVDX = 9,
804 REG_TYPE_MVAX = 10,
805 REG_TYPE_DSPSC = 11,
806 REG_TYPE_IWMMXT = 12,
808 REG_TYPE_MAX = 13
811 /* Functions called by parser. */
812 /* ARM instructions. */
813 static void do_arit PARAMS ((char *));
814 static void do_cmp PARAMS ((char *));
815 static void do_mov PARAMS ((char *));
816 static void do_ldst PARAMS ((char *));
817 static void do_ldstt PARAMS ((char *));
818 static void do_ldmstm PARAMS ((char *));
819 static void do_branch PARAMS ((char *));
820 static void do_swi PARAMS ((char *));
822 /* Pseudo Op codes. */
823 static void do_adr PARAMS ((char *));
824 static void do_adrl PARAMS ((char *));
825 static void do_empty PARAMS ((char *));
827 /* ARM v2. */
828 static void do_mul PARAMS ((char *));
829 static void do_mla PARAMS ((char *));
831 /* ARM v2S. */
832 static void do_swap PARAMS ((char *));
834 /* ARM v3. */
835 static void do_msr PARAMS ((char *));
836 static void do_mrs PARAMS ((char *));
838 /* ARM v3M. */
839 static void do_mull PARAMS ((char *));
841 /* ARM v4. */
842 static void do_ldstv4 PARAMS ((char *));
844 /* ARM v4T. */
845 static void do_bx PARAMS ((char *));
847 /* ARM v5T. */
848 static void do_blx PARAMS ((char *));
849 static void do_bkpt PARAMS ((char *));
850 static void do_clz PARAMS ((char *));
851 static void do_lstc2 PARAMS ((char *));
852 static void do_cdp2 PARAMS ((char *));
853 static void do_co_reg2 PARAMS ((char *));
855 /* ARM v5TExP. */
856 static void do_smla PARAMS ((char *));
857 static void do_smlal PARAMS ((char *));
858 static void do_smul PARAMS ((char *));
859 static void do_qadd PARAMS ((char *));
861 /* ARM v5TE. */
862 static void do_pld PARAMS ((char *));
863 static void do_ldrd PARAMS ((char *));
864 static void do_co_reg2c PARAMS ((char *));
866 /* ARM v5TEJ. */
867 static void do_bxj PARAMS ((char *));
869 /* ARM V6. */
870 static void do_cps PARAMS ((char *));
871 static void do_cpsi PARAMS ((char *));
872 static void do_ldrex PARAMS ((char *));
873 static void do_pkhbt PARAMS ((char *));
874 static void do_pkhtb PARAMS ((char *));
875 static void do_qadd16 PARAMS ((char *));
876 static void do_rev PARAMS ((char *));
877 static void do_rfe PARAMS ((char *));
878 static void do_sxtah PARAMS ((char *));
879 static void do_sxth PARAMS ((char *));
880 static void do_setend PARAMS ((char *));
881 static void do_smlad PARAMS ((char *));
882 static void do_smlald PARAMS ((char *));
883 static void do_smmul PARAMS ((char *));
884 static void do_ssat PARAMS ((char *));
885 static void do_usat PARAMS ((char *));
886 static void do_srs PARAMS ((char *));
887 static void do_ssat16 PARAMS ((char *));
888 static void do_usat16 PARAMS ((char *));
889 static void do_strex PARAMS ((char *));
890 static void do_umaal PARAMS ((char *));
892 static void do_cps_mode PARAMS ((char **));
893 static void do_cps_flags PARAMS ((char **, int));
894 static int do_endian_specifier PARAMS ((char *));
895 static void do_pkh_core PARAMS ((char *, int));
896 static void do_sat PARAMS ((char **, int));
897 static void do_sat16 PARAMS ((char **, int));
899 /* Coprocessor Instructions. */
900 static void do_cdp PARAMS ((char *));
901 static void do_lstc PARAMS ((char *));
902 static void do_co_reg PARAMS ((char *));
904 /* FPA instructions. */
905 static void do_fpa_ctrl PARAMS ((char *));
906 static void do_fpa_ldst PARAMS ((char *));
907 static void do_fpa_ldmstm PARAMS ((char *));
908 static void do_fpa_dyadic PARAMS ((char *));
909 static void do_fpa_monadic PARAMS ((char *));
910 static void do_fpa_cmp PARAMS ((char *));
911 static void do_fpa_from_reg PARAMS ((char *));
912 static void do_fpa_to_reg PARAMS ((char *));
914 /* VFP instructions. */
915 static void do_vfp_sp_monadic PARAMS ((char *));
916 static void do_vfp_dp_monadic PARAMS ((char *));
917 static void do_vfp_sp_dyadic PARAMS ((char *));
918 static void do_vfp_dp_dyadic PARAMS ((char *));
919 static void do_vfp_reg_from_sp PARAMS ((char *));
920 static void do_vfp_sp_from_reg PARAMS ((char *));
921 static void do_vfp_sp_reg2 PARAMS ((char *));
922 static void do_vfp_reg_from_dp PARAMS ((char *));
923 static void do_vfp_reg2_from_dp PARAMS ((char *));
924 static void do_vfp_dp_from_reg PARAMS ((char *));
925 static void do_vfp_dp_from_reg2 PARAMS ((char *));
926 static void do_vfp_reg_from_ctrl PARAMS ((char *));
927 static void do_vfp_ctrl_from_reg PARAMS ((char *));
928 static void do_vfp_sp_ldst PARAMS ((char *));
929 static void do_vfp_dp_ldst PARAMS ((char *));
930 static void do_vfp_sp_ldstmia PARAMS ((char *));
931 static void do_vfp_sp_ldstmdb PARAMS ((char *));
932 static void do_vfp_dp_ldstmia PARAMS ((char *));
933 static void do_vfp_dp_ldstmdb PARAMS ((char *));
934 static void do_vfp_xp_ldstmia PARAMS ((char *));
935 static void do_vfp_xp_ldstmdb PARAMS ((char *));
936 static void do_vfp_sp_compare_z PARAMS ((char *));
937 static void do_vfp_dp_compare_z PARAMS ((char *));
938 static void do_vfp_dp_sp_cvt PARAMS ((char *));
939 static void do_vfp_sp_dp_cvt PARAMS ((char *));
941 /* XScale. */
942 static void do_xsc_mia PARAMS ((char *));
943 static void do_xsc_mar PARAMS ((char *));
944 static void do_xsc_mra PARAMS ((char *));
946 /* Maverick. */
947 static void do_mav_binops PARAMS ((char *, int, enum arm_reg_type,
948 enum arm_reg_type));
949 static void do_mav_binops_1a PARAMS ((char *));
950 static void do_mav_binops_1b PARAMS ((char *));
951 static void do_mav_binops_1c PARAMS ((char *));
952 static void do_mav_binops_1d PARAMS ((char *));
953 static void do_mav_binops_1e PARAMS ((char *));
954 static void do_mav_binops_1f PARAMS ((char *));
955 static void do_mav_binops_1g PARAMS ((char *));
956 static void do_mav_binops_1h PARAMS ((char *));
957 static void do_mav_binops_1i PARAMS ((char *));
958 static void do_mav_binops_1j PARAMS ((char *));
959 static void do_mav_binops_1k PARAMS ((char *));
960 static void do_mav_binops_1l PARAMS ((char *));
961 static void do_mav_binops_1m PARAMS ((char *));
962 static void do_mav_binops_1n PARAMS ((char *));
963 static void do_mav_binops_1o PARAMS ((char *));
964 static void do_mav_binops_2a PARAMS ((char *));
965 static void do_mav_binops_2b PARAMS ((char *));
966 static void do_mav_binops_2c PARAMS ((char *));
967 static void do_mav_binops_3a PARAMS ((char *));
968 static void do_mav_binops_3b PARAMS ((char *));
969 static void do_mav_binops_3c PARAMS ((char *));
970 static void do_mav_binops_3d PARAMS ((char *));
971 static void do_mav_triple PARAMS ((char *, int, enum arm_reg_type,
972 enum arm_reg_type,
973 enum arm_reg_type));
974 static void do_mav_triple_4a PARAMS ((char *));
975 static void do_mav_triple_4b PARAMS ((char *));
976 static void do_mav_triple_5a PARAMS ((char *));
977 static void do_mav_triple_5b PARAMS ((char *));
978 static void do_mav_triple_5c PARAMS ((char *));
979 static void do_mav_triple_5d PARAMS ((char *));
980 static void do_mav_triple_5e PARAMS ((char *));
981 static void do_mav_triple_5f PARAMS ((char *));
982 static void do_mav_triple_5g PARAMS ((char *));
983 static void do_mav_triple_5h PARAMS ((char *));
984 static void do_mav_quad PARAMS ((char *, int, enum arm_reg_type,
985 enum arm_reg_type,
986 enum arm_reg_type,
987 enum arm_reg_type));
988 static void do_mav_quad_6a PARAMS ((char *));
989 static void do_mav_quad_6b PARAMS ((char *));
990 static void do_mav_dspsc_1 PARAMS ((char *));
991 static void do_mav_dspsc_2 PARAMS ((char *));
992 static void do_mav_shift PARAMS ((char *, enum arm_reg_type,
993 enum arm_reg_type));
994 static void do_mav_shift_1 PARAMS ((char *));
995 static void do_mav_shift_2 PARAMS ((char *));
996 static void do_mav_ldst PARAMS ((char *, enum arm_reg_type));
997 static void do_mav_ldst_1 PARAMS ((char *));
998 static void do_mav_ldst_2 PARAMS ((char *));
999 static void do_mav_ldst_3 PARAMS ((char *));
1000 static void do_mav_ldst_4 PARAMS ((char *));
1002 static int mav_reg_required_here PARAMS ((char **, int,
1003 enum arm_reg_type));
1004 static int mav_parse_offset PARAMS ((char **, int *));
1006 static void fix_new_arm PARAMS ((fragS *, int, short, expressionS *,
1007 int, int));
1008 static int arm_reg_parse PARAMS ((char **, struct hash_control *));
1009 static enum arm_reg_type arm_reg_parse_any PARAMS ((char *));
1010 static const struct asm_psr * arm_psr_parse PARAMS ((char **));
1011 static void symbol_locate PARAMS ((symbolS *, const char *, segT, valueT,
1012 fragS *));
1013 static int add_to_lit_pool PARAMS ((void));
1014 static unsigned validate_immediate PARAMS ((unsigned));
1015 static unsigned validate_immediate_twopart PARAMS ((unsigned int,
1016 unsigned int *));
1017 static int validate_offset_imm PARAMS ((unsigned int, int));
1018 static void opcode_select PARAMS ((int));
1019 static void end_of_line PARAMS ((char *));
1020 static int reg_required_here PARAMS ((char **, int));
1021 static int psr_required_here PARAMS ((char **));
1022 static int co_proc_number PARAMS ((char **));
1023 static int cp_opc_expr PARAMS ((char **, int, int));
1024 static int cp_reg_required_here PARAMS ((char **, int));
1025 static int fp_reg_required_here PARAMS ((char **, int));
1026 static int vfp_sp_reg_required_here PARAMS ((char **, enum vfp_sp_reg_pos));
1027 static int vfp_dp_reg_required_here PARAMS ((char **, enum vfp_dp_reg_pos));
1028 static void vfp_sp_ldstm PARAMS ((char *, enum vfp_ldstm_type));
1029 static void vfp_dp_ldstm PARAMS ((char *, enum vfp_ldstm_type));
1030 static long vfp_sp_reg_list PARAMS ((char **, enum vfp_sp_reg_pos));
1031 static long vfp_dp_reg_list PARAMS ((char **));
1032 static int vfp_psr_required_here PARAMS ((char **str));
1033 static const struct vfp_reg *vfp_psr_parse PARAMS ((char **str));
1034 static int cp_address_offset PARAMS ((char **));
1035 static int cp_address_required_here PARAMS ((char **, int));
1036 static int my_get_float_expression PARAMS ((char **));
1037 static int skip_past_comma PARAMS ((char **));
1038 static int walk_no_bignums PARAMS ((symbolS *));
1039 static int negate_data_op PARAMS ((unsigned long *, unsigned long));
1040 static int data_op2 PARAMS ((char **));
1041 static int fp_op2 PARAMS ((char **));
1042 static long reg_list PARAMS ((char **));
1043 static void thumb_load_store PARAMS ((char *, int, int));
1044 static int decode_shift PARAMS ((char **, int));
1045 static int ldst_extend PARAMS ((char **));
1046 static int ldst_extend_v4 PARAMS ((char **));
1047 static void thumb_add_sub PARAMS ((char *, int));
1048 static void insert_reg PARAMS ((const struct reg_entry *,
1049 struct hash_control *));
1050 static void thumb_shift PARAMS ((char *, int));
1051 static void thumb_mov_compare PARAMS ((char *, int));
1052 static void build_arm_ops_hsh PARAMS ((void));
1053 static void set_constant_flonums PARAMS ((void));
1054 static valueT md_chars_to_number PARAMS ((char *, int));
1055 static void build_reg_hsh PARAMS ((struct reg_map *));
1056 static void insert_reg_alias PARAMS ((char *, int, struct hash_control *));
1057 static int create_register_alias PARAMS ((char *, char *));
1058 static void output_inst PARAMS ((const char *));
1059 static int accum0_required_here PARAMS ((char **));
1060 static int ld_mode_required_here PARAMS ((char **));
1061 static void do_branch25 PARAMS ((char *));
1062 static symbolS * find_real_start PARAMS ((symbolS *));
1063 #ifdef OBJ_ELF
1064 static bfd_reloc_code_real_type arm_parse_reloc PARAMS ((void));
1065 #endif
1067 static int wreg_required_here PARAMS ((char **, int, enum wreg_type));
1068 static void do_iwmmxt_byte_addr PARAMS ((char *));
1069 static void do_iwmmxt_tandc PARAMS ((char *));
1070 static void do_iwmmxt_tbcst PARAMS ((char *));
1071 static void do_iwmmxt_textrc PARAMS ((char *));
1072 static void do_iwmmxt_textrm PARAMS ((char *));
1073 static void do_iwmmxt_tinsr PARAMS ((char *));
1074 static void do_iwmmxt_tmcr PARAMS ((char *));
1075 static void do_iwmmxt_tmcrr PARAMS ((char *));
1076 static void do_iwmmxt_tmia PARAMS ((char *));
1077 static void do_iwmmxt_tmovmsk PARAMS ((char *));
1078 static void do_iwmmxt_tmrc PARAMS ((char *));
1079 static void do_iwmmxt_tmrrc PARAMS ((char *));
1080 static void do_iwmmxt_torc PARAMS ((char *));
1081 static void do_iwmmxt_waligni PARAMS ((char *));
1082 static void do_iwmmxt_wmov PARAMS ((char *));
1083 static void do_iwmmxt_word_addr PARAMS ((char *));
1084 static void do_iwmmxt_wrwr PARAMS ((char *));
1085 static void do_iwmmxt_wrwrwcg PARAMS ((char *));
1086 static void do_iwmmxt_wrwrwr PARAMS ((char *));
1087 static void do_iwmmxt_wshufh PARAMS ((char *));
1088 static void do_iwmmxt_wzero PARAMS ((char *));
1089 static int cp_byte_address_offset PARAMS ((char **));
1090 static int cp_byte_address_required_here PARAMS ((char **));
1092 /* ARM instructions take 4bytes in the object file, Thumb instructions
1093 take 2: */
1094 #define INSN_SIZE 4
1096 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
1097 #define MAV_MODE1 0x100c
1099 /* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
1100 #define MAV_MODE2 0x0c10
1102 /* "INSN<cond> X,Y" where X:0, Y:bit16. */
1103 #define MAV_MODE3 0x1000
1105 /* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
1106 #define MAV_MODE4 0x0c0010
1108 /* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
1109 #define MAV_MODE5 0x00100c
1111 /* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
1112 #define MAV_MODE6 0x00100c05
1114 struct asm_opcode
1116 /* Basic string to match. */
1117 const char * template;
1119 /* Basic instruction code. */
1120 unsigned long value;
1122 /* Offset into the template where the condition code (if any) will be.
1123 If zero, then the instruction is never conditional. */
1124 unsigned cond_offset;
1126 /* Which architecture variant provides this instruction. */
1127 unsigned long variant;
1129 /* Function to call to parse args. */
1130 void (* parms) PARAMS ((char *));
1133 static const struct asm_opcode insns[] =
1135 /* Core ARM Instructions. */
1136 {"and", 0xe0000000, 3, ARM_EXT_V1, do_arit},
1137 {"ands", 0xe0100000, 3, ARM_EXT_V1, do_arit},
1138 {"eor", 0xe0200000, 3, ARM_EXT_V1, do_arit},
1139 {"eors", 0xe0300000, 3, ARM_EXT_V1, do_arit},
1140 {"sub", 0xe0400000, 3, ARM_EXT_V1, do_arit},
1141 {"subs", 0xe0500000, 3, ARM_EXT_V1, do_arit},
1142 {"rsb", 0xe0600000, 3, ARM_EXT_V1, do_arit},
1143 {"rsbs", 0xe0700000, 3, ARM_EXT_V1, do_arit},
1144 {"add", 0xe0800000, 3, ARM_EXT_V1, do_arit},
1145 {"adds", 0xe0900000, 3, ARM_EXT_V1, do_arit},
1146 {"adc", 0xe0a00000, 3, ARM_EXT_V1, do_arit},
1147 {"adcs", 0xe0b00000, 3, ARM_EXT_V1, do_arit},
1148 {"sbc", 0xe0c00000, 3, ARM_EXT_V1, do_arit},
1149 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1, do_arit},
1150 {"rsc", 0xe0e00000, 3, ARM_EXT_V1, do_arit},
1151 {"rscs", 0xe0f00000, 3, ARM_EXT_V1, do_arit},
1152 {"orr", 0xe1800000, 3, ARM_EXT_V1, do_arit},
1153 {"orrs", 0xe1900000, 3, ARM_EXT_V1, do_arit},
1154 {"bic", 0xe1c00000, 3, ARM_EXT_V1, do_arit},
1155 {"bics", 0xe1d00000, 3, ARM_EXT_V1, do_arit},
1157 {"tst", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
1158 {"tsts", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
1159 {"tstp", 0xe110f000, 3, ARM_EXT_V1, do_cmp},
1160 {"teq", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
1161 {"teqs", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
1162 {"teqp", 0xe130f000, 3, ARM_EXT_V1, do_cmp},
1163 {"cmp", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
1164 {"cmps", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
1165 {"cmpp", 0xe150f000, 3, ARM_EXT_V1, do_cmp},
1166 {"cmn", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
1167 {"cmns", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
1168 {"cmnp", 0xe170f000, 3, ARM_EXT_V1, do_cmp},
1170 {"mov", 0xe1a00000, 3, ARM_EXT_V1, do_mov},
1171 {"movs", 0xe1b00000, 3, ARM_EXT_V1, do_mov},
1172 {"mvn", 0xe1e00000, 3, ARM_EXT_V1, do_mov},
1173 {"mvns", 0xe1f00000, 3, ARM_EXT_V1, do_mov},
1175 {"ldr", 0xe4100000, 3, ARM_EXT_V1, do_ldst},
1176 {"ldrb", 0xe4500000, 3, ARM_EXT_V1, do_ldst},
1177 {"ldrt", 0xe4300000, 3, ARM_EXT_V1, do_ldstt},
1178 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1, do_ldstt},
1179 {"str", 0xe4000000, 3, ARM_EXT_V1, do_ldst},
1180 {"strb", 0xe4400000, 3, ARM_EXT_V1, do_ldst},
1181 {"strt", 0xe4200000, 3, ARM_EXT_V1, do_ldstt},
1182 {"strbt", 0xe4600000, 3, ARM_EXT_V1, do_ldstt},
1184 {"stmia", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
1185 {"stmib", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
1186 {"stmda", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
1187 {"stmdb", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
1188 {"stmfd", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
1189 {"stmfa", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
1190 {"stmea", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
1191 {"stmed", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
1193 {"ldmia", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
1194 {"ldmib", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
1195 {"ldmda", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
1196 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
1197 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
1198 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
1199 {"ldmea", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
1200 {"ldmed", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
1202 {"swi", 0xef000000, 3, ARM_EXT_V1, do_swi},
1203 #ifdef TE_WINCE
1204 /* XXX This is the wrong place to do this. Think multi-arch. */
1205 {"bl", 0xeb000000, 2, ARM_EXT_V1, do_branch},
1206 {"b", 0xea000000, 1, ARM_EXT_V1, do_branch},
1207 #else
1208 {"bl", 0xebfffffe, 2, ARM_EXT_V1, do_branch},
1209 {"b", 0xeafffffe, 1, ARM_EXT_V1, do_branch},
1210 #endif
1212 /* Pseudo ops. */
1213 {"adr", 0xe28f0000, 3, ARM_EXT_V1, do_adr},
1214 {"adrl", 0xe28f0000, 3, ARM_EXT_V1, do_adrl},
1215 {"nop", 0xe1a00000, 3, ARM_EXT_V1, do_empty},
1217 /* ARM 2 multiplies. */
1218 {"mul", 0xe0000090, 3, ARM_EXT_V2, do_mul},
1219 {"muls", 0xe0100090, 3, ARM_EXT_V2, do_mul},
1220 {"mla", 0xe0200090, 3, ARM_EXT_V2, do_mla},
1221 {"mlas", 0xe0300090, 3, ARM_EXT_V2, do_mla},
1223 /* Generic coprocessor instructions. */
1224 {"cdp", 0xee000000, 3, ARM_EXT_V2, do_cdp},
1225 {"ldc", 0xec100000, 3, ARM_EXT_V2, do_lstc},
1226 {"ldcl", 0xec500000, 3, ARM_EXT_V2, do_lstc},
1227 {"stc", 0xec000000, 3, ARM_EXT_V2, do_lstc},
1228 {"stcl", 0xec400000, 3, ARM_EXT_V2, do_lstc},
1229 {"mcr", 0xee000010, 3, ARM_EXT_V2, do_co_reg},
1230 {"mrc", 0xee100010, 3, ARM_EXT_V2, do_co_reg},
1232 /* ARM 3 - swp instructions. */
1233 {"swp", 0xe1000090, 3, ARM_EXT_V2S, do_swap},
1234 {"swpb", 0xe1400090, 3, ARM_EXT_V2S, do_swap},
1236 /* ARM 6 Status register instructions. */
1237 {"mrs", 0xe10f0000, 3, ARM_EXT_V3, do_mrs},
1238 {"msr", 0xe120f000, 3, ARM_EXT_V3, do_msr},
1239 /* ScottB: our code uses 0xe128f000 for msr.
1240 NickC: but this is wrong because the bits 16 through 19 are
1241 handled by the PSR_xxx defines above. */
1243 /* ARM 7M long multiplies. */
1244 {"smull", 0xe0c00090, 5, ARM_EXT_V3M, do_mull},
1245 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M, do_mull},
1246 {"umull", 0xe0800090, 5, ARM_EXT_V3M, do_mull},
1247 {"umulls", 0xe0900090, 5, ARM_EXT_V3M, do_mull},
1248 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M, do_mull},
1249 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M, do_mull},
1250 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M, do_mull},
1251 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M, do_mull},
1253 /* ARM Architecture 4. */
1254 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4, do_ldstv4},
1255 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4, do_ldstv4},
1256 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4, do_ldstv4},
1257 {"strh", 0xe00000b0, 3, ARM_EXT_V4, do_ldstv4},
1259 /* ARM Architecture 4T. */
1260 /* Note: bx (and blx) are required on V5, even if the processor does
1261 not support Thumb. */
1262 {"bx", 0xe12fff10, 2, ARM_EXT_V4T | ARM_EXT_V5, do_bx},
1264 /* ARM Architecture 5T. */
1265 /* Note: blx has 2 variants, so the .value is set dynamically.
1266 Only one of the variants has conditional execution. */
1267 {"blx", 0xe0000000, 3, ARM_EXT_V5, do_blx},
1268 {"clz", 0xe16f0f10, 3, ARM_EXT_V5, do_clz},
1269 {"bkpt", 0xe1200070, 0, ARM_EXT_V5, do_bkpt},
1270 {"ldc2", 0xfc100000, 0, ARM_EXT_V5, do_lstc2},
1271 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5, do_lstc2},
1272 {"stc2", 0xfc000000, 0, ARM_EXT_V5, do_lstc2},
1273 {"stc2l", 0xfc400000, 0, ARM_EXT_V5, do_lstc2},
1274 {"cdp2", 0xfe000000, 0, ARM_EXT_V5, do_cdp2},
1275 {"mcr2", 0xfe000010, 0, ARM_EXT_V5, do_co_reg2},
1276 {"mrc2", 0xfe100010, 0, ARM_EXT_V5, do_co_reg2},
1278 /* ARM Architecture 5TExP. */
1279 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP, do_smla},
1280 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP, do_smla},
1281 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP, do_smla},
1282 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP, do_smla},
1284 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP, do_smla},
1285 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP, do_smla},
1287 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP, do_smlal},
1288 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP, do_smlal},
1289 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP, do_smlal},
1290 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP, do_smlal},
1292 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP, do_smul},
1293 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP, do_smul},
1294 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP, do_smul},
1295 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP, do_smul},
1297 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP, do_smul},
1298 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP, do_smul},
1300 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP, do_qadd},
1301 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP, do_qadd},
1302 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP, do_qadd},
1303 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP, do_qadd},
1305 /* ARM Architecture 5TE. */
1306 {"pld", 0xf450f000, 0, ARM_EXT_V5E, do_pld},
1307 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E, do_ldrd},
1308 {"strd", 0xe00000f0, 3, ARM_EXT_V5E, do_ldrd},
1310 {"mcrr", 0xec400000, 4, ARM_EXT_V5E, do_co_reg2c},
1311 {"mrrc", 0xec500000, 4, ARM_EXT_V5E, do_co_reg2c},
1313 /* ARM Architecture 5TEJ. */
1314 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J, do_bxj},
1316 /* ARM V6. */
1317 { "cps", 0xf1020000, 0, ARM_EXT_V6, do_cps},
1318 { "cpsie", 0xf1080000, 0, ARM_EXT_V6, do_cpsi},
1319 { "cpsid", 0xf10C0000, 0, ARM_EXT_V6, do_cpsi},
1320 { "ldrex", 0xe1900f9f, 5, ARM_EXT_V6, do_ldrex},
1321 { "mcrr2", 0xfc400000, 0, ARM_EXT_V6, do_co_reg2c},
1322 { "mrrc2", 0xfc500000, 0, ARM_EXT_V6, do_co_reg2c},
1323 { "pkhbt", 0xe6800010, 5, ARM_EXT_V6, do_pkhbt},
1324 { "pkhtb", 0xe6800050, 5, ARM_EXT_V6, do_pkhtb},
1325 { "qadd16", 0xe6200f10, 6, ARM_EXT_V6, do_qadd16},
1326 { "qadd8", 0xe6200f90, 5, ARM_EXT_V6, do_qadd16},
1327 { "qaddsubx", 0xe6200f30, 8, ARM_EXT_V6, do_qadd16},
1328 { "qsub16", 0xe6200f70, 6, ARM_EXT_V6, do_qadd16},
1329 { "qsub8", 0xe6200ff0, 5, ARM_EXT_V6, do_qadd16},
1330 { "qsubaddx", 0xe6200f50, 8, ARM_EXT_V6, do_qadd16},
1331 { "sadd16", 0xe6100f10, 6, ARM_EXT_V6, do_qadd16},
1332 { "sadd8", 0xe6100f90, 5, ARM_EXT_V6, do_qadd16},
1333 { "saddsubx", 0xe6100f30, 8, ARM_EXT_V6, do_qadd16},
1334 { "shadd16", 0xe6300f10, 7, ARM_EXT_V6, do_qadd16},
1335 { "shadd8", 0xe6300f90, 6, ARM_EXT_V6, do_qadd16},
1336 { "shaddsubx", 0xe6300f30, 9, ARM_EXT_V6, do_qadd16},
1337 { "shsub16", 0xe6300f70, 7, ARM_EXT_V6, do_qadd16},
1338 { "shsub8", 0xe6300ff0, 6, ARM_EXT_V6, do_qadd16},
1339 { "shsubaddx", 0xe6300f50, 9, ARM_EXT_V6, do_qadd16},
1340 { "ssub16", 0xe6100f70, 6, ARM_EXT_V6, do_qadd16},
1341 { "ssub8", 0xe6100ff0, 5, ARM_EXT_V6, do_qadd16},
1342 { "ssubaddx", 0xe6100f50, 8, ARM_EXT_V6, do_qadd16},
1343 { "uadd16", 0xe6500f10, 6, ARM_EXT_V6, do_qadd16},
1344 { "uadd8", 0xe6500f90, 5, ARM_EXT_V6, do_qadd16},
1345 { "uaddsubx", 0xe6500f30, 8, ARM_EXT_V6, do_qadd16},
1346 { "uhadd16", 0xe6700f10, 7, ARM_EXT_V6, do_qadd16},
1347 { "uhadd8", 0xe6700f90, 6, ARM_EXT_V6, do_qadd16},
1348 { "uhaddsubx", 0xe6700f30, 9, ARM_EXT_V6, do_qadd16},
1349 { "uhsub16", 0xe6700f70, 7, ARM_EXT_V6, do_qadd16},
1350 { "uhsub8", 0xe6700ff0, 6, ARM_EXT_V6, do_qadd16},
1351 { "uhsubaddx", 0xe6700f50, 9, ARM_EXT_V6, do_qadd16},
1352 { "uqadd16", 0xe6600f10, 7, ARM_EXT_V6, do_qadd16},
1353 { "uqadd8", 0xe6600f90, 6, ARM_EXT_V6, do_qadd16},
1354 { "uqaddsubx", 0xe6600f30, 9, ARM_EXT_V6, do_qadd16},
1355 { "uqsub16", 0xe6600f70, 7, ARM_EXT_V6, do_qadd16},
1356 { "uqsub8", 0xe6600ff0, 6, ARM_EXT_V6, do_qadd16},
1357 { "uqsubaddx", 0xe6600f50, 9, ARM_EXT_V6, do_qadd16},
1358 { "usub16", 0xe6500f70, 6, ARM_EXT_V6, do_qadd16},
1359 { "usub8", 0xe6500ff0, 5, ARM_EXT_V6, do_qadd16},
1360 { "usubaddx", 0xe6500f50, 8, ARM_EXT_V6, do_qadd16},
1361 { "rev", 0xe6bf0f30, 3, ARM_EXT_V6, do_rev},
1362 { "rev16", 0xe6bf0fb0, 5, ARM_EXT_V6, do_rev},
1363 { "revsh", 0xe6ff0fb0, 5, ARM_EXT_V6, do_rev},
1364 { "rfeia", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
1365 { "rfeib", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
1366 { "rfeda", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
1367 { "rfedb", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
1368 { "rfefd", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
1369 { "rfefa", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
1370 { "rfeea", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
1371 { "rfeed", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
1372 { "sxtah", 0xe6b00070, 5, ARM_EXT_V6, do_sxtah},
1373 { "sxtab16", 0xe6800070, 7, ARM_EXT_V6, do_sxtah},
1374 { "sxtab", 0xe6a00070, 5, ARM_EXT_V6, do_sxtah},
1375 { "sxth", 0xe6bf0070, 4, ARM_EXT_V6, do_sxth},
1376 { "sxtb16", 0xe68f0070, 6, ARM_EXT_V6, do_sxth},
1377 { "sxtb", 0xe6af0070, 4, ARM_EXT_V6, do_sxth},
1378 { "uxtah", 0xe6f00070, 5, ARM_EXT_V6, do_sxtah},
1379 { "uxtab16", 0xe6c00070, 7, ARM_EXT_V6, do_sxtah},
1380 { "uxtab", 0xe6e00070, 5, ARM_EXT_V6, do_sxtah},
1381 { "uxth", 0xe6ff0070, 4, ARM_EXT_V6, do_sxth},
1382 { "uxtb16", 0xe6cf0070, 6, ARM_EXT_V6, do_sxth},
1383 { "uxtb", 0xe6ef0070, 4, ARM_EXT_V6, do_sxth},
1384 { "sel", 0xe68000b0, 3, ARM_EXT_V6, do_qadd16},
1385 { "setend", 0xf1010000, 0, ARM_EXT_V6, do_setend},
1386 { "smlad", 0xe7000010, 5, ARM_EXT_V6, do_smlad},
1387 { "smladx", 0xe7000030, 6, ARM_EXT_V6, do_smlad},
1388 { "smlald", 0xe7400010, 6, ARM_EXT_V6, do_smlald},
1389 { "smlaldx", 0xe7400030, 7, ARM_EXT_V6, do_smlald},
1390 { "smlsd", 0xe7000050, 5, ARM_EXT_V6, do_smlad},
1391 { "smlsdx", 0xe7000070, 6, ARM_EXT_V6, do_smlad},
1392 { "smlsld", 0xe7400050, 6, ARM_EXT_V6, do_smlald},
1393 { "smlsldx", 0xe7400070, 7, ARM_EXT_V6, do_smlald},
1394 { "smmla", 0xe7500010, 5, ARM_EXT_V6, do_smlad},
1395 { "smmlar", 0xe7500030, 6, ARM_EXT_V6, do_smlad},
1396 { "smmls", 0xe75000d0, 5, ARM_EXT_V6, do_smlad},
1397 { "smmlsr", 0xe75000f0, 6, ARM_EXT_V6, do_smlad},
1398 { "smmul", 0xe750f010, 5, ARM_EXT_V6, do_smmul},
1399 { "smmulr", 0xe750f030, 6, ARM_EXT_V6, do_smmul},
1400 { "smuad", 0xe700f010, 5, ARM_EXT_V6, do_smmul},
1401 { "smuadx", 0xe700f030, 6, ARM_EXT_V6, do_smmul},
1402 { "smusd", 0xe700f050, 5, ARM_EXT_V6, do_smmul},
1403 { "smusdx", 0xe700f070, 6, ARM_EXT_V6, do_smmul},
1404 { "srsia", 0xf8cd0500, 0, ARM_EXT_V6, do_srs},
1405 { "srsib", 0xf9cd0500, 0, ARM_EXT_V6, do_srs},
1406 { "srsda", 0xf84d0500, 0, ARM_EXT_V6, do_srs},
1407 { "srsdb", 0xf94d0500, 0, ARM_EXT_V6, do_srs},
1408 { "ssat", 0xe6a00010, 4, ARM_EXT_V6, do_ssat},
1409 { "ssat16", 0xe6a00f30, 6, ARM_EXT_V6, do_ssat16},
1410 { "strex", 0xe1800f90, 5, ARM_EXT_V6, do_strex},
1411 { "umaal", 0xe0400090, 5, ARM_EXT_V6, do_umaal},
1412 { "usad8", 0xe780f010, 5, ARM_EXT_V6, do_smmul},
1413 { "usada8", 0xe7800010, 6, ARM_EXT_V6, do_smlad},
1414 { "usat", 0xe6e00010, 4, ARM_EXT_V6, do_usat},
1415 { "usat16", 0xe6e00f30, 6, ARM_EXT_V6, do_usat16},
1417 /* Core FPA instruction set (V1). */
1418 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1419 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1420 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1421 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1423 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1424 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1425 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1426 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1428 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1429 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1430 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1431 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1433 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1434 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1435 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1436 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1437 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1438 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1439 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1440 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1441 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1442 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1443 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1444 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1446 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1447 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1448 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1449 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1450 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1451 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1452 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1453 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1454 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1455 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1456 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1457 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1459 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1460 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1461 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1462 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1463 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1464 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1465 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1466 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1467 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1468 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1469 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1470 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1472 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1473 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1474 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1475 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1476 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1477 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1478 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1479 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1480 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1481 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1482 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1483 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1485 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1486 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1487 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1488 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1489 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1490 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1491 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1492 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1493 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1494 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1495 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1496 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1498 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1499 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1500 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1501 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1502 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1503 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1504 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1505 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1506 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1507 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1508 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1509 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1511 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1512 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1513 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1514 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1515 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1516 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1517 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1518 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1519 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1520 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1521 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1522 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1524 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1525 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1526 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1527 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1528 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1529 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1530 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1531 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1532 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1533 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1534 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1535 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1537 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1538 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1539 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1540 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1541 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1542 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1543 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1544 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1545 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1546 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1547 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1548 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1550 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1551 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1552 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1553 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1554 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1555 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1556 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1557 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1558 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1559 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1560 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1561 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1563 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1564 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1565 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1566 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1567 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1568 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1569 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1570 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1571 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1572 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1573 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1574 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1576 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1577 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1578 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1579 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1580 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1581 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1582 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1583 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1584 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1585 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1586 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1587 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1589 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1590 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1591 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1592 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1593 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1594 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1595 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1596 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1597 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1598 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1599 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1600 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1602 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1603 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1604 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1605 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1606 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1607 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1608 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1609 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1610 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1611 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1612 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1613 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1615 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1616 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1617 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1618 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1619 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1620 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1621 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1622 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1623 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1624 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1625 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1626 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1628 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1629 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1630 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1631 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1632 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1633 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1634 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1635 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1636 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1637 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1638 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1639 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1641 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1642 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1643 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1644 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1645 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1646 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1647 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1648 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1649 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1650 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1651 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1652 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1654 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1655 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1656 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1657 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1658 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1659 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1660 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1661 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1662 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1663 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1664 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1665 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1667 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1668 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1669 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1670 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1671 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1672 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1673 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1674 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1675 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1676 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1677 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1678 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1680 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1681 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1682 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1683 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1684 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1685 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1686 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1687 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1688 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1689 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1690 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1691 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1693 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1694 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1695 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1696 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1697 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1698 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1699 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1700 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1701 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1702 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1703 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1704 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1706 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1707 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1708 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1709 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1710 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1711 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1712 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1713 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1714 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1715 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1716 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1717 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1719 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1720 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1721 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1722 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1723 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1724 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1725 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1726 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1727 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1728 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1729 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1730 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1732 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1733 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1734 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1735 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1736 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1737 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1738 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1739 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1740 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1741 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1742 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1743 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1745 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1746 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1747 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1748 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1749 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1750 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1751 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1752 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1753 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1754 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1755 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1756 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1758 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1759 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1760 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1761 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1762 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1763 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1764 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1765 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1766 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1767 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1768 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1769 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1771 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1772 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1773 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1774 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1775 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1776 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1777 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1778 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1779 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1780 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1781 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1782 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1784 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1785 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1786 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1787 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1788 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1789 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1790 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1791 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1792 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1793 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1794 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1795 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1797 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1798 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1799 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1800 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1801 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1802 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1803 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1804 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1805 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1806 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1807 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1808 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1810 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1811 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1812 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1813 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1814 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
1815 not be an optional suffix, but part of the instruction. To be
1816 compatible, we accept either. */
1817 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
1818 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
1820 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1821 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1822 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1823 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1824 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1825 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1826 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1827 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1828 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1829 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1830 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1831 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1833 /* The implementation of the FIX instruction is broken on some
1834 assemblers, in that it accepts a precision specifier as well as a
1835 rounding specifier, despite the fact that this is meaningless.
1836 To be more compatible, we accept it as well, though of course it
1837 does not set any bits. */
1838 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1839 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1840 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1841 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1842 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1843 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1844 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1845 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1846 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1847 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1848 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1849 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1850 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1852 /* Instructions that were new with the real FPA, call them V2. */
1853 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1854 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1855 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1856 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1857 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1858 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1860 /* VFP V1xD (single precision). */
1861 /* Moves and type conversions. */
1862 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1863 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_sp},
1864 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_from_reg},
1865 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD, do_empty},
1866 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1867 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1868 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1869 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1870 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1871 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1872 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_ctrl},
1873 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_ctrl_from_reg},
1875 /* Memory operations. */
1876 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
1877 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
1878 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1879 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1880 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1881 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1882 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1883 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1884 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1885 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1886 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1887 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1888 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1889 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1890 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1891 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1892 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1893 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1895 /* Monadic operations. */
1896 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1897 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1898 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1900 /* Dyadic operations. */
1901 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1902 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1903 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1904 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1905 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1906 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1907 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1908 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1909 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1911 /* Comparisons. */
1912 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1913 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
1914 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1915 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
1917 /* VFP V1 (Double precision). */
1918 /* Moves and type conversions. */
1919 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1920 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
1921 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1922 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
1923 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
1924 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
1925 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
1926 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
1927 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
1928 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1929 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1930 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1931 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1933 /* Memory operations. */
1934 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
1935 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
1936 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1937 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1938 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1939 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1940 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1941 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1942 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1943 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1945 /* Monadic operations. */
1946 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1947 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1948 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1950 /* Dyadic operations. */
1951 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1952 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1953 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1954 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1955 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1956 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1957 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1958 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1959 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1961 /* Comparisons. */
1962 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1963 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
1964 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1965 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
1967 /* VFP V2. */
1968 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2, do_vfp_sp_reg2},
1969 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2, do_vfp_sp_reg2},
1970 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2, do_vfp_dp_from_reg2},
1971 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_dp},
1973 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
1974 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE, do_xsc_mia},
1975 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1976 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1977 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1978 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1979 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1980 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE, do_xsc_mar},
1981 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE, do_xsc_mra},
1983 /* Intel Wireless MMX technology instructions. */
1984 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
1985 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
1986 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
1987 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
1988 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
1989 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
1990 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
1991 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
1992 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
1993 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
1994 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
1995 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
1996 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
1997 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
1998 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
1999 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
2000 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
2001 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
2002 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmcr},
2003 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmcrr},
2004 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2005 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2006 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2007 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2008 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2009 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2010 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
2011 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
2012 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
2013 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmrc},
2014 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmrrc},
2015 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
2016 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
2017 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
2018 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2019 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2020 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2021 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2022 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2023 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2024 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2025 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2026 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2027 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2028 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2029 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2030 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT, do_iwmmxt_waligni},
2031 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2032 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2033 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2034 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2035 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2036 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2037 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2038 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2039 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2040 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2041 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2042 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2043 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2044 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2045 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2046 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2047 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2048 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2049 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2050 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
2051 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
2052 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2053 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2054 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2055 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2056 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2057 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2058 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2059 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2060 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2061 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2062 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2063 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2064 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2065 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2066 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2067 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2068 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2069 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2070 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2071 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2072 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wmov},
2073 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2074 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2075 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2076 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2077 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2078 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2079 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2080 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2081 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2082 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2083 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2084 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2085 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2086 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2087 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2088 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2089 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2090 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2091 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2092 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2093 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2094 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wshufh},
2095 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2096 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2097 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2098 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2099 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2100 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2101 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2102 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2103 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2104 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2105 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2106 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2107 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2108 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2109 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2110 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2111 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2112 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2113 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
2114 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
2115 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2116 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2117 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2118 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2119 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2120 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2121 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2122 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2123 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2124 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2125 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2126 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2127 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2128 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2129 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2130 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2131 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2132 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2133 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2134 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2135 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2136 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2137 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2138 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2139 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2140 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2141 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2142 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2143 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2144 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2145 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wzero},
2147 /* Cirrus Maverick instructions. */
2148 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
2149 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
2150 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
2151 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
2152 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
2153 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
2154 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
2155 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
2156 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK, do_mav_binops_2a},
2157 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK, do_mav_binops_1a},
2158 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
2159 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
2160 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
2161 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
2162 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
2163 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
2164 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
2165 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
2166 {"cfmval32", 0xee100610, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2167 {"cfmv32al", 0xee000610, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2168 {"cfmvam32", 0xee100630, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2169 {"cfmv32am", 0xee000630, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2170 {"cfmvah32", 0xee100650, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2171 {"cfmv32ah", 0xee000650, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2172 {"cfmva32", 0xee100670, 7, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2173 {"cfmv32a", 0xee000670, 7, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2174 {"cfmva64", 0xee100690, 7, ARM_CEXT_MAVERICK, do_mav_binops_3c},
2175 {"cfmv64a", 0xee000690, 7, ARM_CEXT_MAVERICK, do_mav_binops_3d},
2176 {"cfmvsc32", 0xee1006b0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_1},
2177 {"cfmv32sc", 0xee0006b0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_2},
2178 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
2179 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
2180 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK, do_mav_binops_1f},
2181 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK, do_mav_binops_1g},
2182 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK, do_mav_binops_1h},
2183 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1i},
2184 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1j},
2185 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1k},
2186 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK, do_mav_binops_1l},
2187 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1m},
2188 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1l},
2189 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1m},
2190 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK, do_mav_triple_4a},
2191 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK, do_mav_triple_4b},
2192 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK, do_mav_shift_1},
2193 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK, do_mav_shift_2},
2194 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK, do_mav_triple_5a},
2195 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5b},
2196 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK, do_mav_triple_5c},
2197 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5d},
2198 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
2199 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
2200 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
2201 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
2202 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
2203 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
2204 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
2205 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
2206 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
2207 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
2208 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
2209 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
2210 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
2211 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
2212 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2213 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
2214 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2215 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
2216 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2217 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
2218 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2219 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2220 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
2221 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
2222 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
2223 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
2226 /* Defines for various bits that we will want to toggle. */
2227 #define INST_IMMEDIATE 0x02000000
2228 #define OFFSET_REG 0x02000000
2229 #define HWOFFSET_IMM 0x00400000
2230 #define SHIFT_BY_REG 0x00000010
2231 #define PRE_INDEX 0x01000000
2232 #define INDEX_UP 0x00800000
2233 #define WRITE_BACK 0x00200000
2234 #define LDM_TYPE_2_OR_3 0x00400000
2236 #define LITERAL_MASK 0xf000f000
2237 #define OPCODE_MASK 0xfe1fffff
2238 #define V4_STR_BIT 0x00000020
2240 #define DATA_OP_SHIFT 21
2242 /* Codes to distinguish the arithmetic instructions. */
2243 #define OPCODE_AND 0
2244 #define OPCODE_EOR 1
2245 #define OPCODE_SUB 2
2246 #define OPCODE_RSB 3
2247 #define OPCODE_ADD 4
2248 #define OPCODE_ADC 5
2249 #define OPCODE_SBC 6
2250 #define OPCODE_RSC 7
2251 #define OPCODE_TST 8
2252 #define OPCODE_TEQ 9
2253 #define OPCODE_CMP 10
2254 #define OPCODE_CMN 11
2255 #define OPCODE_ORR 12
2256 #define OPCODE_MOV 13
2257 #define OPCODE_BIC 14
2258 #define OPCODE_MVN 15
2260 /* Thumb v1 (ARMv4T). */
2261 static void do_t_nop PARAMS ((char *));
2262 static void do_t_arit PARAMS ((char *));
2263 static void do_t_add PARAMS ((char *));
2264 static void do_t_asr PARAMS ((char *));
2265 static void do_t_branch9 PARAMS ((char *));
2266 static void do_t_branch12 PARAMS ((char *));
2267 static void do_t_branch23 PARAMS ((char *));
2268 static void do_t_bx PARAMS ((char *));
2269 static void do_t_compare PARAMS ((char *));
2270 static void do_t_ldmstm PARAMS ((char *));
2271 static void do_t_ldr PARAMS ((char *));
2272 static void do_t_ldrb PARAMS ((char *));
2273 static void do_t_ldrh PARAMS ((char *));
2274 static void do_t_lds PARAMS ((char *));
2275 static void do_t_lsl PARAMS ((char *));
2276 static void do_t_lsr PARAMS ((char *));
2277 static void do_t_mov PARAMS ((char *));
2278 static void do_t_push_pop PARAMS ((char *));
2279 static void do_t_str PARAMS ((char *));
2280 static void do_t_strb PARAMS ((char *));
2281 static void do_t_strh PARAMS ((char *));
2282 static void do_t_sub PARAMS ((char *));
2283 static void do_t_swi PARAMS ((char *));
2284 static void do_t_adr PARAMS ((char *));
2286 /* Thumb v2 (ARMv5T). */
2287 static void do_t_blx PARAMS ((char *));
2288 static void do_t_bkpt PARAMS ((char *));
2290 /* ARM V6. */
2291 static void do_t_cps PARAMS ((char *));
2292 static void do_t_cpy PARAMS ((char *));
2293 static void do_t_setend PARAMS ((char *));;
2295 #define T_OPCODE_MUL 0x4340
2296 #define T_OPCODE_TST 0x4200
2297 #define T_OPCODE_CMN 0x42c0
2298 #define T_OPCODE_NEG 0x4240
2299 #define T_OPCODE_MVN 0x43c0
2301 #define T_OPCODE_ADD_R3 0x1800
2302 #define T_OPCODE_SUB_R3 0x1a00
2303 #define T_OPCODE_ADD_HI 0x4400
2304 #define T_OPCODE_ADD_ST 0xb000
2305 #define T_OPCODE_SUB_ST 0xb080
2306 #define T_OPCODE_ADD_SP 0xa800
2307 #define T_OPCODE_ADD_PC 0xa000
2308 #define T_OPCODE_ADD_I8 0x3000
2309 #define T_OPCODE_SUB_I8 0x3800
2310 #define T_OPCODE_ADD_I3 0x1c00
2311 #define T_OPCODE_SUB_I3 0x1e00
2313 #define T_OPCODE_ASR_R 0x4100
2314 #define T_OPCODE_LSL_R 0x4080
2315 #define T_OPCODE_LSR_R 0x40c0
2316 #define T_OPCODE_ASR_I 0x1000
2317 #define T_OPCODE_LSL_I 0x0000
2318 #define T_OPCODE_LSR_I 0x0800
2320 #define T_OPCODE_MOV_I8 0x2000
2321 #define T_OPCODE_CMP_I8 0x2800
2322 #define T_OPCODE_CMP_LR 0x4280
2323 #define T_OPCODE_MOV_HR 0x4600
2324 #define T_OPCODE_CMP_HR 0x4500
2326 #define T_OPCODE_LDR_PC 0x4800
2327 #define T_OPCODE_LDR_SP 0x9800
2328 #define T_OPCODE_STR_SP 0x9000
2329 #define T_OPCODE_LDR_IW 0x6800
2330 #define T_OPCODE_STR_IW 0x6000
2331 #define T_OPCODE_LDR_IH 0x8800
2332 #define T_OPCODE_STR_IH 0x8000
2333 #define T_OPCODE_LDR_IB 0x7800
2334 #define T_OPCODE_STR_IB 0x7000
2335 #define T_OPCODE_LDR_RW 0x5800
2336 #define T_OPCODE_STR_RW 0x5000
2337 #define T_OPCODE_LDR_RH 0x5a00
2338 #define T_OPCODE_STR_RH 0x5200
2339 #define T_OPCODE_LDR_RB 0x5c00
2340 #define T_OPCODE_STR_RB 0x5400
2342 #define T_OPCODE_PUSH 0xb400
2343 #define T_OPCODE_POP 0xbc00
2345 #define T_OPCODE_BRANCH 0xe7fe
2347 static int thumb_reg PARAMS ((char ** str, int hi_lo));
2349 #define THUMB_SIZE 2 /* Size of thumb instruction. */
2350 #define THUMB_REG_LO 0x1
2351 #define THUMB_REG_HI 0x2
2352 #define THUMB_REG_ANY 0x3
2354 #define THUMB_H1 0x0080
2355 #define THUMB_H2 0x0040
2357 #define THUMB_ASR 0
2358 #define THUMB_LSL 1
2359 #define THUMB_LSR 2
2361 #define THUMB_MOVE 0
2362 #define THUMB_COMPARE 1
2363 #define THUMB_CPY 2
2365 #define THUMB_LOAD 0
2366 #define THUMB_STORE 1
2368 #define THUMB_PP_PC_LR 0x0100
2370 /* These three are used for immediate shifts, do not alter. */
2371 #define THUMB_WORD 2
2372 #define THUMB_HALFWORD 1
2373 #define THUMB_BYTE 0
2375 struct thumb_opcode
2377 /* Basic string to match. */
2378 const char * template;
2380 /* Basic instruction code. */
2381 unsigned long value;
2383 int size;
2385 /* Which CPU variants this exists for. */
2386 unsigned long variant;
2388 /* Function to call to parse args. */
2389 void (* parms) PARAMS ((char *));
2392 static const struct thumb_opcode tinsns[] =
2394 /* Thumb v1 (ARMv4T). */
2395 {"adc", 0x4140, 2, ARM_EXT_V4T, do_t_arit},
2396 {"add", 0x0000, 2, ARM_EXT_V4T, do_t_add},
2397 {"and", 0x4000, 2, ARM_EXT_V4T, do_t_arit},
2398 {"asr", 0x0000, 2, ARM_EXT_V4T, do_t_asr},
2399 {"b", T_OPCODE_BRANCH, 2, ARM_EXT_V4T, do_t_branch12},
2400 {"beq", 0xd0fe, 2, ARM_EXT_V4T, do_t_branch9},
2401 {"bne", 0xd1fe, 2, ARM_EXT_V4T, do_t_branch9},
2402 {"bcs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
2403 {"bhs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
2404 {"bcc", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
2405 {"bul", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
2406 {"blo", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
2407 {"bmi", 0xd4fe, 2, ARM_EXT_V4T, do_t_branch9},
2408 {"bpl", 0xd5fe, 2, ARM_EXT_V4T, do_t_branch9},
2409 {"bvs", 0xd6fe, 2, ARM_EXT_V4T, do_t_branch9},
2410 {"bvc", 0xd7fe, 2, ARM_EXT_V4T, do_t_branch9},
2411 {"bhi", 0xd8fe, 2, ARM_EXT_V4T, do_t_branch9},
2412 {"bls", 0xd9fe, 2, ARM_EXT_V4T, do_t_branch9},
2413 {"bge", 0xdafe, 2, ARM_EXT_V4T, do_t_branch9},
2414 {"blt", 0xdbfe, 2, ARM_EXT_V4T, do_t_branch9},
2415 {"bgt", 0xdcfe, 2, ARM_EXT_V4T, do_t_branch9},
2416 {"ble", 0xddfe, 2, ARM_EXT_V4T, do_t_branch9},
2417 {"bal", 0xdefe, 2, ARM_EXT_V4T, do_t_branch9},
2418 {"bic", 0x4380, 2, ARM_EXT_V4T, do_t_arit},
2419 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T, do_t_branch23},
2420 {"bx", 0x4700, 2, ARM_EXT_V4T, do_t_bx},
2421 {"cmn", T_OPCODE_CMN, 2, ARM_EXT_V4T, do_t_arit},
2422 {"cmp", 0x0000, 2, ARM_EXT_V4T, do_t_compare},
2423 {"eor", 0x4040, 2, ARM_EXT_V4T, do_t_arit},
2424 {"ldmia", 0xc800, 2, ARM_EXT_V4T, do_t_ldmstm},
2425 {"ldr", 0x0000, 2, ARM_EXT_V4T, do_t_ldr},
2426 {"ldrb", 0x0000, 2, ARM_EXT_V4T, do_t_ldrb},
2427 {"ldrh", 0x0000, 2, ARM_EXT_V4T, do_t_ldrh},
2428 {"ldrsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
2429 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
2430 {"ldsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
2431 {"ldsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
2432 {"lsl", 0x0000, 2, ARM_EXT_V4T, do_t_lsl},
2433 {"lsr", 0x0000, 2, ARM_EXT_V4T, do_t_lsr},
2434 {"mov", 0x0000, 2, ARM_EXT_V4T, do_t_mov},
2435 {"mul", T_OPCODE_MUL, 2, ARM_EXT_V4T, do_t_arit},
2436 {"mvn", T_OPCODE_MVN, 2, ARM_EXT_V4T, do_t_arit},
2437 {"neg", T_OPCODE_NEG, 2, ARM_EXT_V4T, do_t_arit},
2438 {"orr", 0x4300, 2, ARM_EXT_V4T, do_t_arit},
2439 {"pop", 0xbc00, 2, ARM_EXT_V4T, do_t_push_pop},
2440 {"push", 0xb400, 2, ARM_EXT_V4T, do_t_push_pop},
2441 {"ror", 0x41c0, 2, ARM_EXT_V4T, do_t_arit},
2442 {"sbc", 0x4180, 2, ARM_EXT_V4T, do_t_arit},
2443 {"stmia", 0xc000, 2, ARM_EXT_V4T, do_t_ldmstm},
2444 {"str", 0x0000, 2, ARM_EXT_V4T, do_t_str},
2445 {"strb", 0x0000, 2, ARM_EXT_V4T, do_t_strb},
2446 {"strh", 0x0000, 2, ARM_EXT_V4T, do_t_strh},
2447 {"swi", 0xdf00, 2, ARM_EXT_V4T, do_t_swi},
2448 {"sub", 0x0000, 2, ARM_EXT_V4T, do_t_sub},
2449 {"tst", T_OPCODE_TST, 2, ARM_EXT_V4T, do_t_arit},
2450 /* Pseudo ops: */
2451 {"adr", 0x0000, 2, ARM_EXT_V4T, do_t_adr},
2452 {"nop", 0x46C0, 2, ARM_EXT_V4T, do_t_nop}, /* mov r8,r8 */
2453 /* Thumb v2 (ARMv5T). */
2454 {"blx", 0, 0, ARM_EXT_V5T, do_t_blx},
2455 {"bkpt", 0xbe00, 2, ARM_EXT_V5T, do_t_bkpt},
2457 /* ARM V6. */
2458 {"cpsie", 0xb660, 2, ARM_EXT_V6, do_t_cps},
2459 {"cpsid", 0xb670, 2, ARM_EXT_V6, do_t_cps},
2460 {"cpy", 0x4600, 2, ARM_EXT_V6, do_t_cpy},
2461 {"rev", 0xba00, 2, ARM_EXT_V6, do_t_arit},
2462 {"rev16", 0xba40, 2, ARM_EXT_V6, do_t_arit},
2463 {"revsh", 0xbac0, 2, ARM_EXT_V6, do_t_arit},
2464 {"setend", 0xb650, 2, ARM_EXT_V6, do_t_setend},
2465 {"sxth", 0xb200, 2, ARM_EXT_V6, do_t_arit},
2466 {"sxtb", 0xb240, 2, ARM_EXT_V6, do_t_arit},
2467 {"uxth", 0xb280, 2, ARM_EXT_V6, do_t_arit},
2468 {"uxtb", 0xb2c0, 2, ARM_EXT_V6, do_t_arit},
2471 #define BAD_ARGS _("bad arguments to instruction")
2472 #define BAD_PC _("r15 not allowed here")
2473 #define BAD_COND _("instruction is not conditional")
2474 #define ERR_NO_ACCUM _("acc0 expected")
2476 static struct hash_control * arm_ops_hsh = NULL;
2477 static struct hash_control * arm_tops_hsh = NULL;
2478 static struct hash_control * arm_cond_hsh = NULL;
2479 static struct hash_control * arm_shift_hsh = NULL;
2480 static struct hash_control * arm_psr_hsh = NULL;
2482 /* This table describes all the machine specific pseudo-ops the assembler
2483 has to support. The fields are:
2484 pseudo-op name without dot
2485 function to call to execute this pseudo-op
2486 Integer arg to pass to the function. */
2488 static void s_req PARAMS ((int));
2489 static void s_unreq PARAMS ((int));
2490 static void s_align PARAMS ((int));
2491 static void s_bss PARAMS ((int));
2492 static void s_even PARAMS ((int));
2493 static void s_ltorg PARAMS ((int));
2494 static void s_arm PARAMS ((int));
2495 static void s_thumb PARAMS ((int));
2496 static void s_code PARAMS ((int));
2497 static void s_force_thumb PARAMS ((int));
2498 static void s_thumb_func PARAMS ((int));
2499 static void s_thumb_set PARAMS ((int));
2500 #ifdef OBJ_ELF
2501 static void s_arm_elf_cons PARAMS ((int));
2502 #endif
2504 static int my_get_expression PARAMS ((expressionS *, char **));
2506 const pseudo_typeS md_pseudo_table[] =
2508 /* Never called because '.req' does not start a line. */
2509 { "req", s_req, 0 },
2510 { "unreq", s_unreq, 0 },
2511 { "bss", s_bss, 0 },
2512 { "align", s_align, 0 },
2513 { "arm", s_arm, 0 },
2514 { "thumb", s_thumb, 0 },
2515 { "code", s_code, 0 },
2516 { "force_thumb", s_force_thumb, 0 },
2517 { "thumb_func", s_thumb_func, 0 },
2518 { "thumb_set", s_thumb_set, 0 },
2519 { "even", s_even, 0 },
2520 { "ltorg", s_ltorg, 0 },
2521 { "pool", s_ltorg, 0 },
2522 #ifdef OBJ_ELF
2523 { "word", s_arm_elf_cons, 4 },
2524 { "long", s_arm_elf_cons, 4 },
2525 #else
2526 { "word", cons, 4},
2527 #endif
2528 { "extend", float_cons, 'x' },
2529 { "ldouble", float_cons, 'x' },
2530 { "packed", float_cons, 'p' },
2531 { 0, 0, 0 }
2534 /* Other internal functions. */
2535 static int arm_parse_extension PARAMS ((char *, int *));
2536 static int arm_parse_cpu PARAMS ((char *));
2537 static int arm_parse_arch PARAMS ((char *));
2538 static int arm_parse_fpu PARAMS ((char *));
2539 #if 0 /* Suppressed - for now. */
2540 #if defined OBJ_COFF || defined OBJ_ELF
2541 static void arm_add_note PARAMS ((const char *, const char *, unsigned int));
2542 #endif
2543 #endif
2545 /* Stuff needed to resolve the label ambiguity
2548 label: <insn>
2549 may differ from:
2551 label:
2552 <insn>
2555 symbolS * last_label_seen;
2556 static int label_is_thumb_function_name = FALSE;
2558 /* Literal Pool stuff. */
2560 #define MAX_LITERAL_POOL_SIZE 1024
2562 /* Literal pool structure. Held on a per-section
2563 and per-sub-section basis. */
2564 typedef struct literal_pool
2566 expressionS literals [MAX_LITERAL_POOL_SIZE];
2567 unsigned int next_free_entry;
2568 unsigned int id;
2569 symbolS * symbol;
2570 segT section;
2571 subsegT sub_section;
2572 struct literal_pool * next;
2573 } literal_pool;
2575 /* Pointer to a linked list of literal pools. */
2576 literal_pool * list_of_pools = NULL;
2578 static literal_pool * find_literal_pool PARAMS ((void));
2579 static literal_pool * find_or_make_literal_pool PARAMS ((void));
2581 static literal_pool *
2582 find_literal_pool ()
2584 literal_pool * pool;
2586 for (pool = list_of_pools; pool != NULL; pool = pool->next)
2588 if (pool->section == now_seg
2589 && pool->sub_section == now_subseg)
2590 break;
2593 return pool;
2596 static literal_pool *
2597 find_or_make_literal_pool ()
2599 /* Next literal pool ID number. */
2600 static unsigned int latest_pool_num = 1;
2601 literal_pool * pool;
2603 pool = find_literal_pool ();
2605 if (pool == NULL)
2607 /* Create a new pool. */
2608 pool = (literal_pool *) xmalloc (sizeof (* pool));
2609 if (! pool)
2610 return NULL;
2612 pool->next_free_entry = 0;
2613 pool->section = now_seg;
2614 pool->sub_section = now_subseg;
2615 pool->next = list_of_pools;
2616 pool->symbol = NULL;
2618 /* Add it to the list. */
2619 list_of_pools = pool;
2622 /* New pools, and emptied pools, will have a NULL symbol. */
2623 if (pool->symbol == NULL)
2625 pool->symbol = symbol_create (FAKE_LABEL_NAME, undefined_section,
2626 (valueT) 0, &zero_address_frag);
2627 pool->id = latest_pool_num ++;
2630 /* Done. */
2631 return pool;
2634 /* Add the literal in the global 'inst'
2635 structure to the relevent literal pool. */
2636 static int
2637 add_to_lit_pool ()
2639 literal_pool * pool;
2640 unsigned int entry;
2642 pool = find_or_make_literal_pool ();
2644 /* Check if this literal value is already in the pool. */
2645 for (entry = 0; entry < pool->next_free_entry; entry ++)
2647 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
2648 && (inst.reloc.exp.X_op == O_constant)
2649 && (pool->literals[entry].X_add_number
2650 == inst.reloc.exp.X_add_number)
2651 && (pool->literals[entry].X_unsigned
2652 == inst.reloc.exp.X_unsigned))
2653 break;
2655 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
2656 && (inst.reloc.exp.X_op == O_symbol)
2657 && (pool->literals[entry].X_add_number
2658 == inst.reloc.exp.X_add_number)
2659 && (pool->literals[entry].X_add_symbol
2660 == inst.reloc.exp.X_add_symbol)
2661 && (pool->literals[entry].X_op_symbol
2662 == inst.reloc.exp.X_op_symbol))
2663 break;
2666 /* Do we need to create a new entry? */
2667 if (entry == pool->next_free_entry)
2669 if (entry >= MAX_LITERAL_POOL_SIZE)
2671 inst.error = _("literal pool overflow");
2672 return FAIL;
2675 pool->literals[entry] = inst.reloc.exp;
2676 pool->next_free_entry += 1;
2679 inst.reloc.exp.X_op = O_symbol;
2680 inst.reloc.exp.X_add_number = ((int) entry) * 4 - 8;
2681 inst.reloc.exp.X_add_symbol = pool->symbol;
2683 return SUCCESS;
2686 /* Can't use symbol_new here, so have to create a symbol and then at
2687 a later date assign it a value. Thats what these functions do. */
2689 static void
2690 symbol_locate (symbolP, name, segment, valu, frag)
2691 symbolS * symbolP;
2692 const char * name; /* It is copied, the caller can modify. */
2693 segT segment; /* Segment identifier (SEG_<something>). */
2694 valueT valu; /* Symbol value. */
2695 fragS * frag; /* Associated fragment. */
2697 unsigned int name_length;
2698 char * preserved_copy_of_name;
2700 name_length = strlen (name) + 1; /* +1 for \0. */
2701 obstack_grow (&notes, name, name_length);
2702 preserved_copy_of_name = obstack_finish (&notes);
2703 #ifdef STRIP_UNDERSCORE
2704 if (preserved_copy_of_name[0] == '_')
2705 preserved_copy_of_name++;
2706 #endif
2708 #ifdef tc_canonicalize_symbol_name
2709 preserved_copy_of_name =
2710 tc_canonicalize_symbol_name (preserved_copy_of_name);
2711 #endif
2713 S_SET_NAME (symbolP, preserved_copy_of_name);
2715 S_SET_SEGMENT (symbolP, segment);
2716 S_SET_VALUE (symbolP, valu);
2717 symbol_clear_list_pointers (symbolP);
2719 symbol_set_frag (symbolP, frag);
2721 /* Link to end of symbol chain. */
2723 extern int symbol_table_frozen;
2724 if (symbol_table_frozen)
2725 abort ();
2728 symbol_append (symbolP, symbol_lastP, & symbol_rootP, & symbol_lastP);
2730 obj_symbol_new_hook (symbolP);
2732 #ifdef tc_symbol_new_hook
2733 tc_symbol_new_hook (symbolP);
2734 #endif
2736 #ifdef DEBUG_SYMS
2737 verify_symbol_chain (symbol_rootP, symbol_lastP);
2738 #endif /* DEBUG_SYMS */
2741 /* Check that an immediate is valid.
2742 If so, convert it to the right format. */
2744 static unsigned int
2745 validate_immediate (val)
2746 unsigned int val;
2748 unsigned int a;
2749 unsigned int i;
2751 #define rotate_left(v, n) (v << n | v >> (32 - n))
2753 for (i = 0; i < 32; i += 2)
2754 if ((a = rotate_left (val, i)) <= 0xff)
2755 return a | (i << 7); /* 12-bit pack: [shift-cnt,const]. */
2757 return FAIL;
2760 /* Check to see if an immediate can be computed as two separate immediate
2761 values, added together. We already know that this value cannot be
2762 computed by just one ARM instruction. */
2764 static unsigned int
2765 validate_immediate_twopart (val, highpart)
2766 unsigned int val;
2767 unsigned int * highpart;
2769 unsigned int a;
2770 unsigned int i;
2772 for (i = 0; i < 32; i += 2)
2773 if (((a = rotate_left (val, i)) & 0xff) != 0)
2775 if (a & 0xff00)
2777 if (a & ~ 0xffff)
2778 continue;
2779 * highpart = (a >> 8) | ((i + 24) << 7);
2781 else if (a & 0xff0000)
2783 if (a & 0xff000000)
2784 continue;
2785 * highpart = (a >> 16) | ((i + 16) << 7);
2787 else
2789 assert (a & 0xff000000);
2790 * highpart = (a >> 24) | ((i + 8) << 7);
2793 return (a & 0xff) | (i << 7);
2796 return FAIL;
2799 static int
2800 validate_offset_imm (val, hwse)
2801 unsigned int val;
2802 int hwse;
2804 if ((hwse && val > 255) || val > 4095)
2805 return FAIL;
2806 return val;
2810 #ifdef OBJ_ELF
2811 enum mstate
2813 MAP_DATA,
2814 MAP_ARM,
2815 MAP_THUMB
2818 /* This code is to handle mapping symbols as defined in the ARM ELF spec.
2819 (This text is taken from version B-02 of the spec):
2821 4.4.7 Mapping and tagging symbols
2823 A section of an ARM ELF file can contain a mixture of ARM code,
2824 Thumb code, and data. There are inline transitions between code
2825 and data at literal pool boundaries. There can also be inline
2826 transitions between ARM code and Thumb code, for example in
2827 ARM-Thumb inter-working veneers. Linkers, machine-level
2828 debuggers, profiling tools, and disassembly tools need to map
2829 images accurately. For example, setting an ARM breakpoint on a
2830 Thumb location, or in a literal pool, can crash the program
2831 being debugged, ruining the debugging session.
2833 ARM ELF entities are mapped (see section 4.4.7.1 below) and
2834 tagged (see section 4.4.7.2 below) using local symbols (with
2835 binding STB_LOCAL). To assist consumers, mapping and tagging
2836 symbols should be collated first in the symbol table, before
2837 other symbols with binding STB_LOCAL.
2839 To allow properly collated mapping and tagging symbols to be
2840 skipped by consumers that have no interest in them, the first
2841 such symbol should have the name $m and its st_value field equal
2842 to the total number of mapping and tagging symbols (including
2843 the $m) in the symbol table.
2845 4.4.7.1 Mapping symbols
2847 $a Labels the first byte of a sequence of ARM instructions.
2848 Its type is STT_FUNC.
2850 $d Labels the first byte of a sequence of data items.
2851 Its type is STT_OBJECT.
2853 $t Labels the first byte of a sequence of Thumb instructions.
2854 Its type is STT_FUNC.
2856 This list of mapping symbols may be extended in the future.
2858 Section-relative mapping symbols
2860 Mapping symbols defined in a section define a sequence of
2861 half-open address intervals that cover the address range of the
2862 section. Each interval starts at the address defined by a
2863 mapping symbol, and continues up to, but not including, the
2864 address defined by the next (in address order) mapping symbol or
2865 the end of the section. A corollary is that there must be a
2866 mapping symbol defined at the beginning of each section.
2867 Consumers can ignore the size of a section-relative mapping
2868 symbol. Producers can set it to 0.
2870 Absolute mapping symbols
2872 Because of the need to crystallize a Thumb address with the
2873 Thumb-bit set, absolute symbol of type STT_FUNC (symbols of type
2874 STT_FUNC defined in section SHN_ABS) need to be mapped with $a
2875 or $t.
2877 The extent of a mapping symbol defined in SHN_ABS is [st_value,
2878 st_value + st_size), or [st_value, st_value + 1) if st_size = 0,
2879 where [x, y) denotes the half-open address range from x,
2880 inclusive, to y, exclusive.
2882 In the absence of a mapping symbol, a consumer can interpret a
2883 function symbol with an odd value as the Thumb code address
2884 obtained by clearing the least significant bit of the
2885 value. This interpretation is deprecated, and it may not work in
2886 the future.
2888 Note - the Tagging symbols ($b, $f, $p $m) have been dropped from
2889 the EABI (which is still under development), so they are not
2890 implemented here. */
2892 static void
2893 mapping_state (enum mstate state)
2895 static enum mstate mapstate = MAP_DATA;
2896 symbolS * symbolP;
2897 const char * symname;
2898 int type;
2900 if (mapstate == state)
2901 /* The mapping symbol has already been emitted.
2902 There is nothing else to do. */
2903 return;
2905 mapstate = state;
2907 switch (state)
2909 case MAP_DATA:
2910 symname = "$d";
2911 type = BSF_OBJECT;
2912 break;
2913 case MAP_ARM:
2914 symname = "$a";
2915 type = BSF_FUNCTION;
2916 break;
2917 case MAP_THUMB:
2918 symname = "$t";
2919 type = BSF_FUNCTION;
2920 break;
2921 default:
2922 abort ();
2925 symbolP = symbol_new (symname, now_seg, (valueT) frag_now_fix (), frag_now);
2926 symbol_table_insert (symbolP);
2927 symbol_get_bfdsym (symbolP)->flags |= type | BSF_LOCAL;
2929 switch (state)
2931 case MAP_ARM:
2932 THUMB_SET_FUNC (symbolP, 0);
2933 ARM_SET_THUMB (symbolP, 0);
2934 ARM_SET_INTERWORK (symbolP, support_interwork);
2935 break;
2937 case MAP_THUMB:
2938 THUMB_SET_FUNC (symbolP, 1);
2939 ARM_SET_THUMB (symbolP, 1);
2940 ARM_SET_INTERWORK (symbolP, support_interwork);
2941 break;
2943 case MAP_DATA:
2944 default:
2945 return;
2949 /* When we change sections we need to issue a new mapping symbol. */
2951 void
2952 arm_elf_change_section (void)
2954 flagword flags;
2956 if (!SEG_NORMAL (now_seg))
2957 return;
2959 flags = bfd_get_section_flags (stdoutput, now_seg);
2961 /* We can ignore sections that only contain debug info. */
2962 if ((flags & SEC_ALLOC) == 0)
2963 return;
2965 if (flags & SEC_CODE)
2967 if (thumb_mode)
2968 mapping_state (MAP_THUMB);
2969 else
2970 mapping_state (MAP_ARM);
2972 else
2973 /* This section does not contain code. Therefore it must contain data. */
2974 mapping_state (MAP_DATA);
2976 #else
2977 #define mapping_state(a)
2978 #endif /* OBJ_ELF */
2981 static void
2982 s_req (a)
2983 int a ATTRIBUTE_UNUSED;
2985 as_bad (_("invalid syntax for .req directive"));
2988 /* The .unreq directive deletes an alias which was previously defined
2989 by .req. For example:
2991 my_alias .req r11
2992 .unreq my_alias */
2994 static void
2995 s_unreq (int a ATTRIBUTE_UNUSED)
2997 char *name;
2998 char saved_char;
3000 skip_whitespace (input_line_pointer);
3001 name = input_line_pointer;
3003 while (*input_line_pointer != 0
3004 && *input_line_pointer != ' '
3005 && *input_line_pointer != '\n')
3006 ++input_line_pointer;
3008 saved_char = *input_line_pointer;
3009 *input_line_pointer = 0;
3011 if (*name)
3013 enum arm_reg_type req_type = arm_reg_parse_any (name);
3015 if (req_type != REG_TYPE_MAX)
3017 char *temp_name = name;
3018 int req_no = arm_reg_parse (&temp_name, all_reg_maps[req_type].htab);
3020 if (req_no != FAIL)
3022 struct reg_entry *req_entry;
3024 /* Check to see if this alias is a builtin one. */
3025 req_entry = hash_delete (all_reg_maps[req_type].htab, name);
3027 if (!req_entry)
3028 as_bad (_("unreq: missing hash entry for \"%s\""), name);
3029 else if (req_entry->builtin)
3030 /* FIXME: We are deleting a built in register alias which
3031 points to a const data structure, so we only need to
3032 free up the memory used by the key in the hash table.
3033 Unfortunately we have not recorded this value, so this
3034 is a memory leak. */
3035 /* FIXME: Should we issue a warning message ? */
3037 else
3039 /* Deleting a user defined alias. We need to free the
3040 key and the value, but fortunately the key is the same
3041 as the value->name field. */
3042 free ((char *) req_entry->name);
3043 free (req_entry);
3046 else
3047 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
3049 else
3050 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
3052 else
3053 as_bad (_("invalid syntax for .unreq directive"));
3055 *input_line_pointer = saved_char;
3056 demand_empty_rest_of_line ();
3059 static void
3060 s_bss (ignore)
3061 int ignore ATTRIBUTE_UNUSED;
3063 /* We don't support putting frags in the BSS segment, we fake it by
3064 marking in_bss, then looking at s_skip for clues. */
3065 subseg_set (bss_section, 0);
3066 demand_empty_rest_of_line ();
3067 mapping_state (MAP_DATA);
3070 static void
3071 s_even (ignore)
3072 int ignore ATTRIBUTE_UNUSED;
3074 /* Never make frag if expect extra pass. */
3075 if (!need_pass_2)
3076 frag_align (1, 0, 0);
3078 record_alignment (now_seg, 1);
3080 demand_empty_rest_of_line ();
3083 static void
3084 s_ltorg (ignored)
3085 int ignored ATTRIBUTE_UNUSED;
3087 unsigned int entry;
3088 literal_pool * pool;
3089 char sym_name[20];
3091 pool = find_literal_pool ();
3092 if (pool == NULL
3093 || pool->symbol == NULL
3094 || pool->next_free_entry == 0)
3095 return;
3097 /* Align pool as you have word accesses.
3098 Only make a frag if we have to. */
3099 if (!need_pass_2)
3100 frag_align (2, 0, 0);
3102 record_alignment (now_seg, 2);
3104 sprintf (sym_name, "$$lit_\002%x", pool->id);
3106 symbol_locate (pool->symbol, sym_name, now_seg,
3107 (valueT) frag_now_fix (), frag_now);
3108 symbol_table_insert (pool->symbol);
3110 ARM_SET_THUMB (pool->symbol, thumb_mode);
3112 #if defined OBJ_COFF || defined OBJ_ELF
3113 ARM_SET_INTERWORK (pool->symbol, support_interwork);
3114 #endif
3116 for (entry = 0; entry < pool->next_free_entry; entry ++)
3117 /* First output the expression in the instruction to the pool. */
3118 emit_expr (&(pool->literals[entry]), 4); /* .word */
3120 /* Mark the pool as empty. */
3121 pool->next_free_entry = 0;
3122 pool->symbol = NULL;
3125 /* Same as s_align_ptwo but align 0 => align 2. */
3127 static void
3128 s_align (unused)
3129 int unused ATTRIBUTE_UNUSED;
3131 register int temp;
3132 register long temp_fill;
3133 long max_alignment = 15;
3135 temp = get_absolute_expression ();
3136 if (temp > max_alignment)
3137 as_bad (_("alignment too large: %d assumed"), temp = max_alignment);
3138 else if (temp < 0)
3140 as_bad (_("alignment negative. 0 assumed."));
3141 temp = 0;
3144 if (*input_line_pointer == ',')
3146 input_line_pointer++;
3147 temp_fill = get_absolute_expression ();
3149 else
3150 temp_fill = 0;
3152 if (!temp)
3153 temp = 2;
3155 /* Only make a frag if we HAVE to. */
3156 if (temp && !need_pass_2)
3157 frag_align (temp, (int) temp_fill, 0);
3158 demand_empty_rest_of_line ();
3160 record_alignment (now_seg, temp);
3163 static void
3164 s_force_thumb (ignore)
3165 int ignore ATTRIBUTE_UNUSED;
3167 /* If we are not already in thumb mode go into it, EVEN if
3168 the target processor does not support thumb instructions.
3169 This is used by gcc/config/arm/lib1funcs.asm for example
3170 to compile interworking support functions even if the
3171 target processor should not support interworking. */
3172 if (! thumb_mode)
3174 thumb_mode = 2;
3176 record_alignment (now_seg, 1);
3179 demand_empty_rest_of_line ();
3182 static void
3183 s_thumb_func (ignore)
3184 int ignore ATTRIBUTE_UNUSED;
3186 if (! thumb_mode)
3187 opcode_select (16);
3189 /* The following label is the name/address of the start of a Thumb function.
3190 We need to know this for the interworking support. */
3191 label_is_thumb_function_name = TRUE;
3193 demand_empty_rest_of_line ();
3196 /* Perform a .set directive, but also mark the alias as
3197 being a thumb function. */
3199 static void
3200 s_thumb_set (equiv)
3201 int equiv;
3203 /* XXX the following is a duplicate of the code for s_set() in read.c
3204 We cannot just call that code as we need to get at the symbol that
3205 is created. */
3206 register char * name;
3207 register char delim;
3208 register char * end_name;
3209 register symbolS * symbolP;
3211 /* Especial apologies for the random logic:
3212 This just grew, and could be parsed much more simply!
3213 Dean - in haste. */
3214 name = input_line_pointer;
3215 delim = get_symbol_end ();
3216 end_name = input_line_pointer;
3217 *end_name = delim;
3219 SKIP_WHITESPACE ();
3221 if (*input_line_pointer != ',')
3223 *end_name = 0;
3224 as_bad (_("expected comma after name \"%s\""), name);
3225 *end_name = delim;
3226 ignore_rest_of_line ();
3227 return;
3230 input_line_pointer++;
3231 *end_name = 0;
3233 if (name[0] == '.' && name[1] == '\0')
3235 /* XXX - this should not happen to .thumb_set. */
3236 abort ();
3239 if ((symbolP = symbol_find (name)) == NULL
3240 && (symbolP = md_undefined_symbol (name)) == NULL)
3242 #ifndef NO_LISTING
3243 /* When doing symbol listings, play games with dummy fragments living
3244 outside the normal fragment chain to record the file and line info
3245 for this symbol. */
3246 if (listing & LISTING_SYMBOLS)
3248 extern struct list_info_struct * listing_tail;
3249 fragS * dummy_frag = (fragS *) xmalloc (sizeof (fragS));
3251 memset (dummy_frag, 0, sizeof (fragS));
3252 dummy_frag->fr_type = rs_fill;
3253 dummy_frag->line = listing_tail;
3254 symbolP = symbol_new (name, undefined_section, 0, dummy_frag);
3255 dummy_frag->fr_symbol = symbolP;
3257 else
3258 #endif
3259 symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
3261 #ifdef OBJ_COFF
3262 /* "set" symbols are local unless otherwise specified. */
3263 SF_SET_LOCAL (symbolP);
3264 #endif /* OBJ_COFF */
3265 } /* Make a new symbol. */
3267 symbol_table_insert (symbolP);
3269 * end_name = delim;
3271 if (equiv
3272 && S_IS_DEFINED (symbolP)
3273 && S_GET_SEGMENT (symbolP) != reg_section)
3274 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP));
3276 pseudo_set (symbolP);
3278 demand_empty_rest_of_line ();
3280 /* XXX Now we come to the Thumb specific bit of code. */
3282 THUMB_SET_FUNC (symbolP, 1);
3283 ARM_SET_THUMB (symbolP, 1);
3284 #if defined OBJ_ELF || defined OBJ_COFF
3285 ARM_SET_INTERWORK (symbolP, support_interwork);
3286 #endif
3289 static void
3290 opcode_select (width)
3291 int width;
3293 switch (width)
3295 case 16:
3296 if (! thumb_mode)
3298 if (! (cpu_variant & ARM_EXT_V4T))
3299 as_bad (_("selected processor does not support THUMB opcodes"));
3301 thumb_mode = 1;
3302 /* No need to force the alignment, since we will have been
3303 coming from ARM mode, which is word-aligned. */
3304 record_alignment (now_seg, 1);
3306 mapping_state (MAP_THUMB);
3307 break;
3309 case 32:
3310 if (thumb_mode)
3312 if ((cpu_variant & ARM_ALL) == ARM_EXT_V4T)
3313 as_bad (_("selected processor does not support ARM opcodes"));
3315 thumb_mode = 0;
3317 if (!need_pass_2)
3318 frag_align (2, 0, 0);
3320 record_alignment (now_seg, 1);
3322 mapping_state (MAP_ARM);
3323 break;
3325 default:
3326 as_bad (_("invalid instruction size selected (%d)"), width);
3330 static void
3331 s_arm (ignore)
3332 int ignore ATTRIBUTE_UNUSED;
3334 opcode_select (32);
3335 demand_empty_rest_of_line ();
3338 static void
3339 s_thumb (ignore)
3340 int ignore ATTRIBUTE_UNUSED;
3342 opcode_select (16);
3343 demand_empty_rest_of_line ();
3346 static void
3347 s_code (unused)
3348 int unused ATTRIBUTE_UNUSED;
3350 register int temp;
3352 temp = get_absolute_expression ();
3353 switch (temp)
3355 case 16:
3356 case 32:
3357 opcode_select (temp);
3358 break;
3360 default:
3361 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp);
3365 static void
3366 end_of_line (str)
3367 char *str;
3369 skip_whitespace (str);
3371 if (*str != '\0' && !inst.error)
3372 inst.error = _("garbage following instruction");
3375 static int
3376 skip_past_comma (str)
3377 char ** str;
3379 char * p = * str, c;
3380 int comma = 0;
3382 while ((c = *p) == ' ' || c == ',')
3384 p++;
3385 if (c == ',' && comma++)
3386 return FAIL;
3389 if (c == '\0')
3390 return FAIL;
3392 *str = p;
3393 return comma ? SUCCESS : FAIL;
3396 /* A standard register must be given at this point.
3397 SHIFT is the place to put it in inst.instruction.
3398 Restores input start point on error.
3399 Returns the reg#, or FAIL. */
3401 static int
3402 reg_required_here (str, shift)
3403 char ** str;
3404 int shift;
3406 static char buff [128]; /* XXX */
3407 int reg;
3408 char * start = * str;
3410 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_RN].htab)) != FAIL)
3412 if (shift >= 0)
3413 inst.instruction |= reg << shift;
3414 return reg;
3417 /* Restore the start point, we may have got a reg of the wrong class. */
3418 *str = start;
3420 /* In the few cases where we might be able to accept something else
3421 this error can be overridden. */
3422 sprintf (buff, _("register expected, not '%.100s'"), start);
3423 inst.error = buff;
3425 return FAIL;
3428 /* A Intel Wireless MMX technology register
3429 must be given at this point.
3430 Shift is the place to put it in inst.instruction.
3431 Restores input start point on err.
3432 Returns the reg#, or FAIL. */
3434 static int
3435 wreg_required_here (str, shift, reg_type)
3436 char ** str;
3437 int shift;
3438 enum wreg_type reg_type;
3440 static char buff [128];
3441 int reg;
3442 char * start = *str;
3444 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_IWMMXT].htab)) != FAIL)
3446 if (wr_register (reg)
3447 && (reg_type == IWMMXT_REG_WR || reg_type == IWMMXT_REG_WR_OR_WC))
3449 if (shift >= 0)
3450 inst.instruction |= (reg ^ WR_PREFIX) << shift;
3451 return reg;
3453 else if (wc_register (reg)
3454 && (reg_type == IWMMXT_REG_WC || reg_type == IWMMXT_REG_WR_OR_WC))
3456 if (shift >= 0)
3457 inst.instruction |= (reg ^ WC_PREFIX) << shift;
3458 return reg;
3460 else if ((wcg_register (reg) && reg_type == IWMMXT_REG_WCG))
3462 if (shift >= 0)
3463 inst.instruction |= ((reg ^ WC_PREFIX) - 8) << shift;
3464 return reg;
3468 /* Restore the start point, we may have got a reg of the wrong class. */
3469 *str = start;
3471 /* In the few cases where we might be able to accept
3472 something else this error can be overridden. */
3473 sprintf (buff, _("Intel Wireless MMX technology register expected, not '%.100s'"), start);
3474 inst.error = buff;
3476 return FAIL;
3479 static const struct asm_psr *
3480 arm_psr_parse (ccp)
3481 register char ** ccp;
3483 char * start = * ccp;
3484 char c;
3485 char * p;
3486 const struct asm_psr * psr;
3488 p = start;
3490 /* Skip to the end of the next word in the input stream. */
3493 c = *p++;
3495 while (ISALPHA (c) || c == '_');
3497 /* Terminate the word. */
3498 *--p = 0;
3500 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
3501 feature for ease of use and backwards compatibility. */
3502 if (!strncmp (start, "cpsr", 4))
3503 strncpy (start, "CPSR", 4);
3504 else if (!strncmp (start, "spsr", 4))
3505 strncpy (start, "SPSR", 4);
3507 /* Now locate the word in the psr hash table. */
3508 psr = (const struct asm_psr *) hash_find (arm_psr_hsh, start);
3510 /* Restore the input stream. */
3511 *p = c;
3513 /* If we found a valid match, advance the
3514 stream pointer past the end of the word. */
3515 *ccp = p;
3517 return psr;
3520 /* Parse the input looking for a PSR flag. */
3522 static int
3523 psr_required_here (str)
3524 char ** str;
3526 char * start = * str;
3527 const struct asm_psr * psr;
3529 psr = arm_psr_parse (str);
3531 if (psr)
3533 /* If this is the SPSR that is being modified, set the R bit. */
3534 if (! psr->cpsr)
3535 inst.instruction |= SPSR_BIT;
3537 /* Set the psr flags in the MSR instruction. */
3538 inst.instruction |= psr->field << PSR_SHIFT;
3540 return SUCCESS;
3543 /* In the few cases where we might be able to accept
3544 something else this error can be overridden. */
3545 inst.error = _("flag for {c}psr instruction expected");
3547 /* Restore the start point. */
3548 *str = start;
3549 return FAIL;
3552 static int
3553 co_proc_number (str)
3554 char **str;
3556 int processor, pchar;
3557 char *start;
3559 skip_whitespace (*str);
3560 start = *str;
3562 /* The data sheet seems to imply that just a number on its own is valid
3563 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
3564 accept either. */
3565 if ((processor = arm_reg_parse (str, all_reg_maps[REG_TYPE_CP].htab))
3566 == FAIL)
3568 *str = start;
3570 pchar = *(*str)++;
3571 if (pchar >= '0' && pchar <= '9')
3573 processor = pchar - '0';
3574 if (**str >= '0' && **str <= '9')
3576 processor = processor * 10 + *(*str)++ - '0';
3577 if (processor > 15)
3579 inst.error = _("illegal co-processor number");
3580 return FAIL;
3584 else
3586 inst.error = _("bad or missing co-processor number");
3587 return FAIL;
3591 inst.instruction |= processor << 8;
3592 return SUCCESS;
3595 static int
3596 cp_opc_expr (str, where, length)
3597 char ** str;
3598 int where;
3599 int length;
3601 expressionS expr;
3603 skip_whitespace (* str);
3605 memset (&expr, '\0', sizeof (expr));
3607 if (my_get_expression (&expr, str))
3608 return FAIL;
3609 if (expr.X_op != O_constant)
3611 inst.error = _("bad or missing expression");
3612 return FAIL;
3615 if ((expr.X_add_number & ((1 << length) - 1)) != expr.X_add_number)
3617 inst.error = _("immediate co-processor expression too large");
3618 return FAIL;
3621 inst.instruction |= expr.X_add_number << where;
3622 return SUCCESS;
3625 static int
3626 cp_reg_required_here (str, where)
3627 char ** str;
3628 int where;
3630 int reg;
3631 char * start = *str;
3633 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
3635 inst.instruction |= reg << where;
3636 return reg;
3639 /* In the few cases where we might be able to accept something else
3640 this error can be overridden. */
3641 inst.error = _("co-processor register expected");
3643 /* Restore the start point. */
3644 *str = start;
3645 return FAIL;
3648 static int
3649 fp_reg_required_here (str, where)
3650 char ** str;
3651 int where;
3653 int reg;
3654 char * start = * str;
3656 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_FN].htab)) != FAIL)
3658 inst.instruction |= reg << where;
3659 return reg;
3662 /* In the few cases where we might be able to accept something else
3663 this error can be overridden. */
3664 inst.error = _("floating point register expected");
3666 /* Restore the start point. */
3667 *str = start;
3668 return FAIL;
3671 static int
3672 cp_address_offset (str)
3673 char ** str;
3675 int offset;
3677 skip_whitespace (* str);
3679 if (! is_immediate_prefix (**str))
3681 inst.error = _("immediate expression expected");
3682 return FAIL;
3685 (*str)++;
3687 if (my_get_expression (& inst.reloc.exp, str))
3688 return FAIL;
3690 if (inst.reloc.exp.X_op == O_constant)
3692 offset = inst.reloc.exp.X_add_number;
3694 if (offset & 3)
3696 inst.error = _("co-processor address must be word aligned");
3697 return FAIL;
3700 if (offset > 1023 || offset < -1023)
3702 inst.error = _("offset too large");
3703 return FAIL;
3706 if (offset >= 0)
3707 inst.instruction |= INDEX_UP;
3708 else
3709 offset = -offset;
3711 inst.instruction |= offset >> 2;
3713 else
3714 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
3716 return SUCCESS;
3719 static int
3720 cp_address_required_here (str, wb_ok)
3721 char ** str;
3722 int wb_ok;
3724 char * p = * str;
3725 int pre_inc = 0;
3726 int write_back = 0;
3728 if (*p == '[')
3730 int reg;
3732 p++;
3733 skip_whitespace (p);
3735 if ((reg = reg_required_here (& p, 16)) == FAIL)
3736 return FAIL;
3738 skip_whitespace (p);
3740 if (*p == ']')
3742 p++;
3744 skip_whitespace (p);
3746 if (*p == '\0')
3748 /* As an extension to the official ARM syntax we allow:
3750 [Rn]
3752 as a short hand for:
3754 [Rn,#0] */
3755 inst.instruction |= PRE_INDEX | INDEX_UP;
3756 *str = p;
3757 return SUCCESS;
3760 if (skip_past_comma (& p) == FAIL)
3762 inst.error = _("comma expected after closing square bracket");
3763 return FAIL;
3766 skip_whitespace (p);
3768 if (*p == '#')
3770 if (wb_ok)
3772 /* [Rn], #expr */
3773 write_back = WRITE_BACK;
3775 if (reg == REG_PC)
3777 inst.error = _("pc may not be used in post-increment");
3778 return FAIL;
3781 if (cp_address_offset (& p) == FAIL)
3782 return FAIL;
3784 else
3785 pre_inc = PRE_INDEX | INDEX_UP;
3787 else if (*p == '{')
3789 int option;
3791 /* [Rn], {<expr>} */
3792 p++;
3794 skip_whitespace (p);
3796 if (my_get_expression (& inst.reloc.exp, & p))
3797 return FAIL;
3799 if (inst.reloc.exp.X_op == O_constant)
3801 option = inst.reloc.exp.X_add_number;
3803 if (option > 255 || option < 0)
3805 inst.error = _("'option' field too large");
3806 return FAIL;
3809 skip_whitespace (p);
3811 if (*p != '}')
3813 inst.error = _("'}' expected at end of 'option' field");
3814 return FAIL;
3816 else
3818 p++;
3819 inst.instruction |= option;
3820 inst.instruction |= INDEX_UP;
3823 else
3825 inst.error = _("non-constant expressions for 'option' field not supported");
3826 return FAIL;
3829 else
3831 inst.error = _("# or { expected after comma");
3832 return FAIL;
3835 else
3837 /* '['Rn, #expr']'[!] */
3839 if (skip_past_comma (& p) == FAIL)
3841 inst.error = _("pre-indexed expression expected");
3842 return FAIL;
3845 pre_inc = PRE_INDEX;
3847 if (cp_address_offset (& p) == FAIL)
3848 return FAIL;
3850 skip_whitespace (p);
3852 if (*p++ != ']')
3854 inst.error = _("missing ]");
3855 return FAIL;
3858 skip_whitespace (p);
3860 if (wb_ok && *p == '!')
3862 if (reg == REG_PC)
3864 inst.error = _("pc may not be used with write-back");
3865 return FAIL;
3868 p++;
3869 write_back = WRITE_BACK;
3873 else
3875 if (my_get_expression (&inst.reloc.exp, &p))
3876 return FAIL;
3878 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
3879 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
3880 inst.reloc.pc_rel = 1;
3881 inst.instruction |= (REG_PC << 16);
3882 pre_inc = PRE_INDEX;
3885 inst.instruction |= write_back | pre_inc;
3886 *str = p;
3887 return SUCCESS;
3890 static int
3891 cp_byte_address_offset (str)
3892 char ** str;
3894 int offset;
3896 skip_whitespace (* str);
3898 if (! is_immediate_prefix (**str))
3900 inst.error = _("immediate expression expected");
3901 return FAIL;
3904 (*str)++;
3906 if (my_get_expression (& inst.reloc.exp, str))
3907 return FAIL;
3909 if (inst.reloc.exp.X_op == O_constant)
3911 offset = inst.reloc.exp.X_add_number;
3913 if (offset > 255 || offset < -255)
3915 inst.error = _("offset too large");
3916 return FAIL;
3919 if (offset >= 0)
3920 inst.instruction |= INDEX_UP;
3921 else
3922 offset = -offset;
3924 inst.instruction |= offset;
3926 else
3927 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
3929 return SUCCESS;
3932 static int
3933 cp_byte_address_required_here (str)
3934 char ** str;
3936 char * p = * str;
3937 int pre_inc = 0;
3938 int write_back = 0;
3940 if (*p == '[')
3942 int reg;
3944 p++;
3945 skip_whitespace (p);
3947 if ((reg = reg_required_here (& p, 16)) == FAIL)
3948 return FAIL;
3950 skip_whitespace (p);
3952 if (*p == ']')
3954 p++;
3956 if (skip_past_comma (& p) == SUCCESS)
3958 /* [Rn], #expr */
3959 write_back = WRITE_BACK;
3961 if (reg == REG_PC)
3963 inst.error = _("pc may not be used in post-increment");
3964 return FAIL;
3967 if (cp_byte_address_offset (& p) == FAIL)
3968 return FAIL;
3970 else
3971 pre_inc = PRE_INDEX | INDEX_UP;
3973 else
3975 /* '['Rn, #expr']'[!] */
3977 if (skip_past_comma (& p) == FAIL)
3979 inst.error = _("pre-indexed expression expected");
3980 return FAIL;
3983 pre_inc = PRE_INDEX;
3985 if (cp_byte_address_offset (& p) == FAIL)
3986 return FAIL;
3988 skip_whitespace (p);
3990 if (*p++ != ']')
3992 inst.error = _("missing ]");
3993 return FAIL;
3996 skip_whitespace (p);
3998 if (*p == '!')
4000 if (reg == REG_PC)
4002 inst.error = _("pc may not be used with write-back");
4003 return FAIL;
4006 p++;
4007 write_back = WRITE_BACK;
4011 else
4013 if (my_get_expression (&inst.reloc.exp, &p))
4014 return FAIL;
4016 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
4017 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
4018 inst.reloc.pc_rel = 1;
4019 inst.instruction |= (REG_PC << 16);
4020 pre_inc = PRE_INDEX;
4023 inst.instruction |= write_back | pre_inc;
4024 *str = p;
4025 return SUCCESS;
4028 static void
4029 do_empty (str)
4030 char * str;
4032 /* Do nothing really. */
4033 end_of_line (str);
4034 return;
4037 static void
4038 do_mrs (str)
4039 char *str;
4041 int skip = 0;
4043 /* Only one syntax. */
4044 skip_whitespace (str);
4046 if (reg_required_here (&str, 12) == FAIL)
4048 inst.error = BAD_ARGS;
4049 return;
4052 if (skip_past_comma (&str) == FAIL)
4054 inst.error = _("comma expected after register name");
4055 return;
4058 skip_whitespace (str);
4060 if ( strcmp (str, "CPSR") == 0
4061 || strcmp (str, "SPSR") == 0
4062 /* Lower case versions for backwards compatibility. */
4063 || strcmp (str, "cpsr") == 0
4064 || strcmp (str, "spsr") == 0)
4065 skip = 4;
4067 /* This is for backwards compatibility with older toolchains. */
4068 else if ( strcmp (str, "cpsr_all") == 0
4069 || strcmp (str, "spsr_all") == 0)
4070 skip = 8;
4071 else
4073 inst.error = _("CPSR or SPSR expected");
4074 return;
4077 if (* str == 's' || * str == 'S')
4078 inst.instruction |= SPSR_BIT;
4079 str += skip;
4081 end_of_line (str);
4084 /* Two possible forms:
4085 "{C|S}PSR_<field>, Rm",
4086 "{C|S}PSR_f, #expression". */
4088 static void
4089 do_msr (str)
4090 char * str;
4092 skip_whitespace (str);
4094 if (psr_required_here (& str) == FAIL)
4095 return;
4097 if (skip_past_comma (& str) == FAIL)
4099 inst.error = _("comma missing after psr flags");
4100 return;
4103 skip_whitespace (str);
4105 if (reg_required_here (& str, 0) != FAIL)
4107 inst.error = NULL;
4108 end_of_line (str);
4109 return;
4112 if (! is_immediate_prefix (* str))
4114 inst.error =
4115 _("only a register or immediate value can follow a psr flag");
4116 return;
4119 str ++;
4120 inst.error = NULL;
4122 if (my_get_expression (& inst.reloc.exp, & str))
4124 inst.error =
4125 _("only a register or immediate value can follow a psr flag");
4126 return;
4129 #if 0 /* The first edition of the ARM architecture manual stated that
4130 writing anything other than the flags with an immediate operation
4131 had UNPREDICTABLE effects. This constraint was removed in the
4132 second edition of the specification. */
4133 if ((cpu_variant & ARM_EXT_V5) != ARM_EXT_V5
4134 && inst.instruction & ((PSR_c | PSR_x | PSR_s) << PSR_SHIFT))
4136 inst.error = _("immediate value cannot be used to set this field");
4137 return;
4139 #endif
4141 inst.instruction |= INST_IMMEDIATE;
4143 if (inst.reloc.exp.X_add_symbol)
4145 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
4146 inst.reloc.pc_rel = 0;
4148 else
4150 unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
4152 if (value == (unsigned) FAIL)
4154 inst.error = _("invalid constant");
4155 return;
4158 inst.instruction |= value;
4161 inst.error = NULL;
4162 end_of_line (str);
4165 /* Long Multiply Parser
4166 UMULL RdLo, RdHi, Rm, Rs
4167 SMULL RdLo, RdHi, Rm, Rs
4168 UMLAL RdLo, RdHi, Rm, Rs
4169 SMLAL RdLo, RdHi, Rm, Rs. */
4171 static void
4172 do_mull (str)
4173 char * str;
4175 int rdlo, rdhi, rm, rs;
4177 /* Only one format "rdlo, rdhi, rm, rs". */
4178 skip_whitespace (str);
4180 if ((rdlo = reg_required_here (&str, 12)) == FAIL)
4182 inst.error = BAD_ARGS;
4183 return;
4186 if (skip_past_comma (&str) == FAIL
4187 || (rdhi = reg_required_here (&str, 16)) == FAIL)
4189 inst.error = BAD_ARGS;
4190 return;
4193 if (skip_past_comma (&str) == FAIL
4194 || (rm = reg_required_here (&str, 0)) == FAIL)
4196 inst.error = BAD_ARGS;
4197 return;
4200 /* rdhi, rdlo and rm must all be different. */
4201 if (rdlo == rdhi || rdlo == rm || rdhi == rm)
4202 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
4204 if (skip_past_comma (&str) == FAIL
4205 || (rs = reg_required_here (&str, 8)) == FAIL)
4207 inst.error = BAD_ARGS;
4208 return;
4211 if (rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC)
4213 inst.error = BAD_PC;
4214 return;
4217 end_of_line (str);
4218 return;
4221 static void
4222 do_mul (str)
4223 char * str;
4225 int rd, rm;
4227 /* Only one format "rd, rm, rs". */
4228 skip_whitespace (str);
4230 if ((rd = reg_required_here (&str, 16)) == FAIL)
4232 inst.error = BAD_ARGS;
4233 return;
4236 if (rd == REG_PC)
4238 inst.error = BAD_PC;
4239 return;
4242 if (skip_past_comma (&str) == FAIL
4243 || (rm = reg_required_here (&str, 0)) == FAIL)
4245 inst.error = BAD_ARGS;
4246 return;
4249 if (rm == REG_PC)
4251 inst.error = BAD_PC;
4252 return;
4255 if (rm == rd)
4256 as_tsktsk (_("rd and rm should be different in mul"));
4258 if (skip_past_comma (&str) == FAIL
4259 || (rm = reg_required_here (&str, 8)) == FAIL)
4261 inst.error = BAD_ARGS;
4262 return;
4265 if (rm == REG_PC)
4267 inst.error = BAD_PC;
4268 return;
4271 end_of_line (str);
4272 return;
4275 static void
4276 do_mla (str)
4277 char * str;
4279 int rd, rm;
4281 /* Only one format "rd, rm, rs, rn". */
4282 skip_whitespace (str);
4284 if ((rd = reg_required_here (&str, 16)) == FAIL)
4286 inst.error = BAD_ARGS;
4287 return;
4290 if (rd == REG_PC)
4292 inst.error = BAD_PC;
4293 return;
4296 if (skip_past_comma (&str) == FAIL
4297 || (rm = reg_required_here (&str, 0)) == FAIL)
4299 inst.error = BAD_ARGS;
4300 return;
4303 if (rm == REG_PC)
4305 inst.error = BAD_PC;
4306 return;
4309 if (rm == rd)
4310 as_tsktsk (_("rd and rm should be different in mla"));
4312 if (skip_past_comma (&str) == FAIL
4313 || (rd = reg_required_here (&str, 8)) == FAIL
4314 || skip_past_comma (&str) == FAIL
4315 || (rm = reg_required_here (&str, 12)) == FAIL)
4317 inst.error = BAD_ARGS;
4318 return;
4321 if (rd == REG_PC || rm == REG_PC)
4323 inst.error = BAD_PC;
4324 return;
4327 end_of_line (str);
4328 return;
4331 /* Expects *str -> the characters "acc0", possibly with leading blanks.
4332 Advances *str to the next non-alphanumeric.
4333 Returns 0, or else FAIL (in which case sets inst.error).
4335 (In a future XScale, there may be accumulators other than zero.
4336 At that time this routine and its callers can be upgraded to suit.) */
4338 static int
4339 accum0_required_here (str)
4340 char ** str;
4342 static char buff [128]; /* Note the address is taken. Hence, static. */
4343 char * p = * str;
4344 char c;
4345 int result = 0; /* The accum number. */
4347 skip_whitespace (p);
4349 *str = p; /* Advance caller's string pointer too. */
4350 c = *p++;
4351 while (ISALNUM (c))
4352 c = *p++;
4354 *--p = 0; /* Aap nul into input buffer at non-alnum. */
4356 if (! ( streq (*str, "acc0") || streq (*str, "ACC0")))
4358 sprintf (buff, _("acc0 expected, not '%.100s'"), *str);
4359 inst.error = buff;
4360 result = FAIL;
4363 *p = c; /* Unzap. */
4364 *str = p; /* Caller's string pointer to after match. */
4365 return result;
4368 /* Expects **str -> after a comma. May be leading blanks.
4369 Advances *str, recognizing a load mode, and setting inst.instruction.
4370 Returns rn, or else FAIL (in which case may set inst.error
4371 and not advance str)
4373 Note: doesn't know Rd, so no err checks that require such knowledge. */
4375 static int
4376 ld_mode_required_here (string)
4377 char ** string;
4379 char * str = * string;
4380 int rn;
4381 int pre_inc = 0;
4383 skip_whitespace (str);
4385 if (* str == '[')
4387 str++;
4389 skip_whitespace (str);
4391 if ((rn = reg_required_here (& str, 16)) == FAIL)
4392 return FAIL;
4394 skip_whitespace (str);
4396 if (* str == ']')
4398 str ++;
4400 if (skip_past_comma (& str) == SUCCESS)
4402 /* [Rn],... (post inc) */
4403 if (ldst_extend_v4 (&str) == FAIL)
4404 return FAIL;
4406 else /* [Rn] */
4408 skip_whitespace (str);
4410 if (* str == '!')
4412 str ++;
4413 inst.instruction |= WRITE_BACK;
4416 inst.instruction |= INDEX_UP | HWOFFSET_IMM;
4417 pre_inc = 1;
4420 else /* [Rn,...] */
4422 if (skip_past_comma (& str) == FAIL)
4424 inst.error = _("pre-indexed expression expected");
4425 return FAIL;
4428 pre_inc = 1;
4430 if (ldst_extend_v4 (&str) == FAIL)
4431 return FAIL;
4433 skip_whitespace (str);
4435 if (* str ++ != ']')
4437 inst.error = _("missing ]");
4438 return FAIL;
4441 skip_whitespace (str);
4443 if (* str == '!')
4445 str ++;
4446 inst.instruction |= WRITE_BACK;
4450 else if (* str == '=') /* ldr's "r,=label" syntax */
4451 /* We should never reach here, because <text> = <expression> is
4452 caught gas/read.c read_a_source_file() as a .set operation. */
4453 return FAIL;
4454 else /* PC +- 8 bit immediate offset. */
4456 if (my_get_expression (& inst.reloc.exp, & str))
4457 return FAIL;
4459 inst.instruction |= HWOFFSET_IMM; /* The I bit. */
4460 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
4461 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
4462 inst.reloc.pc_rel = 1;
4463 inst.instruction |= (REG_PC << 16);
4465 rn = REG_PC;
4466 pre_inc = 1;
4469 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
4470 * string = str;
4472 return rn;
4475 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
4476 SMLAxy{cond} Rd,Rm,Rs,Rn
4477 SMLAWy{cond} Rd,Rm,Rs,Rn
4478 Error if any register is R15. */
4480 static void
4481 do_smla (str)
4482 char * str;
4484 int rd, rm, rs, rn;
4486 skip_whitespace (str);
4488 if ((rd = reg_required_here (& str, 16)) == FAIL
4489 || skip_past_comma (& str) == FAIL
4490 || (rm = reg_required_here (& str, 0)) == FAIL
4491 || skip_past_comma (& str) == FAIL
4492 || (rs = reg_required_here (& str, 8)) == FAIL
4493 || skip_past_comma (& str) == FAIL
4494 || (rn = reg_required_here (& str, 12)) == FAIL)
4495 inst.error = BAD_ARGS;
4497 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC || rn == REG_PC)
4498 inst.error = BAD_PC;
4500 else
4501 end_of_line (str);
4504 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
4505 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
4506 Error if any register is R15.
4507 Warning if Rdlo == Rdhi. */
4509 static void
4510 do_smlal (str)
4511 char * str;
4513 int rdlo, rdhi, rm, rs;
4515 skip_whitespace (str);
4517 if ((rdlo = reg_required_here (& str, 12)) == FAIL
4518 || skip_past_comma (& str) == FAIL
4519 || (rdhi = reg_required_here (& str, 16)) == FAIL
4520 || skip_past_comma (& str) == FAIL
4521 || (rm = reg_required_here (& str, 0)) == FAIL
4522 || skip_past_comma (& str) == FAIL
4523 || (rs = reg_required_here (& str, 8)) == FAIL)
4525 inst.error = BAD_ARGS;
4526 return;
4529 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
4531 inst.error = BAD_PC;
4532 return;
4535 if (rdlo == rdhi)
4536 as_tsktsk (_("rdhi and rdlo must be different"));
4538 end_of_line (str);
4541 /* ARM V5E (El Segundo) signed-multiply (argument parse)
4542 SMULxy{cond} Rd,Rm,Rs
4543 Error if any register is R15. */
4545 static void
4546 do_smul (str)
4547 char * str;
4549 int rd, rm, rs;
4551 skip_whitespace (str);
4553 if ((rd = reg_required_here (& str, 16)) == FAIL
4554 || skip_past_comma (& str) == FAIL
4555 || (rm = reg_required_here (& str, 0)) == FAIL
4556 || skip_past_comma (& str) == FAIL
4557 || (rs = reg_required_here (& str, 8)) == FAIL)
4558 inst.error = BAD_ARGS;
4560 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC)
4561 inst.error = BAD_PC;
4563 else
4564 end_of_line (str);
4567 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
4568 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
4569 Error if any register is R15. */
4571 static void
4572 do_qadd (str)
4573 char * str;
4575 int rd, rm, rn;
4577 skip_whitespace (str);
4579 if ((rd = reg_required_here (& str, 12)) == FAIL
4580 || skip_past_comma (& str) == FAIL
4581 || (rm = reg_required_here (& str, 0)) == FAIL
4582 || skip_past_comma (& str) == FAIL
4583 || (rn = reg_required_here (& str, 16)) == FAIL)
4584 inst.error = BAD_ARGS;
4586 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
4587 inst.error = BAD_PC;
4589 else
4590 end_of_line (str);
4593 /* ARM V5E (el Segundo)
4594 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4595 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4597 These are equivalent to the XScale instructions MAR and MRA,
4598 respectively, when coproc == 0, opcode == 0, and CRm == 0.
4600 Result unpredicatable if Rd or Rn is R15. */
4602 static void
4603 do_co_reg2c (str)
4604 char * str;
4606 int rd, rn;
4608 skip_whitespace (str);
4610 if (co_proc_number (& str) == FAIL)
4612 if (!inst.error)
4613 inst.error = BAD_ARGS;
4614 return;
4617 if (skip_past_comma (& str) == FAIL
4618 || cp_opc_expr (& str, 4, 4) == FAIL)
4620 if (!inst.error)
4621 inst.error = BAD_ARGS;
4622 return;
4625 if (skip_past_comma (& str) == FAIL
4626 || (rd = reg_required_here (& str, 12)) == FAIL)
4628 if (!inst.error)
4629 inst.error = BAD_ARGS;
4630 return;
4633 if (skip_past_comma (& str) == FAIL
4634 || (rn = reg_required_here (& str, 16)) == FAIL)
4636 if (!inst.error)
4637 inst.error = BAD_ARGS;
4638 return;
4641 /* Unpredictable result if rd or rn is R15. */
4642 if (rd == REG_PC || rn == REG_PC)
4643 as_tsktsk
4644 (_("Warning: instruction unpredictable when using r15"));
4646 if (skip_past_comma (& str) == FAIL
4647 || cp_reg_required_here (& str, 0) == FAIL)
4649 if (!inst.error)
4650 inst.error = BAD_ARGS;
4651 return;
4654 end_of_line (str);
4657 /* ARM V5 count-leading-zeroes instruction (argument parse)
4658 CLZ{<cond>} <Rd>, <Rm>
4659 Condition defaults to COND_ALWAYS.
4660 Error if Rd or Rm are R15. */
4662 static void
4663 do_clz (str)
4664 char * str;
4666 int rd, rm;
4668 skip_whitespace (str);
4670 if (((rd = reg_required_here (& str, 12)) == FAIL)
4671 || (skip_past_comma (& str) == FAIL)
4672 || ((rm = reg_required_here (& str, 0)) == FAIL))
4673 inst.error = BAD_ARGS;
4675 else if (rd == REG_PC || rm == REG_PC )
4676 inst.error = BAD_PC;
4678 else
4679 end_of_line (str);
4682 /* ARM V5 (argument parse)
4683 LDC2{L} <coproc>, <CRd>, <addressing mode>
4684 STC2{L} <coproc>, <CRd>, <addressing mode>
4685 Instruction is not conditional, and has 0xf in the condition field.
4686 Otherwise, it's the same as LDC/STC. */
4688 static void
4689 do_lstc2 (str)
4690 char * str;
4692 skip_whitespace (str);
4694 if (co_proc_number (& str) == FAIL)
4696 if (!inst.error)
4697 inst.error = BAD_ARGS;
4699 else if (skip_past_comma (& str) == FAIL
4700 || cp_reg_required_here (& str, 12) == FAIL)
4702 if (!inst.error)
4703 inst.error = BAD_ARGS;
4705 else if (skip_past_comma (& str) == FAIL
4706 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
4708 if (! inst.error)
4709 inst.error = BAD_ARGS;
4711 else
4712 end_of_line (str);
4715 /* ARM V5 (argument parse)
4716 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
4717 Instruction is not conditional, and has 0xf in the condition field.
4718 Otherwise, it's the same as CDP. */
4720 static void
4721 do_cdp2 (str)
4722 char * str;
4724 skip_whitespace (str);
4726 if (co_proc_number (& str) == FAIL)
4728 if (!inst.error)
4729 inst.error = BAD_ARGS;
4730 return;
4733 if (skip_past_comma (& str) == FAIL
4734 || cp_opc_expr (& str, 20,4) == FAIL)
4736 if (!inst.error)
4737 inst.error = BAD_ARGS;
4738 return;
4741 if (skip_past_comma (& str) == FAIL
4742 || cp_reg_required_here (& str, 12) == 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, 16) == 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, 0) == FAIL)
4760 if (!inst.error)
4761 inst.error = BAD_ARGS;
4762 return;
4765 if (skip_past_comma (& str) == SUCCESS)
4767 if (cp_opc_expr (& str, 5, 3) == FAIL)
4769 if (!inst.error)
4770 inst.error = BAD_ARGS;
4771 return;
4775 end_of_line (str);
4778 /* ARM V5 (argument parse)
4779 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4780 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4781 Instruction is not conditional, and has 0xf in the condition field.
4782 Otherwise, it's the same as MCR/MRC. */
4784 static void
4785 do_co_reg2 (str)
4786 char * str;
4788 skip_whitespace (str);
4790 if (co_proc_number (& str) == FAIL)
4792 if (!inst.error)
4793 inst.error = BAD_ARGS;
4794 return;
4797 if (skip_past_comma (& str) == FAIL
4798 || cp_opc_expr (& str, 21, 3) == FAIL)
4800 if (!inst.error)
4801 inst.error = BAD_ARGS;
4802 return;
4805 if (skip_past_comma (& str) == FAIL
4806 || reg_required_here (& str, 12) == FAIL)
4808 if (!inst.error)
4809 inst.error = BAD_ARGS;
4810 return;
4813 if (skip_past_comma (& str) == FAIL
4814 || cp_reg_required_here (& str, 16) == 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, 0) == FAIL)
4824 if (!inst.error)
4825 inst.error = BAD_ARGS;
4826 return;
4829 if (skip_past_comma (& str) == SUCCESS)
4831 if (cp_opc_expr (& str, 5, 3) == FAIL)
4833 if (!inst.error)
4834 inst.error = BAD_ARGS;
4835 return;
4839 end_of_line (str);
4842 /* ARM v5TEJ. Jump to Jazelle code. */
4843 static void
4844 do_bxj (str)
4845 char * str;
4847 int reg;
4849 skip_whitespace (str);
4851 if ((reg = reg_required_here (&str, 0)) == FAIL)
4853 inst.error = BAD_ARGS;
4854 return;
4857 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
4858 if (reg == REG_PC)
4859 as_tsktsk (_("use of r15 in bxj is not really useful"));
4861 end_of_line (str);
4864 /* ARM V6 umaal (argument parse). */
4866 static void
4867 do_umaal (str)
4868 char *str;
4871 int rdlo, rdhi, rm, rs;
4873 skip_whitespace (str);
4874 if ((rdlo = reg_required_here (& str, 12)) == FAIL
4875 || skip_past_comma (& str) == FAIL
4876 || (rdhi = reg_required_here (& str, 16)) == FAIL
4877 || skip_past_comma (& str) == FAIL
4878 || (rm = reg_required_here (& str, 0)) == FAIL
4879 || skip_past_comma (& str) == FAIL
4880 || (rs = reg_required_here (& str, 8)) == FAIL)
4882 inst.error = BAD_ARGS;
4883 return;
4886 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
4888 inst.error = BAD_PC;
4889 return;
4892 end_of_line (str);
4895 /* ARM V6 strex (argument parse). */
4897 static void
4898 do_strex (str)
4899 char *str;
4901 int rd, rm, rn;
4903 /* Parse Rd, Rm,. */
4904 skip_whitespace (str);
4905 if ((rd = reg_required_here (& str, 12)) == FAIL
4906 || skip_past_comma (& str) == FAIL
4907 || (rm = reg_required_here (& str, 0)) == FAIL
4908 || skip_past_comma (& str) == FAIL)
4910 inst.error = BAD_ARGS;
4911 return;
4913 if (rd == REG_PC || rm == REG_PC)
4915 inst.error = BAD_PC;
4916 return;
4918 if (rd == rm)
4920 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
4921 return;
4924 /* Skip past '['. */
4925 if ((strlen (str) >= 1)
4926 && strncmp (str, "[", 1) == 0)
4927 str+=1;
4928 skip_whitespace (str);
4930 /* Parse Rn. */
4931 if ((rn = reg_required_here (& str, 16)) == FAIL)
4933 inst.error = BAD_ARGS;
4934 return;
4936 else if (rn == REG_PC)
4938 inst.error = BAD_PC;
4939 return;
4941 if (rd == rn)
4943 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
4944 return;
4946 skip_whitespace (str);
4948 /* Skip past ']'. */
4949 if ((strlen (str) >= 1)
4950 && strncmp (str, "]", 1) == 0)
4951 str+=1;
4953 end_of_line (str);
4956 /* ARM V6 ssat (argument parse). */
4958 static void
4959 do_ssat (str)
4960 char* str;
4962 do_sat (&str, /*bias=*/-1);
4963 end_of_line (str);
4966 /* ARM V6 usat (argument parse). */
4968 static void
4969 do_usat (str)
4970 char* str;
4972 do_sat (&str, /*bias=*/0);
4973 end_of_line (str);
4976 static void
4977 do_sat (str, bias)
4978 char **str;
4979 int bias;
4981 int rd, rm;
4982 expressionS expr;
4984 skip_whitespace (*str);
4986 /* Parse <Rd>, field. */
4987 if ((rd = reg_required_here (str, 12)) == FAIL
4988 || skip_past_comma (str) == FAIL)
4990 inst.error = BAD_ARGS;
4991 return;
4993 if (rd == REG_PC)
4995 inst.error = BAD_PC;
4996 return;
4999 /* Parse #<immed>, field. */
5000 if (is_immediate_prefix (**str))
5001 (*str)++;
5002 else
5004 inst.error = _("immediate expression expected");
5005 return;
5007 if (my_get_expression (&expr, str))
5009 inst.error = _("bad expression");
5010 return;
5012 if (expr.X_op != O_constant)
5014 inst.error = _("constant expression expected");
5015 return;
5017 if (expr.X_add_number + bias < 0
5018 || expr.X_add_number + bias > 31)
5020 inst.error = _("immediate value out of range");
5021 return;
5023 inst.instruction |= (expr.X_add_number + bias) << 16;
5024 if (skip_past_comma (str) == FAIL)
5026 inst.error = BAD_ARGS;
5027 return;
5030 /* Parse <Rm> field. */
5031 if ((rm = reg_required_here (str, 0)) == FAIL)
5033 inst.error = BAD_ARGS;
5034 return;
5036 if (rm == REG_PC)
5038 inst.error = BAD_PC;
5039 return;
5042 if (skip_past_comma (str) == SUCCESS)
5043 decode_shift (str, SHIFT_LSL_OR_ASR_IMMEDIATE);
5046 /* ARM V6 ssat16 (argument parse). */
5048 static void
5049 do_ssat16 (str)
5050 char *str;
5052 do_sat16 (&str, /*bias=*/-1);
5053 end_of_line (str);
5056 static void
5057 do_usat16 (str)
5058 char *str;
5060 do_sat16 (&str, /*bias=*/0);
5061 end_of_line (str);
5064 static void
5065 do_sat16 (str, bias)
5066 char **str;
5067 int bias;
5069 int rd, rm;
5070 expressionS expr;
5072 skip_whitespace (*str);
5074 /* Parse the <Rd> field. */
5075 if ((rd = reg_required_here (str, 12)) == FAIL
5076 || skip_past_comma (str) == FAIL)
5078 inst.error = BAD_ARGS;
5079 return;
5081 if (rd == REG_PC)
5083 inst.error = BAD_PC;
5084 return;
5087 /* Parse #<immed>, field. */
5088 if (is_immediate_prefix (**str))
5089 (*str)++;
5090 else
5092 inst.error = _("immediate expression expected");
5093 return;
5095 if (my_get_expression (&expr, str))
5097 inst.error = _("bad expression");
5098 return;
5100 if (expr.X_op != O_constant)
5102 inst.error = _("constant expression expected");
5103 return;
5105 if (expr.X_add_number + bias < 0
5106 || expr.X_add_number + bias > 15)
5108 inst.error = _("immediate value out of range");
5109 return;
5111 inst.instruction |= (expr.X_add_number + bias) << 16;
5112 if (skip_past_comma (str) == FAIL)
5114 inst.error = BAD_ARGS;
5115 return;
5118 /* Parse <Rm> field. */
5119 if ((rm = reg_required_here (str, 0)) == FAIL)
5121 inst.error = BAD_ARGS;
5122 return;
5124 if (rm == REG_PC)
5126 inst.error = BAD_PC;
5127 return;
5131 /* ARM V6 srs (argument parse). */
5133 static void
5134 do_srs (str)
5135 char* str;
5137 char *exclam;
5138 skip_whitespace (str);
5139 exclam = strchr (str, '!');
5140 if (exclam)
5141 *exclam = '\0';
5142 do_cps_mode (&str);
5143 if (exclam)
5144 *exclam = '!';
5145 if (*str == '!')
5147 inst.instruction |= WRITE_BACK;
5148 str++;
5150 end_of_line (str);
5153 /* ARM V6 SMMUL (argument parse). */
5155 static void
5156 do_smmul (str)
5157 char* str;
5159 int rd, rm, rs;
5161 skip_whitespace (str);
5162 if ((rd = reg_required_here (&str, 16)) == FAIL
5163 || skip_past_comma (&str) == FAIL
5164 || (rm = reg_required_here (&str, 0)) == FAIL
5165 || skip_past_comma (&str) == FAIL
5166 || (rs = reg_required_here (&str, 8)) == FAIL)
5168 inst.error = BAD_ARGS;
5169 return;
5172 if (rd == REG_PC
5173 || rm == REG_PC
5174 || rs == REG_PC)
5176 inst.error = BAD_PC;
5177 return;
5180 end_of_line (str);
5184 /* ARM V6 SMLALD (argument parse). */
5186 static void
5187 do_smlald (str)
5188 char* str;
5190 int rdlo, rdhi, rm, rs;
5191 skip_whitespace (str);
5192 if ((rdlo = reg_required_here (&str, 12)) == FAIL
5193 || skip_past_comma (&str) == FAIL
5194 || (rdhi = reg_required_here (&str, 16)) == FAIL
5195 || skip_past_comma (&str) == FAIL
5196 || (rm = reg_required_here (&str, 0)) == FAIL
5197 || skip_past_comma (&str) == FAIL
5198 || (rs = reg_required_here (&str, 8)) == FAIL)
5200 inst.error = BAD_ARGS;
5201 return;
5204 if (rdlo == REG_PC
5205 || rdhi == REG_PC
5206 || rm == REG_PC
5207 || rs == REG_PC)
5209 inst.error = BAD_PC;
5210 return;
5213 end_of_line (str);
5216 /* ARM V6 SMLAD (argument parse). Signed multiply accumulate dual.
5217 smlad{x}{<cond>} Rd, Rm, Rs, Rn */
5219 static void
5220 do_smlad (str)
5221 char *str;
5223 int rd, rm, rs, rn;
5225 skip_whitespace (str);
5226 if ((rd = reg_required_here (&str, 16)) == FAIL
5227 || skip_past_comma (&str) == FAIL
5228 || (rm = reg_required_here (&str, 0)) == FAIL
5229 || skip_past_comma (&str) == FAIL
5230 || (rs = reg_required_here (&str, 8)) == FAIL
5231 || skip_past_comma (&str) == FAIL
5232 || (rn = reg_required_here (&str, 12)) == FAIL)
5234 inst.error = BAD_ARGS;
5235 return;
5238 if (rd == REG_PC
5239 || rn == REG_PC
5240 || rs == REG_PC
5241 || rm == REG_PC)
5243 inst.error = BAD_PC;
5244 return;
5247 end_of_line (str);
5250 /* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
5251 preserving the other bits.
5253 setend <endian_specifier>, where <endian_specifier> is either
5254 BE or LE. */
5256 static void
5257 do_setend (str)
5258 char *str;
5260 if (do_endian_specifier (str))
5261 inst.instruction |= 0x200;
5264 /* Returns true if the endian-specifier indicates big-endianness. */
5266 static int
5267 do_endian_specifier (str)
5268 char *str;
5270 int big_endian = 0;
5272 skip_whitespace (str);
5273 if (strlen (str) < 2)
5274 inst.error = _("missing endian specifier");
5275 else if (strncasecmp (str, "BE", 2) == 0)
5277 str += 2;
5278 big_endian = 1;
5280 else if (strncasecmp (str, "LE", 2) == 0)
5281 str += 2;
5282 else
5283 inst.error = _("valid endian specifiers are be or le");
5285 end_of_line (str);
5287 return big_endian;
5290 /* ARM V6 SXTH.
5292 SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
5293 Condition defaults to COND_ALWAYS.
5294 Error if any register uses R15. */
5296 static void
5297 do_sxth (str)
5298 char *str;
5300 int rd, rm;
5301 expressionS expr;
5302 int rotation_clear_mask = 0xfffff3ff;
5303 int rotation_eight_mask = 0x00000400;
5304 int rotation_sixteen_mask = 0x00000800;
5305 int rotation_twenty_four_mask = 0x00000c00;
5307 skip_whitespace (str);
5308 if ((rd = reg_required_here (&str, 12)) == FAIL
5309 || skip_past_comma (&str) == FAIL
5310 || (rm = reg_required_here (&str, 0)) == FAIL)
5312 inst.error = BAD_ARGS;
5313 return;
5316 else if (rd == REG_PC || rm == REG_PC)
5318 inst.error = BAD_PC;
5319 return;
5322 /* Zero out the rotation field. */
5323 inst.instruction &= rotation_clear_mask;
5325 /* Check for lack of optional rotation field. */
5326 if (skip_past_comma (&str) == FAIL)
5328 end_of_line (str);
5329 return;
5332 /* Move past 'ROR'. */
5333 skip_whitespace (str);
5334 if (strncasecmp (str, "ROR", 3) == 0)
5335 str+=3;
5336 else
5338 inst.error = _("missing rotation field after comma");
5339 return;
5342 /* Get the immediate constant. */
5343 skip_whitespace (str);
5344 if (is_immediate_prefix (* str))
5345 str++;
5346 else
5348 inst.error = _("immediate expression expected");
5349 return;
5352 if (my_get_expression (&expr, &str))
5354 inst.error = _("bad expression");
5355 return;
5358 if (expr.X_op != O_constant)
5360 inst.error = _("constant expression expected");
5361 return;
5364 switch (expr.X_add_number)
5366 case 0:
5367 /* Rotation field has already been zeroed. */
5368 break;
5369 case 8:
5370 inst.instruction |= rotation_eight_mask;
5371 break;
5373 case 16:
5374 inst.instruction |= rotation_sixteen_mask;
5375 break;
5377 case 24:
5378 inst.instruction |= rotation_twenty_four_mask;
5379 break;
5381 default:
5382 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
5383 break;
5386 end_of_line (str);
5390 /* ARM V6 SXTAH extracts a 16-bit value from a register, sign
5391 extends it to 32-bits, and adds the result to a value in another
5392 register. You can specify a rotation by 0, 8, 16, or 24 bits
5393 before extracting the 16-bit value.
5394 SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
5395 Condition defaults to COND_ALWAYS.
5396 Error if any register uses R15. */
5398 static void
5399 do_sxtah (str)
5400 char *str;
5402 int rd, rn, rm;
5403 expressionS expr;
5404 int rotation_clear_mask = 0xfffff3ff;
5405 int rotation_eight_mask = 0x00000400;
5406 int rotation_sixteen_mask = 0x00000800;
5407 int rotation_twenty_four_mask = 0x00000c00;
5409 skip_whitespace (str);
5410 if ((rd = reg_required_here (&str, 12)) == FAIL
5411 || skip_past_comma (&str) == FAIL
5412 || (rn = reg_required_here (&str, 16)) == FAIL
5413 || skip_past_comma (&str) == FAIL
5414 || (rm = reg_required_here (&str, 0)) == FAIL)
5416 inst.error = BAD_ARGS;
5417 return;
5420 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
5422 inst.error = BAD_PC;
5423 return;
5426 /* Zero out the rotation field. */
5427 inst.instruction &= rotation_clear_mask;
5429 /* Check for lack of optional rotation field. */
5430 if (skip_past_comma (&str) == FAIL)
5432 end_of_line (str);
5433 return;
5436 /* Move past 'ROR'. */
5437 skip_whitespace (str);
5438 if (strncasecmp (str, "ROR", 3) == 0)
5439 str+=3;
5440 else
5442 inst.error = _("missing rotation field after comma");
5443 return;
5446 /* Get the immediate constant. */
5447 skip_whitespace (str);
5448 if (is_immediate_prefix (* str))
5449 str++;
5450 else
5452 inst.error = _("immediate expression expected");
5453 return;
5456 if (my_get_expression (&expr, &str))
5458 inst.error = _("bad expression");
5459 return;
5462 if (expr.X_op != O_constant)
5464 inst.error = _("constant expression expected");
5465 return;
5468 switch (expr.X_add_number)
5470 case 0:
5471 /* Rotation field has already been zeroed. */
5472 break;
5474 case 8:
5475 inst.instruction |= rotation_eight_mask;
5476 break;
5478 case 16:
5479 inst.instruction |= rotation_sixteen_mask;
5480 break;
5482 case 24:
5483 inst.instruction |= rotation_twenty_four_mask;
5484 break;
5486 default:
5487 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
5488 break;
5491 end_of_line (str);
5496 /* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
5497 word at the specified address and the following word
5498 respectively.
5499 Unconditionally executed.
5500 Error if Rn is R15.
5503 static void
5504 do_rfe (str)
5505 char *str;
5507 int rn;
5509 skip_whitespace (str);
5511 if ((rn = reg_required_here (&str, 16)) == FAIL)
5512 return;
5514 if (rn == REG_PC)
5516 inst.error = BAD_PC;
5517 return;
5520 skip_whitespace (str);
5522 if (*str == '!')
5524 inst.instruction |= WRITE_BACK;
5525 str++;
5527 end_of_line (str);
5530 /* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
5531 register (argument parse).
5532 REV{<cond>} Rd, Rm.
5533 Condition defaults to COND_ALWAYS.
5534 Error if Rd or Rm are R15. */
5536 static void
5537 do_rev (str)
5538 char* str;
5540 int rd, rm;
5542 skip_whitespace (str);
5544 if ((rd = reg_required_here (&str, 12)) == FAIL
5545 || skip_past_comma (&str) == FAIL
5546 || (rm = reg_required_here (&str, 0)) == FAIL)
5547 inst.error = BAD_ARGS;
5549 else if (rd == REG_PC || rm == REG_PC)
5550 inst.error = BAD_PC;
5552 else
5553 end_of_line (str);
5556 /* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
5557 QADD16{<cond>} <Rd>, <Rn>, <Rm>
5558 Condition defaults to COND_ALWAYS.
5559 Error if Rd, Rn or Rm are R15. */
5561 static void
5562 do_qadd16 (str)
5563 char* str;
5565 int rd, rm, rn;
5567 skip_whitespace (str);
5569 if ((rd = reg_required_here (&str, 12)) == FAIL
5570 || skip_past_comma (&str) == FAIL
5571 || (rn = reg_required_here (&str, 16)) == FAIL
5572 || skip_past_comma (&str) == FAIL
5573 || (rm = reg_required_here (&str, 0)) == FAIL)
5574 inst.error = BAD_ARGS;
5576 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
5577 inst.error = BAD_PC;
5579 else
5580 end_of_line (str);
5583 /* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
5584 PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
5585 Condition defaults to COND_ALWAYS.
5586 Error if Rd, Rn or Rm are R15. */
5588 static void
5589 do_pkhbt (str)
5590 char* str;
5592 do_pkh_core (str, SHIFT_LSL_IMMEDIATE);
5595 /* ARM V6 PKHTB (Argument Parse). */
5597 static void
5598 do_pkhtb (str)
5599 char* str;
5601 do_pkh_core (str, SHIFT_ASR_IMMEDIATE);
5604 static void
5605 do_pkh_core (str, shift)
5606 char* str;
5607 int shift;
5609 int rd, rn, rm;
5611 skip_whitespace (str);
5612 if (((rd = reg_required_here (&str, 12)) == FAIL)
5613 || (skip_past_comma (&str) == FAIL)
5614 || ((rn = reg_required_here (&str, 16)) == FAIL)
5615 || (skip_past_comma (&str) == FAIL)
5616 || ((rm = reg_required_here (&str, 0)) == FAIL))
5618 inst.error = BAD_ARGS;
5619 return;
5622 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
5624 inst.error = BAD_PC;
5625 return;
5628 /* Check for optional shift immediate constant. */
5629 if (skip_past_comma (&str) == FAIL)
5631 if (shift == SHIFT_ASR_IMMEDIATE)
5633 /* If the shift specifier is ommited, turn the instruction
5634 into pkhbt rd, rm, rn. First, switch the instruction
5635 code, and clear the rn and rm fields. */
5636 inst.instruction &= 0xfff0f010;
5637 /* Now, re-encode the registers. */
5638 inst.instruction |= (rm << 16) | rn;
5640 return;
5643 decode_shift (&str, shift);
5646 /* ARM V6 Load Register Exclusive instruction (argument parse).
5647 LDREX{<cond>} <Rd, [<Rn>]
5648 Condition defaults to COND_ALWAYS.
5649 Error if Rd or Rn are R15.
5650 See ARMARMv6 A4.1.27: LDREX. */
5653 static void
5654 do_ldrex (str)
5655 char * str;
5657 int rd, rn;
5659 skip_whitespace (str);
5661 /* Parse Rd. */
5662 if (((rd = reg_required_here (&str, 12)) == FAIL)
5663 || (skip_past_comma (&str) == FAIL))
5665 inst.error = BAD_ARGS;
5666 return;
5668 else if (rd == REG_PC)
5670 inst.error = BAD_PC;
5671 return;
5673 skip_whitespace (str);
5675 /* Skip past '['. */
5676 if ((strlen (str) >= 1)
5677 &&strncmp (str, "[", 1) == 0)
5678 str+=1;
5679 skip_whitespace (str);
5681 /* Parse Rn. */
5682 if ((rn = reg_required_here (&str, 16)) == FAIL)
5684 inst.error = BAD_ARGS;
5685 return;
5687 else if (rn == REG_PC)
5689 inst.error = BAD_PC;
5690 return;
5692 skip_whitespace (str);
5694 /* Skip past ']'. */
5695 if ((strlen (str) >= 1)
5696 && strncmp (str, "]", 1) == 0)
5697 str+=1;
5699 end_of_line (str);
5702 /* ARM V6 change processor state instruction (argument parse)
5703 CPS, CPSIE, CSPID . */
5705 static void
5706 do_cps (str)
5707 char * str;
5709 do_cps_mode (&str);
5710 end_of_line (str);
5713 static void
5714 do_cpsi (str)
5715 char * str;
5717 do_cps_flags (&str, /*thumb_p=*/0);
5719 if (skip_past_comma (&str) == SUCCESS)
5721 skip_whitespace (str);
5722 do_cps_mode (&str);
5724 end_of_line (str);
5727 static void
5728 do_cps_mode (str)
5729 char **str;
5731 expressionS expr;
5733 skip_whitespace (*str);
5735 if (! is_immediate_prefix (**str))
5737 inst.error = _("immediate expression expected");
5738 return;
5741 (*str)++; /* Strip off the immediate signifier. */
5742 if (my_get_expression (&expr, str))
5744 inst.error = _("bad expression");
5745 return;
5748 if (expr.X_op != O_constant)
5750 inst.error = _("constant expression expected");
5751 return;
5754 /* The mode is a 5 bit field. Valid values are 0-31. */
5755 if (((unsigned) expr.X_add_number) > 31
5756 || (inst.reloc.exp.X_add_number) < 0)
5758 inst.error = _("invalid constant");
5759 return;
5762 inst.instruction |= expr.X_add_number;
5763 return;
5766 static void
5767 do_cps_flags (str, thumb_p)
5768 char **str;
5769 int thumb_p;
5771 struct cps_flag {
5772 char character;
5773 unsigned long arm_value;
5774 unsigned long thumb_value;
5776 static struct cps_flag flag_table[] = {
5777 {'a', 0x100, 0x4 },
5778 {'i', 0x080, 0x2 },
5779 {'f', 0x040, 0x1 }
5782 int saw_a_flag = 0;
5784 skip_whitespace (*str);
5786 /* Get the a, f and i flags. */
5787 while (**str && **str != ',')
5789 struct cps_flag *p;
5790 struct cps_flag *q = flag_table + sizeof (flag_table)/sizeof (*p);
5791 for (p = flag_table; p < q; ++p)
5792 if (strncasecmp (*str, &p->character, 1) == 0)
5794 inst.instruction |= (thumb_p ? p->thumb_value : p->arm_value);
5795 saw_a_flag = 1;
5796 break;
5798 if (p == q)
5800 inst.error = _("unrecognized flag");
5801 return;
5803 (*str)++;
5805 if (!saw_a_flag)
5806 inst.error = _("no 'a', 'i', or 'f' flags for 'cps'");
5809 /* THUMB V5 breakpoint instruction (argument parse)
5810 BKPT <immed_8>. */
5812 static void
5813 do_t_bkpt (str)
5814 char * str;
5816 expressionS expr;
5817 unsigned long number;
5819 skip_whitespace (str);
5821 /* Allow optional leading '#'. */
5822 if (is_immediate_prefix (*str))
5823 str ++;
5825 memset (& expr, '\0', sizeof (expr));
5826 if (my_get_expression (& expr, & str)
5827 || (expr.X_op != O_constant
5828 /* As a convenience we allow 'bkpt' without an operand. */
5829 && expr.X_op != O_absent))
5831 inst.error = _("bad expression");
5832 return;
5835 number = expr.X_add_number;
5837 /* Check it fits an 8 bit unsigned. */
5838 if (number != (number & 0xff))
5840 inst.error = _("immediate value out of range");
5841 return;
5844 inst.instruction |= number;
5846 end_of_line (str);
5849 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
5850 Expects inst.instruction is set for BLX(1).
5851 Note: this is cloned from do_branch, and the reloc changed to be a
5852 new one that can cope with setting one extra bit (the H bit). */
5854 static void
5855 do_branch25 (str)
5856 char * str;
5858 if (my_get_expression (& inst.reloc.exp, & str))
5859 return;
5861 #ifdef OBJ_ELF
5863 char * save_in;
5865 /* ScottB: February 5, 1998 */
5866 /* Check to see of PLT32 reloc required for the instruction. */
5868 /* arm_parse_reloc() works on input_line_pointer.
5869 We actually want to parse the operands to the branch instruction
5870 passed in 'str'. Save the input pointer and restore it later. */
5871 save_in = input_line_pointer;
5872 input_line_pointer = str;
5874 if (inst.reloc.exp.X_op == O_symbol
5875 && *str == '('
5876 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
5878 inst.reloc.type = BFD_RELOC_ARM_PLT32;
5879 inst.reloc.pc_rel = 0;
5880 /* Modify str to point to after parsed operands, otherwise
5881 end_of_line() will complain about the (PLT) left in str. */
5882 str = input_line_pointer;
5884 else
5886 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
5887 inst.reloc.pc_rel = 1;
5890 input_line_pointer = save_in;
5892 #else
5893 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
5894 inst.reloc.pc_rel = 1;
5895 #endif /* OBJ_ELF */
5897 end_of_line (str);
5900 /* ARM V5 branch-link-exchange instruction (argument parse)
5901 BLX <target_addr> ie BLX(1)
5902 BLX{<condition>} <Rm> ie BLX(2)
5903 Unfortunately, there are two different opcodes for this mnemonic.
5904 So, the insns[].value is not used, and the code here zaps values
5905 into inst.instruction.
5906 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
5908 static void
5909 do_blx (str)
5910 char * str;
5912 char * mystr = str;
5913 int rm;
5915 skip_whitespace (mystr);
5916 rm = reg_required_here (& mystr, 0);
5918 /* The above may set inst.error. Ignore his opinion. */
5919 inst.error = 0;
5921 if (rm != FAIL)
5923 /* Arg is a register.
5924 Use the condition code our caller put in inst.instruction.
5925 Pass ourselves off as a BX with a funny opcode. */
5926 inst.instruction |= 0x012fff30;
5927 do_bx (str);
5929 else
5931 /* This must be is BLX <target address>, no condition allowed. */
5932 if (inst.instruction != COND_ALWAYS)
5934 inst.error = BAD_COND;
5935 return;
5938 inst.instruction = 0xfafffffe;
5940 /* Process like a B/BL, but with a different reloc.
5941 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
5942 do_branch25 (str);
5946 /* ARM V5 Thumb BLX (argument parse)
5947 BLX <target_addr> which is BLX(1)
5948 BLX <Rm> which is BLX(2)
5949 Unfortunately, there are two different opcodes for this mnemonic.
5950 So, the tinsns[].value is not used, and the code here zaps values
5951 into inst.instruction. */
5953 static void
5954 do_t_blx (str)
5955 char * str;
5957 char * mystr = str;
5958 int rm;
5960 skip_whitespace (mystr);
5961 inst.instruction = 0x4780;
5963 /* Note that this call is to the ARM register recognizer. BLX(2)
5964 uses the ARM register space, not the Thumb one, so a call to
5965 thumb_reg() would be wrong. */
5966 rm = reg_required_here (& mystr, 3);
5967 inst.error = 0;
5969 if (rm != FAIL)
5971 /* It's BLX(2). The .instruction was zapped with rm & is final. */
5972 inst.size = 2;
5974 else
5976 /* No ARM register. This must be BLX(1). Change the .instruction. */
5977 inst.instruction = 0xf7ffeffe;
5978 inst.size = 4;
5980 if (my_get_expression (& inst.reloc.exp, & mystr))
5981 return;
5983 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BLX;
5984 inst.reloc.pc_rel = 1;
5987 end_of_line (mystr);
5990 /* ARM V5 breakpoint instruction (argument parse)
5991 BKPT <16 bit unsigned immediate>
5992 Instruction is not conditional.
5993 The bit pattern given in insns[] has the COND_ALWAYS condition,
5994 and it is an error if the caller tried to override that. */
5996 static void
5997 do_bkpt (str)
5998 char * str;
6000 expressionS expr;
6001 unsigned long number;
6003 skip_whitespace (str);
6005 /* Allow optional leading '#'. */
6006 if (is_immediate_prefix (* str))
6007 str++;
6009 memset (& expr, '\0', sizeof (expr));
6011 if (my_get_expression (& expr, & str)
6012 || (expr.X_op != O_constant
6013 /* As a convenience we allow 'bkpt' without an operand. */
6014 && expr.X_op != O_absent))
6016 inst.error = _("bad expression");
6017 return;
6020 number = expr.X_add_number;
6022 /* Check it fits a 16 bit unsigned. */
6023 if (number != (number & 0xffff))
6025 inst.error = _("immediate value out of range");
6026 return;
6029 /* Top 12 of 16 bits to bits 19:8. */
6030 inst.instruction |= (number & 0xfff0) << 4;
6032 /* Bottom 4 of 16 bits to bits 3:0. */
6033 inst.instruction |= number & 0xf;
6035 end_of_line (str);
6038 /* THUMB CPS instruction (argument parse). */
6040 static void
6041 do_t_cps (str)
6042 char *str;
6044 do_cps_flags (&str, /*thumb_p=*/1);
6045 end_of_line (str);
6048 /* THUMB CPY instruction (argument parse). */
6050 static void
6051 do_t_cpy (str)
6052 char *str;
6054 thumb_mov_compare (str, THUMB_CPY);
6057 /* THUMB SETEND instruction (argument parse). */
6059 static void
6060 do_t_setend (str)
6061 char *str;
6063 if (do_endian_specifier (str))
6064 inst.instruction |= 0x8;
6067 static unsigned long check_iwmmxt_insn PARAMS ((char *, enum iwmmxt_insn_type, int));
6069 /* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
6071 static unsigned long
6072 check_iwmmxt_insn (str, insn_type, immediate_size)
6073 char * str;
6074 enum iwmmxt_insn_type insn_type;
6075 int immediate_size;
6077 int reg = 0;
6078 const char * inst_error;
6079 expressionS expr;
6080 unsigned long number;
6082 inst_error = inst.error;
6083 if (!inst.error)
6084 inst.error = BAD_ARGS;
6085 skip_whitespace (str);
6087 switch (insn_type)
6089 case check_rd:
6090 if ((reg = reg_required_here (&str, 12)) == FAIL)
6091 return FAIL;
6092 break;
6094 case check_wr:
6095 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR)) == FAIL)
6096 return FAIL;
6097 break;
6099 case check_wrwr:
6100 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6101 || skip_past_comma (&str) == FAIL
6102 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
6103 return FAIL;
6104 break;
6106 case check_wrwrwr:
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 || skip_past_comma (&str) == FAIL
6111 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
6112 return FAIL;
6113 break;
6115 case check_wrwrwcg:
6116 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6117 || skip_past_comma (&str) == FAIL
6118 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6119 || skip_past_comma (&str) == FAIL
6120 || wreg_required_here (&str, 0, IWMMXT_REG_WCG) == FAIL))
6121 return FAIL;
6122 break;
6124 case check_tbcst:
6125 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6126 || skip_past_comma (&str) == FAIL
6127 || reg_required_here (&str, 12) == FAIL))
6128 return FAIL;
6129 break;
6131 case check_tmovmsk:
6132 if ((reg_required_here (&str, 12) == FAIL
6133 || skip_past_comma (&str) == FAIL
6134 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
6135 return FAIL;
6136 break;
6138 case check_tmia:
6139 if ((wreg_required_here (&str, 5, IWMMXT_REG_WR) == FAIL
6140 || skip_past_comma (&str) == FAIL
6141 || reg_required_here (&str, 0) == FAIL
6142 || skip_past_comma (&str) == FAIL
6143 || reg_required_here (&str, 12) == FAIL))
6144 return FAIL;
6145 break;
6147 case check_tmcrr:
6148 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
6149 || skip_past_comma (&str) == FAIL
6150 || reg_required_here (&str, 12) == FAIL
6151 || skip_past_comma (&str) == FAIL
6152 || reg_required_here (&str, 16) == FAIL))
6153 return FAIL;
6154 break;
6156 case check_tmrrc:
6157 if ((reg_required_here (&str, 12) == FAIL
6158 || skip_past_comma (&str) == FAIL
6159 || reg_required_here (&str, 16) == FAIL
6160 || skip_past_comma (&str) == FAIL
6161 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
6162 return FAIL;
6163 break;
6165 case check_tmcr:
6166 if ((wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL
6167 || skip_past_comma (&str) == FAIL
6168 || reg_required_here (&str, 12) == FAIL))
6169 return FAIL;
6170 break;
6172 case check_tmrc:
6173 if ((reg_required_here (&str, 12) == FAIL
6174 || skip_past_comma (&str) == FAIL
6175 || wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL))
6176 return FAIL;
6177 break;
6179 case check_tinsr:
6180 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6181 || skip_past_comma (&str) == FAIL
6182 || reg_required_here (&str, 12) == FAIL
6183 || skip_past_comma (&str) == FAIL))
6184 return FAIL;
6185 break;
6187 case check_textrc:
6188 if ((reg_required_here (&str, 12) == FAIL
6189 || skip_past_comma (&str) == FAIL))
6190 return FAIL;
6191 break;
6193 case check_waligni:
6194 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6195 || skip_past_comma (&str) == FAIL
6196 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6197 || skip_past_comma (&str) == FAIL
6198 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
6199 || skip_past_comma (&str) == FAIL))
6200 return FAIL;
6201 break;
6203 case check_textrm:
6204 if ((reg_required_here (&str, 12) == FAIL
6205 || skip_past_comma (&str) == FAIL
6206 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6207 || skip_past_comma (&str) == FAIL))
6208 return FAIL;
6209 break;
6211 case check_wshufh:
6212 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6213 || skip_past_comma (&str) == FAIL
6214 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6215 || skip_past_comma (&str) == FAIL))
6216 return FAIL;
6217 break;
6220 if (immediate_size == 0)
6222 end_of_line (str);
6223 inst.error = inst_error;
6224 return reg;
6226 else
6228 skip_whitespace (str);
6230 /* Allow optional leading '#'. */
6231 if (is_immediate_prefix (* str))
6232 str++;
6234 memset (& expr, '\0', sizeof (expr));
6236 if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
6238 inst.error = _("bad or missing expression");
6239 return FAIL;
6242 number = expr.X_add_number;
6244 if (number != (number & immediate_size))
6246 inst.error = _("immediate value out of range");
6247 return FAIL;
6249 end_of_line (str);
6250 inst.error = inst_error;
6251 return number;
6255 static void
6256 do_iwmmxt_byte_addr (str)
6257 char * str;
6259 int op = (inst.instruction & 0x300) >> 8;
6260 int reg;
6262 inst.instruction &= ~0x300;
6263 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
6265 skip_whitespace (str);
6267 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
6268 || skip_past_comma (& str) == FAIL
6269 || cp_byte_address_required_here (&str) == FAIL)
6271 if (! inst.error)
6272 inst.error = BAD_ARGS;
6274 else
6275 end_of_line (str);
6277 if (wc_register (reg))
6279 as_bad (_("non-word size not supported with control register"));
6280 inst.instruction |= 0xf0000100;
6281 inst.instruction &= ~0x00400000;
6285 static void
6286 do_iwmmxt_tandc (str)
6287 char * str;
6289 int reg;
6291 reg = check_iwmmxt_insn (str, check_rd, 0);
6293 if (reg != REG_PC && !inst.error)
6294 inst.error = _("only r15 allowed here");
6295 return;
6298 static void
6299 do_iwmmxt_tbcst (str)
6300 char * str;
6302 check_iwmmxt_insn (str, check_tbcst, 0);
6304 return;
6307 static void
6308 do_iwmmxt_textrc (str)
6309 char * str;
6311 unsigned long number;
6313 if ((number = check_iwmmxt_insn (str, check_textrc, 7)) == (unsigned long) FAIL)
6314 return;
6316 inst.instruction |= number & 0x7;
6317 return;
6320 static void
6321 do_iwmmxt_textrm (str)
6322 char * str;
6324 unsigned long number;
6326 if ((number = check_iwmmxt_insn (str, check_textrm, 7)) == (unsigned long) FAIL)
6327 return;
6329 inst.instruction |= number & 0x7;
6332 static void
6333 do_iwmmxt_tinsr (str)
6334 char * str;
6336 unsigned long number;
6338 if ((number = check_iwmmxt_insn (str, check_tinsr, 7)) == (unsigned long) FAIL)
6339 return;
6341 inst.instruction |= number & 0x7;
6342 return;
6345 static void
6346 do_iwmmxt_tmcr (str)
6347 char * str;
6349 check_iwmmxt_insn (str, check_tmcr, 0);
6351 return;
6354 static void
6355 do_iwmmxt_tmcrr (str)
6356 char * str;
6358 check_iwmmxt_insn (str, check_tmcrr, 0);
6360 return;
6363 static void
6364 do_iwmmxt_tmia (str)
6365 char * str;
6367 check_iwmmxt_insn (str, check_tmia, 0);
6369 return;
6372 static void
6373 do_iwmmxt_tmovmsk (str)
6374 char * str;
6376 check_iwmmxt_insn (str, check_tmovmsk, 0);
6378 return;
6381 static void
6382 do_iwmmxt_tmrc (str)
6383 char * str;
6385 check_iwmmxt_insn (str, check_tmrc, 0);
6387 return;
6390 static void
6391 do_iwmmxt_tmrrc (str)
6392 char * str;
6394 check_iwmmxt_insn (str, check_tmrrc, 0);
6396 return;
6399 static void
6400 do_iwmmxt_torc (str)
6401 char * str;
6403 check_iwmmxt_insn (str, check_rd, 0);
6404 return;
6407 static void
6408 do_iwmmxt_waligni (str)
6409 char * str;
6411 unsigned long number;
6413 if ((number = check_iwmmxt_insn (str, check_waligni, 7)) == (unsigned long) FAIL)
6414 return;
6416 inst.instruction |= ((number & 0x7) << 20);
6417 return;
6420 static void
6421 do_iwmmxt_wmov (str)
6422 char * str;
6424 if (check_iwmmxt_insn (str, check_wrwr, 0) == (unsigned long) FAIL)
6425 return;
6427 inst.instruction |= ((inst.instruction >> 16) & 0xf);
6428 return;
6431 static void
6432 do_iwmmxt_word_addr (str)
6433 char * str;
6435 int op = (inst.instruction & 0x300) >> 8;
6436 int reg;
6438 inst.instruction &= ~0x300;
6439 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
6441 skip_whitespace (str);
6443 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
6444 || skip_past_comma (& str) == FAIL
6445 || cp_address_required_here (& str, CP_WB_OK) == FAIL)
6447 if (! inst.error)
6448 inst.error = BAD_ARGS;
6450 else
6451 end_of_line (str);
6453 if (wc_register (reg))
6455 if ((inst.instruction & COND_MASK) != COND_ALWAYS)
6456 as_bad (_("conditional execution not supported with control register"));
6457 if (op != 2)
6458 as_bad (_("non-word size not supported with control register"));
6459 inst.instruction |= 0xf0000100;
6460 inst.instruction &= ~0x00400000;
6464 static void
6465 do_iwmmxt_wrwr (str)
6466 char * str;
6468 check_iwmmxt_insn (str, check_wrwr, 0);
6470 return;
6473 static void
6474 do_iwmmxt_wrwrwcg (str)
6475 char * str;
6477 check_iwmmxt_insn (str, check_wrwrwcg, 0);
6479 return;
6482 static void
6483 do_iwmmxt_wrwrwr (str)
6484 char * str;
6486 check_iwmmxt_insn (str, check_wrwrwr, 0);
6488 return;
6491 static void
6492 do_iwmmxt_wshufh (str)
6493 char * str;
6495 unsigned long number;
6497 if ((number = check_iwmmxt_insn (str, check_wshufh, 0xff)) == (unsigned long) FAIL)
6498 return;
6500 inst.instruction |= ((number & 0xf0) << 16) | (number & 0xf);
6501 return;
6504 static void
6505 do_iwmmxt_wzero (str)
6506 char * str;
6508 if (check_iwmmxt_insn (str, check_wr, 0) == (unsigned long) FAIL)
6509 return;
6511 inst.instruction |= ((inst.instruction & 0xf) << 12) | ((inst.instruction & 0xf) << 16);
6512 return;
6515 /* Xscale multiply-accumulate (argument parse)
6516 MIAcc acc0,Rm,Rs
6517 MIAPHcc acc0,Rm,Rs
6518 MIAxycc acc0,Rm,Rs. */
6520 static void
6521 do_xsc_mia (str)
6522 char * str;
6524 int rs;
6525 int rm;
6527 if (accum0_required_here (& str) == FAIL)
6528 inst.error = ERR_NO_ACCUM;
6530 else if (skip_past_comma (& str) == FAIL
6531 || (rm = reg_required_here (& str, 0)) == FAIL)
6532 inst.error = BAD_ARGS;
6534 else if (skip_past_comma (& str) == FAIL
6535 || (rs = reg_required_here (& str, 12)) == FAIL)
6536 inst.error = BAD_ARGS;
6538 /* inst.instruction has now been zapped with both rm and rs. */
6539 else if (rm == REG_PC || rs == REG_PC)
6540 inst.error = BAD_PC; /* Undefined result if rm or rs is R15. */
6542 else
6543 end_of_line (str);
6546 /* Xscale move-accumulator-register (argument parse)
6548 MARcc acc0,RdLo,RdHi. */
6550 static void
6551 do_xsc_mar (str)
6552 char * str;
6554 int rdlo, rdhi;
6556 if (accum0_required_here (& str) == FAIL)
6557 inst.error = ERR_NO_ACCUM;
6559 else if (skip_past_comma (& str) == FAIL
6560 || (rdlo = reg_required_here (& str, 12)) == FAIL)
6561 inst.error = BAD_ARGS;
6563 else if (skip_past_comma (& str) == FAIL
6564 || (rdhi = reg_required_here (& str, 16)) == FAIL)
6565 inst.error = BAD_ARGS;
6567 /* inst.instruction has now been zapped with both rdlo and rdhi. */
6568 else if (rdlo == REG_PC || rdhi == REG_PC)
6569 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
6571 else
6572 end_of_line (str);
6575 /* Xscale move-register-accumulator (argument parse)
6577 MRAcc RdLo,RdHi,acc0. */
6579 static void
6580 do_xsc_mra (str)
6581 char * str;
6583 int rdlo;
6584 int rdhi;
6586 skip_whitespace (str);
6588 if ((rdlo = reg_required_here (& str, 12)) == FAIL)
6589 inst.error = BAD_ARGS;
6591 else if (skip_past_comma (& str) == FAIL
6592 || (rdhi = reg_required_here (& str, 16)) == FAIL)
6593 inst.error = BAD_ARGS;
6595 else if (skip_past_comma (& str) == FAIL
6596 || accum0_required_here (& str) == FAIL)
6597 inst.error = ERR_NO_ACCUM;
6599 /* inst.instruction has now been zapped with both rdlo and rdhi. */
6600 else if (rdlo == rdhi)
6601 inst.error = BAD_ARGS; /* Undefined result if 2 writes to same reg. */
6603 else if (rdlo == REG_PC || rdhi == REG_PC)
6604 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
6605 else
6606 end_of_line (str);
6609 /* ARMv5TE: Preload-Cache
6611 PLD <addr_mode>
6613 Syntactically, like LDR with B=1, W=0, L=1. */
6615 static void
6616 do_pld (str)
6617 char * str;
6619 int rd;
6621 skip_whitespace (str);
6623 if (* str != '[')
6625 inst.error = _("'[' expected after PLD mnemonic");
6626 return;
6629 ++str;
6630 skip_whitespace (str);
6632 if ((rd = reg_required_here (& str, 16)) == FAIL)
6633 return;
6635 skip_whitespace (str);
6637 if (*str == ']')
6639 /* [Rn], ... ? */
6640 ++str;
6641 skip_whitespace (str);
6643 /* Post-indexed addressing is not allowed with PLD. */
6644 if (skip_past_comma (&str) == SUCCESS)
6646 inst.error
6647 = _("post-indexed expression used in preload instruction");
6648 return;
6650 else if (*str == '!') /* [Rn]! */
6652 inst.error = _("writeback used in preload instruction");
6653 ++str;
6655 else /* [Rn] */
6656 inst.instruction |= INDEX_UP | PRE_INDEX;
6658 else /* [Rn, ...] */
6660 if (skip_past_comma (& str) == FAIL)
6662 inst.error = _("pre-indexed expression expected");
6663 return;
6666 if (ldst_extend (&str) == FAIL)
6667 return;
6669 skip_whitespace (str);
6671 if (* str != ']')
6673 inst.error = _("missing ]");
6674 return;
6677 ++ str;
6678 skip_whitespace (str);
6680 if (* str == '!') /* [Rn]! */
6682 inst.error = _("writeback used in preload instruction");
6683 ++ str;
6686 inst.instruction |= PRE_INDEX;
6689 end_of_line (str);
6692 /* ARMv5TE load-consecutive (argument parse)
6693 Mode is like LDRH.
6695 LDRccD R, mode
6696 STRccD R, mode. */
6698 static void
6699 do_ldrd (str)
6700 char * str;
6702 int rd;
6703 int rn;
6705 skip_whitespace (str);
6707 if ((rd = reg_required_here (& str, 12)) == FAIL)
6709 inst.error = BAD_ARGS;
6710 return;
6713 if (skip_past_comma (& str) == FAIL
6714 || (rn = ld_mode_required_here (& str)) == FAIL)
6716 if (!inst.error)
6717 inst.error = BAD_ARGS;
6718 return;
6721 /* inst.instruction has now been zapped with Rd and the addressing mode. */
6722 if (rd & 1) /* Unpredictable result if Rd is odd. */
6724 inst.error = _("destination register must be even");
6725 return;
6728 if (rd == REG_LR)
6730 inst.error = _("r14 not allowed here");
6731 return;
6734 if (((rd == rn) || (rd + 1 == rn))
6735 && ((inst.instruction & WRITE_BACK)
6736 || (!(inst.instruction & PRE_INDEX))))
6737 as_warn (_("pre/post-indexing used when modified address register is destination"));
6739 /* For an index-register load, the index register must not overlap the
6740 destination (even if not write-back). */
6741 if ((inst.instruction & V4_STR_BIT) == 0
6742 && (inst.instruction & HWOFFSET_IMM) == 0)
6744 int rm = inst.instruction & 0x0000000f;
6746 if (rm == rd || (rm == rd + 1))
6747 as_warn (_("ldrd destination registers must not overlap index register"));
6750 end_of_line (str);
6753 /* Returns the index into fp_values of a floating point number,
6754 or -1 if not in the table. */
6756 static int
6757 my_get_float_expression (str)
6758 char ** str;
6760 LITTLENUM_TYPE words[MAX_LITTLENUMS];
6761 char * save_in;
6762 expressionS exp;
6763 int i;
6764 int j;
6766 memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE));
6768 /* Look for a raw floating point number. */
6769 if ((save_in = atof_ieee (*str, 'x', words)) != NULL
6770 && is_end_of_line[(unsigned char) *save_in])
6772 for (i = 0; i < NUM_FLOAT_VALS; i++)
6774 for (j = 0; j < MAX_LITTLENUMS; j++)
6776 if (words[j] != fp_values[i][j])
6777 break;
6780 if (j == MAX_LITTLENUMS)
6782 *str = save_in;
6783 return i;
6788 /* Try and parse a more complex expression, this will probably fail
6789 unless the code uses a floating point prefix (eg "0f"). */
6790 save_in = input_line_pointer;
6791 input_line_pointer = *str;
6792 if (expression (&exp) == absolute_section
6793 && exp.X_op == O_big
6794 && exp.X_add_number < 0)
6796 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
6797 Ditto for 15. */
6798 if (gen_to_words (words, 5, (long) 15) == 0)
6800 for (i = 0; i < NUM_FLOAT_VALS; i++)
6802 for (j = 0; j < MAX_LITTLENUMS; j++)
6804 if (words[j] != fp_values[i][j])
6805 break;
6808 if (j == MAX_LITTLENUMS)
6810 *str = input_line_pointer;
6811 input_line_pointer = save_in;
6812 return i;
6818 *str = input_line_pointer;
6819 input_line_pointer = save_in;
6820 return -1;
6823 /* Return TRUE if anything in the expression is a bignum. */
6825 static int
6826 walk_no_bignums (sp)
6827 symbolS * sp;
6829 if (symbol_get_value_expression (sp)->X_op == O_big)
6830 return 1;
6832 if (symbol_get_value_expression (sp)->X_add_symbol)
6834 return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
6835 || (symbol_get_value_expression (sp)->X_op_symbol
6836 && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
6839 return 0;
6842 static int in_my_get_expression = 0;
6844 static int
6845 my_get_expression (ep, str)
6846 expressionS * ep;
6847 char ** str;
6849 char * save_in;
6850 segT seg;
6852 save_in = input_line_pointer;
6853 input_line_pointer = *str;
6854 in_my_get_expression = 1;
6855 seg = expression (ep);
6856 in_my_get_expression = 0;
6858 if (ep->X_op == O_illegal)
6860 /* We found a bad expression in md_operand(). */
6861 *str = input_line_pointer;
6862 input_line_pointer = save_in;
6863 return 1;
6866 #ifdef OBJ_AOUT
6867 if (seg != absolute_section
6868 && seg != text_section
6869 && seg != data_section
6870 && seg != bss_section
6871 && seg != undefined_section)
6873 inst.error = _("bad_segment");
6874 *str = input_line_pointer;
6875 input_line_pointer = save_in;
6876 return 1;
6878 #endif
6880 /* Get rid of any bignums now, so that we don't generate an error for which
6881 we can't establish a line number later on. Big numbers are never valid
6882 in instructions, which is where this routine is always called. */
6883 if (ep->X_op == O_big
6884 || (ep->X_add_symbol
6885 && (walk_no_bignums (ep->X_add_symbol)
6886 || (ep->X_op_symbol
6887 && walk_no_bignums (ep->X_op_symbol)))))
6889 inst.error = _("invalid constant");
6890 *str = input_line_pointer;
6891 input_line_pointer = save_in;
6892 return 1;
6895 *str = input_line_pointer;
6896 input_line_pointer = save_in;
6897 return 0;
6900 /* We handle all bad expressions here, so that we can report the faulty
6901 instruction in the error message. */
6902 void
6903 md_operand (expr)
6904 expressionS *expr;
6906 if (in_my_get_expression)
6908 expr->X_op = O_illegal;
6909 if (inst.error == NULL)
6910 inst.error = _("bad expression");
6914 /* KIND indicates what kind of shifts are accepted. */
6916 static int
6917 decode_shift (str, kind)
6918 char ** str;
6919 int kind;
6921 const struct asm_shift_name * shift;
6922 char * p;
6923 char c;
6925 skip_whitespace (* str);
6927 for (p = * str; ISALPHA (* p); p ++)
6930 if (p == * str)
6932 inst.error = _("shift expression expected");
6933 return FAIL;
6936 c = * p;
6937 * p = '\0';
6938 shift = (const struct asm_shift_name *) hash_find (arm_shift_hsh, * str);
6939 * p = c;
6941 if (shift == NULL)
6943 inst.error = _("shift expression expected");
6944 return FAIL;
6947 assert (shift->properties->index == shift_properties[shift->properties->index].index);
6949 if (kind == SHIFT_LSL_OR_ASR_IMMEDIATE
6950 && shift->properties->index != SHIFT_LSL
6951 && shift->properties->index != SHIFT_ASR)
6953 inst.error = _("'LSL' or 'ASR' required");
6954 return FAIL;
6956 else if (kind == SHIFT_LSL_IMMEDIATE
6957 && shift->properties->index != SHIFT_LSL)
6959 inst.error = _("'LSL' required");
6960 return FAIL;
6962 else if (kind == SHIFT_ASR_IMMEDIATE
6963 && shift->properties->index != SHIFT_ASR)
6965 inst.error = _("'ASR' required");
6966 return FAIL;
6969 if (shift->properties->index == SHIFT_RRX)
6971 * str = p;
6972 inst.instruction |= shift->properties->bit_field;
6973 return SUCCESS;
6976 skip_whitespace (p);
6978 if (kind == NO_SHIFT_RESTRICT && reg_required_here (& p, 8) != FAIL)
6980 inst.instruction |= shift->properties->bit_field | SHIFT_BY_REG;
6981 * str = p;
6982 return SUCCESS;
6984 else if (! is_immediate_prefix (* p))
6986 inst.error = (NO_SHIFT_RESTRICT
6987 ? _("shift requires register or #expression")
6988 : _("shift requires #expression"));
6989 * str = p;
6990 return FAIL;
6993 inst.error = NULL;
6994 p ++;
6996 if (my_get_expression (& inst.reloc.exp, & p))
6997 return FAIL;
6999 /* Validate some simple #expressions. */
7000 if (inst.reloc.exp.X_op == O_constant)
7002 unsigned num = inst.reloc.exp.X_add_number;
7004 /* Reject operations greater than 32. */
7005 if (num > 32
7006 /* Reject a shift of 0 unless the mode allows it. */
7007 || (num == 0 && shift->properties->allows_0 == 0)
7008 /* Reject a shift of 32 unless the mode allows it. */
7009 || (num == 32 && shift->properties->allows_32 == 0)
7012 /* As a special case we allow a shift of zero for
7013 modes that do not support it to be recoded as an
7014 logical shift left of zero (ie nothing). We warn
7015 about this though. */
7016 if (num == 0)
7018 as_warn (_("shift of 0 ignored."));
7019 shift = & shift_names[0];
7020 assert (shift->properties->index == SHIFT_LSL);
7022 else
7024 inst.error = _("invalid immediate shift");
7025 return FAIL;
7029 /* Shifts of 32 are encoded as 0, for those shifts that
7030 support it. */
7031 if (num == 32)
7032 num = 0;
7034 inst.instruction |= (num << 7) | shift->properties->bit_field;
7036 else
7038 inst.reloc.type = BFD_RELOC_ARM_SHIFT_IMM;
7039 inst.reloc.pc_rel = 0;
7040 inst.instruction |= shift->properties->bit_field;
7043 * str = p;
7044 return SUCCESS;
7047 /* Do those data_ops which can take a negative immediate constant
7048 by altering the instruction. A bit of a hack really.
7049 MOV <-> MVN
7050 AND <-> BIC
7051 ADC <-> SBC
7052 by inverting the second operand, and
7053 ADD <-> SUB
7054 CMP <-> CMN
7055 by negating the second operand. */
7057 static int
7058 negate_data_op (instruction, value)
7059 unsigned long * instruction;
7060 unsigned long value;
7062 int op, new_inst;
7063 unsigned long negated, inverted;
7065 negated = validate_immediate (-value);
7066 inverted = validate_immediate (~value);
7068 op = (*instruction >> DATA_OP_SHIFT) & 0xf;
7069 switch (op)
7071 /* First negates. */
7072 case OPCODE_SUB: /* ADD <-> SUB */
7073 new_inst = OPCODE_ADD;
7074 value = negated;
7075 break;
7077 case OPCODE_ADD:
7078 new_inst = OPCODE_SUB;
7079 value = negated;
7080 break;
7082 case OPCODE_CMP: /* CMP <-> CMN */
7083 new_inst = OPCODE_CMN;
7084 value = negated;
7085 break;
7087 case OPCODE_CMN:
7088 new_inst = OPCODE_CMP;
7089 value = negated;
7090 break;
7092 /* Now Inverted ops. */
7093 case OPCODE_MOV: /* MOV <-> MVN */
7094 new_inst = OPCODE_MVN;
7095 value = inverted;
7096 break;
7098 case OPCODE_MVN:
7099 new_inst = OPCODE_MOV;
7100 value = inverted;
7101 break;
7103 case OPCODE_AND: /* AND <-> BIC */
7104 new_inst = OPCODE_BIC;
7105 value = inverted;
7106 break;
7108 case OPCODE_BIC:
7109 new_inst = OPCODE_AND;
7110 value = inverted;
7111 break;
7113 case OPCODE_ADC: /* ADC <-> SBC */
7114 new_inst = OPCODE_SBC;
7115 value = inverted;
7116 break;
7118 case OPCODE_SBC:
7119 new_inst = OPCODE_ADC;
7120 value = inverted;
7121 break;
7123 /* We cannot do anything. */
7124 default:
7125 return FAIL;
7128 if (value == (unsigned) FAIL)
7129 return FAIL;
7131 *instruction &= OPCODE_MASK;
7132 *instruction |= new_inst << DATA_OP_SHIFT;
7133 return value;
7136 static int
7137 data_op2 (str)
7138 char ** str;
7140 int value;
7141 expressionS expr;
7143 skip_whitespace (* str);
7145 if (reg_required_here (str, 0) != FAIL)
7147 if (skip_past_comma (str) == SUCCESS)
7148 /* Shift operation on register. */
7149 return decode_shift (str, NO_SHIFT_RESTRICT);
7151 return SUCCESS;
7153 else
7155 /* Immediate expression. */
7156 if (is_immediate_prefix (**str))
7158 (*str)++;
7159 inst.error = NULL;
7161 if (my_get_expression (&inst.reloc.exp, str))
7162 return FAIL;
7164 if (inst.reloc.exp.X_add_symbol)
7166 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
7167 inst.reloc.pc_rel = 0;
7169 else
7171 if (skip_past_comma (str) == SUCCESS)
7173 /* #x, y -- ie explicit rotation by Y. */
7174 if (my_get_expression (&expr, str))
7175 return FAIL;
7177 if (expr.X_op != O_constant)
7179 inst.error = _("constant expression expected");
7180 return FAIL;
7183 /* Rotate must be a multiple of 2. */
7184 if (((unsigned) expr.X_add_number) > 30
7185 || (expr.X_add_number & 1) != 0
7186 || ((unsigned) inst.reloc.exp.X_add_number) > 255)
7188 inst.error = _("invalid constant");
7189 return FAIL;
7191 inst.instruction |= INST_IMMEDIATE;
7192 inst.instruction |= inst.reloc.exp.X_add_number;
7193 inst.instruction |= expr.X_add_number << 7;
7194 return SUCCESS;
7197 /* Implicit rotation, select a suitable one. */
7198 value = validate_immediate (inst.reloc.exp.X_add_number);
7200 if (value == FAIL)
7202 /* Can't be done. Perhaps the code reads something like
7203 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
7204 if ((value = negate_data_op (&inst.instruction,
7205 inst.reloc.exp.X_add_number))
7206 == FAIL)
7208 inst.error = _("invalid constant");
7209 return FAIL;
7213 inst.instruction |= value;
7216 inst.instruction |= INST_IMMEDIATE;
7217 return SUCCESS;
7220 (*str)++;
7221 inst.error = _("register or shift expression expected");
7222 return FAIL;
7226 static int
7227 fp_op2 (str)
7228 char ** str;
7230 skip_whitespace (* str);
7232 if (fp_reg_required_here (str, 0) != FAIL)
7233 return SUCCESS;
7234 else
7236 /* Immediate expression. */
7237 if (*((*str)++) == '#')
7239 int i;
7241 inst.error = NULL;
7243 skip_whitespace (* str);
7245 /* First try and match exact strings, this is to guarantee
7246 that some formats will work even for cross assembly. */
7248 for (i = 0; fp_const[i]; i++)
7250 if (strncmp (*str, fp_const[i], strlen (fp_const[i])) == 0)
7252 char *start = *str;
7254 *str += strlen (fp_const[i]);
7255 if (is_end_of_line[(unsigned char) **str])
7257 inst.instruction |= i + 8;
7258 return SUCCESS;
7260 *str = start;
7264 /* Just because we didn't get a match doesn't mean that the
7265 constant isn't valid, just that it is in a format that we
7266 don't automatically recognize. Try parsing it with
7267 the standard expression routines. */
7268 if ((i = my_get_float_expression (str)) >= 0)
7270 inst.instruction |= i + 8;
7271 return SUCCESS;
7274 inst.error = _("invalid floating point immediate expression");
7275 return FAIL;
7277 inst.error =
7278 _("floating point register or immediate expression expected");
7279 return FAIL;
7283 static void
7284 do_arit (str)
7285 char * str;
7287 skip_whitespace (str);
7289 if (reg_required_here (&str, 12) == FAIL
7290 || skip_past_comma (&str) == FAIL
7291 || reg_required_here (&str, 16) == FAIL
7292 || skip_past_comma (&str) == FAIL
7293 || data_op2 (&str) == FAIL)
7295 if (!inst.error)
7296 inst.error = BAD_ARGS;
7297 return;
7300 end_of_line (str);
7301 return;
7304 static void
7305 do_adr (str)
7306 char * str;
7308 /* This is a pseudo-op of the form "adr rd, label" to be converted
7309 into a relative address of the form "add rd, pc, #label-.-8". */
7310 skip_whitespace (str);
7312 if (reg_required_here (&str, 12) == FAIL
7313 || skip_past_comma (&str) == FAIL
7314 || my_get_expression (&inst.reloc.exp, &str))
7316 if (!inst.error)
7317 inst.error = BAD_ARGS;
7318 return;
7321 /* Frag hacking will turn this into a sub instruction if the offset turns
7322 out to be negative. */
7323 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
7324 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust. */
7325 inst.reloc.pc_rel = 1;
7327 end_of_line (str);
7330 static void
7331 do_adrl (str)
7332 char * str;
7334 /* This is a pseudo-op of the form "adrl rd, label" to be converted
7335 into a relative address of the form:
7336 add rd, pc, #low(label-.-8)"
7337 add rd, rd, #high(label-.-8)" */
7339 skip_whitespace (str);
7341 if (reg_required_here (&str, 12) == FAIL
7342 || skip_past_comma (&str) == FAIL
7343 || my_get_expression (&inst.reloc.exp, &str))
7345 if (!inst.error)
7346 inst.error = BAD_ARGS;
7348 return;
7351 end_of_line (str);
7352 /* Frag hacking will turn this into a sub instruction if the offset turns
7353 out to be negative. */
7354 inst.reloc.type = BFD_RELOC_ARM_ADRL_IMMEDIATE;
7355 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust */
7356 inst.reloc.pc_rel = 1;
7357 inst.size = INSN_SIZE * 2;
7359 return;
7362 static void
7363 do_cmp (str)
7364 char * str;
7366 skip_whitespace (str);
7368 if (reg_required_here (&str, 16) == FAIL)
7370 if (!inst.error)
7371 inst.error = BAD_ARGS;
7372 return;
7375 if (skip_past_comma (&str) == FAIL
7376 || data_op2 (&str) == FAIL)
7378 if (!inst.error)
7379 inst.error = BAD_ARGS;
7380 return;
7383 end_of_line (str);
7384 return;
7387 static void
7388 do_mov (str)
7389 char * str;
7391 skip_whitespace (str);
7393 if (reg_required_here (&str, 12) == FAIL)
7395 if (!inst.error)
7396 inst.error = BAD_ARGS;
7397 return;
7400 if (skip_past_comma (&str) == FAIL
7401 || data_op2 (&str) == FAIL)
7403 if (!inst.error)
7404 inst.error = BAD_ARGS;
7405 return;
7408 end_of_line (str);
7409 return;
7412 static int
7413 ldst_extend (str)
7414 char ** str;
7416 int add = INDEX_UP;
7418 switch (**str)
7420 case '#':
7421 case '$':
7422 (*str)++;
7423 if (my_get_expression (& inst.reloc.exp, str))
7424 return FAIL;
7426 if (inst.reloc.exp.X_op == O_constant)
7428 int value = inst.reloc.exp.X_add_number;
7430 if (value < -4095 || value > 4095)
7432 inst.error = _("address offset too large");
7433 return FAIL;
7436 if (value < 0)
7438 value = -value;
7439 add = 0;
7442 inst.instruction |= add | value;
7444 else
7446 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
7447 inst.reloc.pc_rel = 0;
7449 return SUCCESS;
7451 case '-':
7452 add = 0;
7453 /* Fall through. */
7455 case '+':
7456 (*str)++;
7457 /* Fall through. */
7459 default:
7460 if (reg_required_here (str, 0) == FAIL)
7461 return FAIL;
7463 inst.instruction |= add | OFFSET_REG;
7464 if (skip_past_comma (str) == SUCCESS)
7465 return decode_shift (str, SHIFT_IMMEDIATE);
7467 return SUCCESS;
7471 static void
7472 do_ldst (str)
7473 char * str;
7475 int pre_inc = 0;
7476 int conflict_reg;
7477 int value;
7479 skip_whitespace (str);
7481 if ((conflict_reg = reg_required_here (&str, 12)) == FAIL)
7483 if (!inst.error)
7484 inst.error = BAD_ARGS;
7485 return;
7488 if (skip_past_comma (&str) == FAIL)
7490 inst.error = _("address expected");
7491 return;
7494 if (*str == '[')
7496 int reg;
7498 str++;
7500 skip_whitespace (str);
7502 if ((reg = reg_required_here (&str, 16)) == FAIL)
7503 return;
7505 /* Conflicts can occur on stores as well as loads. */
7506 conflict_reg = (conflict_reg == reg);
7508 skip_whitespace (str);
7510 if (*str == ']')
7512 str ++;
7514 if (skip_past_comma (&str) == SUCCESS)
7516 /* [Rn],... (post inc) */
7517 if (ldst_extend (&str) == FAIL)
7518 return;
7519 if (conflict_reg)
7520 as_warn (_("%s register same as write-back base"),
7521 ((inst.instruction & LOAD_BIT)
7522 ? _("destination") : _("source")));
7524 else
7526 /* [Rn] */
7527 skip_whitespace (str);
7529 if (*str == '!')
7531 if (conflict_reg)
7532 as_warn (_("%s register same as write-back base"),
7533 ((inst.instruction & LOAD_BIT)
7534 ? _("destination") : _("source")));
7535 str++;
7536 inst.instruction |= WRITE_BACK;
7539 inst.instruction |= INDEX_UP;
7540 pre_inc = 1;
7543 else
7545 /* [Rn,...] */
7546 if (skip_past_comma (&str) == FAIL)
7548 inst.error = _("pre-indexed expression expected");
7549 return;
7552 pre_inc = 1;
7553 if (ldst_extend (&str) == FAIL)
7554 return;
7556 skip_whitespace (str);
7558 if (*str++ != ']')
7560 inst.error = _("missing ]");
7561 return;
7564 skip_whitespace (str);
7566 if (*str == '!')
7568 if (conflict_reg)
7569 as_warn (_("%s register same as write-back base"),
7570 ((inst.instruction & LOAD_BIT)
7571 ? _("destination") : _("source")));
7572 str++;
7573 inst.instruction |= WRITE_BACK;
7577 else if (*str == '=')
7579 if ((inst.instruction & LOAD_BIT) == 0)
7581 inst.error = _("invalid pseudo operation");
7582 return;
7585 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
7586 str++;
7588 skip_whitespace (str);
7590 if (my_get_expression (&inst.reloc.exp, &str))
7591 return;
7593 if (inst.reloc.exp.X_op != O_constant
7594 && inst.reloc.exp.X_op != O_symbol)
7596 inst.error = _("constant expression expected");
7597 return;
7600 if (inst.reloc.exp.X_op == O_constant)
7602 value = validate_immediate (inst.reloc.exp.X_add_number);
7604 if (value != FAIL)
7606 /* This can be done with a mov instruction. */
7607 inst.instruction &= LITERAL_MASK;
7608 inst.instruction |= (INST_IMMEDIATE
7609 | (OPCODE_MOV << DATA_OP_SHIFT));
7610 inst.instruction |= value & 0xfff;
7611 end_of_line (str);
7612 return;
7615 value = validate_immediate (~inst.reloc.exp.X_add_number);
7617 if (value != FAIL)
7619 /* This can be done with a mvn instruction. */
7620 inst.instruction &= LITERAL_MASK;
7621 inst.instruction |= (INST_IMMEDIATE
7622 | (OPCODE_MVN << DATA_OP_SHIFT));
7623 inst.instruction |= value & 0xfff;
7624 end_of_line (str);
7625 return;
7629 /* Insert into literal pool. */
7630 if (add_to_lit_pool () == FAIL)
7632 if (!inst.error)
7633 inst.error = _("literal pool insertion failed");
7634 return;
7637 /* Change the instruction exp to point to the pool. */
7638 inst.reloc.type = BFD_RELOC_ARM_LITERAL;
7639 inst.reloc.pc_rel = 1;
7640 inst.instruction |= (REG_PC << 16);
7641 pre_inc = 1;
7643 else
7645 if (my_get_expression (&inst.reloc.exp, &str))
7646 return;
7648 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
7649 #ifndef TE_WINCE
7650 /* PC rel adjust. */
7651 inst.reloc.exp.X_add_number -= 8;
7652 #endif
7653 inst.reloc.pc_rel = 1;
7654 inst.instruction |= (REG_PC << 16);
7655 pre_inc = 1;
7658 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
7659 end_of_line (str);
7660 return;
7663 static void
7664 do_ldstt (str)
7665 char * str;
7667 int conflict_reg;
7669 skip_whitespace (str);
7671 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
7673 if (!inst.error)
7674 inst.error = BAD_ARGS;
7675 return;
7678 if (skip_past_comma (& str) == FAIL)
7680 inst.error = _("address expected");
7681 return;
7684 if (*str == '[')
7686 int reg;
7688 str++;
7690 skip_whitespace (str);
7692 if ((reg = reg_required_here (&str, 16)) == FAIL)
7693 return;
7695 /* ldrt/strt always use post-indexed addressing, so if the base is
7696 the same as Rd, we warn. */
7697 if (conflict_reg == reg)
7698 as_warn (_("%s register same as write-back base"),
7699 ((inst.instruction & LOAD_BIT)
7700 ? _("destination") : _("source")));
7702 skip_whitespace (str);
7704 if (*str == ']')
7706 str ++;
7708 if (skip_past_comma (&str) == SUCCESS)
7710 /* [Rn],... (post inc) */
7711 if (ldst_extend (&str) == FAIL)
7712 return;
7714 else
7716 /* [Rn] */
7717 skip_whitespace (str);
7719 /* Skip a write-back '!'. */
7720 if (*str == '!')
7721 str++;
7723 inst.instruction |= INDEX_UP;
7726 else
7728 inst.error = _("post-indexed expression expected");
7729 return;
7732 else
7734 inst.error = _("post-indexed expression expected");
7735 return;
7738 end_of_line (str);
7739 return;
7742 static int
7743 ldst_extend_v4 (str)
7744 char ** str;
7746 int add = INDEX_UP;
7748 switch (**str)
7750 case '#':
7751 case '$':
7752 (*str)++;
7753 if (my_get_expression (& inst.reloc.exp, str))
7754 return FAIL;
7756 if (inst.reloc.exp.X_op == O_constant)
7758 int value = inst.reloc.exp.X_add_number;
7760 if (value < -255 || value > 255)
7762 inst.error = _("address offset too large");
7763 return FAIL;
7766 if (value < 0)
7768 value = -value;
7769 add = 0;
7772 /* Halfword and signextension instructions have the
7773 immediate value split across bits 11..8 and bits 3..0. */
7774 inst.instruction |= (add | HWOFFSET_IMM
7775 | ((value >> 4) << 8) | (value & 0xF));
7777 else
7779 inst.instruction |= HWOFFSET_IMM;
7780 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
7781 inst.reloc.pc_rel = 0;
7783 return SUCCESS;
7785 case '-':
7786 add = 0;
7787 /* Fall through. */
7789 case '+':
7790 (*str)++;
7791 /* Fall through. */
7793 default:
7794 if (reg_required_here (str, 0) == FAIL)
7795 return FAIL;
7797 inst.instruction |= add;
7798 return SUCCESS;
7802 /* Halfword and signed-byte load/store operations. */
7803 static void
7804 do_ldstv4 (str)
7805 char * str;
7807 int pre_inc = 0;
7808 int conflict_reg;
7809 int value;
7811 skip_whitespace (str);
7813 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
7815 if (!inst.error)
7816 inst.error = BAD_ARGS;
7817 return;
7820 if (skip_past_comma (& str) == FAIL)
7822 inst.error = _("address expected");
7823 return;
7826 if (*str == '[')
7828 int reg;
7830 str++;
7832 skip_whitespace (str);
7834 if ((reg = reg_required_here (&str, 16)) == FAIL)
7835 return;
7837 /* Conflicts can occur on stores as well as loads. */
7838 conflict_reg = (conflict_reg == reg);
7840 skip_whitespace (str);
7842 if (*str == ']')
7844 str ++;
7846 if (skip_past_comma (&str) == SUCCESS)
7848 /* [Rn],... (post inc) */
7849 if (ldst_extend_v4 (&str) == FAIL)
7850 return;
7851 if (conflict_reg)
7852 as_warn (_("%s register same as write-back base"),
7853 ((inst.instruction & LOAD_BIT)
7854 ? _("destination") : _("source")));
7856 else
7858 /* [Rn] */
7859 inst.instruction |= HWOFFSET_IMM;
7861 skip_whitespace (str);
7863 if (*str == '!')
7865 if (conflict_reg)
7866 as_warn (_("%s register same as write-back base"),
7867 ((inst.instruction & LOAD_BIT)
7868 ? _("destination") : _("source")));
7869 str++;
7870 inst.instruction |= WRITE_BACK;
7873 inst.instruction |= INDEX_UP;
7874 pre_inc = 1;
7877 else
7879 /* [Rn,...] */
7880 if (skip_past_comma (&str) == FAIL)
7882 inst.error = _("pre-indexed expression expected");
7883 return;
7886 pre_inc = 1;
7887 if (ldst_extend_v4 (&str) == FAIL)
7888 return;
7890 skip_whitespace (str);
7892 if (*str++ != ']')
7894 inst.error = _("missing ]");
7895 return;
7898 skip_whitespace (str);
7900 if (*str == '!')
7902 if (conflict_reg)
7903 as_warn (_("%s register same as write-back base"),
7904 ((inst.instruction & LOAD_BIT)
7905 ? _("destination") : _("source")));
7906 str++;
7907 inst.instruction |= WRITE_BACK;
7911 else if (*str == '=')
7913 if ((inst.instruction & LOAD_BIT) == 0)
7915 inst.error = _("invalid pseudo operation");
7916 return;
7919 /* XXX Does this work correctly for half-word/byte ops? */
7920 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
7921 str++;
7923 skip_whitespace (str);
7925 if (my_get_expression (&inst.reloc.exp, &str))
7926 return;
7928 if (inst.reloc.exp.X_op != O_constant
7929 && inst.reloc.exp.X_op != O_symbol)
7931 inst.error = _("constant expression expected");
7932 return;
7935 if (inst.reloc.exp.X_op == O_constant)
7937 value = validate_immediate (inst.reloc.exp.X_add_number);
7939 if (value != FAIL)
7941 /* This can be done with a mov instruction. */
7942 inst.instruction &= LITERAL_MASK;
7943 inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
7944 inst.instruction |= value & 0xfff;
7945 end_of_line (str);
7946 return;
7949 value = validate_immediate (~ inst.reloc.exp.X_add_number);
7951 if (value != FAIL)
7953 /* This can be done with a mvn instruction. */
7954 inst.instruction &= LITERAL_MASK;
7955 inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT);
7956 inst.instruction |= value & 0xfff;
7957 end_of_line (str);
7958 return;
7962 /* Insert into literal pool. */
7963 if (add_to_lit_pool () == FAIL)
7965 if (!inst.error)
7966 inst.error = _("literal pool insertion failed");
7967 return;
7970 /* Change the instruction exp to point to the pool. */
7971 inst.instruction |= HWOFFSET_IMM;
7972 inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
7973 inst.reloc.pc_rel = 1;
7974 inst.instruction |= (REG_PC << 16);
7975 pre_inc = 1;
7977 else
7979 if (my_get_expression (&inst.reloc.exp, &str))
7980 return;
7982 inst.instruction |= HWOFFSET_IMM;
7983 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
7984 #ifndef TE_WINCE
7985 /* PC rel adjust. */
7986 inst.reloc.exp.X_add_number -= 8;
7987 #endif
7988 inst.reloc.pc_rel = 1;
7989 inst.instruction |= (REG_PC << 16);
7990 pre_inc = 1;
7993 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
7994 end_of_line (str);
7995 return;
7998 static long
7999 reg_list (strp)
8000 char ** strp;
8002 char * str = * strp;
8003 long range = 0;
8004 int another_range;
8006 /* We come back here if we get ranges concatenated by '+' or '|'. */
8009 another_range = 0;
8011 if (*str == '{')
8013 int in_range = 0;
8014 int cur_reg = -1;
8016 str++;
8019 int reg;
8021 skip_whitespace (str);
8023 if ((reg = reg_required_here (& str, -1)) == FAIL)
8024 return FAIL;
8026 if (in_range)
8028 int i;
8030 if (reg <= cur_reg)
8032 inst.error = _("bad range in register list");
8033 return FAIL;
8036 for (i = cur_reg + 1; i < reg; i++)
8038 if (range & (1 << i))
8039 as_tsktsk
8040 (_("Warning: duplicated register (r%d) in register list"),
8042 else
8043 range |= 1 << i;
8045 in_range = 0;
8048 if (range & (1 << reg))
8049 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
8050 reg);
8051 else if (reg <= cur_reg)
8052 as_tsktsk (_("Warning: register range not in ascending order"));
8054 range |= 1 << reg;
8055 cur_reg = reg;
8057 while (skip_past_comma (&str) != FAIL
8058 || (in_range = 1, *str++ == '-'));
8059 str--;
8060 skip_whitespace (str);
8062 if (*str++ != '}')
8064 inst.error = _("missing `}'");
8065 return FAIL;
8068 else
8070 expressionS expr;
8072 if (my_get_expression (&expr, &str))
8073 return FAIL;
8075 if (expr.X_op == O_constant)
8077 if (expr.X_add_number
8078 != (expr.X_add_number & 0x0000ffff))
8080 inst.error = _("invalid register mask");
8081 return FAIL;
8084 if ((range & expr.X_add_number) != 0)
8086 int regno = range & expr.X_add_number;
8088 regno &= -regno;
8089 regno = (1 << regno) - 1;
8090 as_tsktsk
8091 (_("Warning: duplicated register (r%d) in register list"),
8092 regno);
8095 range |= expr.X_add_number;
8097 else
8099 if (inst.reloc.type != 0)
8101 inst.error = _("expression too complex");
8102 return FAIL;
8105 memcpy (&inst.reloc.exp, &expr, sizeof (expressionS));
8106 inst.reloc.type = BFD_RELOC_ARM_MULTI;
8107 inst.reloc.pc_rel = 0;
8111 skip_whitespace (str);
8113 if (*str == '|' || *str == '+')
8115 str++;
8116 another_range = 1;
8119 while (another_range);
8121 *strp = str;
8122 return range;
8125 static void
8126 do_ldmstm (str)
8127 char * str;
8129 int base_reg;
8130 long range;
8132 skip_whitespace (str);
8134 if ((base_reg = reg_required_here (&str, 16)) == FAIL)
8135 return;
8137 if (base_reg == REG_PC)
8139 inst.error = _("r15 not allowed as base register");
8140 return;
8143 skip_whitespace (str);
8145 if (*str == '!')
8147 inst.instruction |= WRITE_BACK;
8148 str++;
8151 if (skip_past_comma (&str) == FAIL
8152 || (range = reg_list (&str)) == FAIL)
8154 if (! inst.error)
8155 inst.error = BAD_ARGS;
8156 return;
8159 if (*str == '^')
8161 str++;
8162 inst.instruction |= LDM_TYPE_2_OR_3;
8165 if (inst.instruction & WRITE_BACK)
8167 /* Check for unpredictable uses of writeback. */
8168 if (inst.instruction & LOAD_BIT)
8170 /* Not allowed in LDM type 2. */
8171 if ((inst.instruction & LDM_TYPE_2_OR_3)
8172 && ((range & (1 << REG_PC)) == 0))
8173 as_warn (_("writeback of base register is UNPREDICTABLE"));
8174 /* Only allowed if base reg not in list for other types. */
8175 else if (range & (1 << base_reg))
8176 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
8178 else /* STM. */
8180 /* Not allowed for type 2. */
8181 if (inst.instruction & LDM_TYPE_2_OR_3)
8182 as_warn (_("writeback of base register is UNPREDICTABLE"));
8183 /* Only allowed if base reg not in list, or first in list. */
8184 else if ((range & (1 << base_reg))
8185 && (range & ((1 << base_reg) - 1)))
8186 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
8190 inst.instruction |= range;
8191 end_of_line (str);
8192 return;
8195 static void
8196 do_swi (str)
8197 char * str;
8199 skip_whitespace (str);
8201 /* Allow optional leading '#'. */
8202 if (is_immediate_prefix (*str))
8203 str++;
8205 if (my_get_expression (& inst.reloc.exp, & str))
8206 return;
8208 inst.reloc.type = BFD_RELOC_ARM_SWI;
8209 inst.reloc.pc_rel = 0;
8210 end_of_line (str);
8212 return;
8215 static void
8216 do_swap (str)
8217 char * str;
8219 int reg;
8221 skip_whitespace (str);
8223 if ((reg = reg_required_here (&str, 12)) == FAIL)
8224 return;
8226 if (reg == REG_PC)
8228 inst.error = _("r15 not allowed in swap");
8229 return;
8232 if (skip_past_comma (&str) == FAIL
8233 || (reg = reg_required_here (&str, 0)) == FAIL)
8235 if (!inst.error)
8236 inst.error = BAD_ARGS;
8237 return;
8240 if (reg == REG_PC)
8242 inst.error = _("r15 not allowed in swap");
8243 return;
8246 if (skip_past_comma (&str) == FAIL
8247 || *str++ != '[')
8249 inst.error = BAD_ARGS;
8250 return;
8253 skip_whitespace (str);
8255 if ((reg = reg_required_here (&str, 16)) == FAIL)
8256 return;
8258 if (reg == REG_PC)
8260 inst.error = BAD_PC;
8261 return;
8264 skip_whitespace (str);
8266 if (*str++ != ']')
8268 inst.error = _("missing ]");
8269 return;
8272 end_of_line (str);
8273 return;
8276 static void
8277 do_branch (str)
8278 char * str;
8280 if (my_get_expression (&inst.reloc.exp, &str))
8281 return;
8283 #ifdef OBJ_ELF
8285 char * save_in;
8287 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
8288 required for the instruction. */
8290 /* arm_parse_reloc () works on input_line_pointer.
8291 We actually want to parse the operands to the branch instruction
8292 passed in 'str'. Save the input pointer and restore it later. */
8293 save_in = input_line_pointer;
8294 input_line_pointer = str;
8295 if (inst.reloc.exp.X_op == O_symbol
8296 && *str == '('
8297 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
8299 inst.reloc.type = BFD_RELOC_ARM_PLT32;
8300 inst.reloc.pc_rel = 0;
8301 /* Modify str to point to after parsed operands, otherwise
8302 end_of_line() will complain about the (PLT) left in str. */
8303 str = input_line_pointer;
8305 else
8307 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
8308 inst.reloc.pc_rel = 1;
8310 input_line_pointer = save_in;
8312 #else
8313 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
8314 inst.reloc.pc_rel = 1;
8315 #endif /* OBJ_ELF */
8317 end_of_line (str);
8318 return;
8321 static void
8322 do_bx (str)
8323 char * str;
8325 int reg;
8327 skip_whitespace (str);
8329 if ((reg = reg_required_here (&str, 0)) == FAIL)
8331 inst.error = BAD_ARGS;
8332 return;
8335 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
8336 if (reg == REG_PC)
8337 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
8339 end_of_line (str);
8342 static void
8343 do_cdp (str)
8344 char * str;
8346 /* Co-processor data operation.
8347 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
8348 skip_whitespace (str);
8350 if (co_proc_number (&str) == FAIL)
8352 if (!inst.error)
8353 inst.error = BAD_ARGS;
8354 return;
8357 if (skip_past_comma (&str) == FAIL
8358 || cp_opc_expr (&str, 20,4) == FAIL)
8360 if (!inst.error)
8361 inst.error = BAD_ARGS;
8362 return;
8365 if (skip_past_comma (&str) == FAIL
8366 || cp_reg_required_here (&str, 12) == FAIL)
8368 if (!inst.error)
8369 inst.error = BAD_ARGS;
8370 return;
8373 if (skip_past_comma (&str) == FAIL
8374 || cp_reg_required_here (&str, 16) == FAIL)
8376 if (!inst.error)
8377 inst.error = BAD_ARGS;
8378 return;
8381 if (skip_past_comma (&str) == FAIL
8382 || cp_reg_required_here (&str, 0) == FAIL)
8384 if (!inst.error)
8385 inst.error = BAD_ARGS;
8386 return;
8389 if (skip_past_comma (&str) == SUCCESS)
8391 if (cp_opc_expr (&str, 5, 3) == FAIL)
8393 if (!inst.error)
8394 inst.error = BAD_ARGS;
8395 return;
8399 end_of_line (str);
8400 return;
8403 static void
8404 do_lstc (str)
8405 char * str;
8407 /* Co-processor register load/store.
8408 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
8410 skip_whitespace (str);
8412 if (co_proc_number (&str) == FAIL)
8414 if (!inst.error)
8415 inst.error = BAD_ARGS;
8416 return;
8419 if (skip_past_comma (&str) == FAIL
8420 || cp_reg_required_here (&str, 12) == FAIL)
8422 if (!inst.error)
8423 inst.error = BAD_ARGS;
8424 return;
8427 if (skip_past_comma (&str) == FAIL
8428 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
8430 if (! inst.error)
8431 inst.error = BAD_ARGS;
8432 return;
8435 end_of_line (str);
8436 return;
8439 static void
8440 do_co_reg (str)
8441 char * str;
8443 /* Co-processor register transfer.
8444 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
8446 skip_whitespace (str);
8448 if (co_proc_number (&str) == FAIL)
8450 if (!inst.error)
8451 inst.error = BAD_ARGS;
8452 return;
8455 if (skip_past_comma (&str) == FAIL
8456 || cp_opc_expr (&str, 21, 3) == FAIL)
8458 if (!inst.error)
8459 inst.error = BAD_ARGS;
8460 return;
8463 if (skip_past_comma (&str) == FAIL
8464 || reg_required_here (&str, 12) == FAIL)
8466 if (!inst.error)
8467 inst.error = BAD_ARGS;
8468 return;
8471 if (skip_past_comma (&str) == FAIL
8472 || cp_reg_required_here (&str, 16) == FAIL)
8474 if (!inst.error)
8475 inst.error = BAD_ARGS;
8476 return;
8479 if (skip_past_comma (&str) == FAIL
8480 || cp_reg_required_here (&str, 0) == FAIL)
8482 if (!inst.error)
8483 inst.error = BAD_ARGS;
8484 return;
8487 if (skip_past_comma (&str) == SUCCESS)
8489 if (cp_opc_expr (&str, 5, 3) == FAIL)
8491 if (!inst.error)
8492 inst.error = BAD_ARGS;
8493 return;
8497 end_of_line (str);
8498 return;
8501 static void
8502 do_fpa_ctrl (str)
8503 char * str;
8505 /* FP control registers.
8506 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
8508 skip_whitespace (str);
8510 if (reg_required_here (&str, 12) == FAIL)
8512 if (!inst.error)
8513 inst.error = BAD_ARGS;
8514 return;
8517 end_of_line (str);
8518 return;
8521 static void
8522 do_fpa_ldst (str)
8523 char * str;
8525 skip_whitespace (str);
8527 if (fp_reg_required_here (&str, 12) == FAIL)
8529 if (!inst.error)
8530 inst.error = BAD_ARGS;
8531 return;
8534 if (skip_past_comma (&str) == FAIL
8535 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
8537 if (!inst.error)
8538 inst.error = BAD_ARGS;
8539 return;
8542 end_of_line (str);
8545 static void
8546 do_fpa_ldmstm (str)
8547 char * str;
8549 int num_regs;
8551 skip_whitespace (str);
8553 if (fp_reg_required_here (&str, 12) == FAIL)
8555 if (! inst.error)
8556 inst.error = BAD_ARGS;
8557 return;
8560 /* Get Number of registers to transfer. */
8561 if (skip_past_comma (&str) == FAIL
8562 || my_get_expression (&inst.reloc.exp, &str))
8564 if (! inst.error)
8565 inst.error = _("constant expression expected");
8566 return;
8569 if (inst.reloc.exp.X_op != O_constant)
8571 inst.error = _("constant value required for number of registers");
8572 return;
8575 num_regs = inst.reloc.exp.X_add_number;
8577 if (num_regs < 1 || num_regs > 4)
8579 inst.error = _("number of registers must be in the range [1:4]");
8580 return;
8583 switch (num_regs)
8585 case 1:
8586 inst.instruction |= CP_T_X;
8587 break;
8588 case 2:
8589 inst.instruction |= CP_T_Y;
8590 break;
8591 case 3:
8592 inst.instruction |= CP_T_Y | CP_T_X;
8593 break;
8594 case 4:
8595 break;
8596 default:
8597 abort ();
8600 if (inst.instruction & (CP_T_Pre | CP_T_UD)) /* ea/fd format. */
8602 int reg;
8603 int write_back;
8604 int offset;
8606 /* The instruction specified "ea" or "fd", so we can only accept
8607 [Rn]{!}. The instruction does not really support stacking or
8608 unstacking, so we have to emulate these by setting appropriate
8609 bits and offsets. */
8610 if (skip_past_comma (&str) == FAIL
8611 || *str != '[')
8613 if (! inst.error)
8614 inst.error = BAD_ARGS;
8615 return;
8618 str++;
8619 skip_whitespace (str);
8621 if ((reg = reg_required_here (&str, 16)) == FAIL)
8622 return;
8624 skip_whitespace (str);
8626 if (*str != ']')
8628 inst.error = BAD_ARGS;
8629 return;
8632 str++;
8633 if (*str == '!')
8635 write_back = 1;
8636 str++;
8637 if (reg == REG_PC)
8639 inst.error =
8640 _("r15 not allowed as base register with write-back");
8641 return;
8644 else
8645 write_back = 0;
8647 if (inst.instruction & CP_T_Pre)
8649 /* Pre-decrement. */
8650 offset = 3 * num_regs;
8651 if (write_back)
8652 inst.instruction |= CP_T_WB;
8654 else
8656 /* Post-increment. */
8657 if (write_back)
8659 inst.instruction |= CP_T_WB;
8660 offset = 3 * num_regs;
8662 else
8664 /* No write-back, so convert this into a standard pre-increment
8665 instruction -- aesthetically more pleasing. */
8666 inst.instruction |= CP_T_Pre | CP_T_UD;
8667 offset = 0;
8671 inst.instruction |= offset;
8673 else if (skip_past_comma (&str) == FAIL
8674 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
8676 if (! inst.error)
8677 inst.error = BAD_ARGS;
8678 return;
8681 end_of_line (str);
8684 static void
8685 do_fpa_dyadic (str)
8686 char * str;
8688 skip_whitespace (str);
8690 if (fp_reg_required_here (&str, 12) == FAIL)
8692 if (! inst.error)
8693 inst.error = BAD_ARGS;
8694 return;
8697 if (skip_past_comma (&str) == FAIL
8698 || fp_reg_required_here (&str, 16) == FAIL)
8700 if (! inst.error)
8701 inst.error = BAD_ARGS;
8702 return;
8705 if (skip_past_comma (&str) == FAIL
8706 || fp_op2 (&str) == FAIL)
8708 if (! inst.error)
8709 inst.error = BAD_ARGS;
8710 return;
8713 end_of_line (str);
8714 return;
8717 static void
8718 do_fpa_monadic (str)
8719 char * str;
8721 skip_whitespace (str);
8723 if (fp_reg_required_here (&str, 12) == FAIL)
8725 if (! inst.error)
8726 inst.error = BAD_ARGS;
8727 return;
8730 if (skip_past_comma (&str) == FAIL
8731 || fp_op2 (&str) == FAIL)
8733 if (! inst.error)
8734 inst.error = BAD_ARGS;
8735 return;
8738 end_of_line (str);
8739 return;
8742 static void
8743 do_fpa_cmp (str)
8744 char * str;
8746 skip_whitespace (str);
8748 if (fp_reg_required_here (&str, 16) == FAIL)
8750 if (! inst.error)
8751 inst.error = BAD_ARGS;
8752 return;
8755 if (skip_past_comma (&str) == FAIL
8756 || fp_op2 (&str) == FAIL)
8758 if (! inst.error)
8759 inst.error = BAD_ARGS;
8760 return;
8763 end_of_line (str);
8764 return;
8767 static void
8768 do_fpa_from_reg (str)
8769 char * str;
8771 skip_whitespace (str);
8773 if (fp_reg_required_here (&str, 16) == FAIL)
8775 if (! inst.error)
8776 inst.error = BAD_ARGS;
8777 return;
8780 if (skip_past_comma (&str) == FAIL
8781 || reg_required_here (&str, 12) == FAIL)
8783 if (! inst.error)
8784 inst.error = BAD_ARGS;
8785 return;
8788 end_of_line (str);
8789 return;
8792 static void
8793 do_fpa_to_reg (str)
8794 char * str;
8796 skip_whitespace (str);
8798 if (reg_required_here (&str, 12) == FAIL)
8799 return;
8801 if (skip_past_comma (&str) == FAIL
8802 || fp_reg_required_here (&str, 0) == FAIL)
8804 if (! inst.error)
8805 inst.error = BAD_ARGS;
8806 return;
8809 end_of_line (str);
8810 return;
8813 static int
8814 vfp_sp_reg_required_here (str, pos)
8815 char **str;
8816 enum vfp_sp_reg_pos pos;
8818 int reg;
8819 char *start = *str;
8821 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab)) != FAIL)
8823 switch (pos)
8825 case VFP_REG_Sd:
8826 inst.instruction |= ((reg >> 1) << 12) | ((reg & 1) << 22);
8827 break;
8829 case VFP_REG_Sn:
8830 inst.instruction |= ((reg >> 1) << 16) | ((reg & 1) << 7);
8831 break;
8833 case VFP_REG_Sm:
8834 inst.instruction |= ((reg >> 1) << 0) | ((reg & 1) << 5);
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_SN].expected);
8847 /* Restore the start point. */
8848 *str = start;
8849 return FAIL;
8852 static int
8853 vfp_dp_reg_required_here (str, pos)
8854 char **str;
8855 enum vfp_dp_reg_pos pos;
8857 int reg;
8858 char *start = *str;
8860 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab)) != FAIL)
8862 switch (pos)
8864 case VFP_REG_Dd:
8865 inst.instruction |= reg << 12;
8866 break;
8868 case VFP_REG_Dn:
8869 inst.instruction |= reg << 16;
8870 break;
8872 case VFP_REG_Dm:
8873 inst.instruction |= reg << 0;
8874 break;
8876 default:
8877 abort ();
8879 return reg;
8882 /* In the few cases where we might be able to accept something else
8883 this error can be overridden. */
8884 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
8886 /* Restore the start point. */
8887 *str = start;
8888 return FAIL;
8891 static void
8892 do_vfp_sp_monadic (str)
8893 char *str;
8895 skip_whitespace (str);
8897 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8898 return;
8900 if (skip_past_comma (&str) == FAIL
8901 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
8903 if (! inst.error)
8904 inst.error = BAD_ARGS;
8905 return;
8908 end_of_line (str);
8909 return;
8912 static void
8913 do_vfp_dp_monadic (str)
8914 char *str;
8916 skip_whitespace (str);
8918 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8919 return;
8921 if (skip_past_comma (&str) == FAIL
8922 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8924 if (! inst.error)
8925 inst.error = BAD_ARGS;
8926 return;
8929 end_of_line (str);
8930 return;
8933 static void
8934 do_vfp_sp_dyadic (str)
8935 char *str;
8937 skip_whitespace (str);
8939 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8940 return;
8942 if (skip_past_comma (&str) == FAIL
8943 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL
8944 || skip_past_comma (&str) == FAIL
8945 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
8947 if (! inst.error)
8948 inst.error = BAD_ARGS;
8949 return;
8952 end_of_line (str);
8953 return;
8956 static void
8957 do_vfp_dp_dyadic (str)
8958 char *str;
8960 skip_whitespace (str);
8962 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8963 return;
8965 if (skip_past_comma (&str) == FAIL
8966 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL
8967 || skip_past_comma (&str) == FAIL
8968 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8970 if (! inst.error)
8971 inst.error = BAD_ARGS;
8972 return;
8975 end_of_line (str);
8976 return;
8979 static void
8980 do_vfp_reg_from_sp (str)
8981 char *str;
8983 skip_whitespace (str);
8985 if (reg_required_here (&str, 12) == FAIL)
8986 return;
8988 if (skip_past_comma (&str) == FAIL
8989 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
8991 if (! inst.error)
8992 inst.error = BAD_ARGS;
8993 return;
8996 end_of_line (str);
8997 return;
9000 static void
9001 do_vfp_sp_reg2 (str)
9002 char *str;
9004 skip_whitespace (str);
9006 if (reg_required_here (&str, 12) == FAIL)
9007 return;
9009 if (skip_past_comma (&str) == FAIL
9010 || reg_required_here (&str, 16) == FAIL
9011 || skip_past_comma (&str) == FAIL)
9013 if (! inst.error)
9014 inst.error = BAD_ARGS;
9015 return;
9018 /* We require exactly two consecutive SP registers. */
9019 if (vfp_sp_reg_list (&str, VFP_REG_Sm) != 2)
9021 if (! inst.error)
9022 inst.error = _("only two consecutive VFP SP registers allowed here");
9025 end_of_line (str);
9026 return;
9029 static void
9030 do_vfp_sp_from_reg (str)
9031 char *str;
9033 skip_whitespace (str);
9035 if (vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
9036 return;
9038 if (skip_past_comma (&str) == FAIL
9039 || reg_required_here (&str, 12) == FAIL)
9041 if (! inst.error)
9042 inst.error = BAD_ARGS;
9043 return;
9046 end_of_line (str);
9047 return;
9050 static void
9051 do_vfp_reg_from_dp (str)
9052 char *str;
9054 skip_whitespace (str);
9056 if (reg_required_here (&str, 12) == FAIL)
9057 return;
9059 if (skip_past_comma (&str) == FAIL
9060 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
9062 if (! inst.error)
9063 inst.error = BAD_ARGS;
9064 return;
9067 end_of_line (str);
9068 return;
9071 static void
9072 do_vfp_reg2_from_dp (str)
9073 char *str;
9075 skip_whitespace (str);
9077 if (reg_required_here (&str, 12) == FAIL)
9078 return;
9080 if (skip_past_comma (&str) == FAIL
9081 || reg_required_here (&str, 16) == FAIL
9082 || skip_past_comma (&str) == FAIL
9083 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
9085 if (! inst.error)
9086 inst.error = BAD_ARGS;
9087 return;
9090 end_of_line (str);
9091 return;
9094 static void
9095 do_vfp_dp_from_reg (str)
9096 char *str;
9098 skip_whitespace (str);
9100 if (vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
9101 return;
9103 if (skip_past_comma (&str) == FAIL
9104 || reg_required_here (&str, 12) == FAIL)
9106 if (! inst.error)
9107 inst.error = BAD_ARGS;
9108 return;
9111 end_of_line (str);
9112 return;
9115 static void
9116 do_vfp_dp_from_reg2 (str)
9117 char *str;
9119 skip_whitespace (str);
9121 if (vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
9122 return;
9124 if (skip_past_comma (&str) == FAIL
9125 || reg_required_here (&str, 12) == FAIL
9126 || skip_past_comma (&str) == FAIL
9127 || reg_required_here (&str, 16))
9129 if (! inst.error)
9130 inst.error = BAD_ARGS;
9131 return;
9134 end_of_line (str);
9135 return;
9138 static const struct vfp_reg *
9139 vfp_psr_parse (str)
9140 char **str;
9142 char *start = *str;
9143 char c;
9144 char *p;
9145 const struct vfp_reg *vreg;
9147 p = start;
9149 /* Find the end of the current token. */
9152 c = *p++;
9154 while (ISALPHA (c));
9156 /* Mark it. */
9157 *--p = 0;
9159 for (vreg = vfp_regs + 0;
9160 vreg < vfp_regs + sizeof (vfp_regs) / sizeof (struct vfp_reg);
9161 vreg++)
9163 if (strcmp (start, vreg->name) == 0)
9165 *p = c;
9166 *str = p;
9167 return vreg;
9171 *p = c;
9172 return NULL;
9175 static int
9176 vfp_psr_required_here (str)
9177 char **str;
9179 char *start = *str;
9180 const struct vfp_reg *vreg;
9182 vreg = vfp_psr_parse (str);
9184 if (vreg)
9186 inst.instruction |= vreg->regno;
9187 return SUCCESS;
9190 inst.error = _("VFP system register expected");
9192 *str = start;
9193 return FAIL;
9196 static void
9197 do_vfp_reg_from_ctrl (str)
9198 char *str;
9200 skip_whitespace (str);
9202 if (reg_required_here (&str, 12) == FAIL)
9203 return;
9205 if (skip_past_comma (&str) == FAIL
9206 || vfp_psr_required_here (&str) == FAIL)
9208 if (! inst.error)
9209 inst.error = BAD_ARGS;
9210 return;
9213 end_of_line (str);
9214 return;
9217 static void
9218 do_vfp_ctrl_from_reg (str)
9219 char *str;
9221 skip_whitespace (str);
9223 if (vfp_psr_required_here (&str) == FAIL)
9224 return;
9226 if (skip_past_comma (&str) == FAIL
9227 || reg_required_here (&str, 12) == FAIL)
9229 if (! inst.error)
9230 inst.error = BAD_ARGS;
9231 return;
9234 end_of_line (str);
9235 return;
9238 static void
9239 do_vfp_sp_ldst (str)
9240 char *str;
9242 skip_whitespace (str);
9244 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
9246 if (!inst.error)
9247 inst.error = BAD_ARGS;
9248 return;
9251 if (skip_past_comma (&str) == FAIL
9252 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
9254 if (!inst.error)
9255 inst.error = BAD_ARGS;
9256 return;
9259 end_of_line (str);
9260 return;
9263 static void
9264 do_vfp_dp_ldst (str)
9265 char *str;
9267 skip_whitespace (str);
9269 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
9271 if (!inst.error)
9272 inst.error = BAD_ARGS;
9273 return;
9276 if (skip_past_comma (&str) == FAIL
9277 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
9279 if (!inst.error)
9280 inst.error = BAD_ARGS;
9281 return;
9284 end_of_line (str);
9285 return;
9288 /* Parse and encode a VFP SP register list, storing the initial
9289 register in position POS and returning the range as the result. If
9290 the string is invalid return FAIL (an invalid range). */
9291 static long
9292 vfp_sp_reg_list (str, pos)
9293 char **str;
9294 enum vfp_sp_reg_pos pos;
9296 long range = 0;
9297 int base_reg = 0;
9298 int new_base;
9299 long base_bits = 0;
9300 int count = 0;
9301 long tempinst;
9302 unsigned long mask = 0;
9303 int warned = 0;
9305 if (**str != '{')
9306 return FAIL;
9308 (*str)++;
9309 skip_whitespace (*str);
9311 tempinst = inst.instruction;
9315 inst.instruction = 0;
9317 if ((new_base = vfp_sp_reg_required_here (str, pos)) == FAIL)
9318 return FAIL;
9320 if (count == 0 || base_reg > new_base)
9322 base_reg = new_base;
9323 base_bits = inst.instruction;
9326 if (mask & (1 << new_base))
9328 inst.error = _("invalid register list");
9329 return FAIL;
9332 if ((mask >> new_base) != 0 && ! warned)
9334 as_tsktsk (_("register list not in ascending order"));
9335 warned = 1;
9338 mask |= 1 << new_base;
9339 count++;
9341 skip_whitespace (*str);
9343 if (**str == '-') /* We have the start of a range expression */
9345 int high_range;
9347 (*str)++;
9349 if ((high_range
9350 = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab))
9351 == FAIL)
9353 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
9354 return FAIL;
9357 if (high_range <= new_base)
9359 inst.error = _("register range not in ascending order");
9360 return FAIL;
9363 for (new_base++; new_base <= high_range; new_base++)
9365 if (mask & (1 << new_base))
9367 inst.error = _("invalid register list");
9368 return FAIL;
9371 mask |= 1 << new_base;
9372 count++;
9376 while (skip_past_comma (str) != FAIL);
9378 if (**str != '}')
9380 inst.error = _("invalid register list");
9381 return FAIL;
9384 (*str)++;
9386 range = count;
9388 /* Sanity check -- should have raised a parse error above. */
9389 if (count == 0 || count > 32)
9390 abort ();
9392 /* Final test -- the registers must be consecutive. */
9393 while (count--)
9395 if ((mask & (1 << base_reg++)) == 0)
9397 inst.error = _("non-contiguous register range");
9398 return FAIL;
9402 inst.instruction = tempinst | base_bits;
9403 return range;
9406 static long
9407 vfp_dp_reg_list (str)
9408 char **str;
9410 long range = 0;
9411 int base_reg = 0;
9412 int new_base;
9413 int count = 0;
9414 long tempinst;
9415 unsigned long mask = 0;
9416 int warned = 0;
9418 if (**str != '{')
9419 return FAIL;
9421 (*str)++;
9422 skip_whitespace (*str);
9424 tempinst = inst.instruction;
9428 inst.instruction = 0;
9430 if ((new_base = vfp_dp_reg_required_here (str, VFP_REG_Dd)) == FAIL)
9431 return FAIL;
9433 if (count == 0 || base_reg > new_base)
9435 base_reg = new_base;
9436 range = inst.instruction;
9439 if (mask & (1 << new_base))
9441 inst.error = _("invalid register list");
9442 return FAIL;
9445 if ((mask >> new_base) != 0 && ! warned)
9447 as_tsktsk (_("register list not in ascending order"));
9448 warned = 1;
9451 mask |= 1 << new_base;
9452 count++;
9454 skip_whitespace (*str);
9456 if (**str == '-') /* We have the start of a range expression */
9458 int high_range;
9460 (*str)++;
9462 if ((high_range
9463 = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab))
9464 == FAIL)
9466 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
9467 return FAIL;
9470 if (high_range <= new_base)
9472 inst.error = _("register range not in ascending order");
9473 return FAIL;
9476 for (new_base++; new_base <= high_range; new_base++)
9478 if (mask & (1 << new_base))
9480 inst.error = _("invalid register list");
9481 return FAIL;
9484 mask |= 1 << new_base;
9485 count++;
9489 while (skip_past_comma (str) != FAIL);
9491 if (**str != '}')
9493 inst.error = _("invalid register list");
9494 return FAIL;
9497 (*str)++;
9499 range |= 2 * count;
9501 /* Sanity check -- should have raised a parse error above. */
9502 if (count == 0 || count > 16)
9503 abort ();
9505 /* Final test -- the registers must be consecutive. */
9506 while (count--)
9508 if ((mask & (1 << base_reg++)) == 0)
9510 inst.error = _("non-contiguous register range");
9511 return FAIL;
9515 inst.instruction = tempinst;
9516 return range;
9519 static void
9520 vfp_sp_ldstm (str, ldstm_type)
9521 char *str;
9522 enum vfp_ldstm_type ldstm_type;
9524 long range;
9526 skip_whitespace (str);
9528 if (reg_required_here (&str, 16) == FAIL)
9529 return;
9531 skip_whitespace (str);
9533 if (*str == '!')
9535 inst.instruction |= WRITE_BACK;
9536 str++;
9538 else if (ldstm_type != VFP_LDSTMIA)
9540 inst.error = _("this addressing mode requires base-register writeback");
9541 return;
9544 if (skip_past_comma (&str) == FAIL
9545 || (range = vfp_sp_reg_list (&str, VFP_REG_Sd)) == FAIL)
9547 if (!inst.error)
9548 inst.error = BAD_ARGS;
9549 return;
9552 inst.instruction |= range;
9553 end_of_line (str);
9556 static void
9557 vfp_dp_ldstm (str, ldstm_type)
9558 char *str;
9559 enum vfp_ldstm_type ldstm_type;
9561 long range;
9563 skip_whitespace (str);
9565 if (reg_required_here (&str, 16) == FAIL)
9566 return;
9568 skip_whitespace (str);
9570 if (*str == '!')
9572 inst.instruction |= WRITE_BACK;
9573 str++;
9575 else if (ldstm_type != VFP_LDSTMIA && ldstm_type != VFP_LDSTMIAX)
9577 inst.error = _("this addressing mode requires base-register writeback");
9578 return;
9581 if (skip_past_comma (&str) == FAIL
9582 || (range = vfp_dp_reg_list (&str)) == FAIL)
9584 if (!inst.error)
9585 inst.error = BAD_ARGS;
9586 return;
9589 if (ldstm_type == VFP_LDSTMIAX || ldstm_type == VFP_LDSTMDBX)
9590 range += 1;
9592 inst.instruction |= range;
9593 end_of_line (str);
9596 static void
9597 do_vfp_sp_ldstmia (str)
9598 char *str;
9600 vfp_sp_ldstm (str, VFP_LDSTMIA);
9603 static void
9604 do_vfp_sp_ldstmdb (str)
9605 char *str;
9607 vfp_sp_ldstm (str, VFP_LDSTMDB);
9610 static void
9611 do_vfp_dp_ldstmia (str)
9612 char *str;
9614 vfp_dp_ldstm (str, VFP_LDSTMIA);
9617 static void
9618 do_vfp_dp_ldstmdb (str)
9619 char *str;
9621 vfp_dp_ldstm (str, VFP_LDSTMDB);
9624 static void
9625 do_vfp_xp_ldstmia (str)
9626 char *str;
9628 vfp_dp_ldstm (str, VFP_LDSTMIAX);
9631 static void
9632 do_vfp_xp_ldstmdb (str)
9633 char *str;
9635 vfp_dp_ldstm (str, VFP_LDSTMDBX);
9638 static void
9639 do_vfp_sp_compare_z (str)
9640 char *str;
9642 skip_whitespace (str);
9644 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
9646 if (!inst.error)
9647 inst.error = BAD_ARGS;
9648 return;
9651 end_of_line (str);
9652 return;
9655 static void
9656 do_vfp_dp_compare_z (str)
9657 char *str;
9659 skip_whitespace (str);
9661 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
9663 if (!inst.error)
9664 inst.error = BAD_ARGS;
9665 return;
9668 end_of_line (str);
9669 return;
9672 static void
9673 do_vfp_dp_sp_cvt (str)
9674 char *str;
9676 skip_whitespace (str);
9678 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
9679 return;
9681 if (skip_past_comma (&str) == FAIL
9682 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
9684 if (! inst.error)
9685 inst.error = BAD_ARGS;
9686 return;
9689 end_of_line (str);
9690 return;
9693 static void
9694 do_vfp_sp_dp_cvt (str)
9695 char *str;
9697 skip_whitespace (str);
9699 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
9700 return;
9702 if (skip_past_comma (&str) == FAIL
9703 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
9705 if (! inst.error)
9706 inst.error = BAD_ARGS;
9707 return;
9710 end_of_line (str);
9711 return;
9714 /* Thumb specific routines. */
9716 /* Parse and validate that a register is of the right form, this saves
9717 repeated checking of this information in many similar cases.
9718 Unlike the 32-bit case we do not insert the register into the opcode
9719 here, since the position is often unknown until the full instruction
9720 has been parsed. */
9722 static int
9723 thumb_reg (strp, hi_lo)
9724 char ** strp;
9725 int hi_lo;
9727 int reg;
9729 if ((reg = reg_required_here (strp, -1)) == FAIL)
9730 return FAIL;
9732 switch (hi_lo)
9734 case THUMB_REG_LO:
9735 if (reg > 7)
9737 inst.error = _("lo register required");
9738 return FAIL;
9740 break;
9742 case THUMB_REG_HI:
9743 if (reg < 8)
9745 inst.error = _("hi register required");
9746 return FAIL;
9748 break;
9750 default:
9751 break;
9754 return reg;
9757 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
9758 was SUB. */
9760 static void
9761 thumb_add_sub (str, subtract)
9762 char * str;
9763 int subtract;
9765 int Rd, Rs, Rn = FAIL;
9767 skip_whitespace (str);
9769 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
9770 || skip_past_comma (&str) == FAIL)
9772 if (! inst.error)
9773 inst.error = BAD_ARGS;
9774 return;
9777 if (is_immediate_prefix (*str))
9779 Rs = Rd;
9780 str++;
9781 if (my_get_expression (&inst.reloc.exp, &str))
9782 return;
9784 else
9786 if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9787 return;
9789 if (skip_past_comma (&str) == FAIL)
9791 /* Two operand format, shuffle the registers
9792 and pretend there are 3. */
9793 Rn = Rs;
9794 Rs = Rd;
9796 else if (is_immediate_prefix (*str))
9798 str++;
9799 if (my_get_expression (&inst.reloc.exp, &str))
9800 return;
9802 else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9803 return;
9806 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
9807 for the latter case, EXPR contains the immediate that was found. */
9808 if (Rn != FAIL)
9810 /* All register format. */
9811 if (Rd > 7 || Rs > 7 || Rn > 7)
9813 if (Rs != Rd)
9815 inst.error = _("dest and source1 must be the same register");
9816 return;
9819 /* Can't do this for SUB. */
9820 if (subtract)
9822 inst.error = _("subtract valid only on lo regs");
9823 return;
9826 inst.instruction = (T_OPCODE_ADD_HI
9827 | (Rd > 7 ? THUMB_H1 : 0)
9828 | (Rn > 7 ? THUMB_H2 : 0));
9829 inst.instruction |= (Rd & 7) | ((Rn & 7) << 3);
9831 else
9833 inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3;
9834 inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
9837 else
9839 /* Immediate expression, now things start to get nasty. */
9841 /* First deal with HI regs, only very restricted cases allowed:
9842 Adjusting SP, and using PC or SP to get an address. */
9843 if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP))
9844 || (Rs > 7 && Rs != REG_SP && Rs != REG_PC))
9846 inst.error = _("invalid Hi register with immediate");
9847 return;
9850 if (inst.reloc.exp.X_op != O_constant)
9852 /* Value isn't known yet, all we can do is store all the fragments
9853 we know about in the instruction and let the reloc hacking
9854 work it all out. */
9855 inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs;
9856 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
9858 else
9860 int offset = inst.reloc.exp.X_add_number;
9862 if (subtract)
9863 offset = - offset;
9865 if (offset < 0)
9867 offset = - offset;
9868 subtract = 1;
9870 /* Quick check, in case offset is MIN_INT. */
9871 if (offset < 0)
9873 inst.error = _("immediate value out of range");
9874 return;
9877 /* Note - you cannot convert a subtract of 0 into an
9878 add of 0 because the carry flag is set differently. */
9879 else if (offset > 0)
9880 subtract = 0;
9882 if (Rd == REG_SP)
9884 if (offset & ~0x1fc)
9886 inst.error = _("invalid immediate value for stack adjust");
9887 return;
9889 inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
9890 inst.instruction |= offset >> 2;
9892 else if (Rs == REG_PC || Rs == REG_SP)
9894 if (subtract
9895 || (offset & ~0x3fc))
9897 inst.error = _("invalid immediate for address calculation");
9898 return;
9900 inst.instruction = (Rs == REG_PC ? T_OPCODE_ADD_PC
9901 : T_OPCODE_ADD_SP);
9902 inst.instruction |= (Rd << 8) | (offset >> 2);
9904 else if (Rs == Rd)
9906 if (offset & ~0xff)
9908 inst.error = _("immediate value out of range");
9909 return;
9911 inst.instruction = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
9912 inst.instruction |= (Rd << 8) | offset;
9914 else
9916 if (offset & ~0x7)
9918 inst.error = _("immediate value out of range");
9919 return;
9921 inst.instruction = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
9922 inst.instruction |= Rd | (Rs << 3) | (offset << 6);
9927 end_of_line (str);
9930 static void
9931 thumb_shift (str, shift)
9932 char * str;
9933 int shift;
9935 int Rd, Rs, Rn = FAIL;
9937 skip_whitespace (str);
9939 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9940 || skip_past_comma (&str) == FAIL)
9942 if (! inst.error)
9943 inst.error = BAD_ARGS;
9944 return;
9947 if (is_immediate_prefix (*str))
9949 /* Two operand immediate format, set Rs to Rd. */
9950 Rs = Rd;
9951 str ++;
9952 if (my_get_expression (&inst.reloc.exp, &str))
9953 return;
9955 else
9957 if ((Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9958 return;
9960 if (skip_past_comma (&str) == FAIL)
9962 /* Two operand format, shuffle the registers
9963 and pretend there are 3. */
9964 Rn = Rs;
9965 Rs = Rd;
9967 else if (is_immediate_prefix (*str))
9969 str++;
9970 if (my_get_expression (&inst.reloc.exp, &str))
9971 return;
9973 else if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9974 return;
9977 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
9978 for the latter case, EXPR contains the immediate that was found. */
9980 if (Rn != FAIL)
9982 if (Rs != Rd)
9984 inst.error = _("source1 and dest must be same register");
9985 return;
9988 switch (shift)
9990 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_R; break;
9991 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_R; break;
9992 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_R; break;
9995 inst.instruction |= Rd | (Rn << 3);
9997 else
9999 switch (shift)
10001 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_I; break;
10002 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_I; break;
10003 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_I; break;
10006 if (inst.reloc.exp.X_op != O_constant)
10008 /* Value isn't known yet, create a dummy reloc and let reloc
10009 hacking fix it up. */
10010 inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
10012 else
10014 unsigned shift_value = inst.reloc.exp.X_add_number;
10016 if (shift_value > 32 || (shift_value == 32 && shift == THUMB_LSL))
10018 inst.error = _("invalid immediate for shift");
10019 return;
10022 /* Shifts of zero are handled by converting to LSL. */
10023 if (shift_value == 0)
10024 inst.instruction = T_OPCODE_LSL_I;
10026 /* Shifts of 32 are encoded as a shift of zero. */
10027 if (shift_value == 32)
10028 shift_value = 0;
10030 inst.instruction |= shift_value << 6;
10033 inst.instruction |= Rd | (Rs << 3);
10036 end_of_line (str);
10039 static void
10040 thumb_mov_compare (str, move)
10041 char * str;
10042 int move;
10044 int Rd, Rs = FAIL;
10046 skip_whitespace (str);
10048 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
10049 || skip_past_comma (&str) == FAIL)
10051 if (! inst.error)
10052 inst.error = BAD_ARGS;
10053 return;
10056 if (move != THUMB_CPY && is_immediate_prefix (*str))
10058 str++;
10059 if (my_get_expression (&inst.reloc.exp, &str))
10060 return;
10062 else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
10063 return;
10065 if (Rs != FAIL)
10067 if (move != THUMB_CPY && Rs < 8 && Rd < 8)
10069 if (move == THUMB_MOVE)
10070 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
10071 since a MOV instruction produces unpredictable results. */
10072 inst.instruction = T_OPCODE_ADD_I3;
10073 else
10074 inst.instruction = T_OPCODE_CMP_LR;
10075 inst.instruction |= Rd | (Rs << 3);
10077 else
10079 if (move == THUMB_MOVE)
10080 inst.instruction = T_OPCODE_MOV_HR;
10081 else if (move != THUMB_CPY)
10082 inst.instruction = T_OPCODE_CMP_HR;
10084 if (Rd > 7)
10085 inst.instruction |= THUMB_H1;
10087 if (Rs > 7)
10088 inst.instruction |= THUMB_H2;
10090 inst.instruction |= (Rd & 7) | ((Rs & 7) << 3);
10093 else
10095 if (Rd > 7)
10097 inst.error = _("only lo regs allowed with immediate");
10098 return;
10101 if (move == THUMB_MOVE)
10102 inst.instruction = T_OPCODE_MOV_I8;
10103 else
10104 inst.instruction = T_OPCODE_CMP_I8;
10106 inst.instruction |= Rd << 8;
10108 if (inst.reloc.exp.X_op != O_constant)
10109 inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
10110 else
10112 unsigned value = inst.reloc.exp.X_add_number;
10114 if (value > 255)
10116 inst.error = _("invalid immediate");
10117 return;
10120 inst.instruction |= value;
10124 end_of_line (str);
10127 static void
10128 thumb_load_store (str, load_store, size)
10129 char * str;
10130 int load_store;
10131 int size;
10133 int Rd, Rb, Ro = FAIL;
10135 skip_whitespace (str);
10137 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
10138 || skip_past_comma (&str) == FAIL)
10140 if (! inst.error)
10141 inst.error = BAD_ARGS;
10142 return;
10145 if (*str == '[')
10147 str++;
10148 if ((Rb = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
10149 return;
10151 if (skip_past_comma (&str) != FAIL)
10153 if (is_immediate_prefix (*str))
10155 str++;
10156 if (my_get_expression (&inst.reloc.exp, &str))
10157 return;
10159 else if ((Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
10160 return;
10162 else
10164 inst.reloc.exp.X_op = O_constant;
10165 inst.reloc.exp.X_add_number = 0;
10168 if (*str != ']')
10170 inst.error = _("expected ']'");
10171 return;
10173 str++;
10175 else if (*str == '=')
10177 if (load_store != THUMB_LOAD)
10179 inst.error = _("invalid pseudo operation");
10180 return;
10183 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
10184 str++;
10186 skip_whitespace (str);
10188 if (my_get_expression (& inst.reloc.exp, & str))
10189 return;
10191 end_of_line (str);
10193 if ( inst.reloc.exp.X_op != O_constant
10194 && inst.reloc.exp.X_op != O_symbol)
10196 inst.error = "Constant expression expected";
10197 return;
10200 if (inst.reloc.exp.X_op == O_constant
10201 && ((inst.reloc.exp.X_add_number & ~0xFF) == 0))
10203 /* This can be done with a mov instruction. */
10205 inst.instruction = T_OPCODE_MOV_I8 | (Rd << 8);
10206 inst.instruction |= inst.reloc.exp.X_add_number;
10207 return;
10210 /* Insert into literal pool. */
10211 if (add_to_lit_pool () == FAIL)
10213 if (!inst.error)
10214 inst.error = "literal pool insertion failed";
10215 return;
10218 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10219 inst.reloc.pc_rel = 1;
10220 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
10221 /* Adjust ARM pipeline offset to Thumb. */
10222 inst.reloc.exp.X_add_number += 4;
10224 return;
10226 else
10228 if (my_get_expression (&inst.reloc.exp, &str))
10229 return;
10231 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
10232 inst.reloc.pc_rel = 1;
10233 inst.reloc.exp.X_add_number -= 4; /* Pipeline offset. */
10234 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10235 end_of_line (str);
10236 return;
10239 if (Rb == REG_PC || Rb == REG_SP)
10241 if (size != THUMB_WORD)
10243 inst.error = _("byte or halfword not valid for base register");
10244 return;
10246 else if (Rb == REG_PC && load_store != THUMB_LOAD)
10248 inst.error = _("r15 based store not allowed");
10249 return;
10251 else if (Ro != FAIL)
10253 inst.error = _("invalid base register for register offset");
10254 return;
10257 if (Rb == REG_PC)
10258 inst.instruction = T_OPCODE_LDR_PC;
10259 else if (load_store == THUMB_LOAD)
10260 inst.instruction = T_OPCODE_LDR_SP;
10261 else
10262 inst.instruction = T_OPCODE_STR_SP;
10264 inst.instruction |= Rd << 8;
10265 if (inst.reloc.exp.X_op == O_constant)
10267 unsigned offset = inst.reloc.exp.X_add_number;
10269 if (offset & ~0x3fc)
10271 inst.error = _("invalid offset");
10272 return;
10275 inst.instruction |= offset >> 2;
10277 else
10278 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10280 else if (Rb > 7)
10282 inst.error = _("invalid base register in load/store");
10283 return;
10285 else if (Ro == FAIL)
10287 /* Immediate offset. */
10288 if (size == THUMB_WORD)
10289 inst.instruction = (load_store == THUMB_LOAD
10290 ? T_OPCODE_LDR_IW : T_OPCODE_STR_IW);
10291 else if (size == THUMB_HALFWORD)
10292 inst.instruction = (load_store == THUMB_LOAD
10293 ? T_OPCODE_LDR_IH : T_OPCODE_STR_IH);
10294 else
10295 inst.instruction = (load_store == THUMB_LOAD
10296 ? T_OPCODE_LDR_IB : T_OPCODE_STR_IB);
10298 inst.instruction |= Rd | (Rb << 3);
10300 if (inst.reloc.exp.X_op == O_constant)
10302 unsigned offset = inst.reloc.exp.X_add_number;
10304 if (offset & ~(0x1f << size))
10306 inst.error = _("invalid offset");
10307 return;
10309 inst.instruction |= (offset >> size) << 6;
10311 else
10312 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10314 else
10316 /* Register offset. */
10317 if (size == THUMB_WORD)
10318 inst.instruction = (load_store == THUMB_LOAD
10319 ? T_OPCODE_LDR_RW : T_OPCODE_STR_RW);
10320 else if (size == THUMB_HALFWORD)
10321 inst.instruction = (load_store == THUMB_LOAD
10322 ? T_OPCODE_LDR_RH : T_OPCODE_STR_RH);
10323 else
10324 inst.instruction = (load_store == THUMB_LOAD
10325 ? T_OPCODE_LDR_RB : T_OPCODE_STR_RB);
10327 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
10330 end_of_line (str);
10333 /* A register must be given at this point.
10335 Shift is the place to put it in inst.instruction.
10337 Restores input start point on err.
10338 Returns the reg#, or FAIL. */
10340 static int
10341 mav_reg_required_here (str, shift, regtype)
10342 char ** str;
10343 int shift;
10344 enum arm_reg_type regtype;
10346 int reg;
10347 char *start = *str;
10349 if ((reg = arm_reg_parse (str, all_reg_maps[regtype].htab)) != FAIL)
10351 if (shift >= 0)
10352 inst.instruction |= reg << shift;
10354 return reg;
10357 /* Restore the start point. */
10358 *str = start;
10360 /* In the few cases where we might be able to accept something else
10361 this error can be overridden. */
10362 inst.error = _(all_reg_maps[regtype].expected);
10364 return FAIL;
10367 /* Cirrus Maverick Instructions. */
10369 /* Wrapper functions. */
10371 static void
10372 do_mav_binops_1a (str)
10373 char * str;
10375 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVF);
10378 static void
10379 do_mav_binops_1b (str)
10380 char * str;
10382 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVD);
10385 static void
10386 do_mav_binops_1c (str)
10387 char * str;
10389 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVDX);
10392 static void
10393 do_mav_binops_1d (str)
10394 char * str;
10396 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVF);
10399 static void
10400 do_mav_binops_1e (str)
10401 char * str;
10403 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVD);
10406 static void
10407 do_mav_binops_1f (str)
10408 char * str;
10410 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVF);
10413 static void
10414 do_mav_binops_1g (str)
10415 char * str;
10417 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVD);
10420 static void
10421 do_mav_binops_1h (str)
10422 char * str;
10424 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVFX);
10427 static void
10428 do_mav_binops_1i (str)
10429 char * str;
10431 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVFX);
10434 static void
10435 do_mav_binops_1j (str)
10436 char * str;
10438 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVDX);
10441 static void
10442 do_mav_binops_1k (str)
10443 char * str;
10445 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVDX);
10448 static void
10449 do_mav_binops_1l (str)
10450 char * str;
10452 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVF);
10455 static void
10456 do_mav_binops_1m (str)
10457 char * str;
10459 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVD);
10462 static void
10463 do_mav_binops_1n (str)
10464 char * str;
10466 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVFX);
10469 static void
10470 do_mav_binops_1o (str)
10471 char * str;
10473 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVDX, REG_TYPE_MVDX);
10476 static void
10477 do_mav_binops_2a (str)
10478 char * str;
10480 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVF, REG_TYPE_RN);
10483 static void
10484 do_mav_binops_2b (str)
10485 char * str;
10487 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVD, REG_TYPE_RN);
10490 static void
10491 do_mav_binops_2c (str)
10492 char * str;
10494 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVDX, REG_TYPE_RN);
10497 static void
10498 do_mav_binops_3a (str)
10499 char * str;
10501 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVFX);
10504 static void
10505 do_mav_binops_3b (str)
10506 char * str;
10508 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVFX, REG_TYPE_MVAX);
10511 static void
10512 do_mav_binops_3c (str)
10513 char * str;
10515 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVDX);
10518 static void
10519 do_mav_binops_3d (str)
10520 char * str;
10522 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVDX, REG_TYPE_MVAX);
10525 static void
10526 do_mav_triple_4a (str)
10527 char * str;
10529 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_RN);
10532 static void
10533 do_mav_triple_4b (str)
10534 char * str;
10536 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_RN);
10539 static void
10540 do_mav_triple_5a (str)
10541 char * str;
10543 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVF, REG_TYPE_MVF);
10546 static void
10547 do_mav_triple_5b (str)
10548 char * str;
10550 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVD, REG_TYPE_MVD);
10553 static void
10554 do_mav_triple_5c (str)
10555 char * str;
10557 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVFX, REG_TYPE_MVFX);
10560 static void
10561 do_mav_triple_5d (str)
10562 char * str;
10564 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVDX, REG_TYPE_MVDX);
10567 static void
10568 do_mav_triple_5e (str)
10569 char * str;
10571 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVF, REG_TYPE_MVF, REG_TYPE_MVF);
10574 static void
10575 do_mav_triple_5f (str)
10576 char * str;
10578 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVD, REG_TYPE_MVD, REG_TYPE_MVD);
10581 static void
10582 do_mav_triple_5g (str)
10583 char * str;
10585 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_MVFX);
10588 static void
10589 do_mav_triple_5h (str)
10590 char * str;
10592 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_MVDX);
10595 static void
10596 do_mav_quad_6a (str)
10597 char * str;
10599 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVFX, REG_TYPE_MVFX,
10600 REG_TYPE_MVFX);
10603 static void
10604 do_mav_quad_6b (str)
10605 char * str;
10607 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVAX, REG_TYPE_MVFX,
10608 REG_TYPE_MVFX);
10611 /* cfmvsc32<cond> DSPSC,MVFX[15:0]. */
10612 static void
10613 do_mav_dspsc_1 (str)
10614 char * str;
10616 skip_whitespace (str);
10618 /* cfmvsc32. */
10619 if (mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL
10620 || skip_past_comma (&str) == FAIL
10621 || mav_reg_required_here (&str, 16, REG_TYPE_MVFX) == FAIL)
10623 if (!inst.error)
10624 inst.error = BAD_ARGS;
10626 return;
10629 end_of_line (str);
10632 /* cfmv32sc<cond> MVFX[15:0],DSPSC. */
10633 static void
10634 do_mav_dspsc_2 (str)
10635 char * str;
10637 skip_whitespace (str);
10639 /* cfmv32sc. */
10640 if (mav_reg_required_here (&str, 0, REG_TYPE_MVFX) == FAIL
10641 || skip_past_comma (&str) == FAIL
10642 || mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL)
10644 if (!inst.error)
10645 inst.error = BAD_ARGS;
10647 return;
10650 end_of_line (str);
10653 static void
10654 do_mav_shift_1 (str)
10655 char * str;
10657 do_mav_shift (str, REG_TYPE_MVFX, REG_TYPE_MVFX);
10660 static void
10661 do_mav_shift_2 (str)
10662 char * str;
10664 do_mav_shift (str, REG_TYPE_MVDX, REG_TYPE_MVDX);
10667 static void
10668 do_mav_ldst_1 (str)
10669 char * str;
10671 do_mav_ldst (str, REG_TYPE_MVF);
10674 static void
10675 do_mav_ldst_2 (str)
10676 char * str;
10678 do_mav_ldst (str, REG_TYPE_MVD);
10681 static void
10682 do_mav_ldst_3 (str)
10683 char * str;
10685 do_mav_ldst (str, REG_TYPE_MVFX);
10688 static void
10689 do_mav_ldst_4 (str)
10690 char * str;
10692 do_mav_ldst (str, REG_TYPE_MVDX);
10695 /* Isnsn like "foo X,Y". */
10697 static void
10698 do_mav_binops (str, mode, reg0, reg1)
10699 char * str;
10700 int mode;
10701 enum arm_reg_type reg0;
10702 enum arm_reg_type reg1;
10704 int shift0, shift1;
10706 shift0 = mode & 0xff;
10707 shift1 = (mode >> 8) & 0xff;
10709 skip_whitespace (str);
10711 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
10712 || skip_past_comma (&str) == FAIL
10713 || mav_reg_required_here (&str, shift1, reg1) == FAIL)
10715 if (!inst.error)
10716 inst.error = BAD_ARGS;
10718 else
10719 end_of_line (str);
10722 /* Isnsn like "foo X,Y,Z". */
10724 static void
10725 do_mav_triple (str, mode, reg0, reg1, reg2)
10726 char * str;
10727 int mode;
10728 enum arm_reg_type reg0;
10729 enum arm_reg_type reg1;
10730 enum arm_reg_type reg2;
10732 int shift0, shift1, shift2;
10734 shift0 = mode & 0xff;
10735 shift1 = (mode >> 8) & 0xff;
10736 shift2 = (mode >> 16) & 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)
10746 if (!inst.error)
10747 inst.error = BAD_ARGS;
10749 else
10750 end_of_line (str);
10753 /* Isnsn like "foo W,X,Y,Z".
10754 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
10756 static void
10757 do_mav_quad (str, mode, reg0, reg1, reg2, reg3)
10758 char * str;
10759 int mode;
10760 enum arm_reg_type reg0;
10761 enum arm_reg_type reg1;
10762 enum arm_reg_type reg2;
10763 enum arm_reg_type reg3;
10765 int shift0, shift1, shift2, shift3;
10767 shift0= mode & 0xff;
10768 shift1 = (mode >> 8) & 0xff;
10769 shift2 = (mode >> 16) & 0xff;
10770 shift3 = (mode >> 24) & 0xff;
10772 skip_whitespace (str);
10774 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
10775 || skip_past_comma (&str) == FAIL
10776 || mav_reg_required_here (&str, shift1, reg1) == FAIL
10777 || skip_past_comma (&str) == FAIL
10778 || mav_reg_required_here (&str, shift2, reg2) == FAIL
10779 || skip_past_comma (&str) == FAIL
10780 || mav_reg_required_here (&str, shift3, reg3) == FAIL)
10782 if (!inst.error)
10783 inst.error = BAD_ARGS;
10785 else
10786 end_of_line (str);
10789 /* Maverick shift immediate instructions.
10790 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
10791 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
10793 static void
10794 do_mav_shift (str, reg0, reg1)
10795 char * str;
10796 enum arm_reg_type reg0;
10797 enum arm_reg_type reg1;
10799 int error;
10800 int imm, neg = 0;
10802 skip_whitespace (str);
10804 error = 0;
10806 if (mav_reg_required_here (&str, 12, reg0) == FAIL
10807 || skip_past_comma (&str) == FAIL
10808 || mav_reg_required_here (&str, 16, reg1) == FAIL
10809 || skip_past_comma (&str) == FAIL)
10811 if (!inst.error)
10812 inst.error = BAD_ARGS;
10813 return;
10816 /* Calculate the immediate operand.
10817 The operand is a 7bit signed number. */
10818 skip_whitespace (str);
10820 if (*str == '#')
10821 ++str;
10823 if (!ISDIGIT (*str) && *str != '-')
10825 inst.error = _("expecting immediate, 7bit operand");
10826 return;
10829 if (*str == '-')
10831 neg = 1;
10832 ++str;
10835 for (imm = 0; *str && ISDIGIT (*str); ++str)
10836 imm = imm * 10 + *str - '0';
10838 if (imm > 64)
10840 inst.error = _("immediate out of range");
10841 return;
10844 /* Make negative imm's into 7bit signed numbers. */
10845 if (neg)
10847 imm = -imm;
10848 imm &= 0x0000007f;
10851 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
10852 Bits 5-7 of the insn should have bits 4-6 of the immediate.
10853 Bit 4 should be 0. */
10854 imm = (imm & 0xf) | ((imm & 0x70) << 1);
10856 inst.instruction |= imm;
10857 end_of_line (str);
10860 static int
10861 mav_parse_offset (str, negative)
10862 char ** str;
10863 int *negative;
10865 char * p = *str;
10866 int offset;
10868 *negative = 0;
10870 skip_whitespace (p);
10872 if (*p == '#')
10873 ++p;
10875 if (*p == '-')
10877 *negative = 1;
10878 ++p;
10881 if (!ISDIGIT (*p))
10883 inst.error = _("offset expected");
10884 return 0;
10887 for (offset = 0; *p && ISDIGIT (*p); ++p)
10888 offset = offset * 10 + *p - '0';
10890 if (offset > 0xff)
10892 inst.error = _("offset out of range");
10893 return 0;
10896 *str = p;
10898 return *negative ? -offset : offset;
10901 /* Maverick load/store instructions.
10902 <insn><cond> CRd,[Rn,<offset>]{!}.
10903 <insn><cond> CRd,[Rn],<offset>. */
10905 static void
10906 do_mav_ldst (str, reg0)
10907 char * str;
10908 enum arm_reg_type reg0;
10910 int offset, negative;
10912 skip_whitespace (str);
10914 if (mav_reg_required_here (&str, 12, reg0) == FAIL
10915 || skip_past_comma (&str) == FAIL
10916 || *str++ != '['
10917 || reg_required_here (&str, 16) == FAIL)
10918 goto fail_ldst;
10920 if (skip_past_comma (&str) == SUCCESS)
10922 /* You are here: "<offset>]{!}". */
10923 inst.instruction |= PRE_INDEX;
10925 offset = mav_parse_offset (&str, &negative);
10927 if (inst.error)
10928 return;
10930 if (*str++ != ']')
10932 inst.error = _("missing ]");
10933 return;
10936 if (*str == '!')
10938 inst.instruction |= WRITE_BACK;
10939 ++str;
10942 else
10944 /* You are here: "], <offset>". */
10945 if (*str++ != ']')
10947 inst.error = _("missing ]");
10948 return;
10951 if (skip_past_comma (&str) == FAIL
10952 || (offset = mav_parse_offset (&str, &negative), inst.error))
10953 goto fail_ldst;
10955 inst.instruction |= CP_T_WB; /* Post indexed, set bit W. */
10958 if (negative)
10959 offset = -offset;
10960 else
10961 inst.instruction |= CP_T_UD; /* Positive, so set bit U. */
10963 inst.instruction |= offset >> 2;
10964 end_of_line (str);
10965 return;
10967 fail_ldst:
10968 if (!inst.error)
10969 inst.error = BAD_ARGS;
10970 return;
10973 static void
10974 do_t_nop (str)
10975 char * str;
10977 /* Do nothing. */
10978 end_of_line (str);
10979 return;
10982 /* Handle the Format 4 instructions that do not have equivalents in other
10983 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
10984 BIC and MVN. */
10986 static void
10987 do_t_arit (str)
10988 char * str;
10990 int Rd, Rs, Rn;
10992 skip_whitespace (str);
10994 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
10995 || skip_past_comma (&str) == FAIL
10996 || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
10998 inst.error = BAD_ARGS;
10999 return;
11002 if (skip_past_comma (&str) != FAIL)
11004 /* Three operand format not allowed for TST, CMN, NEG and MVN.
11005 (It isn't allowed for CMP either, but that isn't handled by this
11006 function.) */
11007 if (inst.instruction == T_OPCODE_TST
11008 || inst.instruction == T_OPCODE_CMN
11009 || inst.instruction == T_OPCODE_NEG
11010 || inst.instruction == T_OPCODE_MVN)
11012 inst.error = BAD_ARGS;
11013 return;
11016 if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
11017 return;
11019 if (Rs != Rd)
11021 inst.error = _("dest and source1 must be the same register");
11022 return;
11024 Rs = Rn;
11027 if (inst.instruction == T_OPCODE_MUL
11028 && Rs == Rd)
11029 as_tsktsk (_("Rs and Rd must be different in MUL"));
11031 inst.instruction |= Rd | (Rs << 3);
11032 end_of_line (str);
11035 static void
11036 do_t_add (str)
11037 char * str;
11039 thumb_add_sub (str, 0);
11042 static void
11043 do_t_asr (str)
11044 char * str;
11046 thumb_shift (str, THUMB_ASR);
11049 static void
11050 do_t_branch9 (str)
11051 char * str;
11053 if (my_get_expression (&inst.reloc.exp, &str))
11054 return;
11055 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
11056 inst.reloc.pc_rel = 1;
11057 end_of_line (str);
11060 static void
11061 do_t_branch12 (str)
11062 char * str;
11064 if (my_get_expression (&inst.reloc.exp, &str))
11065 return;
11066 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
11067 inst.reloc.pc_rel = 1;
11068 end_of_line (str);
11071 /* Find the real, Thumb encoded start of a Thumb function. */
11073 static symbolS *
11074 find_real_start (symbolP)
11075 symbolS * symbolP;
11077 char * real_start;
11078 const char * name = S_GET_NAME (symbolP);
11079 symbolS * new_target;
11081 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
11082 #define STUB_NAME ".real_start_of"
11084 if (name == NULL)
11085 abort ();
11087 /* Names that start with '.' are local labels, not function entry points.
11088 The compiler may generate BL instructions to these labels because it
11089 needs to perform a branch to a far away location. */
11090 if (name[0] == '.')
11091 return symbolP;
11093 real_start = malloc (strlen (name) + strlen (STUB_NAME) + 1);
11094 sprintf (real_start, "%s%s", STUB_NAME, name);
11096 new_target = symbol_find (real_start);
11098 if (new_target == NULL)
11100 as_warn ("Failed to find real start of function: %s\n", name);
11101 new_target = symbolP;
11104 free (real_start);
11106 return new_target;
11109 static void
11110 do_t_branch23 (str)
11111 char * str;
11113 if (my_get_expression (& inst.reloc.exp, & str))
11114 return;
11116 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH23;
11117 inst.reloc.pc_rel = 1;
11118 end_of_line (str);
11120 /* If the destination of the branch is a defined symbol which does not have
11121 the THUMB_FUNC attribute, then we must be calling a function which has
11122 the (interfacearm) attribute. We look for the Thumb entry point to that
11123 function and change the branch to refer to that function instead. */
11124 if ( inst.reloc.exp.X_op == O_symbol
11125 && inst.reloc.exp.X_add_symbol != NULL
11126 && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
11127 && ! THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
11128 inst.reloc.exp.X_add_symbol =
11129 find_real_start (inst.reloc.exp.X_add_symbol);
11132 static void
11133 do_t_bx (str)
11134 char * str;
11136 int reg;
11138 skip_whitespace (str);
11140 if ((reg = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
11141 return;
11143 /* This sets THUMB_H2 from the top bit of reg. */
11144 inst.instruction |= reg << 3;
11146 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
11147 should cause the alignment to be checked once it is known. This is
11148 because BX PC only works if the instruction is word aligned. */
11150 end_of_line (str);
11153 static void
11154 do_t_compare (str)
11155 char * str;
11157 thumb_mov_compare (str, THUMB_COMPARE);
11160 static void
11161 do_t_ldmstm (str)
11162 char * str;
11164 int Rb;
11165 long range;
11167 skip_whitespace (str);
11169 if ((Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
11170 return;
11172 if (*str != '!')
11173 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
11174 else
11175 str++;
11177 if (skip_past_comma (&str) == FAIL
11178 || (range = reg_list (&str)) == FAIL)
11180 if (! inst.error)
11181 inst.error = BAD_ARGS;
11182 return;
11185 if (inst.reloc.type != BFD_RELOC_NONE)
11187 /* This really doesn't seem worth it. */
11188 inst.reloc.type = BFD_RELOC_NONE;
11189 inst.error = _("expression too complex");
11190 return;
11193 if (range & ~0xff)
11195 inst.error = _("only lo-regs valid in load/store multiple");
11196 return;
11199 inst.instruction |= (Rb << 8) | range;
11200 end_of_line (str);
11203 static void
11204 do_t_ldr (str)
11205 char * str;
11207 thumb_load_store (str, THUMB_LOAD, THUMB_WORD);
11210 static void
11211 do_t_ldrb (str)
11212 char * str;
11214 thumb_load_store (str, THUMB_LOAD, THUMB_BYTE);
11217 static void
11218 do_t_ldrh (str)
11219 char * str;
11221 thumb_load_store (str, THUMB_LOAD, THUMB_HALFWORD);
11224 static void
11225 do_t_lds (str)
11226 char * str;
11228 int Rd, Rb, Ro;
11230 skip_whitespace (str);
11232 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
11233 || skip_past_comma (&str) == FAIL
11234 || *str++ != '['
11235 || (Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL
11236 || skip_past_comma (&str) == FAIL
11237 || (Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL
11238 || *str++ != ']')
11240 if (! inst.error)
11241 inst.error = _("syntax: ldrs[b] Rd, [Rb, Ro]");
11242 return;
11245 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
11246 end_of_line (str);
11249 static void
11250 do_t_lsl (str)
11251 char * str;
11253 thumb_shift (str, THUMB_LSL);
11256 static void
11257 do_t_lsr (str)
11258 char * str;
11260 thumb_shift (str, THUMB_LSR);
11263 static void
11264 do_t_mov (str)
11265 char * str;
11267 thumb_mov_compare (str, THUMB_MOVE);
11270 static void
11271 do_t_push_pop (str)
11272 char * str;
11274 long range;
11276 skip_whitespace (str);
11278 if ((range = reg_list (&str)) == FAIL)
11280 if (! inst.error)
11281 inst.error = BAD_ARGS;
11282 return;
11285 if (inst.reloc.type != BFD_RELOC_NONE)
11287 /* This really doesn't seem worth it. */
11288 inst.reloc.type = BFD_RELOC_NONE;
11289 inst.error = _("expression too complex");
11290 return;
11293 if (range & ~0xff)
11295 if ((inst.instruction == T_OPCODE_PUSH
11296 && (range & ~0xff) == 1 << REG_LR)
11297 || (inst.instruction == T_OPCODE_POP
11298 && (range & ~0xff) == 1 << REG_PC))
11300 inst.instruction |= THUMB_PP_PC_LR;
11301 range &= 0xff;
11303 else
11305 inst.error = _("invalid register list to push/pop instruction");
11306 return;
11310 inst.instruction |= range;
11311 end_of_line (str);
11314 static void
11315 do_t_str (str)
11316 char * str;
11318 thumb_load_store (str, THUMB_STORE, THUMB_WORD);
11321 static void
11322 do_t_strb (str)
11323 char * str;
11325 thumb_load_store (str, THUMB_STORE, THUMB_BYTE);
11328 static void
11329 do_t_strh (str)
11330 char * str;
11332 thumb_load_store (str, THUMB_STORE, THUMB_HALFWORD);
11335 static void
11336 do_t_sub (str)
11337 char * str;
11339 thumb_add_sub (str, 1);
11342 static void
11343 do_t_swi (str)
11344 char * str;
11346 skip_whitespace (str);
11348 if (my_get_expression (&inst.reloc.exp, &str))
11349 return;
11351 inst.reloc.type = BFD_RELOC_ARM_SWI;
11352 end_of_line (str);
11353 return;
11356 static void
11357 do_t_adr (str)
11358 char * str;
11360 int reg;
11362 /* This is a pseudo-op of the form "adr rd, label" to be converted
11363 into a relative address of the form "add rd, pc, #label-.-4". */
11364 skip_whitespace (str);
11366 /* Store Rd in temporary location inside instruction. */
11367 if ((reg = reg_required_here (&str, 4)) == FAIL
11368 || (reg > 7) /* For Thumb reg must be r0..r7. */
11369 || skip_past_comma (&str) == FAIL
11370 || my_get_expression (&inst.reloc.exp, &str))
11372 if (!inst.error)
11373 inst.error = BAD_ARGS;
11374 return;
11377 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
11378 inst.reloc.exp.X_add_number -= 4; /* PC relative adjust. */
11379 inst.reloc.pc_rel = 1;
11380 inst.instruction |= REG_PC; /* Rd is already placed into the instruction. */
11382 end_of_line (str);
11385 static void
11386 insert_reg (r, htab)
11387 const struct reg_entry *r;
11388 struct hash_control *htab;
11390 int len = strlen (r->name) + 2;
11391 char * buf = (char *) xmalloc (len);
11392 char * buf2 = (char *) xmalloc (len);
11393 int i = 0;
11395 #ifdef REGISTER_PREFIX
11396 buf[i++] = REGISTER_PREFIX;
11397 #endif
11399 strcpy (buf + i, r->name);
11401 for (i = 0; buf[i]; i++)
11402 buf2[i] = TOUPPER (buf[i]);
11404 buf2[i] = '\0';
11406 hash_insert (htab, buf, (PTR) r);
11407 hash_insert (htab, buf2, (PTR) r);
11410 static void
11411 build_reg_hsh (map)
11412 struct reg_map *map;
11414 const struct reg_entry *r;
11416 if ((map->htab = hash_new ()) == NULL)
11417 as_fatal (_("virtual memory exhausted"));
11419 for (r = map->names; r->name != NULL; r++)
11420 insert_reg (r, map->htab);
11423 static void
11424 insert_reg_alias (str, regnum, htab)
11425 char *str;
11426 int regnum;
11427 struct hash_control *htab;
11429 const char *error;
11430 struct reg_entry *new = xmalloc (sizeof (struct reg_entry));
11431 const char *name = xmalloc (strlen (str) + 1);
11433 strcpy ((char *) name, str);
11435 new->name = name;
11436 new->number = regnum;
11437 new->builtin = FALSE;
11439 error = hash_insert (htab, name, (PTR) new);
11440 if (error)
11442 as_bad (_("failed to create an alias for %s, reason: %s"),
11443 str, error);
11444 free ((char *) name);
11445 free (new);
11449 /* Look for the .req directive. This is of the form:
11451 new_register_name .req existing_register_name
11453 If we find one, or if it looks sufficiently like one that we want to
11454 handle any error here, return non-zero. Otherwise return zero. */
11455 static int
11456 create_register_alias (newname, p)
11457 char *newname;
11458 char *p;
11460 char *q;
11461 char c;
11463 q = p;
11464 skip_whitespace (q);
11466 c = *p;
11467 *p = '\0';
11469 if (*q && !strncmp (q, ".req ", 5))
11471 char *copy_of_str;
11472 char *r;
11474 #ifdef IGNORE_OPCODE_CASE
11475 newname = original_case_string;
11476 #endif
11477 copy_of_str = newname;
11479 q += 4;
11480 skip_whitespace (q);
11482 for (r = q; *r != '\0'; r++)
11483 if (*r == ' ')
11484 break;
11486 if (r != q)
11488 enum arm_reg_type new_type, old_type;
11489 int old_regno;
11490 char d = *r;
11492 *r = '\0';
11493 old_type = arm_reg_parse_any (q);
11494 *r = d;
11496 new_type = arm_reg_parse_any (newname);
11498 if (new_type == REG_TYPE_MAX)
11500 if (old_type != REG_TYPE_MAX)
11502 old_regno = arm_reg_parse (&q, all_reg_maps[old_type].htab);
11503 insert_reg_alias (newname, old_regno,
11504 all_reg_maps[old_type].htab);
11506 else
11507 as_warn (_("register '%s' does not exist\n"), q);
11509 else if (old_type == REG_TYPE_MAX)
11511 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
11512 copy_of_str, q);
11514 else
11516 /* Do not warn about redefinitions to the same alias. */
11517 if (new_type != old_type
11518 || (arm_reg_parse (&q, all_reg_maps[old_type].htab)
11519 != arm_reg_parse (&q, all_reg_maps[new_type].htab)))
11520 as_warn (_("ignoring redefinition of register alias '%s'"),
11521 copy_of_str);
11525 else
11526 as_warn (_("ignoring incomplete .req pseuso op"));
11528 *p = c;
11529 return 1;
11532 *p = c;
11533 return 0;
11536 static void
11537 set_constant_flonums ()
11539 int i;
11541 for (i = 0; i < NUM_FLOAT_VALS; i++)
11542 if (atof_ieee ((char *) fp_const[i], 'x', fp_values[i]) == NULL)
11543 abort ();
11546 /* Iterate over the base tables to create the instruction patterns. */
11547 static void
11548 build_arm_ops_hsh ()
11550 unsigned int i;
11551 unsigned int j;
11552 static struct obstack insn_obstack;
11554 obstack_begin (&insn_obstack, 4000);
11556 for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
11558 const struct asm_opcode *insn = insns + i;
11560 if (insn->cond_offset != 0)
11562 /* Insn supports conditional execution. Build the varaints
11563 and insert them in the hash table. */
11564 for (j = 0; j < sizeof (conds) / sizeof (struct asm_cond); j++)
11566 unsigned len = strlen (insn->template);
11567 struct asm_opcode *new;
11568 char *template;
11570 new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
11571 /* All condition codes are two characters. */
11572 template = obstack_alloc (&insn_obstack, len + 3);
11574 strncpy (template, insn->template, insn->cond_offset);
11575 strcpy (template + insn->cond_offset, conds[j].template);
11576 if (len > insn->cond_offset)
11577 strcpy (template + insn->cond_offset + 2,
11578 insn->template + insn->cond_offset);
11579 new->template = template;
11580 new->cond_offset = 0;
11581 new->variant = insn->variant;
11582 new->parms = insn->parms;
11583 new->value = (insn->value & ~COND_MASK) | conds[j].value;
11585 hash_insert (arm_ops_hsh, new->template, (PTR) new);
11588 /* Finally, insert the unconditional insn in the table directly;
11589 no need to build a copy. */
11590 hash_insert (arm_ops_hsh, insn->template, (PTR) insn);
11594 #if 0 /* Suppressed - for now. */
11595 #if defined OBJ_ELF || defined OBJ_COFF
11597 #ifdef OBJ_ELF
11598 #define arm_Note Elf_External_Note
11599 #else
11600 typedef struct
11602 unsigned char namesz[4]; /* Size of entry's owner string. */
11603 unsigned char descsz[4]; /* Size of the note descriptor. */
11604 unsigned char type[4]; /* Interpretation of the descriptor. */
11605 char name[1]; /* Start of the name+desc data. */
11606 } arm_Note;
11607 #endif
11609 /* The description is kept to a fix sized in order to make updating
11610 it and merging it easier. */
11611 #define ARM_NOTE_DESCRIPTION_LENGTH 8
11613 static void
11614 arm_add_note (name, description, type)
11615 const char * name;
11616 const char * description;
11617 unsigned int type;
11619 arm_Note note ATTRIBUTE_UNUSED;
11620 char * p;
11621 unsigned int name_len;
11623 name_len = (strlen (name) + 1 + 3) & ~3;
11625 p = frag_more (sizeof (note.namesz));
11626 md_number_to_chars (p, (valueT) name_len, sizeof (note.namesz));
11628 p = frag_more (sizeof (note.descsz));
11629 md_number_to_chars (p, (valueT) ARM_NOTE_DESCRIPTION_LENGTH, sizeof (note.descsz));
11631 p = frag_more (sizeof (note.type));
11632 md_number_to_chars (p, (valueT) type, sizeof (note.type));
11634 p = frag_more (name_len);
11635 strcpy (p, name);
11637 p = frag_more (ARM_NOTE_DESCRIPTION_LENGTH);
11638 strncpy (p, description, ARM_NOTE_DESCRIPTION_LENGTH);
11639 frag_align (2, 0, 0);
11641 #endif
11642 #endif
11644 void
11645 md_begin ()
11647 unsigned mach;
11648 unsigned int i;
11650 if ( (arm_ops_hsh = hash_new ()) == NULL
11651 || (arm_tops_hsh = hash_new ()) == NULL
11652 || (arm_cond_hsh = hash_new ()) == NULL
11653 || (arm_shift_hsh = hash_new ()) == NULL
11654 || (arm_psr_hsh = hash_new ()) == NULL)
11655 as_fatal (_("virtual memory exhausted"));
11657 build_arm_ops_hsh ();
11658 for (i = 0; i < sizeof (tinsns) / sizeof (struct thumb_opcode); i++)
11659 hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
11660 for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
11661 hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
11662 for (i = 0; i < sizeof (shift_names) / sizeof (struct asm_shift_name); i++)
11663 hash_insert (arm_shift_hsh, shift_names[i].name, (PTR) (shift_names + i));
11664 for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
11665 hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
11667 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
11668 build_reg_hsh (all_reg_maps + i);
11670 set_constant_flonums ();
11672 /* Set the cpu variant based on the command-line options. We prefer
11673 -mcpu= over -march= if both are set (as for GCC); and we prefer
11674 -mfpu= over any other way of setting the floating point unit.
11675 Use of legacy options with new options are faulted. */
11676 if (legacy_cpu != -1)
11678 if (mcpu_cpu_opt != -1 || march_cpu_opt != -1)
11679 as_bad (_("use of old and new-style options to set CPU type"));
11681 mcpu_cpu_opt = legacy_cpu;
11683 else if (mcpu_cpu_opt == -1)
11684 mcpu_cpu_opt = march_cpu_opt;
11686 if (legacy_fpu != -1)
11688 if (mfpu_opt != -1)
11689 as_bad (_("use of old and new-style options to set FPU type"));
11691 mfpu_opt = legacy_fpu;
11693 else if (mfpu_opt == -1)
11695 #if !(defined (TE_LINUX) || defined (TE_NetBSD))
11696 /* Some environments specify a default FPU. If they don't, infer it
11697 from the processor. */
11698 if (mcpu_fpu_opt != -1)
11699 mfpu_opt = mcpu_fpu_opt;
11700 else
11701 mfpu_opt = march_fpu_opt;
11702 #else
11703 mfpu_opt = FPU_DEFAULT;
11704 #endif
11707 if (mfpu_opt == -1)
11709 if (mcpu_cpu_opt == -1)
11710 mfpu_opt = FPU_DEFAULT;
11711 else if (mcpu_cpu_opt & ARM_EXT_V5)
11712 mfpu_opt = FPU_ARCH_VFP_V2;
11713 else
11714 mfpu_opt = FPU_ARCH_FPA;
11717 if (mcpu_cpu_opt == -1)
11718 mcpu_cpu_opt = CPU_DEFAULT;
11720 cpu_variant = mcpu_cpu_opt | mfpu_opt;
11722 #if defined OBJ_COFF || defined OBJ_ELF
11724 unsigned int flags = 0;
11726 /* Set the flags in the private structure. */
11727 if (uses_apcs_26) flags |= F_APCS26;
11728 if (support_interwork) flags |= F_INTERWORK;
11729 if (uses_apcs_float) flags |= F_APCS_FLOAT;
11730 if (pic_code) flags |= F_PIC;
11731 if ((cpu_variant & FPU_ANY) == FPU_NONE
11732 || (cpu_variant & FPU_ANY) == FPU_ARCH_VFP) /* VFP layout only. */
11733 flags |= F_SOFT_FLOAT;
11734 /* Using VFP conventions (even if soft-float). */
11735 if (cpu_variant & FPU_VFP_EXT_NONE) flags |= F_VFP_FLOAT;
11737 #if defined OBJ_ELF
11738 if (cpu_variant & ARM_CEXT_MAVERICK)
11740 flags &= ~ F_SOFT_FLOAT;
11741 flags |= EF_ARM_MAVERICK_FLOAT;
11743 #endif
11745 bfd_set_private_flags (stdoutput, flags);
11747 /* We have run out flags in the COFF header to encode the
11748 status of ATPCS support, so instead we create a dummy,
11749 empty, debug section called .arm.atpcs. */
11750 if (atpcs)
11752 asection * sec;
11754 sec = bfd_make_section (stdoutput, ".arm.atpcs");
11756 if (sec != NULL)
11758 bfd_set_section_flags
11759 (stdoutput, sec, SEC_READONLY | SEC_DEBUGGING /* | SEC_HAS_CONTENTS */);
11760 bfd_set_section_size (stdoutput, sec, 0);
11761 bfd_set_section_contents (stdoutput, sec, NULL, 0, 0);
11765 #endif
11767 /* Record the CPU type as well. */
11768 switch (cpu_variant & ARM_CPU_MASK)
11770 case ARM_2:
11771 mach = bfd_mach_arm_2;
11772 break;
11774 case ARM_3: /* Also ARM_250. */
11775 mach = bfd_mach_arm_2a;
11776 break;
11778 case ARM_6: /* Also ARM_7. */
11779 mach = bfd_mach_arm_3;
11780 break;
11782 default:
11783 mach = bfd_mach_arm_unknown;
11784 break;
11787 /* Catch special cases. */
11788 if (cpu_variant & ARM_CEXT_IWMMXT)
11789 mach = bfd_mach_arm_iWMMXt;
11790 else if (cpu_variant & ARM_CEXT_XSCALE)
11791 mach = bfd_mach_arm_XScale;
11792 else if (cpu_variant & ARM_CEXT_MAVERICK)
11793 mach = bfd_mach_arm_ep9312;
11794 else if (cpu_variant & ARM_EXT_V5E)
11795 mach = bfd_mach_arm_5TE;
11796 else if (cpu_variant & ARM_EXT_V5)
11798 if (cpu_variant & ARM_EXT_V4T)
11799 mach = bfd_mach_arm_5T;
11800 else
11801 mach = bfd_mach_arm_5;
11803 else if (cpu_variant & ARM_EXT_V4)
11805 if (cpu_variant & ARM_EXT_V4T)
11806 mach = bfd_mach_arm_4T;
11807 else
11808 mach = bfd_mach_arm_4;
11810 else if (cpu_variant & ARM_EXT_V3M)
11811 mach = bfd_mach_arm_3M;
11813 #if 0 /* Suppressed - for now. */
11814 #if defined (OBJ_ELF) || defined (OBJ_COFF)
11816 /* Create a .note section to fully identify this arm binary. */
11818 #define NOTE_ARCH_STRING "arch: "
11820 #if defined OBJ_COFF && ! defined NT_VERSION
11821 #define NT_VERSION 1
11822 #define NT_ARCH 2
11823 #endif
11826 segT current_seg = now_seg;
11827 subsegT current_subseg = now_subseg;
11828 asection * arm_arch;
11829 const char * arch_string;
11831 arm_arch = bfd_make_section_old_way (stdoutput, ARM_NOTE_SECTION);
11833 #ifdef OBJ_COFF
11834 bfd_set_section_flags (stdoutput, arm_arch,
11835 SEC_DATA | SEC_ALLOC | SEC_LOAD | SEC_LINK_ONCE \
11836 | SEC_HAS_CONTENTS);
11837 #endif
11838 arm_arch->output_section = arm_arch;
11839 subseg_set (arm_arch, 0);
11841 switch (mach)
11843 default:
11844 case bfd_mach_arm_unknown: arch_string = "unknown"; break;
11845 case bfd_mach_arm_2: arch_string = "armv2"; break;
11846 case bfd_mach_arm_2a: arch_string = "armv2a"; break;
11847 case bfd_mach_arm_3: arch_string = "armv3"; break;
11848 case bfd_mach_arm_3M: arch_string = "armv3M"; break;
11849 case bfd_mach_arm_4: arch_string = "armv4"; break;
11850 case bfd_mach_arm_4T: arch_string = "armv4t"; break;
11851 case bfd_mach_arm_5: arch_string = "armv5"; break;
11852 case bfd_mach_arm_5T: arch_string = "armv5t"; break;
11853 case bfd_mach_arm_5TE: arch_string = "armv5te"; break;
11854 case bfd_mach_arm_XScale: arch_string = "XScale"; break;
11855 case bfd_mach_arm_ep9312: arch_string = "ep9312"; break;
11856 case bfd_mach_arm_iWMMXt: arch_string = "iWMMXt"; break;
11859 arm_add_note (NOTE_ARCH_STRING, arch_string, NT_ARCH);
11861 subseg_set (current_seg, current_subseg);
11863 #endif
11864 #endif /* Suppressed code. */
11866 bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
11869 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11870 for use in the a.out file, and stores them in the array pointed to by buf.
11871 This knows about the endian-ness of the target machine and does
11872 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11873 2 (short) and 4 (long) Floating numbers are put out as a series of
11874 LITTLENUMS (shorts, here at least). */
11876 void
11877 md_number_to_chars (buf, val, n)
11878 char * buf;
11879 valueT val;
11880 int n;
11882 if (target_big_endian)
11883 number_to_chars_bigendian (buf, val, n);
11884 else
11885 number_to_chars_littleendian (buf, val, n);
11888 static valueT
11889 md_chars_to_number (buf, n)
11890 char * buf;
11891 int n;
11893 valueT result = 0;
11894 unsigned char * where = (unsigned char *) buf;
11896 if (target_big_endian)
11898 while (n--)
11900 result <<= 8;
11901 result |= (*where++ & 255);
11904 else
11906 while (n--)
11908 result <<= 8;
11909 result |= (where[n] & 255);
11913 return result;
11916 /* Turn a string in input_line_pointer into a floating point constant
11917 of type TYPE, and store the appropriate bytes in *LITP. The number
11918 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11919 returned, or NULL on OK.
11921 Note that fp constants aren't represent in the normal way on the ARM.
11922 In big endian mode, things are as expected. However, in little endian
11923 mode fp constants are big-endian word-wise, and little-endian byte-wise
11924 within the words. For example, (double) 1.1 in big endian mode is
11925 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11926 the byte sequence 99 99 f1 3f 9a 99 99 99.
11928 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11930 char *
11931 md_atof (type, litP, sizeP)
11932 char type;
11933 char * litP;
11934 int * sizeP;
11936 int prec;
11937 LITTLENUM_TYPE words[MAX_LITTLENUMS];
11938 char *t;
11939 int i;
11941 switch (type)
11943 case 'f':
11944 case 'F':
11945 case 's':
11946 case 'S':
11947 prec = 2;
11948 break;
11950 case 'd':
11951 case 'D':
11952 case 'r':
11953 case 'R':
11954 prec = 4;
11955 break;
11957 case 'x':
11958 case 'X':
11959 prec = 6;
11960 break;
11962 case 'p':
11963 case 'P':
11964 prec = 6;
11965 break;
11967 default:
11968 *sizeP = 0;
11969 return _("bad call to MD_ATOF()");
11972 t = atof_ieee (input_line_pointer, type, words);
11973 if (t)
11974 input_line_pointer = t;
11975 *sizeP = prec * 2;
11977 if (target_big_endian)
11979 for (i = 0; i < prec; i++)
11981 md_number_to_chars (litP, (valueT) words[i], 2);
11982 litP += 2;
11985 else
11987 if (cpu_variant & FPU_ARCH_VFP)
11988 for (i = prec - 1; i >= 0; i--)
11990 md_number_to_chars (litP, (valueT) words[i], 2);
11991 litP += 2;
11993 else
11994 /* For a 4 byte float the order of elements in `words' is 1 0.
11995 For an 8 byte float the order is 1 0 3 2. */
11996 for (i = 0; i < prec; i += 2)
11998 md_number_to_chars (litP, (valueT) words[i + 1], 2);
11999 md_number_to_chars (litP + 2, (valueT) words[i], 2);
12000 litP += 4;
12004 return 0;
12007 /* The knowledge of the PC's pipeline offset is built into the insns
12008 themselves. */
12010 long
12011 md_pcrel_from (fixP)
12012 fixS * fixP;
12014 if (fixP->fx_addsy
12015 && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section
12016 && fixP->fx_subsy == NULL)
12017 return 0;
12019 if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD))
12021 /* PC relative addressing on the Thumb is slightly odd
12022 as the bottom two bits of the PC are forced to zero
12023 for the calculation. */
12024 return (fixP->fx_where + fixP->fx_frag->fr_address) & ~3;
12027 #ifdef TE_WINCE
12028 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
12029 so we un-adjust here to compensate for the accommodation. */
12030 return fixP->fx_where + fixP->fx_frag->fr_address + 8;
12031 #else
12032 return fixP->fx_where + fixP->fx_frag->fr_address;
12033 #endif
12036 /* Round up a section size to the appropriate boundary. */
12038 valueT
12039 md_section_align (segment, size)
12040 segT segment ATTRIBUTE_UNUSED;
12041 valueT size;
12043 #ifdef OBJ_ELF
12044 return size;
12045 #else
12046 /* Round all sects to multiple of 4. */
12047 return (size + 3) & ~3;
12048 #endif
12051 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
12052 Otherwise we have no need to default values of symbols. */
12054 symbolS *
12055 md_undefined_symbol (name)
12056 char * name ATTRIBUTE_UNUSED;
12058 #ifdef OBJ_ELF
12059 if (name[0] == '_' && name[1] == 'G'
12060 && streq (name, GLOBAL_OFFSET_TABLE_NAME))
12062 if (!GOT_symbol)
12064 if (symbol_find (name))
12065 as_bad ("GOT already in the symbol table");
12067 GOT_symbol = symbol_new (name, undefined_section,
12068 (valueT) 0, & zero_address_frag);
12071 return GOT_symbol;
12073 #endif
12075 return 0;
12078 /* arm_reg_parse () := if it looks like a register, return its token and
12079 advance the pointer. */
12081 static int
12082 arm_reg_parse (ccp, htab)
12083 register char ** ccp;
12084 struct hash_control *htab;
12086 char * start = * ccp;
12087 char c;
12088 char * p;
12089 struct reg_entry * reg;
12091 #ifdef REGISTER_PREFIX
12092 if (*start != REGISTER_PREFIX)
12093 return FAIL;
12094 p = start + 1;
12095 #else
12096 p = start;
12097 #ifdef OPTIONAL_REGISTER_PREFIX
12098 if (*p == OPTIONAL_REGISTER_PREFIX)
12099 p++, start++;
12100 #endif
12101 #endif
12102 if (!ISALPHA (*p) || !is_name_beginner (*p))
12103 return FAIL;
12105 c = *p++;
12106 while (ISALPHA (c) || ISDIGIT (c) || c == '_')
12107 c = *p++;
12109 *--p = 0;
12110 reg = (struct reg_entry *) hash_find (htab, start);
12111 *p = c;
12113 if (reg)
12115 *ccp = p;
12116 return reg->number;
12119 return FAIL;
12122 /* Search for the following register name in each of the possible reg name
12123 tables. Return the classification if found, or REG_TYPE_MAX if not
12124 present. */
12125 static enum arm_reg_type
12126 arm_reg_parse_any (cp)
12127 char *cp;
12129 int i;
12131 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
12132 if (arm_reg_parse (&cp, all_reg_maps[i].htab) != FAIL)
12133 return (enum arm_reg_type) i;
12135 return REG_TYPE_MAX;
12138 void
12139 md_apply_fix3 (fixP, valP, seg)
12140 fixS * fixP;
12141 valueT * valP;
12142 segT seg;
12144 offsetT value = * valP;
12145 offsetT newval;
12146 unsigned int newimm;
12147 unsigned long temp;
12148 int sign;
12149 char * buf = fixP->fx_where + fixP->fx_frag->fr_literal;
12150 arm_fix_data * arm_data = (arm_fix_data *) fixP->tc_fix_data;
12152 assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
12154 /* Note whether this will delete the relocation. */
12155 #if 0
12156 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
12157 doesn't work fully.) */
12158 if ((fixP->fx_addsy == 0 || symbol_constant_p (fixP->fx_addsy))
12159 && !fixP->fx_pcrel)
12160 #else
12161 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
12162 #endif
12163 fixP->fx_done = 1;
12165 /* If this symbol is in a different section then we need to leave it for
12166 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
12167 so we have to undo it's effects here. */
12168 if (fixP->fx_pcrel)
12170 if (fixP->fx_addsy != NULL
12171 && S_IS_DEFINED (fixP->fx_addsy)
12172 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
12174 if (target_oabi
12175 && (fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
12176 || fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
12178 value = 0;
12179 else
12180 value += md_pcrel_from (fixP);
12184 /* Remember value for emit_reloc. */
12185 fixP->fx_addnumber = value;
12187 switch (fixP->fx_r_type)
12189 case BFD_RELOC_ARM_IMMEDIATE:
12190 newimm = validate_immediate (value);
12191 temp = md_chars_to_number (buf, INSN_SIZE);
12193 /* If the instruction will fail, see if we can fix things up by
12194 changing the opcode. */
12195 if (newimm == (unsigned int) FAIL
12196 && (newimm = negate_data_op (&temp, value)) == (unsigned int) FAIL)
12198 as_bad_where (fixP->fx_file, fixP->fx_line,
12199 _("invalid constant (%lx) after fixup"),
12200 (unsigned long) value);
12201 break;
12204 newimm |= (temp & 0xfffff000);
12205 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
12206 fixP->fx_done = 1;
12207 break;
12209 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
12211 unsigned int highpart = 0;
12212 unsigned int newinsn = 0xe1a00000; /* nop. */
12214 newimm = validate_immediate (value);
12215 temp = md_chars_to_number (buf, INSN_SIZE);
12217 /* If the instruction will fail, see if we can fix things up by
12218 changing the opcode. */
12219 if (newimm == (unsigned int) FAIL
12220 && (newimm = negate_data_op (& temp, value)) == (unsigned int) FAIL)
12222 /* No ? OK - try using two ADD instructions to generate
12223 the value. */
12224 newimm = validate_immediate_twopart (value, & highpart);
12226 /* Yes - then make sure that the second instruction is
12227 also an add. */
12228 if (newimm != (unsigned int) FAIL)
12229 newinsn = temp;
12230 /* Still No ? Try using a negated value. */
12231 else if ((newimm = validate_immediate_twopart (- value, & highpart)) != (unsigned int) FAIL)
12232 temp = newinsn = (temp & OPCODE_MASK) | OPCODE_SUB << DATA_OP_SHIFT;
12233 /* Otherwise - give up. */
12234 else
12236 as_bad_where (fixP->fx_file, fixP->fx_line,
12237 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
12238 (long) value);
12239 break;
12242 /* Replace the first operand in the 2nd instruction (which
12243 is the PC) with the destination register. We have
12244 already added in the PC in the first instruction and we
12245 do not want to do it again. */
12246 newinsn &= ~ 0xf0000;
12247 newinsn |= ((newinsn & 0x0f000) << 4);
12250 newimm |= (temp & 0xfffff000);
12251 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
12253 highpart |= (newinsn & 0xfffff000);
12254 md_number_to_chars (buf + INSN_SIZE, (valueT) highpart, INSN_SIZE);
12256 break;
12258 case BFD_RELOC_ARM_OFFSET_IMM:
12259 sign = value >= 0;
12261 if (value < 0)
12262 value = - value;
12264 if (validate_offset_imm (value, 0) == FAIL)
12266 as_bad_where (fixP->fx_file, fixP->fx_line,
12267 _("bad immediate value for offset (%ld)"),
12268 (long) value);
12269 break;
12272 newval = md_chars_to_number (buf, INSN_SIZE);
12273 newval &= 0xff7ff000;
12274 newval |= value | (sign ? INDEX_UP : 0);
12275 md_number_to_chars (buf, newval, INSN_SIZE);
12276 break;
12278 case BFD_RELOC_ARM_OFFSET_IMM8:
12279 case BFD_RELOC_ARM_HWLITERAL:
12280 sign = value >= 0;
12282 if (value < 0)
12283 value = - value;
12285 if (validate_offset_imm (value, 1) == FAIL)
12287 if (fixP->fx_r_type == BFD_RELOC_ARM_HWLITERAL)
12288 as_bad_where (fixP->fx_file, fixP->fx_line,
12289 _("invalid literal constant: pool needs to be closer"));
12290 else
12291 as_bad (_("bad immediate value for half-word offset (%ld)"),
12292 (long) value);
12293 break;
12296 newval = md_chars_to_number (buf, INSN_SIZE);
12297 newval &= 0xff7ff0f0;
12298 newval |= ((value >> 4) << 8) | (value & 0xf) | (sign ? INDEX_UP : 0);
12299 md_number_to_chars (buf, newval, INSN_SIZE);
12300 break;
12302 case BFD_RELOC_ARM_LITERAL:
12303 sign = value >= 0;
12305 if (value < 0)
12306 value = - value;
12308 if (validate_offset_imm (value, 0) == FAIL)
12310 as_bad_where (fixP->fx_file, fixP->fx_line,
12311 _("invalid literal constant: pool needs to be closer"));
12312 break;
12315 newval = md_chars_to_number (buf, INSN_SIZE);
12316 newval &= 0xff7ff000;
12317 newval |= value | (sign ? INDEX_UP : 0);
12318 md_number_to_chars (buf, newval, INSN_SIZE);
12319 break;
12321 case BFD_RELOC_ARM_SHIFT_IMM:
12322 newval = md_chars_to_number (buf, INSN_SIZE);
12323 if (((unsigned long) value) > 32
12324 || (value == 32
12325 && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60)))
12327 as_bad_where (fixP->fx_file, fixP->fx_line,
12328 _("shift expression is too large"));
12329 break;
12332 if (value == 0)
12333 /* Shifts of zero must be done as lsl. */
12334 newval &= ~0x60;
12335 else if (value == 32)
12336 value = 0;
12337 newval &= 0xfffff07f;
12338 newval |= (value & 0x1f) << 7;
12339 md_number_to_chars (buf, newval, INSN_SIZE);
12340 break;
12342 case BFD_RELOC_ARM_SWI:
12343 if (arm_data->thumb_mode)
12345 if (((unsigned long) value) > 0xff)
12346 as_bad_where (fixP->fx_file, fixP->fx_line,
12347 _("invalid swi expression"));
12348 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xff00;
12349 newval |= value;
12350 md_number_to_chars (buf, newval, THUMB_SIZE);
12352 else
12354 if (((unsigned long) value) > 0x00ffffff)
12355 as_bad_where (fixP->fx_file, fixP->fx_line,
12356 _("invalid swi expression"));
12357 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
12358 newval |= value;
12359 md_number_to_chars (buf, newval, INSN_SIZE);
12361 break;
12363 case BFD_RELOC_ARM_MULTI:
12364 if (((unsigned long) value) > 0xffff)
12365 as_bad_where (fixP->fx_file, fixP->fx_line,
12366 _("invalid expression in load/store multiple"));
12367 newval = value | md_chars_to_number (buf, INSN_SIZE);
12368 md_number_to_chars (buf, newval, INSN_SIZE);
12369 break;
12371 case BFD_RELOC_ARM_PCREL_BRANCH:
12372 newval = md_chars_to_number (buf, INSN_SIZE);
12374 /* Sign-extend a 24-bit number. */
12375 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
12377 #ifdef OBJ_ELF
12378 if (! target_oabi)
12379 value = fixP->fx_offset;
12380 #endif
12382 /* We are going to store value (shifted right by two) in the
12383 instruction, in a 24 bit, signed field. Thus we need to check
12384 that none of the top 8 bits of the shifted value (top 7 bits of
12385 the unshifted, unsigned value) are set, or that they are all set. */
12386 if ((value & ~ ((offsetT) 0x1ffffff)) != 0
12387 && ((value & ~ ((offsetT) 0x1ffffff)) != ~ ((offsetT) 0x1ffffff)))
12389 #ifdef OBJ_ELF
12390 /* Normally we would be stuck at this point, since we cannot store
12391 the absolute address that is the destination of the branch in the
12392 24 bits of the branch instruction. If however, we happen to know
12393 that the destination of the branch is in the same section as the
12394 branch instruction itself, then we can compute the relocation for
12395 ourselves and not have to bother the linker with it.
12397 FIXME: The tests for OBJ_ELF and ! target_oabi are only here
12398 because I have not worked out how to do this for OBJ_COFF or
12399 target_oabi. */
12400 if (! target_oabi
12401 && fixP->fx_addsy != NULL
12402 && S_IS_DEFINED (fixP->fx_addsy)
12403 && S_GET_SEGMENT (fixP->fx_addsy) == seg)
12405 /* Get pc relative value to go into the branch. */
12406 value = * valP;
12408 /* Permit a backward branch provided that enough bits
12409 are set. Allow a forwards branch, provided that
12410 enough bits are clear. */
12411 if ( (value & ~ ((offsetT) 0x1ffffff)) == ~ ((offsetT) 0x1ffffff)
12412 || (value & ~ ((offsetT) 0x1ffffff)) == 0)
12413 fixP->fx_done = 1;
12416 if (! fixP->fx_done)
12417 #endif
12418 as_bad_where (fixP->fx_file, fixP->fx_line,
12419 _("GAS can't handle same-section branch dest >= 0x04000000"));
12422 value >>= 2;
12423 value += SEXT24 (newval);
12425 if ( (value & ~ ((offsetT) 0xffffff)) != 0
12426 && ((value & ~ ((offsetT) 0xffffff)) != ~ ((offsetT) 0xffffff)))
12427 as_bad_where (fixP->fx_file, fixP->fx_line,
12428 _("out of range branch"));
12430 newval = (value & 0x00ffffff) | (newval & 0xff000000);
12431 md_number_to_chars (buf, newval, INSN_SIZE);
12432 break;
12434 case BFD_RELOC_ARM_PCREL_BLX:
12436 offsetT hbit;
12437 newval = md_chars_to_number (buf, INSN_SIZE);
12439 #ifdef OBJ_ELF
12440 if (! target_oabi)
12441 value = fixP->fx_offset;
12442 #endif
12443 hbit = (value >> 1) & 1;
12444 value = (value >> 2) & 0x00ffffff;
12445 value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
12446 newval = value | (newval & 0xfe000000) | (hbit << 24);
12447 md_number_to_chars (buf, newval, INSN_SIZE);
12449 break;
12451 case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch. */
12452 newval = md_chars_to_number (buf, THUMB_SIZE);
12454 addressT diff = (newval & 0xff) << 1;
12455 if (diff & 0x100)
12456 diff |= ~0xff;
12458 value += diff;
12459 if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
12460 as_bad_where (fixP->fx_file, fixP->fx_line,
12461 _("branch out of range"));
12462 newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
12464 md_number_to_chars (buf, newval, THUMB_SIZE);
12465 break;
12467 case BFD_RELOC_THUMB_PCREL_BRANCH12: /* Unconditional branch. */
12468 newval = md_chars_to_number (buf, THUMB_SIZE);
12470 addressT diff = (newval & 0x7ff) << 1;
12471 if (diff & 0x800)
12472 diff |= ~0x7ff;
12474 value += diff;
12475 if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
12476 as_bad_where (fixP->fx_file, fixP->fx_line,
12477 _("branch out of range"));
12478 newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
12480 md_number_to_chars (buf, newval, THUMB_SIZE);
12481 break;
12483 case BFD_RELOC_THUMB_PCREL_BLX:
12484 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12486 offsetT newval2;
12487 addressT diff;
12489 newval = md_chars_to_number (buf, THUMB_SIZE);
12490 newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
12491 diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
12492 if (diff & 0x400000)
12493 diff |= ~0x3fffff;
12494 #ifdef OBJ_ELF
12495 value = fixP->fx_offset;
12496 #endif
12497 value += diff;
12499 if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
12500 as_bad_where (fixP->fx_file, fixP->fx_line,
12501 _("branch with link out of range"));
12503 newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12);
12504 newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
12505 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
12506 /* For a BLX instruction, make sure that the relocation is rounded up
12507 to a word boundary. This follows the semantics of the instruction
12508 which specifies that bit 1 of the target address will come from bit
12509 1 of the base address. */
12510 newval2 = (newval2 + 1) & ~ 1;
12511 md_number_to_chars (buf, newval, THUMB_SIZE);
12512 md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
12514 break;
12516 case BFD_RELOC_8:
12517 if (fixP->fx_done || fixP->fx_pcrel)
12518 md_number_to_chars (buf, value, 1);
12519 #ifdef OBJ_ELF
12520 else if (!target_oabi)
12522 value = fixP->fx_offset;
12523 md_number_to_chars (buf, value, 1);
12525 #endif
12526 break;
12528 case BFD_RELOC_16:
12529 if (fixP->fx_done || fixP->fx_pcrel)
12530 md_number_to_chars (buf, value, 2);
12531 #ifdef OBJ_ELF
12532 else if (!target_oabi)
12534 value = fixP->fx_offset;
12535 md_number_to_chars (buf, value, 2);
12537 #endif
12538 break;
12540 #ifdef OBJ_ELF
12541 case BFD_RELOC_ARM_GOT32:
12542 case BFD_RELOC_ARM_GOTOFF:
12543 md_number_to_chars (buf, 0, 4);
12544 break;
12545 #endif
12547 case BFD_RELOC_RVA:
12548 case BFD_RELOC_32:
12549 if (fixP->fx_done || fixP->fx_pcrel)
12550 md_number_to_chars (buf, value, 4);
12551 #ifdef OBJ_ELF
12552 else if (!target_oabi)
12554 value = fixP->fx_offset;
12555 md_number_to_chars (buf, value, 4);
12557 #endif
12558 break;
12560 #ifdef OBJ_ELF
12561 case BFD_RELOC_ARM_PLT32:
12562 /* It appears the instruction is fully prepared at this point. */
12563 break;
12564 #endif
12566 case BFD_RELOC_ARM_CP_OFF_IMM:
12567 sign = value >= 0;
12568 if (value < -1023 || value > 1023 || (value & 3))
12569 as_bad_where (fixP->fx_file, fixP->fx_line,
12570 _("illegal value for co-processor offset"));
12571 if (value < 0)
12572 value = -value;
12573 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
12574 newval |= (value >> 2) | (sign ? INDEX_UP : 0);
12575 md_number_to_chars (buf, newval, INSN_SIZE);
12576 break;
12578 case BFD_RELOC_ARM_CP_OFF_IMM_S2:
12579 sign = value >= 0;
12580 if (value < -255 || value > 255)
12581 as_bad_where (fixP->fx_file, fixP->fx_line,
12582 _("Illegal value for co-processor offset"));
12583 if (value < 0)
12584 value = -value;
12585 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
12586 newval |= value | (sign ? INDEX_UP : 0);
12587 md_number_to_chars (buf, newval , INSN_SIZE);
12588 break;
12590 case BFD_RELOC_ARM_THUMB_OFFSET:
12591 newval = md_chars_to_number (buf, THUMB_SIZE);
12592 /* Exactly what ranges, and where the offset is inserted depends
12593 on the type of instruction, we can establish this from the
12594 top 4 bits. */
12595 switch (newval >> 12)
12597 case 4: /* PC load. */
12598 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
12599 forced to zero for these loads, so we will need to round
12600 up the offset if the instruction address is not word
12601 aligned (since the final address produced must be, and
12602 we can only describe word-aligned immediate offsets). */
12604 if ((fixP->fx_frag->fr_address + fixP->fx_where + value) & 3)
12605 as_bad_where (fixP->fx_file, fixP->fx_line,
12606 _("invalid offset, target not word aligned (0x%08X)"),
12607 (unsigned int) (fixP->fx_frag->fr_address
12608 + fixP->fx_where + value));
12610 if ((value + 2) & ~0x3fe)
12611 as_bad_where (fixP->fx_file, fixP->fx_line,
12612 _("invalid offset, value too big (0x%08lX)"),
12613 (long) value);
12615 /* Round up, since pc will be rounded down. */
12616 newval |= (value + 2) >> 2;
12617 break;
12619 case 9: /* SP load/store. */
12620 if (value & ~0x3fc)
12621 as_bad_where (fixP->fx_file, fixP->fx_line,
12622 _("invalid offset, value too big (0x%08lX)"),
12623 (long) value);
12624 newval |= value >> 2;
12625 break;
12627 case 6: /* Word load/store. */
12628 if (value & ~0x7c)
12629 as_bad_where (fixP->fx_file, fixP->fx_line,
12630 _("invalid offset, value too big (0x%08lX)"),
12631 (long) value);
12632 newval |= value << 4; /* 6 - 2. */
12633 break;
12635 case 7: /* Byte load/store. */
12636 if (value & ~0x1f)
12637 as_bad_where (fixP->fx_file, fixP->fx_line,
12638 _("invalid offset, value too big (0x%08lX)"),
12639 (long) value);
12640 newval |= value << 6;
12641 break;
12643 case 8: /* Halfword load/store. */
12644 if (value & ~0x3e)
12645 as_bad_where (fixP->fx_file, fixP->fx_line,
12646 _("invalid offset, value too big (0x%08lX)"),
12647 (long) value);
12648 newval |= value << 5; /* 6 - 1. */
12649 break;
12651 default:
12652 as_bad_where (fixP->fx_file, fixP->fx_line,
12653 "Unable to process relocation for thumb opcode: %lx",
12654 (unsigned long) newval);
12655 break;
12657 md_number_to_chars (buf, newval, THUMB_SIZE);
12658 break;
12660 case BFD_RELOC_ARM_THUMB_ADD:
12661 /* This is a complicated relocation, since we use it for all of
12662 the following immediate relocations:
12664 3bit ADD/SUB
12665 8bit ADD/SUB
12666 9bit ADD/SUB SP word-aligned
12667 10bit ADD PC/SP word-aligned
12669 The type of instruction being processed is encoded in the
12670 instruction field:
12672 0x8000 SUB
12673 0x00F0 Rd
12674 0x000F Rs
12676 newval = md_chars_to_number (buf, THUMB_SIZE);
12678 int rd = (newval >> 4) & 0xf;
12679 int rs = newval & 0xf;
12680 int subtract = newval & 0x8000;
12682 if (rd == REG_SP)
12684 if (value & ~0x1fc)
12685 as_bad_where (fixP->fx_file, fixP->fx_line,
12686 _("invalid immediate for stack address calculation"));
12687 newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
12688 newval |= value >> 2;
12690 else if (rs == REG_PC || rs == REG_SP)
12692 if (subtract ||
12693 value & ~0x3fc)
12694 as_bad_where (fixP->fx_file, fixP->fx_line,
12695 _("invalid immediate for address calculation (value = 0x%08lX)"),
12696 (unsigned long) value);
12697 newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP);
12698 newval |= rd << 8;
12699 newval |= value >> 2;
12701 else if (rs == rd)
12703 if (value & ~0xff)
12704 as_bad_where (fixP->fx_file, fixP->fx_line,
12705 _("invalid 8bit immediate"));
12706 newval = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
12707 newval |= (rd << 8) | value;
12709 else
12711 if (value & ~0x7)
12712 as_bad_where (fixP->fx_file, fixP->fx_line,
12713 _("invalid 3bit immediate"));
12714 newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
12715 newval |= rd | (rs << 3) | (value << 6);
12718 md_number_to_chars (buf, newval, THUMB_SIZE);
12719 break;
12721 case BFD_RELOC_ARM_THUMB_IMM:
12722 newval = md_chars_to_number (buf, THUMB_SIZE);
12723 switch (newval >> 11)
12725 case 0x04: /* 8bit immediate MOV. */
12726 case 0x05: /* 8bit immediate CMP. */
12727 if (value < 0 || value > 255)
12728 as_bad_where (fixP->fx_file, fixP->fx_line,
12729 _("invalid immediate: %ld is too large"),
12730 (long) value);
12731 newval |= value;
12732 break;
12734 default:
12735 abort ();
12737 md_number_to_chars (buf, newval, THUMB_SIZE);
12738 break;
12740 case BFD_RELOC_ARM_THUMB_SHIFT:
12741 /* 5bit shift value (0..31). */
12742 if (value < 0 || value > 31)
12743 as_bad_where (fixP->fx_file, fixP->fx_line,
12744 _("illegal Thumb shift value: %ld"), (long) value);
12745 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xf03f;
12746 newval |= value << 6;
12747 md_number_to_chars (buf, newval, THUMB_SIZE);
12748 break;
12750 case BFD_RELOC_VTABLE_INHERIT:
12751 case BFD_RELOC_VTABLE_ENTRY:
12752 fixP->fx_done = 0;
12753 return;
12755 case BFD_RELOC_NONE:
12756 default:
12757 as_bad_where (fixP->fx_file, fixP->fx_line,
12758 _("bad relocation fixup type (%d)"), fixP->fx_r_type);
12762 /* Translate internal representation of relocation info to BFD target
12763 format. */
12765 arelent *
12766 tc_gen_reloc (section, fixp)
12767 asection * section ATTRIBUTE_UNUSED;
12768 fixS * fixp;
12770 arelent * reloc;
12771 bfd_reloc_code_real_type code;
12773 reloc = (arelent *) xmalloc (sizeof (arelent));
12775 reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
12776 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
12777 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
12779 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12780 #ifndef OBJ_ELF
12781 if (fixp->fx_pcrel == 0)
12782 reloc->addend = fixp->fx_offset;
12783 else
12784 reloc->addend = fixp->fx_offset = reloc->address;
12785 #else /* OBJ_ELF */
12786 reloc->addend = fixp->fx_offset;
12787 #endif
12789 switch (fixp->fx_r_type)
12791 case BFD_RELOC_8:
12792 if (fixp->fx_pcrel)
12794 code = BFD_RELOC_8_PCREL;
12795 break;
12798 case BFD_RELOC_16:
12799 if (fixp->fx_pcrel)
12801 code = BFD_RELOC_16_PCREL;
12802 break;
12805 case BFD_RELOC_32:
12806 if (fixp->fx_pcrel)
12808 code = BFD_RELOC_32_PCREL;
12809 break;
12812 case BFD_RELOC_ARM_PCREL_BRANCH:
12813 case BFD_RELOC_ARM_PCREL_BLX:
12814 case BFD_RELOC_RVA:
12815 case BFD_RELOC_THUMB_PCREL_BRANCH9:
12816 case BFD_RELOC_THUMB_PCREL_BRANCH12:
12817 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12818 case BFD_RELOC_THUMB_PCREL_BLX:
12819 case BFD_RELOC_VTABLE_ENTRY:
12820 case BFD_RELOC_VTABLE_INHERIT:
12821 code = fixp->fx_r_type;
12822 break;
12824 case BFD_RELOC_ARM_LITERAL:
12825 case BFD_RELOC_ARM_HWLITERAL:
12826 /* If this is called then the a literal has
12827 been referenced across a section boundary. */
12828 as_bad_where (fixp->fx_file, fixp->fx_line,
12829 _("literal referenced across section boundary"));
12830 return NULL;
12832 #ifdef OBJ_ELF
12833 case BFD_RELOC_ARM_GOT32:
12834 case BFD_RELOC_ARM_GOTOFF:
12835 case BFD_RELOC_ARM_PLT32:
12836 code = fixp->fx_r_type;
12837 break;
12838 #endif
12840 case BFD_RELOC_ARM_IMMEDIATE:
12841 as_bad_where (fixp->fx_file, fixp->fx_line,
12842 _("internal relocation (type: IMMEDIATE) not fixed up"));
12843 return NULL;
12845 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
12846 as_bad_where (fixp->fx_file, fixp->fx_line,
12847 _("ADRL used for a symbol not defined in the same file"));
12848 return NULL;
12850 case BFD_RELOC_ARM_OFFSET_IMM:
12851 as_bad_where (fixp->fx_file, fixp->fx_line,
12852 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
12853 return NULL;
12855 default:
12857 char * type;
12859 switch (fixp->fx_r_type)
12861 case BFD_RELOC_ARM_OFFSET_IMM8: type = "OFFSET_IMM8"; break;
12862 case BFD_RELOC_ARM_SHIFT_IMM: type = "SHIFT_IMM"; break;
12863 case BFD_RELOC_ARM_SWI: type = "SWI"; break;
12864 case BFD_RELOC_ARM_MULTI: type = "MULTI"; break;
12865 case BFD_RELOC_ARM_CP_OFF_IMM: type = "CP_OFF_IMM"; break;
12866 case BFD_RELOC_ARM_THUMB_ADD: type = "THUMB_ADD"; break;
12867 case BFD_RELOC_ARM_THUMB_SHIFT: type = "THUMB_SHIFT"; break;
12868 case BFD_RELOC_ARM_THUMB_IMM: type = "THUMB_IMM"; break;
12869 case BFD_RELOC_ARM_THUMB_OFFSET: type = "THUMB_OFFSET"; break;
12870 default: type = _("<unknown>"); break;
12872 as_bad_where (fixp->fx_file, fixp->fx_line,
12873 _("cannot represent %s relocation in this object file format"),
12874 type);
12875 return NULL;
12879 #ifdef OBJ_ELF
12880 if ((code == BFD_RELOC_32_PCREL || code == BFD_RELOC_32)
12881 && GOT_symbol
12882 && fixp->fx_addsy == GOT_symbol)
12884 code = BFD_RELOC_ARM_GOTPC;
12885 reloc->addend = fixp->fx_offset = reloc->address;
12887 #endif
12889 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
12891 if (reloc->howto == NULL)
12893 as_bad_where (fixp->fx_file, fixp->fx_line,
12894 _("cannot represent %s relocation in this object file format"),
12895 bfd_get_reloc_code_name (code));
12896 return NULL;
12899 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12900 vtable entry to be used in the relocation's section offset. */
12901 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
12902 reloc->address = fixp->fx_offset;
12904 return reloc;
12908 md_estimate_size_before_relax (fragP, segtype)
12909 fragS * fragP ATTRIBUTE_UNUSED;
12910 segT segtype ATTRIBUTE_UNUSED;
12912 as_fatal (_("md_estimate_size_before_relax\n"));
12913 return 1;
12916 static void
12917 output_inst (str)
12918 const char *str;
12920 char * to = NULL;
12922 if (inst.error)
12924 as_bad ("%s -- `%s'", inst.error, str);
12925 return;
12928 to = frag_more (inst.size);
12930 if (thumb_mode && (inst.size > THUMB_SIZE))
12932 assert (inst.size == (2 * THUMB_SIZE));
12933 md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE);
12934 md_number_to_chars (to + THUMB_SIZE, inst.instruction, THUMB_SIZE);
12936 else if (inst.size > INSN_SIZE)
12938 assert (inst.size == (2 * INSN_SIZE));
12939 md_number_to_chars (to, inst.instruction, INSN_SIZE);
12940 md_number_to_chars (to + INSN_SIZE, inst.instruction, INSN_SIZE);
12942 else
12943 md_number_to_chars (to, inst.instruction, inst.size);
12945 if (inst.reloc.type != BFD_RELOC_NONE)
12946 fix_new_arm (frag_now, to - frag_now->fr_literal,
12947 inst.size, & inst.reloc.exp, inst.reloc.pc_rel,
12948 inst.reloc.type);
12950 #ifdef OBJ_ELF
12951 dwarf2_emit_insn (inst.size);
12952 #endif
12955 void
12956 md_assemble (str)
12957 char * str;
12959 char c;
12960 char *p;
12961 char *start;
12963 /* Align the instruction.
12964 This may not be the right thing to do but ... */
12965 #if 0
12966 arm_align (2, 0);
12967 #endif
12969 /* Align the previous label if needed. */
12970 if (last_label_seen != NULL)
12972 symbol_set_frag (last_label_seen, frag_now);
12973 S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ());
12974 S_SET_SEGMENT (last_label_seen, now_seg);
12977 memset (&inst, '\0', sizeof (inst));
12978 inst.reloc.type = BFD_RELOC_NONE;
12980 skip_whitespace (str);
12982 /* Scan up to the end of the op-code, which must end in white space or
12983 end of string. */
12984 for (start = p = str; *p != '\0'; p++)
12985 if (*p == ' ')
12986 break;
12988 if (p == str)
12990 as_bad (_("no operator -- statement `%s'\n"), str);
12991 return;
12994 if (thumb_mode)
12996 const struct thumb_opcode * opcode;
12998 c = *p;
12999 *p = '\0';
13000 opcode = (const struct thumb_opcode *) hash_find (arm_tops_hsh, str);
13001 *p = c;
13003 if (opcode)
13005 /* Check that this instruction is supported for this CPU. */
13006 if (thumb_mode == 1 && (opcode->variant & cpu_variant) == 0)
13008 as_bad (_("selected processor does not support `%s'"), str);
13009 return;
13012 mapping_state (MAP_THUMB);
13013 inst.instruction = opcode->value;
13014 inst.size = opcode->size;
13015 (*opcode->parms) (p);
13016 output_inst (str);
13017 return;
13020 else
13022 const struct asm_opcode * opcode;
13024 c = *p;
13025 *p = '\0';
13026 opcode = (const struct asm_opcode *) hash_find (arm_ops_hsh, str);
13027 *p = c;
13029 if (opcode)
13031 /* Check that this instruction is supported for this CPU. */
13032 if ((opcode->variant & cpu_variant) == 0)
13034 as_bad (_("selected processor does not support `%s'"), str);
13035 return;
13038 mapping_state (MAP_ARM);
13039 inst.instruction = opcode->value;
13040 inst.size = INSN_SIZE;
13041 (*opcode->parms) (p);
13042 output_inst (str);
13043 return;
13047 /* It wasn't an instruction, but it might be a register alias of the form
13048 alias .req reg. */
13049 if (create_register_alias (str, p))
13050 return;
13052 as_bad (_("bad instruction `%s'"), start);
13055 /* md_parse_option
13056 Invocation line includes a switch not recognized by the base assembler.
13057 See if it's a processor-specific option.
13059 This routine is somewhat complicated by the need for backwards
13060 compatibility (since older releases of gcc can't be changed).
13061 The new options try to make the interface as compatible as
13062 possible with GCC.
13064 New options (supported) are:
13066 -mcpu=<cpu name> Assemble for selected processor
13067 -march=<architecture name> Assemble for selected architecture
13068 -mfpu=<fpu architecture> Assemble for selected FPU.
13069 -EB/-mbig-endian Big-endian
13070 -EL/-mlittle-endian Little-endian
13071 -k Generate PIC code
13072 -mthumb Start in Thumb mode
13073 -mthumb-interwork Code supports ARM/Thumb interworking
13075 For now we will also provide support for:
13077 -mapcs-32 32-bit Program counter
13078 -mapcs-26 26-bit Program counter
13079 -macps-float Floats passed in FP registers
13080 -mapcs-reentrant Reentrant code
13081 -matpcs
13082 (sometime these will probably be replaced with -mapcs=<list of options>
13083 and -matpcs=<list of options>)
13085 The remaining options are only supported for back-wards compatibility.
13086 Cpu variants, the arm part is optional:
13087 -m[arm]1 Currently not supported.
13088 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
13089 -m[arm]3 Arm 3 processor
13090 -m[arm]6[xx], Arm 6 processors
13091 -m[arm]7[xx][t][[d]m] Arm 7 processors
13092 -m[arm]8[10] Arm 8 processors
13093 -m[arm]9[20][tdmi] Arm 9 processors
13094 -mstrongarm[110[0]] StrongARM processors
13095 -mxscale XScale processors
13096 -m[arm]v[2345[t[e]]] Arm architectures
13097 -mall All (except the ARM1)
13098 FP variants:
13099 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
13100 -mfpe-old (No float load/store multiples)
13101 -mvfpxd VFP Single precision
13102 -mvfp All VFP
13103 -mno-fpu Disable all floating point instructions
13105 The following CPU names are recognized:
13106 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
13107 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
13108 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
13109 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
13110 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
13111 arm10t arm10e, arm1020t, arm1020e, arm10200e,
13112 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
13116 const char * md_shortopts = "m:k";
13118 #ifdef ARM_BI_ENDIAN
13119 #define OPTION_EB (OPTION_MD_BASE + 0)
13120 #define OPTION_EL (OPTION_MD_BASE + 1)
13121 #else
13122 #if TARGET_BYTES_BIG_ENDIAN
13123 #define OPTION_EB (OPTION_MD_BASE + 0)
13124 #else
13125 #define OPTION_EL (OPTION_MD_BASE + 1)
13126 #endif
13127 #endif
13129 struct option md_longopts[] =
13131 #ifdef OPTION_EB
13132 {"EB", no_argument, NULL, OPTION_EB},
13133 #endif
13134 #ifdef OPTION_EL
13135 {"EL", no_argument, NULL, OPTION_EL},
13136 #endif
13137 {NULL, no_argument, NULL, 0}
13140 size_t md_longopts_size = sizeof (md_longopts);
13142 struct arm_option_table
13144 char *option; /* Option name to match. */
13145 char *help; /* Help information. */
13146 int *var; /* Variable to change. */
13147 int value; /* What to change it to. */
13148 char *deprecated; /* If non-null, print this message. */
13151 struct arm_option_table arm_opts[] =
13153 {"k", N_("generate PIC code"), &pic_code, 1, NULL},
13154 {"mthumb", N_("assemble Thumb code"), &thumb_mode, 1, NULL},
13155 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
13156 &support_interwork, 1, NULL},
13157 {"moabi", N_("use old ABI (ELF only)"), &target_oabi, 1, NULL},
13158 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26, 0, NULL},
13159 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26, 1, NULL},
13160 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float,
13161 1, NULL},
13162 {"mapcs-reentrant", N_("re-entrant code"), &pic_code, 1, NULL},
13163 {"matpcs", N_("code is ATPCS conformant"), &atpcs, 1, NULL},
13164 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian, 1, NULL},
13165 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian, 1,
13166 NULL},
13168 /* These are recognized by the assembler, but have no affect on code. */
13169 {"mapcs-frame", N_("use frame pointer"), NULL, 0, NULL},
13170 {"mapcs-stack-check", N_("use stack size checking"), NULL, 0, NULL},
13172 /* DON'T add any new processors to this list -- we want the whole list
13173 to go away... Add them to the processors table instead. */
13174 {"marm1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
13175 {"m1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
13176 {"marm2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
13177 {"m2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
13178 {"marm250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
13179 {"m250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
13180 {"marm3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
13181 {"m3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
13182 {"marm6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
13183 {"m6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
13184 {"marm600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
13185 {"m600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
13186 {"marm610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
13187 {"m610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
13188 {"marm620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
13189 {"m620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
13190 {"marm7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
13191 {"m7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
13192 {"marm70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
13193 {"m70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
13194 {"marm700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
13195 {"m700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
13196 {"marm700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
13197 {"m700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
13198 {"marm710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
13199 {"m710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
13200 {"marm710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
13201 {"m710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
13202 {"marm720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
13203 {"m720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
13204 {"marm7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
13205 {"m7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
13206 {"marm7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
13207 {"m7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
13208 {"marm7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
13209 {"m7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
13210 {"marm7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
13211 {"m7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
13212 {"marm7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
13213 {"m7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
13214 {"marm7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
13215 {"m7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
13216 {"marm7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
13217 {"m7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
13218 {"marm7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
13219 {"m7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
13220 {"marm7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13221 {"m7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13222 {"marm7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13223 {"m7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13224 {"marm710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
13225 {"m710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
13226 {"marm720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
13227 {"m720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
13228 {"marm740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
13229 {"m740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
13230 {"marm8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
13231 {"m8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
13232 {"marm810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
13233 {"m810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
13234 {"marm9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
13235 {"m9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
13236 {"marm9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
13237 {"m9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
13238 {"marm920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
13239 {"m920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
13240 {"marm940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
13241 {"m940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
13242 {"mstrongarm", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=strongarm")},
13243 {"mstrongarm110", NULL, &legacy_cpu, ARM_ARCH_V4,
13244 N_("use -mcpu=strongarm110")},
13245 {"mstrongarm1100", NULL, &legacy_cpu, ARM_ARCH_V4,
13246 N_("use -mcpu=strongarm1100")},
13247 {"mstrongarm1110", NULL, &legacy_cpu, ARM_ARCH_V4,
13248 N_("use -mcpu=strongarm1110")},
13249 {"mxscale", NULL, &legacy_cpu, ARM_ARCH_XSCALE, N_("use -mcpu=xscale")},
13250 {"miwmmxt", NULL, &legacy_cpu, ARM_ARCH_IWMMXT, N_("use -mcpu=iwmmxt")},
13251 {"mall", NULL, &legacy_cpu, ARM_ANY, N_("use -mcpu=all")},
13253 /* Architecture variants -- don't add any more to this list either. */
13254 {"mv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
13255 {"marmv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
13256 {"mv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
13257 {"marmv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
13258 {"mv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
13259 {"marmv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
13260 {"mv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
13261 {"marmv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
13262 {"mv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
13263 {"marmv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
13264 {"mv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
13265 {"marmv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
13266 {"mv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
13267 {"marmv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
13268 {"mv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
13269 {"marmv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
13270 {"mv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
13271 {"marmv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
13273 /* Floating point variants -- don't add any more to this list either. */
13274 {"mfpe-old", NULL, &legacy_fpu, FPU_ARCH_FPE, N_("use -mfpu=fpe")},
13275 {"mfpa10", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa10")},
13276 {"mfpa11", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa11")},
13277 {"mno-fpu", NULL, &legacy_fpu, 0,
13278 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
13280 {NULL, NULL, NULL, 0, NULL}
13283 struct arm_cpu_option_table
13285 char *name;
13286 int value;
13287 /* For some CPUs we assume an FPU unless the user explicitly sets
13288 -mfpu=... */
13289 int default_fpu;
13292 /* This list should, at a minimum, contain all the cpu names
13293 recognized by GCC. */
13294 static struct arm_cpu_option_table arm_cpus[] =
13296 {"all", ARM_ANY, FPU_ARCH_FPA},
13297 {"arm1", ARM_ARCH_V1, FPU_ARCH_FPA},
13298 {"arm2", ARM_ARCH_V2, FPU_ARCH_FPA},
13299 {"arm250", ARM_ARCH_V2S, FPU_ARCH_FPA},
13300 {"arm3", ARM_ARCH_V2S, FPU_ARCH_FPA},
13301 {"arm6", ARM_ARCH_V3, FPU_ARCH_FPA},
13302 {"arm60", ARM_ARCH_V3, FPU_ARCH_FPA},
13303 {"arm600", ARM_ARCH_V3, FPU_ARCH_FPA},
13304 {"arm610", ARM_ARCH_V3, FPU_ARCH_FPA},
13305 {"arm620", ARM_ARCH_V3, FPU_ARCH_FPA},
13306 {"arm7", ARM_ARCH_V3, FPU_ARCH_FPA},
13307 {"arm7m", ARM_ARCH_V3M, FPU_ARCH_FPA},
13308 {"arm7d", ARM_ARCH_V3, FPU_ARCH_FPA},
13309 {"arm7dm", ARM_ARCH_V3M, FPU_ARCH_FPA},
13310 {"arm7di", ARM_ARCH_V3, FPU_ARCH_FPA},
13311 {"arm7dmi", ARM_ARCH_V3M, FPU_ARCH_FPA},
13312 {"arm70", ARM_ARCH_V3, FPU_ARCH_FPA},
13313 {"arm700", ARM_ARCH_V3, FPU_ARCH_FPA},
13314 {"arm700i", ARM_ARCH_V3, FPU_ARCH_FPA},
13315 {"arm710", ARM_ARCH_V3, FPU_ARCH_FPA},
13316 {"arm710t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13317 {"arm720", ARM_ARCH_V3, FPU_ARCH_FPA},
13318 {"arm720t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13319 {"arm740t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13320 {"arm710c", ARM_ARCH_V3, FPU_ARCH_FPA},
13321 {"arm7100", ARM_ARCH_V3, FPU_ARCH_FPA},
13322 {"arm7500", ARM_ARCH_V3, FPU_ARCH_FPA},
13323 {"arm7500fe", ARM_ARCH_V3, FPU_ARCH_FPA},
13324 {"arm7t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13325 {"arm7tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
13326 {"arm8", ARM_ARCH_V4, FPU_ARCH_FPA},
13327 {"arm810", ARM_ARCH_V4, FPU_ARCH_FPA},
13328 {"strongarm", ARM_ARCH_V4, FPU_ARCH_FPA},
13329 {"strongarm1", ARM_ARCH_V4, FPU_ARCH_FPA},
13330 {"strongarm110", ARM_ARCH_V4, FPU_ARCH_FPA},
13331 {"strongarm1100", ARM_ARCH_V4, FPU_ARCH_FPA},
13332 {"strongarm1110", ARM_ARCH_V4, FPU_ARCH_FPA},
13333 {"arm9", ARM_ARCH_V4T, FPU_ARCH_FPA},
13334 {"arm920", ARM_ARCH_V4T, FPU_ARCH_FPA},
13335 {"arm920t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13336 {"arm922t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13337 {"arm940t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13338 {"arm9tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
13339 /* For V5 or later processors we default to using VFP; but the user
13340 should really set the FPU type explicitly. */
13341 {"arm9e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13342 {"arm9e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13343 {"arm926ej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
13344 {"arm946e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13345 {"arm946e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13346 {"arm966e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13347 {"arm966e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13348 {"arm10t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
13349 {"arm10e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13350 {"arm1020", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13351 {"arm1020t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
13352 {"arm1020e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13353 {"arm1136js", ARM_ARCH_V6, FPU_NONE},
13354 {"arm1136jfs", ARM_ARCH_V6, FPU_ARCH_VFP_V2},
13355 /* ??? XSCALE is really an architecture. */
13356 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
13357 /* ??? iwmmxt is not a processor. */
13358 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP_V2},
13359 {"i80200", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
13360 /* Maverick */
13361 {"ep9312", ARM_ARCH_V4T | ARM_CEXT_MAVERICK, FPU_NONE},
13362 {NULL, 0, 0}
13365 struct arm_arch_option_table
13367 char *name;
13368 int value;
13369 int default_fpu;
13372 /* This list should, at a minimum, contain all the architecture names
13373 recognized by GCC. */
13374 static struct arm_arch_option_table arm_archs[] =
13376 {"all", ARM_ANY, FPU_ARCH_FPA},
13377 {"armv1", ARM_ARCH_V1, FPU_ARCH_FPA},
13378 {"armv2", ARM_ARCH_V2, FPU_ARCH_FPA},
13379 {"armv2a", ARM_ARCH_V2S, FPU_ARCH_FPA},
13380 {"armv2s", ARM_ARCH_V2S, FPU_ARCH_FPA},
13381 {"armv3", ARM_ARCH_V3, FPU_ARCH_FPA},
13382 {"armv3m", ARM_ARCH_V3M, FPU_ARCH_FPA},
13383 {"armv4", ARM_ARCH_V4, FPU_ARCH_FPA},
13384 {"armv4xm", ARM_ARCH_V4xM, FPU_ARCH_FPA},
13385 {"armv4t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13386 {"armv4txm", ARM_ARCH_V4TxM, FPU_ARCH_FPA},
13387 {"armv5", ARM_ARCH_V5, FPU_ARCH_VFP},
13388 {"armv5t", ARM_ARCH_V5T, FPU_ARCH_VFP},
13389 {"armv5txm", ARM_ARCH_V5TxM, FPU_ARCH_VFP},
13390 {"armv5te", ARM_ARCH_V5TE, FPU_ARCH_VFP},
13391 {"armv5texp", ARM_ARCH_V5TExP, FPU_ARCH_VFP},
13392 {"armv5tej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP},
13393 {"armv6", ARM_ARCH_V6, FPU_ARCH_VFP},
13394 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP},
13395 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP},
13396 {NULL, 0, 0}
13399 /* ISA extensions in the co-processor space. */
13400 struct arm_arch_extension_table
13402 char *name;
13403 int value;
13406 static struct arm_arch_extension_table arm_extensions[] =
13408 {"maverick", ARM_CEXT_MAVERICK},
13409 {"xscale", ARM_CEXT_XSCALE},
13410 {"iwmmxt", ARM_CEXT_IWMMXT},
13411 {NULL, 0}
13414 struct arm_fpu_option_table
13416 char *name;
13417 int value;
13420 /* This list should, at a minimum, contain all the fpu names
13421 recognized by GCC. */
13422 static struct arm_fpu_option_table arm_fpus[] =
13424 {"softfpa", FPU_NONE},
13425 {"fpe", FPU_ARCH_FPE},
13426 {"fpe2", FPU_ARCH_FPE},
13427 {"fpe3", FPU_ARCH_FPA}, /* Third release supports LFM/SFM. */
13428 {"fpa", FPU_ARCH_FPA},
13429 {"fpa10", FPU_ARCH_FPA},
13430 {"fpa11", FPU_ARCH_FPA},
13431 {"arm7500fe", FPU_ARCH_FPA},
13432 {"softvfp", FPU_ARCH_VFP},
13433 {"softvfp+vfp", FPU_ARCH_VFP_V2},
13434 {"vfp", FPU_ARCH_VFP_V2},
13435 {"vfp9", FPU_ARCH_VFP_V2},
13436 {"vfp10", FPU_ARCH_VFP_V2},
13437 {"vfp10-r0", FPU_ARCH_VFP_V1},
13438 {"vfpxd", FPU_ARCH_VFP_V1xD},
13439 {"arm1020t", FPU_ARCH_VFP_V1},
13440 {"arm1020e", FPU_ARCH_VFP_V2},
13441 {"arm1136jfs", FPU_ARCH_VFP_V2},
13442 {NULL, 0}
13445 struct arm_long_option_table
13447 char *option; /* Substring to match. */
13448 char *help; /* Help information. */
13449 int (*func) PARAMS ((char *subopt)); /* Function to decode sub-option. */
13450 char *deprecated; /* If non-null, print this message. */
13453 static int
13454 arm_parse_extension (str, opt_p)
13455 char *str;
13456 int *opt_p;
13458 while (str != NULL && *str != 0)
13460 struct arm_arch_extension_table *opt;
13461 char *ext;
13462 int optlen;
13464 if (*str != '+')
13466 as_bad (_("invalid architectural extension"));
13467 return 0;
13470 str++;
13471 ext = strchr (str, '+');
13473 if (ext != NULL)
13474 optlen = ext - str;
13475 else
13476 optlen = strlen (str);
13478 if (optlen == 0)
13480 as_bad (_("missing architectural extension"));
13481 return 0;
13484 for (opt = arm_extensions; opt->name != NULL; opt++)
13485 if (strncmp (opt->name, str, optlen) == 0)
13487 *opt_p |= opt->value;
13488 break;
13491 if (opt->name == NULL)
13493 as_bad (_("unknown architectural extnsion `%s'"), str);
13494 return 0;
13497 str = ext;
13500 return 1;
13503 static int
13504 arm_parse_cpu (str)
13505 char *str;
13507 struct arm_cpu_option_table *opt;
13508 char *ext = strchr (str, '+');
13509 int optlen;
13511 if (ext != NULL)
13512 optlen = ext - str;
13513 else
13514 optlen = strlen (str);
13516 if (optlen == 0)
13518 as_bad (_("missing cpu name `%s'"), str);
13519 return 0;
13522 for (opt = arm_cpus; opt->name != NULL; opt++)
13523 if (strncmp (opt->name, str, optlen) == 0)
13525 mcpu_cpu_opt = opt->value;
13526 mcpu_fpu_opt = opt->default_fpu;
13528 if (ext != NULL)
13529 return arm_parse_extension (ext, &mcpu_cpu_opt);
13531 return 1;
13534 as_bad (_("unknown cpu `%s'"), str);
13535 return 0;
13538 static int
13539 arm_parse_arch (str)
13540 char *str;
13542 struct arm_arch_option_table *opt;
13543 char *ext = strchr (str, '+');
13544 int optlen;
13546 if (ext != NULL)
13547 optlen = ext - str;
13548 else
13549 optlen = strlen (str);
13551 if (optlen == 0)
13553 as_bad (_("missing architecture name `%s'"), str);
13554 return 0;
13558 for (opt = arm_archs; opt->name != NULL; opt++)
13559 if (strcmp (opt->name, str) == 0)
13561 march_cpu_opt = opt->value;
13562 march_fpu_opt = opt->default_fpu;
13564 if (ext != NULL)
13565 return arm_parse_extension (ext, &march_cpu_opt);
13567 return 1;
13570 as_bad (_("unknown architecture `%s'\n"), str);
13571 return 0;
13574 static int
13575 arm_parse_fpu (str)
13576 char *str;
13578 struct arm_fpu_option_table *opt;
13580 for (opt = arm_fpus; opt->name != NULL; opt++)
13581 if (strcmp (opt->name, str) == 0)
13583 mfpu_opt = opt->value;
13584 return 1;
13587 as_bad (_("unknown floating point format `%s'\n"), str);
13588 return 0;
13591 struct arm_long_option_table arm_long_opts[] =
13593 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13594 arm_parse_cpu, NULL},
13595 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13596 arm_parse_arch, NULL},
13597 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13598 arm_parse_fpu, NULL},
13599 {NULL, NULL, 0, NULL}
13603 md_parse_option (c, arg)
13604 int c;
13605 char * arg;
13607 struct arm_option_table *opt;
13608 struct arm_long_option_table *lopt;
13610 switch (c)
13612 #ifdef OPTION_EB
13613 case OPTION_EB:
13614 target_big_endian = 1;
13615 break;
13616 #endif
13618 #ifdef OPTION_EL
13619 case OPTION_EL:
13620 target_big_endian = 0;
13621 break;
13622 #endif
13624 case 'a':
13625 /* Listing option. Just ignore these, we don't support additional
13626 ones. */
13627 return 0;
13629 default:
13630 for (opt = arm_opts; opt->option != NULL; opt++)
13632 if (c == opt->option[0]
13633 && ((arg == NULL && opt->option[1] == 0)
13634 || strcmp (arg, opt->option + 1) == 0))
13636 #if WARN_DEPRECATED
13637 /* If the option is deprecated, tell the user. */
13638 if (opt->deprecated != NULL)
13639 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c,
13640 arg ? arg : "", _(opt->deprecated));
13641 #endif
13643 if (opt->var != NULL)
13644 *opt->var = opt->value;
13646 return 1;
13650 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13652 /* These options are expected to have an argument. */
13653 if (c == lopt->option[0]
13654 && arg != NULL
13655 && strncmp (arg, lopt->option + 1,
13656 strlen (lopt->option + 1)) == 0)
13658 #if WARN_DEPRECATED
13659 /* If the option is deprecated, tell the user. */
13660 if (lopt->deprecated != NULL)
13661 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c, arg,
13662 _(lopt->deprecated));
13663 #endif
13665 /* Call the sup-option parser. */
13666 return (*lopt->func)(arg + strlen (lopt->option) - 1);
13670 as_bad (_("unrecognized option `-%c%s'"), c, arg ? arg : "");
13671 return 0;
13674 return 1;
13677 void
13678 md_show_usage (fp)
13679 FILE * fp;
13681 struct arm_option_table *opt;
13682 struct arm_long_option_table *lopt;
13684 fprintf (fp, _(" ARM-specific assembler options:\n"));
13686 for (opt = arm_opts; opt->option != NULL; opt++)
13687 if (opt->help != NULL)
13688 fprintf (fp, " -%-23s%s\n", opt->option, _(opt->help));
13690 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13691 if (lopt->help != NULL)
13692 fprintf (fp, " -%s%s\n", lopt->option, _(lopt->help));
13694 #ifdef OPTION_EB
13695 fprintf (fp, _("\
13696 -EB assemble code for a big-endian cpu\n"));
13697 #endif
13699 #ifdef OPTION_EL
13700 fprintf (fp, _("\
13701 -EL assemble code for a little-endian cpu\n"));
13702 #endif
13705 /* We need to be able to fix up arbitrary expressions in some statements.
13706 This is so that we can handle symbols that are an arbitrary distance from
13707 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
13708 which returns part of an address in a form which will be valid for
13709 a data instruction. We do this by pushing the expression into a symbol
13710 in the expr_section, and creating a fix for that. */
13712 static void
13713 fix_new_arm (frag, where, size, exp, pc_rel, reloc)
13714 fragS * frag;
13715 int where;
13716 short int size;
13717 expressionS * exp;
13718 int pc_rel;
13719 int reloc;
13721 fixS * new_fix;
13722 arm_fix_data * arm_data;
13724 switch (exp->X_op)
13726 case O_constant:
13727 case O_symbol:
13728 case O_add:
13729 case O_subtract:
13730 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
13731 break;
13733 default:
13734 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0,
13735 pc_rel, reloc);
13736 break;
13739 /* Mark whether the fix is to a THUMB instruction, or an ARM
13740 instruction. */
13741 arm_data = (arm_fix_data *) obstack_alloc (& notes, sizeof (arm_fix_data));
13742 new_fix->tc_fix_data = (PTR) arm_data;
13743 arm_data->thumb_mode = thumb_mode;
13745 return;
13748 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13750 void
13751 cons_fix_new_arm (frag, where, size, exp)
13752 fragS * frag;
13753 int where;
13754 int size;
13755 expressionS * exp;
13757 bfd_reloc_code_real_type type;
13758 int pcrel = 0;
13760 /* Pick a reloc.
13761 FIXME: @@ Should look at CPU word size. */
13762 switch (size)
13764 case 1:
13765 type = BFD_RELOC_8;
13766 break;
13767 case 2:
13768 type = BFD_RELOC_16;
13769 break;
13770 case 4:
13771 default:
13772 type = BFD_RELOC_32;
13773 break;
13774 case 8:
13775 type = BFD_RELOC_64;
13776 break;
13779 fix_new_exp (frag, where, (int) size, exp, pcrel, type);
13782 /* A good place to do this, although this was probably not intended
13783 for this kind of use. We need to dump the literal pool before
13784 references are made to a null symbol pointer. */
13786 void
13787 arm_cleanup ()
13789 literal_pool * pool;
13791 for (pool = list_of_pools; pool; pool = pool->next)
13793 /* Put it at the end of the relevent section. */
13794 subseg_set (pool->section, pool->sub_section);
13795 s_ltorg (0);
13799 void
13800 arm_start_line_hook ()
13802 last_label_seen = NULL;
13805 void
13806 arm_frob_label (sym)
13807 symbolS * sym;
13809 last_label_seen = sym;
13811 ARM_SET_THUMB (sym, thumb_mode);
13813 #if defined OBJ_COFF || defined OBJ_ELF
13814 ARM_SET_INTERWORK (sym, support_interwork);
13815 #endif
13817 /* Note - do not allow local symbols (.Lxxx) to be labeled
13818 as Thumb functions. This is because these labels, whilst
13819 they exist inside Thumb code, are not the entry points for
13820 possible ARM->Thumb calls. Also, these labels can be used
13821 as part of a computed goto or switch statement. eg gcc
13822 can generate code that looks like this:
13824 ldr r2, [pc, .Laaa]
13825 lsl r3, r3, #2
13826 ldr r2, [r3, r2]
13827 mov pc, r2
13829 .Lbbb: .word .Lxxx
13830 .Lccc: .word .Lyyy
13831 ..etc...
13832 .Laaa: .word Lbbb
13834 The first instruction loads the address of the jump table.
13835 The second instruction converts a table index into a byte offset.
13836 The third instruction gets the jump address out of the table.
13837 The fourth instruction performs the jump.
13839 If the address stored at .Laaa is that of a symbol which has the
13840 Thumb_Func bit set, then the linker will arrange for this address
13841 to have the bottom bit set, which in turn would mean that the
13842 address computation performed by the third instruction would end
13843 up with the bottom bit set. Since the ARM is capable of unaligned
13844 word loads, the instruction would then load the incorrect address
13845 out of the jump table, and chaos would ensue. */
13846 if (label_is_thumb_function_name
13847 && (S_GET_NAME (sym)[0] != '.' || S_GET_NAME (sym)[1] != 'L')
13848 && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
13850 /* When the address of a Thumb function is taken the bottom
13851 bit of that address should be set. This will allow
13852 interworking between Arm and Thumb functions to work
13853 correctly. */
13855 THUMB_SET_FUNC (sym, 1);
13857 label_is_thumb_function_name = FALSE;
13861 /* Adjust the symbol table. This marks Thumb symbols as distinct from
13862 ARM ones. */
13864 void
13865 arm_adjust_symtab ()
13867 #ifdef OBJ_COFF
13868 symbolS * sym;
13870 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13872 if (ARM_IS_THUMB (sym))
13874 if (THUMB_IS_FUNC (sym))
13876 /* Mark the symbol as a Thumb function. */
13877 if ( S_GET_STORAGE_CLASS (sym) == C_STAT
13878 || S_GET_STORAGE_CLASS (sym) == C_LABEL) /* This can happen! */
13879 S_SET_STORAGE_CLASS (sym, C_THUMBSTATFUNC);
13881 else if (S_GET_STORAGE_CLASS (sym) == C_EXT)
13882 S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC);
13883 else
13884 as_bad (_("%s: unexpected function type: %d"),
13885 S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym));
13887 else switch (S_GET_STORAGE_CLASS (sym))
13889 case C_EXT:
13890 S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
13891 break;
13892 case C_STAT:
13893 S_SET_STORAGE_CLASS (sym, C_THUMBSTAT);
13894 break;
13895 case C_LABEL:
13896 S_SET_STORAGE_CLASS (sym, C_THUMBLABEL);
13897 break;
13898 default:
13899 /* Do nothing. */
13900 break;
13904 if (ARM_IS_INTERWORK (sym))
13905 coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_flags = 0xFF;
13907 #endif
13908 #ifdef OBJ_ELF
13909 symbolS * sym;
13910 char bind;
13912 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13914 if (ARM_IS_THUMB (sym))
13916 elf_symbol_type * elf_sym;
13918 elf_sym = elf_symbol (symbol_get_bfdsym (sym));
13919 bind = ELF_ST_BIND (elf_sym);
13921 /* If it's a .thumb_func, declare it as so,
13922 otherwise tag label as .code 16. */
13923 if (THUMB_IS_FUNC (sym))
13924 elf_sym->internal_elf_sym.st_info =
13925 ELF_ST_INFO (bind, STT_ARM_TFUNC);
13926 else
13927 elf_sym->internal_elf_sym.st_info =
13928 ELF_ST_INFO (bind, STT_ARM_16BIT);
13931 #endif
13935 arm_data_in_code ()
13937 if (thumb_mode && ! strncmp (input_line_pointer + 1, "data:", 5))
13939 *input_line_pointer = '/';
13940 input_line_pointer += 5;
13941 *input_line_pointer = 0;
13942 return 1;
13945 return 0;
13948 char *
13949 arm_canonicalize_symbol_name (name)
13950 char * name;
13952 int len;
13954 if (thumb_mode && (len = strlen (name)) > 5
13955 && streq (name + len - 5, "/data"))
13956 *(name + len - 5) = 0;
13958 return name;
13961 #if defined OBJ_COFF || defined OBJ_ELF
13962 void
13963 arm_validate_fix (fixP)
13964 fixS * fixP;
13966 /* If the destination of the branch is a defined symbol which does not have
13967 the THUMB_FUNC attribute, then we must be calling a function which has
13968 the (interfacearm) attribute. We look for the Thumb entry point to that
13969 function and change the branch to refer to that function instead. */
13970 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23
13971 && fixP->fx_addsy != NULL
13972 && S_IS_DEFINED (fixP->fx_addsy)
13973 && ! THUMB_IS_FUNC (fixP->fx_addsy))
13975 fixP->fx_addsy = find_real_start (fixP->fx_addsy);
13978 #endif
13981 arm_force_relocation (fixp)
13982 struct fix * fixp;
13984 #if defined (OBJ_COFF) && defined (TE_PE)
13985 if (fixp->fx_r_type == BFD_RELOC_RVA)
13986 return 1;
13987 #endif
13988 #ifdef OBJ_ELF
13989 if (fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
13990 || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
13991 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX
13992 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23)
13993 return 1;
13994 #endif
13996 /* Resolve these relocations even if the symbol is extern or weak. */
13997 if (fixp->fx_r_type == BFD_RELOC_ARM_IMMEDIATE
13998 || fixp->fx_r_type == BFD_RELOC_ARM_OFFSET_IMM
13999 || fixp->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
14000 return 0;
14002 return generic_force_reloc (fixp);
14005 #ifdef OBJ_COFF
14006 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
14007 local labels from being added to the output symbol table when they
14008 are used with the ADRL pseudo op. The ADRL relocation should always
14009 be resolved before the binbary is emitted, so it is safe to say that
14010 it is adjustable. */
14012 bfd_boolean
14013 arm_fix_adjustable (fixP)
14014 fixS * fixP;
14016 if (fixP->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
14017 return 1;
14018 return 0;
14020 #endif
14022 #ifdef OBJ_ELF
14023 /* Relocations against Thumb function names must be left unadjusted,
14024 so that the linker can use this information to correctly set the
14025 bottom bit of their addresses. The MIPS version of this function
14026 also prevents relocations that are mips-16 specific, but I do not
14027 know why it does this.
14029 FIXME:
14030 There is one other problem that ought to be addressed here, but
14031 which currently is not: Taking the address of a label (rather
14032 than a function) and then later jumping to that address. Such
14033 addresses also ought to have their bottom bit set (assuming that
14034 they reside in Thumb code), but at the moment they will not. */
14036 bfd_boolean
14037 arm_fix_adjustable (fixP)
14038 fixS * fixP;
14040 if (fixP->fx_addsy == NULL)
14041 return 1;
14043 if (THUMB_IS_FUNC (fixP->fx_addsy)
14044 && fixP->fx_subsy == NULL)
14045 return 0;
14047 /* We need the symbol name for the VTABLE entries. */
14048 if ( fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
14049 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
14050 return 0;
14052 /* Don't allow symbols to be discarded on GOT related relocs. */
14053 if (fixP->fx_r_type == BFD_RELOC_ARM_PLT32
14054 || fixP->fx_r_type == BFD_RELOC_ARM_GOT32
14055 || fixP->fx_r_type == BFD_RELOC_ARM_GOTOFF)
14056 return 0;
14058 return 1;
14061 const char *
14062 elf32_arm_target_format ()
14064 if (target_big_endian)
14066 if (target_oabi)
14067 return "elf32-bigarm-oabi";
14068 else
14069 return "elf32-bigarm";
14071 else
14073 if (target_oabi)
14074 return "elf32-littlearm-oabi";
14075 else
14076 return "elf32-littlearm";
14080 void
14081 armelf_frob_symbol (symp, puntp)
14082 symbolS * symp;
14083 int * puntp;
14085 elf_frob_symbol (symp, puntp);
14088 static bfd_reloc_code_real_type
14089 arm_parse_reloc ()
14091 char id [16];
14092 char * ip;
14093 unsigned int i;
14094 static struct
14096 char * str;
14097 int len;
14098 bfd_reloc_code_real_type reloc;
14100 reloc_map[] =
14102 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
14103 MAP ("(got)", BFD_RELOC_ARM_GOT32),
14104 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF),
14105 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
14106 branch instructions generated by GCC for PLT relocs. */
14107 MAP ("(plt)", BFD_RELOC_ARM_PLT32),
14108 { NULL, 0, BFD_RELOC_UNUSED }
14109 #undef MAP
14112 for (i = 0, ip = input_line_pointer;
14113 i < sizeof (id) && (ISALNUM (*ip) || ISPUNCT (*ip));
14114 i++, ip++)
14115 id[i] = TOLOWER (*ip);
14117 for (i = 0; reloc_map[i].str; i++)
14118 if (strncmp (id, reloc_map[i].str, reloc_map[i].len) == 0)
14119 break;
14121 input_line_pointer += reloc_map[i].len;
14123 return reloc_map[i].reloc;
14126 static void
14127 s_arm_elf_cons (nbytes)
14128 int nbytes;
14130 expressionS exp;
14132 #ifdef md_flush_pending_output
14133 md_flush_pending_output ();
14134 #endif
14136 if (is_it_end_of_statement ())
14138 demand_empty_rest_of_line ();
14139 return;
14142 #ifdef md_cons_align
14143 md_cons_align (nbytes);
14144 #endif
14146 mapping_state (MAP_DATA);
14149 bfd_reloc_code_real_type reloc;
14151 expression (& exp);
14153 if (exp.X_op == O_symbol
14154 && * input_line_pointer == '('
14155 && (reloc = arm_parse_reloc ()) != BFD_RELOC_UNUSED)
14157 reloc_howto_type *howto = bfd_reloc_type_lookup (stdoutput, reloc);
14158 int size = bfd_get_reloc_size (howto);
14160 if (size > nbytes)
14161 as_bad ("%s relocations do not fit in %d bytes",
14162 howto->name, nbytes);
14163 else
14165 register char *p = frag_more ((int) nbytes);
14166 int offset = nbytes - size;
14168 fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size,
14169 &exp, 0, reloc);
14172 else
14173 emit_expr (&exp, (unsigned int) nbytes);
14175 while (*input_line_pointer++ == ',');
14177 /* Put terminator back into stream. */
14178 input_line_pointer --;
14179 demand_empty_rest_of_line ();
14182 #endif /* OBJ_ELF */
14184 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
14185 of an rs_align_code fragment. */
14187 void
14188 arm_handle_align (fragP)
14189 fragS *fragP;
14191 static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 };
14192 static char const thumb_noop[2] = { 0xc0, 0x46 };
14193 static char const arm_bigend_noop[4] = { 0xe1, 0xa0, 0x00, 0x00 };
14194 static char const thumb_bigend_noop[2] = { 0x46, 0xc0 };
14196 int bytes, fix, noop_size;
14197 char * p;
14198 const char * noop;
14200 if (fragP->fr_type != rs_align_code)
14201 return;
14203 bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
14204 p = fragP->fr_literal + fragP->fr_fix;
14205 fix = 0;
14207 if (bytes > MAX_MEM_FOR_RS_ALIGN_CODE)
14208 bytes &= MAX_MEM_FOR_RS_ALIGN_CODE;
14210 if (fragP->tc_frag_data)
14212 if (target_big_endian)
14213 noop = thumb_bigend_noop;
14214 else
14215 noop = thumb_noop;
14216 noop_size = sizeof (thumb_noop);
14218 else
14220 if (target_big_endian)
14221 noop = arm_bigend_noop;
14222 else
14223 noop = arm_noop;
14224 noop_size = sizeof (arm_noop);
14227 if (bytes & (noop_size - 1))
14229 fix = bytes & (noop_size - 1);
14230 memset (p, 0, fix);
14231 p += fix;
14232 bytes -= fix;
14235 while (bytes >= noop_size)
14237 memcpy (p, noop, noop_size);
14238 p += noop_size;
14239 bytes -= noop_size;
14240 fix += noop_size;
14243 fragP->fr_fix += fix;
14244 fragP->fr_var = noop_size;
14247 /* Called from md_do_align. Used to create an alignment
14248 frag in a code section. */
14250 void
14251 arm_frag_align_code (n, max)
14252 int n;
14253 int max;
14255 char * p;
14257 /* We assume that there will never be a requirement
14258 to support alignments greater than 32 bytes. */
14259 if (max > MAX_MEM_FOR_RS_ALIGN_CODE)
14260 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
14262 p = frag_var (rs_align_code,
14263 MAX_MEM_FOR_RS_ALIGN_CODE,
14265 (relax_substateT) max,
14266 (symbolS *) NULL,
14267 (offsetT) n,
14268 (char *) NULL);
14269 *p = 0;
14273 /* Perform target specific initialisation of a frag. */
14275 void
14276 arm_init_frag (fragP)
14277 fragS *fragP;
14279 /* Record whether this frag is in an ARM or a THUMB area. */
14280 fragP->tc_frag_data = thumb_mode;