* config/tc-arm.c (arm_elf_change_section): Not static.
[binutils.git] / gas / config / tc-arm.c
blob2b6f70f28c72d2c5b60ca914276f06aa4c5caaa2
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. */
59 /* Co-processor space extensions. */
60 #define ARM_CEXT_XSCALE 0x00800000 /* Allow MIA etc. */
61 #define ARM_CEXT_MAVERICK 0x00400000 /* Use Cirrus/DSP coprocessor. */
62 #define ARM_CEXT_IWMMXT 0x00200000 /* Intel Wireless MMX technology coprocessor. */
64 /* Architectures are the sum of the base and extensions. The ARM ARM (rev E)
65 defines the following: ARMv3, ARMv3M, ARMv4xM, ARMv4, ARMv4TxM, ARMv4T,
66 ARMv5xM, ARMv5, ARMv5TxM, ARMv5T, ARMv5TExP, ARMv5TE. To these we add
67 three more to cover cores prior to ARM6. Finally, there are cores which
68 implement further extensions in the co-processor space. */
69 #define ARM_ARCH_V1 ARM_EXT_V1
70 #define ARM_ARCH_V2 (ARM_ARCH_V1 | ARM_EXT_V2)
71 #define ARM_ARCH_V2S (ARM_ARCH_V2 | ARM_EXT_V2S)
72 #define ARM_ARCH_V3 (ARM_ARCH_V2S | ARM_EXT_V3)
73 #define ARM_ARCH_V3M (ARM_ARCH_V3 | ARM_EXT_V3M)
74 #define ARM_ARCH_V4xM (ARM_ARCH_V3 | ARM_EXT_V4)
75 #define ARM_ARCH_V4 (ARM_ARCH_V3M | ARM_EXT_V4)
76 #define ARM_ARCH_V4TxM (ARM_ARCH_V4xM | ARM_EXT_V4T)
77 #define ARM_ARCH_V4T (ARM_ARCH_V4 | ARM_EXT_V4T)
78 #define ARM_ARCH_V5xM (ARM_ARCH_V4xM | ARM_EXT_V5)
79 #define ARM_ARCH_V5 (ARM_ARCH_V4 | ARM_EXT_V5)
80 #define ARM_ARCH_V5TxM (ARM_ARCH_V5xM | ARM_EXT_V4T | ARM_EXT_V5T)
81 #define ARM_ARCH_V5T (ARM_ARCH_V5 | ARM_EXT_V4T | ARM_EXT_V5T)
82 #define ARM_ARCH_V5TExP (ARM_ARCH_V5T | ARM_EXT_V5ExP)
83 #define ARM_ARCH_V5TE (ARM_ARCH_V5TExP | ARM_EXT_V5E)
84 #define ARM_ARCH_V5TEJ (ARM_ARCH_V5TE | ARM_EXT_V5J)
86 /* Processors with specific extensions in the co-processor space. */
87 #define ARM_ARCH_XSCALE (ARM_ARCH_V5TE | ARM_CEXT_XSCALE)
88 #define ARM_ARCH_IWMMXT (ARM_ARCH_XSCALE | ARM_CEXT_IWMMXT)
90 /* Some useful combinations: */
91 #define ARM_ANY 0x0000ffff /* Any basic core. */
92 #define ARM_ALL 0x00ffffff /* Any core + co-processor */
93 #define CPROC_ANY 0x00ff0000 /* Any co-processor */
94 #define FPU_ANY 0xff000000 /* Note this is ~ARM_ALL. */
97 #define FPU_FPA_EXT_V1 0x80000000 /* Base FPA instruction set. */
98 #define FPU_FPA_EXT_V2 0x40000000 /* LFM/SFM. */
99 #define FPU_VFP_EXT_NONE 0x20000000 /* Use VFP word-ordering. */
100 #define FPU_VFP_EXT_V1xD 0x10000000 /* Base VFP instruction set. */
101 #define FPU_VFP_EXT_V1 0x08000000 /* Double-precision insns. */
102 #define FPU_VFP_EXT_V2 0x04000000 /* ARM10E VFPr1. */
103 #define FPU_NONE 0
105 #define FPU_ARCH_FPE FPU_FPA_EXT_V1
106 #define FPU_ARCH_FPA (FPU_ARCH_FPE | FPU_FPA_EXT_V2)
108 #define FPU_ARCH_VFP FPU_VFP_EXT_NONE
109 #define FPU_ARCH_VFP_V1xD (FPU_VFP_EXT_V1xD | FPU_VFP_EXT_NONE)
110 #define FPU_ARCH_VFP_V1 (FPU_ARCH_VFP_V1xD | FPU_VFP_EXT_V1)
111 #define FPU_ARCH_VFP_V2 (FPU_ARCH_VFP_V1 | FPU_VFP_EXT_V2)
113 /* Types of processor to assemble for. */
114 #define ARM_1 ARM_ARCH_V1
115 #define ARM_2 ARM_ARCH_V2
116 #define ARM_3 ARM_ARCH_V2S
117 #define ARM_250 ARM_ARCH_V2S
118 #define ARM_6 ARM_ARCH_V3
119 #define ARM_7 ARM_ARCH_V3
120 #define ARM_8 ARM_ARCH_V4
121 #define ARM_9 ARM_ARCH_V4T
122 #define ARM_STRONG ARM_ARCH_V4
123 #define ARM_CPU_MASK 0x0000000f /* XXX? */
125 #ifndef CPU_DEFAULT
126 #if defined __XSCALE__
127 #define CPU_DEFAULT (ARM_ARCH_XSCALE)
128 #else
129 #if defined __thumb__
130 #define CPU_DEFAULT (ARM_ARCH_V5T)
131 #else
132 #define CPU_DEFAULT ARM_ANY
133 #endif
134 #endif
135 #endif
137 #ifdef TE_LINUX
138 #define FPU_DEFAULT FPU_ARCH_FPA
139 #endif
141 #ifdef TE_NetBSD
142 #ifdef OBJ_ELF
143 #define FPU_DEFAULT FPU_ARCH_VFP /* Soft-float, but VFP order. */
144 #else
145 /* Legacy a.out format. */
146 #define FPU_DEFAULT FPU_ARCH_FPA /* Soft-float, but FPA order. */
147 #endif
148 #endif
150 /* For backwards compatibility we default to the FPA. */
151 #ifndef FPU_DEFAULT
152 #define FPU_DEFAULT FPU_ARCH_FPA
153 #endif
155 #define streq(a, b) (strcmp (a, b) == 0)
156 #define skip_whitespace(str) while (*(str) == ' ') ++(str)
158 static unsigned long cpu_variant;
159 static int target_oabi = 0;
161 /* Flags stored in private area of BFD structure. */
162 static int uses_apcs_26 = FALSE;
163 static int atpcs = FALSE;
164 static int support_interwork = FALSE;
165 static int uses_apcs_float = FALSE;
166 static int pic_code = FALSE;
168 /* Variables that we set while parsing command-line options. Once all
169 options have been read we re-process these values to set the real
170 assembly flags. */
171 static int legacy_cpu = -1;
172 static int legacy_fpu = -1;
174 static int mcpu_cpu_opt = -1;
175 static int mcpu_fpu_opt = -1;
176 static int march_cpu_opt = -1;
177 static int march_fpu_opt = -1;
178 static int mfpu_opt = -1;
180 /* This array holds the chars that always start a comment. If the
181 pre-processor is disabled, these aren't very useful. */
182 const char comment_chars[] = "@";
184 /* This array holds the chars that only start a comment at the beginning of
185 a line. If the line seems to have the form '# 123 filename'
186 .line and .file directives will appear in the pre-processed output. */
187 /* Note that input_file.c hand checks for '#' at the beginning of the
188 first line of the input file. This is because the compiler outputs
189 #NO_APP at the beginning of its output. */
190 /* Also note that comments like this one will always work. */
191 const char line_comment_chars[] = "#";
193 const char line_separator_chars[] = ";";
195 /* Chars that can be used to separate mant
196 from exp in floating point numbers. */
197 const char EXP_CHARS[] = "eE";
199 /* Chars that mean this number is a floating point constant. */
200 /* As in 0f12.456 */
201 /* or 0d1.2345e12 */
203 const char FLT_CHARS[] = "rRsSfFdDxXeEpP";
205 /* Prefix characters that indicate the start of an immediate
206 value. */
207 #define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
209 #ifdef OBJ_ELF
210 /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
211 symbolS * GOT_symbol;
212 #endif
214 /* Size of relocation record. */
215 const int md_reloc_size = 8;
217 /* 0: assemble for ARM,
218 1: assemble for Thumb,
219 2: assemble for Thumb even though target CPU does not support thumb
220 instructions. */
221 static int thumb_mode = 0;
223 typedef struct arm_fix
225 int thumb_mode;
226 } arm_fix_data;
228 struct arm_it
230 const char * error;
231 unsigned long instruction;
232 int size;
233 struct
235 bfd_reloc_code_real_type type;
236 expressionS exp;
237 int pc_rel;
238 } reloc;
241 struct arm_it inst;
243 enum asm_shift_index
245 SHIFT_LSL = 0,
246 SHIFT_LSR,
247 SHIFT_ASR,
248 SHIFT_ROR,
249 SHIFT_RRX
252 struct asm_shift_properties
254 enum asm_shift_index index;
255 unsigned long bit_field;
256 unsigned int allows_0 : 1;
257 unsigned int allows_32 : 1;
260 static const struct asm_shift_properties shift_properties [] =
262 { SHIFT_LSL, 0, 1, 0},
263 { SHIFT_LSR, 0x20, 0, 1},
264 { SHIFT_ASR, 0x40, 0, 1},
265 { SHIFT_ROR, 0x60, 0, 0},
266 { SHIFT_RRX, 0x60, 0, 0}
269 struct asm_shift_name
271 const char * name;
272 const struct asm_shift_properties * properties;
275 static const struct asm_shift_name shift_names [] =
277 { "asl", shift_properties + SHIFT_LSL },
278 { "lsl", shift_properties + SHIFT_LSL },
279 { "lsr", shift_properties + SHIFT_LSR },
280 { "asr", shift_properties + SHIFT_ASR },
281 { "ror", shift_properties + SHIFT_ROR },
282 { "rrx", shift_properties + SHIFT_RRX },
283 { "ASL", shift_properties + SHIFT_LSL },
284 { "LSL", shift_properties + SHIFT_LSL },
285 { "LSR", shift_properties + SHIFT_LSR },
286 { "ASR", shift_properties + SHIFT_ASR },
287 { "ROR", shift_properties + SHIFT_ROR },
288 { "RRX", shift_properties + SHIFT_RRX }
291 #define NO_SHIFT_RESTRICT 1
292 #define SHIFT_RESTRICT 0
294 #define NUM_FLOAT_VALS 8
296 const char * fp_const[] =
298 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
301 /* Number of littlenums required to hold an extended precision number. */
302 #define MAX_LITTLENUMS 6
304 LITTLENUM_TYPE fp_values[NUM_FLOAT_VALS][MAX_LITTLENUMS];
306 #define FAIL (-1)
307 #define SUCCESS (0)
309 /* Whether a Co-processor load/store operation accepts write-back forms. */
310 #define CP_WB_OK 1
311 #define CP_NO_WB 0
313 #define SUFF_S 1
314 #define SUFF_D 2
315 #define SUFF_E 3
316 #define SUFF_P 4
318 #define CP_T_X 0x00008000
319 #define CP_T_Y 0x00400000
320 #define CP_T_Pre 0x01000000
321 #define CP_T_UD 0x00800000
322 #define CP_T_WB 0x00200000
324 #define CONDS_BIT 0x00100000
325 #define LOAD_BIT 0x00100000
327 #define DOUBLE_LOAD_FLAG 0x00000001
329 struct asm_cond
331 const char * template;
332 unsigned long value;
335 #define COND_ALWAYS 0xe0000000
336 #define COND_MASK 0xf0000000
338 static const struct asm_cond conds[] =
340 {"eq", 0x00000000},
341 {"ne", 0x10000000},
342 {"cs", 0x20000000}, {"hs", 0x20000000},
343 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
344 {"mi", 0x40000000},
345 {"pl", 0x50000000},
346 {"vs", 0x60000000},
347 {"vc", 0x70000000},
348 {"hi", 0x80000000},
349 {"ls", 0x90000000},
350 {"ge", 0xa0000000},
351 {"lt", 0xb0000000},
352 {"gt", 0xc0000000},
353 {"le", 0xd0000000},
354 {"al", 0xe0000000},
355 {"nv", 0xf0000000}
358 struct asm_psr
360 const char *template;
361 bfd_boolean cpsr;
362 unsigned long field;
365 /* The bit that distnguishes CPSR and SPSR. */
366 #define SPSR_BIT (1 << 22)
368 /* How many bits to shift the PSR_xxx bits up by. */
369 #define PSR_SHIFT 16
371 #define PSR_c (1 << 0)
372 #define PSR_x (1 << 1)
373 #define PSR_s (1 << 2)
374 #define PSR_f (1 << 3)
376 static const struct asm_psr psrs[] =
378 {"CPSR", TRUE, PSR_c | PSR_f},
379 {"CPSR_all", TRUE, PSR_c | PSR_f},
380 {"SPSR", FALSE, PSR_c | PSR_f},
381 {"SPSR_all", FALSE, PSR_c | PSR_f},
382 {"CPSR_flg", TRUE, PSR_f},
383 {"CPSR_f", TRUE, PSR_f},
384 {"SPSR_flg", FALSE, PSR_f},
385 {"SPSR_f", FALSE, PSR_f},
386 {"CPSR_c", TRUE, PSR_c},
387 {"CPSR_ctl", TRUE, PSR_c},
388 {"SPSR_c", FALSE, PSR_c},
389 {"SPSR_ctl", FALSE, PSR_c},
390 {"CPSR_x", TRUE, PSR_x},
391 {"CPSR_s", TRUE, PSR_s},
392 {"SPSR_x", FALSE, PSR_x},
393 {"SPSR_s", FALSE, PSR_s},
394 /* Combinations of flags. */
395 {"CPSR_fs", TRUE, PSR_f | PSR_s},
396 {"CPSR_fx", TRUE, PSR_f | PSR_x},
397 {"CPSR_fc", TRUE, PSR_f | PSR_c},
398 {"CPSR_sf", TRUE, PSR_s | PSR_f},
399 {"CPSR_sx", TRUE, PSR_s | PSR_x},
400 {"CPSR_sc", TRUE, PSR_s | PSR_c},
401 {"CPSR_xf", TRUE, PSR_x | PSR_f},
402 {"CPSR_xs", TRUE, PSR_x | PSR_s},
403 {"CPSR_xc", TRUE, PSR_x | PSR_c},
404 {"CPSR_cf", TRUE, PSR_c | PSR_f},
405 {"CPSR_cs", TRUE, PSR_c | PSR_s},
406 {"CPSR_cx", TRUE, PSR_c | PSR_x},
407 {"CPSR_fsx", TRUE, PSR_f | PSR_s | PSR_x},
408 {"CPSR_fsc", TRUE, PSR_f | PSR_s | PSR_c},
409 {"CPSR_fxs", TRUE, PSR_f | PSR_x | PSR_s},
410 {"CPSR_fxc", TRUE, PSR_f | PSR_x | PSR_c},
411 {"CPSR_fcs", TRUE, PSR_f | PSR_c | PSR_s},
412 {"CPSR_fcx", TRUE, PSR_f | PSR_c | PSR_x},
413 {"CPSR_sfx", TRUE, PSR_s | PSR_f | PSR_x},
414 {"CPSR_sfc", TRUE, PSR_s | PSR_f | PSR_c},
415 {"CPSR_sxf", TRUE, PSR_s | PSR_x | PSR_f},
416 {"CPSR_sxc", TRUE, PSR_s | PSR_x | PSR_c},
417 {"CPSR_scf", TRUE, PSR_s | PSR_c | PSR_f},
418 {"CPSR_scx", TRUE, PSR_s | PSR_c | PSR_x},
419 {"CPSR_xfs", TRUE, PSR_x | PSR_f | PSR_s},
420 {"CPSR_xfc", TRUE, PSR_x | PSR_f | PSR_c},
421 {"CPSR_xsf", TRUE, PSR_x | PSR_s | PSR_f},
422 {"CPSR_xsc", TRUE, PSR_x | PSR_s | PSR_c},
423 {"CPSR_xcf", TRUE, PSR_x | PSR_c | PSR_f},
424 {"CPSR_xcs", TRUE, PSR_x | PSR_c | PSR_s},
425 {"CPSR_cfs", TRUE, PSR_c | PSR_f | PSR_s},
426 {"CPSR_cfx", TRUE, PSR_c | PSR_f | PSR_x},
427 {"CPSR_csf", TRUE, PSR_c | PSR_s | PSR_f},
428 {"CPSR_csx", TRUE, PSR_c | PSR_s | PSR_x},
429 {"CPSR_cxf", TRUE, PSR_c | PSR_x | PSR_f},
430 {"CPSR_cxs", TRUE, PSR_c | PSR_x | PSR_s},
431 {"CPSR_fsxc", TRUE, PSR_f | PSR_s | PSR_x | PSR_c},
432 {"CPSR_fscx", TRUE, PSR_f | PSR_s | PSR_c | PSR_x},
433 {"CPSR_fxsc", TRUE, PSR_f | PSR_x | PSR_s | PSR_c},
434 {"CPSR_fxcs", TRUE, PSR_f | PSR_x | PSR_c | PSR_s},
435 {"CPSR_fcsx", TRUE, PSR_f | PSR_c | PSR_s | PSR_x},
436 {"CPSR_fcxs", TRUE, PSR_f | PSR_c | PSR_x | PSR_s},
437 {"CPSR_sfxc", TRUE, PSR_s | PSR_f | PSR_x | PSR_c},
438 {"CPSR_sfcx", TRUE, PSR_s | PSR_f | PSR_c | PSR_x},
439 {"CPSR_sxfc", TRUE, PSR_s | PSR_x | PSR_f | PSR_c},
440 {"CPSR_sxcf", TRUE, PSR_s | PSR_x | PSR_c | PSR_f},
441 {"CPSR_scfx", TRUE, PSR_s | PSR_c | PSR_f | PSR_x},
442 {"CPSR_scxf", TRUE, PSR_s | PSR_c | PSR_x | PSR_f},
443 {"CPSR_xfsc", TRUE, PSR_x | PSR_f | PSR_s | PSR_c},
444 {"CPSR_xfcs", TRUE, PSR_x | PSR_f | PSR_c | PSR_s},
445 {"CPSR_xsfc", TRUE, PSR_x | PSR_s | PSR_f | PSR_c},
446 {"CPSR_xscf", TRUE, PSR_x | PSR_s | PSR_c | PSR_f},
447 {"CPSR_xcfs", TRUE, PSR_x | PSR_c | PSR_f | PSR_s},
448 {"CPSR_xcsf", TRUE, PSR_x | PSR_c | PSR_s | PSR_f},
449 {"CPSR_cfsx", TRUE, PSR_c | PSR_f | PSR_s | PSR_x},
450 {"CPSR_cfxs", TRUE, PSR_c | PSR_f | PSR_x | PSR_s},
451 {"CPSR_csfx", TRUE, PSR_c | PSR_s | PSR_f | PSR_x},
452 {"CPSR_csxf", TRUE, PSR_c | PSR_s | PSR_x | PSR_f},
453 {"CPSR_cxfs", TRUE, PSR_c | PSR_x | PSR_f | PSR_s},
454 {"CPSR_cxsf", TRUE, PSR_c | PSR_x | PSR_s | PSR_f},
455 {"SPSR_fs", FALSE, PSR_f | PSR_s},
456 {"SPSR_fx", FALSE, PSR_f | PSR_x},
457 {"SPSR_fc", FALSE, PSR_f | PSR_c},
458 {"SPSR_sf", FALSE, PSR_s | PSR_f},
459 {"SPSR_sx", FALSE, PSR_s | PSR_x},
460 {"SPSR_sc", FALSE, PSR_s | PSR_c},
461 {"SPSR_xf", FALSE, PSR_x | PSR_f},
462 {"SPSR_xs", FALSE, PSR_x | PSR_s},
463 {"SPSR_xc", FALSE, PSR_x | PSR_c},
464 {"SPSR_cf", FALSE, PSR_c | PSR_f},
465 {"SPSR_cs", FALSE, PSR_c | PSR_s},
466 {"SPSR_cx", FALSE, PSR_c | PSR_x},
467 {"SPSR_fsx", FALSE, PSR_f | PSR_s | PSR_x},
468 {"SPSR_fsc", FALSE, PSR_f | PSR_s | PSR_c},
469 {"SPSR_fxs", FALSE, PSR_f | PSR_x | PSR_s},
470 {"SPSR_fxc", FALSE, PSR_f | PSR_x | PSR_c},
471 {"SPSR_fcs", FALSE, PSR_f | PSR_c | PSR_s},
472 {"SPSR_fcx", FALSE, PSR_f | PSR_c | PSR_x},
473 {"SPSR_sfx", FALSE, PSR_s | PSR_f | PSR_x},
474 {"SPSR_sfc", FALSE, PSR_s | PSR_f | PSR_c},
475 {"SPSR_sxf", FALSE, PSR_s | PSR_x | PSR_f},
476 {"SPSR_sxc", FALSE, PSR_s | PSR_x | PSR_c},
477 {"SPSR_scf", FALSE, PSR_s | PSR_c | PSR_f},
478 {"SPSR_scx", FALSE, PSR_s | PSR_c | PSR_x},
479 {"SPSR_xfs", FALSE, PSR_x | PSR_f | PSR_s},
480 {"SPSR_xfc", FALSE, PSR_x | PSR_f | PSR_c},
481 {"SPSR_xsf", FALSE, PSR_x | PSR_s | PSR_f},
482 {"SPSR_xsc", FALSE, PSR_x | PSR_s | PSR_c},
483 {"SPSR_xcf", FALSE, PSR_x | PSR_c | PSR_f},
484 {"SPSR_xcs", FALSE, PSR_x | PSR_c | PSR_s},
485 {"SPSR_cfs", FALSE, PSR_c | PSR_f | PSR_s},
486 {"SPSR_cfx", FALSE, PSR_c | PSR_f | PSR_x},
487 {"SPSR_csf", FALSE, PSR_c | PSR_s | PSR_f},
488 {"SPSR_csx", FALSE, PSR_c | PSR_s | PSR_x},
489 {"SPSR_cxf", FALSE, PSR_c | PSR_x | PSR_f},
490 {"SPSR_cxs", FALSE, PSR_c | PSR_x | PSR_s},
491 {"SPSR_fsxc", FALSE, PSR_f | PSR_s | PSR_x | PSR_c},
492 {"SPSR_fscx", FALSE, PSR_f | PSR_s | PSR_c | PSR_x},
493 {"SPSR_fxsc", FALSE, PSR_f | PSR_x | PSR_s | PSR_c},
494 {"SPSR_fxcs", FALSE, PSR_f | PSR_x | PSR_c | PSR_s},
495 {"SPSR_fcsx", FALSE, PSR_f | PSR_c | PSR_s | PSR_x},
496 {"SPSR_fcxs", FALSE, PSR_f | PSR_c | PSR_x | PSR_s},
497 {"SPSR_sfxc", FALSE, PSR_s | PSR_f | PSR_x | PSR_c},
498 {"SPSR_sfcx", FALSE, PSR_s | PSR_f | PSR_c | PSR_x},
499 {"SPSR_sxfc", FALSE, PSR_s | PSR_x | PSR_f | PSR_c},
500 {"SPSR_sxcf", FALSE, PSR_s | PSR_x | PSR_c | PSR_f},
501 {"SPSR_scfx", FALSE, PSR_s | PSR_c | PSR_f | PSR_x},
502 {"SPSR_scxf", FALSE, PSR_s | PSR_c | PSR_x | PSR_f},
503 {"SPSR_xfsc", FALSE, PSR_x | PSR_f | PSR_s | PSR_c},
504 {"SPSR_xfcs", FALSE, PSR_x | PSR_f | PSR_c | PSR_s},
505 {"SPSR_xsfc", FALSE, PSR_x | PSR_s | PSR_f | PSR_c},
506 {"SPSR_xscf", FALSE, PSR_x | PSR_s | PSR_c | PSR_f},
507 {"SPSR_xcfs", FALSE, PSR_x | PSR_c | PSR_f | PSR_s},
508 {"SPSR_xcsf", FALSE, PSR_x | PSR_c | PSR_s | PSR_f},
509 {"SPSR_cfsx", FALSE, PSR_c | PSR_f | PSR_s | PSR_x},
510 {"SPSR_cfxs", FALSE, PSR_c | PSR_f | PSR_x | PSR_s},
511 {"SPSR_csfx", FALSE, PSR_c | PSR_s | PSR_f | PSR_x},
512 {"SPSR_csxf", FALSE, PSR_c | PSR_s | PSR_x | PSR_f},
513 {"SPSR_cxfs", FALSE, PSR_c | PSR_x | PSR_f | PSR_s},
514 {"SPSR_cxsf", FALSE, PSR_c | PSR_x | PSR_s | PSR_f},
517 enum wreg_type
519 IWMMXT_REG_WR = 0,
520 IWMMXT_REG_WC = 1,
521 IWMMXT_REG_WR_OR_WC = 2,
522 IWMMXT_REG_WCG
525 enum iwmmxt_insn_type
527 check_rd,
528 check_wr,
529 check_wrwr,
530 check_wrwrwr,
531 check_wrwrwcg,
532 check_tbcst,
533 check_tmovmsk,
534 check_tmia,
535 check_tmcrr,
536 check_tmrrc,
537 check_tmcr,
538 check_tmrc,
539 check_tinsr,
540 check_textrc,
541 check_waligni,
542 check_textrm,
543 check_wshufh
546 enum vfp_dp_reg_pos
548 VFP_REG_Dd, VFP_REG_Dm, VFP_REG_Dn
551 enum vfp_sp_reg_pos
553 VFP_REG_Sd, VFP_REG_Sm, VFP_REG_Sn
556 enum vfp_ldstm_type
558 VFP_LDSTMIA, VFP_LDSTMDB, VFP_LDSTMIAX, VFP_LDSTMDBX
561 /* VFP system registers. */
562 struct vfp_reg
564 const char *name;
565 unsigned long regno;
568 static const struct vfp_reg vfp_regs[] =
570 {"fpsid", 0x00000000},
571 {"FPSID", 0x00000000},
572 {"fpscr", 0x00010000},
573 {"FPSCR", 0x00010000},
574 {"fpexc", 0x00080000},
575 {"FPEXC", 0x00080000}
578 /* Structure for a hash table entry for a register. */
579 struct reg_entry
581 const char * name;
582 int number;
583 bfd_boolean builtin;
586 /* Some well known registers that we refer to directly elsewhere. */
587 #define REG_SP 13
588 #define REG_LR 14
589 #define REG_PC 15
591 #define wr_register(reg) ((reg ^ WR_PREFIX) >= 0 && (reg ^ WR_PREFIX) <= 15)
592 #define wc_register(reg) ((reg ^ WC_PREFIX) >= 0 && (reg ^ WC_PREFIX) <= 15)
593 #define wcg_register(reg) ((reg ^ WC_PREFIX) >= 8 && (reg ^ WC_PREFIX) <= 11)
595 /* These are the standard names. Users can add aliases with .req.
596 and delete them with .unreq. */
598 /* Integer Register Numbers. */
599 static const struct reg_entry rn_table[] =
601 {"r0", 0, TRUE}, {"r1", 1, TRUE}, {"r2", 2, TRUE}, {"r3", 3, TRUE},
602 {"r4", 4, TRUE}, {"r5", 5, TRUE}, {"r6", 6, TRUE}, {"r7", 7, TRUE},
603 {"r8", 8, TRUE}, {"r9", 9, TRUE}, {"r10", 10, TRUE}, {"r11", 11, TRUE},
604 {"r12", 12, TRUE}, {"r13", REG_SP, TRUE}, {"r14", REG_LR, TRUE}, {"r15", REG_PC, TRUE},
605 /* ATPCS Synonyms. */
606 {"a1", 0, TRUE}, {"a2", 1, TRUE}, {"a3", 2, TRUE}, {"a4", 3, TRUE},
607 {"v1", 4, TRUE}, {"v2", 5, TRUE}, {"v3", 6, TRUE}, {"v4", 7, TRUE},
608 {"v5", 8, TRUE}, {"v6", 9, TRUE}, {"v7", 10, TRUE}, {"v8", 11, TRUE},
609 /* Well-known aliases. */
610 {"wr", 7, TRUE}, {"sb", 9, TRUE}, {"sl", 10, TRUE}, {"fp", 11, TRUE},
611 {"ip", 12, TRUE}, {"sp", REG_SP, TRUE}, {"lr", REG_LR, TRUE}, {"pc", REG_PC, TRUE},
612 {NULL, 0, TRUE}
615 #define WR_PREFIX 0x200
616 #define WC_PREFIX 0x400
618 static const struct reg_entry iwmmxt_table[] =
620 /* Intel Wireless MMX technology register names. */
621 { "wr0", 0x0 | WR_PREFIX, TRUE}, {"wr1", 0x1 | WR_PREFIX, TRUE},
622 { "wr2", 0x2 | WR_PREFIX, TRUE}, {"wr3", 0x3 | WR_PREFIX, TRUE},
623 { "wr4", 0x4 | WR_PREFIX, TRUE}, {"wr5", 0x5 | WR_PREFIX, TRUE},
624 { "wr6", 0x6 | WR_PREFIX, TRUE}, {"wr7", 0x7 | WR_PREFIX, TRUE},
625 { "wr8", 0x8 | WR_PREFIX, TRUE}, {"wr9", 0x9 | WR_PREFIX, TRUE},
626 { "wr10", 0xa | WR_PREFIX, TRUE}, {"wr11", 0xb | WR_PREFIX, TRUE},
627 { "wr12", 0xc | WR_PREFIX, TRUE}, {"wr13", 0xd | WR_PREFIX, TRUE},
628 { "wr14", 0xe | WR_PREFIX, TRUE}, {"wr15", 0xf | WR_PREFIX, TRUE},
629 { "wcid", 0x0 | WC_PREFIX, TRUE}, {"wcon", 0x1 | WC_PREFIX, TRUE},
630 {"wcssf", 0x2 | WC_PREFIX, TRUE}, {"wcasf", 0x3 | WC_PREFIX, TRUE},
631 {"wcgr0", 0x8 | WC_PREFIX, TRUE}, {"wcgr1", 0x9 | WC_PREFIX, TRUE},
632 {"wcgr2", 0xa | WC_PREFIX, TRUE}, {"wcgr3", 0xb | WC_PREFIX, TRUE},
634 { "wR0", 0x0 | WR_PREFIX, TRUE}, {"wR1", 0x1 | WR_PREFIX, TRUE},
635 { "wR2", 0x2 | WR_PREFIX, TRUE}, {"wR3", 0x3 | WR_PREFIX, TRUE},
636 { "wR4", 0x4 | WR_PREFIX, TRUE}, {"wR5", 0x5 | WR_PREFIX, TRUE},
637 { "wR6", 0x6 | WR_PREFIX, TRUE}, {"wR7", 0x7 | WR_PREFIX, TRUE},
638 { "wR8", 0x8 | WR_PREFIX, TRUE}, {"wR9", 0x9 | WR_PREFIX, TRUE},
639 { "wR10", 0xa | WR_PREFIX, TRUE}, {"wR11", 0xb | WR_PREFIX, TRUE},
640 { "wR12", 0xc | WR_PREFIX, TRUE}, {"wR13", 0xd | WR_PREFIX, TRUE},
641 { "wR14", 0xe | WR_PREFIX, TRUE}, {"wR15", 0xf | WR_PREFIX, TRUE},
642 { "wCID", 0x0 | WC_PREFIX, TRUE}, {"wCon", 0x1 | WC_PREFIX, TRUE},
643 {"wCSSF", 0x2 | WC_PREFIX, TRUE}, {"wCASF", 0x3 | WC_PREFIX, TRUE},
644 {"wCGR0", 0x8 | WC_PREFIX, TRUE}, {"wCGR1", 0x9 | WC_PREFIX, TRUE},
645 {"wCGR2", 0xa | WC_PREFIX, TRUE}, {"wCGR3", 0xb | WC_PREFIX, TRUE},
646 {NULL, 0, TRUE}
649 /* Co-processor Numbers. */
650 static const struct reg_entry cp_table[] =
652 {"p0", 0, TRUE}, {"p1", 1, TRUE}, {"p2", 2, TRUE}, {"p3", 3, TRUE},
653 {"p4", 4, TRUE}, {"p5", 5, TRUE}, {"p6", 6, TRUE}, {"p7", 7, TRUE},
654 {"p8", 8, TRUE}, {"p9", 9, TRUE}, {"p10", 10, TRUE}, {"p11", 11, TRUE},
655 {"p12", 12, TRUE}, {"p13", 13, TRUE}, {"p14", 14, TRUE}, {"p15", 15, TRUE},
656 {NULL, 0, TRUE}
659 /* Co-processor Register Numbers. */
660 static const struct reg_entry cn_table[] =
662 {"c0", 0, TRUE}, {"c1", 1, TRUE}, {"c2", 2, TRUE}, {"c3", 3, TRUE},
663 {"c4", 4, TRUE}, {"c5", 5, TRUE}, {"c6", 6, TRUE}, {"c7", 7, TRUE},
664 {"c8", 8, TRUE}, {"c9", 9, TRUE}, {"c10", 10, TRUE}, {"c11", 11, TRUE},
665 {"c12", 12, TRUE}, {"c13", 13, TRUE}, {"c14", 14, TRUE}, {"c15", 15, TRUE},
666 /* Not really valid, but kept for back-wards compatibility. */
667 {"cr0", 0, TRUE}, {"cr1", 1, TRUE}, {"cr2", 2, TRUE}, {"cr3", 3, TRUE},
668 {"cr4", 4, TRUE}, {"cr5", 5, TRUE}, {"cr6", 6, TRUE}, {"cr7", 7, TRUE},
669 {"cr8", 8, TRUE}, {"cr9", 9, TRUE}, {"cr10", 10, TRUE}, {"cr11", 11, TRUE},
670 {"cr12", 12, TRUE}, {"cr13", 13, TRUE}, {"cr14", 14, TRUE}, {"cr15", 15, TRUE},
671 {NULL, 0, TRUE}
674 /* FPA Registers. */
675 static const struct reg_entry fn_table[] =
677 {"f0", 0, TRUE}, {"f1", 1, TRUE}, {"f2", 2, TRUE}, {"f3", 3, TRUE},
678 {"f4", 4, TRUE}, {"f5", 5, TRUE}, {"f6", 6, TRUE}, {"f7", 7, TRUE},
679 {NULL, 0, TRUE}
682 /* VFP SP Registers. */
683 static const struct reg_entry sn_table[] =
685 {"s0", 0, TRUE}, {"s1", 1, TRUE}, {"s2", 2, TRUE}, {"s3", 3, TRUE},
686 {"s4", 4, TRUE}, {"s5", 5, TRUE}, {"s6", 6, TRUE}, {"s7", 7, TRUE},
687 {"s8", 8, TRUE}, {"s9", 9, TRUE}, {"s10", 10, TRUE}, {"s11", 11, TRUE},
688 {"s12", 12, TRUE}, {"s13", 13, TRUE}, {"s14", 14, TRUE}, {"s15", 15, TRUE},
689 {"s16", 16, TRUE}, {"s17", 17, TRUE}, {"s18", 18, TRUE}, {"s19", 19, TRUE},
690 {"s20", 20, TRUE}, {"s21", 21, TRUE}, {"s22", 22, TRUE}, {"s23", 23, TRUE},
691 {"s24", 24, TRUE}, {"s25", 25, TRUE}, {"s26", 26, TRUE}, {"s27", 27, TRUE},
692 {"s28", 28, TRUE}, {"s29", 29, TRUE}, {"s30", 30, TRUE}, {"s31", 31, TRUE},
693 {NULL, 0, TRUE}
696 /* VFP DP Registers. */
697 static const struct reg_entry dn_table[] =
699 {"d0", 0, TRUE}, {"d1", 1, TRUE}, {"d2", 2, TRUE}, {"d3", 3, TRUE},
700 {"d4", 4, TRUE}, {"d5", 5, TRUE}, {"d6", 6, TRUE}, {"d7", 7, TRUE},
701 {"d8", 8, TRUE}, {"d9", 9, TRUE}, {"d10", 10, TRUE}, {"d11", 11, TRUE},
702 {"d12", 12, TRUE}, {"d13", 13, TRUE}, {"d14", 14, TRUE}, {"d15", 15, TRUE},
703 {NULL, 0, TRUE}
706 /* Maverick DSP coprocessor registers. */
707 static const struct reg_entry mav_mvf_table[] =
709 {"mvf0", 0, TRUE}, {"mvf1", 1, TRUE}, {"mvf2", 2, TRUE}, {"mvf3", 3, TRUE},
710 {"mvf4", 4, TRUE}, {"mvf5", 5, TRUE}, {"mvf6", 6, TRUE}, {"mvf7", 7, TRUE},
711 {"mvf8", 8, TRUE}, {"mvf9", 9, TRUE}, {"mvf10", 10, TRUE}, {"mvf11", 11, TRUE},
712 {"mvf12", 12, TRUE}, {"mvf13", 13, TRUE}, {"mvf14", 14, TRUE}, {"mvf15", 15, TRUE},
713 {NULL, 0, TRUE}
716 static const struct reg_entry mav_mvd_table[] =
718 {"mvd0", 0, TRUE}, {"mvd1", 1, TRUE}, {"mvd2", 2, TRUE}, {"mvd3", 3, TRUE},
719 {"mvd4", 4, TRUE}, {"mvd5", 5, TRUE}, {"mvd6", 6, TRUE}, {"mvd7", 7, TRUE},
720 {"mvd8", 8, TRUE}, {"mvd9", 9, TRUE}, {"mvd10", 10, TRUE}, {"mvd11", 11, TRUE},
721 {"mvd12", 12, TRUE}, {"mvd13", 13, TRUE}, {"mvd14", 14, TRUE}, {"mvd15", 15, TRUE},
722 {NULL, 0, TRUE}
725 static const struct reg_entry mav_mvfx_table[] =
727 {"mvfx0", 0, TRUE}, {"mvfx1", 1, TRUE}, {"mvfx2", 2, TRUE}, {"mvfx3", 3, TRUE},
728 {"mvfx4", 4, TRUE}, {"mvfx5", 5, TRUE}, {"mvfx6", 6, TRUE}, {"mvfx7", 7, TRUE},
729 {"mvfx8", 8, TRUE}, {"mvfx9", 9, TRUE}, {"mvfx10", 10, TRUE}, {"mvfx11", 11, TRUE},
730 {"mvfx12", 12, TRUE}, {"mvfx13", 13, TRUE}, {"mvfx14", 14, TRUE}, {"mvfx15", 15, TRUE},
731 {NULL, 0, TRUE}
734 static const struct reg_entry mav_mvdx_table[] =
736 {"mvdx0", 0, TRUE}, {"mvdx1", 1, TRUE}, {"mvdx2", 2, TRUE}, {"mvdx3", 3, TRUE},
737 {"mvdx4", 4, TRUE}, {"mvdx5", 5, TRUE}, {"mvdx6", 6, TRUE}, {"mvdx7", 7, TRUE},
738 {"mvdx8", 8, TRUE}, {"mvdx9", 9, TRUE}, {"mvdx10", 10, TRUE}, {"mvdx11", 11, TRUE},
739 {"mvdx12", 12, TRUE}, {"mvdx13", 13, TRUE}, {"mvdx14", 14, TRUE}, {"mvdx15", 15, TRUE},
740 {NULL, 0, TRUE}
743 static const struct reg_entry mav_mvax_table[] =
745 {"mvax0", 0, TRUE}, {"mvax1", 1, TRUE}, {"mvax2", 2, TRUE}, {"mvax3", 3, TRUE},
746 {NULL, 0, TRUE}
749 static const struct reg_entry mav_dspsc_table[] =
751 {"dspsc", 0, TRUE},
752 {NULL, 0, TRUE}
755 struct reg_map
757 const struct reg_entry *names;
758 int max_regno;
759 struct hash_control *htab;
760 const char *expected;
763 struct reg_map all_reg_maps[] =
765 {rn_table, 15, NULL, N_("ARM register expected")},
766 {cp_table, 15, NULL, N_("bad or missing co-processor number")},
767 {cn_table, 15, NULL, N_("co-processor register expected")},
768 {fn_table, 7, NULL, N_("FPA register expected")},
769 {sn_table, 31, NULL, N_("VFP single precision register expected")},
770 {dn_table, 15, NULL, N_("VFP double precision register expected")},
771 {mav_mvf_table, 15, NULL, N_("Maverick MVF register expected")},
772 {mav_mvd_table, 15, NULL, N_("Maverick MVD register expected")},
773 {mav_mvfx_table, 15, NULL, N_("Maverick MVFX register expected")},
774 {mav_mvdx_table, 15, NULL, N_("Maverick MVDX register expected")},
775 {mav_mvax_table, 3, NULL, N_("Maverick MVAX register expected")},
776 {mav_dspsc_table, 0, NULL, N_("Maverick DSPSC register expected")},
777 {iwmmxt_table, 23, NULL, N_("Intel Wireless MMX technology register expected")},
780 /* Enumeration matching entries in table above. */
781 enum arm_reg_type
783 REG_TYPE_RN = 0,
784 #define REG_TYPE_FIRST REG_TYPE_RN
785 REG_TYPE_CP = 1,
786 REG_TYPE_CN = 2,
787 REG_TYPE_FN = 3,
788 REG_TYPE_SN = 4,
789 REG_TYPE_DN = 5,
790 REG_TYPE_MVF = 6,
791 REG_TYPE_MVD = 7,
792 REG_TYPE_MVFX = 8,
793 REG_TYPE_MVDX = 9,
794 REG_TYPE_MVAX = 10,
795 REG_TYPE_DSPSC = 11,
796 REG_TYPE_IWMMXT = 12,
798 REG_TYPE_MAX = 13
801 /* Functions called by parser. */
802 /* ARM instructions. */
803 static void do_arit PARAMS ((char *));
804 static void do_cmp PARAMS ((char *));
805 static void do_mov PARAMS ((char *));
806 static void do_ldst PARAMS ((char *));
807 static void do_ldstt PARAMS ((char *));
808 static void do_ldmstm PARAMS ((char *));
809 static void do_branch PARAMS ((char *));
810 static void do_swi PARAMS ((char *));
812 /* Pseudo Op codes. */
813 static void do_adr PARAMS ((char *));
814 static void do_adrl PARAMS ((char *));
815 static void do_empty PARAMS ((char *));
817 /* ARM v2. */
818 static void do_mul PARAMS ((char *));
819 static void do_mla PARAMS ((char *));
821 /* ARM v2S. */
822 static void do_swap PARAMS ((char *));
824 /* ARM v3. */
825 static void do_msr PARAMS ((char *));
826 static void do_mrs PARAMS ((char *));
828 /* ARM v3M. */
829 static void do_mull PARAMS ((char *));
831 /* ARM v4. */
832 static void do_ldstv4 PARAMS ((char *));
834 /* ARM v4T. */
835 static void do_bx PARAMS ((char *));
837 /* ARM v5T. */
838 static void do_blx PARAMS ((char *));
839 static void do_bkpt PARAMS ((char *));
840 static void do_clz PARAMS ((char *));
841 static void do_lstc2 PARAMS ((char *));
842 static void do_cdp2 PARAMS ((char *));
843 static void do_co_reg2 PARAMS ((char *));
845 /* ARM v5TExP. */
846 static void do_smla PARAMS ((char *));
847 static void do_smlal PARAMS ((char *));
848 static void do_smul PARAMS ((char *));
849 static void do_qadd PARAMS ((char *));
851 /* ARM v5TE. */
852 static void do_pld PARAMS ((char *));
853 static void do_ldrd PARAMS ((char *));
854 static void do_co_reg2c PARAMS ((char *));
856 /* ARM v5TEJ. */
857 static void do_bxj PARAMS ((char *));
859 /* Coprocessor Instructions. */
860 static void do_cdp PARAMS ((char *));
861 static void do_lstc PARAMS ((char *));
862 static void do_co_reg PARAMS ((char *));
864 /* FPA instructions. */
865 static void do_fpa_ctrl PARAMS ((char *));
866 static void do_fpa_ldst PARAMS ((char *));
867 static void do_fpa_ldmstm PARAMS ((char *));
868 static void do_fpa_dyadic PARAMS ((char *));
869 static void do_fpa_monadic PARAMS ((char *));
870 static void do_fpa_cmp PARAMS ((char *));
871 static void do_fpa_from_reg PARAMS ((char *));
872 static void do_fpa_to_reg PARAMS ((char *));
874 /* VFP instructions. */
875 static void do_vfp_sp_monadic PARAMS ((char *));
876 static void do_vfp_dp_monadic PARAMS ((char *));
877 static void do_vfp_sp_dyadic PARAMS ((char *));
878 static void do_vfp_dp_dyadic PARAMS ((char *));
879 static void do_vfp_reg_from_sp PARAMS ((char *));
880 static void do_vfp_sp_from_reg PARAMS ((char *));
881 static void do_vfp_sp_reg2 PARAMS ((char *));
882 static void do_vfp_reg_from_dp PARAMS ((char *));
883 static void do_vfp_reg2_from_dp PARAMS ((char *));
884 static void do_vfp_dp_from_reg PARAMS ((char *));
885 static void do_vfp_dp_from_reg2 PARAMS ((char *));
886 static void do_vfp_reg_from_ctrl PARAMS ((char *));
887 static void do_vfp_ctrl_from_reg PARAMS ((char *));
888 static void do_vfp_sp_ldst PARAMS ((char *));
889 static void do_vfp_dp_ldst PARAMS ((char *));
890 static void do_vfp_sp_ldstmia PARAMS ((char *));
891 static void do_vfp_sp_ldstmdb PARAMS ((char *));
892 static void do_vfp_dp_ldstmia PARAMS ((char *));
893 static void do_vfp_dp_ldstmdb PARAMS ((char *));
894 static void do_vfp_xp_ldstmia PARAMS ((char *));
895 static void do_vfp_xp_ldstmdb PARAMS ((char *));
896 static void do_vfp_sp_compare_z PARAMS ((char *));
897 static void do_vfp_dp_compare_z PARAMS ((char *));
898 static void do_vfp_dp_sp_cvt PARAMS ((char *));
899 static void do_vfp_sp_dp_cvt PARAMS ((char *));
901 /* XScale. */
902 static void do_xsc_mia PARAMS ((char *));
903 static void do_xsc_mar PARAMS ((char *));
904 static void do_xsc_mra PARAMS ((char *));
906 /* Maverick. */
907 static void do_mav_binops PARAMS ((char *, int, enum arm_reg_type,
908 enum arm_reg_type));
909 static void do_mav_binops_1a PARAMS ((char *));
910 static void do_mav_binops_1b PARAMS ((char *));
911 static void do_mav_binops_1c PARAMS ((char *));
912 static void do_mav_binops_1d PARAMS ((char *));
913 static void do_mav_binops_1e PARAMS ((char *));
914 static void do_mav_binops_1f PARAMS ((char *));
915 static void do_mav_binops_1g PARAMS ((char *));
916 static void do_mav_binops_1h PARAMS ((char *));
917 static void do_mav_binops_1i PARAMS ((char *));
918 static void do_mav_binops_1j PARAMS ((char *));
919 static void do_mav_binops_1k PARAMS ((char *));
920 static void do_mav_binops_1l PARAMS ((char *));
921 static void do_mav_binops_1m PARAMS ((char *));
922 static void do_mav_binops_1n PARAMS ((char *));
923 static void do_mav_binops_1o PARAMS ((char *));
924 static void do_mav_binops_2a PARAMS ((char *));
925 static void do_mav_binops_2b PARAMS ((char *));
926 static void do_mav_binops_2c PARAMS ((char *));
927 static void do_mav_binops_3a PARAMS ((char *));
928 static void do_mav_binops_3b PARAMS ((char *));
929 static void do_mav_binops_3c PARAMS ((char *));
930 static void do_mav_binops_3d PARAMS ((char *));
931 static void do_mav_triple PARAMS ((char *, int, enum arm_reg_type,
932 enum arm_reg_type,
933 enum arm_reg_type));
934 static void do_mav_triple_4a PARAMS ((char *));
935 static void do_mav_triple_4b PARAMS ((char *));
936 static void do_mav_triple_5a PARAMS ((char *));
937 static void do_mav_triple_5b PARAMS ((char *));
938 static void do_mav_triple_5c PARAMS ((char *));
939 static void do_mav_triple_5d PARAMS ((char *));
940 static void do_mav_triple_5e PARAMS ((char *));
941 static void do_mav_triple_5f PARAMS ((char *));
942 static void do_mav_triple_5g PARAMS ((char *));
943 static void do_mav_triple_5h PARAMS ((char *));
944 static void do_mav_quad PARAMS ((char *, int, enum arm_reg_type,
945 enum arm_reg_type,
946 enum arm_reg_type,
947 enum arm_reg_type));
948 static void do_mav_quad_6a PARAMS ((char *));
949 static void do_mav_quad_6b PARAMS ((char *));
950 static void do_mav_dspsc_1 PARAMS ((char *));
951 static void do_mav_dspsc_2 PARAMS ((char *));
952 static void do_mav_shift PARAMS ((char *, enum arm_reg_type,
953 enum arm_reg_type));
954 static void do_mav_shift_1 PARAMS ((char *));
955 static void do_mav_shift_2 PARAMS ((char *));
956 static void do_mav_ldst PARAMS ((char *, enum arm_reg_type));
957 static void do_mav_ldst_1 PARAMS ((char *));
958 static void do_mav_ldst_2 PARAMS ((char *));
959 static void do_mav_ldst_3 PARAMS ((char *));
960 static void do_mav_ldst_4 PARAMS ((char *));
962 static int mav_reg_required_here PARAMS ((char **, int,
963 enum arm_reg_type));
964 static int mav_parse_offset PARAMS ((char **, int *));
966 static void fix_new_arm PARAMS ((fragS *, int, short, expressionS *,
967 int, int));
968 static int arm_reg_parse PARAMS ((char **, struct hash_control *));
969 static enum arm_reg_type arm_reg_parse_any PARAMS ((char *));
970 static const struct asm_psr * arm_psr_parse PARAMS ((char **));
971 static void symbol_locate PARAMS ((symbolS *, const char *, segT, valueT,
972 fragS *));
973 static int add_to_lit_pool PARAMS ((void));
974 static unsigned validate_immediate PARAMS ((unsigned));
975 static unsigned validate_immediate_twopart PARAMS ((unsigned int,
976 unsigned int *));
977 static int validate_offset_imm PARAMS ((unsigned int, int));
978 static void opcode_select PARAMS ((int));
979 static void end_of_line PARAMS ((char *));
980 static int reg_required_here PARAMS ((char **, int));
981 static int psr_required_here PARAMS ((char **));
982 static int co_proc_number PARAMS ((char **));
983 static int cp_opc_expr PARAMS ((char **, int, int));
984 static int cp_reg_required_here PARAMS ((char **, int));
985 static int fp_reg_required_here PARAMS ((char **, int));
986 static int vfp_sp_reg_required_here PARAMS ((char **, enum vfp_sp_reg_pos));
987 static int vfp_dp_reg_required_here PARAMS ((char **, enum vfp_dp_reg_pos));
988 static void vfp_sp_ldstm PARAMS ((char *, enum vfp_ldstm_type));
989 static void vfp_dp_ldstm PARAMS ((char *, enum vfp_ldstm_type));
990 static long vfp_sp_reg_list PARAMS ((char **, enum vfp_sp_reg_pos));
991 static long vfp_dp_reg_list PARAMS ((char **));
992 static int vfp_psr_required_here PARAMS ((char **str));
993 static const struct vfp_reg *vfp_psr_parse PARAMS ((char **str));
994 static int cp_address_offset PARAMS ((char **));
995 static int cp_address_required_here PARAMS ((char **, int));
996 static int my_get_float_expression PARAMS ((char **));
997 static int skip_past_comma PARAMS ((char **));
998 static int walk_no_bignums PARAMS ((symbolS *));
999 static int negate_data_op PARAMS ((unsigned long *, unsigned long));
1000 static int data_op2 PARAMS ((char **));
1001 static int fp_op2 PARAMS ((char **));
1002 static long reg_list PARAMS ((char **));
1003 static void thumb_load_store PARAMS ((char *, int, int));
1004 static int decode_shift PARAMS ((char **, int));
1005 static int ldst_extend PARAMS ((char **));
1006 static int ldst_extend_v4 PARAMS ((char **));
1007 static void thumb_add_sub PARAMS ((char *, int));
1008 static void insert_reg PARAMS ((const struct reg_entry *,
1009 struct hash_control *));
1010 static void thumb_shift PARAMS ((char *, int));
1011 static void thumb_mov_compare PARAMS ((char *, int));
1012 static void build_arm_ops_hsh PARAMS ((void));
1013 static void set_constant_flonums PARAMS ((void));
1014 static valueT md_chars_to_number PARAMS ((char *, int));
1015 static void build_reg_hsh PARAMS ((struct reg_map *));
1016 static void insert_reg_alias PARAMS ((char *, int, struct hash_control *));
1017 static int create_register_alias PARAMS ((char *, char *));
1018 static void output_inst PARAMS ((const char *));
1019 static int accum0_required_here PARAMS ((char **));
1020 static int ld_mode_required_here PARAMS ((char **));
1021 static void do_branch25 PARAMS ((char *));
1022 static symbolS * find_real_start PARAMS ((symbolS *));
1023 #ifdef OBJ_ELF
1024 static bfd_reloc_code_real_type arm_parse_reloc PARAMS ((void));
1025 #endif
1027 static int wreg_required_here PARAMS ((char **, int, enum wreg_type));
1028 static void do_iwmmxt_byte_addr PARAMS ((char *));
1029 static void do_iwmmxt_tandc PARAMS ((char *));
1030 static void do_iwmmxt_tbcst PARAMS ((char *));
1031 static void do_iwmmxt_textrc PARAMS ((char *));
1032 static void do_iwmmxt_textrm PARAMS ((char *));
1033 static void do_iwmmxt_tinsr PARAMS ((char *));
1034 static void do_iwmmxt_tmcr PARAMS ((char *));
1035 static void do_iwmmxt_tmcrr PARAMS ((char *));
1036 static void do_iwmmxt_tmia PARAMS ((char *));
1037 static void do_iwmmxt_tmovmsk PARAMS ((char *));
1038 static void do_iwmmxt_tmrc PARAMS ((char *));
1039 static void do_iwmmxt_tmrrc PARAMS ((char *));
1040 static void do_iwmmxt_torc PARAMS ((char *));
1041 static void do_iwmmxt_waligni PARAMS ((char *));
1042 static void do_iwmmxt_wmov PARAMS ((char *));
1043 static void do_iwmmxt_word_addr PARAMS ((char *));
1044 static void do_iwmmxt_wrwr PARAMS ((char *));
1045 static void do_iwmmxt_wrwrwcg PARAMS ((char *));
1046 static void do_iwmmxt_wrwrwr PARAMS ((char *));
1047 static void do_iwmmxt_wshufh PARAMS ((char *));
1048 static void do_iwmmxt_wzero PARAMS ((char *));
1049 static int cp_byte_address_offset PARAMS ((char **));
1050 static int cp_byte_address_required_here PARAMS ((char **));
1052 /* ARM instructions take 4bytes in the object file, Thumb instructions
1053 take 2: */
1054 #define INSN_SIZE 4
1056 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
1057 #define MAV_MODE1 0x100c
1059 /* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
1060 #define MAV_MODE2 0x0c10
1062 /* "INSN<cond> X,Y" where X:0, Y:bit16. */
1063 #define MAV_MODE3 0x1000
1065 /* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
1066 #define MAV_MODE4 0x0c0010
1068 /* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
1069 #define MAV_MODE5 0x00100c
1071 /* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
1072 #define MAV_MODE6 0x00100c05
1074 struct asm_opcode
1076 /* Basic string to match. */
1077 const char * template;
1079 /* Basic instruction code. */
1080 unsigned long value;
1082 /* Offset into the template where the condition code (if any) will be.
1083 If zero, then the instruction is never conditional. */
1084 unsigned cond_offset;
1086 /* Which architecture variant provides this instruction. */
1087 unsigned long variant;
1089 /* Function to call to parse args. */
1090 void (* parms) PARAMS ((char *));
1093 static const struct asm_opcode insns[] =
1095 /* Core ARM Instructions. */
1096 {"and", 0xe0000000, 3, ARM_EXT_V1, do_arit},
1097 {"ands", 0xe0100000, 3, ARM_EXT_V1, do_arit},
1098 {"eor", 0xe0200000, 3, ARM_EXT_V1, do_arit},
1099 {"eors", 0xe0300000, 3, ARM_EXT_V1, do_arit},
1100 {"sub", 0xe0400000, 3, ARM_EXT_V1, do_arit},
1101 {"subs", 0xe0500000, 3, ARM_EXT_V1, do_arit},
1102 {"rsb", 0xe0600000, 3, ARM_EXT_V1, do_arit},
1103 {"rsbs", 0xe0700000, 3, ARM_EXT_V1, do_arit},
1104 {"add", 0xe0800000, 3, ARM_EXT_V1, do_arit},
1105 {"adds", 0xe0900000, 3, ARM_EXT_V1, do_arit},
1106 {"adc", 0xe0a00000, 3, ARM_EXT_V1, do_arit},
1107 {"adcs", 0xe0b00000, 3, ARM_EXT_V1, do_arit},
1108 {"sbc", 0xe0c00000, 3, ARM_EXT_V1, do_arit},
1109 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1, do_arit},
1110 {"rsc", 0xe0e00000, 3, ARM_EXT_V1, do_arit},
1111 {"rscs", 0xe0f00000, 3, ARM_EXT_V1, do_arit},
1112 {"orr", 0xe1800000, 3, ARM_EXT_V1, do_arit},
1113 {"orrs", 0xe1900000, 3, ARM_EXT_V1, do_arit},
1114 {"bic", 0xe1c00000, 3, ARM_EXT_V1, do_arit},
1115 {"bics", 0xe1d00000, 3, ARM_EXT_V1, do_arit},
1117 {"tst", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
1118 {"tsts", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
1119 {"tstp", 0xe110f000, 3, ARM_EXT_V1, do_cmp},
1120 {"teq", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
1121 {"teqs", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
1122 {"teqp", 0xe130f000, 3, ARM_EXT_V1, do_cmp},
1123 {"cmp", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
1124 {"cmps", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
1125 {"cmpp", 0xe150f000, 3, ARM_EXT_V1, do_cmp},
1126 {"cmn", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
1127 {"cmns", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
1128 {"cmnp", 0xe170f000, 3, ARM_EXT_V1, do_cmp},
1130 {"mov", 0xe1a00000, 3, ARM_EXT_V1, do_mov},
1131 {"movs", 0xe1b00000, 3, ARM_EXT_V1, do_mov},
1132 {"mvn", 0xe1e00000, 3, ARM_EXT_V1, do_mov},
1133 {"mvns", 0xe1f00000, 3, ARM_EXT_V1, do_mov},
1135 {"ldr", 0xe4100000, 3, ARM_EXT_V1, do_ldst},
1136 {"ldrb", 0xe4500000, 3, ARM_EXT_V1, do_ldst},
1137 {"ldrt", 0xe4300000, 3, ARM_EXT_V1, do_ldstt},
1138 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1, do_ldstt},
1139 {"str", 0xe4000000, 3, ARM_EXT_V1, do_ldst},
1140 {"strb", 0xe4400000, 3, ARM_EXT_V1, do_ldst},
1141 {"strt", 0xe4200000, 3, ARM_EXT_V1, do_ldstt},
1142 {"strbt", 0xe4600000, 3, ARM_EXT_V1, do_ldstt},
1144 {"stmia", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
1145 {"stmib", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
1146 {"stmda", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
1147 {"stmdb", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
1148 {"stmfd", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
1149 {"stmfa", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
1150 {"stmea", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
1151 {"stmed", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
1153 {"ldmia", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
1154 {"ldmib", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
1155 {"ldmda", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
1156 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
1157 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
1158 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
1159 {"ldmea", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
1160 {"ldmed", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
1162 {"swi", 0xef000000, 3, ARM_EXT_V1, do_swi},
1163 #ifdef TE_WINCE
1164 /* XXX This is the wrong place to do this. Think multi-arch. */
1165 {"bl", 0xeb000000, 2, ARM_EXT_V1, do_branch},
1166 {"b", 0xea000000, 1, ARM_EXT_V1, do_branch},
1167 #else
1168 {"bl", 0xebfffffe, 2, ARM_EXT_V1, do_branch},
1169 {"b", 0xeafffffe, 1, ARM_EXT_V1, do_branch},
1170 #endif
1172 /* Pseudo ops. */
1173 {"adr", 0xe28f0000, 3, ARM_EXT_V1, do_adr},
1174 {"adrl", 0xe28f0000, 3, ARM_EXT_V1, do_adrl},
1175 {"nop", 0xe1a00000, 3, ARM_EXT_V1, do_empty},
1177 /* ARM 2 multiplies. */
1178 {"mul", 0xe0000090, 3, ARM_EXT_V2, do_mul},
1179 {"muls", 0xe0100090, 3, ARM_EXT_V2, do_mul},
1180 {"mla", 0xe0200090, 3, ARM_EXT_V2, do_mla},
1181 {"mlas", 0xe0300090, 3, ARM_EXT_V2, do_mla},
1183 /* Generic copressor instructions. */
1184 {"cdp", 0xee000000, 3, ARM_EXT_V2, do_cdp},
1185 {"ldc", 0xec100000, 3, ARM_EXT_V2, do_lstc},
1186 {"ldcl", 0xec500000, 3, ARM_EXT_V2, do_lstc},
1187 {"stc", 0xec000000, 3, ARM_EXT_V2, do_lstc},
1188 {"stcl", 0xec400000, 3, ARM_EXT_V2, do_lstc},
1189 {"mcr", 0xee000010, 3, ARM_EXT_V2, do_co_reg},
1190 {"mrc", 0xee100010, 3, ARM_EXT_V2, do_co_reg},
1192 /* ARM 3 - swp instructions. */
1193 {"swp", 0xe1000090, 3, ARM_EXT_V2S, do_swap},
1194 {"swpb", 0xe1400090, 3, ARM_EXT_V2S, do_swap},
1196 /* ARM 6 Status register instructions. */
1197 {"mrs", 0xe10f0000, 3, ARM_EXT_V3, do_mrs},
1198 {"msr", 0xe120f000, 3, ARM_EXT_V3, do_msr},
1199 /* ScottB: our code uses 0xe128f000 for msr.
1200 NickC: but this is wrong because the bits 16 through 19 are
1201 handled by the PSR_xxx defines above. */
1203 /* ARM 7M long multiplies. */
1204 {"smull", 0xe0c00090, 5, ARM_EXT_V3M, do_mull},
1205 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M, do_mull},
1206 {"umull", 0xe0800090, 5, ARM_EXT_V3M, do_mull},
1207 {"umulls", 0xe0900090, 5, ARM_EXT_V3M, do_mull},
1208 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M, do_mull},
1209 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M, do_mull},
1210 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M, do_mull},
1211 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M, do_mull},
1213 /* ARM Architecture 4. */
1214 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4, do_ldstv4},
1215 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4, do_ldstv4},
1216 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4, do_ldstv4},
1217 {"strh", 0xe00000b0, 3, ARM_EXT_V4, do_ldstv4},
1219 /* ARM Architecture 4T. */
1220 /* Note: bx (and blx) are required on V5, even if the processor does
1221 not support Thumb. */
1222 {"bx", 0xe12fff10, 2, ARM_EXT_V4T | ARM_EXT_V5, do_bx},
1224 /* ARM Architecture 5T. */
1225 /* Note: blx has 2 variants, so the .value is set dynamically.
1226 Only one of the variants has conditional execution. */
1227 {"blx", 0xe0000000, 3, ARM_EXT_V5, do_blx},
1228 {"clz", 0xe16f0f10, 3, ARM_EXT_V5, do_clz},
1229 {"bkpt", 0xe1200070, 0, ARM_EXT_V5, do_bkpt},
1230 {"ldc2", 0xfc100000, 0, ARM_EXT_V5, do_lstc2},
1231 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5, do_lstc2},
1232 {"stc2", 0xfc000000, 0, ARM_EXT_V5, do_lstc2},
1233 {"stc2l", 0xfc400000, 0, ARM_EXT_V5, do_lstc2},
1234 {"cdp2", 0xfe000000, 0, ARM_EXT_V5, do_cdp2},
1235 {"mcr2", 0xfe000010, 0, ARM_EXT_V5, do_co_reg2},
1236 {"mrc2", 0xfe100010, 0, ARM_EXT_V5, do_co_reg2},
1238 /* ARM Architecture 5TExP. */
1239 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP, do_smla},
1240 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP, do_smla},
1241 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP, do_smla},
1242 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP, do_smla},
1244 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP, do_smla},
1245 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP, do_smla},
1247 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP, do_smlal},
1248 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP, do_smlal},
1249 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP, do_smlal},
1250 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP, do_smlal},
1252 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP, do_smul},
1253 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP, do_smul},
1254 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP, do_smul},
1255 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP, do_smul},
1257 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP, do_smul},
1258 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP, do_smul},
1260 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP, do_qadd},
1261 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP, do_qadd},
1262 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP, do_qadd},
1263 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP, do_qadd},
1265 /* ARM Architecture 5TE. */
1266 {"pld", 0xf450f000, 0, ARM_EXT_V5E, do_pld},
1267 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E, do_ldrd},
1268 {"strd", 0xe00000f0, 3, ARM_EXT_V5E, do_ldrd},
1270 {"mcrr", 0xec400000, 4, ARM_EXT_V5E, do_co_reg2c},
1271 {"mrrc", 0xec500000, 4, ARM_EXT_V5E, do_co_reg2c},
1273 /* ARM Architecture 5TEJ. */
1274 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J, do_bxj},
1276 /* Core FPA instruction set (V1). */
1277 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1278 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1279 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1280 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1282 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1283 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1284 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1285 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1287 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1288 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1289 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1290 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1292 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1293 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1294 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1295 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1296 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1297 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1298 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1299 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1300 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1301 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1302 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1303 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1305 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1306 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1307 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1308 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1309 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1310 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1311 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1312 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1313 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1314 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1315 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1316 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1318 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1319 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1320 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1321 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1322 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1323 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1324 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1325 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1326 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1327 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1328 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1329 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1331 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1332 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1333 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1334 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1335 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1336 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1337 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1338 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1339 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1340 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1341 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1342 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1344 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1345 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1346 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1347 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1348 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1349 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1350 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1351 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1352 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1353 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1354 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1355 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1357 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1358 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1359 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1360 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1361 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1362 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1363 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1364 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1365 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1366 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1367 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1368 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1370 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1371 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1372 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1373 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1374 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1375 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1376 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1377 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1378 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1379 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1380 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1381 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1383 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1384 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1385 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1386 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1387 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1388 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1389 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1390 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1391 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1392 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1393 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1394 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1396 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1397 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1398 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1399 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1400 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1401 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1402 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1403 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1404 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1405 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1406 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1407 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1409 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1410 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1411 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1412 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1413 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1414 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1415 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1416 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1417 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1418 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1419 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1420 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1422 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1423 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1424 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1425 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1426 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1427 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1428 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1429 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1430 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1431 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1432 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1433 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1435 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1436 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1437 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1438 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1439 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1440 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1441 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1442 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1443 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1444 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1445 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1446 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1448 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1449 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1450 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1451 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1452 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1453 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1454 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1455 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1456 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1457 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1458 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1459 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1461 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1462 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1463 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1464 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1465 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1466 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1467 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1468 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1469 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1470 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1471 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1472 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1474 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1475 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1476 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1477 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1478 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1479 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1480 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1481 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1482 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1483 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1484 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1485 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1487 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1488 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1489 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1490 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1491 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1492 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1493 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1494 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1495 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1496 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1497 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1498 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1500 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1501 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1502 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1503 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1504 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1505 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1506 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1507 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1508 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1509 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1510 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1511 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1513 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1514 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1515 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1516 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1517 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1518 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1519 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1520 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1521 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1522 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1523 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1524 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1526 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1527 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1528 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1529 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1530 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1531 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1532 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1533 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1534 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1535 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1536 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1537 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1539 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1540 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1541 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1542 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1543 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1544 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1545 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1546 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1547 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1548 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1549 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1550 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1552 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1553 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1554 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1555 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1556 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1557 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1558 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1559 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1560 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1561 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1562 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1563 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1565 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1566 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1567 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1568 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1569 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1570 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1571 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1572 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1573 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1574 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1575 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1576 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1578 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1579 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1580 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1581 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1582 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1583 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1584 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1585 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1586 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1587 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1588 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1589 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1591 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1592 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1593 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1594 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1595 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1596 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1597 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1598 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1599 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1600 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1601 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1602 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1604 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1605 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1606 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1607 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1608 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1609 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1610 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1611 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1612 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1613 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1614 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1615 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1617 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1618 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1619 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1620 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1621 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1622 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1623 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1624 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1625 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1626 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1627 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1628 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1630 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1631 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1632 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1633 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1634 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1635 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1636 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1637 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1638 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1639 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1640 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1641 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1643 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1644 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1645 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1646 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1647 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1648 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1649 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1650 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1651 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1652 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1653 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1654 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1656 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1657 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1658 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1659 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1660 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1661 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1662 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1663 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1664 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1665 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1666 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1667 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1669 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1670 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1671 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1672 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1673 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
1674 not be an optional suffix, but part of the instruction. To be
1675 compatible, we accept either. */
1676 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
1677 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
1679 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1680 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1681 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1682 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1683 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1684 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1685 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1686 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1687 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1688 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1689 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1690 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1692 /* The implementation of the FIX instruction is broken on some
1693 assemblers, in that it accepts a precision specifier as well as a
1694 rounding specifier, despite the fact that this is meaningless.
1695 To be more compatible, we accept it as well, though of course it
1696 does not set any bits. */
1697 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1698 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1699 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1700 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1701 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1702 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1703 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1704 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1705 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1706 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1707 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1708 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1709 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1711 /* Instructions that were new with the real FPA, call them V2. */
1712 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1713 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1714 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1715 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1716 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1717 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1719 /* VFP V1xD (single precision). */
1720 /* Moves and type conversions. */
1721 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1722 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_sp},
1723 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_from_reg},
1724 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD, do_empty},
1725 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1726 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1727 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1728 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1729 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1730 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1731 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_ctrl},
1732 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_ctrl_from_reg},
1734 /* Memory operations. */
1735 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
1736 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
1737 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1738 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1739 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1740 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1741 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1742 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1743 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1744 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1745 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1746 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1747 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1748 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1749 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1750 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1751 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1752 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1754 /* Monadic operations. */
1755 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1756 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1757 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1759 /* Dyadic operations. */
1760 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1761 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1762 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1763 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1764 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1765 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1766 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1767 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1768 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1770 /* Comparisons. */
1771 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1772 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
1773 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1774 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
1776 /* VFP V1 (Double precision). */
1777 /* Moves and type conversions. */
1778 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1779 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
1780 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1781 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
1782 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
1783 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
1784 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
1785 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
1786 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
1787 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1788 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1789 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1790 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1792 /* Memory operations. */
1793 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
1794 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
1795 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1796 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1797 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1798 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1799 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1800 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1801 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1802 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1804 /* Monadic operations. */
1805 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1806 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1807 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1809 /* Dyadic operations. */
1810 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1811 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1812 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1813 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1814 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1815 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1816 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1817 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1818 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1820 /* Comparisons. */
1821 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1822 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
1823 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1824 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
1826 /* VFP V2. */
1827 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2, do_vfp_sp_reg2},
1828 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2, do_vfp_sp_reg2},
1829 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2, do_vfp_dp_from_reg2},
1830 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_dp},
1832 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
1833 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE, do_xsc_mia},
1834 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1835 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1836 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1837 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1838 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1839 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE, do_xsc_mar},
1840 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE, do_xsc_mra},
1842 /* Intel Wireless MMX technology instructions. */
1843 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
1844 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
1845 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
1846 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
1847 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
1848 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
1849 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
1850 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
1851 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
1852 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
1853 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
1854 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
1855 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
1856 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
1857 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
1858 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
1859 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
1860 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
1861 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmcr},
1862 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmcrr},
1863 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
1864 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
1865 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
1866 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
1867 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
1868 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
1869 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
1870 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
1871 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
1872 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmrc},
1873 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmrrc},
1874 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
1875 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
1876 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
1877 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1878 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1879 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1880 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1881 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1882 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1883 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1884 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1885 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1886 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1887 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1888 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1889 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT, do_iwmmxt_waligni},
1890 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1891 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1892 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1893 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1894 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1895 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1896 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1897 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1898 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1899 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1900 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1901 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1902 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1903 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1904 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1905 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1906 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1907 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1908 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1909 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
1910 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
1911 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
1912 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
1913 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1914 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1915 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1916 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1917 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1918 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1919 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1920 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1921 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1922 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1923 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1924 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1925 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1926 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1927 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1928 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1929 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1930 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1931 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wmov},
1932 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1933 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1934 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1935 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1936 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1937 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1938 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1939 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1940 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1941 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1942 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1943 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1944 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
1945 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1946 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
1947 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1948 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
1949 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1950 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1951 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1952 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1953 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wshufh},
1954 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1955 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
1956 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1957 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
1958 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1959 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
1960 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1961 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
1962 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1963 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
1964 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1965 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
1966 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1967 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
1968 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1969 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
1970 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1971 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
1972 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
1973 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
1974 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
1975 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
1976 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1977 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1978 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1979 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1980 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1981 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1982 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1983 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1984 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1985 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1986 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1987 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1988 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1989 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1990 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1991 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1992 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1993 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1994 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1995 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1996 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1997 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1998 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1999 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2000 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2001 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2002 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2003 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2004 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wzero},
2006 /* Cirrus Maverick instructions. */
2007 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
2008 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
2009 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
2010 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
2011 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
2012 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
2013 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
2014 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
2015 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK, do_mav_binops_2a},
2016 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK, do_mav_binops_1a},
2017 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
2018 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
2019 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
2020 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
2021 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
2022 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
2023 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
2024 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
2025 {"cfmval32", 0xee100610, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2026 {"cfmv32al", 0xee000610, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2027 {"cfmvam32", 0xee100630, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2028 {"cfmv32am", 0xee000630, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2029 {"cfmvah32", 0xee100650, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2030 {"cfmv32ah", 0xee000650, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2031 {"cfmva32", 0xee100670, 7, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2032 {"cfmv32a", 0xee000670, 7, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2033 {"cfmva64", 0xee100690, 7, ARM_CEXT_MAVERICK, do_mav_binops_3c},
2034 {"cfmv64a", 0xee000690, 7, ARM_CEXT_MAVERICK, do_mav_binops_3d},
2035 {"cfmvsc32", 0xee1006b0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_1},
2036 {"cfmv32sc", 0xee0006b0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_2},
2037 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
2038 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
2039 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK, do_mav_binops_1f},
2040 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK, do_mav_binops_1g},
2041 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK, do_mav_binops_1h},
2042 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1i},
2043 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1j},
2044 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1k},
2045 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK, do_mav_binops_1l},
2046 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1m},
2047 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1l},
2048 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1m},
2049 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK, do_mav_triple_4a},
2050 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK, do_mav_triple_4b},
2051 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK, do_mav_shift_1},
2052 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK, do_mav_shift_2},
2053 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK, do_mav_triple_5a},
2054 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5b},
2055 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK, do_mav_triple_5c},
2056 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5d},
2057 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
2058 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
2059 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
2060 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
2061 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
2062 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
2063 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
2064 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
2065 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
2066 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
2067 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
2068 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
2069 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
2070 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
2071 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2072 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
2073 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2074 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
2075 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2076 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
2077 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2078 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2079 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
2080 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
2081 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
2082 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
2085 /* Defines for various bits that we will want to toggle. */
2086 #define INST_IMMEDIATE 0x02000000
2087 #define OFFSET_REG 0x02000000
2088 #define HWOFFSET_IMM 0x00400000
2089 #define SHIFT_BY_REG 0x00000010
2090 #define PRE_INDEX 0x01000000
2091 #define INDEX_UP 0x00800000
2092 #define WRITE_BACK 0x00200000
2093 #define LDM_TYPE_2_OR_3 0x00400000
2095 #define LITERAL_MASK 0xf000f000
2096 #define OPCODE_MASK 0xfe1fffff
2097 #define V4_STR_BIT 0x00000020
2099 #define DATA_OP_SHIFT 21
2101 /* Codes to distinguish the arithmetic instructions. */
2102 #define OPCODE_AND 0
2103 #define OPCODE_EOR 1
2104 #define OPCODE_SUB 2
2105 #define OPCODE_RSB 3
2106 #define OPCODE_ADD 4
2107 #define OPCODE_ADC 5
2108 #define OPCODE_SBC 6
2109 #define OPCODE_RSC 7
2110 #define OPCODE_TST 8
2111 #define OPCODE_TEQ 9
2112 #define OPCODE_CMP 10
2113 #define OPCODE_CMN 11
2114 #define OPCODE_ORR 12
2115 #define OPCODE_MOV 13
2116 #define OPCODE_BIC 14
2117 #define OPCODE_MVN 15
2119 /* Thumb v1 (ARMv4T). */
2120 static void do_t_nop PARAMS ((char *));
2121 static void do_t_arit PARAMS ((char *));
2122 static void do_t_add PARAMS ((char *));
2123 static void do_t_asr PARAMS ((char *));
2124 static void do_t_branch9 PARAMS ((char *));
2125 static void do_t_branch12 PARAMS ((char *));
2126 static void do_t_branch23 PARAMS ((char *));
2127 static void do_t_bx PARAMS ((char *));
2128 static void do_t_compare PARAMS ((char *));
2129 static void do_t_ldmstm PARAMS ((char *));
2130 static void do_t_ldr PARAMS ((char *));
2131 static void do_t_ldrb PARAMS ((char *));
2132 static void do_t_ldrh PARAMS ((char *));
2133 static void do_t_lds PARAMS ((char *));
2134 static void do_t_lsl PARAMS ((char *));
2135 static void do_t_lsr PARAMS ((char *));
2136 static void do_t_mov PARAMS ((char *));
2137 static void do_t_push_pop PARAMS ((char *));
2138 static void do_t_str PARAMS ((char *));
2139 static void do_t_strb PARAMS ((char *));
2140 static void do_t_strh PARAMS ((char *));
2141 static void do_t_sub PARAMS ((char *));
2142 static void do_t_swi PARAMS ((char *));
2143 static void do_t_adr PARAMS ((char *));
2145 /* Thumb v2 (ARMv5T). */
2146 static void do_t_blx PARAMS ((char *));
2147 static void do_t_bkpt PARAMS ((char *));
2149 #define T_OPCODE_MUL 0x4340
2150 #define T_OPCODE_TST 0x4200
2151 #define T_OPCODE_CMN 0x42c0
2152 #define T_OPCODE_NEG 0x4240
2153 #define T_OPCODE_MVN 0x43c0
2155 #define T_OPCODE_ADD_R3 0x1800
2156 #define T_OPCODE_SUB_R3 0x1a00
2157 #define T_OPCODE_ADD_HI 0x4400
2158 #define T_OPCODE_ADD_ST 0xb000
2159 #define T_OPCODE_SUB_ST 0xb080
2160 #define T_OPCODE_ADD_SP 0xa800
2161 #define T_OPCODE_ADD_PC 0xa000
2162 #define T_OPCODE_ADD_I8 0x3000
2163 #define T_OPCODE_SUB_I8 0x3800
2164 #define T_OPCODE_ADD_I3 0x1c00
2165 #define T_OPCODE_SUB_I3 0x1e00
2167 #define T_OPCODE_ASR_R 0x4100
2168 #define T_OPCODE_LSL_R 0x4080
2169 #define T_OPCODE_LSR_R 0x40c0
2170 #define T_OPCODE_ASR_I 0x1000
2171 #define T_OPCODE_LSL_I 0x0000
2172 #define T_OPCODE_LSR_I 0x0800
2174 #define T_OPCODE_MOV_I8 0x2000
2175 #define T_OPCODE_CMP_I8 0x2800
2176 #define T_OPCODE_CMP_LR 0x4280
2177 #define T_OPCODE_MOV_HR 0x4600
2178 #define T_OPCODE_CMP_HR 0x4500
2180 #define T_OPCODE_LDR_PC 0x4800
2181 #define T_OPCODE_LDR_SP 0x9800
2182 #define T_OPCODE_STR_SP 0x9000
2183 #define T_OPCODE_LDR_IW 0x6800
2184 #define T_OPCODE_STR_IW 0x6000
2185 #define T_OPCODE_LDR_IH 0x8800
2186 #define T_OPCODE_STR_IH 0x8000
2187 #define T_OPCODE_LDR_IB 0x7800
2188 #define T_OPCODE_STR_IB 0x7000
2189 #define T_OPCODE_LDR_RW 0x5800
2190 #define T_OPCODE_STR_RW 0x5000
2191 #define T_OPCODE_LDR_RH 0x5a00
2192 #define T_OPCODE_STR_RH 0x5200
2193 #define T_OPCODE_LDR_RB 0x5c00
2194 #define T_OPCODE_STR_RB 0x5400
2196 #define T_OPCODE_PUSH 0xb400
2197 #define T_OPCODE_POP 0xbc00
2199 #define T_OPCODE_BRANCH 0xe7fe
2201 static int thumb_reg PARAMS ((char ** str, int hi_lo));
2203 #define THUMB_SIZE 2 /* Size of thumb instruction. */
2204 #define THUMB_REG_LO 0x1
2205 #define THUMB_REG_HI 0x2
2206 #define THUMB_REG_ANY 0x3
2208 #define THUMB_H1 0x0080
2209 #define THUMB_H2 0x0040
2211 #define THUMB_ASR 0
2212 #define THUMB_LSL 1
2213 #define THUMB_LSR 2
2215 #define THUMB_MOVE 0
2216 #define THUMB_COMPARE 1
2218 #define THUMB_LOAD 0
2219 #define THUMB_STORE 1
2221 #define THUMB_PP_PC_LR 0x0100
2223 /* These three are used for immediate shifts, do not alter. */
2224 #define THUMB_WORD 2
2225 #define THUMB_HALFWORD 1
2226 #define THUMB_BYTE 0
2228 struct thumb_opcode
2230 /* Basic string to match. */
2231 const char * template;
2233 /* Basic instruction code. */
2234 unsigned long value;
2236 int size;
2238 /* Which CPU variants this exists for. */
2239 unsigned long variant;
2241 /* Function to call to parse args. */
2242 void (* parms) PARAMS ((char *));
2245 static const struct thumb_opcode tinsns[] =
2247 /* Thumb v1 (ARMv4T). */
2248 {"adc", 0x4140, 2, ARM_EXT_V4T, do_t_arit},
2249 {"add", 0x0000, 2, ARM_EXT_V4T, do_t_add},
2250 {"and", 0x4000, 2, ARM_EXT_V4T, do_t_arit},
2251 {"asr", 0x0000, 2, ARM_EXT_V4T, do_t_asr},
2252 {"b", T_OPCODE_BRANCH, 2, ARM_EXT_V4T, do_t_branch12},
2253 {"beq", 0xd0fe, 2, ARM_EXT_V4T, do_t_branch9},
2254 {"bne", 0xd1fe, 2, ARM_EXT_V4T, do_t_branch9},
2255 {"bcs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
2256 {"bhs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
2257 {"bcc", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
2258 {"bul", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
2259 {"blo", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
2260 {"bmi", 0xd4fe, 2, ARM_EXT_V4T, do_t_branch9},
2261 {"bpl", 0xd5fe, 2, ARM_EXT_V4T, do_t_branch9},
2262 {"bvs", 0xd6fe, 2, ARM_EXT_V4T, do_t_branch9},
2263 {"bvc", 0xd7fe, 2, ARM_EXT_V4T, do_t_branch9},
2264 {"bhi", 0xd8fe, 2, ARM_EXT_V4T, do_t_branch9},
2265 {"bls", 0xd9fe, 2, ARM_EXT_V4T, do_t_branch9},
2266 {"bge", 0xdafe, 2, ARM_EXT_V4T, do_t_branch9},
2267 {"blt", 0xdbfe, 2, ARM_EXT_V4T, do_t_branch9},
2268 {"bgt", 0xdcfe, 2, ARM_EXT_V4T, do_t_branch9},
2269 {"ble", 0xddfe, 2, ARM_EXT_V4T, do_t_branch9},
2270 {"bal", 0xdefe, 2, ARM_EXT_V4T, do_t_branch9},
2271 {"bic", 0x4380, 2, ARM_EXT_V4T, do_t_arit},
2272 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T, do_t_branch23},
2273 {"bx", 0x4700, 2, ARM_EXT_V4T, do_t_bx},
2274 {"cmn", T_OPCODE_CMN, 2, ARM_EXT_V4T, do_t_arit},
2275 {"cmp", 0x0000, 2, ARM_EXT_V4T, do_t_compare},
2276 {"eor", 0x4040, 2, ARM_EXT_V4T, do_t_arit},
2277 {"ldmia", 0xc800, 2, ARM_EXT_V4T, do_t_ldmstm},
2278 {"ldr", 0x0000, 2, ARM_EXT_V4T, do_t_ldr},
2279 {"ldrb", 0x0000, 2, ARM_EXT_V4T, do_t_ldrb},
2280 {"ldrh", 0x0000, 2, ARM_EXT_V4T, do_t_ldrh},
2281 {"ldrsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
2282 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
2283 {"ldsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
2284 {"ldsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
2285 {"lsl", 0x0000, 2, ARM_EXT_V4T, do_t_lsl},
2286 {"lsr", 0x0000, 2, ARM_EXT_V4T, do_t_lsr},
2287 {"mov", 0x0000, 2, ARM_EXT_V4T, do_t_mov},
2288 {"mul", T_OPCODE_MUL, 2, ARM_EXT_V4T, do_t_arit},
2289 {"mvn", T_OPCODE_MVN, 2, ARM_EXT_V4T, do_t_arit},
2290 {"neg", T_OPCODE_NEG, 2, ARM_EXT_V4T, do_t_arit},
2291 {"orr", 0x4300, 2, ARM_EXT_V4T, do_t_arit},
2292 {"pop", 0xbc00, 2, ARM_EXT_V4T, do_t_push_pop},
2293 {"push", 0xb400, 2, ARM_EXT_V4T, do_t_push_pop},
2294 {"ror", 0x41c0, 2, ARM_EXT_V4T, do_t_arit},
2295 {"sbc", 0x4180, 2, ARM_EXT_V4T, do_t_arit},
2296 {"stmia", 0xc000, 2, ARM_EXT_V4T, do_t_ldmstm},
2297 {"str", 0x0000, 2, ARM_EXT_V4T, do_t_str},
2298 {"strb", 0x0000, 2, ARM_EXT_V4T, do_t_strb},
2299 {"strh", 0x0000, 2, ARM_EXT_V4T, do_t_strh},
2300 {"swi", 0xdf00, 2, ARM_EXT_V4T, do_t_swi},
2301 {"sub", 0x0000, 2, ARM_EXT_V4T, do_t_sub},
2302 {"tst", T_OPCODE_TST, 2, ARM_EXT_V4T, do_t_arit},
2303 /* Pseudo ops: */
2304 {"adr", 0x0000, 2, ARM_EXT_V4T, do_t_adr},
2305 {"nop", 0x46C0, 2, ARM_EXT_V4T, do_t_nop}, /* mov r8,r8 */
2306 /* Thumb v2 (ARMv5T). */
2307 {"blx", 0, 0, ARM_EXT_V5T, do_t_blx},
2308 {"bkpt", 0xbe00, 2, ARM_EXT_V5T, do_t_bkpt},
2311 #define BAD_ARGS _("bad arguments to instruction")
2312 #define BAD_PC _("r15 not allowed here")
2313 #define BAD_COND _("instruction is not conditional")
2314 #define ERR_NO_ACCUM _("acc0 expected")
2316 static struct hash_control * arm_ops_hsh = NULL;
2317 static struct hash_control * arm_tops_hsh = NULL;
2318 static struct hash_control * arm_cond_hsh = NULL;
2319 static struct hash_control * arm_shift_hsh = NULL;
2320 static struct hash_control * arm_psr_hsh = NULL;
2322 /* This table describes all the machine specific pseudo-ops the assembler
2323 has to support. The fields are:
2324 pseudo-op name without dot
2325 function to call to execute this pseudo-op
2326 Integer arg to pass to the function. */
2328 static void s_req PARAMS ((int));
2329 static void s_unreq PARAMS ((int));
2330 static void s_align PARAMS ((int));
2331 static void s_bss PARAMS ((int));
2332 static void s_even PARAMS ((int));
2333 static void s_ltorg PARAMS ((int));
2334 static void s_arm PARAMS ((int));
2335 static void s_thumb PARAMS ((int));
2336 static void s_code PARAMS ((int));
2337 static void s_force_thumb PARAMS ((int));
2338 static void s_thumb_func PARAMS ((int));
2339 static void s_thumb_set PARAMS ((int));
2340 #ifdef OBJ_ELF
2341 static void s_arm_elf_cons PARAMS ((int));
2342 #endif
2344 static int my_get_expression PARAMS ((expressionS *, char **));
2346 const pseudo_typeS md_pseudo_table[] =
2348 /* Never called because '.req' does not start a line. */
2349 { "req", s_req, 0 },
2350 { "unreq", s_unreq, 0 },
2351 { "bss", s_bss, 0 },
2352 { "align", s_align, 0 },
2353 { "arm", s_arm, 0 },
2354 { "thumb", s_thumb, 0 },
2355 { "code", s_code, 0 },
2356 { "force_thumb", s_force_thumb, 0 },
2357 { "thumb_func", s_thumb_func, 0 },
2358 { "thumb_set", s_thumb_set, 0 },
2359 { "even", s_even, 0 },
2360 { "ltorg", s_ltorg, 0 },
2361 { "pool", s_ltorg, 0 },
2362 #ifdef OBJ_ELF
2363 { "word", s_arm_elf_cons, 4 },
2364 { "long", s_arm_elf_cons, 4 },
2365 #else
2366 { "word", cons, 4},
2367 #endif
2368 { "extend", float_cons, 'x' },
2369 { "ldouble", float_cons, 'x' },
2370 { "packed", float_cons, 'p' },
2371 { 0, 0, 0 }
2374 /* Other internal functions. */
2375 static int arm_parse_extension PARAMS ((char *, int *));
2376 static int arm_parse_cpu PARAMS ((char *));
2377 static int arm_parse_arch PARAMS ((char *));
2378 static int arm_parse_fpu PARAMS ((char *));
2379 #if 0 /* Suppressed - for now. */
2380 #if defined OBJ_COFF || defined OBJ_ELF
2381 static void arm_add_note PARAMS ((const char *, const char *, unsigned int));
2382 #endif
2383 #endif
2385 /* Stuff needed to resolve the label ambiguity
2388 label: <insn>
2389 may differ from:
2391 label:
2392 <insn>
2395 symbolS * last_label_seen;
2396 static int label_is_thumb_function_name = FALSE;
2398 /* Literal Pool stuff. */
2400 #define MAX_LITERAL_POOL_SIZE 1024
2402 /* Literal pool structure. Held on a per-section
2403 and per-sub-section basis. */
2404 typedef struct literal_pool
2406 expressionS literals [MAX_LITERAL_POOL_SIZE];
2407 unsigned int next_free_entry;
2408 unsigned int id;
2409 symbolS * symbol;
2410 segT section;
2411 subsegT sub_section;
2412 struct literal_pool * next;
2413 } literal_pool;
2415 /* Pointer to a linked list of literal pools. */
2416 literal_pool * list_of_pools = NULL;
2418 static literal_pool * find_literal_pool PARAMS ((void));
2419 static literal_pool * find_or_make_literal_pool PARAMS ((void));
2421 static literal_pool *
2422 find_literal_pool ()
2424 literal_pool * pool;
2426 for (pool = list_of_pools; pool != NULL; pool = pool->next)
2428 if (pool->section == now_seg
2429 && pool->sub_section == now_subseg)
2430 break;
2433 return pool;
2436 static literal_pool *
2437 find_or_make_literal_pool ()
2439 /* Next literal pool ID number. */
2440 static unsigned int latest_pool_num = 1;
2441 literal_pool * pool;
2443 pool = find_literal_pool ();
2445 if (pool == NULL)
2447 /* Create a new pool. */
2448 pool = (literal_pool *) xmalloc (sizeof (* pool));
2449 if (! pool)
2450 return NULL;
2452 pool->next_free_entry = 0;
2453 pool->section = now_seg;
2454 pool->sub_section = now_subseg;
2455 pool->next = list_of_pools;
2456 pool->symbol = NULL;
2458 /* Add it to the list. */
2459 list_of_pools = pool;
2462 /* New pools, and emptied pools, will have a NULL symbol. */
2463 if (pool->symbol == NULL)
2465 pool->symbol = symbol_create (FAKE_LABEL_NAME, undefined_section,
2466 (valueT) 0, &zero_address_frag);
2467 pool->id = latest_pool_num ++;
2470 /* Done. */
2471 return pool;
2474 /* Add the literal in the global 'inst'
2475 structure to the relevent literal pool. */
2476 static int
2477 add_to_lit_pool ()
2479 literal_pool * pool;
2480 unsigned int entry;
2482 pool = find_or_make_literal_pool ();
2484 /* Check if this literal value is already in the pool. */
2485 for (entry = 0; entry < pool->next_free_entry; entry ++)
2487 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
2488 && (inst.reloc.exp.X_op == O_constant)
2489 && (pool->literals[entry].X_add_number
2490 == inst.reloc.exp.X_add_number)
2491 && (pool->literals[entry].X_unsigned
2492 == inst.reloc.exp.X_unsigned))
2493 break;
2495 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
2496 && (inst.reloc.exp.X_op == O_symbol)
2497 && (pool->literals[entry].X_add_number
2498 == inst.reloc.exp.X_add_number)
2499 && (pool->literals[entry].X_add_symbol
2500 == inst.reloc.exp.X_add_symbol)
2501 && (pool->literals[entry].X_op_symbol
2502 == inst.reloc.exp.X_op_symbol))
2503 break;
2506 /* Do we need to create a new entry? */
2507 if (entry == pool->next_free_entry)
2509 if (entry >= MAX_LITERAL_POOL_SIZE)
2511 inst.error = _("literal pool overflow");
2512 return FAIL;
2515 pool->literals[entry] = inst.reloc.exp;
2516 pool->next_free_entry += 1;
2519 inst.reloc.exp.X_op = O_symbol;
2520 inst.reloc.exp.X_add_number = ((int) entry) * 4 - 8;
2521 inst.reloc.exp.X_add_symbol = pool->symbol;
2523 return SUCCESS;
2526 /* Can't use symbol_new here, so have to create a symbol and then at
2527 a later date assign it a value. Thats what these functions do. */
2529 static void
2530 symbol_locate (symbolP, name, segment, valu, frag)
2531 symbolS * symbolP;
2532 const char * name; /* It is copied, the caller can modify. */
2533 segT segment; /* Segment identifier (SEG_<something>). */
2534 valueT valu; /* Symbol value. */
2535 fragS * frag; /* Associated fragment. */
2537 unsigned int name_length;
2538 char * preserved_copy_of_name;
2540 name_length = strlen (name) + 1; /* +1 for \0. */
2541 obstack_grow (&notes, name, name_length);
2542 preserved_copy_of_name = obstack_finish (&notes);
2543 #ifdef STRIP_UNDERSCORE
2544 if (preserved_copy_of_name[0] == '_')
2545 preserved_copy_of_name++;
2546 #endif
2548 #ifdef tc_canonicalize_symbol_name
2549 preserved_copy_of_name =
2550 tc_canonicalize_symbol_name (preserved_copy_of_name);
2551 #endif
2553 S_SET_NAME (symbolP, preserved_copy_of_name);
2555 S_SET_SEGMENT (symbolP, segment);
2556 S_SET_VALUE (symbolP, valu);
2557 symbol_clear_list_pointers (symbolP);
2559 symbol_set_frag (symbolP, frag);
2561 /* Link to end of symbol chain. */
2563 extern int symbol_table_frozen;
2564 if (symbol_table_frozen)
2565 abort ();
2568 symbol_append (symbolP, symbol_lastP, & symbol_rootP, & symbol_lastP);
2570 obj_symbol_new_hook (symbolP);
2572 #ifdef tc_symbol_new_hook
2573 tc_symbol_new_hook (symbolP);
2574 #endif
2576 #ifdef DEBUG_SYMS
2577 verify_symbol_chain (symbol_rootP, symbol_lastP);
2578 #endif /* DEBUG_SYMS */
2581 /* Check that an immediate is valid.
2582 If so, convert it to the right format. */
2584 static unsigned int
2585 validate_immediate (val)
2586 unsigned int val;
2588 unsigned int a;
2589 unsigned int i;
2591 #define rotate_left(v, n) (v << n | v >> (32 - n))
2593 for (i = 0; i < 32; i += 2)
2594 if ((a = rotate_left (val, i)) <= 0xff)
2595 return a | (i << 7); /* 12-bit pack: [shift-cnt,const]. */
2597 return FAIL;
2600 /* Check to see if an immediate can be computed as two seperate immediate
2601 values, added together. We already know that this value cannot be
2602 computed by just one ARM instruction. */
2604 static unsigned int
2605 validate_immediate_twopart (val, highpart)
2606 unsigned int val;
2607 unsigned int * highpart;
2609 unsigned int a;
2610 unsigned int i;
2612 for (i = 0; i < 32; i += 2)
2613 if (((a = rotate_left (val, i)) & 0xff) != 0)
2615 if (a & 0xff00)
2617 if (a & ~ 0xffff)
2618 continue;
2619 * highpart = (a >> 8) | ((i + 24) << 7);
2621 else if (a & 0xff0000)
2623 if (a & 0xff000000)
2624 continue;
2625 * highpart = (a >> 16) | ((i + 16) << 7);
2627 else
2629 assert (a & 0xff000000);
2630 * highpart = (a >> 24) | ((i + 8) << 7);
2633 return (a & 0xff) | (i << 7);
2636 return FAIL;
2639 static int
2640 validate_offset_imm (val, hwse)
2641 unsigned int val;
2642 int hwse;
2644 if ((hwse && val > 255) || val > 4095)
2645 return FAIL;
2646 return val;
2650 #ifdef OBJ_ELF
2651 enum mstate
2653 MAP_DATA,
2654 MAP_ARM,
2655 MAP_THUMB
2658 /* This code is to handle mapping symbols as defined in the ARM ELF spec.
2659 (This text is taken from version B-02 of the spec):
2661 4.4.7 Mapping and tagging symbols
2663 A section of an ARM ELF file can contain a mixture of ARM code,
2664 Thumb code, and data. There are inline transitions between code
2665 and data at literal pool boundaries. There can also be inline
2666 transitions between ARM code and Thumb code, for example in
2667 ARM-Thumb inter-working veneers. Linkers, machine-level
2668 debuggers, profiling tools, and disassembly tools need to map
2669 images accurately. For example, setting an ARM breakpoint on a
2670 Thumb location, or in a literal pool, can crash the program
2671 being debugged, ruining the debugging session.
2673 ARM ELF entities are mapped (see section 4.4.7.1 below) and
2674 tagged (see section 4.4.7.2 below) using local symbols (with
2675 binding STB_LOCAL). To assist consumers, mapping and tagging
2676 symbols should be collated first in the symbol table, before
2677 other symbols with binding STB_LOCAL.
2679 To allow properly collated mapping and tagging symbols to be
2680 skipped by consumers that have no interest in them, the first
2681 such symbol should have the name $m and its st_value field equal
2682 to the total number of mapping and tagging symbols (including
2683 the $m) in the symbol table.
2685 4.4.7.1 Mapping symbols
2687 $a Labels the first byte of a sequence of ARM instructions.
2688 Its type is STT_FUNC.
2690 $d Labels the first byte of a sequence of data items.
2691 Its type is STT_OBJECT.
2693 $t Labels the first byte of a sequence of Thumb instructions.
2694 Its type is STT_FUNC.
2696 This list of mapping symbols may be extended in the future.
2698 Section-relative mapping symbols
2700 Mapping symbols defined in a section define a sequence of
2701 half-open address intervals that cover the address range of the
2702 section. Each interval starts at the address defined by a
2703 mapping symbol, and continues up to, but not including, the
2704 address defined by the next (in address order) mapping symbol or
2705 the end of the section. A corollary is that there must be a
2706 mapping symbol defined at the beginning of each section.
2707 Consumers can ignore the size of a section-relative mapping
2708 symbol. Producers can set it to 0.
2710 Absolute mapping symbols
2712 Because of the need to crystallize a Thumb address with the
2713 Thumb-bit set, absolute symbol of type STT_FUNC (symbols of type
2714 STT_FUNC defined in section SHN_ABS) need to be mapped with $a
2715 or $t.
2717 The extent of a mapping symbol defined in SHN_ABS is [st_value,
2718 st_value + st_size), or [st_value, st_value + 1) if st_size = 0,
2719 where [x, y) denotes the half-open address range from x,
2720 inclusive, to y, exclusive.
2722 In the absence of a mapping symbol, a consumer can interpret a
2723 function symbol with an odd value as the Thumb code address
2724 obtained by clearing the least significant bit of the
2725 value. This interpretation is deprecated, and it may not work in
2726 the future.
2728 Note - the Tagging symbols ($b, $f, $p $m) have been dropped from
2729 the EABI (which is still under development), so they are not
2730 implemented here. */
2732 static void
2733 mapping_state (enum mstate state)
2735 static enum mstate mapstate = MAP_DATA;
2736 symbolS * symbolP;
2737 const char * symname;
2738 int type;
2740 if (mapstate == state)
2741 /* The mapping symbol has already been emitted.
2742 There is nothing else to do. */
2743 return;
2745 mapstate = state;
2747 switch (state)
2749 case MAP_DATA:
2750 symname = "$d";
2751 type = BSF_OBJECT;
2752 break;
2753 case MAP_ARM:
2754 symname = "$a";
2755 type = BSF_FUNCTION;
2756 break;
2757 case MAP_THUMB:
2758 symname = "$t";
2759 type = BSF_FUNCTION;
2760 break;
2761 default:
2762 abort ();
2765 symbolP = symbol_new (symname, now_seg, (valueT) frag_now_fix (), frag_now);
2766 symbol_table_insert (symbolP);
2767 symbol_get_bfdsym (symbolP)->flags |= type | BSF_LOCAL;
2769 switch (state)
2771 case MAP_ARM:
2772 THUMB_SET_FUNC (symbolP, 0);
2773 ARM_SET_THUMB (symbolP, 0);
2774 ARM_SET_INTERWORK (symbolP, support_interwork);
2775 break;
2777 case MAP_THUMB:
2778 THUMB_SET_FUNC (symbolP, 1);
2779 ARM_SET_THUMB (symbolP, 1);
2780 ARM_SET_INTERWORK (symbolP, support_interwork);
2781 break;
2783 case MAP_DATA:
2784 default:
2785 return;
2789 /* When we change sections we need to issue a new mapping symbol. */
2791 void
2792 arm_elf_change_section (void)
2794 flagword flags;
2796 if (!SEG_NORMAL (now_seg))
2797 return;
2799 flags = bfd_get_section_flags (stdoutput, now_seg);
2801 /* We can ignore sections that only contain debug info. */
2802 if ((flags & SEC_ALLOC) == 0)
2803 return;
2805 if (flags & SEC_CODE)
2807 if (thumb_mode)
2808 mapping_state (MAP_THUMB);
2809 else
2810 mapping_state (MAP_ARM);
2812 else
2813 /* This section does not contain code. Therefore it must contain data. */
2814 mapping_state (MAP_DATA);
2816 #else
2817 #define mapping_state(a)
2818 #endif /* OBJ_ELF */
2821 static void
2822 s_req (a)
2823 int a ATTRIBUTE_UNUSED;
2825 as_bad (_("invalid syntax for .req directive"));
2828 /* The .unreq directive deletes an alias which was previously defined
2829 by .req. For example:
2831 my_alias .req r11
2832 .unreq my_alias */
2834 static void
2835 s_unreq (int a ATTRIBUTE_UNUSED)
2837 char *name;
2838 char saved_char;
2840 skip_whitespace (input_line_pointer);
2841 name = input_line_pointer;
2843 while (*input_line_pointer != 0
2844 && *input_line_pointer != ' '
2845 && *input_line_pointer != '\n')
2846 ++input_line_pointer;
2848 saved_char = *input_line_pointer;
2849 *input_line_pointer = 0;
2851 if (*name)
2853 enum arm_reg_type req_type = arm_reg_parse_any (name);
2855 if (req_type != REG_TYPE_MAX)
2857 char *temp_name = name;
2858 int req_no = arm_reg_parse (&temp_name, all_reg_maps[req_type].htab);
2860 if (req_no != FAIL)
2862 struct reg_entry *req_entry;
2864 /* Check to see if this alias is a builtin one. */
2865 req_entry = hash_delete (all_reg_maps[req_type].htab, name);
2867 if (!req_entry)
2868 as_bad (_("unreq: missing hash entry for \"%s\""), name);
2869 else if (req_entry->builtin)
2870 /* FIXME: We are deleteing a built in register alias which
2871 points to a const data structure, so we only need to
2872 free up the memory used by the key in the hash table.
2873 Unfortunately we have not recorded this value, so this
2874 is a memory leak. */
2875 /* FIXME: Should we issue a warning message ? */
2877 else
2879 /* Deleteing a user defined alias. We need to free the
2880 key and the value, but fortunately the key is the same
2881 as the value->name field. */
2882 free ((char *) req_entry->name);
2883 free (req_entry);
2886 else
2887 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
2889 else
2890 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
2892 else
2893 as_bad (_("invalid syntax for .unreq directive"));
2895 *input_line_pointer = saved_char;
2896 demand_empty_rest_of_line ();
2899 static void
2900 s_bss (ignore)
2901 int ignore ATTRIBUTE_UNUSED;
2903 /* We don't support putting frags in the BSS segment, we fake it by
2904 marking in_bss, then looking at s_skip for clues. */
2905 subseg_set (bss_section, 0);
2906 demand_empty_rest_of_line ();
2907 mapping_state (MAP_DATA);
2910 static void
2911 s_even (ignore)
2912 int ignore ATTRIBUTE_UNUSED;
2914 /* Never make frag if expect extra pass. */
2915 if (!need_pass_2)
2916 frag_align (1, 0, 0);
2918 record_alignment (now_seg, 1);
2920 demand_empty_rest_of_line ();
2923 static void
2924 s_ltorg (ignored)
2925 int ignored ATTRIBUTE_UNUSED;
2927 unsigned int entry;
2928 literal_pool * pool;
2929 char sym_name[20];
2931 pool = find_literal_pool ();
2932 if (pool == NULL
2933 || pool->symbol == NULL
2934 || pool->next_free_entry == 0)
2935 return;
2937 /* Align pool as you have word accesses.
2938 Only make a frag if we have to. */
2939 if (!need_pass_2)
2940 frag_align (2, 0, 0);
2942 record_alignment (now_seg, 2);
2944 sprintf (sym_name, "$$lit_\002%x", pool->id);
2946 symbol_locate (pool->symbol, sym_name, now_seg,
2947 (valueT) frag_now_fix (), frag_now);
2948 symbol_table_insert (pool->symbol);
2950 ARM_SET_THUMB (pool->symbol, thumb_mode);
2952 #if defined OBJ_COFF || defined OBJ_ELF
2953 ARM_SET_INTERWORK (pool->symbol, support_interwork);
2954 #endif
2956 for (entry = 0; entry < pool->next_free_entry; entry ++)
2957 /* First output the expression in the instruction to the pool. */
2958 emit_expr (&(pool->literals[entry]), 4); /* .word */
2960 /* Mark the pool as empty. */
2961 pool->next_free_entry = 0;
2962 pool->symbol = NULL;
2965 /* Same as s_align_ptwo but align 0 => align 2. */
2967 static void
2968 s_align (unused)
2969 int unused ATTRIBUTE_UNUSED;
2971 register int temp;
2972 register long temp_fill;
2973 long max_alignment = 15;
2975 temp = get_absolute_expression ();
2976 if (temp > max_alignment)
2977 as_bad (_("alignment too large: %d assumed"), temp = max_alignment);
2978 else if (temp < 0)
2980 as_bad (_("alignment negative. 0 assumed."));
2981 temp = 0;
2984 if (*input_line_pointer == ',')
2986 input_line_pointer++;
2987 temp_fill = get_absolute_expression ();
2989 else
2990 temp_fill = 0;
2992 if (!temp)
2993 temp = 2;
2995 /* Only make a frag if we HAVE to. */
2996 if (temp && !need_pass_2)
2997 frag_align (temp, (int) temp_fill, 0);
2998 demand_empty_rest_of_line ();
3000 record_alignment (now_seg, temp);
3003 static void
3004 s_force_thumb (ignore)
3005 int ignore ATTRIBUTE_UNUSED;
3007 /* If we are not already in thumb mode go into it, EVEN if
3008 the target processor does not support thumb instructions.
3009 This is used by gcc/config/arm/lib1funcs.asm for example
3010 to compile interworking support functions even if the
3011 target processor should not support interworking. */
3012 if (! thumb_mode)
3014 thumb_mode = 2;
3016 record_alignment (now_seg, 1);
3019 demand_empty_rest_of_line ();
3022 static void
3023 s_thumb_func (ignore)
3024 int ignore ATTRIBUTE_UNUSED;
3026 if (! thumb_mode)
3027 opcode_select (16);
3029 /* The following label is the name/address of the start of a Thumb function.
3030 We need to know this for the interworking support. */
3031 label_is_thumb_function_name = TRUE;
3033 demand_empty_rest_of_line ();
3036 /* Perform a .set directive, but also mark the alias as
3037 being a thumb function. */
3039 static void
3040 s_thumb_set (equiv)
3041 int equiv;
3043 /* XXX the following is a duplicate of the code for s_set() in read.c
3044 We cannot just call that code as we need to get at the symbol that
3045 is created. */
3046 register char * name;
3047 register char delim;
3048 register char * end_name;
3049 register symbolS * symbolP;
3051 /* Especial apologies for the random logic:
3052 This just grew, and could be parsed much more simply!
3053 Dean - in haste. */
3054 name = input_line_pointer;
3055 delim = get_symbol_end ();
3056 end_name = input_line_pointer;
3057 *end_name = delim;
3059 SKIP_WHITESPACE ();
3061 if (*input_line_pointer != ',')
3063 *end_name = 0;
3064 as_bad (_("expected comma after name \"%s\""), name);
3065 *end_name = delim;
3066 ignore_rest_of_line ();
3067 return;
3070 input_line_pointer++;
3071 *end_name = 0;
3073 if (name[0] == '.' && name[1] == '\0')
3075 /* XXX - this should not happen to .thumb_set. */
3076 abort ();
3079 if ((symbolP = symbol_find (name)) == NULL
3080 && (symbolP = md_undefined_symbol (name)) == NULL)
3082 #ifndef NO_LISTING
3083 /* When doing symbol listings, play games with dummy fragments living
3084 outside the normal fragment chain to record the file and line info
3085 for this symbol. */
3086 if (listing & LISTING_SYMBOLS)
3088 extern struct list_info_struct * listing_tail;
3089 fragS * dummy_frag = (fragS *) xmalloc (sizeof (fragS));
3091 memset (dummy_frag, 0, sizeof (fragS));
3092 dummy_frag->fr_type = rs_fill;
3093 dummy_frag->line = listing_tail;
3094 symbolP = symbol_new (name, undefined_section, 0, dummy_frag);
3095 dummy_frag->fr_symbol = symbolP;
3097 else
3098 #endif
3099 symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
3101 #ifdef OBJ_COFF
3102 /* "set" symbols are local unless otherwise specified. */
3103 SF_SET_LOCAL (symbolP);
3104 #endif /* OBJ_COFF */
3105 } /* Make a new symbol. */
3107 symbol_table_insert (symbolP);
3109 * end_name = delim;
3111 if (equiv
3112 && S_IS_DEFINED (symbolP)
3113 && S_GET_SEGMENT (symbolP) != reg_section)
3114 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP));
3116 pseudo_set (symbolP);
3118 demand_empty_rest_of_line ();
3120 /* XXX Now we come to the Thumb specific bit of code. */
3122 THUMB_SET_FUNC (symbolP, 1);
3123 ARM_SET_THUMB (symbolP, 1);
3124 #if defined OBJ_ELF || defined OBJ_COFF
3125 ARM_SET_INTERWORK (symbolP, support_interwork);
3126 #endif
3129 static void
3130 opcode_select (width)
3131 int width;
3133 switch (width)
3135 case 16:
3136 if (! thumb_mode)
3138 if (! (cpu_variant & ARM_EXT_V4T))
3139 as_bad (_("selected processor does not support THUMB opcodes"));
3141 thumb_mode = 1;
3142 /* No need to force the alignment, since we will have been
3143 coming from ARM mode, which is word-aligned. */
3144 record_alignment (now_seg, 1);
3146 mapping_state (MAP_THUMB);
3147 break;
3149 case 32:
3150 if (thumb_mode)
3152 if ((cpu_variant & ARM_ALL) == ARM_EXT_V4T)
3153 as_bad (_("selected processor does not support ARM opcodes"));
3155 thumb_mode = 0;
3157 if (!need_pass_2)
3158 frag_align (2, 0, 0);
3160 record_alignment (now_seg, 1);
3162 mapping_state (MAP_ARM);
3163 break;
3165 default:
3166 as_bad (_("invalid instruction size selected (%d)"), width);
3170 static void
3171 s_arm (ignore)
3172 int ignore ATTRIBUTE_UNUSED;
3174 opcode_select (32);
3175 demand_empty_rest_of_line ();
3178 static void
3179 s_thumb (ignore)
3180 int ignore ATTRIBUTE_UNUSED;
3182 opcode_select (16);
3183 demand_empty_rest_of_line ();
3186 static void
3187 s_code (unused)
3188 int unused ATTRIBUTE_UNUSED;
3190 register int temp;
3192 temp = get_absolute_expression ();
3193 switch (temp)
3195 case 16:
3196 case 32:
3197 opcode_select (temp);
3198 break;
3200 default:
3201 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp);
3205 static void
3206 end_of_line (str)
3207 char *str;
3209 skip_whitespace (str);
3211 if (*str != '\0' && !inst.error)
3212 inst.error = _("garbage following instruction");
3215 static int
3216 skip_past_comma (str)
3217 char ** str;
3219 char * p = * str, c;
3220 int comma = 0;
3222 while ((c = *p) == ' ' || c == ',')
3224 p++;
3225 if (c == ',' && comma++)
3226 return FAIL;
3229 if (c == '\0')
3230 return FAIL;
3232 *str = p;
3233 return comma ? SUCCESS : FAIL;
3236 /* A standard register must be given at this point.
3237 SHIFT is the place to put it in inst.instruction.
3238 Restores input start point on error.
3239 Returns the reg#, or FAIL. */
3241 static int
3242 reg_required_here (str, shift)
3243 char ** str;
3244 int shift;
3246 static char buff [128]; /* XXX */
3247 int reg;
3248 char * start = * str;
3250 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_RN].htab)) != FAIL)
3252 if (shift >= 0)
3253 inst.instruction |= reg << shift;
3254 return reg;
3257 /* Restore the start point, we may have got a reg of the wrong class. */
3258 *str = start;
3260 /* In the few cases where we might be able to accept something else
3261 this error can be overridden. */
3262 sprintf (buff, _("register expected, not '%.100s'"), start);
3263 inst.error = buff;
3265 return FAIL;
3268 /* A Intel Wireless MMX technology register
3269 must be given at this point.
3270 Shift is the place to put it in inst.instruction.
3271 Restores input start point on err.
3272 Returns the reg#, or FAIL. */
3274 static int
3275 wreg_required_here (str, shift, reg_type)
3276 char ** str;
3277 int shift;
3278 enum wreg_type reg_type;
3280 static char buff [128];
3281 int reg;
3282 char * start = *str;
3284 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_IWMMXT].htab)) != FAIL)
3286 if (wr_register (reg)
3287 && (reg_type == IWMMXT_REG_WR || reg_type == IWMMXT_REG_WR_OR_WC))
3289 if (shift >= 0)
3290 inst.instruction |= (reg ^ WR_PREFIX) << shift;
3291 return reg;
3293 else if (wc_register (reg)
3294 && (reg_type == IWMMXT_REG_WC || reg_type == IWMMXT_REG_WR_OR_WC))
3296 if (shift >= 0)
3297 inst.instruction |= (reg ^ WC_PREFIX) << shift;
3298 return reg;
3300 else if ((wcg_register (reg) && reg_type == IWMMXT_REG_WCG))
3302 if (shift >= 0)
3303 inst.instruction |= ((reg ^ WC_PREFIX) - 8) << shift;
3304 return reg;
3308 /* Restore the start point, we may have got a reg of the wrong class. */
3309 *str = start;
3311 /* In the few cases where we might be able to accept
3312 something else this error can be overridden. */
3313 sprintf (buff, _("Intel Wireless MMX technology register expected, not '%.100s'"), start);
3314 inst.error = buff;
3316 return FAIL;
3319 static const struct asm_psr *
3320 arm_psr_parse (ccp)
3321 register char ** ccp;
3323 char * start = * ccp;
3324 char c;
3325 char * p;
3326 const struct asm_psr * psr;
3328 p = start;
3330 /* Skip to the end of the next word in the input stream. */
3333 c = *p++;
3335 while (ISALPHA (c) || c == '_');
3337 /* Terminate the word. */
3338 *--p = 0;
3340 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
3341 feature for ease of use and backwards compatibility. */
3342 if (!strncmp (start, "cpsr", 4))
3343 strncpy (start, "CPSR", 4);
3344 else if (!strncmp (start, "spsr", 4))
3345 strncpy (start, "SPSR", 4);
3347 /* Now locate the word in the psr hash table. */
3348 psr = (const struct asm_psr *) hash_find (arm_psr_hsh, start);
3350 /* Restore the input stream. */
3351 *p = c;
3353 /* If we found a valid match, advance the
3354 stream pointer past the end of the word. */
3355 *ccp = p;
3357 return psr;
3360 /* Parse the input looking for a PSR flag. */
3362 static int
3363 psr_required_here (str)
3364 char ** str;
3366 char * start = * str;
3367 const struct asm_psr * psr;
3369 psr = arm_psr_parse (str);
3371 if (psr)
3373 /* If this is the SPSR that is being modified, set the R bit. */
3374 if (! psr->cpsr)
3375 inst.instruction |= SPSR_BIT;
3377 /* Set the psr flags in the MSR instruction. */
3378 inst.instruction |= psr->field << PSR_SHIFT;
3380 return SUCCESS;
3383 /* In the few cases where we might be able to accept
3384 something else this error can be overridden. */
3385 inst.error = _("flag for {c}psr instruction expected");
3387 /* Restore the start point. */
3388 *str = start;
3389 return FAIL;
3392 static int
3393 co_proc_number (str)
3394 char **str;
3396 int processor, pchar;
3397 char *start;
3399 skip_whitespace (*str);
3400 start = *str;
3402 /* The data sheet seems to imply that just a number on its own is valid
3403 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
3404 accept either. */
3405 if ((processor = arm_reg_parse (str, all_reg_maps[REG_TYPE_CP].htab))
3406 == FAIL)
3408 *str = start;
3410 pchar = *(*str)++;
3411 if (pchar >= '0' && pchar <= '9')
3413 processor = pchar - '0';
3414 if (**str >= '0' && **str <= '9')
3416 processor = processor * 10 + *(*str)++ - '0';
3417 if (processor > 15)
3419 inst.error = _("illegal co-processor number");
3420 return FAIL;
3424 else
3426 inst.error = _("bad or missing co-processor number");
3427 return FAIL;
3431 inst.instruction |= processor << 8;
3432 return SUCCESS;
3435 static int
3436 cp_opc_expr (str, where, length)
3437 char ** str;
3438 int where;
3439 int length;
3441 expressionS expr;
3443 skip_whitespace (* str);
3445 memset (&expr, '\0', sizeof (expr));
3447 if (my_get_expression (&expr, str))
3448 return FAIL;
3449 if (expr.X_op != O_constant)
3451 inst.error = _("bad or missing expression");
3452 return FAIL;
3455 if ((expr.X_add_number & ((1 << length) - 1)) != expr.X_add_number)
3457 inst.error = _("immediate co-processor expression too large");
3458 return FAIL;
3461 inst.instruction |= expr.X_add_number << where;
3462 return SUCCESS;
3465 static int
3466 cp_reg_required_here (str, where)
3467 char ** str;
3468 int where;
3470 int reg;
3471 char * start = *str;
3473 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
3475 inst.instruction |= reg << where;
3476 return reg;
3479 /* In the few cases where we might be able to accept something else
3480 this error can be overridden. */
3481 inst.error = _("co-processor register expected");
3483 /* Restore the start point. */
3484 *str = start;
3485 return FAIL;
3488 static int
3489 fp_reg_required_here (str, where)
3490 char ** str;
3491 int where;
3493 int reg;
3494 char * start = * str;
3496 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_FN].htab)) != FAIL)
3498 inst.instruction |= reg << where;
3499 return reg;
3502 /* In the few cases where we might be able to accept something else
3503 this error can be overridden. */
3504 inst.error = _("floating point register expected");
3506 /* Restore the start point. */
3507 *str = start;
3508 return FAIL;
3511 static int
3512 cp_address_offset (str)
3513 char ** str;
3515 int offset;
3517 skip_whitespace (* str);
3519 if (! is_immediate_prefix (**str))
3521 inst.error = _("immediate expression expected");
3522 return FAIL;
3525 (*str)++;
3527 if (my_get_expression (& inst.reloc.exp, str))
3528 return FAIL;
3530 if (inst.reloc.exp.X_op == O_constant)
3532 offset = inst.reloc.exp.X_add_number;
3534 if (offset & 3)
3536 inst.error = _("co-processor address must be word aligned");
3537 return FAIL;
3540 if (offset > 1023 || offset < -1023)
3542 inst.error = _("offset too large");
3543 return FAIL;
3546 if (offset >= 0)
3547 inst.instruction |= INDEX_UP;
3548 else
3549 offset = -offset;
3551 inst.instruction |= offset >> 2;
3553 else
3554 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
3556 return SUCCESS;
3559 static int
3560 cp_address_required_here (str, wb_ok)
3561 char ** str;
3562 int wb_ok;
3564 char * p = * str;
3565 int pre_inc = 0;
3566 int write_back = 0;
3568 if (*p == '[')
3570 int reg;
3572 p++;
3573 skip_whitespace (p);
3575 if ((reg = reg_required_here (& p, 16)) == FAIL)
3576 return FAIL;
3578 skip_whitespace (p);
3580 if (*p == ']')
3582 p++;
3584 skip_whitespace (p);
3586 if (*p == '\0')
3588 /* As an extension to the official ARM syntax we allow:
3590 [Rn]
3592 as a short hand for:
3594 [Rn,#0] */
3595 inst.instruction |= PRE_INDEX | INDEX_UP;
3596 *str = p;
3597 return SUCCESS;
3600 if (skip_past_comma (& p) == FAIL)
3602 inst.error = _("comma expected after closing square bracket");
3603 return FAIL;
3606 skip_whitespace (p);
3608 if (*p == '#')
3610 if (wb_ok)
3612 /* [Rn], #expr */
3613 write_back = WRITE_BACK;
3615 if (reg == REG_PC)
3617 inst.error = _("pc may not be used in post-increment");
3618 return FAIL;
3621 if (cp_address_offset (& p) == FAIL)
3622 return FAIL;
3624 else
3625 pre_inc = PRE_INDEX | INDEX_UP;
3627 else if (*p == '{')
3629 int option;
3631 /* [Rn], {<expr>} */
3632 p++;
3634 skip_whitespace (p);
3636 if (my_get_expression (& inst.reloc.exp, & p))
3637 return FAIL;
3639 if (inst.reloc.exp.X_op == O_constant)
3641 option = inst.reloc.exp.X_add_number;
3643 if (option > 255 || option < 0)
3645 inst.error = _("'option' field too large");
3646 return FAIL;
3649 skip_whitespace (p);
3651 if (*p != '}')
3653 inst.error = _("'}' expected at end of 'option' field");
3654 return FAIL;
3656 else
3658 p++;
3659 inst.instruction |= option;
3660 inst.instruction |= INDEX_UP;
3663 else
3665 inst.error = _("non-constant expressions for 'option' field not supported");
3666 return FAIL;
3669 else
3671 inst.error = _("# or { expected after comma");
3672 return FAIL;
3675 else
3677 /* '['Rn, #expr']'[!] */
3679 if (skip_past_comma (& p) == FAIL)
3681 inst.error = _("pre-indexed expression expected");
3682 return FAIL;
3685 pre_inc = PRE_INDEX;
3687 if (cp_address_offset (& p) == FAIL)
3688 return FAIL;
3690 skip_whitespace (p);
3692 if (*p++ != ']')
3694 inst.error = _("missing ]");
3695 return FAIL;
3698 skip_whitespace (p);
3700 if (wb_ok && *p == '!')
3702 if (reg == REG_PC)
3704 inst.error = _("pc may not be used with write-back");
3705 return FAIL;
3708 p++;
3709 write_back = WRITE_BACK;
3713 else
3715 if (my_get_expression (&inst.reloc.exp, &p))
3716 return FAIL;
3718 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
3719 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
3720 inst.reloc.pc_rel = 1;
3721 inst.instruction |= (REG_PC << 16);
3722 pre_inc = PRE_INDEX;
3725 inst.instruction |= write_back | pre_inc;
3726 *str = p;
3727 return SUCCESS;
3730 static int
3731 cp_byte_address_offset (str)
3732 char ** str;
3734 int offset;
3736 skip_whitespace (* str);
3738 if (! is_immediate_prefix (**str))
3740 inst.error = _("immediate expression expected");
3741 return FAIL;
3744 (*str)++;
3746 if (my_get_expression (& inst.reloc.exp, str))
3747 return FAIL;
3749 if (inst.reloc.exp.X_op == O_constant)
3751 offset = inst.reloc.exp.X_add_number;
3753 if (offset > 255 || offset < -255)
3755 inst.error = _("offset too large");
3756 return FAIL;
3759 if (offset >= 0)
3760 inst.instruction |= INDEX_UP;
3761 else
3762 offset = -offset;
3764 inst.instruction |= offset;
3766 else
3767 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
3769 return SUCCESS;
3772 static int
3773 cp_byte_address_required_here (str)
3774 char ** str;
3776 char * p = * str;
3777 int pre_inc = 0;
3778 int write_back = 0;
3780 if (*p == '[')
3782 int reg;
3784 p++;
3785 skip_whitespace (p);
3787 if ((reg = reg_required_here (& p, 16)) == FAIL)
3788 return FAIL;
3790 skip_whitespace (p);
3792 if (*p == ']')
3794 p++;
3796 if (skip_past_comma (& p) == SUCCESS)
3798 /* [Rn], #expr */
3799 write_back = WRITE_BACK;
3801 if (reg == REG_PC)
3803 inst.error = _("pc may not be used in post-increment");
3804 return FAIL;
3807 if (cp_byte_address_offset (& p) == FAIL)
3808 return FAIL;
3810 else
3811 pre_inc = PRE_INDEX | INDEX_UP;
3813 else
3815 /* '['Rn, #expr']'[!] */
3817 if (skip_past_comma (& p) == FAIL)
3819 inst.error = _("pre-indexed expression expected");
3820 return FAIL;
3823 pre_inc = PRE_INDEX;
3825 if (cp_byte_address_offset (& p) == FAIL)
3826 return FAIL;
3828 skip_whitespace (p);
3830 if (*p++ != ']')
3832 inst.error = _("missing ]");
3833 return FAIL;
3836 skip_whitespace (p);
3838 if (*p == '!')
3840 if (reg == REG_PC)
3842 inst.error = _("pc may not be used with write-back");
3843 return FAIL;
3846 p++;
3847 write_back = WRITE_BACK;
3851 else
3853 if (my_get_expression (&inst.reloc.exp, &p))
3854 return FAIL;
3856 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
3857 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
3858 inst.reloc.pc_rel = 1;
3859 inst.instruction |= (REG_PC << 16);
3860 pre_inc = PRE_INDEX;
3863 inst.instruction |= write_back | pre_inc;
3864 *str = p;
3865 return SUCCESS;
3868 static void
3869 do_empty (str)
3870 char * str;
3872 /* Do nothing really. */
3873 end_of_line (str);
3874 return;
3877 static void
3878 do_mrs (str)
3879 char *str;
3881 int skip = 0;
3883 /* Only one syntax. */
3884 skip_whitespace (str);
3886 if (reg_required_here (&str, 12) == FAIL)
3888 inst.error = BAD_ARGS;
3889 return;
3892 if (skip_past_comma (&str) == FAIL)
3894 inst.error = _("comma expected after register name");
3895 return;
3898 skip_whitespace (str);
3900 if ( strcmp (str, "CPSR") == 0
3901 || strcmp (str, "SPSR") == 0
3902 /* Lower case versions for backwards compatability. */
3903 || strcmp (str, "cpsr") == 0
3904 || strcmp (str, "spsr") == 0)
3905 skip = 4;
3907 /* This is for backwards compatability with older toolchains. */
3908 else if ( strcmp (str, "cpsr_all") == 0
3909 || strcmp (str, "spsr_all") == 0)
3910 skip = 8;
3911 else
3913 inst.error = _("CPSR or SPSR expected");
3914 return;
3917 if (* str == 's' || * str == 'S')
3918 inst.instruction |= SPSR_BIT;
3919 str += skip;
3921 end_of_line (str);
3924 /* Two possible forms:
3925 "{C|S}PSR_<field>, Rm",
3926 "{C|S}PSR_f, #expression". */
3928 static void
3929 do_msr (str)
3930 char * str;
3932 skip_whitespace (str);
3934 if (psr_required_here (& str) == FAIL)
3935 return;
3937 if (skip_past_comma (& str) == FAIL)
3939 inst.error = _("comma missing after psr flags");
3940 return;
3943 skip_whitespace (str);
3945 if (reg_required_here (& str, 0) != FAIL)
3947 inst.error = NULL;
3948 end_of_line (str);
3949 return;
3952 if (! is_immediate_prefix (* str))
3954 inst.error =
3955 _("only a register or immediate value can follow a psr flag");
3956 return;
3959 str ++;
3960 inst.error = NULL;
3962 if (my_get_expression (& inst.reloc.exp, & str))
3964 inst.error =
3965 _("only a register or immediate value can follow a psr flag");
3966 return;
3969 #if 0 /* The first edition of the ARM architecture manual stated that
3970 writing anything other than the flags with an immediate operation
3971 had UNPREDICTABLE effects. This constraint was removed in the
3972 second edition of the specification. */
3973 if ((cpu_variant & ARM_EXT_V5) != ARM_EXT_V5
3974 && inst.instruction & ((PSR_c | PSR_x | PSR_s) << PSR_SHIFT))
3976 inst.error = _("immediate value cannot be used to set this field");
3977 return;
3979 #endif
3981 inst.instruction |= INST_IMMEDIATE;
3983 if (inst.reloc.exp.X_add_symbol)
3985 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
3986 inst.reloc.pc_rel = 0;
3988 else
3990 unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
3992 if (value == (unsigned) FAIL)
3994 inst.error = _("invalid constant");
3995 return;
3998 inst.instruction |= value;
4001 inst.error = NULL;
4002 end_of_line (str);
4005 /* Long Multiply Parser
4006 UMULL RdLo, RdHi, Rm, Rs
4007 SMULL RdLo, RdHi, Rm, Rs
4008 UMLAL RdLo, RdHi, Rm, Rs
4009 SMLAL RdLo, RdHi, Rm, Rs. */
4011 static void
4012 do_mull (str)
4013 char * str;
4015 int rdlo, rdhi, rm, rs;
4017 /* Only one format "rdlo, rdhi, rm, rs". */
4018 skip_whitespace (str);
4020 if ((rdlo = reg_required_here (&str, 12)) == FAIL)
4022 inst.error = BAD_ARGS;
4023 return;
4026 if (skip_past_comma (&str) == FAIL
4027 || (rdhi = reg_required_here (&str, 16)) == FAIL)
4029 inst.error = BAD_ARGS;
4030 return;
4033 if (skip_past_comma (&str) == FAIL
4034 || (rm = reg_required_here (&str, 0)) == FAIL)
4036 inst.error = BAD_ARGS;
4037 return;
4040 /* rdhi, rdlo and rm must all be different. */
4041 if (rdlo == rdhi || rdlo == rm || rdhi == rm)
4042 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
4044 if (skip_past_comma (&str) == FAIL
4045 || (rs = reg_required_here (&str, 8)) == FAIL)
4047 inst.error = BAD_ARGS;
4048 return;
4051 if (rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC)
4053 inst.error = BAD_PC;
4054 return;
4057 end_of_line (str);
4058 return;
4061 static void
4062 do_mul (str)
4063 char * str;
4065 int rd, rm;
4067 /* Only one format "rd, rm, rs". */
4068 skip_whitespace (str);
4070 if ((rd = reg_required_here (&str, 16)) == FAIL)
4072 inst.error = BAD_ARGS;
4073 return;
4076 if (rd == REG_PC)
4078 inst.error = BAD_PC;
4079 return;
4082 if (skip_past_comma (&str) == FAIL
4083 || (rm = reg_required_here (&str, 0)) == FAIL)
4085 inst.error = BAD_ARGS;
4086 return;
4089 if (rm == REG_PC)
4091 inst.error = BAD_PC;
4092 return;
4095 if (rm == rd)
4096 as_tsktsk (_("rd and rm should be different in mul"));
4098 if (skip_past_comma (&str) == FAIL
4099 || (rm = reg_required_here (&str, 8)) == FAIL)
4101 inst.error = BAD_ARGS;
4102 return;
4105 if (rm == REG_PC)
4107 inst.error = BAD_PC;
4108 return;
4111 end_of_line (str);
4112 return;
4115 static void
4116 do_mla (str)
4117 char * str;
4119 int rd, rm;
4121 /* Only one format "rd, rm, rs, rn". */
4122 skip_whitespace (str);
4124 if ((rd = reg_required_here (&str, 16)) == FAIL)
4126 inst.error = BAD_ARGS;
4127 return;
4130 if (rd == REG_PC)
4132 inst.error = BAD_PC;
4133 return;
4136 if (skip_past_comma (&str) == FAIL
4137 || (rm = reg_required_here (&str, 0)) == FAIL)
4139 inst.error = BAD_ARGS;
4140 return;
4143 if (rm == REG_PC)
4145 inst.error = BAD_PC;
4146 return;
4149 if (rm == rd)
4150 as_tsktsk (_("rd and rm should be different in mla"));
4152 if (skip_past_comma (&str) == FAIL
4153 || (rd = reg_required_here (&str, 8)) == FAIL
4154 || skip_past_comma (&str) == FAIL
4155 || (rm = reg_required_here (&str, 12)) == FAIL)
4157 inst.error = BAD_ARGS;
4158 return;
4161 if (rd == REG_PC || rm == REG_PC)
4163 inst.error = BAD_PC;
4164 return;
4167 end_of_line (str);
4168 return;
4171 /* Expects *str -> the characters "acc0", possibly with leading blanks.
4172 Advances *str to the next non-alphanumeric.
4173 Returns 0, or else FAIL (in which case sets inst.error).
4175 (In a future XScale, there may be accumulators other than zero.
4176 At that time this routine and its callers can be upgraded to suit.) */
4178 static int
4179 accum0_required_here (str)
4180 char ** str;
4182 static char buff [128]; /* Note the address is taken. Hence, static. */
4183 char * p = * str;
4184 char c;
4185 int result = 0; /* The accum number. */
4187 skip_whitespace (p);
4189 *str = p; /* Advance caller's string pointer too. */
4190 c = *p++;
4191 while (ISALNUM (c))
4192 c = *p++;
4194 *--p = 0; /* Aap nul into input buffer at non-alnum. */
4196 if (! ( streq (*str, "acc0") || streq (*str, "ACC0")))
4198 sprintf (buff, _("acc0 expected, not '%.100s'"), *str);
4199 inst.error = buff;
4200 result = FAIL;
4203 *p = c; /* Unzap. */
4204 *str = p; /* Caller's string pointer to after match. */
4205 return result;
4208 /* Expects **str -> after a comma. May be leading blanks.
4209 Advances *str, recognizing a load mode, and setting inst.instruction.
4210 Returns rn, or else FAIL (in which case may set inst.error
4211 and not advance str)
4213 Note: doesn't know Rd, so no err checks that require such knowledge. */
4215 static int
4216 ld_mode_required_here (string)
4217 char ** string;
4219 char * str = * string;
4220 int rn;
4221 int pre_inc = 0;
4223 skip_whitespace (str);
4225 if (* str == '[')
4227 str++;
4229 skip_whitespace (str);
4231 if ((rn = reg_required_here (& str, 16)) == FAIL)
4232 return FAIL;
4234 skip_whitespace (str);
4236 if (* str == ']')
4238 str ++;
4240 if (skip_past_comma (& str) == SUCCESS)
4242 /* [Rn],... (post inc) */
4243 if (ldst_extend_v4 (&str) == FAIL)
4244 return FAIL;
4246 else /* [Rn] */
4248 skip_whitespace (str);
4250 if (* str == '!')
4252 str ++;
4253 inst.instruction |= WRITE_BACK;
4256 inst.instruction |= INDEX_UP | HWOFFSET_IMM;
4257 pre_inc = 1;
4260 else /* [Rn,...] */
4262 if (skip_past_comma (& str) == FAIL)
4264 inst.error = _("pre-indexed expression expected");
4265 return FAIL;
4268 pre_inc = 1;
4270 if (ldst_extend_v4 (&str) == FAIL)
4271 return FAIL;
4273 skip_whitespace (str);
4275 if (* str ++ != ']')
4277 inst.error = _("missing ]");
4278 return FAIL;
4281 skip_whitespace (str);
4283 if (* str == '!')
4285 str ++;
4286 inst.instruction |= WRITE_BACK;
4290 else if (* str == '=') /* ldr's "r,=label" syntax */
4291 /* We should never reach here, because <text> = <expression> is
4292 caught gas/read.c read_a_source_file() as a .set operation. */
4293 return FAIL;
4294 else /* PC +- 8 bit immediate offset. */
4296 if (my_get_expression (& inst.reloc.exp, & str))
4297 return FAIL;
4299 inst.instruction |= HWOFFSET_IMM; /* The I bit. */
4300 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
4301 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
4302 inst.reloc.pc_rel = 1;
4303 inst.instruction |= (REG_PC << 16);
4305 rn = REG_PC;
4306 pre_inc = 1;
4309 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
4310 * string = str;
4312 return rn;
4315 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
4316 SMLAxy{cond} Rd,Rm,Rs,Rn
4317 SMLAWy{cond} Rd,Rm,Rs,Rn
4318 Error if any register is R15. */
4320 static void
4321 do_smla (str)
4322 char * str;
4324 int rd, rm, rs, rn;
4326 skip_whitespace (str);
4328 if ((rd = reg_required_here (& str, 16)) == FAIL
4329 || skip_past_comma (& str) == FAIL
4330 || (rm = reg_required_here (& str, 0)) == FAIL
4331 || skip_past_comma (& str) == FAIL
4332 || (rs = reg_required_here (& str, 8)) == FAIL
4333 || skip_past_comma (& str) == FAIL
4334 || (rn = reg_required_here (& str, 12)) == FAIL)
4335 inst.error = BAD_ARGS;
4337 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC || rn == REG_PC)
4338 inst.error = BAD_PC;
4340 else
4341 end_of_line (str);
4344 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
4345 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
4346 Error if any register is R15.
4347 Warning if Rdlo == Rdhi. */
4349 static void
4350 do_smlal (str)
4351 char * str;
4353 int rdlo, rdhi, rm, rs;
4355 skip_whitespace (str);
4357 if ((rdlo = reg_required_here (& str, 12)) == FAIL
4358 || skip_past_comma (& str) == FAIL
4359 || (rdhi = reg_required_here (& str, 16)) == FAIL
4360 || skip_past_comma (& str) == FAIL
4361 || (rm = reg_required_here (& str, 0)) == FAIL
4362 || skip_past_comma (& str) == FAIL
4363 || (rs = reg_required_here (& str, 8)) == FAIL)
4365 inst.error = BAD_ARGS;
4366 return;
4369 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
4371 inst.error = BAD_PC;
4372 return;
4375 if (rdlo == rdhi)
4376 as_tsktsk (_("rdhi and rdlo must be different"));
4378 end_of_line (str);
4381 /* ARM V5E (El Segundo) signed-multiply (argument parse)
4382 SMULxy{cond} Rd,Rm,Rs
4383 Error if any register is R15. */
4385 static void
4386 do_smul (str)
4387 char * str;
4389 int rd, rm, rs;
4391 skip_whitespace (str);
4393 if ((rd = reg_required_here (& str, 16)) == FAIL
4394 || skip_past_comma (& str) == FAIL
4395 || (rm = reg_required_here (& str, 0)) == FAIL
4396 || skip_past_comma (& str) == FAIL
4397 || (rs = reg_required_here (& str, 8)) == FAIL)
4398 inst.error = BAD_ARGS;
4400 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC)
4401 inst.error = BAD_PC;
4403 else
4404 end_of_line (str);
4407 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
4408 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
4409 Error if any register is R15. */
4411 static void
4412 do_qadd (str)
4413 char * str;
4415 int rd, rm, rn;
4417 skip_whitespace (str);
4419 if ((rd = reg_required_here (& str, 12)) == FAIL
4420 || skip_past_comma (& str) == FAIL
4421 || (rm = reg_required_here (& str, 0)) == FAIL
4422 || skip_past_comma (& str) == FAIL
4423 || (rn = reg_required_here (& str, 16)) == FAIL)
4424 inst.error = BAD_ARGS;
4426 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
4427 inst.error = BAD_PC;
4429 else
4430 end_of_line (str);
4433 /* ARM V5E (el Segundo)
4434 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4435 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4437 These are equivalent to the XScale instructions MAR and MRA,
4438 respectively, when coproc == 0, opcode == 0, and CRm == 0.
4440 Result unpredicatable if Rd or Rn is R15. */
4442 static void
4443 do_co_reg2c (str)
4444 char * str;
4446 int rd, rn;
4448 skip_whitespace (str);
4450 if (co_proc_number (& str) == FAIL)
4452 if (!inst.error)
4453 inst.error = BAD_ARGS;
4454 return;
4457 if (skip_past_comma (& str) == FAIL
4458 || cp_opc_expr (& str, 4, 4) == FAIL)
4460 if (!inst.error)
4461 inst.error = BAD_ARGS;
4462 return;
4465 if (skip_past_comma (& str) == FAIL
4466 || (rd = reg_required_here (& str, 12)) == FAIL)
4468 if (!inst.error)
4469 inst.error = BAD_ARGS;
4470 return;
4473 if (skip_past_comma (& str) == FAIL
4474 || (rn = reg_required_here (& str, 16)) == FAIL)
4476 if (!inst.error)
4477 inst.error = BAD_ARGS;
4478 return;
4481 /* Unpredictable result if rd or rn is R15. */
4482 if (rd == REG_PC || rn == REG_PC)
4483 as_tsktsk
4484 (_("Warning: instruction unpredictable when using r15"));
4486 if (skip_past_comma (& str) == FAIL
4487 || cp_reg_required_here (& str, 0) == FAIL)
4489 if (!inst.error)
4490 inst.error = BAD_ARGS;
4491 return;
4494 end_of_line (str);
4497 /* ARM V5 count-leading-zeroes instruction (argument parse)
4498 CLZ{<cond>} <Rd>, <Rm>
4499 Condition defaults to COND_ALWAYS.
4500 Error if Rd or Rm are R15. */
4502 static void
4503 do_clz (str)
4504 char * str;
4506 int rd, rm;
4508 skip_whitespace (str);
4510 if (((rd = reg_required_here (& str, 12)) == FAIL)
4511 || (skip_past_comma (& str) == FAIL)
4512 || ((rm = reg_required_here (& str, 0)) == FAIL))
4513 inst.error = BAD_ARGS;
4515 else if (rd == REG_PC || rm == REG_PC )
4516 inst.error = BAD_PC;
4518 else
4519 end_of_line (str);
4522 /* ARM V5 (argument parse)
4523 LDC2{L} <coproc>, <CRd>, <addressing mode>
4524 STC2{L} <coproc>, <CRd>, <addressing mode>
4525 Instruction is not conditional, and has 0xf in the codition field.
4526 Otherwise, it's the same as LDC/STC. */
4528 static void
4529 do_lstc2 (str)
4530 char * str;
4532 skip_whitespace (str);
4534 if (co_proc_number (& str) == FAIL)
4536 if (!inst.error)
4537 inst.error = BAD_ARGS;
4539 else if (skip_past_comma (& str) == FAIL
4540 || cp_reg_required_here (& str, 12) == FAIL)
4542 if (!inst.error)
4543 inst.error = BAD_ARGS;
4545 else if (skip_past_comma (& str) == FAIL
4546 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
4548 if (! inst.error)
4549 inst.error = BAD_ARGS;
4551 else
4552 end_of_line (str);
4555 /* ARM V5 (argument parse)
4556 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
4557 Instruction is not conditional, and has 0xf in the condition field.
4558 Otherwise, it's the same as CDP. */
4560 static void
4561 do_cdp2 (str)
4562 char * str;
4564 skip_whitespace (str);
4566 if (co_proc_number (& str) == FAIL)
4568 if (!inst.error)
4569 inst.error = BAD_ARGS;
4570 return;
4573 if (skip_past_comma (& str) == FAIL
4574 || cp_opc_expr (& str, 20,4) == FAIL)
4576 if (!inst.error)
4577 inst.error = BAD_ARGS;
4578 return;
4581 if (skip_past_comma (& str) == FAIL
4582 || cp_reg_required_here (& str, 12) == FAIL)
4584 if (!inst.error)
4585 inst.error = BAD_ARGS;
4586 return;
4589 if (skip_past_comma (& str) == FAIL
4590 || cp_reg_required_here (& str, 16) == FAIL)
4592 if (!inst.error)
4593 inst.error = BAD_ARGS;
4594 return;
4597 if (skip_past_comma (& str) == FAIL
4598 || cp_reg_required_here (& str, 0) == FAIL)
4600 if (!inst.error)
4601 inst.error = BAD_ARGS;
4602 return;
4605 if (skip_past_comma (& str) == SUCCESS)
4607 if (cp_opc_expr (& str, 5, 3) == FAIL)
4609 if (!inst.error)
4610 inst.error = BAD_ARGS;
4611 return;
4615 end_of_line (str);
4618 /* ARM V5 (argument parse)
4619 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4620 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4621 Instruction is not conditional, and has 0xf in the condition field.
4622 Otherwise, it's the same as MCR/MRC. */
4624 static void
4625 do_co_reg2 (str)
4626 char * str;
4628 skip_whitespace (str);
4630 if (co_proc_number (& str) == FAIL)
4632 if (!inst.error)
4633 inst.error = BAD_ARGS;
4634 return;
4637 if (skip_past_comma (& str) == FAIL
4638 || cp_opc_expr (& str, 21, 3) == FAIL)
4640 if (!inst.error)
4641 inst.error = BAD_ARGS;
4642 return;
4645 if (skip_past_comma (& str) == FAIL
4646 || reg_required_here (& str, 12) == FAIL)
4648 if (!inst.error)
4649 inst.error = BAD_ARGS;
4650 return;
4653 if (skip_past_comma (& str) == FAIL
4654 || cp_reg_required_here (& str, 16) == FAIL)
4656 if (!inst.error)
4657 inst.error = BAD_ARGS;
4658 return;
4661 if (skip_past_comma (& str) == FAIL
4662 || cp_reg_required_here (& str, 0) == FAIL)
4664 if (!inst.error)
4665 inst.error = BAD_ARGS;
4666 return;
4669 if (skip_past_comma (& str) == SUCCESS)
4671 if (cp_opc_expr (& str, 5, 3) == FAIL)
4673 if (!inst.error)
4674 inst.error = BAD_ARGS;
4675 return;
4679 end_of_line (str);
4682 /* ARM v5TEJ. Jump to Jazelle code. */
4683 static void
4684 do_bxj (str)
4685 char * str;
4687 int reg;
4689 skip_whitespace (str);
4691 if ((reg = reg_required_here (&str, 0)) == FAIL)
4693 inst.error = BAD_ARGS;
4694 return;
4697 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
4698 if (reg == REG_PC)
4699 as_tsktsk (_("use of r15 in bxj is not really useful"));
4701 end_of_line (str);
4704 /* THUMB V5 breakpoint instruction (argument parse)
4705 BKPT <immed_8>. */
4707 static void
4708 do_t_bkpt (str)
4709 char * str;
4711 expressionS expr;
4712 unsigned long number;
4714 skip_whitespace (str);
4716 /* Allow optional leading '#'. */
4717 if (is_immediate_prefix (*str))
4718 str ++;
4720 memset (& expr, '\0', sizeof (expr));
4721 if (my_get_expression (& expr, & str)
4722 || (expr.X_op != O_constant
4723 /* As a convenience we allow 'bkpt' without an operand. */
4724 && expr.X_op != O_absent))
4726 inst.error = _("bad expression");
4727 return;
4730 number = expr.X_add_number;
4732 /* Check it fits an 8 bit unsigned. */
4733 if (number != (number & 0xff))
4735 inst.error = _("immediate value out of range");
4736 return;
4739 inst.instruction |= number;
4741 end_of_line (str);
4744 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
4745 Expects inst.instruction is set for BLX(1).
4746 Note: this is cloned from do_branch, and the reloc changed to be a
4747 new one that can cope with setting one extra bit (the H bit). */
4749 static void
4750 do_branch25 (str)
4751 char * str;
4753 if (my_get_expression (& inst.reloc.exp, & str))
4754 return;
4756 #ifdef OBJ_ELF
4758 char * save_in;
4760 /* ScottB: February 5, 1998 */
4761 /* Check to see of PLT32 reloc required for the instruction. */
4763 /* arm_parse_reloc() works on input_line_pointer.
4764 We actually want to parse the operands to the branch instruction
4765 passed in 'str'. Save the input pointer and restore it later. */
4766 save_in = input_line_pointer;
4767 input_line_pointer = str;
4769 if (inst.reloc.exp.X_op == O_symbol
4770 && *str == '('
4771 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
4773 inst.reloc.type = BFD_RELOC_ARM_PLT32;
4774 inst.reloc.pc_rel = 0;
4775 /* Modify str to point to after parsed operands, otherwise
4776 end_of_line() will complain about the (PLT) left in str. */
4777 str = input_line_pointer;
4779 else
4781 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
4782 inst.reloc.pc_rel = 1;
4785 input_line_pointer = save_in;
4787 #else
4788 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
4789 inst.reloc.pc_rel = 1;
4790 #endif /* OBJ_ELF */
4792 end_of_line (str);
4795 /* ARM V5 branch-link-exchange instruction (argument parse)
4796 BLX <target_addr> ie BLX(1)
4797 BLX{<condition>} <Rm> ie BLX(2)
4798 Unfortunately, there are two different opcodes for this mnemonic.
4799 So, the insns[].value is not used, and the code here zaps values
4800 into inst.instruction.
4801 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
4803 static void
4804 do_blx (str)
4805 char * str;
4807 char * mystr = str;
4808 int rm;
4810 skip_whitespace (mystr);
4811 rm = reg_required_here (& mystr, 0);
4813 /* The above may set inst.error. Ignore his opinion. */
4814 inst.error = 0;
4816 if (rm != FAIL)
4818 /* Arg is a register.
4819 Use the condition code our caller put in inst.instruction.
4820 Pass ourselves off as a BX with a funny opcode. */
4821 inst.instruction |= 0x012fff30;
4822 do_bx (str);
4824 else
4826 /* This must be is BLX <target address>, no condition allowed. */
4827 if (inst.instruction != COND_ALWAYS)
4829 inst.error = BAD_COND;
4830 return;
4833 inst.instruction = 0xfafffffe;
4835 /* Process like a B/BL, but with a different reloc.
4836 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
4837 do_branch25 (str);
4841 /* ARM V5 Thumb BLX (argument parse)
4842 BLX <target_addr> which is BLX(1)
4843 BLX <Rm> which is BLX(2)
4844 Unfortunately, there are two different opcodes for this mnemonic.
4845 So, the tinsns[].value is not used, and the code here zaps values
4846 into inst.instruction. */
4848 static void
4849 do_t_blx (str)
4850 char * str;
4852 char * mystr = str;
4853 int rm;
4855 skip_whitespace (mystr);
4856 inst.instruction = 0x4780;
4858 /* Note that this call is to the ARM register recognizer. BLX(2)
4859 uses the ARM register space, not the Thumb one, so a call to
4860 thumb_reg() would be wrong. */
4861 rm = reg_required_here (& mystr, 3);
4862 inst.error = 0;
4864 if (rm != FAIL)
4866 /* It's BLX(2). The .instruction was zapped with rm & is final. */
4867 inst.size = 2;
4869 else
4871 /* No ARM register. This must be BLX(1). Change the .instruction. */
4872 inst.instruction = 0xf7ffeffe;
4873 inst.size = 4;
4875 if (my_get_expression (& inst.reloc.exp, & mystr))
4876 return;
4878 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BLX;
4879 inst.reloc.pc_rel = 1;
4882 end_of_line (mystr);
4885 /* ARM V5 breakpoint instruction (argument parse)
4886 BKPT <16 bit unsigned immediate>
4887 Instruction is not conditional.
4888 The bit pattern given in insns[] has the COND_ALWAYS condition,
4889 and it is an error if the caller tried to override that. */
4891 static void
4892 do_bkpt (str)
4893 char * str;
4895 expressionS expr;
4896 unsigned long number;
4898 skip_whitespace (str);
4900 /* Allow optional leading '#'. */
4901 if (is_immediate_prefix (* str))
4902 str++;
4904 memset (& expr, '\0', sizeof (expr));
4906 if (my_get_expression (& expr, & str)
4907 || (expr.X_op != O_constant
4908 /* As a convenience we allow 'bkpt' without an operand. */
4909 && expr.X_op != O_absent))
4911 inst.error = _("bad expression");
4912 return;
4915 number = expr.X_add_number;
4917 /* Check it fits a 16 bit unsigned. */
4918 if (number != (number & 0xffff))
4920 inst.error = _("immediate value out of range");
4921 return;
4924 /* Top 12 of 16 bits to bits 19:8. */
4925 inst.instruction |= (number & 0xfff0) << 4;
4927 /* Bottom 4 of 16 bits to bits 3:0. */
4928 inst.instruction |= number & 0xf;
4930 end_of_line (str);
4933 static unsigned long check_iwmmxt_insn PARAMS ((char *, enum iwmmxt_insn_type, int));
4935 /* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
4937 static unsigned long
4938 check_iwmmxt_insn (str, insn_type, immediate_size)
4939 char * str;
4940 enum iwmmxt_insn_type insn_type;
4941 int immediate_size;
4943 int reg = 0;
4944 const char * inst_error;
4945 expressionS expr;
4946 unsigned long number;
4948 inst_error = inst.error;
4949 if (!inst.error)
4950 inst.error = BAD_ARGS;
4951 skip_whitespace (str);
4953 switch (insn_type)
4955 case check_rd:
4956 if ((reg = reg_required_here (&str, 12)) == FAIL)
4957 return FAIL;
4958 break;
4960 case check_wr:
4961 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR)) == FAIL)
4962 return FAIL;
4963 break;
4965 case check_wrwr:
4966 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
4967 || skip_past_comma (&str) == FAIL
4968 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
4969 return FAIL;
4970 break;
4972 case check_wrwrwr:
4973 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
4974 || skip_past_comma (&str) == FAIL
4975 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4976 || skip_past_comma (&str) == FAIL
4977 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
4978 return FAIL;
4979 break;
4981 case check_wrwrwcg:
4982 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
4983 || skip_past_comma (&str) == FAIL
4984 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4985 || skip_past_comma (&str) == FAIL
4986 || wreg_required_here (&str, 0, IWMMXT_REG_WCG) == FAIL))
4987 return FAIL;
4988 break;
4990 case check_tbcst:
4991 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4992 || skip_past_comma (&str) == FAIL
4993 || reg_required_here (&str, 12) == FAIL))
4994 return FAIL;
4995 break;
4997 case check_tmovmsk:
4998 if ((reg_required_here (&str, 12) == FAIL
4999 || skip_past_comma (&str) == FAIL
5000 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
5001 return FAIL;
5002 break;
5004 case check_tmia:
5005 if ((wreg_required_here (&str, 5, IWMMXT_REG_WR) == FAIL
5006 || skip_past_comma (&str) == FAIL
5007 || reg_required_here (&str, 0) == FAIL
5008 || skip_past_comma (&str) == FAIL
5009 || reg_required_here (&str, 12) == FAIL))
5010 return FAIL;
5011 break;
5013 case check_tmcrr:
5014 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
5015 || skip_past_comma (&str) == FAIL
5016 || reg_required_here (&str, 12) == FAIL
5017 || skip_past_comma (&str) == FAIL
5018 || reg_required_here (&str, 16) == FAIL))
5019 return FAIL;
5020 break;
5022 case check_tmrrc:
5023 if ((reg_required_here (&str, 12) == FAIL
5024 || skip_past_comma (&str) == FAIL
5025 || reg_required_here (&str, 16) == FAIL
5026 || skip_past_comma (&str) == FAIL
5027 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
5028 return FAIL;
5029 break;
5031 case check_tmcr:
5032 if ((wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL
5033 || skip_past_comma (&str) == FAIL
5034 || reg_required_here (&str, 12) == FAIL))
5035 return FAIL;
5036 break;
5038 case check_tmrc:
5039 if ((reg_required_here (&str, 12) == FAIL
5040 || skip_past_comma (&str) == FAIL
5041 || wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL))
5042 return FAIL;
5043 break;
5045 case check_tinsr:
5046 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5047 || skip_past_comma (&str) == FAIL
5048 || reg_required_here (&str, 12) == FAIL
5049 || skip_past_comma (&str) == FAIL))
5050 return FAIL;
5051 break;
5053 case check_textrc:
5054 if ((reg_required_here (&str, 12) == FAIL
5055 || skip_past_comma (&str) == FAIL))
5056 return FAIL;
5057 break;
5059 case check_waligni:
5060 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5061 || skip_past_comma (&str) == FAIL
5062 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5063 || skip_past_comma (&str) == FAIL
5064 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
5065 || skip_past_comma (&str) == FAIL))
5066 return FAIL;
5067 break;
5069 case check_textrm:
5070 if ((reg_required_here (&str, 12) == FAIL
5071 || skip_past_comma (&str) == FAIL
5072 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5073 || skip_past_comma (&str) == FAIL))
5074 return FAIL;
5075 break;
5077 case check_wshufh:
5078 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5079 || skip_past_comma (&str) == FAIL
5080 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5081 || skip_past_comma (&str) == FAIL))
5082 return FAIL;
5083 break;
5086 if (immediate_size == 0)
5088 end_of_line (str);
5089 inst.error = inst_error;
5090 return reg;
5092 else
5094 skip_whitespace (str);
5096 /* Allow optional leading '#'. */
5097 if (is_immediate_prefix (* str))
5098 str++;
5100 memset (& expr, '\0', sizeof (expr));
5102 if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
5104 inst.error = _("bad or missing expression");
5105 return FAIL;
5108 number = expr.X_add_number;
5110 if (number != (number & immediate_size))
5112 inst.error = _("immediate value out of range");
5113 return FAIL;
5115 end_of_line (str);
5116 inst.error = inst_error;
5117 return number;
5121 static void
5122 do_iwmmxt_byte_addr (str)
5123 char * str;
5125 int op = (inst.instruction & 0x300) >> 8;
5126 int reg;
5128 inst.instruction &= ~0x300;
5129 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
5131 skip_whitespace (str);
5133 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
5134 || skip_past_comma (& str) == FAIL
5135 || cp_byte_address_required_here (&str) == FAIL)
5137 if (! inst.error)
5138 inst.error = BAD_ARGS;
5140 else
5141 end_of_line (str);
5143 if (wc_register (reg))
5145 as_bad (_("non-word size not supported with control register"));
5146 inst.instruction |= 0xf0000100;
5147 inst.instruction &= ~0x00400000;
5151 static void
5152 do_iwmmxt_tandc (str)
5153 char * str;
5155 int reg;
5157 reg = check_iwmmxt_insn (str, check_rd, 0);
5159 if (reg != REG_PC && !inst.error)
5160 inst.error = _("only r15 allowed here");
5161 return;
5164 static void
5165 do_iwmmxt_tbcst (str)
5166 char * str;
5168 check_iwmmxt_insn (str, check_tbcst, 0);
5170 return;
5173 static void
5174 do_iwmmxt_textrc (str)
5175 char * str;
5177 unsigned long number;
5179 if ((number = check_iwmmxt_insn (str, check_textrc, 7)) == (unsigned long) FAIL)
5180 return;
5182 inst.instruction |= number & 0x7;
5183 return;
5186 static void
5187 do_iwmmxt_textrm (str)
5188 char * str;
5190 unsigned long number;
5192 if ((number = check_iwmmxt_insn (str, check_textrm, 7)) == (unsigned long) FAIL)
5193 return;
5195 inst.instruction |= number & 0x7;
5198 static void
5199 do_iwmmxt_tinsr (str)
5200 char * str;
5202 unsigned long number;
5204 if ((number = check_iwmmxt_insn (str, check_tinsr, 7)) == (unsigned long) FAIL)
5205 return;
5207 inst.instruction |= number & 0x7;
5208 return;
5211 static void
5212 do_iwmmxt_tmcr (str)
5213 char * str;
5215 check_iwmmxt_insn (str, check_tmcr, 0);
5217 return;
5220 static void
5221 do_iwmmxt_tmcrr (str)
5222 char * str;
5224 check_iwmmxt_insn (str, check_tmcrr, 0);
5226 return;
5229 static void
5230 do_iwmmxt_tmia (str)
5231 char * str;
5233 check_iwmmxt_insn (str, check_tmia, 0);
5235 return;
5238 static void
5239 do_iwmmxt_tmovmsk (str)
5240 char * str;
5242 check_iwmmxt_insn (str, check_tmovmsk, 0);
5244 return;
5247 static void
5248 do_iwmmxt_tmrc (str)
5249 char * str;
5251 check_iwmmxt_insn (str, check_tmrc, 0);
5253 return;
5256 static void
5257 do_iwmmxt_tmrrc (str)
5258 char * str;
5260 check_iwmmxt_insn (str, check_tmrrc, 0);
5262 return;
5265 static void
5266 do_iwmmxt_torc (str)
5267 char * str;
5269 check_iwmmxt_insn (str, check_rd, 0);
5270 return;
5273 static void
5274 do_iwmmxt_waligni (str)
5275 char * str;
5277 unsigned long number;
5279 if ((number = check_iwmmxt_insn (str, check_waligni, 7)) == (unsigned long) FAIL)
5280 return;
5282 inst.instruction |= ((number & 0x7) << 20);
5283 return;
5286 static void
5287 do_iwmmxt_wmov (str)
5288 char * str;
5290 if (check_iwmmxt_insn (str, check_wrwr, 0) == (unsigned long) FAIL)
5291 return;
5293 inst.instruction |= ((inst.instruction >> 16) & 0xf);
5294 return;
5297 static void
5298 do_iwmmxt_word_addr (str)
5299 char * str;
5301 int op = (inst.instruction & 0x300) >> 8;
5302 int reg;
5304 inst.instruction &= ~0x300;
5305 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
5307 skip_whitespace (str);
5309 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
5310 || skip_past_comma (& str) == FAIL
5311 || cp_address_required_here (& str, CP_WB_OK) == FAIL)
5313 if (! inst.error)
5314 inst.error = BAD_ARGS;
5316 else
5317 end_of_line (str);
5319 if (wc_register (reg))
5321 if ((inst.instruction & COND_MASK) != COND_ALWAYS)
5322 as_bad (_("conditional execution not supported with control register"));
5323 if (op != 2)
5324 as_bad (_("non-word size not supported with control register"));
5325 inst.instruction |= 0xf0000100;
5326 inst.instruction &= ~0x00400000;
5330 static void
5331 do_iwmmxt_wrwr (str)
5332 char * str;
5334 check_iwmmxt_insn (str, check_wrwr, 0);
5336 return;
5339 static void
5340 do_iwmmxt_wrwrwcg (str)
5341 char * str;
5343 check_iwmmxt_insn (str, check_wrwrwcg, 0);
5345 return;
5348 static void
5349 do_iwmmxt_wrwrwr (str)
5350 char * str;
5352 check_iwmmxt_insn (str, check_wrwrwr, 0);
5354 return;
5357 static void
5358 do_iwmmxt_wshufh (str)
5359 char * str;
5361 unsigned long number;
5363 if ((number = check_iwmmxt_insn (str, check_wshufh, 0xff)) == (unsigned long) FAIL)
5364 return;
5366 inst.instruction |= ((number & 0xf0) << 16) | (number & 0xf);
5367 return;
5370 static void
5371 do_iwmmxt_wzero (str)
5372 char * str;
5374 if (check_iwmmxt_insn (str, check_wr, 0) == (unsigned long) FAIL)
5375 return;
5377 inst.instruction |= ((inst.instruction & 0xf) << 12) | ((inst.instruction & 0xf) << 16);
5378 return;
5381 /* Xscale multiply-accumulate (argument parse)
5382 MIAcc acc0,Rm,Rs
5383 MIAPHcc acc0,Rm,Rs
5384 MIAxycc acc0,Rm,Rs. */
5386 static void
5387 do_xsc_mia (str)
5388 char * str;
5390 int rs;
5391 int rm;
5393 if (accum0_required_here (& str) == FAIL)
5394 inst.error = ERR_NO_ACCUM;
5396 else if (skip_past_comma (& str) == FAIL
5397 || (rm = reg_required_here (& str, 0)) == FAIL)
5398 inst.error = BAD_ARGS;
5400 else if (skip_past_comma (& str) == FAIL
5401 || (rs = reg_required_here (& str, 12)) == FAIL)
5402 inst.error = BAD_ARGS;
5404 /* inst.instruction has now been zapped with both rm and rs. */
5405 else if (rm == REG_PC || rs == REG_PC)
5406 inst.error = BAD_PC; /* Undefined result if rm or rs is R15. */
5408 else
5409 end_of_line (str);
5412 /* Xscale move-accumulator-register (argument parse)
5414 MARcc acc0,RdLo,RdHi. */
5416 static void
5417 do_xsc_mar (str)
5418 char * str;
5420 int rdlo, rdhi;
5422 if (accum0_required_here (& str) == FAIL)
5423 inst.error = ERR_NO_ACCUM;
5425 else if (skip_past_comma (& str) == FAIL
5426 || (rdlo = reg_required_here (& str, 12)) == FAIL)
5427 inst.error = BAD_ARGS;
5429 else if (skip_past_comma (& str) == FAIL
5430 || (rdhi = reg_required_here (& str, 16)) == FAIL)
5431 inst.error = BAD_ARGS;
5433 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5434 else if (rdlo == REG_PC || rdhi == REG_PC)
5435 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
5437 else
5438 end_of_line (str);
5441 /* Xscale move-register-accumulator (argument parse)
5443 MRAcc RdLo,RdHi,acc0. */
5445 static void
5446 do_xsc_mra (str)
5447 char * str;
5449 int rdlo;
5450 int rdhi;
5452 skip_whitespace (str);
5454 if ((rdlo = reg_required_here (& str, 12)) == FAIL)
5455 inst.error = BAD_ARGS;
5457 else if (skip_past_comma (& str) == FAIL
5458 || (rdhi = reg_required_here (& str, 16)) == FAIL)
5459 inst.error = BAD_ARGS;
5461 else if (skip_past_comma (& str) == FAIL
5462 || accum0_required_here (& str) == FAIL)
5463 inst.error = ERR_NO_ACCUM;
5465 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5466 else if (rdlo == rdhi)
5467 inst.error = BAD_ARGS; /* Undefined result if 2 writes to same reg. */
5469 else if (rdlo == REG_PC || rdhi == REG_PC)
5470 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
5471 else
5472 end_of_line (str);
5475 /* ARMv5TE: Preload-Cache
5477 PLD <addr_mode>
5479 Syntactically, like LDR with B=1, W=0, L=1. */
5481 static void
5482 do_pld (str)
5483 char * str;
5485 int rd;
5487 skip_whitespace (str);
5489 if (* str != '[')
5491 inst.error = _("'[' expected after PLD mnemonic");
5492 return;
5495 ++str;
5496 skip_whitespace (str);
5498 if ((rd = reg_required_here (& str, 16)) == FAIL)
5499 return;
5501 skip_whitespace (str);
5503 if (*str == ']')
5505 /* [Rn], ... ? */
5506 ++str;
5507 skip_whitespace (str);
5509 /* Post-indexed addressing is not allowed with PLD. */
5510 if (skip_past_comma (&str) == SUCCESS)
5512 inst.error
5513 = _("post-indexed expression used in preload instruction");
5514 return;
5516 else if (*str == '!') /* [Rn]! */
5518 inst.error = _("writeback used in preload instruction");
5519 ++str;
5521 else /* [Rn] */
5522 inst.instruction |= INDEX_UP | PRE_INDEX;
5524 else /* [Rn, ...] */
5526 if (skip_past_comma (& str) == FAIL)
5528 inst.error = _("pre-indexed expression expected");
5529 return;
5532 if (ldst_extend (&str) == FAIL)
5533 return;
5535 skip_whitespace (str);
5537 if (* str != ']')
5539 inst.error = _("missing ]");
5540 return;
5543 ++ str;
5544 skip_whitespace (str);
5546 if (* str == '!') /* [Rn]! */
5548 inst.error = _("writeback used in preload instruction");
5549 ++ str;
5552 inst.instruction |= PRE_INDEX;
5555 end_of_line (str);
5558 /* ARMv5TE load-consecutive (argument parse)
5559 Mode is like LDRH.
5561 LDRccD R, mode
5562 STRccD R, mode. */
5564 static void
5565 do_ldrd (str)
5566 char * str;
5568 int rd;
5569 int rn;
5571 skip_whitespace (str);
5573 if ((rd = reg_required_here (& str, 12)) == FAIL)
5575 inst.error = BAD_ARGS;
5576 return;
5579 if (skip_past_comma (& str) == FAIL
5580 || (rn = ld_mode_required_here (& str)) == FAIL)
5582 if (!inst.error)
5583 inst.error = BAD_ARGS;
5584 return;
5587 /* inst.instruction has now been zapped with Rd and the addressing mode. */
5588 if (rd & 1) /* Unpredictable result if Rd is odd. */
5590 inst.error = _("destination register must be even");
5591 return;
5594 if (rd == REG_LR)
5596 inst.error = _("r14 not allowed here");
5597 return;
5600 if (((rd == rn) || (rd + 1 == rn))
5601 && ((inst.instruction & WRITE_BACK)
5602 || (!(inst.instruction & PRE_INDEX))))
5603 as_warn (_("pre/post-indexing used when modified address register is destination"));
5605 /* For an index-register load, the index register must not overlap the
5606 destination (even if not write-back). */
5607 if ((inst.instruction & V4_STR_BIT) == 0
5608 && (inst.instruction & HWOFFSET_IMM) == 0)
5610 int rm = inst.instruction & 0x0000000f;
5612 if (rm == rd || (rm == rd + 1))
5613 as_warn (_("ldrd destination registers must not overlap index register"));
5616 end_of_line (str);
5619 /* Returns the index into fp_values of a floating point number,
5620 or -1 if not in the table. */
5622 static int
5623 my_get_float_expression (str)
5624 char ** str;
5626 LITTLENUM_TYPE words[MAX_LITTLENUMS];
5627 char * save_in;
5628 expressionS exp;
5629 int i;
5630 int j;
5632 memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE));
5634 /* Look for a raw floating point number. */
5635 if ((save_in = atof_ieee (*str, 'x', words)) != NULL
5636 && is_end_of_line[(unsigned char) *save_in])
5638 for (i = 0; i < NUM_FLOAT_VALS; i++)
5640 for (j = 0; j < MAX_LITTLENUMS; j++)
5642 if (words[j] != fp_values[i][j])
5643 break;
5646 if (j == MAX_LITTLENUMS)
5648 *str = save_in;
5649 return i;
5654 /* Try and parse a more complex expression, this will probably fail
5655 unless the code uses a floating point prefix (eg "0f"). */
5656 save_in = input_line_pointer;
5657 input_line_pointer = *str;
5658 if (expression (&exp) == absolute_section
5659 && exp.X_op == O_big
5660 && exp.X_add_number < 0)
5662 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
5663 Ditto for 15. */
5664 if (gen_to_words (words, 5, (long) 15) == 0)
5666 for (i = 0; i < NUM_FLOAT_VALS; i++)
5668 for (j = 0; j < MAX_LITTLENUMS; j++)
5670 if (words[j] != fp_values[i][j])
5671 break;
5674 if (j == MAX_LITTLENUMS)
5676 *str = input_line_pointer;
5677 input_line_pointer = save_in;
5678 return i;
5684 *str = input_line_pointer;
5685 input_line_pointer = save_in;
5686 return -1;
5689 /* Return TRUE if anything in the expression is a bignum. */
5691 static int
5692 walk_no_bignums (sp)
5693 symbolS * sp;
5695 if (symbol_get_value_expression (sp)->X_op == O_big)
5696 return 1;
5698 if (symbol_get_value_expression (sp)->X_add_symbol)
5700 return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
5701 || (symbol_get_value_expression (sp)->X_op_symbol
5702 && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
5705 return 0;
5708 static int in_my_get_expression = 0;
5710 static int
5711 my_get_expression (ep, str)
5712 expressionS * ep;
5713 char ** str;
5715 char * save_in;
5716 segT seg;
5718 save_in = input_line_pointer;
5719 input_line_pointer = *str;
5720 in_my_get_expression = 1;
5721 seg = expression (ep);
5722 in_my_get_expression = 0;
5724 if (ep->X_op == O_illegal)
5726 /* We found a bad expression in md_operand(). */
5727 *str = input_line_pointer;
5728 input_line_pointer = save_in;
5729 return 1;
5732 #ifdef OBJ_AOUT
5733 if (seg != absolute_section
5734 && seg != text_section
5735 && seg != data_section
5736 && seg != bss_section
5737 && seg != undefined_section)
5739 inst.error = _("bad_segment");
5740 *str = input_line_pointer;
5741 input_line_pointer = save_in;
5742 return 1;
5744 #endif
5746 /* Get rid of any bignums now, so that we don't generate an error for which
5747 we can't establish a line number later on. Big numbers are never valid
5748 in instructions, which is where this routine is always called. */
5749 if (ep->X_op == O_big
5750 || (ep->X_add_symbol
5751 && (walk_no_bignums (ep->X_add_symbol)
5752 || (ep->X_op_symbol
5753 && walk_no_bignums (ep->X_op_symbol)))))
5755 inst.error = _("invalid constant");
5756 *str = input_line_pointer;
5757 input_line_pointer = save_in;
5758 return 1;
5761 *str = input_line_pointer;
5762 input_line_pointer = save_in;
5763 return 0;
5766 /* We handle all bad expressions here, so that we can report the faulty
5767 instruction in the error message. */
5768 void
5769 md_operand (expr)
5770 expressionS *expr;
5772 if (in_my_get_expression)
5774 expr->X_op = O_illegal;
5775 if (inst.error == NULL)
5776 inst.error = _("bad expression");
5780 /* UNRESTRICT should be one if <shift> <register> is permitted for this
5781 instruction. */
5783 static int
5784 decode_shift (str, unrestrict)
5785 char ** str;
5786 int unrestrict;
5788 const struct asm_shift_name * shift;
5789 char * p;
5790 char c;
5792 skip_whitespace (* str);
5794 for (p = * str; ISALPHA (* p); p ++)
5797 if (p == * str)
5799 inst.error = _("shift expression expected");
5800 return FAIL;
5803 c = * p;
5804 * p = '\0';
5805 shift = (const struct asm_shift_name *) hash_find (arm_shift_hsh, * str);
5806 * p = c;
5808 if (shift == NULL)
5810 inst.error = _("shift expression expected");
5811 return FAIL;
5814 assert (shift->properties->index == shift_properties[shift->properties->index].index);
5816 if (shift->properties->index == SHIFT_RRX)
5818 * str = p;
5819 inst.instruction |= shift->properties->bit_field;
5820 return SUCCESS;
5823 skip_whitespace (p);
5825 if (unrestrict && reg_required_here (& p, 8) != FAIL)
5827 inst.instruction |= shift->properties->bit_field | SHIFT_BY_REG;
5828 * str = p;
5829 return SUCCESS;
5831 else if (! is_immediate_prefix (* p))
5833 inst.error = (unrestrict
5834 ? _("shift requires register or #expression")
5835 : _("shift requires #expression"));
5836 * str = p;
5837 return FAIL;
5840 inst.error = NULL;
5841 p ++;
5843 if (my_get_expression (& inst.reloc.exp, & p))
5844 return FAIL;
5846 /* Validate some simple #expressions. */
5847 if (inst.reloc.exp.X_op == O_constant)
5849 unsigned num = inst.reloc.exp.X_add_number;
5851 /* Reject operations greater than 32. */
5852 if (num > 32
5853 /* Reject a shift of 0 unless the mode allows it. */
5854 || (num == 0 && shift->properties->allows_0 == 0)
5855 /* Reject a shift of 32 unless the mode allows it. */
5856 || (num == 32 && shift->properties->allows_32 == 0)
5859 /* As a special case we allow a shift of zero for
5860 modes that do not support it to be recoded as an
5861 logical shift left of zero (ie nothing). We warn
5862 about this though. */
5863 if (num == 0)
5865 as_warn (_("shift of 0 ignored."));
5866 shift = & shift_names[0];
5867 assert (shift->properties->index == SHIFT_LSL);
5869 else
5871 inst.error = _("invalid immediate shift");
5872 return FAIL;
5876 /* Shifts of 32 are encoded as 0, for those shifts that
5877 support it. */
5878 if (num == 32)
5879 num = 0;
5881 inst.instruction |= (num << 7) | shift->properties->bit_field;
5883 else
5885 inst.reloc.type = BFD_RELOC_ARM_SHIFT_IMM;
5886 inst.reloc.pc_rel = 0;
5887 inst.instruction |= shift->properties->bit_field;
5890 * str = p;
5891 return SUCCESS;
5894 /* Do those data_ops which can take a negative immediate constant
5895 by altering the instuction. A bit of a hack really.
5896 MOV <-> MVN
5897 AND <-> BIC
5898 ADC <-> SBC
5899 by inverting the second operand, and
5900 ADD <-> SUB
5901 CMP <-> CMN
5902 by negating the second operand. */
5904 static int
5905 negate_data_op (instruction, value)
5906 unsigned long * instruction;
5907 unsigned long value;
5909 int op, new_inst;
5910 unsigned long negated, inverted;
5912 negated = validate_immediate (-value);
5913 inverted = validate_immediate (~value);
5915 op = (*instruction >> DATA_OP_SHIFT) & 0xf;
5916 switch (op)
5918 /* First negates. */
5919 case OPCODE_SUB: /* ADD <-> SUB */
5920 new_inst = OPCODE_ADD;
5921 value = negated;
5922 break;
5924 case OPCODE_ADD:
5925 new_inst = OPCODE_SUB;
5926 value = negated;
5927 break;
5929 case OPCODE_CMP: /* CMP <-> CMN */
5930 new_inst = OPCODE_CMN;
5931 value = negated;
5932 break;
5934 case OPCODE_CMN:
5935 new_inst = OPCODE_CMP;
5936 value = negated;
5937 break;
5939 /* Now Inverted ops. */
5940 case OPCODE_MOV: /* MOV <-> MVN */
5941 new_inst = OPCODE_MVN;
5942 value = inverted;
5943 break;
5945 case OPCODE_MVN:
5946 new_inst = OPCODE_MOV;
5947 value = inverted;
5948 break;
5950 case OPCODE_AND: /* AND <-> BIC */
5951 new_inst = OPCODE_BIC;
5952 value = inverted;
5953 break;
5955 case OPCODE_BIC:
5956 new_inst = OPCODE_AND;
5957 value = inverted;
5958 break;
5960 case OPCODE_ADC: /* ADC <-> SBC */
5961 new_inst = OPCODE_SBC;
5962 value = inverted;
5963 break;
5965 case OPCODE_SBC:
5966 new_inst = OPCODE_ADC;
5967 value = inverted;
5968 break;
5970 /* We cannot do anything. */
5971 default:
5972 return FAIL;
5975 if (value == (unsigned) FAIL)
5976 return FAIL;
5978 *instruction &= OPCODE_MASK;
5979 *instruction |= new_inst << DATA_OP_SHIFT;
5980 return value;
5983 static int
5984 data_op2 (str)
5985 char ** str;
5987 int value;
5988 expressionS expr;
5990 skip_whitespace (* str);
5992 if (reg_required_here (str, 0) != FAIL)
5994 if (skip_past_comma (str) == SUCCESS)
5995 /* Shift operation on register. */
5996 return decode_shift (str, NO_SHIFT_RESTRICT);
5998 return SUCCESS;
6000 else
6002 /* Immediate expression. */
6003 if (is_immediate_prefix (**str))
6005 (*str)++;
6006 inst.error = NULL;
6008 if (my_get_expression (&inst.reloc.exp, str))
6009 return FAIL;
6011 if (inst.reloc.exp.X_add_symbol)
6013 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
6014 inst.reloc.pc_rel = 0;
6016 else
6018 if (skip_past_comma (str) == SUCCESS)
6020 /* #x, y -- ie explicit rotation by Y. */
6021 if (my_get_expression (&expr, str))
6022 return FAIL;
6024 if (expr.X_op != O_constant)
6026 inst.error = _("constant expression expected");
6027 return FAIL;
6030 /* Rotate must be a multiple of 2. */
6031 if (((unsigned) expr.X_add_number) > 30
6032 || (expr.X_add_number & 1) != 0
6033 || ((unsigned) inst.reloc.exp.X_add_number) > 255)
6035 inst.error = _("invalid constant");
6036 return FAIL;
6038 inst.instruction |= INST_IMMEDIATE;
6039 inst.instruction |= inst.reloc.exp.X_add_number;
6040 inst.instruction |= expr.X_add_number << 7;
6041 return SUCCESS;
6044 /* Implicit rotation, select a suitable one. */
6045 value = validate_immediate (inst.reloc.exp.X_add_number);
6047 if (value == FAIL)
6049 /* Can't be done. Perhaps the code reads something like
6050 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
6051 if ((value = negate_data_op (&inst.instruction,
6052 inst.reloc.exp.X_add_number))
6053 == FAIL)
6055 inst.error = _("invalid constant");
6056 return FAIL;
6060 inst.instruction |= value;
6063 inst.instruction |= INST_IMMEDIATE;
6064 return SUCCESS;
6067 (*str)++;
6068 inst.error = _("register or shift expression expected");
6069 return FAIL;
6073 static int
6074 fp_op2 (str)
6075 char ** str;
6077 skip_whitespace (* str);
6079 if (fp_reg_required_here (str, 0) != FAIL)
6080 return SUCCESS;
6081 else
6083 /* Immediate expression. */
6084 if (*((*str)++) == '#')
6086 int i;
6088 inst.error = NULL;
6090 skip_whitespace (* str);
6092 /* First try and match exact strings, this is to guarantee
6093 that some formats will work even for cross assembly. */
6095 for (i = 0; fp_const[i]; i++)
6097 if (strncmp (*str, fp_const[i], strlen (fp_const[i])) == 0)
6099 char *start = *str;
6101 *str += strlen (fp_const[i]);
6102 if (is_end_of_line[(unsigned char) **str])
6104 inst.instruction |= i + 8;
6105 return SUCCESS;
6107 *str = start;
6111 /* Just because we didn't get a match doesn't mean that the
6112 constant isn't valid, just that it is in a format that we
6113 don't automatically recognize. Try parsing it with
6114 the standard expression routines. */
6115 if ((i = my_get_float_expression (str)) >= 0)
6117 inst.instruction |= i + 8;
6118 return SUCCESS;
6121 inst.error = _("invalid floating point immediate expression");
6122 return FAIL;
6124 inst.error =
6125 _("floating point register or immediate expression expected");
6126 return FAIL;
6130 static void
6131 do_arit (str)
6132 char * str;
6134 skip_whitespace (str);
6136 if (reg_required_here (&str, 12) == FAIL
6137 || skip_past_comma (&str) == FAIL
6138 || reg_required_here (&str, 16) == FAIL
6139 || skip_past_comma (&str) == FAIL
6140 || data_op2 (&str) == FAIL)
6142 if (!inst.error)
6143 inst.error = BAD_ARGS;
6144 return;
6147 end_of_line (str);
6148 return;
6151 static void
6152 do_adr (str)
6153 char * str;
6155 /* This is a pseudo-op of the form "adr rd, label" to be converted
6156 into a relative address of the form "add rd, pc, #label-.-8". */
6157 skip_whitespace (str);
6159 if (reg_required_here (&str, 12) == FAIL
6160 || skip_past_comma (&str) == FAIL
6161 || my_get_expression (&inst.reloc.exp, &str))
6163 if (!inst.error)
6164 inst.error = BAD_ARGS;
6165 return;
6168 /* Frag hacking will turn this into a sub instruction if the offset turns
6169 out to be negative. */
6170 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
6171 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust. */
6172 inst.reloc.pc_rel = 1;
6174 end_of_line (str);
6177 static void
6178 do_adrl (str)
6179 char * str;
6181 /* This is a pseudo-op of the form "adrl rd, label" to be converted
6182 into a relative address of the form:
6183 add rd, pc, #low(label-.-8)"
6184 add rd, rd, #high(label-.-8)" */
6186 skip_whitespace (str);
6188 if (reg_required_here (&str, 12) == FAIL
6189 || skip_past_comma (&str) == FAIL
6190 || my_get_expression (&inst.reloc.exp, &str))
6192 if (!inst.error)
6193 inst.error = BAD_ARGS;
6195 return;
6198 end_of_line (str);
6199 /* Frag hacking will turn this into a sub instruction if the offset turns
6200 out to be negative. */
6201 inst.reloc.type = BFD_RELOC_ARM_ADRL_IMMEDIATE;
6202 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust */
6203 inst.reloc.pc_rel = 1;
6204 inst.size = INSN_SIZE * 2;
6206 return;
6209 static void
6210 do_cmp (str)
6211 char * str;
6213 skip_whitespace (str);
6215 if (reg_required_here (&str, 16) == FAIL)
6217 if (!inst.error)
6218 inst.error = BAD_ARGS;
6219 return;
6222 if (skip_past_comma (&str) == FAIL
6223 || data_op2 (&str) == FAIL)
6225 if (!inst.error)
6226 inst.error = BAD_ARGS;
6227 return;
6230 end_of_line (str);
6231 return;
6234 static void
6235 do_mov (str)
6236 char * str;
6238 skip_whitespace (str);
6240 if (reg_required_here (&str, 12) == FAIL)
6242 if (!inst.error)
6243 inst.error = BAD_ARGS;
6244 return;
6247 if (skip_past_comma (&str) == FAIL
6248 || data_op2 (&str) == FAIL)
6250 if (!inst.error)
6251 inst.error = BAD_ARGS;
6252 return;
6255 end_of_line (str);
6256 return;
6259 static int
6260 ldst_extend (str)
6261 char ** str;
6263 int add = INDEX_UP;
6265 switch (**str)
6267 case '#':
6268 case '$':
6269 (*str)++;
6270 if (my_get_expression (& inst.reloc.exp, str))
6271 return FAIL;
6273 if (inst.reloc.exp.X_op == O_constant)
6275 int value = inst.reloc.exp.X_add_number;
6277 if (value < -4095 || value > 4095)
6279 inst.error = _("address offset too large");
6280 return FAIL;
6283 if (value < 0)
6285 value = -value;
6286 add = 0;
6289 inst.instruction |= add | value;
6291 else
6293 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
6294 inst.reloc.pc_rel = 0;
6296 return SUCCESS;
6298 case '-':
6299 add = 0;
6300 /* Fall through. */
6302 case '+':
6303 (*str)++;
6304 /* Fall through. */
6306 default:
6307 if (reg_required_here (str, 0) == FAIL)
6308 return FAIL;
6310 inst.instruction |= add | OFFSET_REG;
6311 if (skip_past_comma (str) == SUCCESS)
6312 return decode_shift (str, SHIFT_RESTRICT);
6314 return SUCCESS;
6318 static void
6319 do_ldst (str)
6320 char * str;
6322 int pre_inc = 0;
6323 int conflict_reg;
6324 int value;
6326 skip_whitespace (str);
6328 if ((conflict_reg = reg_required_here (&str, 12)) == FAIL)
6330 if (!inst.error)
6331 inst.error = BAD_ARGS;
6332 return;
6335 if (skip_past_comma (&str) == FAIL)
6337 inst.error = _("address expected");
6338 return;
6341 if (*str == '[')
6343 int reg;
6345 str++;
6347 skip_whitespace (str);
6349 if ((reg = reg_required_here (&str, 16)) == FAIL)
6350 return;
6352 /* Conflicts can occur on stores as well as loads. */
6353 conflict_reg = (conflict_reg == reg);
6355 skip_whitespace (str);
6357 if (*str == ']')
6359 str ++;
6361 if (skip_past_comma (&str) == SUCCESS)
6363 /* [Rn],... (post inc) */
6364 if (ldst_extend (&str) == FAIL)
6365 return;
6366 if (conflict_reg)
6367 as_warn (_("%s register same as write-back base"),
6368 ((inst.instruction & LOAD_BIT)
6369 ? _("destination") : _("source")));
6371 else
6373 /* [Rn] */
6374 skip_whitespace (str);
6376 if (*str == '!')
6378 if (conflict_reg)
6379 as_warn (_("%s register same as write-back base"),
6380 ((inst.instruction & LOAD_BIT)
6381 ? _("destination") : _("source")));
6382 str++;
6383 inst.instruction |= WRITE_BACK;
6386 inst.instruction |= INDEX_UP;
6387 pre_inc = 1;
6390 else
6392 /* [Rn,...] */
6393 if (skip_past_comma (&str) == FAIL)
6395 inst.error = _("pre-indexed expression expected");
6396 return;
6399 pre_inc = 1;
6400 if (ldst_extend (&str) == FAIL)
6401 return;
6403 skip_whitespace (str);
6405 if (*str++ != ']')
6407 inst.error = _("missing ]");
6408 return;
6411 skip_whitespace (str);
6413 if (*str == '!')
6415 if (conflict_reg)
6416 as_warn (_("%s register same as write-back base"),
6417 ((inst.instruction & LOAD_BIT)
6418 ? _("destination") : _("source")));
6419 str++;
6420 inst.instruction |= WRITE_BACK;
6424 else if (*str == '=')
6426 if ((inst.instruction & LOAD_BIT) == 0)
6428 inst.error = _("invalid pseudo operation");
6429 return;
6432 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6433 str++;
6435 skip_whitespace (str);
6437 if (my_get_expression (&inst.reloc.exp, &str))
6438 return;
6440 if (inst.reloc.exp.X_op != O_constant
6441 && inst.reloc.exp.X_op != O_symbol)
6443 inst.error = _("constant expression expected");
6444 return;
6447 if (inst.reloc.exp.X_op == O_constant)
6449 value = validate_immediate (inst.reloc.exp.X_add_number);
6451 if (value != FAIL)
6453 /* This can be done with a mov instruction. */
6454 inst.instruction &= LITERAL_MASK;
6455 inst.instruction |= (INST_IMMEDIATE
6456 | (OPCODE_MOV << DATA_OP_SHIFT));
6457 inst.instruction |= value & 0xfff;
6458 end_of_line (str);
6459 return;
6462 value = validate_immediate (~inst.reloc.exp.X_add_number);
6464 if (value != FAIL)
6466 /* This can be done with a mvn instruction. */
6467 inst.instruction &= LITERAL_MASK;
6468 inst.instruction |= (INST_IMMEDIATE
6469 | (OPCODE_MVN << DATA_OP_SHIFT));
6470 inst.instruction |= value & 0xfff;
6471 end_of_line (str);
6472 return;
6476 /* Insert into literal pool. */
6477 if (add_to_lit_pool () == FAIL)
6479 if (!inst.error)
6480 inst.error = _("literal pool insertion failed");
6481 return;
6484 /* Change the instruction exp to point to the pool. */
6485 inst.reloc.type = BFD_RELOC_ARM_LITERAL;
6486 inst.reloc.pc_rel = 1;
6487 inst.instruction |= (REG_PC << 16);
6488 pre_inc = 1;
6490 else
6492 if (my_get_expression (&inst.reloc.exp, &str))
6493 return;
6495 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
6496 #ifndef TE_WINCE
6497 /* PC rel adjust. */
6498 inst.reloc.exp.X_add_number -= 8;
6499 #endif
6500 inst.reloc.pc_rel = 1;
6501 inst.instruction |= (REG_PC << 16);
6502 pre_inc = 1;
6505 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
6506 end_of_line (str);
6507 return;
6510 static void
6511 do_ldstt (str)
6512 char * str;
6514 int conflict_reg;
6516 skip_whitespace (str);
6518 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
6520 if (!inst.error)
6521 inst.error = BAD_ARGS;
6522 return;
6525 if (skip_past_comma (& str) == FAIL)
6527 inst.error = _("address expected");
6528 return;
6531 if (*str == '[')
6533 int reg;
6535 str++;
6537 skip_whitespace (str);
6539 if ((reg = reg_required_here (&str, 16)) == FAIL)
6540 return;
6542 /* ldrt/strt always use post-indexed addressing, so if the base is
6543 the same as Rd, we warn. */
6544 if (conflict_reg == reg)
6545 as_warn (_("%s register same as write-back base"),
6546 ((inst.instruction & LOAD_BIT)
6547 ? _("destination") : _("source")));
6549 skip_whitespace (str);
6551 if (*str == ']')
6553 str ++;
6555 if (skip_past_comma (&str) == SUCCESS)
6557 /* [Rn],... (post inc) */
6558 if (ldst_extend (&str) == FAIL)
6559 return;
6561 else
6563 /* [Rn] */
6564 skip_whitespace (str);
6566 /* Skip a write-back '!'. */
6567 if (*str == '!')
6568 str++;
6570 inst.instruction |= INDEX_UP;
6573 else
6575 inst.error = _("post-indexed expression expected");
6576 return;
6579 else
6581 inst.error = _("post-indexed expression expected");
6582 return;
6585 end_of_line (str);
6586 return;
6589 static int
6590 ldst_extend_v4 (str)
6591 char ** str;
6593 int add = INDEX_UP;
6595 switch (**str)
6597 case '#':
6598 case '$':
6599 (*str)++;
6600 if (my_get_expression (& inst.reloc.exp, str))
6601 return FAIL;
6603 if (inst.reloc.exp.X_op == O_constant)
6605 int value = inst.reloc.exp.X_add_number;
6607 if (value < -255 || value > 255)
6609 inst.error = _("address offset too large");
6610 return FAIL;
6613 if (value < 0)
6615 value = -value;
6616 add = 0;
6619 /* Halfword and signextension instructions have the
6620 immediate value split across bits 11..8 and bits 3..0. */
6621 inst.instruction |= (add | HWOFFSET_IMM
6622 | ((value >> 4) << 8) | (value & 0xF));
6624 else
6626 inst.instruction |= HWOFFSET_IMM;
6627 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
6628 inst.reloc.pc_rel = 0;
6630 return SUCCESS;
6632 case '-':
6633 add = 0;
6634 /* Fall through. */
6636 case '+':
6637 (*str)++;
6638 /* Fall through. */
6640 default:
6641 if (reg_required_here (str, 0) == FAIL)
6642 return FAIL;
6644 inst.instruction |= add;
6645 return SUCCESS;
6649 /* Halfword and signed-byte load/store operations. */
6650 static void
6651 do_ldstv4 (str)
6652 char * str;
6654 int pre_inc = 0;
6655 int conflict_reg;
6656 int value;
6658 skip_whitespace (str);
6660 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
6662 if (!inst.error)
6663 inst.error = BAD_ARGS;
6664 return;
6667 if (skip_past_comma (& str) == FAIL)
6669 inst.error = _("address expected");
6670 return;
6673 if (*str == '[')
6675 int reg;
6677 str++;
6679 skip_whitespace (str);
6681 if ((reg = reg_required_here (&str, 16)) == FAIL)
6682 return;
6684 /* Conflicts can occur on stores as well as loads. */
6685 conflict_reg = (conflict_reg == reg);
6687 skip_whitespace (str);
6689 if (*str == ']')
6691 str ++;
6693 if (skip_past_comma (&str) == SUCCESS)
6695 /* [Rn],... (post inc) */
6696 if (ldst_extend_v4 (&str) == FAIL)
6697 return;
6698 if (conflict_reg)
6699 as_warn (_("%s register same as write-back base"),
6700 ((inst.instruction & LOAD_BIT)
6701 ? _("destination") : _("source")));
6703 else
6705 /* [Rn] */
6706 inst.instruction |= HWOFFSET_IMM;
6708 skip_whitespace (str);
6710 if (*str == '!')
6712 if (conflict_reg)
6713 as_warn (_("%s register same as write-back base"),
6714 ((inst.instruction & LOAD_BIT)
6715 ? _("destination") : _("source")));
6716 str++;
6717 inst.instruction |= WRITE_BACK;
6720 inst.instruction |= INDEX_UP;
6721 pre_inc = 1;
6724 else
6726 /* [Rn,...] */
6727 if (skip_past_comma (&str) == FAIL)
6729 inst.error = _("pre-indexed expression expected");
6730 return;
6733 pre_inc = 1;
6734 if (ldst_extend_v4 (&str) == FAIL)
6735 return;
6737 skip_whitespace (str);
6739 if (*str++ != ']')
6741 inst.error = _("missing ]");
6742 return;
6745 skip_whitespace (str);
6747 if (*str == '!')
6749 if (conflict_reg)
6750 as_warn (_("%s register same as write-back base"),
6751 ((inst.instruction & LOAD_BIT)
6752 ? _("destination") : _("source")));
6753 str++;
6754 inst.instruction |= WRITE_BACK;
6758 else if (*str == '=')
6760 if ((inst.instruction & LOAD_BIT) == 0)
6762 inst.error = _("invalid pseudo operation");
6763 return;
6766 /* XXX Does this work correctly for half-word/byte ops? */
6767 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6768 str++;
6770 skip_whitespace (str);
6772 if (my_get_expression (&inst.reloc.exp, &str))
6773 return;
6775 if (inst.reloc.exp.X_op != O_constant
6776 && inst.reloc.exp.X_op != O_symbol)
6778 inst.error = _("constant expression expected");
6779 return;
6782 if (inst.reloc.exp.X_op == O_constant)
6784 value = validate_immediate (inst.reloc.exp.X_add_number);
6786 if (value != FAIL)
6788 /* This can be done with a mov instruction. */
6789 inst.instruction &= LITERAL_MASK;
6790 inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
6791 inst.instruction |= value & 0xfff;
6792 end_of_line (str);
6793 return;
6796 value = validate_immediate (~ inst.reloc.exp.X_add_number);
6798 if (value != FAIL)
6800 /* This can be done with a mvn instruction. */
6801 inst.instruction &= LITERAL_MASK;
6802 inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT);
6803 inst.instruction |= value & 0xfff;
6804 end_of_line (str);
6805 return;
6809 /* Insert into literal pool. */
6810 if (add_to_lit_pool () == FAIL)
6812 if (!inst.error)
6813 inst.error = _("literal pool insertion failed");
6814 return;
6817 /* Change the instruction exp to point to the pool. */
6818 inst.instruction |= HWOFFSET_IMM;
6819 inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
6820 inst.reloc.pc_rel = 1;
6821 inst.instruction |= (REG_PC << 16);
6822 pre_inc = 1;
6824 else
6826 if (my_get_expression (&inst.reloc.exp, &str))
6827 return;
6829 inst.instruction |= HWOFFSET_IMM;
6830 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
6831 #ifndef TE_WINCE
6832 /* PC rel adjust. */
6833 inst.reloc.exp.X_add_number -= 8;
6834 #endif
6835 inst.reloc.pc_rel = 1;
6836 inst.instruction |= (REG_PC << 16);
6837 pre_inc = 1;
6840 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
6841 end_of_line (str);
6842 return;
6845 static long
6846 reg_list (strp)
6847 char ** strp;
6849 char * str = * strp;
6850 long range = 0;
6851 int another_range;
6853 /* We come back here if we get ranges concatenated by '+' or '|'. */
6856 another_range = 0;
6858 if (*str == '{')
6860 int in_range = 0;
6861 int cur_reg = -1;
6863 str++;
6866 int reg;
6868 skip_whitespace (str);
6870 if ((reg = reg_required_here (& str, -1)) == FAIL)
6871 return FAIL;
6873 if (in_range)
6875 int i;
6877 if (reg <= cur_reg)
6879 inst.error = _("bad range in register list");
6880 return FAIL;
6883 for (i = cur_reg + 1; i < reg; i++)
6885 if (range & (1 << i))
6886 as_tsktsk
6887 (_("Warning: duplicated register (r%d) in register list"),
6889 else
6890 range |= 1 << i;
6892 in_range = 0;
6895 if (range & (1 << reg))
6896 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
6897 reg);
6898 else if (reg <= cur_reg)
6899 as_tsktsk (_("Warning: register range not in ascending order"));
6901 range |= 1 << reg;
6902 cur_reg = reg;
6904 while (skip_past_comma (&str) != FAIL
6905 || (in_range = 1, *str++ == '-'));
6906 str--;
6907 skip_whitespace (str);
6909 if (*str++ != '}')
6911 inst.error = _("missing `}'");
6912 return FAIL;
6915 else
6917 expressionS expr;
6919 if (my_get_expression (&expr, &str))
6920 return FAIL;
6922 if (expr.X_op == O_constant)
6924 if (expr.X_add_number
6925 != (expr.X_add_number & 0x0000ffff))
6927 inst.error = _("invalid register mask");
6928 return FAIL;
6931 if ((range & expr.X_add_number) != 0)
6933 int regno = range & expr.X_add_number;
6935 regno &= -regno;
6936 regno = (1 << regno) - 1;
6937 as_tsktsk
6938 (_("Warning: duplicated register (r%d) in register list"),
6939 regno);
6942 range |= expr.X_add_number;
6944 else
6946 if (inst.reloc.type != 0)
6948 inst.error = _("expression too complex");
6949 return FAIL;
6952 memcpy (&inst.reloc.exp, &expr, sizeof (expressionS));
6953 inst.reloc.type = BFD_RELOC_ARM_MULTI;
6954 inst.reloc.pc_rel = 0;
6958 skip_whitespace (str);
6960 if (*str == '|' || *str == '+')
6962 str++;
6963 another_range = 1;
6966 while (another_range);
6968 *strp = str;
6969 return range;
6972 static void
6973 do_ldmstm (str)
6974 char * str;
6976 int base_reg;
6977 long range;
6979 skip_whitespace (str);
6981 if ((base_reg = reg_required_here (&str, 16)) == FAIL)
6982 return;
6984 if (base_reg == REG_PC)
6986 inst.error = _("r15 not allowed as base register");
6987 return;
6990 skip_whitespace (str);
6992 if (*str == '!')
6994 inst.instruction |= WRITE_BACK;
6995 str++;
6998 if (skip_past_comma (&str) == FAIL
6999 || (range = reg_list (&str)) == FAIL)
7001 if (! inst.error)
7002 inst.error = BAD_ARGS;
7003 return;
7006 if (*str == '^')
7008 str++;
7009 inst.instruction |= LDM_TYPE_2_OR_3;
7012 if (inst.instruction & WRITE_BACK)
7014 /* Check for unpredictable uses of writeback. */
7015 if (inst.instruction & LOAD_BIT)
7017 /* Not allowed in LDM type 2. */
7018 if ((inst.instruction & LDM_TYPE_2_OR_3)
7019 && ((range & (1 << REG_PC)) == 0))
7020 as_warn (_("writeback of base register is UNPREDICTABLE"));
7021 /* Only allowed if base reg not in list for other types. */
7022 else if (range & (1 << base_reg))
7023 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
7025 else /* STM. */
7027 /* Not allowed for type 2. */
7028 if (inst.instruction & LDM_TYPE_2_OR_3)
7029 as_warn (_("writeback of base register is UNPREDICTABLE"));
7030 /* Only allowed if base reg not in list, or first in list. */
7031 else if ((range & (1 << base_reg))
7032 && (range & ((1 << base_reg) - 1)))
7033 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
7037 inst.instruction |= range;
7038 end_of_line (str);
7039 return;
7042 static void
7043 do_swi (str)
7044 char * str;
7046 skip_whitespace (str);
7048 /* Allow optional leading '#'. */
7049 if (is_immediate_prefix (*str))
7050 str++;
7052 if (my_get_expression (& inst.reloc.exp, & str))
7053 return;
7055 inst.reloc.type = BFD_RELOC_ARM_SWI;
7056 inst.reloc.pc_rel = 0;
7057 end_of_line (str);
7059 return;
7062 static void
7063 do_swap (str)
7064 char * str;
7066 int reg;
7068 skip_whitespace (str);
7070 if ((reg = reg_required_here (&str, 12)) == FAIL)
7071 return;
7073 if (reg == REG_PC)
7075 inst.error = _("r15 not allowed in swap");
7076 return;
7079 if (skip_past_comma (&str) == FAIL
7080 || (reg = reg_required_here (&str, 0)) == FAIL)
7082 if (!inst.error)
7083 inst.error = BAD_ARGS;
7084 return;
7087 if (reg == REG_PC)
7089 inst.error = _("r15 not allowed in swap");
7090 return;
7093 if (skip_past_comma (&str) == FAIL
7094 || *str++ != '[')
7096 inst.error = BAD_ARGS;
7097 return;
7100 skip_whitespace (str);
7102 if ((reg = reg_required_here (&str, 16)) == FAIL)
7103 return;
7105 if (reg == REG_PC)
7107 inst.error = BAD_PC;
7108 return;
7111 skip_whitespace (str);
7113 if (*str++ != ']')
7115 inst.error = _("missing ]");
7116 return;
7119 end_of_line (str);
7120 return;
7123 static void
7124 do_branch (str)
7125 char * str;
7127 if (my_get_expression (&inst.reloc.exp, &str))
7128 return;
7130 #ifdef OBJ_ELF
7132 char * save_in;
7134 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
7135 required for the instruction. */
7137 /* arm_parse_reloc () works on input_line_pointer.
7138 We actually want to parse the operands to the branch instruction
7139 passed in 'str'. Save the input pointer and restore it later. */
7140 save_in = input_line_pointer;
7141 input_line_pointer = str;
7142 if (inst.reloc.exp.X_op == O_symbol
7143 && *str == '('
7144 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
7146 inst.reloc.type = BFD_RELOC_ARM_PLT32;
7147 inst.reloc.pc_rel = 0;
7148 /* Modify str to point to after parsed operands, otherwise
7149 end_of_line() will complain about the (PLT) left in str. */
7150 str = input_line_pointer;
7152 else
7154 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
7155 inst.reloc.pc_rel = 1;
7157 input_line_pointer = save_in;
7159 #else
7160 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
7161 inst.reloc.pc_rel = 1;
7162 #endif /* OBJ_ELF */
7164 end_of_line (str);
7165 return;
7168 static void
7169 do_bx (str)
7170 char * str;
7172 int reg;
7174 skip_whitespace (str);
7176 if ((reg = reg_required_here (&str, 0)) == FAIL)
7178 inst.error = BAD_ARGS;
7179 return;
7182 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
7183 if (reg == REG_PC)
7184 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
7186 end_of_line (str);
7189 static void
7190 do_cdp (str)
7191 char * str;
7193 /* Co-processor data operation.
7194 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
7195 skip_whitespace (str);
7197 if (co_proc_number (&str) == FAIL)
7199 if (!inst.error)
7200 inst.error = BAD_ARGS;
7201 return;
7204 if (skip_past_comma (&str) == FAIL
7205 || cp_opc_expr (&str, 20,4) == FAIL)
7207 if (!inst.error)
7208 inst.error = BAD_ARGS;
7209 return;
7212 if (skip_past_comma (&str) == FAIL
7213 || cp_reg_required_here (&str, 12) == FAIL)
7215 if (!inst.error)
7216 inst.error = BAD_ARGS;
7217 return;
7220 if (skip_past_comma (&str) == FAIL
7221 || cp_reg_required_here (&str, 16) == FAIL)
7223 if (!inst.error)
7224 inst.error = BAD_ARGS;
7225 return;
7228 if (skip_past_comma (&str) == FAIL
7229 || cp_reg_required_here (&str, 0) == FAIL)
7231 if (!inst.error)
7232 inst.error = BAD_ARGS;
7233 return;
7236 if (skip_past_comma (&str) == SUCCESS)
7238 if (cp_opc_expr (&str, 5, 3) == FAIL)
7240 if (!inst.error)
7241 inst.error = BAD_ARGS;
7242 return;
7246 end_of_line (str);
7247 return;
7250 static void
7251 do_lstc (str)
7252 char * str;
7254 /* Co-processor register load/store.
7255 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
7257 skip_whitespace (str);
7259 if (co_proc_number (&str) == FAIL)
7261 if (!inst.error)
7262 inst.error = BAD_ARGS;
7263 return;
7266 if (skip_past_comma (&str) == FAIL
7267 || cp_reg_required_here (&str, 12) == FAIL)
7269 if (!inst.error)
7270 inst.error = BAD_ARGS;
7271 return;
7274 if (skip_past_comma (&str) == FAIL
7275 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
7277 if (! inst.error)
7278 inst.error = BAD_ARGS;
7279 return;
7282 end_of_line (str);
7283 return;
7286 static void
7287 do_co_reg (str)
7288 char * str;
7290 /* Co-processor register transfer.
7291 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
7293 skip_whitespace (str);
7295 if (co_proc_number (&str) == FAIL)
7297 if (!inst.error)
7298 inst.error = BAD_ARGS;
7299 return;
7302 if (skip_past_comma (&str) == FAIL
7303 || cp_opc_expr (&str, 21, 3) == FAIL)
7305 if (!inst.error)
7306 inst.error = BAD_ARGS;
7307 return;
7310 if (skip_past_comma (&str) == FAIL
7311 || reg_required_here (&str, 12) == FAIL)
7313 if (!inst.error)
7314 inst.error = BAD_ARGS;
7315 return;
7318 if (skip_past_comma (&str) == FAIL
7319 || cp_reg_required_here (&str, 16) == FAIL)
7321 if (!inst.error)
7322 inst.error = BAD_ARGS;
7323 return;
7326 if (skip_past_comma (&str) == FAIL
7327 || cp_reg_required_here (&str, 0) == FAIL)
7329 if (!inst.error)
7330 inst.error = BAD_ARGS;
7331 return;
7334 if (skip_past_comma (&str) == SUCCESS)
7336 if (cp_opc_expr (&str, 5, 3) == FAIL)
7338 if (!inst.error)
7339 inst.error = BAD_ARGS;
7340 return;
7344 end_of_line (str);
7345 return;
7348 static void
7349 do_fpa_ctrl (str)
7350 char * str;
7352 /* FP control registers.
7353 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
7355 skip_whitespace (str);
7357 if (reg_required_here (&str, 12) == FAIL)
7359 if (!inst.error)
7360 inst.error = BAD_ARGS;
7361 return;
7364 end_of_line (str);
7365 return;
7368 static void
7369 do_fpa_ldst (str)
7370 char * str;
7372 skip_whitespace (str);
7374 if (fp_reg_required_here (&str, 12) == FAIL)
7376 if (!inst.error)
7377 inst.error = BAD_ARGS;
7378 return;
7381 if (skip_past_comma (&str) == FAIL
7382 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
7384 if (!inst.error)
7385 inst.error = BAD_ARGS;
7386 return;
7389 end_of_line (str);
7392 static void
7393 do_fpa_ldmstm (str)
7394 char * str;
7396 int num_regs;
7398 skip_whitespace (str);
7400 if (fp_reg_required_here (&str, 12) == FAIL)
7402 if (! inst.error)
7403 inst.error = BAD_ARGS;
7404 return;
7407 /* Get Number of registers to transfer. */
7408 if (skip_past_comma (&str) == FAIL
7409 || my_get_expression (&inst.reloc.exp, &str))
7411 if (! inst.error)
7412 inst.error = _("constant expression expected");
7413 return;
7416 if (inst.reloc.exp.X_op != O_constant)
7418 inst.error = _("constant value required for number of registers");
7419 return;
7422 num_regs = inst.reloc.exp.X_add_number;
7424 if (num_regs < 1 || num_regs > 4)
7426 inst.error = _("number of registers must be in the range [1:4]");
7427 return;
7430 switch (num_regs)
7432 case 1:
7433 inst.instruction |= CP_T_X;
7434 break;
7435 case 2:
7436 inst.instruction |= CP_T_Y;
7437 break;
7438 case 3:
7439 inst.instruction |= CP_T_Y | CP_T_X;
7440 break;
7441 case 4:
7442 break;
7443 default:
7444 abort ();
7447 if (inst.instruction & (CP_T_Pre | CP_T_UD)) /* ea/fd format. */
7449 int reg;
7450 int write_back;
7451 int offset;
7453 /* The instruction specified "ea" or "fd", so we can only accept
7454 [Rn]{!}. The instruction does not really support stacking or
7455 unstacking, so we have to emulate these by setting appropriate
7456 bits and offsets. */
7457 if (skip_past_comma (&str) == FAIL
7458 || *str != '[')
7460 if (! inst.error)
7461 inst.error = BAD_ARGS;
7462 return;
7465 str++;
7466 skip_whitespace (str);
7468 if ((reg = reg_required_here (&str, 16)) == FAIL)
7469 return;
7471 skip_whitespace (str);
7473 if (*str != ']')
7475 inst.error = BAD_ARGS;
7476 return;
7479 str++;
7480 if (*str == '!')
7482 write_back = 1;
7483 str++;
7484 if (reg == REG_PC)
7486 inst.error =
7487 _("r15 not allowed as base register with write-back");
7488 return;
7491 else
7492 write_back = 0;
7494 if (inst.instruction & CP_T_Pre)
7496 /* Pre-decrement. */
7497 offset = 3 * num_regs;
7498 if (write_back)
7499 inst.instruction |= CP_T_WB;
7501 else
7503 /* Post-increment. */
7504 if (write_back)
7506 inst.instruction |= CP_T_WB;
7507 offset = 3 * num_regs;
7509 else
7511 /* No write-back, so convert this into a standard pre-increment
7512 instruction -- aesthetically more pleasing. */
7513 inst.instruction |= CP_T_Pre | CP_T_UD;
7514 offset = 0;
7518 inst.instruction |= offset;
7520 else if (skip_past_comma (&str) == FAIL
7521 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
7523 if (! inst.error)
7524 inst.error = BAD_ARGS;
7525 return;
7528 end_of_line (str);
7531 static void
7532 do_fpa_dyadic (str)
7533 char * str;
7535 skip_whitespace (str);
7537 if (fp_reg_required_here (&str, 12) == FAIL)
7539 if (! inst.error)
7540 inst.error = BAD_ARGS;
7541 return;
7544 if (skip_past_comma (&str) == FAIL
7545 || fp_reg_required_here (&str, 16) == FAIL)
7547 if (! inst.error)
7548 inst.error = BAD_ARGS;
7549 return;
7552 if (skip_past_comma (&str) == FAIL
7553 || fp_op2 (&str) == FAIL)
7555 if (! inst.error)
7556 inst.error = BAD_ARGS;
7557 return;
7560 end_of_line (str);
7561 return;
7564 static void
7565 do_fpa_monadic (str)
7566 char * str;
7568 skip_whitespace (str);
7570 if (fp_reg_required_here (&str, 12) == FAIL)
7572 if (! inst.error)
7573 inst.error = BAD_ARGS;
7574 return;
7577 if (skip_past_comma (&str) == FAIL
7578 || fp_op2 (&str) == FAIL)
7580 if (! inst.error)
7581 inst.error = BAD_ARGS;
7582 return;
7585 end_of_line (str);
7586 return;
7589 static void
7590 do_fpa_cmp (str)
7591 char * str;
7593 skip_whitespace (str);
7595 if (fp_reg_required_here (&str, 16) == FAIL)
7597 if (! inst.error)
7598 inst.error = BAD_ARGS;
7599 return;
7602 if (skip_past_comma (&str) == FAIL
7603 || fp_op2 (&str) == FAIL)
7605 if (! inst.error)
7606 inst.error = BAD_ARGS;
7607 return;
7610 end_of_line (str);
7611 return;
7614 static void
7615 do_fpa_from_reg (str)
7616 char * str;
7618 skip_whitespace (str);
7620 if (fp_reg_required_here (&str, 16) == FAIL)
7622 if (! inst.error)
7623 inst.error = BAD_ARGS;
7624 return;
7627 if (skip_past_comma (&str) == FAIL
7628 || reg_required_here (&str, 12) == FAIL)
7630 if (! inst.error)
7631 inst.error = BAD_ARGS;
7632 return;
7635 end_of_line (str);
7636 return;
7639 static void
7640 do_fpa_to_reg (str)
7641 char * str;
7643 skip_whitespace (str);
7645 if (reg_required_here (&str, 12) == FAIL)
7646 return;
7648 if (skip_past_comma (&str) == FAIL
7649 || fp_reg_required_here (&str, 0) == FAIL)
7651 if (! inst.error)
7652 inst.error = BAD_ARGS;
7653 return;
7656 end_of_line (str);
7657 return;
7660 static int
7661 vfp_sp_reg_required_here (str, pos)
7662 char **str;
7663 enum vfp_sp_reg_pos pos;
7665 int reg;
7666 char *start = *str;
7668 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab)) != FAIL)
7670 switch (pos)
7672 case VFP_REG_Sd:
7673 inst.instruction |= ((reg >> 1) << 12) | ((reg & 1) << 22);
7674 break;
7676 case VFP_REG_Sn:
7677 inst.instruction |= ((reg >> 1) << 16) | ((reg & 1) << 7);
7678 break;
7680 case VFP_REG_Sm:
7681 inst.instruction |= ((reg >> 1) << 0) | ((reg & 1) << 5);
7682 break;
7684 default:
7685 abort ();
7687 return reg;
7690 /* In the few cases where we might be able to accept something else
7691 this error can be overridden. */
7692 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
7694 /* Restore the start point. */
7695 *str = start;
7696 return FAIL;
7699 static int
7700 vfp_dp_reg_required_here (str, pos)
7701 char **str;
7702 enum vfp_dp_reg_pos pos;
7704 int reg;
7705 char *start = *str;
7707 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab)) != FAIL)
7709 switch (pos)
7711 case VFP_REG_Dd:
7712 inst.instruction |= reg << 12;
7713 break;
7715 case VFP_REG_Dn:
7716 inst.instruction |= reg << 16;
7717 break;
7719 case VFP_REG_Dm:
7720 inst.instruction |= reg << 0;
7721 break;
7723 default:
7724 abort ();
7726 return reg;
7729 /* In the few cases where we might be able to accept something else
7730 this error can be overridden. */
7731 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
7733 /* Restore the start point. */
7734 *str = start;
7735 return FAIL;
7738 static void
7739 do_vfp_sp_monadic (str)
7740 char *str;
7742 skip_whitespace (str);
7744 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7745 return;
7747 if (skip_past_comma (&str) == FAIL
7748 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
7750 if (! inst.error)
7751 inst.error = BAD_ARGS;
7752 return;
7755 end_of_line (str);
7756 return;
7759 static void
7760 do_vfp_dp_monadic (str)
7761 char *str;
7763 skip_whitespace (str);
7765 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7766 return;
7768 if (skip_past_comma (&str) == FAIL
7769 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7771 if (! inst.error)
7772 inst.error = BAD_ARGS;
7773 return;
7776 end_of_line (str);
7777 return;
7780 static void
7781 do_vfp_sp_dyadic (str)
7782 char *str;
7784 skip_whitespace (str);
7786 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7787 return;
7789 if (skip_past_comma (&str) == FAIL
7790 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL
7791 || skip_past_comma (&str) == FAIL
7792 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
7794 if (! inst.error)
7795 inst.error = BAD_ARGS;
7796 return;
7799 end_of_line (str);
7800 return;
7803 static void
7804 do_vfp_dp_dyadic (str)
7805 char *str;
7807 skip_whitespace (str);
7809 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7810 return;
7812 if (skip_past_comma (&str) == FAIL
7813 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL
7814 || skip_past_comma (&str) == FAIL
7815 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7817 if (! inst.error)
7818 inst.error = BAD_ARGS;
7819 return;
7822 end_of_line (str);
7823 return;
7826 static void
7827 do_vfp_reg_from_sp (str)
7828 char *str;
7830 skip_whitespace (str);
7832 if (reg_required_here (&str, 12) == FAIL)
7833 return;
7835 if (skip_past_comma (&str) == FAIL
7836 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
7838 if (! inst.error)
7839 inst.error = BAD_ARGS;
7840 return;
7843 end_of_line (str);
7844 return;
7847 static void
7848 do_vfp_sp_reg2 (str)
7849 char *str;
7851 skip_whitespace (str);
7853 if (reg_required_here (&str, 12) == FAIL)
7854 return;
7856 if (skip_past_comma (&str) == FAIL
7857 || reg_required_here (&str, 16) == FAIL
7858 || skip_past_comma (&str) == FAIL)
7860 if (! inst.error)
7861 inst.error = BAD_ARGS;
7862 return;
7865 /* We require exactly two consecutive SP registers. */
7866 if (vfp_sp_reg_list (&str, VFP_REG_Sm) != 2)
7868 if (! inst.error)
7869 inst.error = _("only two consecutive VFP SP registers allowed here");
7872 end_of_line (str);
7873 return;
7876 static void
7877 do_vfp_sp_from_reg (str)
7878 char *str;
7880 skip_whitespace (str);
7882 if (vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
7883 return;
7885 if (skip_past_comma (&str) == FAIL
7886 || reg_required_here (&str, 12) == FAIL)
7888 if (! inst.error)
7889 inst.error = BAD_ARGS;
7890 return;
7893 end_of_line (str);
7894 return;
7897 static void
7898 do_vfp_reg_from_dp (str)
7899 char *str;
7901 skip_whitespace (str);
7903 if (reg_required_here (&str, 12) == FAIL)
7904 return;
7906 if (skip_past_comma (&str) == FAIL
7907 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
7909 if (! inst.error)
7910 inst.error = BAD_ARGS;
7911 return;
7914 end_of_line (str);
7915 return;
7918 static void
7919 do_vfp_reg2_from_dp (str)
7920 char *str;
7922 skip_whitespace (str);
7924 if (reg_required_here (&str, 12) == FAIL)
7925 return;
7927 if (skip_past_comma (&str) == FAIL
7928 || reg_required_here (&str, 16) == FAIL
7929 || skip_past_comma (&str) == FAIL
7930 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7932 if (! inst.error)
7933 inst.error = BAD_ARGS;
7934 return;
7937 end_of_line (str);
7938 return;
7941 static void
7942 do_vfp_dp_from_reg (str)
7943 char *str;
7945 skip_whitespace (str);
7947 if (vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
7948 return;
7950 if (skip_past_comma (&str) == FAIL
7951 || reg_required_here (&str, 12) == FAIL)
7953 if (! inst.error)
7954 inst.error = BAD_ARGS;
7955 return;
7958 end_of_line (str);
7959 return;
7962 static void
7963 do_vfp_dp_from_reg2 (str)
7964 char *str;
7966 skip_whitespace (str);
7968 if (vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7969 return;
7971 if (skip_past_comma (&str) == FAIL
7972 || reg_required_here (&str, 12) == FAIL
7973 || skip_past_comma (&str) == FAIL
7974 || reg_required_here (&str, 16))
7976 if (! inst.error)
7977 inst.error = BAD_ARGS;
7978 return;
7981 end_of_line (str);
7982 return;
7985 static const struct vfp_reg *
7986 vfp_psr_parse (str)
7987 char **str;
7989 char *start = *str;
7990 char c;
7991 char *p;
7992 const struct vfp_reg *vreg;
7994 p = start;
7996 /* Find the end of the current token. */
7999 c = *p++;
8001 while (ISALPHA (c));
8003 /* Mark it. */
8004 *--p = 0;
8006 for (vreg = vfp_regs + 0;
8007 vreg < vfp_regs + sizeof (vfp_regs) / sizeof (struct vfp_reg);
8008 vreg++)
8010 if (strcmp (start, vreg->name) == 0)
8012 *p = c;
8013 *str = p;
8014 return vreg;
8018 *p = c;
8019 return NULL;
8022 static int
8023 vfp_psr_required_here (str)
8024 char **str;
8026 char *start = *str;
8027 const struct vfp_reg *vreg;
8029 vreg = vfp_psr_parse (str);
8031 if (vreg)
8033 inst.instruction |= vreg->regno;
8034 return SUCCESS;
8037 inst.error = _("VFP system register expected");
8039 *str = start;
8040 return FAIL;
8043 static void
8044 do_vfp_reg_from_ctrl (str)
8045 char *str;
8047 skip_whitespace (str);
8049 if (reg_required_here (&str, 12) == FAIL)
8050 return;
8052 if (skip_past_comma (&str) == FAIL
8053 || vfp_psr_required_here (&str) == FAIL)
8055 if (! inst.error)
8056 inst.error = BAD_ARGS;
8057 return;
8060 end_of_line (str);
8061 return;
8064 static void
8065 do_vfp_ctrl_from_reg (str)
8066 char *str;
8068 skip_whitespace (str);
8070 if (vfp_psr_required_here (&str) == FAIL)
8071 return;
8073 if (skip_past_comma (&str) == FAIL
8074 || reg_required_here (&str, 12) == FAIL)
8076 if (! inst.error)
8077 inst.error = BAD_ARGS;
8078 return;
8081 end_of_line (str);
8082 return;
8085 static void
8086 do_vfp_sp_ldst (str)
8087 char *str;
8089 skip_whitespace (str);
8091 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8093 if (!inst.error)
8094 inst.error = BAD_ARGS;
8095 return;
8098 if (skip_past_comma (&str) == FAIL
8099 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
8101 if (!inst.error)
8102 inst.error = BAD_ARGS;
8103 return;
8106 end_of_line (str);
8107 return;
8110 static void
8111 do_vfp_dp_ldst (str)
8112 char *str;
8114 skip_whitespace (str);
8116 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8118 if (!inst.error)
8119 inst.error = BAD_ARGS;
8120 return;
8123 if (skip_past_comma (&str) == FAIL
8124 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
8126 if (!inst.error)
8127 inst.error = BAD_ARGS;
8128 return;
8131 end_of_line (str);
8132 return;
8135 /* Parse and encode a VFP SP register list, storing the initial
8136 register in position POS and returning the range as the result. If
8137 the string is invalid return FAIL (an invalid range). */
8138 static long
8139 vfp_sp_reg_list (str, pos)
8140 char **str;
8141 enum vfp_sp_reg_pos pos;
8143 long range = 0;
8144 int base_reg = 0;
8145 int new_base;
8146 long base_bits = 0;
8147 int count = 0;
8148 long tempinst;
8149 unsigned long mask = 0;
8150 int warned = 0;
8152 if (**str != '{')
8153 return FAIL;
8155 (*str)++;
8156 skip_whitespace (*str);
8158 tempinst = inst.instruction;
8162 inst.instruction = 0;
8164 if ((new_base = vfp_sp_reg_required_here (str, pos)) == FAIL)
8165 return FAIL;
8167 if (count == 0 || base_reg > new_base)
8169 base_reg = new_base;
8170 base_bits = inst.instruction;
8173 if (mask & (1 << new_base))
8175 inst.error = _("invalid register list");
8176 return FAIL;
8179 if ((mask >> new_base) != 0 && ! warned)
8181 as_tsktsk (_("register list not in ascending order"));
8182 warned = 1;
8185 mask |= 1 << new_base;
8186 count++;
8188 skip_whitespace (*str);
8190 if (**str == '-') /* We have the start of a range expression */
8192 int high_range;
8194 (*str)++;
8196 if ((high_range
8197 = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab))
8198 == FAIL)
8200 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
8201 return FAIL;
8204 if (high_range <= new_base)
8206 inst.error = _("register range not in ascending order");
8207 return FAIL;
8210 for (new_base++; new_base <= high_range; new_base++)
8212 if (mask & (1 << new_base))
8214 inst.error = _("invalid register list");
8215 return FAIL;
8218 mask |= 1 << new_base;
8219 count++;
8223 while (skip_past_comma (str) != FAIL);
8225 if (**str != '}')
8227 inst.error = _("invalid register list");
8228 return FAIL;
8231 (*str)++;
8233 range = count;
8235 /* Sanity check -- should have raised a parse error above. */
8236 if (count == 0 || count > 32)
8237 abort ();
8239 /* Final test -- the registers must be consecutive. */
8240 while (count--)
8242 if ((mask & (1 << base_reg++)) == 0)
8244 inst.error = _("non-contiguous register range");
8245 return FAIL;
8249 inst.instruction = tempinst | base_bits;
8250 return range;
8253 static long
8254 vfp_dp_reg_list (str)
8255 char **str;
8257 long range = 0;
8258 int base_reg = 0;
8259 int new_base;
8260 int count = 0;
8261 long tempinst;
8262 unsigned long mask = 0;
8263 int warned = 0;
8265 if (**str != '{')
8266 return FAIL;
8268 (*str)++;
8269 skip_whitespace (*str);
8271 tempinst = inst.instruction;
8275 inst.instruction = 0;
8277 if ((new_base = vfp_dp_reg_required_here (str, VFP_REG_Dd)) == FAIL)
8278 return FAIL;
8280 if (count == 0 || base_reg > new_base)
8282 base_reg = new_base;
8283 range = inst.instruction;
8286 if (mask & (1 << new_base))
8288 inst.error = _("invalid register list");
8289 return FAIL;
8292 if ((mask >> new_base) != 0 && ! warned)
8294 as_tsktsk (_("register list not in ascending order"));
8295 warned = 1;
8298 mask |= 1 << new_base;
8299 count++;
8301 skip_whitespace (*str);
8303 if (**str == '-') /* We have the start of a range expression */
8305 int high_range;
8307 (*str)++;
8309 if ((high_range
8310 = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab))
8311 == FAIL)
8313 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
8314 return FAIL;
8317 if (high_range <= new_base)
8319 inst.error = _("register range not in ascending order");
8320 return FAIL;
8323 for (new_base++; new_base <= high_range; new_base++)
8325 if (mask & (1 << new_base))
8327 inst.error = _("invalid register list");
8328 return FAIL;
8331 mask |= 1 << new_base;
8332 count++;
8336 while (skip_past_comma (str) != FAIL);
8338 if (**str != '}')
8340 inst.error = _("invalid register list");
8341 return FAIL;
8344 (*str)++;
8346 range |= 2 * count;
8348 /* Sanity check -- should have raised a parse error above. */
8349 if (count == 0 || count > 16)
8350 abort ();
8352 /* Final test -- the registers must be consecutive. */
8353 while (count--)
8355 if ((mask & (1 << base_reg++)) == 0)
8357 inst.error = _("non-contiguous register range");
8358 return FAIL;
8362 inst.instruction = tempinst;
8363 return range;
8366 static void
8367 vfp_sp_ldstm (str, ldstm_type)
8368 char *str;
8369 enum vfp_ldstm_type ldstm_type;
8371 long range;
8373 skip_whitespace (str);
8375 if (reg_required_here (&str, 16) == FAIL)
8376 return;
8378 skip_whitespace (str);
8380 if (*str == '!')
8382 inst.instruction |= WRITE_BACK;
8383 str++;
8385 else if (ldstm_type != VFP_LDSTMIA)
8387 inst.error = _("this addressing mode requires base-register writeback");
8388 return;
8391 if (skip_past_comma (&str) == FAIL
8392 || (range = vfp_sp_reg_list (&str, VFP_REG_Sd)) == FAIL)
8394 if (!inst.error)
8395 inst.error = BAD_ARGS;
8396 return;
8399 inst.instruction |= range;
8400 end_of_line (str);
8403 static void
8404 vfp_dp_ldstm (str, ldstm_type)
8405 char *str;
8406 enum vfp_ldstm_type ldstm_type;
8408 long range;
8410 skip_whitespace (str);
8412 if (reg_required_here (&str, 16) == FAIL)
8413 return;
8415 skip_whitespace (str);
8417 if (*str == '!')
8419 inst.instruction |= WRITE_BACK;
8420 str++;
8422 else if (ldstm_type != VFP_LDSTMIA && ldstm_type != VFP_LDSTMIAX)
8424 inst.error = _("this addressing mode requires base-register writeback");
8425 return;
8428 if (skip_past_comma (&str) == FAIL
8429 || (range = vfp_dp_reg_list (&str)) == FAIL)
8431 if (!inst.error)
8432 inst.error = BAD_ARGS;
8433 return;
8436 if (ldstm_type == VFP_LDSTMIAX || ldstm_type == VFP_LDSTMDBX)
8437 range += 1;
8439 inst.instruction |= range;
8440 end_of_line (str);
8443 static void
8444 do_vfp_sp_ldstmia (str)
8445 char *str;
8447 vfp_sp_ldstm (str, VFP_LDSTMIA);
8450 static void
8451 do_vfp_sp_ldstmdb (str)
8452 char *str;
8454 vfp_sp_ldstm (str, VFP_LDSTMDB);
8457 static void
8458 do_vfp_dp_ldstmia (str)
8459 char *str;
8461 vfp_dp_ldstm (str, VFP_LDSTMIA);
8464 static void
8465 do_vfp_dp_ldstmdb (str)
8466 char *str;
8468 vfp_dp_ldstm (str, VFP_LDSTMDB);
8471 static void
8472 do_vfp_xp_ldstmia (str)
8473 char *str;
8475 vfp_dp_ldstm (str, VFP_LDSTMIAX);
8478 static void
8479 do_vfp_xp_ldstmdb (str)
8480 char *str;
8482 vfp_dp_ldstm (str, VFP_LDSTMDBX);
8485 static void
8486 do_vfp_sp_compare_z (str)
8487 char *str;
8489 skip_whitespace (str);
8491 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8493 if (!inst.error)
8494 inst.error = BAD_ARGS;
8495 return;
8498 end_of_line (str);
8499 return;
8502 static void
8503 do_vfp_dp_compare_z (str)
8504 char *str;
8506 skip_whitespace (str);
8508 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8510 if (!inst.error)
8511 inst.error = BAD_ARGS;
8512 return;
8515 end_of_line (str);
8516 return;
8519 static void
8520 do_vfp_dp_sp_cvt (str)
8521 char *str;
8523 skip_whitespace (str);
8525 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8526 return;
8528 if (skip_past_comma (&str) == FAIL
8529 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
8531 if (! inst.error)
8532 inst.error = BAD_ARGS;
8533 return;
8536 end_of_line (str);
8537 return;
8540 static void
8541 do_vfp_sp_dp_cvt (str)
8542 char *str;
8544 skip_whitespace (str);
8546 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8547 return;
8549 if (skip_past_comma (&str) == FAIL
8550 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8552 if (! inst.error)
8553 inst.error = BAD_ARGS;
8554 return;
8557 end_of_line (str);
8558 return;
8561 /* Thumb specific routines. */
8563 /* Parse and validate that a register is of the right form, this saves
8564 repeated checking of this information in many similar cases.
8565 Unlike the 32-bit case we do not insert the register into the opcode
8566 here, since the position is often unknown until the full instruction
8567 has been parsed. */
8569 static int
8570 thumb_reg (strp, hi_lo)
8571 char ** strp;
8572 int hi_lo;
8574 int reg;
8576 if ((reg = reg_required_here (strp, -1)) == FAIL)
8577 return FAIL;
8579 switch (hi_lo)
8581 case THUMB_REG_LO:
8582 if (reg > 7)
8584 inst.error = _("lo register required");
8585 return FAIL;
8587 break;
8589 case THUMB_REG_HI:
8590 if (reg < 8)
8592 inst.error = _("hi register required");
8593 return FAIL;
8595 break;
8597 default:
8598 break;
8601 return reg;
8604 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
8605 was SUB. */
8607 static void
8608 thumb_add_sub (str, subtract)
8609 char * str;
8610 int subtract;
8612 int Rd, Rs, Rn = FAIL;
8614 skip_whitespace (str);
8616 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
8617 || skip_past_comma (&str) == FAIL)
8619 if (! inst.error)
8620 inst.error = BAD_ARGS;
8621 return;
8624 if (is_immediate_prefix (*str))
8626 Rs = Rd;
8627 str++;
8628 if (my_get_expression (&inst.reloc.exp, &str))
8629 return;
8631 else
8633 if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8634 return;
8636 if (skip_past_comma (&str) == FAIL)
8638 /* Two operand format, shuffle the registers
8639 and pretend there are 3. */
8640 Rn = Rs;
8641 Rs = Rd;
8643 else if (is_immediate_prefix (*str))
8645 str++;
8646 if (my_get_expression (&inst.reloc.exp, &str))
8647 return;
8649 else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8650 return;
8653 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8654 for the latter case, EXPR contains the immediate that was found. */
8655 if (Rn != FAIL)
8657 /* All register format. */
8658 if (Rd > 7 || Rs > 7 || Rn > 7)
8660 if (Rs != Rd)
8662 inst.error = _("dest and source1 must be the same register");
8663 return;
8666 /* Can't do this for SUB. */
8667 if (subtract)
8669 inst.error = _("subtract valid only on lo regs");
8670 return;
8673 inst.instruction = (T_OPCODE_ADD_HI
8674 | (Rd > 7 ? THUMB_H1 : 0)
8675 | (Rn > 7 ? THUMB_H2 : 0));
8676 inst.instruction |= (Rd & 7) | ((Rn & 7) << 3);
8678 else
8680 inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3;
8681 inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
8684 else
8686 /* Immediate expression, now things start to get nasty. */
8688 /* First deal with HI regs, only very restricted cases allowed:
8689 Adjusting SP, and using PC or SP to get an address. */
8690 if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP))
8691 || (Rs > 7 && Rs != REG_SP && Rs != REG_PC))
8693 inst.error = _("invalid Hi register with immediate");
8694 return;
8697 if (inst.reloc.exp.X_op != O_constant)
8699 /* Value isn't known yet, all we can do is store all the fragments
8700 we know about in the instruction and let the reloc hacking
8701 work it all out. */
8702 inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs;
8703 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
8705 else
8707 int offset = inst.reloc.exp.X_add_number;
8709 if (subtract)
8710 offset = - offset;
8712 if (offset < 0)
8714 offset = - offset;
8715 subtract = 1;
8717 /* Quick check, in case offset is MIN_INT. */
8718 if (offset < 0)
8720 inst.error = _("immediate value out of range");
8721 return;
8724 /* Note - you cannot convert a subtract of 0 into an
8725 add of 0 because the carry flag is set differently. */
8726 else if (offset > 0)
8727 subtract = 0;
8729 if (Rd == REG_SP)
8731 if (offset & ~0x1fc)
8733 inst.error = _("invalid immediate value for stack adjust");
8734 return;
8736 inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
8737 inst.instruction |= offset >> 2;
8739 else if (Rs == REG_PC || Rs == REG_SP)
8741 if (subtract
8742 || (offset & ~0x3fc))
8744 inst.error = _("invalid immediate for address calculation");
8745 return;
8747 inst.instruction = (Rs == REG_PC ? T_OPCODE_ADD_PC
8748 : T_OPCODE_ADD_SP);
8749 inst.instruction |= (Rd << 8) | (offset >> 2);
8751 else if (Rs == Rd)
8753 if (offset & ~0xff)
8755 inst.error = _("immediate value out of range");
8756 return;
8758 inst.instruction = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
8759 inst.instruction |= (Rd << 8) | offset;
8761 else
8763 if (offset & ~0x7)
8765 inst.error = _("immediate value out of range");
8766 return;
8768 inst.instruction = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
8769 inst.instruction |= Rd | (Rs << 3) | (offset << 6);
8774 end_of_line (str);
8777 static void
8778 thumb_shift (str, shift)
8779 char * str;
8780 int shift;
8782 int Rd, Rs, Rn = FAIL;
8784 skip_whitespace (str);
8786 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8787 || skip_past_comma (&str) == FAIL)
8789 if (! inst.error)
8790 inst.error = BAD_ARGS;
8791 return;
8794 if (is_immediate_prefix (*str))
8796 /* Two operand immediate format, set Rs to Rd. */
8797 Rs = Rd;
8798 str ++;
8799 if (my_get_expression (&inst.reloc.exp, &str))
8800 return;
8802 else
8804 if ((Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8805 return;
8807 if (skip_past_comma (&str) == FAIL)
8809 /* Two operand format, shuffle the registers
8810 and pretend there are 3. */
8811 Rn = Rs;
8812 Rs = Rd;
8814 else if (is_immediate_prefix (*str))
8816 str++;
8817 if (my_get_expression (&inst.reloc.exp, &str))
8818 return;
8820 else if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8821 return;
8824 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8825 for the latter case, EXPR contains the immediate that was found. */
8827 if (Rn != FAIL)
8829 if (Rs != Rd)
8831 inst.error = _("source1 and dest must be same register");
8832 return;
8835 switch (shift)
8837 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_R; break;
8838 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_R; break;
8839 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_R; break;
8842 inst.instruction |= Rd | (Rn << 3);
8844 else
8846 switch (shift)
8848 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_I; break;
8849 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_I; break;
8850 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_I; break;
8853 if (inst.reloc.exp.X_op != O_constant)
8855 /* Value isn't known yet, create a dummy reloc and let reloc
8856 hacking fix it up. */
8857 inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
8859 else
8861 unsigned shift_value = inst.reloc.exp.X_add_number;
8863 if (shift_value > 32 || (shift_value == 32 && shift == THUMB_LSL))
8865 inst.error = _("invalid immediate for shift");
8866 return;
8869 /* Shifts of zero are handled by converting to LSL. */
8870 if (shift_value == 0)
8871 inst.instruction = T_OPCODE_LSL_I;
8873 /* Shifts of 32 are encoded as a shift of zero. */
8874 if (shift_value == 32)
8875 shift_value = 0;
8877 inst.instruction |= shift_value << 6;
8880 inst.instruction |= Rd | (Rs << 3);
8883 end_of_line (str);
8886 static void
8887 thumb_mov_compare (str, move)
8888 char * str;
8889 int move;
8891 int Rd, Rs = FAIL;
8893 skip_whitespace (str);
8895 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
8896 || skip_past_comma (&str) == FAIL)
8898 if (! inst.error)
8899 inst.error = BAD_ARGS;
8900 return;
8903 if (is_immediate_prefix (*str))
8905 str++;
8906 if (my_get_expression (&inst.reloc.exp, &str))
8907 return;
8909 else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8910 return;
8912 if (Rs != FAIL)
8914 if (Rs < 8 && Rd < 8)
8916 if (move == THUMB_MOVE)
8917 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
8918 since a MOV instruction produces unpredictable results. */
8919 inst.instruction = T_OPCODE_ADD_I3;
8920 else
8921 inst.instruction = T_OPCODE_CMP_LR;
8922 inst.instruction |= Rd | (Rs << 3);
8924 else
8926 if (move == THUMB_MOVE)
8927 inst.instruction = T_OPCODE_MOV_HR;
8928 else
8929 inst.instruction = T_OPCODE_CMP_HR;
8931 if (Rd > 7)
8932 inst.instruction |= THUMB_H1;
8934 if (Rs > 7)
8935 inst.instruction |= THUMB_H2;
8937 inst.instruction |= (Rd & 7) | ((Rs & 7) << 3);
8940 else
8942 if (Rd > 7)
8944 inst.error = _("only lo regs allowed with immediate");
8945 return;
8948 if (move == THUMB_MOVE)
8949 inst.instruction = T_OPCODE_MOV_I8;
8950 else
8951 inst.instruction = T_OPCODE_CMP_I8;
8953 inst.instruction |= Rd << 8;
8955 if (inst.reloc.exp.X_op != O_constant)
8956 inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
8957 else
8959 unsigned value = inst.reloc.exp.X_add_number;
8961 if (value > 255)
8963 inst.error = _("invalid immediate");
8964 return;
8967 inst.instruction |= value;
8971 end_of_line (str);
8974 static void
8975 thumb_load_store (str, load_store, size)
8976 char * str;
8977 int load_store;
8978 int size;
8980 int Rd, Rb, Ro = FAIL;
8982 skip_whitespace (str);
8984 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8985 || skip_past_comma (&str) == FAIL)
8987 if (! inst.error)
8988 inst.error = BAD_ARGS;
8989 return;
8992 if (*str == '[')
8994 str++;
8995 if ((Rb = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8996 return;
8998 if (skip_past_comma (&str) != FAIL)
9000 if (is_immediate_prefix (*str))
9002 str++;
9003 if (my_get_expression (&inst.reloc.exp, &str))
9004 return;
9006 else if ((Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9007 return;
9009 else
9011 inst.reloc.exp.X_op = O_constant;
9012 inst.reloc.exp.X_add_number = 0;
9015 if (*str != ']')
9017 inst.error = _("expected ']'");
9018 return;
9020 str++;
9022 else if (*str == '=')
9024 if (load_store != THUMB_LOAD)
9026 inst.error = _("invalid pseudo operation");
9027 return;
9030 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
9031 str++;
9033 skip_whitespace (str);
9035 if (my_get_expression (& inst.reloc.exp, & str))
9036 return;
9038 end_of_line (str);
9040 if ( inst.reloc.exp.X_op != O_constant
9041 && inst.reloc.exp.X_op != O_symbol)
9043 inst.error = "Constant expression expected";
9044 return;
9047 if (inst.reloc.exp.X_op == O_constant
9048 && ((inst.reloc.exp.X_add_number & ~0xFF) == 0))
9050 /* This can be done with a mov instruction. */
9052 inst.instruction = T_OPCODE_MOV_I8 | (Rd << 8);
9053 inst.instruction |= inst.reloc.exp.X_add_number;
9054 return;
9057 /* Insert into literal pool. */
9058 if (add_to_lit_pool () == FAIL)
9060 if (!inst.error)
9061 inst.error = "literal pool insertion failed";
9062 return;
9065 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
9066 inst.reloc.pc_rel = 1;
9067 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
9068 /* Adjust ARM pipeline offset to Thumb. */
9069 inst.reloc.exp.X_add_number += 4;
9071 return;
9073 else
9075 if (my_get_expression (&inst.reloc.exp, &str))
9076 return;
9078 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
9079 inst.reloc.pc_rel = 1;
9080 inst.reloc.exp.X_add_number -= 4; /* Pipeline offset. */
9081 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
9082 end_of_line (str);
9083 return;
9086 if (Rb == REG_PC || Rb == REG_SP)
9088 if (size != THUMB_WORD)
9090 inst.error = _("byte or halfword not valid for base register");
9091 return;
9093 else if (Rb == REG_PC && load_store != THUMB_LOAD)
9095 inst.error = _("r15 based store not allowed");
9096 return;
9098 else if (Ro != FAIL)
9100 inst.error = _("invalid base register for register offset");
9101 return;
9104 if (Rb == REG_PC)
9105 inst.instruction = T_OPCODE_LDR_PC;
9106 else if (load_store == THUMB_LOAD)
9107 inst.instruction = T_OPCODE_LDR_SP;
9108 else
9109 inst.instruction = T_OPCODE_STR_SP;
9111 inst.instruction |= Rd << 8;
9112 if (inst.reloc.exp.X_op == O_constant)
9114 unsigned offset = inst.reloc.exp.X_add_number;
9116 if (offset & ~0x3fc)
9118 inst.error = _("invalid offset");
9119 return;
9122 inst.instruction |= offset >> 2;
9124 else
9125 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
9127 else if (Rb > 7)
9129 inst.error = _("invalid base register in load/store");
9130 return;
9132 else if (Ro == FAIL)
9134 /* Immediate offset. */
9135 if (size == THUMB_WORD)
9136 inst.instruction = (load_store == THUMB_LOAD
9137 ? T_OPCODE_LDR_IW : T_OPCODE_STR_IW);
9138 else if (size == THUMB_HALFWORD)
9139 inst.instruction = (load_store == THUMB_LOAD
9140 ? T_OPCODE_LDR_IH : T_OPCODE_STR_IH);
9141 else
9142 inst.instruction = (load_store == THUMB_LOAD
9143 ? T_OPCODE_LDR_IB : T_OPCODE_STR_IB);
9145 inst.instruction |= Rd | (Rb << 3);
9147 if (inst.reloc.exp.X_op == O_constant)
9149 unsigned offset = inst.reloc.exp.X_add_number;
9151 if (offset & ~(0x1f << size))
9153 inst.error = _("invalid offset");
9154 return;
9156 inst.instruction |= (offset >> size) << 6;
9158 else
9159 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
9161 else
9163 /* Register offset. */
9164 if (size == THUMB_WORD)
9165 inst.instruction = (load_store == THUMB_LOAD
9166 ? T_OPCODE_LDR_RW : T_OPCODE_STR_RW);
9167 else if (size == THUMB_HALFWORD)
9168 inst.instruction = (load_store == THUMB_LOAD
9169 ? T_OPCODE_LDR_RH : T_OPCODE_STR_RH);
9170 else
9171 inst.instruction = (load_store == THUMB_LOAD
9172 ? T_OPCODE_LDR_RB : T_OPCODE_STR_RB);
9174 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
9177 end_of_line (str);
9180 /* A register must be given at this point.
9182 Shift is the place to put it in inst.instruction.
9184 Restores input start point on err.
9185 Returns the reg#, or FAIL. */
9187 static int
9188 mav_reg_required_here (str, shift, regtype)
9189 char ** str;
9190 int shift;
9191 enum arm_reg_type regtype;
9193 int reg;
9194 char *start = *str;
9196 if ((reg = arm_reg_parse (str, all_reg_maps[regtype].htab)) != FAIL)
9198 if (shift >= 0)
9199 inst.instruction |= reg << shift;
9201 return reg;
9204 /* Restore the start point. */
9205 *str = start;
9207 /* In the few cases where we might be able to accept something else
9208 this error can be overridden. */
9209 inst.error = _(all_reg_maps[regtype].expected);
9211 return FAIL;
9214 /* Cirrus Maverick Instructions. */
9216 /* Wrapper functions. */
9218 static void
9219 do_mav_binops_1a (str)
9220 char * str;
9222 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVF);
9225 static void
9226 do_mav_binops_1b (str)
9227 char * str;
9229 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVD);
9232 static void
9233 do_mav_binops_1c (str)
9234 char * str;
9236 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVDX);
9239 static void
9240 do_mav_binops_1d (str)
9241 char * str;
9243 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVF);
9246 static void
9247 do_mav_binops_1e (str)
9248 char * str;
9250 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVD);
9253 static void
9254 do_mav_binops_1f (str)
9255 char * str;
9257 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVF);
9260 static void
9261 do_mav_binops_1g (str)
9262 char * str;
9264 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVD);
9267 static void
9268 do_mav_binops_1h (str)
9269 char * str;
9271 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVFX);
9274 static void
9275 do_mav_binops_1i (str)
9276 char * str;
9278 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVFX);
9281 static void
9282 do_mav_binops_1j (str)
9283 char * str;
9285 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVDX);
9288 static void
9289 do_mav_binops_1k (str)
9290 char * str;
9292 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVDX);
9295 static void
9296 do_mav_binops_1l (str)
9297 char * str;
9299 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVF);
9302 static void
9303 do_mav_binops_1m (str)
9304 char * str;
9306 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVD);
9309 static void
9310 do_mav_binops_1n (str)
9311 char * str;
9313 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVFX);
9316 static void
9317 do_mav_binops_1o (str)
9318 char * str;
9320 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVDX, REG_TYPE_MVDX);
9323 static void
9324 do_mav_binops_2a (str)
9325 char * str;
9327 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVF, REG_TYPE_RN);
9330 static void
9331 do_mav_binops_2b (str)
9332 char * str;
9334 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVD, REG_TYPE_RN);
9337 static void
9338 do_mav_binops_2c (str)
9339 char * str;
9341 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVDX, REG_TYPE_RN);
9344 static void
9345 do_mav_binops_3a (str)
9346 char * str;
9348 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVFX);
9351 static void
9352 do_mav_binops_3b (str)
9353 char * str;
9355 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVFX, REG_TYPE_MVAX);
9358 static void
9359 do_mav_binops_3c (str)
9360 char * str;
9362 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVDX);
9365 static void
9366 do_mav_binops_3d (str)
9367 char * str;
9369 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVDX, REG_TYPE_MVAX);
9372 static void
9373 do_mav_triple_4a (str)
9374 char * str;
9376 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_RN);
9379 static void
9380 do_mav_triple_4b (str)
9381 char * str;
9383 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_RN);
9386 static void
9387 do_mav_triple_5a (str)
9388 char * str;
9390 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVF, REG_TYPE_MVF);
9393 static void
9394 do_mav_triple_5b (str)
9395 char * str;
9397 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVD, REG_TYPE_MVD);
9400 static void
9401 do_mav_triple_5c (str)
9402 char * str;
9404 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVFX, REG_TYPE_MVFX);
9407 static void
9408 do_mav_triple_5d (str)
9409 char * str;
9411 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVDX, REG_TYPE_MVDX);
9414 static void
9415 do_mav_triple_5e (str)
9416 char * str;
9418 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVF, REG_TYPE_MVF, REG_TYPE_MVF);
9421 static void
9422 do_mav_triple_5f (str)
9423 char * str;
9425 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVD, REG_TYPE_MVD, REG_TYPE_MVD);
9428 static void
9429 do_mav_triple_5g (str)
9430 char * str;
9432 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_MVFX);
9435 static void
9436 do_mav_triple_5h (str)
9437 char * str;
9439 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_MVDX);
9442 static void
9443 do_mav_quad_6a (str)
9444 char * str;
9446 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVFX, REG_TYPE_MVFX,
9447 REG_TYPE_MVFX);
9450 static void
9451 do_mav_quad_6b (str)
9452 char * str;
9454 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVAX, REG_TYPE_MVFX,
9455 REG_TYPE_MVFX);
9458 /* cfmvsc32<cond> DSPSC,MVFX[15:0]. */
9459 static void
9460 do_mav_dspsc_1 (str)
9461 char * str;
9463 skip_whitespace (str);
9465 /* cfmvsc32. */
9466 if (mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL
9467 || skip_past_comma (&str) == FAIL
9468 || mav_reg_required_here (&str, 16, REG_TYPE_MVFX) == FAIL)
9470 if (!inst.error)
9471 inst.error = BAD_ARGS;
9473 return;
9476 end_of_line (str);
9479 /* cfmv32sc<cond> MVFX[15:0],DSPSC. */
9480 static void
9481 do_mav_dspsc_2 (str)
9482 char * str;
9484 skip_whitespace (str);
9486 /* cfmv32sc. */
9487 if (mav_reg_required_here (&str, 0, REG_TYPE_MVFX) == FAIL
9488 || skip_past_comma (&str) == FAIL
9489 || mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL)
9491 if (!inst.error)
9492 inst.error = BAD_ARGS;
9494 return;
9497 end_of_line (str);
9500 static void
9501 do_mav_shift_1 (str)
9502 char * str;
9504 do_mav_shift (str, REG_TYPE_MVFX, REG_TYPE_MVFX);
9507 static void
9508 do_mav_shift_2 (str)
9509 char * str;
9511 do_mav_shift (str, REG_TYPE_MVDX, REG_TYPE_MVDX);
9514 static void
9515 do_mav_ldst_1 (str)
9516 char * str;
9518 do_mav_ldst (str, REG_TYPE_MVF);
9521 static void
9522 do_mav_ldst_2 (str)
9523 char * str;
9525 do_mav_ldst (str, REG_TYPE_MVD);
9528 static void
9529 do_mav_ldst_3 (str)
9530 char * str;
9532 do_mav_ldst (str, REG_TYPE_MVFX);
9535 static void
9536 do_mav_ldst_4 (str)
9537 char * str;
9539 do_mav_ldst (str, REG_TYPE_MVDX);
9542 /* Isnsn like "foo X,Y". */
9544 static void
9545 do_mav_binops (str, mode, reg0, reg1)
9546 char * str;
9547 int mode;
9548 enum arm_reg_type reg0;
9549 enum arm_reg_type reg1;
9551 int shift0, shift1;
9553 shift0 = mode & 0xff;
9554 shift1 = (mode >> 8) & 0xff;
9556 skip_whitespace (str);
9558 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
9559 || skip_past_comma (&str) == FAIL
9560 || mav_reg_required_here (&str, shift1, reg1) == FAIL)
9562 if (!inst.error)
9563 inst.error = BAD_ARGS;
9565 else
9566 end_of_line (str);
9569 /* Isnsn like "foo X,Y,Z". */
9571 static void
9572 do_mav_triple (str, mode, reg0, reg1, reg2)
9573 char * str;
9574 int mode;
9575 enum arm_reg_type reg0;
9576 enum arm_reg_type reg1;
9577 enum arm_reg_type reg2;
9579 int shift0, shift1, shift2;
9581 shift0 = mode & 0xff;
9582 shift1 = (mode >> 8) & 0xff;
9583 shift2 = (mode >> 16) & 0xff;
9585 skip_whitespace (str);
9587 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
9588 || skip_past_comma (&str) == FAIL
9589 || mav_reg_required_here (&str, shift1, reg1) == FAIL
9590 || skip_past_comma (&str) == FAIL
9591 || mav_reg_required_here (&str, shift2, reg2) == FAIL)
9593 if (!inst.error)
9594 inst.error = BAD_ARGS;
9596 else
9597 end_of_line (str);
9600 /* Isnsn like "foo W,X,Y,Z".
9601 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
9603 static void
9604 do_mav_quad (str, mode, reg0, reg1, reg2, reg3)
9605 char * str;
9606 int mode;
9607 enum arm_reg_type reg0;
9608 enum arm_reg_type reg1;
9609 enum arm_reg_type reg2;
9610 enum arm_reg_type reg3;
9612 int shift0, shift1, shift2, shift3;
9614 shift0= mode & 0xff;
9615 shift1 = (mode >> 8) & 0xff;
9616 shift2 = (mode >> 16) & 0xff;
9617 shift3 = (mode >> 24) & 0xff;
9619 skip_whitespace (str);
9621 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
9622 || skip_past_comma (&str) == FAIL
9623 || mav_reg_required_here (&str, shift1, reg1) == FAIL
9624 || skip_past_comma (&str) == FAIL
9625 || mav_reg_required_here (&str, shift2, reg2) == FAIL
9626 || skip_past_comma (&str) == FAIL
9627 || mav_reg_required_here (&str, shift3, reg3) == FAIL)
9629 if (!inst.error)
9630 inst.error = BAD_ARGS;
9632 else
9633 end_of_line (str);
9636 /* Maverick shift immediate instructions.
9637 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
9638 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
9640 static void
9641 do_mav_shift (str, reg0, reg1)
9642 char * str;
9643 enum arm_reg_type reg0;
9644 enum arm_reg_type reg1;
9646 int error;
9647 int imm, neg = 0;
9649 skip_whitespace (str);
9651 error = 0;
9653 if (mav_reg_required_here (&str, 12, reg0) == FAIL
9654 || skip_past_comma (&str) == FAIL
9655 || mav_reg_required_here (&str, 16, reg1) == FAIL
9656 || skip_past_comma (&str) == FAIL)
9658 if (!inst.error)
9659 inst.error = BAD_ARGS;
9660 return;
9663 /* Calculate the immediate operand.
9664 The operand is a 7bit signed number. */
9665 skip_whitespace (str);
9667 if (*str == '#')
9668 ++str;
9670 if (!ISDIGIT (*str) && *str != '-')
9672 inst.error = _("expecting immediate, 7bit operand");
9673 return;
9676 if (*str == '-')
9678 neg = 1;
9679 ++str;
9682 for (imm = 0; *str && ISDIGIT (*str); ++str)
9683 imm = imm * 10 + *str - '0';
9685 if (imm > 64)
9687 inst.error = _("immediate out of range");
9688 return;
9691 /* Make negative imm's into 7bit signed numbers. */
9692 if (neg)
9694 imm = -imm;
9695 imm &= 0x0000007f;
9698 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
9699 Bits 5-7 of the insn should have bits 4-6 of the immediate.
9700 Bit 4 should be 0. */
9701 imm = (imm & 0xf) | ((imm & 0x70) << 1);
9703 inst.instruction |= imm;
9704 end_of_line (str);
9707 static int
9708 mav_parse_offset (str, negative)
9709 char ** str;
9710 int *negative;
9712 char * p = *str;
9713 int offset;
9715 *negative = 0;
9717 skip_whitespace (p);
9719 if (*p == '#')
9720 ++p;
9722 if (*p == '-')
9724 *negative = 1;
9725 ++p;
9728 if (!ISDIGIT (*p))
9730 inst.error = _("offset expected");
9731 return 0;
9734 for (offset = 0; *p && ISDIGIT (*p); ++p)
9735 offset = offset * 10 + *p - '0';
9737 if (offset > 0xff)
9739 inst.error = _("offset out of range");
9740 return 0;
9743 *str = p;
9745 return *negative ? -offset : offset;
9748 /* Maverick load/store instructions.
9749 <insn><cond> CRd,[Rn,<offset>]{!}.
9750 <insn><cond> CRd,[Rn],<offset>. */
9752 static void
9753 do_mav_ldst (str, reg0)
9754 char * str;
9755 enum arm_reg_type reg0;
9757 int offset, negative;
9759 skip_whitespace (str);
9761 if (mav_reg_required_here (&str, 12, reg0) == FAIL
9762 || skip_past_comma (&str) == FAIL
9763 || *str++ != '['
9764 || reg_required_here (&str, 16) == FAIL)
9765 goto fail_ldst;
9767 if (skip_past_comma (&str) == SUCCESS)
9769 /* You are here: "<offset>]{!}". */
9770 inst.instruction |= PRE_INDEX;
9772 offset = mav_parse_offset (&str, &negative);
9774 if (inst.error)
9775 return;
9777 if (*str++ != ']')
9779 inst.error = _("missing ]");
9780 return;
9783 if (*str == '!')
9785 inst.instruction |= WRITE_BACK;
9786 ++str;
9789 else
9791 /* You are here: "], <offset>". */
9792 if (*str++ != ']')
9794 inst.error = _("missing ]");
9795 return;
9798 if (skip_past_comma (&str) == FAIL
9799 || (offset = mav_parse_offset (&str, &negative), inst.error))
9800 goto fail_ldst;
9802 inst.instruction |= CP_T_WB; /* Post indexed, set bit W. */
9805 if (negative)
9806 offset = -offset;
9807 else
9808 inst.instruction |= CP_T_UD; /* Postive, so set bit U. */
9810 inst.instruction |= offset >> 2;
9811 end_of_line (str);
9812 return;
9814 fail_ldst:
9815 if (!inst.error)
9816 inst.error = BAD_ARGS;
9817 return;
9820 static void
9821 do_t_nop (str)
9822 char * str;
9824 /* Do nothing. */
9825 end_of_line (str);
9826 return;
9829 /* Handle the Format 4 instructions that do not have equivalents in other
9830 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
9831 BIC and MVN. */
9833 static void
9834 do_t_arit (str)
9835 char * str;
9837 int Rd, Rs, Rn;
9839 skip_whitespace (str);
9841 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9842 || skip_past_comma (&str) == FAIL
9843 || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9845 inst.error = BAD_ARGS;
9846 return;
9849 if (skip_past_comma (&str) != FAIL)
9851 /* Three operand format not allowed for TST, CMN, NEG and MVN.
9852 (It isn't allowed for CMP either, but that isn't handled by this
9853 function.) */
9854 if (inst.instruction == T_OPCODE_TST
9855 || inst.instruction == T_OPCODE_CMN
9856 || inst.instruction == T_OPCODE_NEG
9857 || inst.instruction == T_OPCODE_MVN)
9859 inst.error = BAD_ARGS;
9860 return;
9863 if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9864 return;
9866 if (Rs != Rd)
9868 inst.error = _("dest and source1 must be the same register");
9869 return;
9871 Rs = Rn;
9874 if (inst.instruction == T_OPCODE_MUL
9875 && Rs == Rd)
9876 as_tsktsk (_("Rs and Rd must be different in MUL"));
9878 inst.instruction |= Rd | (Rs << 3);
9879 end_of_line (str);
9882 static void
9883 do_t_add (str)
9884 char * str;
9886 thumb_add_sub (str, 0);
9889 static void
9890 do_t_asr (str)
9891 char * str;
9893 thumb_shift (str, THUMB_ASR);
9896 static void
9897 do_t_branch9 (str)
9898 char * str;
9900 if (my_get_expression (&inst.reloc.exp, &str))
9901 return;
9902 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
9903 inst.reloc.pc_rel = 1;
9904 end_of_line (str);
9907 static void
9908 do_t_branch12 (str)
9909 char * str;
9911 if (my_get_expression (&inst.reloc.exp, &str))
9912 return;
9913 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
9914 inst.reloc.pc_rel = 1;
9915 end_of_line (str);
9918 /* Find the real, Thumb encoded start of a Thumb function. */
9920 static symbolS *
9921 find_real_start (symbolP)
9922 symbolS * symbolP;
9924 char * real_start;
9925 const char * name = S_GET_NAME (symbolP);
9926 symbolS * new_target;
9928 /* This definiton must agree with the one in gcc/config/arm/thumb.c. */
9929 #define STUB_NAME ".real_start_of"
9931 if (name == NULL)
9932 abort ();
9934 /* Names that start with '.' are local labels, not function entry points.
9935 The compiler may generate BL instructions to these labels because it
9936 needs to perform a branch to a far away location. */
9937 if (name[0] == '.')
9938 return symbolP;
9940 real_start = malloc (strlen (name) + strlen (STUB_NAME) + 1);
9941 sprintf (real_start, "%s%s", STUB_NAME, name);
9943 new_target = symbol_find (real_start);
9945 if (new_target == NULL)
9947 as_warn ("Failed to find real start of function: %s\n", name);
9948 new_target = symbolP;
9951 free (real_start);
9953 return new_target;
9956 static void
9957 do_t_branch23 (str)
9958 char * str;
9960 if (my_get_expression (& inst.reloc.exp, & str))
9961 return;
9963 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH23;
9964 inst.reloc.pc_rel = 1;
9965 end_of_line (str);
9967 /* If the destination of the branch is a defined symbol which does not have
9968 the THUMB_FUNC attribute, then we must be calling a function which has
9969 the (interfacearm) attribute. We look for the Thumb entry point to that
9970 function and change the branch to refer to that function instead. */
9971 if ( inst.reloc.exp.X_op == O_symbol
9972 && inst.reloc.exp.X_add_symbol != NULL
9973 && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
9974 && ! THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
9975 inst.reloc.exp.X_add_symbol =
9976 find_real_start (inst.reloc.exp.X_add_symbol);
9979 static void
9980 do_t_bx (str)
9981 char * str;
9983 int reg;
9985 skip_whitespace (str);
9987 if ((reg = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9988 return;
9990 /* This sets THUMB_H2 from the top bit of reg. */
9991 inst.instruction |= reg << 3;
9993 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
9994 should cause the alignment to be checked once it is known. This is
9995 because BX PC only works if the instruction is word aligned. */
9997 end_of_line (str);
10000 static void
10001 do_t_compare (str)
10002 char * str;
10004 thumb_mov_compare (str, THUMB_COMPARE);
10007 static void
10008 do_t_ldmstm (str)
10009 char * str;
10011 int Rb;
10012 long range;
10014 skip_whitespace (str);
10016 if ((Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
10017 return;
10019 if (*str != '!')
10020 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
10021 else
10022 str++;
10024 if (skip_past_comma (&str) == FAIL
10025 || (range = reg_list (&str)) == FAIL)
10027 if (! inst.error)
10028 inst.error = BAD_ARGS;
10029 return;
10032 if (inst.reloc.type != BFD_RELOC_NONE)
10034 /* This really doesn't seem worth it. */
10035 inst.reloc.type = BFD_RELOC_NONE;
10036 inst.error = _("expression too complex");
10037 return;
10040 if (range & ~0xff)
10042 inst.error = _("only lo-regs valid in load/store multiple");
10043 return;
10046 inst.instruction |= (Rb << 8) | range;
10047 end_of_line (str);
10050 static void
10051 do_t_ldr (str)
10052 char * str;
10054 thumb_load_store (str, THUMB_LOAD, THUMB_WORD);
10057 static void
10058 do_t_ldrb (str)
10059 char * str;
10061 thumb_load_store (str, THUMB_LOAD, THUMB_BYTE);
10064 static void
10065 do_t_ldrh (str)
10066 char * str;
10068 thumb_load_store (str, THUMB_LOAD, THUMB_HALFWORD);
10071 static void
10072 do_t_lds (str)
10073 char * str;
10075 int Rd, Rb, Ro;
10077 skip_whitespace (str);
10079 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
10080 || skip_past_comma (&str) == FAIL
10081 || *str++ != '['
10082 || (Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL
10083 || skip_past_comma (&str) == FAIL
10084 || (Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL
10085 || *str++ != ']')
10087 if (! inst.error)
10088 inst.error = _("syntax: ldrs[b] Rd, [Rb, Ro]");
10089 return;
10092 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
10093 end_of_line (str);
10096 static void
10097 do_t_lsl (str)
10098 char * str;
10100 thumb_shift (str, THUMB_LSL);
10103 static void
10104 do_t_lsr (str)
10105 char * str;
10107 thumb_shift (str, THUMB_LSR);
10110 static void
10111 do_t_mov (str)
10112 char * str;
10114 thumb_mov_compare (str, THUMB_MOVE);
10117 static void
10118 do_t_push_pop (str)
10119 char * str;
10121 long range;
10123 skip_whitespace (str);
10125 if ((range = reg_list (&str)) == FAIL)
10127 if (! inst.error)
10128 inst.error = BAD_ARGS;
10129 return;
10132 if (inst.reloc.type != BFD_RELOC_NONE)
10134 /* This really doesn't seem worth it. */
10135 inst.reloc.type = BFD_RELOC_NONE;
10136 inst.error = _("expression too complex");
10137 return;
10140 if (range & ~0xff)
10142 if ((inst.instruction == T_OPCODE_PUSH
10143 && (range & ~0xff) == 1 << REG_LR)
10144 || (inst.instruction == T_OPCODE_POP
10145 && (range & ~0xff) == 1 << REG_PC))
10147 inst.instruction |= THUMB_PP_PC_LR;
10148 range &= 0xff;
10150 else
10152 inst.error = _("invalid register list to push/pop instruction");
10153 return;
10157 inst.instruction |= range;
10158 end_of_line (str);
10161 static void
10162 do_t_str (str)
10163 char * str;
10165 thumb_load_store (str, THUMB_STORE, THUMB_WORD);
10168 static void
10169 do_t_strb (str)
10170 char * str;
10172 thumb_load_store (str, THUMB_STORE, THUMB_BYTE);
10175 static void
10176 do_t_strh (str)
10177 char * str;
10179 thumb_load_store (str, THUMB_STORE, THUMB_HALFWORD);
10182 static void
10183 do_t_sub (str)
10184 char * str;
10186 thumb_add_sub (str, 1);
10189 static void
10190 do_t_swi (str)
10191 char * str;
10193 skip_whitespace (str);
10195 if (my_get_expression (&inst.reloc.exp, &str))
10196 return;
10198 inst.reloc.type = BFD_RELOC_ARM_SWI;
10199 end_of_line (str);
10200 return;
10203 static void
10204 do_t_adr (str)
10205 char * str;
10207 int reg;
10209 /* This is a pseudo-op of the form "adr rd, label" to be converted
10210 into a relative address of the form "add rd, pc, #label-.-4". */
10211 skip_whitespace (str);
10213 /* Store Rd in temporary location inside instruction. */
10214 if ((reg = reg_required_here (&str, 4)) == FAIL
10215 || (reg > 7) /* For Thumb reg must be r0..r7. */
10216 || skip_past_comma (&str) == FAIL
10217 || my_get_expression (&inst.reloc.exp, &str))
10219 if (!inst.error)
10220 inst.error = BAD_ARGS;
10221 return;
10224 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
10225 inst.reloc.exp.X_add_number -= 4; /* PC relative adjust. */
10226 inst.reloc.pc_rel = 1;
10227 inst.instruction |= REG_PC; /* Rd is already placed into the instruction. */
10229 end_of_line (str);
10232 static void
10233 insert_reg (r, htab)
10234 const struct reg_entry *r;
10235 struct hash_control *htab;
10237 int len = strlen (r->name) + 2;
10238 char * buf = (char *) xmalloc (len);
10239 char * buf2 = (char *) xmalloc (len);
10240 int i = 0;
10242 #ifdef REGISTER_PREFIX
10243 buf[i++] = REGISTER_PREFIX;
10244 #endif
10246 strcpy (buf + i, r->name);
10248 for (i = 0; buf[i]; i++)
10249 buf2[i] = TOUPPER (buf[i]);
10251 buf2[i] = '\0';
10253 hash_insert (htab, buf, (PTR) r);
10254 hash_insert (htab, buf2, (PTR) r);
10257 static void
10258 build_reg_hsh (map)
10259 struct reg_map *map;
10261 const struct reg_entry *r;
10263 if ((map->htab = hash_new ()) == NULL)
10264 as_fatal (_("virtual memory exhausted"));
10266 for (r = map->names; r->name != NULL; r++)
10267 insert_reg (r, map->htab);
10270 static void
10271 insert_reg_alias (str, regnum, htab)
10272 char *str;
10273 int regnum;
10274 struct hash_control *htab;
10276 const char *error;
10277 struct reg_entry *new = xmalloc (sizeof (struct reg_entry));
10278 const char *name = xmalloc (strlen (str) + 1);
10280 strcpy ((char *) name, str);
10282 new->name = name;
10283 new->number = regnum;
10284 new->builtin = FALSE;
10286 error = hash_insert (htab, name, (PTR) new);
10287 if (error)
10289 as_bad (_("failed to create an alias for %s, reason: %s"),
10290 str, error);
10291 free ((char *) name);
10292 free (new);
10296 /* Look for the .req directive. This is of the form:
10298 new_register_name .req existing_register_name
10300 If we find one, or if it looks sufficiently like one that we want to
10301 handle any error here, return non-zero. Otherwise return zero. */
10302 static int
10303 create_register_alias (newname, p)
10304 char *newname;
10305 char *p;
10307 char *q;
10308 char c;
10310 q = p;
10311 skip_whitespace (q);
10313 c = *p;
10314 *p = '\0';
10316 if (*q && !strncmp (q, ".req ", 5))
10318 char *copy_of_str;
10319 char *r;
10321 #ifdef IGNORE_OPCODE_CASE
10322 newname = original_case_string;
10323 #endif
10324 copy_of_str = newname;
10326 q += 4;
10327 skip_whitespace (q);
10329 for (r = q; *r != '\0'; r++)
10330 if (*r == ' ')
10331 break;
10333 if (r != q)
10335 enum arm_reg_type new_type, old_type;
10336 int old_regno;
10337 char d = *r;
10339 *r = '\0';
10340 old_type = arm_reg_parse_any (q);
10341 *r = d;
10343 new_type = arm_reg_parse_any (newname);
10345 if (new_type == REG_TYPE_MAX)
10347 if (old_type != REG_TYPE_MAX)
10349 old_regno = arm_reg_parse (&q, all_reg_maps[old_type].htab);
10350 insert_reg_alias (newname, old_regno,
10351 all_reg_maps[old_type].htab);
10353 else
10354 as_warn (_("register '%s' does not exist\n"), q);
10356 else if (old_type == REG_TYPE_MAX)
10358 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
10359 copy_of_str, q);
10361 else
10363 /* Do not warn about redefinitions to the same alias. */
10364 if (new_type != old_type
10365 || (arm_reg_parse (&q, all_reg_maps[old_type].htab)
10366 != arm_reg_parse (&q, all_reg_maps[new_type].htab)))
10367 as_warn (_("ignoring redefinition of register alias '%s'"),
10368 copy_of_str);
10372 else
10373 as_warn (_("ignoring incomplete .req pseuso op"));
10375 *p = c;
10376 return 1;
10379 *p = c;
10380 return 0;
10383 static void
10384 set_constant_flonums ()
10386 int i;
10388 for (i = 0; i < NUM_FLOAT_VALS; i++)
10389 if (atof_ieee ((char *) fp_const[i], 'x', fp_values[i]) == NULL)
10390 abort ();
10393 /* Iterate over the base tables to create the instruction patterns. */
10394 static void
10395 build_arm_ops_hsh ()
10397 unsigned int i;
10398 unsigned int j;
10399 static struct obstack insn_obstack;
10401 obstack_begin (&insn_obstack, 4000);
10403 for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
10405 const struct asm_opcode *insn = insns + i;
10407 if (insn->cond_offset != 0)
10409 /* Insn supports conditional execution. Build the varaints
10410 and insert them in the hash table. */
10411 for (j = 0; j < sizeof (conds) / sizeof (struct asm_cond); j++)
10413 unsigned len = strlen (insn->template);
10414 struct asm_opcode *new;
10415 char *template;
10417 new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
10418 /* All condition codes are two characters. */
10419 template = obstack_alloc (&insn_obstack, len + 3);
10421 strncpy (template, insn->template, insn->cond_offset);
10422 strcpy (template + insn->cond_offset, conds[j].template);
10423 if (len > insn->cond_offset)
10424 strcpy (template + insn->cond_offset + 2,
10425 insn->template + insn->cond_offset);
10426 new->template = template;
10427 new->cond_offset = 0;
10428 new->variant = insn->variant;
10429 new->parms = insn->parms;
10430 new->value = (insn->value & ~COND_MASK) | conds[j].value;
10432 hash_insert (arm_ops_hsh, new->template, (PTR) new);
10435 /* Finally, insert the unconditional insn in the table directly;
10436 no need to build a copy. */
10437 hash_insert (arm_ops_hsh, insn->template, (PTR) insn);
10441 #if 0 /* Suppressed - for now. */
10442 #if defined OBJ_ELF || defined OBJ_COFF
10444 #ifdef OBJ_ELF
10445 #define arm_Note Elf_External_Note
10446 #else
10447 typedef struct
10449 unsigned char namesz[4]; /* Size of entry's owner string. */
10450 unsigned char descsz[4]; /* Size of the note descriptor. */
10451 unsigned char type[4]; /* Interpretation of the descriptor. */
10452 char name[1]; /* Start of the name+desc data. */
10453 } arm_Note;
10454 #endif
10456 /* The description is kept to a fix sized in order to make updating
10457 it and merging it easier. */
10458 #define ARM_NOTE_DESCRIPTION_LENGTH 8
10460 static void
10461 arm_add_note (name, description, type)
10462 const char * name;
10463 const char * description;
10464 unsigned int type;
10466 arm_Note note ATTRIBUTE_UNUSED;
10467 char * p;
10468 unsigned int name_len;
10470 name_len = (strlen (name) + 1 + 3) & ~3;
10472 p = frag_more (sizeof (note.namesz));
10473 md_number_to_chars (p, (valueT) name_len, sizeof (note.namesz));
10475 p = frag_more (sizeof (note.descsz));
10476 md_number_to_chars (p, (valueT) ARM_NOTE_DESCRIPTION_LENGTH, sizeof (note.descsz));
10478 p = frag_more (sizeof (note.type));
10479 md_number_to_chars (p, (valueT) type, sizeof (note.type));
10481 p = frag_more (name_len);
10482 strcpy (p, name);
10484 p = frag_more (ARM_NOTE_DESCRIPTION_LENGTH);
10485 strncpy (p, description, ARM_NOTE_DESCRIPTION_LENGTH);
10486 frag_align (2, 0, 0);
10488 #endif
10489 #endif
10491 void
10492 md_begin ()
10494 unsigned mach;
10495 unsigned int i;
10497 if ( (arm_ops_hsh = hash_new ()) == NULL
10498 || (arm_tops_hsh = hash_new ()) == NULL
10499 || (arm_cond_hsh = hash_new ()) == NULL
10500 || (arm_shift_hsh = hash_new ()) == NULL
10501 || (arm_psr_hsh = hash_new ()) == NULL)
10502 as_fatal (_("virtual memory exhausted"));
10504 build_arm_ops_hsh ();
10505 for (i = 0; i < sizeof (tinsns) / sizeof (struct thumb_opcode); i++)
10506 hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
10507 for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
10508 hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
10509 for (i = 0; i < sizeof (shift_names) / sizeof (struct asm_shift_name); i++)
10510 hash_insert (arm_shift_hsh, shift_names[i].name, (PTR) (shift_names + i));
10511 for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
10512 hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
10514 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
10515 build_reg_hsh (all_reg_maps + i);
10517 set_constant_flonums ();
10519 /* Set the cpu variant based on the command-line options. We prefer
10520 -mcpu= over -march= if both are set (as for GCC); and we prefer
10521 -mfpu= over any other way of setting the floating point unit.
10522 Use of legacy options with new options are faulted. */
10523 if (legacy_cpu != -1)
10525 if (mcpu_cpu_opt != -1 || march_cpu_opt != -1)
10526 as_bad (_("use of old and new-style options to set CPU type"));
10528 mcpu_cpu_opt = legacy_cpu;
10530 else if (mcpu_cpu_opt == -1)
10531 mcpu_cpu_opt = march_cpu_opt;
10533 if (legacy_fpu != -1)
10535 if (mfpu_opt != -1)
10536 as_bad (_("use of old and new-style options to set FPU type"));
10538 mfpu_opt = legacy_fpu;
10540 else if (mfpu_opt == -1)
10542 #if !(defined (TE_LINUX) || defined (TE_NetBSD))
10543 /* Some environments specify a default FPU. If they don't, infer it
10544 from the processor. */
10545 if (mcpu_fpu_opt != -1)
10546 mfpu_opt = mcpu_fpu_opt;
10547 else
10548 mfpu_opt = march_fpu_opt;
10549 #else
10550 mfpu_opt = FPU_DEFAULT;
10551 #endif
10554 if (mfpu_opt == -1)
10556 if (mcpu_cpu_opt == -1)
10557 mfpu_opt = FPU_DEFAULT;
10558 else if (mcpu_cpu_opt & ARM_EXT_V5)
10559 mfpu_opt = FPU_ARCH_VFP_V2;
10560 else
10561 mfpu_opt = FPU_ARCH_FPA;
10564 if (mcpu_cpu_opt == -1)
10565 mcpu_cpu_opt = CPU_DEFAULT;
10567 cpu_variant = mcpu_cpu_opt | mfpu_opt;
10569 #if defined OBJ_COFF || defined OBJ_ELF
10571 unsigned int flags = 0;
10573 /* Set the flags in the private structure. */
10574 if (uses_apcs_26) flags |= F_APCS26;
10575 if (support_interwork) flags |= F_INTERWORK;
10576 if (uses_apcs_float) flags |= F_APCS_FLOAT;
10577 if (pic_code) flags |= F_PIC;
10578 if ((cpu_variant & FPU_ANY) == FPU_NONE
10579 || (cpu_variant & FPU_ANY) == FPU_ARCH_VFP) /* VFP layout only. */
10580 flags |= F_SOFT_FLOAT;
10581 /* Using VFP conventions (even if soft-float). */
10582 if (cpu_variant & FPU_VFP_EXT_NONE) flags |= F_VFP_FLOAT;
10584 #if defined OBJ_ELF
10585 if (cpu_variant & ARM_CEXT_MAVERICK)
10587 flags &= ~ F_SOFT_FLOAT;
10588 flags |= EF_ARM_MAVERICK_FLOAT;
10590 #endif
10592 bfd_set_private_flags (stdoutput, flags);
10594 /* We have run out flags in the COFF header to encode the
10595 status of ATPCS support, so instead we create a dummy,
10596 empty, debug section called .arm.atpcs. */
10597 if (atpcs)
10599 asection * sec;
10601 sec = bfd_make_section (stdoutput, ".arm.atpcs");
10603 if (sec != NULL)
10605 bfd_set_section_flags
10606 (stdoutput, sec, SEC_READONLY | SEC_DEBUGGING /* | SEC_HAS_CONTENTS */);
10607 bfd_set_section_size (stdoutput, sec, 0);
10608 bfd_set_section_contents (stdoutput, sec, NULL, 0, 0);
10612 #endif
10614 /* Record the CPU type as well. */
10615 switch (cpu_variant & ARM_CPU_MASK)
10617 case ARM_2:
10618 mach = bfd_mach_arm_2;
10619 break;
10621 case ARM_3: /* Also ARM_250. */
10622 mach = bfd_mach_arm_2a;
10623 break;
10625 case ARM_6: /* Also ARM_7. */
10626 mach = bfd_mach_arm_3;
10627 break;
10629 default:
10630 mach = bfd_mach_arm_unknown;
10631 break;
10634 /* Catch special cases. */
10635 if (cpu_variant & ARM_CEXT_IWMMXT)
10636 mach = bfd_mach_arm_iWMMXt;
10637 else if (cpu_variant & ARM_CEXT_XSCALE)
10638 mach = bfd_mach_arm_XScale;
10639 else if (cpu_variant & ARM_CEXT_MAVERICK)
10640 mach = bfd_mach_arm_ep9312;
10641 else if (cpu_variant & ARM_EXT_V5E)
10642 mach = bfd_mach_arm_5TE;
10643 else if (cpu_variant & ARM_EXT_V5)
10645 if (cpu_variant & ARM_EXT_V4T)
10646 mach = bfd_mach_arm_5T;
10647 else
10648 mach = bfd_mach_arm_5;
10650 else if (cpu_variant & ARM_EXT_V4)
10652 if (cpu_variant & ARM_EXT_V4T)
10653 mach = bfd_mach_arm_4T;
10654 else
10655 mach = bfd_mach_arm_4;
10657 else if (cpu_variant & ARM_EXT_V3M)
10658 mach = bfd_mach_arm_3M;
10660 #if 0 /* Suppressed - for now. */
10661 #if defined (OBJ_ELF) || defined (OBJ_COFF)
10663 /* Create a .note section to fully identify this arm binary. */
10665 #define NOTE_ARCH_STRING "arch: "
10667 #if defined OBJ_COFF && ! defined NT_VERSION
10668 #define NT_VERSION 1
10669 #define NT_ARCH 2
10670 #endif
10673 segT current_seg = now_seg;
10674 subsegT current_subseg = now_subseg;
10675 asection * arm_arch;
10676 const char * arch_string;
10678 arm_arch = bfd_make_section_old_way (stdoutput, ARM_NOTE_SECTION);
10680 #ifdef OBJ_COFF
10681 bfd_set_section_flags (stdoutput, arm_arch,
10682 SEC_DATA | SEC_ALLOC | SEC_LOAD | SEC_LINK_ONCE \
10683 | SEC_HAS_CONTENTS);
10684 #endif
10685 arm_arch->output_section = arm_arch;
10686 subseg_set (arm_arch, 0);
10688 switch (mach)
10690 default:
10691 case bfd_mach_arm_unknown: arch_string = "unknown"; break;
10692 case bfd_mach_arm_2: arch_string = "armv2"; break;
10693 case bfd_mach_arm_2a: arch_string = "armv2a"; break;
10694 case bfd_mach_arm_3: arch_string = "armv3"; break;
10695 case bfd_mach_arm_3M: arch_string = "armv3M"; break;
10696 case bfd_mach_arm_4: arch_string = "armv4"; break;
10697 case bfd_mach_arm_4T: arch_string = "armv4t"; break;
10698 case bfd_mach_arm_5: arch_string = "armv5"; break;
10699 case bfd_mach_arm_5T: arch_string = "armv5t"; break;
10700 case bfd_mach_arm_5TE: arch_string = "armv5te"; break;
10701 case bfd_mach_arm_XScale: arch_string = "XScale"; break;
10702 case bfd_mach_arm_ep9312: arch_string = "ep9312"; break;
10703 case bfd_mach_arm_iWMMXt: arch_string = "iWMMXt"; break;
10706 arm_add_note (NOTE_ARCH_STRING, arch_string, NT_ARCH);
10708 subseg_set (current_seg, current_subseg);
10710 #endif
10711 #endif /* Suppressed code. */
10713 bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
10716 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
10717 for use in the a.out file, and stores them in the array pointed to by buf.
10718 This knows about the endian-ness of the target machine and does
10719 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
10720 2 (short) and 4 (long) Floating numbers are put out as a series of
10721 LITTLENUMS (shorts, here at least). */
10723 void
10724 md_number_to_chars (buf, val, n)
10725 char * buf;
10726 valueT val;
10727 int n;
10729 if (target_big_endian)
10730 number_to_chars_bigendian (buf, val, n);
10731 else
10732 number_to_chars_littleendian (buf, val, n);
10735 static valueT
10736 md_chars_to_number (buf, n)
10737 char * buf;
10738 int n;
10740 valueT result = 0;
10741 unsigned char * where = (unsigned char *) buf;
10743 if (target_big_endian)
10745 while (n--)
10747 result <<= 8;
10748 result |= (*where++ & 255);
10751 else
10753 while (n--)
10755 result <<= 8;
10756 result |= (where[n] & 255);
10760 return result;
10763 /* Turn a string in input_line_pointer into a floating point constant
10764 of type TYPE, and store the appropriate bytes in *LITP. The number
10765 of LITTLENUMS emitted is stored in *SIZEP. An error message is
10766 returned, or NULL on OK.
10768 Note that fp constants aren't represent in the normal way on the ARM.
10769 In big endian mode, things are as expected. However, in little endian
10770 mode fp constants are big-endian word-wise, and little-endian byte-wise
10771 within the words. For example, (double) 1.1 in big endian mode is
10772 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
10773 the byte sequence 99 99 f1 3f 9a 99 99 99.
10775 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
10777 char *
10778 md_atof (type, litP, sizeP)
10779 char type;
10780 char * litP;
10781 int * sizeP;
10783 int prec;
10784 LITTLENUM_TYPE words[MAX_LITTLENUMS];
10785 char *t;
10786 int i;
10788 switch (type)
10790 case 'f':
10791 case 'F':
10792 case 's':
10793 case 'S':
10794 prec = 2;
10795 break;
10797 case 'd':
10798 case 'D':
10799 case 'r':
10800 case 'R':
10801 prec = 4;
10802 break;
10804 case 'x':
10805 case 'X':
10806 prec = 6;
10807 break;
10809 case 'p':
10810 case 'P':
10811 prec = 6;
10812 break;
10814 default:
10815 *sizeP = 0;
10816 return _("bad call to MD_ATOF()");
10819 t = atof_ieee (input_line_pointer, type, words);
10820 if (t)
10821 input_line_pointer = t;
10822 *sizeP = prec * 2;
10824 if (target_big_endian)
10826 for (i = 0; i < prec; i++)
10828 md_number_to_chars (litP, (valueT) words[i], 2);
10829 litP += 2;
10832 else
10834 if (cpu_variant & FPU_ARCH_VFP)
10835 for (i = prec - 1; i >= 0; i--)
10837 md_number_to_chars (litP, (valueT) words[i], 2);
10838 litP += 2;
10840 else
10841 /* For a 4 byte float the order of elements in `words' is 1 0.
10842 For an 8 byte float the order is 1 0 3 2. */
10843 for (i = 0; i < prec; i += 2)
10845 md_number_to_chars (litP, (valueT) words[i + 1], 2);
10846 md_number_to_chars (litP + 2, (valueT) words[i], 2);
10847 litP += 4;
10851 return 0;
10854 /* The knowledge of the PC's pipeline offset is built into the insns
10855 themselves. */
10857 long
10858 md_pcrel_from (fixP)
10859 fixS * fixP;
10861 if (fixP->fx_addsy
10862 && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section
10863 && fixP->fx_subsy == NULL)
10864 return 0;
10866 if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD))
10868 /* PC relative addressing on the Thumb is slightly odd
10869 as the bottom two bits of the PC are forced to zero
10870 for the calculation. */
10871 return (fixP->fx_where + fixP->fx_frag->fr_address) & ~3;
10874 #ifdef TE_WINCE
10875 /* The pattern was adjusted to accomodate CE's off-by-one fixups,
10876 so we un-adjust here to compensate for the accomodation. */
10877 return fixP->fx_where + fixP->fx_frag->fr_address + 8;
10878 #else
10879 return fixP->fx_where + fixP->fx_frag->fr_address;
10880 #endif
10883 /* Round up a section size to the appropriate boundary. */
10885 valueT
10886 md_section_align (segment, size)
10887 segT segment ATTRIBUTE_UNUSED;
10888 valueT size;
10890 #ifdef OBJ_ELF
10891 return size;
10892 #else
10893 /* Round all sects to multiple of 4. */
10894 return (size + 3) & ~3;
10895 #endif
10898 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
10899 Otherwise we have no need to default values of symbols. */
10901 symbolS *
10902 md_undefined_symbol (name)
10903 char * name ATTRIBUTE_UNUSED;
10905 #ifdef OBJ_ELF
10906 if (name[0] == '_' && name[1] == 'G'
10907 && streq (name, GLOBAL_OFFSET_TABLE_NAME))
10909 if (!GOT_symbol)
10911 if (symbol_find (name))
10912 as_bad ("GOT already in the symbol table");
10914 GOT_symbol = symbol_new (name, undefined_section,
10915 (valueT) 0, & zero_address_frag);
10918 return GOT_symbol;
10920 #endif
10922 return 0;
10925 /* arm_reg_parse () := if it looks like a register, return its token and
10926 advance the pointer. */
10928 static int
10929 arm_reg_parse (ccp, htab)
10930 register char ** ccp;
10931 struct hash_control *htab;
10933 char * start = * ccp;
10934 char c;
10935 char * p;
10936 struct reg_entry * reg;
10938 #ifdef REGISTER_PREFIX
10939 if (*start != REGISTER_PREFIX)
10940 return FAIL;
10941 p = start + 1;
10942 #else
10943 p = start;
10944 #ifdef OPTIONAL_REGISTER_PREFIX
10945 if (*p == OPTIONAL_REGISTER_PREFIX)
10946 p++, start++;
10947 #endif
10948 #endif
10949 if (!ISALPHA (*p) || !is_name_beginner (*p))
10950 return FAIL;
10952 c = *p++;
10953 while (ISALPHA (c) || ISDIGIT (c) || c == '_')
10954 c = *p++;
10956 *--p = 0;
10957 reg = (struct reg_entry *) hash_find (htab, start);
10958 *p = c;
10960 if (reg)
10962 *ccp = p;
10963 return reg->number;
10966 return FAIL;
10969 /* Search for the following register name in each of the possible reg name
10970 tables. Return the classification if found, or REG_TYPE_MAX if not
10971 present. */
10972 static enum arm_reg_type
10973 arm_reg_parse_any (cp)
10974 char *cp;
10976 int i;
10978 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
10979 if (arm_reg_parse (&cp, all_reg_maps[i].htab) != FAIL)
10980 return (enum arm_reg_type) i;
10982 return REG_TYPE_MAX;
10985 void
10986 md_apply_fix3 (fixP, valP, seg)
10987 fixS * fixP;
10988 valueT * valP;
10989 segT seg;
10991 offsetT value = * valP;
10992 offsetT newval;
10993 unsigned int newimm;
10994 unsigned long temp;
10995 int sign;
10996 char * buf = fixP->fx_where + fixP->fx_frag->fr_literal;
10997 arm_fix_data * arm_data = (arm_fix_data *) fixP->tc_fix_data;
10999 assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
11001 /* Note whether this will delete the relocation. */
11002 #if 0
11003 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
11004 doesn't work fully.) */
11005 if ((fixP->fx_addsy == 0 || symbol_constant_p (fixP->fx_addsy))
11006 && !fixP->fx_pcrel)
11007 #else
11008 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
11009 #endif
11010 fixP->fx_done = 1;
11012 /* If this symbol is in a different section then we need to leave it for
11013 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
11014 so we have to undo it's effects here. */
11015 if (fixP->fx_pcrel)
11017 if (fixP->fx_addsy != NULL
11018 && S_IS_DEFINED (fixP->fx_addsy)
11019 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
11021 if (target_oabi
11022 && (fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
11023 || fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
11025 value = 0;
11026 else
11027 value += md_pcrel_from (fixP);
11031 /* Remember value for emit_reloc. */
11032 fixP->fx_addnumber = value;
11034 switch (fixP->fx_r_type)
11036 case BFD_RELOC_ARM_IMMEDIATE:
11037 newimm = validate_immediate (value);
11038 temp = md_chars_to_number (buf, INSN_SIZE);
11040 /* If the instruction will fail, see if we can fix things up by
11041 changing the opcode. */
11042 if (newimm == (unsigned int) FAIL
11043 && (newimm = negate_data_op (&temp, value)) == (unsigned int) FAIL)
11045 as_bad_where (fixP->fx_file, fixP->fx_line,
11046 _("invalid constant (%lx) after fixup"),
11047 (unsigned long) value);
11048 break;
11051 newimm |= (temp & 0xfffff000);
11052 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
11053 fixP->fx_done = 1;
11054 break;
11056 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
11058 unsigned int highpart = 0;
11059 unsigned int newinsn = 0xe1a00000; /* nop. */
11061 newimm = validate_immediate (value);
11062 temp = md_chars_to_number (buf, INSN_SIZE);
11064 /* If the instruction will fail, see if we can fix things up by
11065 changing the opcode. */
11066 if (newimm == (unsigned int) FAIL
11067 && (newimm = negate_data_op (& temp, value)) == (unsigned int) FAIL)
11069 /* No ? OK - try using two ADD instructions to generate
11070 the value. */
11071 newimm = validate_immediate_twopart (value, & highpart);
11073 /* Yes - then make sure that the second instruction is
11074 also an add. */
11075 if (newimm != (unsigned int) FAIL)
11076 newinsn = temp;
11077 /* Still No ? Try using a negated value. */
11078 else if ((newimm = validate_immediate_twopart (- value, & highpart)) != (unsigned int) FAIL)
11079 temp = newinsn = (temp & OPCODE_MASK) | OPCODE_SUB << DATA_OP_SHIFT;
11080 /* Otherwise - give up. */
11081 else
11083 as_bad_where (fixP->fx_file, fixP->fx_line,
11084 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
11085 (long) value);
11086 break;
11089 /* Replace the first operand in the 2nd instruction (which
11090 is the PC) with the destination register. We have
11091 already added in the PC in the first instruction and we
11092 do not want to do it again. */
11093 newinsn &= ~ 0xf0000;
11094 newinsn |= ((newinsn & 0x0f000) << 4);
11097 newimm |= (temp & 0xfffff000);
11098 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
11100 highpart |= (newinsn & 0xfffff000);
11101 md_number_to_chars (buf + INSN_SIZE, (valueT) highpart, INSN_SIZE);
11103 break;
11105 case BFD_RELOC_ARM_OFFSET_IMM:
11106 sign = value >= 0;
11108 if (value < 0)
11109 value = - value;
11111 if (validate_offset_imm (value, 0) == FAIL)
11113 as_bad_where (fixP->fx_file, fixP->fx_line,
11114 _("bad immediate value for offset (%ld)"),
11115 (long) value);
11116 break;
11119 newval = md_chars_to_number (buf, INSN_SIZE);
11120 newval &= 0xff7ff000;
11121 newval |= value | (sign ? INDEX_UP : 0);
11122 md_number_to_chars (buf, newval, INSN_SIZE);
11123 break;
11125 case BFD_RELOC_ARM_OFFSET_IMM8:
11126 case BFD_RELOC_ARM_HWLITERAL:
11127 sign = value >= 0;
11129 if (value < 0)
11130 value = - value;
11132 if (validate_offset_imm (value, 1) == FAIL)
11134 if (fixP->fx_r_type == BFD_RELOC_ARM_HWLITERAL)
11135 as_bad_where (fixP->fx_file, fixP->fx_line,
11136 _("invalid literal constant: pool needs to be closer"));
11137 else
11138 as_bad (_("bad immediate value for half-word offset (%ld)"),
11139 (long) value);
11140 break;
11143 newval = md_chars_to_number (buf, INSN_SIZE);
11144 newval &= 0xff7ff0f0;
11145 newval |= ((value >> 4) << 8) | (value & 0xf) | (sign ? INDEX_UP : 0);
11146 md_number_to_chars (buf, newval, INSN_SIZE);
11147 break;
11149 case BFD_RELOC_ARM_LITERAL:
11150 sign = value >= 0;
11152 if (value < 0)
11153 value = - value;
11155 if (validate_offset_imm (value, 0) == FAIL)
11157 as_bad_where (fixP->fx_file, fixP->fx_line,
11158 _("invalid literal constant: pool needs to be closer"));
11159 break;
11162 newval = md_chars_to_number (buf, INSN_SIZE);
11163 newval &= 0xff7ff000;
11164 newval |= value | (sign ? INDEX_UP : 0);
11165 md_number_to_chars (buf, newval, INSN_SIZE);
11166 break;
11168 case BFD_RELOC_ARM_SHIFT_IMM:
11169 newval = md_chars_to_number (buf, INSN_SIZE);
11170 if (((unsigned long) value) > 32
11171 || (value == 32
11172 && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60)))
11174 as_bad_where (fixP->fx_file, fixP->fx_line,
11175 _("shift expression is too large"));
11176 break;
11179 if (value == 0)
11180 /* Shifts of zero must be done as lsl. */
11181 newval &= ~0x60;
11182 else if (value == 32)
11183 value = 0;
11184 newval &= 0xfffff07f;
11185 newval |= (value & 0x1f) << 7;
11186 md_number_to_chars (buf, newval, INSN_SIZE);
11187 break;
11189 case BFD_RELOC_ARM_SWI:
11190 if (arm_data->thumb_mode)
11192 if (((unsigned long) value) > 0xff)
11193 as_bad_where (fixP->fx_file, fixP->fx_line,
11194 _("invalid swi expression"));
11195 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xff00;
11196 newval |= value;
11197 md_number_to_chars (buf, newval, THUMB_SIZE);
11199 else
11201 if (((unsigned long) value) > 0x00ffffff)
11202 as_bad_where (fixP->fx_file, fixP->fx_line,
11203 _("invalid swi expression"));
11204 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
11205 newval |= value;
11206 md_number_to_chars (buf, newval, INSN_SIZE);
11208 break;
11210 case BFD_RELOC_ARM_MULTI:
11211 if (((unsigned long) value) > 0xffff)
11212 as_bad_where (fixP->fx_file, fixP->fx_line,
11213 _("invalid expression in load/store multiple"));
11214 newval = value | md_chars_to_number (buf, INSN_SIZE);
11215 md_number_to_chars (buf, newval, INSN_SIZE);
11216 break;
11218 case BFD_RELOC_ARM_PCREL_BRANCH:
11219 newval = md_chars_to_number (buf, INSN_SIZE);
11221 /* Sign-extend a 24-bit number. */
11222 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
11224 #ifdef OBJ_ELF
11225 if (! target_oabi)
11226 value = fixP->fx_offset;
11227 #endif
11229 /* We are going to store value (shifted right by two) in the
11230 instruction, in a 24 bit, signed field. Thus we need to check
11231 that none of the top 8 bits of the shifted value (top 7 bits of
11232 the unshifted, unsigned value) are set, or that they are all set. */
11233 if ((value & ~ ((offsetT) 0x1ffffff)) != 0
11234 && ((value & ~ ((offsetT) 0x1ffffff)) != ~ ((offsetT) 0x1ffffff)))
11236 #ifdef OBJ_ELF
11237 /* Normally we would be stuck at this point, since we cannot store
11238 the absolute address that is the destination of the branch in the
11239 24 bits of the branch instruction. If however, we happen to know
11240 that the destination of the branch is in the same section as the
11241 branch instruciton itself, then we can compute the relocation for
11242 ourselves and not have to bother the linker with it.
11244 FIXME: The tests for OBJ_ELF and ! target_oabi are only here
11245 because I have not worked out how to do this for OBJ_COFF or
11246 target_oabi. */
11247 if (! target_oabi
11248 && fixP->fx_addsy != NULL
11249 && S_IS_DEFINED (fixP->fx_addsy)
11250 && S_GET_SEGMENT (fixP->fx_addsy) == seg)
11252 /* Get pc relative value to go into the branch. */
11253 value = * valP;
11255 /* Permit a backward branch provided that enough bits
11256 are set. Allow a forwards branch, provided that
11257 enough bits are clear. */
11258 if ( (value & ~ ((offsetT) 0x1ffffff)) == ~ ((offsetT) 0x1ffffff)
11259 || (value & ~ ((offsetT) 0x1ffffff)) == 0)
11260 fixP->fx_done = 1;
11263 if (! fixP->fx_done)
11264 #endif
11265 as_bad_where (fixP->fx_file, fixP->fx_line,
11266 _("GAS can't handle same-section branch dest >= 0x04000000"));
11269 value >>= 2;
11270 value += SEXT24 (newval);
11272 if ( (value & ~ ((offsetT) 0xffffff)) != 0
11273 && ((value & ~ ((offsetT) 0xffffff)) != ~ ((offsetT) 0xffffff)))
11274 as_bad_where (fixP->fx_file, fixP->fx_line,
11275 _("out of range branch"));
11277 newval = (value & 0x00ffffff) | (newval & 0xff000000);
11278 md_number_to_chars (buf, newval, INSN_SIZE);
11279 break;
11281 case BFD_RELOC_ARM_PCREL_BLX:
11283 offsetT hbit;
11284 newval = md_chars_to_number (buf, INSN_SIZE);
11286 #ifdef OBJ_ELF
11287 if (! target_oabi)
11288 value = fixP->fx_offset;
11289 #endif
11290 hbit = (value >> 1) & 1;
11291 value = (value >> 2) & 0x00ffffff;
11292 value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
11293 newval = value | (newval & 0xfe000000) | (hbit << 24);
11294 md_number_to_chars (buf, newval, INSN_SIZE);
11296 break;
11298 case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch. */
11299 newval = md_chars_to_number (buf, THUMB_SIZE);
11301 addressT diff = (newval & 0xff) << 1;
11302 if (diff & 0x100)
11303 diff |= ~0xff;
11305 value += diff;
11306 if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
11307 as_bad_where (fixP->fx_file, fixP->fx_line,
11308 _("branch out of range"));
11309 newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
11311 md_number_to_chars (buf, newval, THUMB_SIZE);
11312 break;
11314 case BFD_RELOC_THUMB_PCREL_BRANCH12: /* Unconditional branch. */
11315 newval = md_chars_to_number (buf, THUMB_SIZE);
11317 addressT diff = (newval & 0x7ff) << 1;
11318 if (diff & 0x800)
11319 diff |= ~0x7ff;
11321 value += diff;
11322 if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
11323 as_bad_where (fixP->fx_file, fixP->fx_line,
11324 _("branch out of range"));
11325 newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
11327 md_number_to_chars (buf, newval, THUMB_SIZE);
11328 break;
11330 case BFD_RELOC_THUMB_PCREL_BLX:
11331 case BFD_RELOC_THUMB_PCREL_BRANCH23:
11333 offsetT newval2;
11334 addressT diff;
11336 newval = md_chars_to_number (buf, THUMB_SIZE);
11337 newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
11338 diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
11339 if (diff & 0x400000)
11340 diff |= ~0x3fffff;
11341 #ifdef OBJ_ELF
11342 value = fixP->fx_offset;
11343 #endif
11344 value += diff;
11346 if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
11347 as_bad_where (fixP->fx_file, fixP->fx_line,
11348 _("branch with link out of range"));
11350 newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12);
11351 newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
11352 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
11353 /* For a BLX instruction, make sure that the relocation is rounded up
11354 to a word boundary. This follows the semantics of the instruction
11355 which specifies that bit 1 of the target address will come from bit
11356 1 of the base address. */
11357 newval2 = (newval2 + 1) & ~ 1;
11358 md_number_to_chars (buf, newval, THUMB_SIZE);
11359 md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
11361 break;
11363 case BFD_RELOC_8:
11364 if (fixP->fx_done || fixP->fx_pcrel)
11365 md_number_to_chars (buf, value, 1);
11366 #ifdef OBJ_ELF
11367 else if (!target_oabi)
11369 value = fixP->fx_offset;
11370 md_number_to_chars (buf, value, 1);
11372 #endif
11373 break;
11375 case BFD_RELOC_16:
11376 if (fixP->fx_done || fixP->fx_pcrel)
11377 md_number_to_chars (buf, value, 2);
11378 #ifdef OBJ_ELF
11379 else if (!target_oabi)
11381 value = fixP->fx_offset;
11382 md_number_to_chars (buf, value, 2);
11384 #endif
11385 break;
11387 #ifdef OBJ_ELF
11388 case BFD_RELOC_ARM_GOT32:
11389 case BFD_RELOC_ARM_GOTOFF:
11390 md_number_to_chars (buf, 0, 4);
11391 break;
11392 #endif
11394 case BFD_RELOC_RVA:
11395 case BFD_RELOC_32:
11396 if (fixP->fx_done || fixP->fx_pcrel)
11397 md_number_to_chars (buf, value, 4);
11398 #ifdef OBJ_ELF
11399 else if (!target_oabi)
11401 value = fixP->fx_offset;
11402 md_number_to_chars (buf, value, 4);
11404 #endif
11405 break;
11407 #ifdef OBJ_ELF
11408 case BFD_RELOC_ARM_PLT32:
11409 /* It appears the instruction is fully prepared at this point. */
11410 break;
11411 #endif
11413 case BFD_RELOC_ARM_CP_OFF_IMM:
11414 sign = value >= 0;
11415 if (value < -1023 || value > 1023 || (value & 3))
11416 as_bad_where (fixP->fx_file, fixP->fx_line,
11417 _("illegal value for co-processor offset"));
11418 if (value < 0)
11419 value = -value;
11420 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
11421 newval |= (value >> 2) | (sign ? INDEX_UP : 0);
11422 md_number_to_chars (buf, newval, INSN_SIZE);
11423 break;
11425 case BFD_RELOC_ARM_CP_OFF_IMM_S2:
11426 sign = value >= 0;
11427 if (value < -255 || value > 255)
11428 as_bad_where (fixP->fx_file, fixP->fx_line,
11429 _("Illegal value for co-processor offset"));
11430 if (value < 0)
11431 value = -value;
11432 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
11433 newval |= value | (sign ? INDEX_UP : 0);
11434 md_number_to_chars (buf, newval , INSN_SIZE);
11435 break;
11437 case BFD_RELOC_ARM_THUMB_OFFSET:
11438 newval = md_chars_to_number (buf, THUMB_SIZE);
11439 /* Exactly what ranges, and where the offset is inserted depends
11440 on the type of instruction, we can establish this from the
11441 top 4 bits. */
11442 switch (newval >> 12)
11444 case 4: /* PC load. */
11445 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
11446 forced to zero for these loads, so we will need to round
11447 up the offset if the instruction address is not word
11448 aligned (since the final address produced must be, and
11449 we can only describe word-aligned immediate offsets). */
11451 if ((fixP->fx_frag->fr_address + fixP->fx_where + value) & 3)
11452 as_bad_where (fixP->fx_file, fixP->fx_line,
11453 _("invalid offset, target not word aligned (0x%08X)"),
11454 (unsigned int) (fixP->fx_frag->fr_address
11455 + fixP->fx_where + value));
11457 if ((value + 2) & ~0x3fe)
11458 as_bad_where (fixP->fx_file, fixP->fx_line,
11459 _("invalid offset, value too big (0x%08lX)"),
11460 (long) value);
11462 /* Round up, since pc will be rounded down. */
11463 newval |= (value + 2) >> 2;
11464 break;
11466 case 9: /* SP load/store. */
11467 if (value & ~0x3fc)
11468 as_bad_where (fixP->fx_file, fixP->fx_line,
11469 _("invalid offset, value too big (0x%08lX)"),
11470 (long) value);
11471 newval |= value >> 2;
11472 break;
11474 case 6: /* Word load/store. */
11475 if (value & ~0x7c)
11476 as_bad_where (fixP->fx_file, fixP->fx_line,
11477 _("invalid offset, value too big (0x%08lX)"),
11478 (long) value);
11479 newval |= value << 4; /* 6 - 2. */
11480 break;
11482 case 7: /* Byte load/store. */
11483 if (value & ~0x1f)
11484 as_bad_where (fixP->fx_file, fixP->fx_line,
11485 _("invalid offset, value too big (0x%08lX)"),
11486 (long) value);
11487 newval |= value << 6;
11488 break;
11490 case 8: /* Halfword load/store. */
11491 if (value & ~0x3e)
11492 as_bad_where (fixP->fx_file, fixP->fx_line,
11493 _("invalid offset, value too big (0x%08lX)"),
11494 (long) value);
11495 newval |= value << 5; /* 6 - 1. */
11496 break;
11498 default:
11499 as_bad_where (fixP->fx_file, fixP->fx_line,
11500 "Unable to process relocation for thumb opcode: %lx",
11501 (unsigned long) newval);
11502 break;
11504 md_number_to_chars (buf, newval, THUMB_SIZE);
11505 break;
11507 case BFD_RELOC_ARM_THUMB_ADD:
11508 /* This is a complicated relocation, since we use it for all of
11509 the following immediate relocations:
11511 3bit ADD/SUB
11512 8bit ADD/SUB
11513 9bit ADD/SUB SP word-aligned
11514 10bit ADD PC/SP word-aligned
11516 The type of instruction being processed is encoded in the
11517 instruction field:
11519 0x8000 SUB
11520 0x00F0 Rd
11521 0x000F Rs
11523 newval = md_chars_to_number (buf, THUMB_SIZE);
11525 int rd = (newval >> 4) & 0xf;
11526 int rs = newval & 0xf;
11527 int subtract = newval & 0x8000;
11529 if (rd == REG_SP)
11531 if (value & ~0x1fc)
11532 as_bad_where (fixP->fx_file, fixP->fx_line,
11533 _("invalid immediate for stack address calculation"));
11534 newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
11535 newval |= value >> 2;
11537 else if (rs == REG_PC || rs == REG_SP)
11539 if (subtract ||
11540 value & ~0x3fc)
11541 as_bad_where (fixP->fx_file, fixP->fx_line,
11542 _("invalid immediate for address calculation (value = 0x%08lX)"),
11543 (unsigned long) value);
11544 newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP);
11545 newval |= rd << 8;
11546 newval |= value >> 2;
11548 else if (rs == rd)
11550 if (value & ~0xff)
11551 as_bad_where (fixP->fx_file, fixP->fx_line,
11552 _("invalid 8bit immediate"));
11553 newval = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
11554 newval |= (rd << 8) | value;
11556 else
11558 if (value & ~0x7)
11559 as_bad_where (fixP->fx_file, fixP->fx_line,
11560 _("invalid 3bit immediate"));
11561 newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
11562 newval |= rd | (rs << 3) | (value << 6);
11565 md_number_to_chars (buf, newval, THUMB_SIZE);
11566 break;
11568 case BFD_RELOC_ARM_THUMB_IMM:
11569 newval = md_chars_to_number (buf, THUMB_SIZE);
11570 switch (newval >> 11)
11572 case 0x04: /* 8bit immediate MOV. */
11573 case 0x05: /* 8bit immediate CMP. */
11574 if (value < 0 || value > 255)
11575 as_bad_where (fixP->fx_file, fixP->fx_line,
11576 _("invalid immediate: %ld is too large"),
11577 (long) value);
11578 newval |= value;
11579 break;
11581 default:
11582 abort ();
11584 md_number_to_chars (buf, newval, THUMB_SIZE);
11585 break;
11587 case BFD_RELOC_ARM_THUMB_SHIFT:
11588 /* 5bit shift value (0..31). */
11589 if (value < 0 || value > 31)
11590 as_bad_where (fixP->fx_file, fixP->fx_line,
11591 _("illegal Thumb shift value: %ld"), (long) value);
11592 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xf03f;
11593 newval |= value << 6;
11594 md_number_to_chars (buf, newval, THUMB_SIZE);
11595 break;
11597 case BFD_RELOC_VTABLE_INHERIT:
11598 case BFD_RELOC_VTABLE_ENTRY:
11599 fixP->fx_done = 0;
11600 return;
11602 case BFD_RELOC_NONE:
11603 default:
11604 as_bad_where (fixP->fx_file, fixP->fx_line,
11605 _("bad relocation fixup type (%d)"), fixP->fx_r_type);
11609 /* Translate internal representation of relocation info to BFD target
11610 format. */
11612 arelent *
11613 tc_gen_reloc (section, fixp)
11614 asection * section ATTRIBUTE_UNUSED;
11615 fixS * fixp;
11617 arelent * reloc;
11618 bfd_reloc_code_real_type code;
11620 reloc = (arelent *) xmalloc (sizeof (arelent));
11622 reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
11623 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
11624 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
11626 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
11627 #ifndef OBJ_ELF
11628 if (fixp->fx_pcrel == 0)
11629 reloc->addend = fixp->fx_offset;
11630 else
11631 reloc->addend = fixp->fx_offset = reloc->address;
11632 #else /* OBJ_ELF */
11633 reloc->addend = fixp->fx_offset;
11634 #endif
11636 switch (fixp->fx_r_type)
11638 case BFD_RELOC_8:
11639 if (fixp->fx_pcrel)
11641 code = BFD_RELOC_8_PCREL;
11642 break;
11645 case BFD_RELOC_16:
11646 if (fixp->fx_pcrel)
11648 code = BFD_RELOC_16_PCREL;
11649 break;
11652 case BFD_RELOC_32:
11653 if (fixp->fx_pcrel)
11655 code = BFD_RELOC_32_PCREL;
11656 break;
11659 case BFD_RELOC_ARM_PCREL_BRANCH:
11660 case BFD_RELOC_ARM_PCREL_BLX:
11661 case BFD_RELOC_RVA:
11662 case BFD_RELOC_THUMB_PCREL_BRANCH9:
11663 case BFD_RELOC_THUMB_PCREL_BRANCH12:
11664 case BFD_RELOC_THUMB_PCREL_BRANCH23:
11665 case BFD_RELOC_THUMB_PCREL_BLX:
11666 case BFD_RELOC_VTABLE_ENTRY:
11667 case BFD_RELOC_VTABLE_INHERIT:
11668 code = fixp->fx_r_type;
11669 break;
11671 case BFD_RELOC_ARM_LITERAL:
11672 case BFD_RELOC_ARM_HWLITERAL:
11673 /* If this is called then the a literal has
11674 been referenced across a section boundary. */
11675 as_bad_where (fixp->fx_file, fixp->fx_line,
11676 _("literal referenced across section boundary"));
11677 return NULL;
11679 #ifdef OBJ_ELF
11680 case BFD_RELOC_ARM_GOT32:
11681 case BFD_RELOC_ARM_GOTOFF:
11682 case BFD_RELOC_ARM_PLT32:
11683 code = fixp->fx_r_type;
11684 break;
11685 #endif
11687 case BFD_RELOC_ARM_IMMEDIATE:
11688 as_bad_where (fixp->fx_file, fixp->fx_line,
11689 _("internal relocation (type: IMMEDIATE) not fixed up"));
11690 return NULL;
11692 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
11693 as_bad_where (fixp->fx_file, fixp->fx_line,
11694 _("ADRL used for a symbol not defined in the same file"));
11695 return NULL;
11697 case BFD_RELOC_ARM_OFFSET_IMM:
11698 as_bad_where (fixp->fx_file, fixp->fx_line,
11699 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
11700 return NULL;
11702 default:
11704 char * type;
11706 switch (fixp->fx_r_type)
11708 case BFD_RELOC_ARM_OFFSET_IMM8: type = "OFFSET_IMM8"; break;
11709 case BFD_RELOC_ARM_SHIFT_IMM: type = "SHIFT_IMM"; break;
11710 case BFD_RELOC_ARM_SWI: type = "SWI"; break;
11711 case BFD_RELOC_ARM_MULTI: type = "MULTI"; break;
11712 case BFD_RELOC_ARM_CP_OFF_IMM: type = "CP_OFF_IMM"; break;
11713 case BFD_RELOC_ARM_THUMB_ADD: type = "THUMB_ADD"; break;
11714 case BFD_RELOC_ARM_THUMB_SHIFT: type = "THUMB_SHIFT"; break;
11715 case BFD_RELOC_ARM_THUMB_IMM: type = "THUMB_IMM"; break;
11716 case BFD_RELOC_ARM_THUMB_OFFSET: type = "THUMB_OFFSET"; break;
11717 default: type = _("<unknown>"); break;
11719 as_bad_where (fixp->fx_file, fixp->fx_line,
11720 _("cannot represent %s relocation in this object file format"),
11721 type);
11722 return NULL;
11726 #ifdef OBJ_ELF
11727 if ((code == BFD_RELOC_32_PCREL || code == BFD_RELOC_32)
11728 && GOT_symbol
11729 && fixp->fx_addsy == GOT_symbol)
11731 code = BFD_RELOC_ARM_GOTPC;
11732 reloc->addend = fixp->fx_offset = reloc->address;
11734 #endif
11736 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
11738 if (reloc->howto == NULL)
11740 as_bad_where (fixp->fx_file, fixp->fx_line,
11741 _("cannot represent %s relocation in this object file format"),
11742 bfd_get_reloc_code_name (code));
11743 return NULL;
11746 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
11747 vtable entry to be used in the relocation's section offset. */
11748 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
11749 reloc->address = fixp->fx_offset;
11751 return reloc;
11755 md_estimate_size_before_relax (fragP, segtype)
11756 fragS * fragP ATTRIBUTE_UNUSED;
11757 segT segtype ATTRIBUTE_UNUSED;
11759 as_fatal (_("md_estimate_size_before_relax\n"));
11760 return 1;
11763 static void
11764 output_inst (str)
11765 const char *str;
11767 char * to = NULL;
11769 if (inst.error)
11771 as_bad ("%s -- `%s'", inst.error, str);
11772 return;
11775 to = frag_more (inst.size);
11777 if (thumb_mode && (inst.size > THUMB_SIZE))
11779 assert (inst.size == (2 * THUMB_SIZE));
11780 md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE);
11781 md_number_to_chars (to + THUMB_SIZE, inst.instruction, THUMB_SIZE);
11783 else if (inst.size > INSN_SIZE)
11785 assert (inst.size == (2 * INSN_SIZE));
11786 md_number_to_chars (to, inst.instruction, INSN_SIZE);
11787 md_number_to_chars (to + INSN_SIZE, inst.instruction, INSN_SIZE);
11789 else
11790 md_number_to_chars (to, inst.instruction, inst.size);
11792 if (inst.reloc.type != BFD_RELOC_NONE)
11793 fix_new_arm (frag_now, to - frag_now->fr_literal,
11794 inst.size, & inst.reloc.exp, inst.reloc.pc_rel,
11795 inst.reloc.type);
11797 #ifdef OBJ_ELF
11798 dwarf2_emit_insn (inst.size);
11799 #endif
11802 void
11803 md_assemble (str)
11804 char * str;
11806 char c;
11807 char *p;
11808 char *start;
11810 /* Align the instruction.
11811 This may not be the right thing to do but ... */
11812 #if 0
11813 arm_align (2, 0);
11814 #endif
11816 /* Align the previous label if needed. */
11817 if (last_label_seen != NULL)
11819 symbol_set_frag (last_label_seen, frag_now);
11820 S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ());
11821 S_SET_SEGMENT (last_label_seen, now_seg);
11824 memset (&inst, '\0', sizeof (inst));
11825 inst.reloc.type = BFD_RELOC_NONE;
11827 skip_whitespace (str);
11829 /* Scan up to the end of the op-code, which must end in white space or
11830 end of string. */
11831 for (start = p = str; *p != '\0'; p++)
11832 if (*p == ' ')
11833 break;
11835 if (p == str)
11837 as_bad (_("no operator -- statement `%s'\n"), str);
11838 return;
11841 if (thumb_mode)
11843 const struct thumb_opcode * opcode;
11845 c = *p;
11846 *p = '\0';
11847 opcode = (const struct thumb_opcode *) hash_find (arm_tops_hsh, str);
11848 *p = c;
11850 if (opcode)
11852 /* Check that this instruction is supported for this CPU. */
11853 if (thumb_mode == 1 && (opcode->variant & cpu_variant) == 0)
11855 as_bad (_("selected processor does not support `%s'"), str);
11856 return;
11859 mapping_state (MAP_THUMB);
11860 inst.instruction = opcode->value;
11861 inst.size = opcode->size;
11862 (*opcode->parms) (p);
11863 output_inst (str);
11864 return;
11867 else
11869 const struct asm_opcode * opcode;
11871 c = *p;
11872 *p = '\0';
11873 opcode = (const struct asm_opcode *) hash_find (arm_ops_hsh, str);
11874 *p = c;
11876 if (opcode)
11878 /* Check that this instruction is supported for this CPU. */
11879 if ((opcode->variant & cpu_variant) == 0)
11881 as_bad (_("selected processor does not support `%s'"), str);
11882 return;
11885 mapping_state (MAP_ARM);
11886 inst.instruction = opcode->value;
11887 inst.size = INSN_SIZE;
11888 (*opcode->parms) (p);
11889 output_inst (str);
11890 return;
11894 /* It wasn't an instruction, but it might be a register alias of the form
11895 alias .req reg. */
11896 if (create_register_alias (str, p))
11897 return;
11899 as_bad (_("bad instruction `%s'"), start);
11902 /* md_parse_option
11903 Invocation line includes a switch not recognized by the base assembler.
11904 See if it's a processor-specific option.
11906 This routine is somewhat complicated by the need for backwards
11907 compatibility (since older releases of gcc can't be changed).
11908 The new options try to make the interface as compatible as
11909 possible with GCC.
11911 New options (supported) are:
11913 -mcpu=<cpu name> Assemble for selected processor
11914 -march=<architecture name> Assemble for selected architecture
11915 -mfpu=<fpu architecture> Assemble for selected FPU.
11916 -EB/-mbig-endian Big-endian
11917 -EL/-mlittle-endian Little-endian
11918 -k Generate PIC code
11919 -mthumb Start in Thumb mode
11920 -mthumb-interwork Code supports ARM/Thumb interworking
11922 For now we will also provide support for:
11924 -mapcs-32 32-bit Program counter
11925 -mapcs-26 26-bit Program counter
11926 -macps-float Floats passed in FP registers
11927 -mapcs-reentrant Reentrant code
11928 -matpcs
11929 (sometime these will probably be replaced with -mapcs=<list of options>
11930 and -matpcs=<list of options>)
11932 The remaining options are only supported for back-wards compatibility.
11933 Cpu variants, the arm part is optional:
11934 -m[arm]1 Currently not supported.
11935 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
11936 -m[arm]3 Arm 3 processor
11937 -m[arm]6[xx], Arm 6 processors
11938 -m[arm]7[xx][t][[d]m] Arm 7 processors
11939 -m[arm]8[10] Arm 8 processors
11940 -m[arm]9[20][tdmi] Arm 9 processors
11941 -mstrongarm[110[0]] StrongARM processors
11942 -mxscale XScale processors
11943 -m[arm]v[2345[t[e]]] Arm architectures
11944 -mall All (except the ARM1)
11945 FP variants:
11946 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
11947 -mfpe-old (No float load/store multiples)
11948 -mvfpxd VFP Single precision
11949 -mvfp All VFP
11950 -mno-fpu Disable all floating point instructions
11952 The following CPU names are recognized:
11953 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
11954 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
11955 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
11956 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
11957 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
11958 arm10t arm10e, arm1020t, arm1020e, arm10200e,
11959 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
11963 const char * md_shortopts = "m:k";
11965 #ifdef ARM_BI_ENDIAN
11966 #define OPTION_EB (OPTION_MD_BASE + 0)
11967 #define OPTION_EL (OPTION_MD_BASE + 1)
11968 #else
11969 #if TARGET_BYTES_BIG_ENDIAN
11970 #define OPTION_EB (OPTION_MD_BASE + 0)
11971 #else
11972 #define OPTION_EL (OPTION_MD_BASE + 1)
11973 #endif
11974 #endif
11976 struct option md_longopts[] =
11978 #ifdef OPTION_EB
11979 {"EB", no_argument, NULL, OPTION_EB},
11980 #endif
11981 #ifdef OPTION_EL
11982 {"EL", no_argument, NULL, OPTION_EL},
11983 #endif
11984 {NULL, no_argument, NULL, 0}
11987 size_t md_longopts_size = sizeof (md_longopts);
11989 struct arm_option_table
11991 char *option; /* Option name to match. */
11992 char *help; /* Help information. */
11993 int *var; /* Variable to change. */
11994 int value; /* What to change it to. */
11995 char *deprecated; /* If non-null, print this message. */
11998 struct arm_option_table arm_opts[] =
12000 {"k", N_("generate PIC code"), &pic_code, 1, NULL},
12001 {"mthumb", N_("assemble Thumb code"), &thumb_mode, 1, NULL},
12002 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
12003 &support_interwork, 1, NULL},
12004 {"moabi", N_("use old ABI (ELF only)"), &target_oabi, 1, NULL},
12005 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26, 0, NULL},
12006 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26, 1, NULL},
12007 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float,
12008 1, NULL},
12009 {"mapcs-reentrant", N_("re-entrant code"), &pic_code, 1, NULL},
12010 {"matpcs", N_("code is ATPCS conformant"), &atpcs, 1, NULL},
12011 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian, 1, NULL},
12012 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian, 1,
12013 NULL},
12015 /* These are recognized by the assembler, but have no affect on code. */
12016 {"mapcs-frame", N_("use frame pointer"), NULL, 0, NULL},
12017 {"mapcs-stack-check", N_("use stack size checking"), NULL, 0, NULL},
12019 /* DON'T add any new processors to this list -- we want the whole list
12020 to go away... Add them to the processors table instead. */
12021 {"marm1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
12022 {"m1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
12023 {"marm2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
12024 {"m2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
12025 {"marm250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
12026 {"m250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
12027 {"marm3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
12028 {"m3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
12029 {"marm6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
12030 {"m6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
12031 {"marm600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
12032 {"m600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
12033 {"marm610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
12034 {"m610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
12035 {"marm620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
12036 {"m620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
12037 {"marm7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
12038 {"m7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
12039 {"marm70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
12040 {"m70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
12041 {"marm700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
12042 {"m700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
12043 {"marm700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
12044 {"m700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
12045 {"marm710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
12046 {"m710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
12047 {"marm710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
12048 {"m710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
12049 {"marm720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
12050 {"m720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
12051 {"marm7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
12052 {"m7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
12053 {"marm7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
12054 {"m7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
12055 {"marm7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
12056 {"m7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
12057 {"marm7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
12058 {"m7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
12059 {"marm7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
12060 {"m7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
12061 {"marm7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
12062 {"m7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
12063 {"marm7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
12064 {"m7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
12065 {"marm7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
12066 {"m7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
12067 {"marm7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12068 {"m7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12069 {"marm7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12070 {"m7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12071 {"marm710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
12072 {"m710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
12073 {"marm720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
12074 {"m720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
12075 {"marm740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
12076 {"m740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
12077 {"marm8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
12078 {"m8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
12079 {"marm810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
12080 {"m810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
12081 {"marm9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
12082 {"m9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
12083 {"marm9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
12084 {"m9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
12085 {"marm920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
12086 {"m920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
12087 {"marm940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
12088 {"m940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
12089 {"mstrongarm", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=strongarm")},
12090 {"mstrongarm110", NULL, &legacy_cpu, ARM_ARCH_V4,
12091 N_("use -mcpu=strongarm110")},
12092 {"mstrongarm1100", NULL, &legacy_cpu, ARM_ARCH_V4,
12093 N_("use -mcpu=strongarm1100")},
12094 {"mstrongarm1110", NULL, &legacy_cpu, ARM_ARCH_V4,
12095 N_("use -mcpu=strongarm1110")},
12096 {"mxscale", NULL, &legacy_cpu, ARM_ARCH_XSCALE, N_("use -mcpu=xscale")},
12097 {"miwmmxt", NULL, &legacy_cpu, ARM_ARCH_IWMMXT, N_("use -mcpu=iwmmxt")},
12098 {"mall", NULL, &legacy_cpu, ARM_ANY, N_("use -mcpu=all")},
12100 /* Architecture variants -- don't add any more to this list either. */
12101 {"mv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
12102 {"marmv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
12103 {"mv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
12104 {"marmv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
12105 {"mv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
12106 {"marmv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
12107 {"mv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
12108 {"marmv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
12109 {"mv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
12110 {"marmv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
12111 {"mv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
12112 {"marmv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
12113 {"mv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
12114 {"marmv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
12115 {"mv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
12116 {"marmv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
12117 {"mv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
12118 {"marmv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
12120 /* Floating point variants -- don't add any more to this list either. */
12121 {"mfpe-old", NULL, &legacy_fpu, FPU_ARCH_FPE, N_("use -mfpu=fpe")},
12122 {"mfpa10", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa10")},
12123 {"mfpa11", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa11")},
12124 {"mno-fpu", NULL, &legacy_fpu, 0,
12125 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
12127 {NULL, NULL, NULL, 0, NULL}
12130 struct arm_cpu_option_table
12132 char *name;
12133 int value;
12134 /* For some CPUs we assume an FPU unless the user explicitly sets
12135 -mfpu=... */
12136 int default_fpu;
12139 /* This list should, at a minimum, contain all the cpu names
12140 recognized by GCC. */
12141 static struct arm_cpu_option_table arm_cpus[] =
12143 {"all", ARM_ANY, FPU_ARCH_FPA},
12144 {"arm1", ARM_ARCH_V1, FPU_ARCH_FPA},
12145 {"arm2", ARM_ARCH_V2, FPU_ARCH_FPA},
12146 {"arm250", ARM_ARCH_V2S, FPU_ARCH_FPA},
12147 {"arm3", ARM_ARCH_V2S, FPU_ARCH_FPA},
12148 {"arm6", ARM_ARCH_V3, FPU_ARCH_FPA},
12149 {"arm60", ARM_ARCH_V3, FPU_ARCH_FPA},
12150 {"arm600", ARM_ARCH_V3, FPU_ARCH_FPA},
12151 {"arm610", ARM_ARCH_V3, FPU_ARCH_FPA},
12152 {"arm620", ARM_ARCH_V3, FPU_ARCH_FPA},
12153 {"arm7", ARM_ARCH_V3, FPU_ARCH_FPA},
12154 {"arm7m", ARM_ARCH_V3M, FPU_ARCH_FPA},
12155 {"arm7d", ARM_ARCH_V3, FPU_ARCH_FPA},
12156 {"arm7dm", ARM_ARCH_V3M, FPU_ARCH_FPA},
12157 {"arm7di", ARM_ARCH_V3, FPU_ARCH_FPA},
12158 {"arm7dmi", ARM_ARCH_V3M, FPU_ARCH_FPA},
12159 {"arm70", ARM_ARCH_V3, FPU_ARCH_FPA},
12160 {"arm700", ARM_ARCH_V3, FPU_ARCH_FPA},
12161 {"arm700i", ARM_ARCH_V3, FPU_ARCH_FPA},
12162 {"arm710", ARM_ARCH_V3, FPU_ARCH_FPA},
12163 {"arm710t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12164 {"arm720", ARM_ARCH_V3, FPU_ARCH_FPA},
12165 {"arm720t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12166 {"arm740t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12167 {"arm710c", ARM_ARCH_V3, FPU_ARCH_FPA},
12168 {"arm7100", ARM_ARCH_V3, FPU_ARCH_FPA},
12169 {"arm7500", ARM_ARCH_V3, FPU_ARCH_FPA},
12170 {"arm7500fe", ARM_ARCH_V3, FPU_ARCH_FPA},
12171 {"arm7t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12172 {"arm7tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
12173 {"arm8", ARM_ARCH_V4, FPU_ARCH_FPA},
12174 {"arm810", ARM_ARCH_V4, FPU_ARCH_FPA},
12175 {"strongarm", ARM_ARCH_V4, FPU_ARCH_FPA},
12176 {"strongarm1", ARM_ARCH_V4, FPU_ARCH_FPA},
12177 {"strongarm110", ARM_ARCH_V4, FPU_ARCH_FPA},
12178 {"strongarm1100", ARM_ARCH_V4, FPU_ARCH_FPA},
12179 {"strongarm1110", ARM_ARCH_V4, FPU_ARCH_FPA},
12180 {"arm9", ARM_ARCH_V4T, FPU_ARCH_FPA},
12181 {"arm920", ARM_ARCH_V4T, FPU_ARCH_FPA},
12182 {"arm920t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12183 {"arm922t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12184 {"arm940t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12185 {"arm9tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
12186 /* For V5 or later processors we default to using VFP; but the user
12187 should really set the FPU type explicitly. */
12188 {"arm9e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
12189 {"arm9e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12190 {"arm926ej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
12191 {"arm946e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
12192 {"arm946e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12193 {"arm966e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
12194 {"arm966e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12195 {"arm10t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
12196 {"arm10e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12197 {"arm1020", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12198 {"arm1020t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
12199 {"arm1020e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12200 /* ??? XSCALE is really an architecture. */
12201 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
12202 /* ??? iwmmxt is not a processor. */
12203 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP_V2},
12204 {"i80200", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
12205 /* Maverick */
12206 {"ep9312", ARM_ARCH_V4T | ARM_CEXT_MAVERICK, FPU_NONE},
12207 {NULL, 0, 0}
12210 struct arm_arch_option_table
12212 char *name;
12213 int value;
12214 int default_fpu;
12217 /* This list should, at a minimum, contain all the architecture names
12218 recognized by GCC. */
12219 static struct arm_arch_option_table arm_archs[] =
12221 {"all", ARM_ANY, FPU_ARCH_FPA},
12222 {"armv1", ARM_ARCH_V1, FPU_ARCH_FPA},
12223 {"armv2", ARM_ARCH_V2, FPU_ARCH_FPA},
12224 {"armv2a", ARM_ARCH_V2S, FPU_ARCH_FPA},
12225 {"armv2s", ARM_ARCH_V2S, FPU_ARCH_FPA},
12226 {"armv3", ARM_ARCH_V3, FPU_ARCH_FPA},
12227 {"armv3m", ARM_ARCH_V3M, FPU_ARCH_FPA},
12228 {"armv4", ARM_ARCH_V4, FPU_ARCH_FPA},
12229 {"armv4xm", ARM_ARCH_V4xM, FPU_ARCH_FPA},
12230 {"armv4t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12231 {"armv4txm", ARM_ARCH_V4TxM, FPU_ARCH_FPA},
12232 {"armv5", ARM_ARCH_V5, FPU_ARCH_VFP},
12233 {"armv5t", ARM_ARCH_V5T, FPU_ARCH_VFP},
12234 {"armv5txm", ARM_ARCH_V5TxM, FPU_ARCH_VFP},
12235 {"armv5te", ARM_ARCH_V5TE, FPU_ARCH_VFP},
12236 {"armv5texp", ARM_ARCH_V5TExP, FPU_ARCH_VFP},
12237 {"armv5tej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP},
12238 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP},
12239 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP},
12240 {NULL, 0, 0}
12243 /* ISA extensions in the co-processor space. */
12244 struct arm_arch_extension_table
12246 char *name;
12247 int value;
12250 static struct arm_arch_extension_table arm_extensions[] =
12252 {"maverick", ARM_CEXT_MAVERICK},
12253 {"xscale", ARM_CEXT_XSCALE},
12254 {"iwmmxt", ARM_CEXT_IWMMXT},
12255 {NULL, 0}
12258 struct arm_fpu_option_table
12260 char *name;
12261 int value;
12264 /* This list should, at a minimum, contain all the fpu names
12265 recognized by GCC. */
12266 static struct arm_fpu_option_table arm_fpus[] =
12268 {"softfpa", FPU_NONE},
12269 {"fpe", FPU_ARCH_FPE},
12270 {"fpe2", FPU_ARCH_FPE},
12271 {"fpe3", FPU_ARCH_FPA}, /* Third release supports LFM/SFM. */
12272 {"fpa", FPU_ARCH_FPA},
12273 {"fpa10", FPU_ARCH_FPA},
12274 {"fpa11", FPU_ARCH_FPA},
12275 {"arm7500fe", FPU_ARCH_FPA},
12276 {"softvfp", FPU_ARCH_VFP},
12277 {"softvfp+vfp", FPU_ARCH_VFP_V2},
12278 {"vfp", FPU_ARCH_VFP_V2},
12279 {"vfp9", FPU_ARCH_VFP_V2},
12280 {"vfp10", FPU_ARCH_VFP_V2},
12281 {"vfp10-r0", FPU_ARCH_VFP_V1},
12282 {"vfpxd", FPU_ARCH_VFP_V1xD},
12283 {"arm1020t", FPU_ARCH_VFP_V1},
12284 {"arm1020e", FPU_ARCH_VFP_V2},
12285 {NULL, 0}
12288 struct arm_long_option_table
12290 char *option; /* Substring to match. */
12291 char *help; /* Help information. */
12292 int (*func) PARAMS ((char *subopt)); /* Function to decode sub-option. */
12293 char *deprecated; /* If non-null, print this message. */
12296 static int
12297 arm_parse_extension (str, opt_p)
12298 char *str;
12299 int *opt_p;
12301 while (str != NULL && *str != 0)
12303 struct arm_arch_extension_table *opt;
12304 char *ext;
12305 int optlen;
12307 if (*str != '+')
12309 as_bad (_("invalid architectural extension"));
12310 return 0;
12313 str++;
12314 ext = strchr (str, '+');
12316 if (ext != NULL)
12317 optlen = ext - str;
12318 else
12319 optlen = strlen (str);
12321 if (optlen == 0)
12323 as_bad (_("missing architectural extension"));
12324 return 0;
12327 for (opt = arm_extensions; opt->name != NULL; opt++)
12328 if (strncmp (opt->name, str, optlen) == 0)
12330 *opt_p |= opt->value;
12331 break;
12334 if (opt->name == NULL)
12336 as_bad (_("unknown architectural extnsion `%s'"), str);
12337 return 0;
12340 str = ext;
12343 return 1;
12346 static int
12347 arm_parse_cpu (str)
12348 char *str;
12350 struct arm_cpu_option_table *opt;
12351 char *ext = strchr (str, '+');
12352 int optlen;
12354 if (ext != NULL)
12355 optlen = ext - str;
12356 else
12357 optlen = strlen (str);
12359 if (optlen == 0)
12361 as_bad (_("missing cpu name `%s'"), str);
12362 return 0;
12365 for (opt = arm_cpus; opt->name != NULL; opt++)
12366 if (strncmp (opt->name, str, optlen) == 0)
12368 mcpu_cpu_opt = opt->value;
12369 mcpu_fpu_opt = opt->default_fpu;
12371 if (ext != NULL)
12372 return arm_parse_extension (ext, &mcpu_cpu_opt);
12374 return 1;
12377 as_bad (_("unknown cpu `%s'"), str);
12378 return 0;
12381 static int
12382 arm_parse_arch (str)
12383 char *str;
12385 struct arm_arch_option_table *opt;
12386 char *ext = strchr (str, '+');
12387 int optlen;
12389 if (ext != NULL)
12390 optlen = ext - str;
12391 else
12392 optlen = strlen (str);
12394 if (optlen == 0)
12396 as_bad (_("missing architecture name `%s'"), str);
12397 return 0;
12401 for (opt = arm_archs; opt->name != NULL; opt++)
12402 if (strcmp (opt->name, str) == 0)
12404 march_cpu_opt = opt->value;
12405 march_fpu_opt = opt->default_fpu;
12407 if (ext != NULL)
12408 return arm_parse_extension (ext, &march_cpu_opt);
12410 return 1;
12413 as_bad (_("unknown architecture `%s'\n"), str);
12414 return 0;
12417 static int
12418 arm_parse_fpu (str)
12419 char *str;
12421 struct arm_fpu_option_table *opt;
12423 for (opt = arm_fpus; opt->name != NULL; opt++)
12424 if (strcmp (opt->name, str) == 0)
12426 mfpu_opt = opt->value;
12427 return 1;
12430 as_bad (_("unknown floating point format `%s'\n"), str);
12431 return 0;
12434 struct arm_long_option_table arm_long_opts[] =
12436 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
12437 arm_parse_cpu, NULL},
12438 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
12439 arm_parse_arch, NULL},
12440 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
12441 arm_parse_fpu, NULL},
12442 {NULL, NULL, 0, NULL}
12446 md_parse_option (c, arg)
12447 int c;
12448 char * arg;
12450 struct arm_option_table *opt;
12451 struct arm_long_option_table *lopt;
12453 switch (c)
12455 #ifdef OPTION_EB
12456 case OPTION_EB:
12457 target_big_endian = 1;
12458 break;
12459 #endif
12461 #ifdef OPTION_EL
12462 case OPTION_EL:
12463 target_big_endian = 0;
12464 break;
12465 #endif
12467 case 'a':
12468 /* Listing option. Just ignore these, we don't support additional
12469 ones. */
12470 return 0;
12472 default:
12473 for (opt = arm_opts; opt->option != NULL; opt++)
12475 if (c == opt->option[0]
12476 && ((arg == NULL && opt->option[1] == 0)
12477 || strcmp (arg, opt->option + 1) == 0))
12479 #if WARN_DEPRECATED
12480 /* If the option is deprecated, tell the user. */
12481 if (opt->deprecated != NULL)
12482 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c,
12483 arg ? arg : "", _(opt->deprecated));
12484 #endif
12486 if (opt->var != NULL)
12487 *opt->var = opt->value;
12489 return 1;
12493 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
12495 /* These options are expected to have an argument. */
12496 if (c == lopt->option[0]
12497 && arg != NULL
12498 && strncmp (arg, lopt->option + 1,
12499 strlen (lopt->option + 1)) == 0)
12501 #if WARN_DEPRECATED
12502 /* If the option is deprecated, tell the user. */
12503 if (lopt->deprecated != NULL)
12504 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c, arg,
12505 _(lopt->deprecated));
12506 #endif
12508 /* Call the sup-option parser. */
12509 return (*lopt->func)(arg + strlen (lopt->option) - 1);
12513 as_bad (_("unrecognized option `-%c%s'"), c, arg ? arg : "");
12514 return 0;
12517 return 1;
12520 void
12521 md_show_usage (fp)
12522 FILE * fp;
12524 struct arm_option_table *opt;
12525 struct arm_long_option_table *lopt;
12527 fprintf (fp, _(" ARM-specific assembler options:\n"));
12529 for (opt = arm_opts; opt->option != NULL; opt++)
12530 if (opt->help != NULL)
12531 fprintf (fp, " -%-23s%s\n", opt->option, _(opt->help));
12533 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
12534 if (lopt->help != NULL)
12535 fprintf (fp, " -%s%s\n", lopt->option, _(lopt->help));
12537 #ifdef OPTION_EB
12538 fprintf (fp, _("\
12539 -EB assemble code for a big-endian cpu\n"));
12540 #endif
12542 #ifdef OPTION_EL
12543 fprintf (fp, _("\
12544 -EL assemble code for a little-endian cpu\n"));
12545 #endif
12548 /* We need to be able to fix up arbitrary expressions in some statements.
12549 This is so that we can handle symbols that are an arbitrary distance from
12550 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
12551 which returns part of an address in a form which will be valid for
12552 a data instruction. We do this by pushing the expression into a symbol
12553 in the expr_section, and creating a fix for that. */
12555 static void
12556 fix_new_arm (frag, where, size, exp, pc_rel, reloc)
12557 fragS * frag;
12558 int where;
12559 short int size;
12560 expressionS * exp;
12561 int pc_rel;
12562 int reloc;
12564 fixS * new_fix;
12565 arm_fix_data * arm_data;
12567 switch (exp->X_op)
12569 case O_constant:
12570 case O_symbol:
12571 case O_add:
12572 case O_subtract:
12573 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
12574 break;
12576 default:
12577 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0,
12578 pc_rel, reloc);
12579 break;
12582 /* Mark whether the fix is to a THUMB instruction, or an ARM
12583 instruction. */
12584 arm_data = (arm_fix_data *) obstack_alloc (& notes, sizeof (arm_fix_data));
12585 new_fix->tc_fix_data = (PTR) arm_data;
12586 arm_data->thumb_mode = thumb_mode;
12588 return;
12591 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
12593 void
12594 cons_fix_new_arm (frag, where, size, exp)
12595 fragS * frag;
12596 int where;
12597 int size;
12598 expressionS * exp;
12600 bfd_reloc_code_real_type type;
12601 int pcrel = 0;
12603 /* Pick a reloc.
12604 FIXME: @@ Should look at CPU word size. */
12605 switch (size)
12607 case 1:
12608 type = BFD_RELOC_8;
12609 break;
12610 case 2:
12611 type = BFD_RELOC_16;
12612 break;
12613 case 4:
12614 default:
12615 type = BFD_RELOC_32;
12616 break;
12617 case 8:
12618 type = BFD_RELOC_64;
12619 break;
12622 fix_new_exp (frag, where, (int) size, exp, pcrel, type);
12625 /* A good place to do this, although this was probably not intended
12626 for this kind of use. We need to dump the literal pool before
12627 references are made to a null symbol pointer. */
12629 void
12630 arm_cleanup ()
12632 literal_pool * pool;
12634 for (pool = list_of_pools; pool; pool = pool->next)
12636 /* Put it at the end of the relevent section. */
12637 subseg_set (pool->section, pool->sub_section);
12638 s_ltorg (0);
12642 void
12643 arm_start_line_hook ()
12645 last_label_seen = NULL;
12648 void
12649 arm_frob_label (sym)
12650 symbolS * sym;
12652 last_label_seen = sym;
12654 ARM_SET_THUMB (sym, thumb_mode);
12656 #if defined OBJ_COFF || defined OBJ_ELF
12657 ARM_SET_INTERWORK (sym, support_interwork);
12658 #endif
12660 /* Note - do not allow local symbols (.Lxxx) to be labeled
12661 as Thumb functions. This is because these labels, whilst
12662 they exist inside Thumb code, are not the entry points for
12663 possible ARM->Thumb calls. Also, these labels can be used
12664 as part of a computed goto or switch statement. eg gcc
12665 can generate code that looks like this:
12667 ldr r2, [pc, .Laaa]
12668 lsl r3, r3, #2
12669 ldr r2, [r3, r2]
12670 mov pc, r2
12672 .Lbbb: .word .Lxxx
12673 .Lccc: .word .Lyyy
12674 ..etc...
12675 .Laaa: .word Lbbb
12677 The first instruction loads the address of the jump table.
12678 The second instruction converts a table index into a byte offset.
12679 The third instruction gets the jump address out of the table.
12680 The fourth instruction performs the jump.
12682 If the address stored at .Laaa is that of a symbol which has the
12683 Thumb_Func bit set, then the linker will arrange for this address
12684 to have the bottom bit set, which in turn would mean that the
12685 address computation performed by the third instruction would end
12686 up with the bottom bit set. Since the ARM is capable of unaligned
12687 word loads, the instruction would then load the incorrect address
12688 out of the jump table, and chaos would ensue. */
12689 if (label_is_thumb_function_name
12690 && (S_GET_NAME (sym)[0] != '.' || S_GET_NAME (sym)[1] != 'L')
12691 && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
12693 /* When the address of a Thumb function is taken the bottom
12694 bit of that address should be set. This will allow
12695 interworking between Arm and Thumb functions to work
12696 correctly. */
12698 THUMB_SET_FUNC (sym, 1);
12700 label_is_thumb_function_name = FALSE;
12704 /* Adjust the symbol table. This marks Thumb symbols as distinct from
12705 ARM ones. */
12707 void
12708 arm_adjust_symtab ()
12710 #ifdef OBJ_COFF
12711 symbolS * sym;
12713 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
12715 if (ARM_IS_THUMB (sym))
12717 if (THUMB_IS_FUNC (sym))
12719 /* Mark the symbol as a Thumb function. */
12720 if ( S_GET_STORAGE_CLASS (sym) == C_STAT
12721 || S_GET_STORAGE_CLASS (sym) == C_LABEL) /* This can happen! */
12722 S_SET_STORAGE_CLASS (sym, C_THUMBSTATFUNC);
12724 else if (S_GET_STORAGE_CLASS (sym) == C_EXT)
12725 S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC);
12726 else
12727 as_bad (_("%s: unexpected function type: %d"),
12728 S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym));
12730 else switch (S_GET_STORAGE_CLASS (sym))
12732 case C_EXT:
12733 S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
12734 break;
12735 case C_STAT:
12736 S_SET_STORAGE_CLASS (sym, C_THUMBSTAT);
12737 break;
12738 case C_LABEL:
12739 S_SET_STORAGE_CLASS (sym, C_THUMBLABEL);
12740 break;
12741 default:
12742 /* Do nothing. */
12743 break;
12747 if (ARM_IS_INTERWORK (sym))
12748 coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_flags = 0xFF;
12750 #endif
12751 #ifdef OBJ_ELF
12752 symbolS * sym;
12753 char bind;
12755 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
12757 if (ARM_IS_THUMB (sym))
12759 elf_symbol_type * elf_sym;
12761 elf_sym = elf_symbol (symbol_get_bfdsym (sym));
12762 bind = ELF_ST_BIND (elf_sym);
12764 /* If it's a .thumb_func, declare it as so,
12765 otherwise tag label as .code 16. */
12766 if (THUMB_IS_FUNC (sym))
12767 elf_sym->internal_elf_sym.st_info =
12768 ELF_ST_INFO (bind, STT_ARM_TFUNC);
12769 else
12770 elf_sym->internal_elf_sym.st_info =
12771 ELF_ST_INFO (bind, STT_ARM_16BIT);
12774 #endif
12778 arm_data_in_code ()
12780 if (thumb_mode && ! strncmp (input_line_pointer + 1, "data:", 5))
12782 *input_line_pointer = '/';
12783 input_line_pointer += 5;
12784 *input_line_pointer = 0;
12785 return 1;
12788 return 0;
12791 char *
12792 arm_canonicalize_symbol_name (name)
12793 char * name;
12795 int len;
12797 if (thumb_mode && (len = strlen (name)) > 5
12798 && streq (name + len - 5, "/data"))
12799 *(name + len - 5) = 0;
12801 return name;
12804 #if defined OBJ_COFF || defined OBJ_ELF
12805 void
12806 arm_validate_fix (fixP)
12807 fixS * fixP;
12809 /* If the destination of the branch is a defined symbol which does not have
12810 the THUMB_FUNC attribute, then we must be calling a function which has
12811 the (interfacearm) attribute. We look for the Thumb entry point to that
12812 function and change the branch to refer to that function instead. */
12813 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23
12814 && fixP->fx_addsy != NULL
12815 && S_IS_DEFINED (fixP->fx_addsy)
12816 && ! THUMB_IS_FUNC (fixP->fx_addsy))
12818 fixP->fx_addsy = find_real_start (fixP->fx_addsy);
12821 #endif
12824 arm_force_relocation (fixp)
12825 struct fix * fixp;
12827 #if defined (OBJ_COFF) && defined (TE_PE)
12828 if (fixp->fx_r_type == BFD_RELOC_RVA)
12829 return 1;
12830 #endif
12831 #ifdef OBJ_ELF
12832 if (fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
12833 || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
12834 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX
12835 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23)
12836 return 1;
12837 #endif
12839 /* Resolve these relocations even if the symbol is extern or weak. */
12840 if (fixp->fx_r_type == BFD_RELOC_ARM_IMMEDIATE
12841 || fixp->fx_r_type == BFD_RELOC_ARM_OFFSET_IMM
12842 || fixp->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
12843 return 0;
12845 return generic_force_reloc (fixp);
12848 #ifdef OBJ_COFF
12849 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
12850 local labels from being added to the output symbol table when they
12851 are used with the ADRL pseudo op. The ADRL relocation should always
12852 be resolved before the binbary is emitted, so it is safe to say that
12853 it is adjustable. */
12855 bfd_boolean
12856 arm_fix_adjustable (fixP)
12857 fixS * fixP;
12859 if (fixP->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
12860 return 1;
12861 return 0;
12863 #endif
12865 #ifdef OBJ_ELF
12866 /* Relocations against Thumb function names must be left unadjusted,
12867 so that the linker can use this information to correctly set the
12868 bottom bit of their addresses. The MIPS version of this function
12869 also prevents relocations that are mips-16 specific, but I do not
12870 know why it does this.
12872 FIXME:
12873 There is one other problem that ought to be addressed here, but
12874 which currently is not: Taking the address of a label (rather
12875 than a function) and then later jumping to that address. Such
12876 addresses also ought to have their bottom bit set (assuming that
12877 they reside in Thumb code), but at the moment they will not. */
12879 bfd_boolean
12880 arm_fix_adjustable (fixP)
12881 fixS * fixP;
12883 if (fixP->fx_addsy == NULL)
12884 return 1;
12886 if (THUMB_IS_FUNC (fixP->fx_addsy)
12887 && fixP->fx_subsy == NULL)
12888 return 0;
12890 /* We need the symbol name for the VTABLE entries. */
12891 if ( fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
12892 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
12893 return 0;
12895 /* Don't allow symbols to be discarded on GOT related relocs. */
12896 if (fixP->fx_r_type == BFD_RELOC_ARM_PLT32
12897 || fixP->fx_r_type == BFD_RELOC_ARM_GOT32
12898 || fixP->fx_r_type == BFD_RELOC_ARM_GOTOFF)
12899 return 0;
12901 return 1;
12904 const char *
12905 elf32_arm_target_format ()
12907 if (target_big_endian)
12909 if (target_oabi)
12910 return "elf32-bigarm-oabi";
12911 else
12912 return "elf32-bigarm";
12914 else
12916 if (target_oabi)
12917 return "elf32-littlearm-oabi";
12918 else
12919 return "elf32-littlearm";
12923 void
12924 armelf_frob_symbol (symp, puntp)
12925 symbolS * symp;
12926 int * puntp;
12928 elf_frob_symbol (symp, puntp);
12931 static bfd_reloc_code_real_type
12932 arm_parse_reloc ()
12934 char id [16];
12935 char * ip;
12936 unsigned int i;
12937 static struct
12939 char * str;
12940 int len;
12941 bfd_reloc_code_real_type reloc;
12943 reloc_map[] =
12945 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
12946 MAP ("(got)", BFD_RELOC_ARM_GOT32),
12947 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF),
12948 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
12949 branch instructions generated by GCC for PLT relocs. */
12950 MAP ("(plt)", BFD_RELOC_ARM_PLT32),
12951 { NULL, 0, BFD_RELOC_UNUSED }
12952 #undef MAP
12955 for (i = 0, ip = input_line_pointer;
12956 i < sizeof (id) && (ISALNUM (*ip) || ISPUNCT (*ip));
12957 i++, ip++)
12958 id[i] = TOLOWER (*ip);
12960 for (i = 0; reloc_map[i].str; i++)
12961 if (strncmp (id, reloc_map[i].str, reloc_map[i].len) == 0)
12962 break;
12964 input_line_pointer += reloc_map[i].len;
12966 return reloc_map[i].reloc;
12969 static void
12970 s_arm_elf_cons (nbytes)
12971 int nbytes;
12973 expressionS exp;
12975 #ifdef md_flush_pending_output
12976 md_flush_pending_output ();
12977 #endif
12979 if (is_it_end_of_statement ())
12981 demand_empty_rest_of_line ();
12982 return;
12985 #ifdef md_cons_align
12986 md_cons_align (nbytes);
12987 #endif
12989 mapping_state (MAP_DATA);
12992 bfd_reloc_code_real_type reloc;
12994 expression (& exp);
12996 if (exp.X_op == O_symbol
12997 && * input_line_pointer == '('
12998 && (reloc = arm_parse_reloc ()) != BFD_RELOC_UNUSED)
13000 reloc_howto_type *howto = bfd_reloc_type_lookup (stdoutput, reloc);
13001 int size = bfd_get_reloc_size (howto);
13003 if (size > nbytes)
13004 as_bad ("%s relocations do not fit in %d bytes",
13005 howto->name, nbytes);
13006 else
13008 register char *p = frag_more ((int) nbytes);
13009 int offset = nbytes - size;
13011 fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size,
13012 &exp, 0, reloc);
13015 else
13016 emit_expr (&exp, (unsigned int) nbytes);
13018 while (*input_line_pointer++ == ',');
13020 /* Put terminator back into stream. */
13021 input_line_pointer --;
13022 demand_empty_rest_of_line ();
13025 #endif /* OBJ_ELF */
13027 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
13028 of an rs_align_code fragment. */
13030 void
13031 arm_handle_align (fragP)
13032 fragS *fragP;
13034 static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 };
13035 static char const thumb_noop[2] = { 0xc0, 0x46 };
13036 static char const arm_bigend_noop[4] = { 0xe1, 0xa0, 0x00, 0x00 };
13037 static char const thumb_bigend_noop[2] = { 0x46, 0xc0 };
13039 int bytes, fix, noop_size;
13040 char * p;
13041 const char * noop;
13043 if (fragP->fr_type != rs_align_code)
13044 return;
13046 bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
13047 p = fragP->fr_literal + fragP->fr_fix;
13048 fix = 0;
13050 if (bytes > MAX_MEM_FOR_RS_ALIGN_CODE)
13051 bytes &= MAX_MEM_FOR_RS_ALIGN_CODE;
13053 if (fragP->tc_frag_data)
13055 if (target_big_endian)
13056 noop = thumb_bigend_noop;
13057 else
13058 noop = thumb_noop;
13059 noop_size = sizeof (thumb_noop);
13061 else
13063 if (target_big_endian)
13064 noop = arm_bigend_noop;
13065 else
13066 noop = arm_noop;
13067 noop_size = sizeof (arm_noop);
13070 if (bytes & (noop_size - 1))
13072 fix = bytes & (noop_size - 1);
13073 memset (p, 0, fix);
13074 p += fix;
13075 bytes -= fix;
13078 while (bytes >= noop_size)
13080 memcpy (p, noop, noop_size);
13081 p += noop_size;
13082 bytes -= noop_size;
13083 fix += noop_size;
13086 fragP->fr_fix += fix;
13087 fragP->fr_var = noop_size;
13090 /* Called from md_do_align. Used to create an alignment
13091 frag in a code section. */
13093 void
13094 arm_frag_align_code (n, max)
13095 int n;
13096 int max;
13098 char * p;
13100 /* We assume that there will never be a requirment
13101 to support alignments greater than 32 bytes. */
13102 if (max > MAX_MEM_FOR_RS_ALIGN_CODE)
13103 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
13105 p = frag_var (rs_align_code,
13106 MAX_MEM_FOR_RS_ALIGN_CODE,
13108 (relax_substateT) max,
13109 (symbolS *) NULL,
13110 (offsetT) n,
13111 (char *) NULL);
13112 *p = 0;
13116 /* Perform target specific initialisation of a frag. */
13118 void
13119 arm_init_frag (fragP)
13120 fragS *fragP;
13122 /* Record whether this frag is in an ARM or a THUMB area. */
13123 fragP->tc_frag_data = thumb_mode;