* ld-mmix/bpo-9.d, ld-mmix/bpo-10.d, ld-mmix/bpo-11.d: Adjust for
[binutils.git] / gas / config / tc-arm.c
blob907191ac48c51880146cba02238d369a9f05025c
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;
585 /* Some well known registers that we refer to directly elsewhere. */
586 #define REG_SP 13
587 #define REG_LR 14
588 #define REG_PC 15
590 #define wr_register(reg) ((reg ^ WR_PREFIX) >= 0 && (reg ^ WR_PREFIX) <= 15)
591 #define wc_register(reg) ((reg ^ WC_PREFIX) >= 0 && (reg ^ WC_PREFIX) <= 15)
592 #define wcg_register(reg) ((reg ^ WC_PREFIX) >= 8 && (reg ^ WC_PREFIX) <= 11)
594 /* These are the standard names. Users can add aliases with .req. */
595 /* Integer Register Numbers. */
596 static const struct reg_entry rn_table[] =
598 {"r0", 0}, {"r1", 1}, {"r2", 2}, {"r3", 3},
599 {"r4", 4}, {"r5", 5}, {"r6", 6}, {"r7", 7},
600 {"r8", 8}, {"r9", 9}, {"r10", 10}, {"r11", 11},
601 {"r12", 12}, {"r13", REG_SP}, {"r14", REG_LR}, {"r15", REG_PC},
602 /* ATPCS Synonyms. */
603 {"a1", 0}, {"a2", 1}, {"a3", 2}, {"a4", 3},
604 {"v1", 4}, {"v2", 5}, {"v3", 6}, {"v4", 7},
605 {"v5", 8}, {"v6", 9}, {"v7", 10}, {"v8", 11},
606 /* Well-known aliases. */
607 {"wr", 7},
608 {"sb", 9}, {"sl", 10}, {"fp", 11},
609 {"ip", 12}, {"sp", REG_SP}, {"lr", REG_LR}, {"pc", REG_PC},
610 {NULL, 0}
613 #define WR_PREFIX 0x200
614 #define WC_PREFIX 0x400
616 static const struct reg_entry iwmmxt_table[] =
618 /* Intel Wireless MMX technology register names. */
619 { "wr0", 0x0 | WR_PREFIX}, {"wr1", 0x1 | WR_PREFIX},
620 { "wr2", 0x2 | WR_PREFIX}, {"wr3", 0x3 | WR_PREFIX},
621 { "wr4", 0x4 | WR_PREFIX}, {"wr5", 0x5 | WR_PREFIX},
622 { "wr6", 0x6 | WR_PREFIX}, {"wr7", 0x7 | WR_PREFIX},
623 { "wr8", 0x8 | WR_PREFIX}, {"wr9", 0x9 | WR_PREFIX},
624 { "wr10", 0xa | WR_PREFIX}, {"wr11", 0xb | WR_PREFIX},
625 { "wr12", 0xc | WR_PREFIX}, {"wr13", 0xd | WR_PREFIX},
626 { "wr14", 0xe | WR_PREFIX}, {"wr15", 0xf | WR_PREFIX},
627 { "wcid", 0x0 | WC_PREFIX}, {"wcon", 0x1 | WC_PREFIX},
628 {"wcssf", 0x2 | WC_PREFIX}, {"wcasf", 0x3 | WC_PREFIX},
629 {"wcgr0", 0x8 | WC_PREFIX}, {"wcgr1", 0x9 | WC_PREFIX},
630 {"wcgr2", 0xa | WC_PREFIX}, {"wcgr3", 0xb | WC_PREFIX},
632 { "wR0", 0x0 | WR_PREFIX}, {"wR1", 0x1 | WR_PREFIX},
633 { "wR2", 0x2 | WR_PREFIX}, {"wR3", 0x3 | WR_PREFIX},
634 { "wR4", 0x4 | WR_PREFIX}, {"wR5", 0x5 | WR_PREFIX},
635 { "wR6", 0x6 | WR_PREFIX}, {"wR7", 0x7 | WR_PREFIX},
636 { "wR8", 0x8 | WR_PREFIX}, {"wR9", 0x9 | WR_PREFIX},
637 { "wR10", 0xa | WR_PREFIX}, {"wR11", 0xb | WR_PREFIX},
638 { "wR12", 0xc | WR_PREFIX}, {"wR13", 0xd | WR_PREFIX},
639 { "wR14", 0xe | WR_PREFIX}, {"wR15", 0xf | WR_PREFIX},
640 { "wCID", 0x0 | WC_PREFIX}, {"wCon", 0x1 | WC_PREFIX},
641 {"wCSSF", 0x2 | WC_PREFIX}, {"wCASF", 0x3 | WC_PREFIX},
642 {"wCGR0", 0x8 | WC_PREFIX}, {"wCGR1", 0x9 | WC_PREFIX},
643 {"wCGR2", 0xa | WC_PREFIX}, {"wCGR3", 0xb | WC_PREFIX},
644 {NULL, 0}
647 /* Co-processor Numbers. */
648 static const struct reg_entry cp_table[] =
650 {"p0", 0}, {"p1", 1}, {"p2", 2}, {"p3", 3},
651 {"p4", 4}, {"p5", 5}, {"p6", 6}, {"p7", 7},
652 {"p8", 8}, {"p9", 9}, {"p10", 10}, {"p11", 11},
653 {"p12", 12}, {"p13", 13}, {"p14", 14}, {"p15", 15},
654 {NULL, 0}
657 /* Co-processor Register Numbers. */
658 static const struct reg_entry cn_table[] =
660 {"c0", 0}, {"c1", 1}, {"c2", 2}, {"c3", 3},
661 {"c4", 4}, {"c5", 5}, {"c6", 6}, {"c7", 7},
662 {"c8", 8}, {"c9", 9}, {"c10", 10}, {"c11", 11},
663 {"c12", 12}, {"c13", 13}, {"c14", 14}, {"c15", 15},
664 /* Not really valid, but kept for back-wards compatibility. */
665 {"cr0", 0}, {"cr1", 1}, {"cr2", 2}, {"cr3", 3},
666 {"cr4", 4}, {"cr5", 5}, {"cr6", 6}, {"cr7", 7},
667 {"cr8", 8}, {"cr9", 9}, {"cr10", 10}, {"cr11", 11},
668 {"cr12", 12}, {"cr13", 13}, {"cr14", 14}, {"cr15", 15},
669 {NULL, 0}
672 /* FPA Registers. */
673 static const struct reg_entry fn_table[] =
675 {"f0", 0}, {"f1", 1}, {"f2", 2}, {"f3", 3},
676 {"f4", 4}, {"f5", 5}, {"f6", 6}, {"f7", 7},
677 {NULL, 0}
680 /* VFP SP Registers. */
681 static const struct reg_entry sn_table[] =
683 {"s0", 0}, {"s1", 1}, {"s2", 2}, {"s3", 3},
684 {"s4", 4}, {"s5", 5}, {"s6", 6}, {"s7", 7},
685 {"s8", 8}, {"s9", 9}, {"s10", 10}, {"s11", 11},
686 {"s12", 12}, {"s13", 13}, {"s14", 14}, {"s15", 15},
687 {"s16", 16}, {"s17", 17}, {"s18", 18}, {"s19", 19},
688 {"s20", 20}, {"s21", 21}, {"s22", 22}, {"s23", 23},
689 {"s24", 24}, {"s25", 25}, {"s26", 26}, {"s27", 27},
690 {"s28", 28}, {"s29", 29}, {"s30", 30}, {"s31", 31},
691 {NULL, 0}
694 /* VFP DP Registers. */
695 static const struct reg_entry dn_table[] =
697 {"d0", 0}, {"d1", 1}, {"d2", 2}, {"d3", 3},
698 {"d4", 4}, {"d5", 5}, {"d6", 6}, {"d7", 7},
699 {"d8", 8}, {"d9", 9}, {"d10", 10}, {"d11", 11},
700 {"d12", 12}, {"d13", 13}, {"d14", 14}, {"d15", 15},
701 {NULL, 0}
704 /* Maverick DSP coprocessor registers. */
705 static const struct reg_entry mav_mvf_table[] =
707 {"mvf0", 0}, {"mvf1", 1}, {"mvf2", 2}, {"mvf3", 3},
708 {"mvf4", 4}, {"mvf5", 5}, {"mvf6", 6}, {"mvf7", 7},
709 {"mvf8", 8}, {"mvf9", 9}, {"mvf10", 10}, {"mvf11", 11},
710 {"mvf12", 12}, {"mvf13", 13}, {"mvf14", 14}, {"mvf15", 15},
711 {NULL, 0}
714 static const struct reg_entry mav_mvd_table[] =
716 {"mvd0", 0}, {"mvd1", 1}, {"mvd2", 2}, {"mvd3", 3},
717 {"mvd4", 4}, {"mvd5", 5}, {"mvd6", 6}, {"mvd7", 7},
718 {"mvd8", 8}, {"mvd9", 9}, {"mvd10", 10}, {"mvd11", 11},
719 {"mvd12", 12}, {"mvd13", 13}, {"mvd14", 14}, {"mvd15", 15},
720 {NULL, 0}
723 static const struct reg_entry mav_mvfx_table[] =
725 {"mvfx0", 0}, {"mvfx1", 1}, {"mvfx2", 2}, {"mvfx3", 3},
726 {"mvfx4", 4}, {"mvfx5", 5}, {"mvfx6", 6}, {"mvfx7", 7},
727 {"mvfx8", 8}, {"mvfx9", 9}, {"mvfx10", 10}, {"mvfx11", 11},
728 {"mvfx12", 12}, {"mvfx13", 13}, {"mvfx14", 14}, {"mvfx15", 15},
729 {NULL, 0}
732 static const struct reg_entry mav_mvdx_table[] =
734 {"mvdx0", 0}, {"mvdx1", 1}, {"mvdx2", 2}, {"mvdx3", 3},
735 {"mvdx4", 4}, {"mvdx5", 5}, {"mvdx6", 6}, {"mvdx7", 7},
736 {"mvdx8", 8}, {"mvdx9", 9}, {"mvdx10", 10}, {"mvdx11", 11},
737 {"mvdx12", 12}, {"mvdx13", 13}, {"mvdx14", 14}, {"mvdx15", 15},
738 {NULL, 0}
741 static const struct reg_entry mav_mvax_table[] =
743 {"mvax0", 0}, {"mvax1", 1}, {"mvax2", 2}, {"mvax3", 3},
744 {NULL, 0}
747 static const struct reg_entry mav_dspsc_table[] =
749 {"dspsc", 0},
750 {NULL, 0}
753 struct reg_map
755 const struct reg_entry *names;
756 int max_regno;
757 struct hash_control *htab;
758 const char *expected;
761 struct reg_map all_reg_maps[] =
763 {rn_table, 15, NULL, N_("ARM register expected")},
764 {cp_table, 15, NULL, N_("bad or missing co-processor number")},
765 {cn_table, 15, NULL, N_("co-processor register expected")},
766 {fn_table, 7, NULL, N_("FPA register expected")},
767 {sn_table, 31, NULL, N_("VFP single precision register expected")},
768 {dn_table, 15, NULL, N_("VFP double precision register expected")},
769 {mav_mvf_table, 15, NULL, N_("Maverick MVF register expected")},
770 {mav_mvd_table, 15, NULL, N_("Maverick MVD register expected")},
771 {mav_mvfx_table, 15, NULL, N_("Maverick MVFX register expected")},
772 {mav_mvdx_table, 15, NULL, N_("Maverick MVFX register expected")},
773 {mav_mvax_table, 3, NULL, N_("Maverick MVAX register expected")},
774 {mav_dspsc_table, 0, NULL, N_("Maverick DSPSC register expected")},
775 {iwmmxt_table, 23, NULL, N_("Intel Wireless MMX technology register expected")},
778 /* Enumeration matching entries in table above. */
779 enum arm_reg_type
781 REG_TYPE_RN = 0,
782 #define REG_TYPE_FIRST REG_TYPE_RN
783 REG_TYPE_CP = 1,
784 REG_TYPE_CN = 2,
785 REG_TYPE_FN = 3,
786 REG_TYPE_SN = 4,
787 REG_TYPE_DN = 5,
788 REG_TYPE_MVF = 6,
789 REG_TYPE_MVD = 7,
790 REG_TYPE_MVFX = 8,
791 REG_TYPE_MVDX = 9,
792 REG_TYPE_MVAX = 10,
793 REG_TYPE_DSPSC = 11,
794 REG_TYPE_IWMMXT = 12,
796 REG_TYPE_MAX = 13
799 /* Functions called by parser. */
800 /* ARM instructions. */
801 static void do_arit PARAMS ((char *));
802 static void do_cmp PARAMS ((char *));
803 static void do_mov PARAMS ((char *));
804 static void do_ldst PARAMS ((char *));
805 static void do_ldstt PARAMS ((char *));
806 static void do_ldmstm PARAMS ((char *));
807 static void do_branch PARAMS ((char *));
808 static void do_swi PARAMS ((char *));
810 /* Pseudo Op codes. */
811 static void do_adr PARAMS ((char *));
812 static void do_adrl PARAMS ((char *));
813 static void do_empty PARAMS ((char *));
815 /* ARM v2. */
816 static void do_mul PARAMS ((char *));
817 static void do_mla PARAMS ((char *));
819 /* ARM v2S. */
820 static void do_swap PARAMS ((char *));
822 /* ARM v3. */
823 static void do_msr PARAMS ((char *));
824 static void do_mrs PARAMS ((char *));
826 /* ARM v3M. */
827 static void do_mull PARAMS ((char *));
829 /* ARM v4. */
830 static void do_ldstv4 PARAMS ((char *));
832 /* ARM v4T. */
833 static void do_bx PARAMS ((char *));
835 /* ARM v5T. */
836 static void do_blx PARAMS ((char *));
837 static void do_bkpt PARAMS ((char *));
838 static void do_clz PARAMS ((char *));
839 static void do_lstc2 PARAMS ((char *));
840 static void do_cdp2 PARAMS ((char *));
841 static void do_co_reg2 PARAMS ((char *));
843 /* ARM v5TExP. */
844 static void do_smla PARAMS ((char *));
845 static void do_smlal PARAMS ((char *));
846 static void do_smul PARAMS ((char *));
847 static void do_qadd PARAMS ((char *));
849 /* ARM v5TE. */
850 static void do_pld PARAMS ((char *));
851 static void do_ldrd PARAMS ((char *));
852 static void do_co_reg2c PARAMS ((char *));
854 /* ARM v5TEJ. */
855 static void do_bxj PARAMS ((char *));
857 /* Coprocessor Instructions. */
858 static void do_cdp PARAMS ((char *));
859 static void do_lstc PARAMS ((char *));
860 static void do_co_reg PARAMS ((char *));
862 /* FPA instructions. */
863 static void do_fpa_ctrl PARAMS ((char *));
864 static void do_fpa_ldst PARAMS ((char *));
865 static void do_fpa_ldmstm PARAMS ((char *));
866 static void do_fpa_dyadic PARAMS ((char *));
867 static void do_fpa_monadic PARAMS ((char *));
868 static void do_fpa_cmp PARAMS ((char *));
869 static void do_fpa_from_reg PARAMS ((char *));
870 static void do_fpa_to_reg PARAMS ((char *));
872 /* VFP instructions. */
873 static void do_vfp_sp_monadic PARAMS ((char *));
874 static void do_vfp_dp_monadic PARAMS ((char *));
875 static void do_vfp_sp_dyadic PARAMS ((char *));
876 static void do_vfp_dp_dyadic PARAMS ((char *));
877 static void do_vfp_reg_from_sp PARAMS ((char *));
878 static void do_vfp_sp_from_reg PARAMS ((char *));
879 static void do_vfp_sp_reg2 PARAMS ((char *));
880 static void do_vfp_reg_from_dp PARAMS ((char *));
881 static void do_vfp_reg2_from_dp PARAMS ((char *));
882 static void do_vfp_dp_from_reg PARAMS ((char *));
883 static void do_vfp_dp_from_reg2 PARAMS ((char *));
884 static void do_vfp_reg_from_ctrl PARAMS ((char *));
885 static void do_vfp_ctrl_from_reg PARAMS ((char *));
886 static void do_vfp_sp_ldst PARAMS ((char *));
887 static void do_vfp_dp_ldst PARAMS ((char *));
888 static void do_vfp_sp_ldstmia PARAMS ((char *));
889 static void do_vfp_sp_ldstmdb PARAMS ((char *));
890 static void do_vfp_dp_ldstmia PARAMS ((char *));
891 static void do_vfp_dp_ldstmdb PARAMS ((char *));
892 static void do_vfp_xp_ldstmia PARAMS ((char *));
893 static void do_vfp_xp_ldstmdb PARAMS ((char *));
894 static void do_vfp_sp_compare_z PARAMS ((char *));
895 static void do_vfp_dp_compare_z PARAMS ((char *));
896 static void do_vfp_dp_sp_cvt PARAMS ((char *));
897 static void do_vfp_sp_dp_cvt PARAMS ((char *));
899 /* XScale. */
900 static void do_xsc_mia PARAMS ((char *));
901 static void do_xsc_mar PARAMS ((char *));
902 static void do_xsc_mra PARAMS ((char *));
904 /* Maverick. */
905 static void do_mav_binops PARAMS ((char *, int, enum arm_reg_type,
906 enum arm_reg_type));
907 static void do_mav_binops_1a PARAMS ((char *));
908 static void do_mav_binops_1b PARAMS ((char *));
909 static void do_mav_binops_1c PARAMS ((char *));
910 static void do_mav_binops_1d PARAMS ((char *));
911 static void do_mav_binops_1e PARAMS ((char *));
912 static void do_mav_binops_1f PARAMS ((char *));
913 static void do_mav_binops_1g PARAMS ((char *));
914 static void do_mav_binops_1h PARAMS ((char *));
915 static void do_mav_binops_1i PARAMS ((char *));
916 static void do_mav_binops_1j PARAMS ((char *));
917 static void do_mav_binops_1k PARAMS ((char *));
918 static void do_mav_binops_1l PARAMS ((char *));
919 static void do_mav_binops_1m PARAMS ((char *));
920 static void do_mav_binops_1n PARAMS ((char *));
921 static void do_mav_binops_1o PARAMS ((char *));
922 static void do_mav_binops_2a PARAMS ((char *));
923 static void do_mav_binops_2b PARAMS ((char *));
924 static void do_mav_binops_2c PARAMS ((char *));
925 static void do_mav_binops_3a PARAMS ((char *));
926 static void do_mav_binops_3b PARAMS ((char *));
927 static void do_mav_binops_3c PARAMS ((char *));
928 static void do_mav_binops_3d PARAMS ((char *));
929 static void do_mav_triple PARAMS ((char *, int, enum arm_reg_type,
930 enum arm_reg_type,
931 enum arm_reg_type));
932 static void do_mav_triple_4a PARAMS ((char *));
933 static void do_mav_triple_4b PARAMS ((char *));
934 static void do_mav_triple_5a PARAMS ((char *));
935 static void do_mav_triple_5b PARAMS ((char *));
936 static void do_mav_triple_5c PARAMS ((char *));
937 static void do_mav_triple_5d PARAMS ((char *));
938 static void do_mav_triple_5e PARAMS ((char *));
939 static void do_mav_triple_5f PARAMS ((char *));
940 static void do_mav_triple_5g PARAMS ((char *));
941 static void do_mav_triple_5h PARAMS ((char *));
942 static void do_mav_quad PARAMS ((char *, int, enum arm_reg_type,
943 enum arm_reg_type,
944 enum arm_reg_type,
945 enum arm_reg_type));
946 static void do_mav_quad_6a PARAMS ((char *));
947 static void do_mav_quad_6b PARAMS ((char *));
948 static void do_mav_dspsc_1 PARAMS ((char *));
949 static void do_mav_dspsc_2 PARAMS ((char *));
950 static void do_mav_shift PARAMS ((char *, enum arm_reg_type,
951 enum arm_reg_type));
952 static void do_mav_shift_1 PARAMS ((char *));
953 static void do_mav_shift_2 PARAMS ((char *));
954 static void do_mav_ldst PARAMS ((char *, enum arm_reg_type));
955 static void do_mav_ldst_1 PARAMS ((char *));
956 static void do_mav_ldst_2 PARAMS ((char *));
957 static void do_mav_ldst_3 PARAMS ((char *));
958 static void do_mav_ldst_4 PARAMS ((char *));
960 static int mav_reg_required_here PARAMS ((char **, int,
961 enum arm_reg_type));
962 static int mav_parse_offset PARAMS ((char **, int *));
964 static void fix_new_arm PARAMS ((fragS *, int, short, expressionS *,
965 int, int));
966 static int arm_reg_parse PARAMS ((char **, struct hash_control *));
967 static enum arm_reg_type arm_reg_parse_any PARAMS ((char *));
968 static const struct asm_psr * arm_psr_parse PARAMS ((char **));
969 static void symbol_locate PARAMS ((symbolS *, const char *, segT, valueT,
970 fragS *));
971 static int add_to_lit_pool PARAMS ((void));
972 static unsigned validate_immediate PARAMS ((unsigned));
973 static unsigned validate_immediate_twopart PARAMS ((unsigned int,
974 unsigned int *));
975 static int validate_offset_imm PARAMS ((unsigned int, int));
976 static void opcode_select PARAMS ((int));
977 static void end_of_line PARAMS ((char *));
978 static int reg_required_here PARAMS ((char **, int));
979 static int psr_required_here PARAMS ((char **));
980 static int co_proc_number PARAMS ((char **));
981 static int cp_opc_expr PARAMS ((char **, int, int));
982 static int cp_reg_required_here PARAMS ((char **, int));
983 static int fp_reg_required_here PARAMS ((char **, int));
984 static int vfp_sp_reg_required_here PARAMS ((char **, enum vfp_sp_reg_pos));
985 static int vfp_dp_reg_required_here PARAMS ((char **, enum vfp_dp_reg_pos));
986 static void vfp_sp_ldstm PARAMS ((char *, enum vfp_ldstm_type));
987 static void vfp_dp_ldstm PARAMS ((char *, enum vfp_ldstm_type));
988 static long vfp_sp_reg_list PARAMS ((char **, enum vfp_sp_reg_pos));
989 static long vfp_dp_reg_list PARAMS ((char **));
990 static int vfp_psr_required_here PARAMS ((char **str));
991 static const struct vfp_reg *vfp_psr_parse PARAMS ((char **str));
992 static int cp_address_offset PARAMS ((char **));
993 static int cp_address_required_here PARAMS ((char **, int));
994 static int my_get_float_expression PARAMS ((char **));
995 static int skip_past_comma PARAMS ((char **));
996 static int walk_no_bignums PARAMS ((symbolS *));
997 static int negate_data_op PARAMS ((unsigned long *, unsigned long));
998 static int data_op2 PARAMS ((char **));
999 static int fp_op2 PARAMS ((char **));
1000 static long reg_list PARAMS ((char **));
1001 static void thumb_load_store PARAMS ((char *, int, int));
1002 static int decode_shift PARAMS ((char **, int));
1003 static int ldst_extend PARAMS ((char **));
1004 static int ldst_extend_v4 PARAMS ((char **));
1005 static void thumb_add_sub PARAMS ((char *, int));
1006 static void insert_reg PARAMS ((const struct reg_entry *,
1007 struct hash_control *));
1008 static void thumb_shift PARAMS ((char *, int));
1009 static void thumb_mov_compare PARAMS ((char *, int));
1010 static void build_arm_ops_hsh PARAMS ((void));
1011 static void set_constant_flonums PARAMS ((void));
1012 static valueT md_chars_to_number PARAMS ((char *, int));
1013 static void build_reg_hsh PARAMS ((struct reg_map *));
1014 static void insert_reg_alias PARAMS ((char *, int, struct hash_control *));
1015 static int create_register_alias PARAMS ((char *, char *));
1016 static void output_inst PARAMS ((const char *));
1017 static int accum0_required_here PARAMS ((char **));
1018 static int ld_mode_required_here PARAMS ((char **));
1019 static void do_branch25 PARAMS ((char *));
1020 static symbolS * find_real_start PARAMS ((symbolS *));
1021 #ifdef OBJ_ELF
1022 static bfd_reloc_code_real_type arm_parse_reloc PARAMS ((void));
1023 #endif
1025 static int wreg_required_here PARAMS ((char **, int, enum wreg_type));
1026 static void do_iwmmxt_byte_addr PARAMS ((char *));
1027 static void do_iwmmxt_tandc PARAMS ((char *));
1028 static void do_iwmmxt_tbcst PARAMS ((char *));
1029 static void do_iwmmxt_textrc PARAMS ((char *));
1030 static void do_iwmmxt_textrm PARAMS ((char *));
1031 static void do_iwmmxt_tinsr PARAMS ((char *));
1032 static void do_iwmmxt_tmcr PARAMS ((char *));
1033 static void do_iwmmxt_tmcrr PARAMS ((char *));
1034 static void do_iwmmxt_tmia PARAMS ((char *));
1035 static void do_iwmmxt_tmovmsk PARAMS ((char *));
1036 static void do_iwmmxt_tmrc PARAMS ((char *));
1037 static void do_iwmmxt_tmrrc PARAMS ((char *));
1038 static void do_iwmmxt_torc PARAMS ((char *));
1039 static void do_iwmmxt_waligni PARAMS ((char *));
1040 static void do_iwmmxt_wmov PARAMS ((char *));
1041 static void do_iwmmxt_word_addr PARAMS ((char *));
1042 static void do_iwmmxt_wrwr PARAMS ((char *));
1043 static void do_iwmmxt_wrwrwcg PARAMS ((char *));
1044 static void do_iwmmxt_wrwrwr PARAMS ((char *));
1045 static void do_iwmmxt_wshufh PARAMS ((char *));
1046 static void do_iwmmxt_wzero PARAMS ((char *));
1047 static int cp_byte_address_offset PARAMS ((char **));
1048 static int cp_byte_address_required_here PARAMS ((char **));
1050 /* ARM instructions take 4bytes in the object file, Thumb instructions
1051 take 2: */
1052 #define INSN_SIZE 4
1054 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
1055 #define MAV_MODE1 0x100c
1057 /* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
1058 #define MAV_MODE2 0x0c10
1060 /* "INSN<cond> X,Y" where X:0, Y:bit16. */
1061 #define MAV_MODE3 0x1000
1063 /* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
1064 #define MAV_MODE4 0x0c0010
1066 /* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
1067 #define MAV_MODE5 0x00100c
1069 /* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
1070 #define MAV_MODE6 0x00100c05
1072 struct asm_opcode
1074 /* Basic string to match. */
1075 const char * template;
1077 /* Basic instruction code. */
1078 unsigned long value;
1080 /* Offset into the template where the condition code (if any) will be.
1081 If zero, then the instruction is never conditional. */
1082 unsigned cond_offset;
1084 /* Which architecture variant provides this instruction. */
1085 unsigned long variant;
1087 /* Function to call to parse args. */
1088 void (* parms) PARAMS ((char *));
1091 static const struct asm_opcode insns[] =
1093 /* Core ARM Instructions. */
1094 {"and", 0xe0000000, 3, ARM_EXT_V1, do_arit},
1095 {"ands", 0xe0100000, 3, ARM_EXT_V1, do_arit},
1096 {"eor", 0xe0200000, 3, ARM_EXT_V1, do_arit},
1097 {"eors", 0xe0300000, 3, ARM_EXT_V1, do_arit},
1098 {"sub", 0xe0400000, 3, ARM_EXT_V1, do_arit},
1099 {"subs", 0xe0500000, 3, ARM_EXT_V1, do_arit},
1100 {"rsb", 0xe0600000, 3, ARM_EXT_V1, do_arit},
1101 {"rsbs", 0xe0700000, 3, ARM_EXT_V1, do_arit},
1102 {"add", 0xe0800000, 3, ARM_EXT_V1, do_arit},
1103 {"adds", 0xe0900000, 3, ARM_EXT_V1, do_arit},
1104 {"adc", 0xe0a00000, 3, ARM_EXT_V1, do_arit},
1105 {"adcs", 0xe0b00000, 3, ARM_EXT_V1, do_arit},
1106 {"sbc", 0xe0c00000, 3, ARM_EXT_V1, do_arit},
1107 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1, do_arit},
1108 {"rsc", 0xe0e00000, 3, ARM_EXT_V1, do_arit},
1109 {"rscs", 0xe0f00000, 3, ARM_EXT_V1, do_arit},
1110 {"orr", 0xe1800000, 3, ARM_EXT_V1, do_arit},
1111 {"orrs", 0xe1900000, 3, ARM_EXT_V1, do_arit},
1112 {"bic", 0xe1c00000, 3, ARM_EXT_V1, do_arit},
1113 {"bics", 0xe1d00000, 3, ARM_EXT_V1, do_arit},
1115 {"tst", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
1116 {"tsts", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
1117 {"tstp", 0xe110f000, 3, ARM_EXT_V1, do_cmp},
1118 {"teq", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
1119 {"teqs", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
1120 {"teqp", 0xe130f000, 3, ARM_EXT_V1, do_cmp},
1121 {"cmp", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
1122 {"cmps", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
1123 {"cmpp", 0xe150f000, 3, ARM_EXT_V1, do_cmp},
1124 {"cmn", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
1125 {"cmns", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
1126 {"cmnp", 0xe170f000, 3, ARM_EXT_V1, do_cmp},
1128 {"mov", 0xe1a00000, 3, ARM_EXT_V1, do_mov},
1129 {"movs", 0xe1b00000, 3, ARM_EXT_V1, do_mov},
1130 {"mvn", 0xe1e00000, 3, ARM_EXT_V1, do_mov},
1131 {"mvns", 0xe1f00000, 3, ARM_EXT_V1, do_mov},
1133 {"ldr", 0xe4100000, 3, ARM_EXT_V1, do_ldst},
1134 {"ldrb", 0xe4500000, 3, ARM_EXT_V1, do_ldst},
1135 {"ldrt", 0xe4300000, 3, ARM_EXT_V1, do_ldstt},
1136 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1, do_ldstt},
1137 {"str", 0xe4000000, 3, ARM_EXT_V1, do_ldst},
1138 {"strb", 0xe4400000, 3, ARM_EXT_V1, do_ldst},
1139 {"strt", 0xe4200000, 3, ARM_EXT_V1, do_ldstt},
1140 {"strbt", 0xe4600000, 3, ARM_EXT_V1, do_ldstt},
1142 {"stmia", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
1143 {"stmib", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
1144 {"stmda", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
1145 {"stmdb", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
1146 {"stmfd", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
1147 {"stmfa", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
1148 {"stmea", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
1149 {"stmed", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
1151 {"ldmia", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
1152 {"ldmib", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
1153 {"ldmda", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
1154 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
1155 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
1156 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
1157 {"ldmea", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
1158 {"ldmed", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
1160 {"swi", 0xef000000, 3, ARM_EXT_V1, do_swi},
1161 #ifdef TE_WINCE
1162 /* XXX This is the wrong place to do this. Think multi-arch. */
1163 {"bl", 0xeb000000, 2, ARM_EXT_V1, do_branch},
1164 {"b", 0xea000000, 1, ARM_EXT_V1, do_branch},
1165 #else
1166 {"bl", 0xebfffffe, 2, ARM_EXT_V1, do_branch},
1167 {"b", 0xeafffffe, 1, ARM_EXT_V1, do_branch},
1168 #endif
1170 /* Pseudo ops. */
1171 {"adr", 0xe28f0000, 3, ARM_EXT_V1, do_adr},
1172 {"adrl", 0xe28f0000, 3, ARM_EXT_V1, do_adrl},
1173 {"nop", 0xe1a00000, 3, ARM_EXT_V1, do_empty},
1175 /* ARM 2 multiplies. */
1176 {"mul", 0xe0000090, 3, ARM_EXT_V2, do_mul},
1177 {"muls", 0xe0100090, 3, ARM_EXT_V2, do_mul},
1178 {"mla", 0xe0200090, 3, ARM_EXT_V2, do_mla},
1179 {"mlas", 0xe0300090, 3, ARM_EXT_V2, do_mla},
1181 /* Generic copressor instructions. */
1182 {"cdp", 0xee000000, 3, ARM_EXT_V2, do_cdp},
1183 {"ldc", 0xec100000, 3, ARM_EXT_V2, do_lstc},
1184 {"ldcl", 0xec500000, 3, ARM_EXT_V2, do_lstc},
1185 {"stc", 0xec000000, 3, ARM_EXT_V2, do_lstc},
1186 {"stcl", 0xec400000, 3, ARM_EXT_V2, do_lstc},
1187 {"mcr", 0xee000010, 3, ARM_EXT_V2, do_co_reg},
1188 {"mrc", 0xee100010, 3, ARM_EXT_V2, do_co_reg},
1190 /* ARM 3 - swp instructions. */
1191 {"swp", 0xe1000090, 3, ARM_EXT_V2S, do_swap},
1192 {"swpb", 0xe1400090, 3, ARM_EXT_V2S, do_swap},
1194 /* ARM 6 Status register instructions. */
1195 {"mrs", 0xe10f0000, 3, ARM_EXT_V3, do_mrs},
1196 {"msr", 0xe120f000, 3, ARM_EXT_V3, do_msr},
1197 /* ScottB: our code uses 0xe128f000 for msr.
1198 NickC: but this is wrong because the bits 16 through 19 are
1199 handled by the PSR_xxx defines above. */
1201 /* ARM 7M long multiplies. */
1202 {"smull", 0xe0c00090, 5, ARM_EXT_V3M, do_mull},
1203 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M, do_mull},
1204 {"umull", 0xe0800090, 5, ARM_EXT_V3M, do_mull},
1205 {"umulls", 0xe0900090, 5, ARM_EXT_V3M, do_mull},
1206 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M, do_mull},
1207 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M, do_mull},
1208 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M, do_mull},
1209 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M, do_mull},
1211 /* ARM Architecture 4. */
1212 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4, do_ldstv4},
1213 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4, do_ldstv4},
1214 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4, do_ldstv4},
1215 {"strh", 0xe00000b0, 3, ARM_EXT_V4, do_ldstv4},
1217 /* ARM Architecture 4T. */
1218 /* Note: bx (and blx) are required on V5, even if the processor does
1219 not support Thumb. */
1220 {"bx", 0xe12fff10, 2, ARM_EXT_V4T | ARM_EXT_V5, do_bx},
1222 /* ARM Architecture 5T. */
1223 /* Note: blx has 2 variants, so the .value is set dynamically.
1224 Only one of the variants has conditional execution. */
1225 {"blx", 0xe0000000, 3, ARM_EXT_V5, do_blx},
1226 {"clz", 0xe16f0f10, 3, ARM_EXT_V5, do_clz},
1227 {"bkpt", 0xe1200070, 0, ARM_EXT_V5, do_bkpt},
1228 {"ldc2", 0xfc100000, 0, ARM_EXT_V5, do_lstc2},
1229 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5, do_lstc2},
1230 {"stc2", 0xfc000000, 0, ARM_EXT_V5, do_lstc2},
1231 {"stc2l", 0xfc400000, 0, ARM_EXT_V5, do_lstc2},
1232 {"cdp2", 0xfe000000, 0, ARM_EXT_V5, do_cdp2},
1233 {"mcr2", 0xfe000010, 0, ARM_EXT_V5, do_co_reg2},
1234 {"mrc2", 0xfe100010, 0, ARM_EXT_V5, do_co_reg2},
1236 /* ARM Architecture 5TExP. */
1237 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP, do_smla},
1238 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP, do_smla},
1239 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP, do_smla},
1240 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP, do_smla},
1242 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP, do_smla},
1243 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP, do_smla},
1245 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP, do_smlal},
1246 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP, do_smlal},
1247 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP, do_smlal},
1248 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP, do_smlal},
1250 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP, do_smul},
1251 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP, do_smul},
1252 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP, do_smul},
1253 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP, do_smul},
1255 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP, do_smul},
1256 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP, do_smul},
1258 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP, do_qadd},
1259 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP, do_qadd},
1260 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP, do_qadd},
1261 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP, do_qadd},
1263 /* ARM Architecture 5TE. */
1264 {"pld", 0xf450f000, 0, ARM_EXT_V5E, do_pld},
1265 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E, do_ldrd},
1266 {"strd", 0xe00000f0, 3, ARM_EXT_V5E, do_ldrd},
1268 {"mcrr", 0xec400000, 4, ARM_EXT_V5E, do_co_reg2c},
1269 {"mrrc", 0xec500000, 4, ARM_EXT_V5E, do_co_reg2c},
1271 /* ARM Architecture 5TEJ. */
1272 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J, do_bxj},
1274 /* Core FPA instruction set (V1). */
1275 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1276 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1277 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1278 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1280 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1281 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1282 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1283 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1285 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1286 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1287 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1288 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1290 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1291 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1292 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1293 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1294 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1295 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1296 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1297 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1298 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1299 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1300 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1301 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1303 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1304 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1305 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1306 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1307 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1308 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1309 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1310 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1311 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1312 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1313 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1314 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1316 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1317 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1318 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1319 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1320 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1321 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1322 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1323 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1324 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1325 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1326 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1327 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1329 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1330 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1331 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1332 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1333 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1334 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1335 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1336 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1337 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1338 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1339 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1340 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1342 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1343 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1344 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1345 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1346 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1347 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1348 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1349 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1350 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1351 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1352 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1353 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1355 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1356 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1357 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1358 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1359 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1360 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1361 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1362 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1363 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1364 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1365 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1366 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1368 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1369 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1370 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1371 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1372 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1373 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1374 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1375 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1376 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1377 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1378 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1379 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1381 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1382 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1383 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1384 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1385 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1386 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1387 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1388 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1389 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1390 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1391 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1392 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1394 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1395 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1396 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1397 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1398 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1399 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1400 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1401 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1402 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1403 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1404 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1405 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1407 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1408 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1409 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1410 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1411 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1412 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1413 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1414 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1415 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1416 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1417 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1418 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1420 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1421 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1422 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1423 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1424 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1425 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1426 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1427 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1428 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1429 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1430 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1431 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1433 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1434 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1435 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1436 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1437 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1438 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1439 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1440 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1441 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1442 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1443 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1444 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1446 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1447 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1448 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1449 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1450 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1451 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1452 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1453 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1454 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1455 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1456 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1457 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1459 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1460 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1461 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1462 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1463 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1464 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1465 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1466 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1467 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1468 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1469 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1470 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1472 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1473 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1474 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1475 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1476 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1477 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1478 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1479 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1480 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1481 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1482 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1483 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1485 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1486 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1487 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1488 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1489 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1490 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1491 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1492 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1493 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1494 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1495 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1496 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1498 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1499 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1500 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1501 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1502 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1503 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1504 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1505 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1506 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1507 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1508 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1509 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1511 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1512 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1513 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1514 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1515 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1516 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1517 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1518 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1519 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1520 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1521 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1522 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1524 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1525 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1526 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1527 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1528 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1529 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1530 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1531 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1532 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1533 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1534 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1535 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1537 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1538 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1539 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1540 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1541 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1542 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1543 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1544 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1545 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1546 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1547 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1548 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1550 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1551 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1552 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1553 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1554 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1555 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1556 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1557 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1558 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1559 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1560 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1561 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1563 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1564 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1565 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1566 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1567 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1568 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1569 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1570 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1571 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1572 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1573 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1574 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1576 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1577 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1578 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1579 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1580 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1581 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1582 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1583 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1584 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1585 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1586 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1587 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1589 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1590 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1591 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1592 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1593 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1594 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1595 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1596 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1597 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1598 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1599 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1600 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1602 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1603 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1604 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1605 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1606 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1607 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1608 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1609 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1610 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1611 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1612 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1613 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1615 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1616 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1617 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1618 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1619 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1620 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1621 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1622 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1623 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1624 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1625 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1626 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1628 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1629 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1630 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1631 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1632 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1633 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1634 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1635 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1636 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1637 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1638 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1639 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1641 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1642 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1643 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1644 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1645 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1646 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1647 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1648 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1649 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1650 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1651 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1652 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1654 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1655 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1656 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1657 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1658 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1659 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1660 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1661 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1662 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1663 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1664 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1665 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1667 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1668 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1669 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1670 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1671 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
1672 not be an optional suffix, but part of the instruction. To be
1673 compatible, we accept either. */
1674 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
1675 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
1677 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1678 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1679 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1680 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1681 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1682 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1683 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1684 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1685 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1686 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1687 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1688 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1690 /* The implementation of the FIX instruction is broken on some
1691 assemblers, in that it accepts a precision specifier as well as a
1692 rounding specifier, despite the fact that this is meaningless.
1693 To be more compatible, we accept it as well, though of course it
1694 does not set any bits. */
1695 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1696 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1697 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1698 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1699 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1700 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1701 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1702 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1703 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1704 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1705 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1706 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1707 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1709 /* Instructions that were new with the real FPA, call them V2. */
1710 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1711 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1712 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1713 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1714 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1715 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1717 /* VFP V1xD (single precision). */
1718 /* Moves and type conversions. */
1719 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1720 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_sp},
1721 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_from_reg},
1722 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD, do_empty},
1723 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1724 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1725 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1726 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1727 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1728 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1729 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_ctrl},
1730 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_ctrl_from_reg},
1732 /* Memory operations. */
1733 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
1734 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
1735 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1736 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1737 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1738 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1739 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1740 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1741 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1742 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1743 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1744 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1745 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1746 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1747 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1748 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1749 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1750 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1752 /* Monadic operations. */
1753 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1754 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1755 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1757 /* Dyadic operations. */
1758 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1759 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1760 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1761 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1762 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1763 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1764 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1765 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1766 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1768 /* Comparisons. */
1769 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1770 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
1771 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1772 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
1774 /* VFP V1 (Double precision). */
1775 /* Moves and type conversions. */
1776 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1777 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
1778 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1779 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
1780 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
1781 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
1782 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
1783 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
1784 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
1785 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1786 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1787 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1788 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1790 /* Memory operations. */
1791 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
1792 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
1793 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1794 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1795 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1796 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1797 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1798 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1799 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1800 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1802 /* Monadic operations. */
1803 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1804 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1805 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1807 /* Dyadic operations. */
1808 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1809 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1810 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1811 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1812 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1813 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1814 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1815 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1816 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1818 /* Comparisons. */
1819 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1820 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
1821 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1822 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
1824 /* VFP V2. */
1825 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2, do_vfp_sp_reg2},
1826 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2, do_vfp_sp_reg2},
1827 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2, do_vfp_dp_from_reg2},
1828 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_dp},
1830 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
1831 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE, do_xsc_mia},
1832 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1833 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1834 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1835 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1836 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1837 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE, do_xsc_mar},
1838 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE, do_xsc_mra},
1840 /* Intel Wireless MMX technology instructions. */
1841 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
1842 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
1843 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
1844 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
1845 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
1846 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
1847 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
1848 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
1849 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
1850 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
1851 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
1852 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
1853 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
1854 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
1855 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
1856 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
1857 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
1858 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
1859 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmcr},
1860 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmcrr},
1861 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
1862 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
1863 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
1864 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
1865 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
1866 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
1867 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
1868 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
1869 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
1870 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmrc},
1871 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmrrc},
1872 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
1873 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
1874 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
1875 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1876 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1877 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1878 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1879 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1880 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1881 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1882 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1883 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1884 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1885 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1886 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1887 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT, do_iwmmxt_waligni},
1888 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1889 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1890 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1891 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1892 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1893 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1894 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1895 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1896 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1897 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1898 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1899 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1900 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1901 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1902 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1903 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1904 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1905 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1906 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1907 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
1908 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
1909 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
1910 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
1911 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1912 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1913 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1914 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1915 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1916 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1917 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1918 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1919 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1920 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1921 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1922 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1923 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1924 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1925 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1926 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1927 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1928 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1929 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wmov},
1930 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1931 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1932 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1933 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1934 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1935 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1936 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1937 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1938 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1939 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1940 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1941 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1942 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
1943 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1944 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
1945 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1946 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
1947 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1948 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1949 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1950 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1951 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wshufh},
1952 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1953 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
1954 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1955 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
1956 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1957 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
1958 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1959 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
1960 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1961 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
1962 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1963 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
1964 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1965 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
1966 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1967 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
1968 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1969 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
1970 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
1971 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
1972 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
1973 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
1974 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1975 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1976 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1977 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1978 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1979 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1980 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1981 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1982 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1983 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1984 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1985 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1986 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1987 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1988 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1989 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1990 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1991 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1992 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1993 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1994 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1995 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1996 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1997 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1998 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1999 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2000 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2001 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2002 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wzero},
2004 /* Cirrus Maverick instructions. */
2005 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
2006 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
2007 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
2008 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
2009 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
2010 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
2011 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
2012 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
2013 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK, do_mav_binops_2a},
2014 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK, do_mav_binops_1a},
2015 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
2016 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
2017 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
2018 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
2019 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
2020 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
2021 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
2022 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
2023 {"cfmval32", 0xee100610, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2024 {"cfmv32al", 0xee000610, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2025 {"cfmvam32", 0xee100630, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2026 {"cfmv32am", 0xee000630, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2027 {"cfmvah32", 0xee100650, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2028 {"cfmv32ah", 0xee000650, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2029 {"cfmva32", 0xee100670, 7, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2030 {"cfmv32a", 0xee000670, 7, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2031 {"cfmva64", 0xee100690, 7, ARM_CEXT_MAVERICK, do_mav_binops_3c},
2032 {"cfmv64a", 0xee000690, 7, ARM_CEXT_MAVERICK, do_mav_binops_3d},
2033 {"cfmvsc32", 0xee1006b0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_1},
2034 {"cfmv32sc", 0xee0006b0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_2},
2035 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
2036 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
2037 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK, do_mav_binops_1f},
2038 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK, do_mav_binops_1g},
2039 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK, do_mav_binops_1h},
2040 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1i},
2041 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1j},
2042 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1k},
2043 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK, do_mav_binops_1l},
2044 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1m},
2045 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1l},
2046 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1m},
2047 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK, do_mav_triple_4a},
2048 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK, do_mav_triple_4b},
2049 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK, do_mav_shift_1},
2050 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK, do_mav_shift_2},
2051 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK, do_mav_triple_5a},
2052 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5b},
2053 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK, do_mav_triple_5c},
2054 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5d},
2055 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
2056 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
2057 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
2058 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
2059 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
2060 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
2061 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
2062 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
2063 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
2064 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
2065 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
2066 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
2067 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
2068 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
2069 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2070 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
2071 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2072 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
2073 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2074 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
2075 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2076 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2077 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
2078 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
2079 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
2080 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
2083 /* Defines for various bits that we will want to toggle. */
2084 #define INST_IMMEDIATE 0x02000000
2085 #define OFFSET_REG 0x02000000
2086 #define HWOFFSET_IMM 0x00400000
2087 #define SHIFT_BY_REG 0x00000010
2088 #define PRE_INDEX 0x01000000
2089 #define INDEX_UP 0x00800000
2090 #define WRITE_BACK 0x00200000
2091 #define LDM_TYPE_2_OR_3 0x00400000
2093 #define LITERAL_MASK 0xf000f000
2094 #define OPCODE_MASK 0xfe1fffff
2095 #define V4_STR_BIT 0x00000020
2097 #define DATA_OP_SHIFT 21
2099 /* Codes to distinguish the arithmetic instructions. */
2100 #define OPCODE_AND 0
2101 #define OPCODE_EOR 1
2102 #define OPCODE_SUB 2
2103 #define OPCODE_RSB 3
2104 #define OPCODE_ADD 4
2105 #define OPCODE_ADC 5
2106 #define OPCODE_SBC 6
2107 #define OPCODE_RSC 7
2108 #define OPCODE_TST 8
2109 #define OPCODE_TEQ 9
2110 #define OPCODE_CMP 10
2111 #define OPCODE_CMN 11
2112 #define OPCODE_ORR 12
2113 #define OPCODE_MOV 13
2114 #define OPCODE_BIC 14
2115 #define OPCODE_MVN 15
2117 /* Thumb v1 (ARMv4T). */
2118 static void do_t_nop PARAMS ((char *));
2119 static void do_t_arit PARAMS ((char *));
2120 static void do_t_add PARAMS ((char *));
2121 static void do_t_asr PARAMS ((char *));
2122 static void do_t_branch9 PARAMS ((char *));
2123 static void do_t_branch12 PARAMS ((char *));
2124 static void do_t_branch23 PARAMS ((char *));
2125 static void do_t_bx PARAMS ((char *));
2126 static void do_t_compare PARAMS ((char *));
2127 static void do_t_ldmstm PARAMS ((char *));
2128 static void do_t_ldr PARAMS ((char *));
2129 static void do_t_ldrb PARAMS ((char *));
2130 static void do_t_ldrh PARAMS ((char *));
2131 static void do_t_lds PARAMS ((char *));
2132 static void do_t_lsl PARAMS ((char *));
2133 static void do_t_lsr PARAMS ((char *));
2134 static void do_t_mov PARAMS ((char *));
2135 static void do_t_push_pop PARAMS ((char *));
2136 static void do_t_str PARAMS ((char *));
2137 static void do_t_strb PARAMS ((char *));
2138 static void do_t_strh PARAMS ((char *));
2139 static void do_t_sub PARAMS ((char *));
2140 static void do_t_swi PARAMS ((char *));
2141 static void do_t_adr PARAMS ((char *));
2143 /* Thumb v2 (ARMv5T). */
2144 static void do_t_blx PARAMS ((char *));
2145 static void do_t_bkpt PARAMS ((char *));
2147 #define T_OPCODE_MUL 0x4340
2148 #define T_OPCODE_TST 0x4200
2149 #define T_OPCODE_CMN 0x42c0
2150 #define T_OPCODE_NEG 0x4240
2151 #define T_OPCODE_MVN 0x43c0
2153 #define T_OPCODE_ADD_R3 0x1800
2154 #define T_OPCODE_SUB_R3 0x1a00
2155 #define T_OPCODE_ADD_HI 0x4400
2156 #define T_OPCODE_ADD_ST 0xb000
2157 #define T_OPCODE_SUB_ST 0xb080
2158 #define T_OPCODE_ADD_SP 0xa800
2159 #define T_OPCODE_ADD_PC 0xa000
2160 #define T_OPCODE_ADD_I8 0x3000
2161 #define T_OPCODE_SUB_I8 0x3800
2162 #define T_OPCODE_ADD_I3 0x1c00
2163 #define T_OPCODE_SUB_I3 0x1e00
2165 #define T_OPCODE_ASR_R 0x4100
2166 #define T_OPCODE_LSL_R 0x4080
2167 #define T_OPCODE_LSR_R 0x40c0
2168 #define T_OPCODE_ASR_I 0x1000
2169 #define T_OPCODE_LSL_I 0x0000
2170 #define T_OPCODE_LSR_I 0x0800
2172 #define T_OPCODE_MOV_I8 0x2000
2173 #define T_OPCODE_CMP_I8 0x2800
2174 #define T_OPCODE_CMP_LR 0x4280
2175 #define T_OPCODE_MOV_HR 0x4600
2176 #define T_OPCODE_CMP_HR 0x4500
2178 #define T_OPCODE_LDR_PC 0x4800
2179 #define T_OPCODE_LDR_SP 0x9800
2180 #define T_OPCODE_STR_SP 0x9000
2181 #define T_OPCODE_LDR_IW 0x6800
2182 #define T_OPCODE_STR_IW 0x6000
2183 #define T_OPCODE_LDR_IH 0x8800
2184 #define T_OPCODE_STR_IH 0x8000
2185 #define T_OPCODE_LDR_IB 0x7800
2186 #define T_OPCODE_STR_IB 0x7000
2187 #define T_OPCODE_LDR_RW 0x5800
2188 #define T_OPCODE_STR_RW 0x5000
2189 #define T_OPCODE_LDR_RH 0x5a00
2190 #define T_OPCODE_STR_RH 0x5200
2191 #define T_OPCODE_LDR_RB 0x5c00
2192 #define T_OPCODE_STR_RB 0x5400
2194 #define T_OPCODE_PUSH 0xb400
2195 #define T_OPCODE_POP 0xbc00
2197 #define T_OPCODE_BRANCH 0xe7fe
2199 static int thumb_reg PARAMS ((char ** str, int hi_lo));
2201 #define THUMB_SIZE 2 /* Size of thumb instruction. */
2202 #define THUMB_REG_LO 0x1
2203 #define THUMB_REG_HI 0x2
2204 #define THUMB_REG_ANY 0x3
2206 #define THUMB_H1 0x0080
2207 #define THUMB_H2 0x0040
2209 #define THUMB_ASR 0
2210 #define THUMB_LSL 1
2211 #define THUMB_LSR 2
2213 #define THUMB_MOVE 0
2214 #define THUMB_COMPARE 1
2216 #define THUMB_LOAD 0
2217 #define THUMB_STORE 1
2219 #define THUMB_PP_PC_LR 0x0100
2221 /* These three are used for immediate shifts, do not alter. */
2222 #define THUMB_WORD 2
2223 #define THUMB_HALFWORD 1
2224 #define THUMB_BYTE 0
2226 struct thumb_opcode
2228 /* Basic string to match. */
2229 const char * template;
2231 /* Basic instruction code. */
2232 unsigned long value;
2234 int size;
2236 /* Which CPU variants this exists for. */
2237 unsigned long variant;
2239 /* Function to call to parse args. */
2240 void (* parms) PARAMS ((char *));
2243 static const struct thumb_opcode tinsns[] =
2245 /* Thumb v1 (ARMv4T). */
2246 {"adc", 0x4140, 2, ARM_EXT_V4T, do_t_arit},
2247 {"add", 0x0000, 2, ARM_EXT_V4T, do_t_add},
2248 {"and", 0x4000, 2, ARM_EXT_V4T, do_t_arit},
2249 {"asr", 0x0000, 2, ARM_EXT_V4T, do_t_asr},
2250 {"b", T_OPCODE_BRANCH, 2, ARM_EXT_V4T, do_t_branch12},
2251 {"beq", 0xd0fe, 2, ARM_EXT_V4T, do_t_branch9},
2252 {"bne", 0xd1fe, 2, ARM_EXT_V4T, do_t_branch9},
2253 {"bcs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
2254 {"bhs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
2255 {"bcc", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
2256 {"bul", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
2257 {"blo", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
2258 {"bmi", 0xd4fe, 2, ARM_EXT_V4T, do_t_branch9},
2259 {"bpl", 0xd5fe, 2, ARM_EXT_V4T, do_t_branch9},
2260 {"bvs", 0xd6fe, 2, ARM_EXT_V4T, do_t_branch9},
2261 {"bvc", 0xd7fe, 2, ARM_EXT_V4T, do_t_branch9},
2262 {"bhi", 0xd8fe, 2, ARM_EXT_V4T, do_t_branch9},
2263 {"bls", 0xd9fe, 2, ARM_EXT_V4T, do_t_branch9},
2264 {"bge", 0xdafe, 2, ARM_EXT_V4T, do_t_branch9},
2265 {"blt", 0xdbfe, 2, ARM_EXT_V4T, do_t_branch9},
2266 {"bgt", 0xdcfe, 2, ARM_EXT_V4T, do_t_branch9},
2267 {"ble", 0xddfe, 2, ARM_EXT_V4T, do_t_branch9},
2268 {"bal", 0xdefe, 2, ARM_EXT_V4T, do_t_branch9},
2269 {"bic", 0x4380, 2, ARM_EXT_V4T, do_t_arit},
2270 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T, do_t_branch23},
2271 {"bx", 0x4700, 2, ARM_EXT_V4T, do_t_bx},
2272 {"cmn", T_OPCODE_CMN, 2, ARM_EXT_V4T, do_t_arit},
2273 {"cmp", 0x0000, 2, ARM_EXT_V4T, do_t_compare},
2274 {"eor", 0x4040, 2, ARM_EXT_V4T, do_t_arit},
2275 {"ldmia", 0xc800, 2, ARM_EXT_V4T, do_t_ldmstm},
2276 {"ldr", 0x0000, 2, ARM_EXT_V4T, do_t_ldr},
2277 {"ldrb", 0x0000, 2, ARM_EXT_V4T, do_t_ldrb},
2278 {"ldrh", 0x0000, 2, ARM_EXT_V4T, do_t_ldrh},
2279 {"ldrsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
2280 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
2281 {"ldsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
2282 {"ldsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
2283 {"lsl", 0x0000, 2, ARM_EXT_V4T, do_t_lsl},
2284 {"lsr", 0x0000, 2, ARM_EXT_V4T, do_t_lsr},
2285 {"mov", 0x0000, 2, ARM_EXT_V4T, do_t_mov},
2286 {"mul", T_OPCODE_MUL, 2, ARM_EXT_V4T, do_t_arit},
2287 {"mvn", T_OPCODE_MVN, 2, ARM_EXT_V4T, do_t_arit},
2288 {"neg", T_OPCODE_NEG, 2, ARM_EXT_V4T, do_t_arit},
2289 {"orr", 0x4300, 2, ARM_EXT_V4T, do_t_arit},
2290 {"pop", 0xbc00, 2, ARM_EXT_V4T, do_t_push_pop},
2291 {"push", 0xb400, 2, ARM_EXT_V4T, do_t_push_pop},
2292 {"ror", 0x41c0, 2, ARM_EXT_V4T, do_t_arit},
2293 {"sbc", 0x4180, 2, ARM_EXT_V4T, do_t_arit},
2294 {"stmia", 0xc000, 2, ARM_EXT_V4T, do_t_ldmstm},
2295 {"str", 0x0000, 2, ARM_EXT_V4T, do_t_str},
2296 {"strb", 0x0000, 2, ARM_EXT_V4T, do_t_strb},
2297 {"strh", 0x0000, 2, ARM_EXT_V4T, do_t_strh},
2298 {"swi", 0xdf00, 2, ARM_EXT_V4T, do_t_swi},
2299 {"sub", 0x0000, 2, ARM_EXT_V4T, do_t_sub},
2300 {"tst", T_OPCODE_TST, 2, ARM_EXT_V4T, do_t_arit},
2301 /* Pseudo ops: */
2302 {"adr", 0x0000, 2, ARM_EXT_V4T, do_t_adr},
2303 {"nop", 0x46C0, 2, ARM_EXT_V4T, do_t_nop}, /* mov r8,r8 */
2304 /* Thumb v2 (ARMv5T). */
2305 {"blx", 0, 0, ARM_EXT_V5T, do_t_blx},
2306 {"bkpt", 0xbe00, 2, ARM_EXT_V5T, do_t_bkpt},
2309 #define BAD_ARGS _("bad arguments to instruction")
2310 #define BAD_PC _("r15 not allowed here")
2311 #define BAD_COND _("instruction is not conditional")
2312 #define ERR_NO_ACCUM _("acc0 expected")
2314 static struct hash_control * arm_ops_hsh = NULL;
2315 static struct hash_control * arm_tops_hsh = NULL;
2316 static struct hash_control * arm_cond_hsh = NULL;
2317 static struct hash_control * arm_shift_hsh = NULL;
2318 static struct hash_control * arm_psr_hsh = NULL;
2320 /* This table describes all the machine specific pseudo-ops the assembler
2321 has to support. The fields are:
2322 pseudo-op name without dot
2323 function to call to execute this pseudo-op
2324 Integer arg to pass to the function. */
2326 static void s_req PARAMS ((int));
2327 static void s_align PARAMS ((int));
2328 static void s_bss PARAMS ((int));
2329 static void s_even PARAMS ((int));
2330 static void s_ltorg PARAMS ((int));
2331 static void s_arm PARAMS ((int));
2332 static void s_thumb PARAMS ((int));
2333 static void s_code PARAMS ((int));
2334 static void s_force_thumb PARAMS ((int));
2335 static void s_thumb_func PARAMS ((int));
2336 static void s_thumb_set PARAMS ((int));
2337 #ifdef OBJ_ELF
2338 static void s_arm_elf_cons PARAMS ((int));
2339 #endif
2341 static int my_get_expression PARAMS ((expressionS *, char **));
2343 const pseudo_typeS md_pseudo_table[] =
2345 /* Never called becasue '.req' does not start line. */
2346 { "req", s_req, 0 },
2347 { "bss", s_bss, 0 },
2348 { "align", s_align, 0 },
2349 { "arm", s_arm, 0 },
2350 { "thumb", s_thumb, 0 },
2351 { "code", s_code, 0 },
2352 { "force_thumb", s_force_thumb, 0 },
2353 { "thumb_func", s_thumb_func, 0 },
2354 { "thumb_set", s_thumb_set, 0 },
2355 { "even", s_even, 0 },
2356 { "ltorg", s_ltorg, 0 },
2357 { "pool", s_ltorg, 0 },
2358 #ifdef OBJ_ELF
2359 { "word", s_arm_elf_cons, 4 },
2360 { "long", s_arm_elf_cons, 4 },
2361 #else
2362 { "word", cons, 4},
2363 #endif
2364 { "extend", float_cons, 'x' },
2365 { "ldouble", float_cons, 'x' },
2366 { "packed", float_cons, 'p' },
2367 { 0, 0, 0 }
2370 /* Other internal functions. */
2371 static int arm_parse_extension PARAMS ((char *, int *));
2372 static int arm_parse_cpu PARAMS ((char *));
2373 static int arm_parse_arch PARAMS ((char *));
2374 static int arm_parse_fpu PARAMS ((char *));
2375 #if defined OBJ_COFF || defined OBJ_ELF
2376 static void arm_add_note PARAMS ((const char *, const char *, unsigned int));
2377 #endif
2379 /* Stuff needed to resolve the label ambiguity
2382 label: <insn>
2383 may differ from:
2385 label:
2386 <insn>
2389 symbolS * last_label_seen;
2390 static int label_is_thumb_function_name = FALSE;
2392 /* Literal Pool stuff. */
2394 #define MAX_LITERAL_POOL_SIZE 1024
2396 /* Literal pool structure. Held on a per-section
2397 and per-sub-section basis. */
2398 typedef struct literal_pool
2400 expressionS literals [MAX_LITERAL_POOL_SIZE];
2401 unsigned int next_free_entry;
2402 unsigned int id;
2403 symbolS * symbol;
2404 segT section;
2405 subsegT sub_section;
2406 struct literal_pool * next;
2407 } literal_pool;
2409 /* Pointer to a linked list of literal pools. */
2410 literal_pool * list_of_pools = NULL;
2412 static literal_pool * find_literal_pool PARAMS ((void));
2413 static literal_pool * find_or_make_literal_pool PARAMS ((void));
2415 static literal_pool *
2416 find_literal_pool ()
2418 literal_pool * pool;
2420 for (pool = list_of_pools; pool != NULL; pool = pool->next)
2422 if (pool->section == now_seg
2423 && pool->sub_section == now_subseg)
2424 break;
2427 return pool;
2430 static literal_pool *
2431 find_or_make_literal_pool ()
2433 /* Next literal pool ID number. */
2434 static unsigned int latest_pool_num = 1;
2435 literal_pool * pool;
2437 pool = find_literal_pool ();
2439 if (pool == NULL)
2441 /* Create a new pool. */
2442 pool = (literal_pool *) xmalloc (sizeof (* pool));
2443 if (! pool)
2444 return NULL;
2446 pool->next_free_entry = 0;
2447 pool->section = now_seg;
2448 pool->sub_section = now_subseg;
2449 pool->next = list_of_pools;
2450 pool->symbol = NULL;
2452 /* Add it to the list. */
2453 list_of_pools = pool;
2456 /* New pools, and emptied pools, will have a NULL symbol. */
2457 if (pool->symbol == NULL)
2459 pool->symbol = symbol_create (FAKE_LABEL_NAME, undefined_section,
2460 (valueT) 0, &zero_address_frag);
2461 pool->id = latest_pool_num ++;
2464 /* Done. */
2465 return pool;
2468 /* Add the literal in the global 'inst'
2469 structure to the relevent literal pool. */
2470 static int
2471 add_to_lit_pool ()
2473 literal_pool * pool;
2474 unsigned int entry;
2476 pool = find_or_make_literal_pool ();
2478 /* Check if this literal value is already in the pool. */
2479 for (entry = 0; entry < pool->next_free_entry; entry ++)
2481 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
2482 && (inst.reloc.exp.X_op == O_constant)
2483 && (pool->literals[entry].X_add_number
2484 == inst.reloc.exp.X_add_number)
2485 && (pool->literals[entry].X_unsigned
2486 == inst.reloc.exp.X_unsigned))
2487 break;
2489 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
2490 && (inst.reloc.exp.X_op == O_symbol)
2491 && (pool->literals[entry].X_add_number
2492 == inst.reloc.exp.X_add_number)
2493 && (pool->literals[entry].X_add_symbol
2494 == inst.reloc.exp.X_add_symbol)
2495 && (pool->literals[entry].X_op_symbol
2496 == inst.reloc.exp.X_op_symbol))
2497 break;
2500 /* Do we need to create a new entry? */
2501 if (entry == pool->next_free_entry)
2503 if (entry >= MAX_LITERAL_POOL_SIZE)
2505 inst.error = _("literal pool overflow");
2506 return FAIL;
2509 pool->literals[entry] = inst.reloc.exp;
2510 pool->next_free_entry += 1;
2513 inst.reloc.exp.X_op = O_symbol;
2514 inst.reloc.exp.X_add_number = ((int) entry) * 4 - 8;
2515 inst.reloc.exp.X_add_symbol = pool->symbol;
2517 return SUCCESS;
2520 /* Can't use symbol_new here, so have to create a symbol and then at
2521 a later date assign it a value. Thats what these functions do. */
2523 static void
2524 symbol_locate (symbolP, name, segment, valu, frag)
2525 symbolS * symbolP;
2526 const char * name; /* It is copied, the caller can modify. */
2527 segT segment; /* Segment identifier (SEG_<something>). */
2528 valueT valu; /* Symbol value. */
2529 fragS * frag; /* Associated fragment. */
2531 unsigned int name_length;
2532 char * preserved_copy_of_name;
2534 name_length = strlen (name) + 1; /* +1 for \0. */
2535 obstack_grow (&notes, name, name_length);
2536 preserved_copy_of_name = obstack_finish (&notes);
2537 #ifdef STRIP_UNDERSCORE
2538 if (preserved_copy_of_name[0] == '_')
2539 preserved_copy_of_name++;
2540 #endif
2542 #ifdef tc_canonicalize_symbol_name
2543 preserved_copy_of_name =
2544 tc_canonicalize_symbol_name (preserved_copy_of_name);
2545 #endif
2547 S_SET_NAME (symbolP, preserved_copy_of_name);
2549 S_SET_SEGMENT (symbolP, segment);
2550 S_SET_VALUE (symbolP, valu);
2551 symbol_clear_list_pointers (symbolP);
2553 symbol_set_frag (symbolP, frag);
2555 /* Link to end of symbol chain. */
2557 extern int symbol_table_frozen;
2558 if (symbol_table_frozen)
2559 abort ();
2562 symbol_append (symbolP, symbol_lastP, & symbol_rootP, & symbol_lastP);
2564 obj_symbol_new_hook (symbolP);
2566 #ifdef tc_symbol_new_hook
2567 tc_symbol_new_hook (symbolP);
2568 #endif
2570 #ifdef DEBUG_SYMS
2571 verify_symbol_chain (symbol_rootP, symbol_lastP);
2572 #endif /* DEBUG_SYMS */
2575 /* Check that an immediate is valid.
2576 If so, convert it to the right format. */
2578 static unsigned int
2579 validate_immediate (val)
2580 unsigned int val;
2582 unsigned int a;
2583 unsigned int i;
2585 #define rotate_left(v, n) (v << n | v >> (32 - n))
2587 for (i = 0; i < 32; i += 2)
2588 if ((a = rotate_left (val, i)) <= 0xff)
2589 return a | (i << 7); /* 12-bit pack: [shift-cnt,const]. */
2591 return FAIL;
2594 /* Check to see if an immediate can be computed as two seperate immediate
2595 values, added together. We already know that this value cannot be
2596 computed by just one ARM instruction. */
2598 static unsigned int
2599 validate_immediate_twopart (val, highpart)
2600 unsigned int val;
2601 unsigned int * highpart;
2603 unsigned int a;
2604 unsigned int i;
2606 for (i = 0; i < 32; i += 2)
2607 if (((a = rotate_left (val, i)) & 0xff) != 0)
2609 if (a & 0xff00)
2611 if (a & ~ 0xffff)
2612 continue;
2613 * highpart = (a >> 8) | ((i + 24) << 7);
2615 else if (a & 0xff0000)
2617 if (a & 0xff000000)
2618 continue;
2619 * highpart = (a >> 16) | ((i + 16) << 7);
2621 else
2623 assert (a & 0xff000000);
2624 * highpart = (a >> 24) | ((i + 8) << 7);
2627 return (a & 0xff) | (i << 7);
2630 return FAIL;
2633 static int
2634 validate_offset_imm (val, hwse)
2635 unsigned int val;
2636 int hwse;
2638 if ((hwse && val > 255) || val > 4095)
2639 return FAIL;
2640 return val;
2643 static void
2644 s_req (a)
2645 int a ATTRIBUTE_UNUSED;
2647 as_bad (_("invalid syntax for .req directive"));
2650 static void
2651 s_bss (ignore)
2652 int ignore ATTRIBUTE_UNUSED;
2654 /* We don't support putting frags in the BSS segment, we fake it by
2655 marking in_bss, then looking at s_skip for clues. */
2656 subseg_set (bss_section, 0);
2657 demand_empty_rest_of_line ();
2660 static void
2661 s_even (ignore)
2662 int ignore ATTRIBUTE_UNUSED;
2664 /* Never make frag if expect extra pass. */
2665 if (!need_pass_2)
2666 frag_align (1, 0, 0);
2668 record_alignment (now_seg, 1);
2670 demand_empty_rest_of_line ();
2673 static void
2674 s_ltorg (ignored)
2675 int ignored ATTRIBUTE_UNUSED;
2677 unsigned int entry;
2678 literal_pool * pool;
2679 char sym_name[20];
2681 pool = find_literal_pool ();
2682 if (pool == NULL
2683 || pool->symbol == NULL
2684 || pool->next_free_entry == 0)
2685 return;
2687 /* Align pool as you have word accesses.
2688 Only make a frag if we have to. */
2689 if (!need_pass_2)
2690 frag_align (2, 0, 0);
2692 record_alignment (now_seg, 2);
2694 sprintf (sym_name, "$$lit_\002%x", pool->id);
2696 symbol_locate (pool->symbol, sym_name, now_seg,
2697 (valueT) frag_now_fix (), frag_now);
2698 symbol_table_insert (pool->symbol);
2700 ARM_SET_THUMB (pool->symbol, thumb_mode);
2702 #if defined OBJ_COFF || defined OBJ_ELF
2703 ARM_SET_INTERWORK (pool->symbol, support_interwork);
2704 #endif
2706 for (entry = 0; entry < pool->next_free_entry; entry ++)
2707 /* First output the expression in the instruction to the pool. */
2708 emit_expr (&(pool->literals[entry]), 4); /* .word */
2710 /* Mark the pool as empty. */
2711 pool->next_free_entry = 0;
2712 pool->symbol = NULL;
2715 /* Same as s_align_ptwo but align 0 => align 2. */
2717 static void
2718 s_align (unused)
2719 int unused ATTRIBUTE_UNUSED;
2721 register int temp;
2722 register long temp_fill;
2723 long max_alignment = 15;
2725 temp = get_absolute_expression ();
2726 if (temp > max_alignment)
2727 as_bad (_("alignment too large: %d assumed"), temp = max_alignment);
2728 else if (temp < 0)
2730 as_bad (_("alignment negative. 0 assumed."));
2731 temp = 0;
2734 if (*input_line_pointer == ',')
2736 input_line_pointer++;
2737 temp_fill = get_absolute_expression ();
2739 else
2740 temp_fill = 0;
2742 if (!temp)
2743 temp = 2;
2745 /* Only make a frag if we HAVE to. */
2746 if (temp && !need_pass_2)
2747 frag_align (temp, (int) temp_fill, 0);
2748 demand_empty_rest_of_line ();
2750 record_alignment (now_seg, temp);
2753 static void
2754 s_force_thumb (ignore)
2755 int ignore ATTRIBUTE_UNUSED;
2757 /* If we are not already in thumb mode go into it, EVEN if
2758 the target processor does not support thumb instructions.
2759 This is used by gcc/config/arm/lib1funcs.asm for example
2760 to compile interworking support functions even if the
2761 target processor should not support interworking. */
2762 if (! thumb_mode)
2764 thumb_mode = 2;
2766 record_alignment (now_seg, 1);
2769 demand_empty_rest_of_line ();
2772 static void
2773 s_thumb_func (ignore)
2774 int ignore ATTRIBUTE_UNUSED;
2776 if (! thumb_mode)
2777 opcode_select (16);
2779 /* The following label is the name/address of the start of a Thumb function.
2780 We need to know this for the interworking support. */
2781 label_is_thumb_function_name = TRUE;
2783 demand_empty_rest_of_line ();
2786 /* Perform a .set directive, but also mark the alias as
2787 being a thumb function. */
2789 static void
2790 s_thumb_set (equiv)
2791 int equiv;
2793 /* XXX the following is a duplicate of the code for s_set() in read.c
2794 We cannot just call that code as we need to get at the symbol that
2795 is created. */
2796 register char * name;
2797 register char delim;
2798 register char * end_name;
2799 register symbolS * symbolP;
2801 /* Especial apologies for the random logic:
2802 This just grew, and could be parsed much more simply!
2803 Dean - in haste. */
2804 name = input_line_pointer;
2805 delim = get_symbol_end ();
2806 end_name = input_line_pointer;
2807 *end_name = delim;
2809 SKIP_WHITESPACE ();
2811 if (*input_line_pointer != ',')
2813 *end_name = 0;
2814 as_bad (_("expected comma after name \"%s\""), name);
2815 *end_name = delim;
2816 ignore_rest_of_line ();
2817 return;
2820 input_line_pointer++;
2821 *end_name = 0;
2823 if (name[0] == '.' && name[1] == '\0')
2825 /* XXX - this should not happen to .thumb_set. */
2826 abort ();
2829 if ((symbolP = symbol_find (name)) == NULL
2830 && (symbolP = md_undefined_symbol (name)) == NULL)
2832 #ifndef NO_LISTING
2833 /* When doing symbol listings, play games with dummy fragments living
2834 outside the normal fragment chain to record the file and line info
2835 for this symbol. */
2836 if (listing & LISTING_SYMBOLS)
2838 extern struct list_info_struct * listing_tail;
2839 fragS * dummy_frag = (fragS *) xmalloc (sizeof (fragS));
2841 memset (dummy_frag, 0, sizeof (fragS));
2842 dummy_frag->fr_type = rs_fill;
2843 dummy_frag->line = listing_tail;
2844 symbolP = symbol_new (name, undefined_section, 0, dummy_frag);
2845 dummy_frag->fr_symbol = symbolP;
2847 else
2848 #endif
2849 symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
2851 #ifdef OBJ_COFF
2852 /* "set" symbols are local unless otherwise specified. */
2853 SF_SET_LOCAL (symbolP);
2854 #endif /* OBJ_COFF */
2855 } /* Make a new symbol. */
2857 symbol_table_insert (symbolP);
2859 * end_name = delim;
2861 if (equiv
2862 && S_IS_DEFINED (symbolP)
2863 && S_GET_SEGMENT (symbolP) != reg_section)
2864 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP));
2866 pseudo_set (symbolP);
2868 demand_empty_rest_of_line ();
2870 /* XXX Now we come to the Thumb specific bit of code. */
2872 THUMB_SET_FUNC (symbolP, 1);
2873 ARM_SET_THUMB (symbolP, 1);
2874 #if defined OBJ_ELF || defined OBJ_COFF
2875 ARM_SET_INTERWORK (symbolP, support_interwork);
2876 #endif
2879 static void
2880 opcode_select (width)
2881 int width;
2883 switch (width)
2885 case 16:
2886 if (! thumb_mode)
2888 if (! (cpu_variant & ARM_EXT_V4T))
2889 as_bad (_("selected processor does not support THUMB opcodes"));
2891 thumb_mode = 1;
2892 /* No need to force the alignment, since we will have been
2893 coming from ARM mode, which is word-aligned. */
2894 record_alignment (now_seg, 1);
2896 break;
2898 case 32:
2899 if (thumb_mode)
2901 if ((cpu_variant & ARM_ALL) == ARM_EXT_V4T)
2902 as_bad (_("selected processor does not support ARM opcodes"));
2904 thumb_mode = 0;
2906 if (!need_pass_2)
2907 frag_align (2, 0, 0);
2909 record_alignment (now_seg, 1);
2911 break;
2913 default:
2914 as_bad (_("invalid instruction size selected (%d)"), width);
2918 static void
2919 s_arm (ignore)
2920 int ignore ATTRIBUTE_UNUSED;
2922 opcode_select (32);
2923 demand_empty_rest_of_line ();
2926 static void
2927 s_thumb (ignore)
2928 int ignore ATTRIBUTE_UNUSED;
2930 opcode_select (16);
2931 demand_empty_rest_of_line ();
2934 static void
2935 s_code (unused)
2936 int unused ATTRIBUTE_UNUSED;
2938 register int temp;
2940 temp = get_absolute_expression ();
2941 switch (temp)
2943 case 16:
2944 case 32:
2945 opcode_select (temp);
2946 break;
2948 default:
2949 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp);
2953 static void
2954 end_of_line (str)
2955 char *str;
2957 skip_whitespace (str);
2959 if (*str != '\0' && !inst.error)
2960 inst.error = _("garbage following instruction");
2963 static int
2964 skip_past_comma (str)
2965 char ** str;
2967 char * p = * str, c;
2968 int comma = 0;
2970 while ((c = *p) == ' ' || c == ',')
2972 p++;
2973 if (c == ',' && comma++)
2974 return FAIL;
2977 if (c == '\0')
2978 return FAIL;
2980 *str = p;
2981 return comma ? SUCCESS : FAIL;
2984 /* A standard register must be given at this point.
2985 SHIFT is the place to put it in inst.instruction.
2986 Restores input start point on error.
2987 Returns the reg#, or FAIL. */
2989 static int
2990 reg_required_here (str, shift)
2991 char ** str;
2992 int shift;
2994 static char buff [128]; /* XXX */
2995 int reg;
2996 char * start = * str;
2998 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_RN].htab)) != FAIL)
3000 if (shift >= 0)
3001 inst.instruction |= reg << shift;
3002 return reg;
3005 /* Restore the start point, we may have got a reg of the wrong class. */
3006 *str = start;
3008 /* In the few cases where we might be able to accept something else
3009 this error can be overridden. */
3010 sprintf (buff, _("register expected, not '%.100s'"), start);
3011 inst.error = buff;
3013 return FAIL;
3016 /* A Intel Wireless MMX technology register
3017 must be given at this point.
3018 Shift is the place to put it in inst.instruction.
3019 Restores input start point on err.
3020 Returns the reg#, or FAIL. */
3022 static int
3023 wreg_required_here (str, shift, reg_type)
3024 char ** str;
3025 int shift;
3026 enum wreg_type reg_type;
3028 static char buff [128];
3029 int reg;
3030 char * start = *str;
3032 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_IWMMXT].htab)) != FAIL)
3034 if (wr_register (reg)
3035 && (reg_type == IWMMXT_REG_WR || reg_type == IWMMXT_REG_WR_OR_WC))
3037 if (shift >= 0)
3038 inst.instruction |= (reg ^ WR_PREFIX) << shift;
3039 return reg;
3041 else if (wc_register (reg)
3042 && (reg_type == IWMMXT_REG_WC || reg_type == IWMMXT_REG_WR_OR_WC))
3044 if (shift >= 0)
3045 inst.instruction |= (reg ^ WC_PREFIX) << shift;
3046 return reg;
3048 else if ((wcg_register (reg) && reg_type == IWMMXT_REG_WCG))
3050 if (shift >= 0)
3051 inst.instruction |= ((reg ^ WC_PREFIX) - 8) << shift;
3052 return reg;
3056 /* Restore the start point, we may have got a reg of the wrong class. */
3057 *str = start;
3059 /* In the few cases where we might be able to accept
3060 something else this error can be overridden. */
3061 sprintf (buff, _("Intel Wireless MMX technology register expected, not '%.100s'"), start);
3062 inst.error = buff;
3064 return FAIL;
3067 static const struct asm_psr *
3068 arm_psr_parse (ccp)
3069 register char ** ccp;
3071 char * start = * ccp;
3072 char c;
3073 char * p;
3074 const struct asm_psr * psr;
3076 p = start;
3078 /* Skip to the end of the next word in the input stream. */
3081 c = *p++;
3083 while (ISALPHA (c) || c == '_');
3085 /* Terminate the word. */
3086 *--p = 0;
3088 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
3089 feature for ease of use and backwards compatibility. */
3090 if (!strncmp (start, "cpsr", 4))
3091 strncpy (start, "CPSR", 4);
3092 else if (!strncmp (start, "spsr", 4))
3093 strncpy (start, "SPSR", 4);
3095 /* Now locate the word in the psr hash table. */
3096 psr = (const struct asm_psr *) hash_find (arm_psr_hsh, start);
3098 /* Restore the input stream. */
3099 *p = c;
3101 /* If we found a valid match, advance the
3102 stream pointer past the end of the word. */
3103 *ccp = p;
3105 return psr;
3108 /* Parse the input looking for a PSR flag. */
3110 static int
3111 psr_required_here (str)
3112 char ** str;
3114 char * start = * str;
3115 const struct asm_psr * psr;
3117 psr = arm_psr_parse (str);
3119 if (psr)
3121 /* If this is the SPSR that is being modified, set the R bit. */
3122 if (! psr->cpsr)
3123 inst.instruction |= SPSR_BIT;
3125 /* Set the psr flags in the MSR instruction. */
3126 inst.instruction |= psr->field << PSR_SHIFT;
3128 return SUCCESS;
3131 /* In the few cases where we might be able to accept
3132 something else this error can be overridden. */
3133 inst.error = _("flag for {c}psr instruction expected");
3135 /* Restore the start point. */
3136 *str = start;
3137 return FAIL;
3140 static int
3141 co_proc_number (str)
3142 char **str;
3144 int processor, pchar;
3145 char *start;
3147 skip_whitespace (*str);
3148 start = *str;
3150 /* The data sheet seems to imply that just a number on its own is valid
3151 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
3152 accept either. */
3153 if ((processor = arm_reg_parse (str, all_reg_maps[REG_TYPE_CP].htab))
3154 == FAIL)
3156 *str = start;
3158 pchar = *(*str)++;
3159 if (pchar >= '0' && pchar <= '9')
3161 processor = pchar - '0';
3162 if (**str >= '0' && **str <= '9')
3164 processor = processor * 10 + *(*str)++ - '0';
3165 if (processor > 15)
3167 inst.error = _("illegal co-processor number");
3168 return FAIL;
3172 else
3174 inst.error = _("bad or missing co-processor number");
3175 return FAIL;
3179 inst.instruction |= processor << 8;
3180 return SUCCESS;
3183 static int
3184 cp_opc_expr (str, where, length)
3185 char ** str;
3186 int where;
3187 int length;
3189 expressionS expr;
3191 skip_whitespace (* str);
3193 memset (&expr, '\0', sizeof (expr));
3195 if (my_get_expression (&expr, str))
3196 return FAIL;
3197 if (expr.X_op != O_constant)
3199 inst.error = _("bad or missing expression");
3200 return FAIL;
3203 if ((expr.X_add_number & ((1 << length) - 1)) != expr.X_add_number)
3205 inst.error = _("immediate co-processor expression too large");
3206 return FAIL;
3209 inst.instruction |= expr.X_add_number << where;
3210 return SUCCESS;
3213 static int
3214 cp_reg_required_here (str, where)
3215 char ** str;
3216 int where;
3218 int reg;
3219 char * start = *str;
3221 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
3223 inst.instruction |= reg << where;
3224 return reg;
3227 /* In the few cases where we might be able to accept something else
3228 this error can be overridden. */
3229 inst.error = _("co-processor register expected");
3231 /* Restore the start point. */
3232 *str = start;
3233 return FAIL;
3236 static int
3237 fp_reg_required_here (str, where)
3238 char ** str;
3239 int where;
3241 int reg;
3242 char * start = * str;
3244 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_FN].htab)) != FAIL)
3246 inst.instruction |= reg << where;
3247 return reg;
3250 /* In the few cases where we might be able to accept something else
3251 this error can be overridden. */
3252 inst.error = _("floating point register expected");
3254 /* Restore the start point. */
3255 *str = start;
3256 return FAIL;
3259 static int
3260 cp_address_offset (str)
3261 char ** str;
3263 int offset;
3265 skip_whitespace (* str);
3267 if (! is_immediate_prefix (**str))
3269 inst.error = _("immediate expression expected");
3270 return FAIL;
3273 (*str)++;
3275 if (my_get_expression (& inst.reloc.exp, str))
3276 return FAIL;
3278 if (inst.reloc.exp.X_op == O_constant)
3280 offset = inst.reloc.exp.X_add_number;
3282 if (offset & 3)
3284 inst.error = _("co-processor address must be word aligned");
3285 return FAIL;
3288 if (offset > 1023 || offset < -1023)
3290 inst.error = _("offset too large");
3291 return FAIL;
3294 if (offset >= 0)
3295 inst.instruction |= INDEX_UP;
3296 else
3297 offset = -offset;
3299 inst.instruction |= offset >> 2;
3301 else
3302 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
3304 return SUCCESS;
3307 static int
3308 cp_address_required_here (str, wb_ok)
3309 char ** str;
3310 int wb_ok;
3312 char * p = * str;
3313 int pre_inc = 0;
3314 int write_back = 0;
3316 if (*p == '[')
3318 int reg;
3320 p++;
3321 skip_whitespace (p);
3323 if ((reg = reg_required_here (& p, 16)) == FAIL)
3324 return FAIL;
3326 skip_whitespace (p);
3328 if (*p == ']')
3330 p++;
3332 if (wb_ok && skip_past_comma (& p) == SUCCESS)
3334 /* [Rn], #expr */
3335 write_back = WRITE_BACK;
3337 if (reg == REG_PC)
3339 inst.error = _("pc may not be used in post-increment");
3340 return FAIL;
3343 if (cp_address_offset (& p) == FAIL)
3344 return FAIL;
3346 else
3347 pre_inc = PRE_INDEX | INDEX_UP;
3349 else
3351 /* '['Rn, #expr']'[!] */
3353 if (skip_past_comma (& p) == FAIL)
3355 inst.error = _("pre-indexed expression expected");
3356 return FAIL;
3359 pre_inc = PRE_INDEX;
3361 if (cp_address_offset (& p) == FAIL)
3362 return FAIL;
3364 skip_whitespace (p);
3366 if (*p++ != ']')
3368 inst.error = _("missing ]");
3369 return FAIL;
3372 skip_whitespace (p);
3374 if (wb_ok && *p == '!')
3376 if (reg == REG_PC)
3378 inst.error = _("pc may not be used with write-back");
3379 return FAIL;
3382 p++;
3383 write_back = WRITE_BACK;
3387 else
3389 if (my_get_expression (&inst.reloc.exp, &p))
3390 return FAIL;
3392 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
3393 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
3394 inst.reloc.pc_rel = 1;
3395 inst.instruction |= (REG_PC << 16);
3396 pre_inc = PRE_INDEX;
3399 inst.instruction |= write_back | pre_inc;
3400 *str = p;
3401 return SUCCESS;
3404 static int
3405 cp_byte_address_offset (str)
3406 char ** str;
3408 int offset;
3410 skip_whitespace (* str);
3412 if (! is_immediate_prefix (**str))
3414 inst.error = _("immediate expression expected");
3415 return FAIL;
3418 (*str)++;
3420 if (my_get_expression (& inst.reloc.exp, str))
3421 return FAIL;
3423 if (inst.reloc.exp.X_op == O_constant)
3425 offset = inst.reloc.exp.X_add_number;
3427 if (offset > 255 || offset < -255)
3429 inst.error = _("offset too large");
3430 return FAIL;
3433 if (offset >= 0)
3434 inst.instruction |= INDEX_UP;
3435 else
3436 offset = -offset;
3438 inst.instruction |= offset;
3440 else
3441 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
3443 return SUCCESS;
3446 static int
3447 cp_byte_address_required_here (str)
3448 char ** str;
3450 char * p = * str;
3451 int pre_inc = 0;
3452 int write_back = 0;
3454 if (*p == '[')
3456 int reg;
3458 p++;
3459 skip_whitespace (p);
3461 if ((reg = reg_required_here (& p, 16)) == FAIL)
3462 return FAIL;
3464 skip_whitespace (p);
3466 if (*p == ']')
3468 p++;
3470 if (skip_past_comma (& p) == SUCCESS)
3472 /* [Rn], #expr */
3473 write_back = WRITE_BACK;
3475 if (reg == REG_PC)
3477 inst.error = _("pc may not be used in post-increment");
3478 return FAIL;
3481 if (cp_byte_address_offset (& p) == FAIL)
3482 return FAIL;
3484 else
3485 pre_inc = PRE_INDEX | INDEX_UP;
3487 else
3489 /* '['Rn, #expr']'[!] */
3491 if (skip_past_comma (& p) == FAIL)
3493 inst.error = _("pre-indexed expression expected");
3494 return FAIL;
3497 pre_inc = PRE_INDEX;
3499 if (cp_byte_address_offset (& p) == FAIL)
3500 return FAIL;
3502 skip_whitespace (p);
3504 if (*p++ != ']')
3506 inst.error = _("missing ]");
3507 return FAIL;
3510 skip_whitespace (p);
3512 if (*p == '!')
3514 if (reg == REG_PC)
3516 inst.error = _("pc may not be used with write-back");
3517 return FAIL;
3520 p++;
3521 write_back = WRITE_BACK;
3525 else
3527 if (my_get_expression (&inst.reloc.exp, &p))
3528 return FAIL;
3530 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
3531 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
3532 inst.reloc.pc_rel = 1;
3533 inst.instruction |= (REG_PC << 16);
3534 pre_inc = PRE_INDEX;
3537 inst.instruction |= write_back | pre_inc;
3538 *str = p;
3539 return SUCCESS;
3542 static void
3543 do_empty (str)
3544 char * str;
3546 /* Do nothing really. */
3547 end_of_line (str);
3548 return;
3551 static void
3552 do_mrs (str)
3553 char *str;
3555 int skip = 0;
3557 /* Only one syntax. */
3558 skip_whitespace (str);
3560 if (reg_required_here (&str, 12) == FAIL)
3562 inst.error = BAD_ARGS;
3563 return;
3566 if (skip_past_comma (&str) == FAIL)
3568 inst.error = _("comma expected after register name");
3569 return;
3572 skip_whitespace (str);
3574 if ( strcmp (str, "CPSR") == 0
3575 || strcmp (str, "SPSR") == 0
3576 /* Lower case versions for backwards compatability. */
3577 || strcmp (str, "cpsr") == 0
3578 || strcmp (str, "spsr") == 0)
3579 skip = 4;
3581 /* This is for backwards compatability with older toolchains. */
3582 else if ( strcmp (str, "cpsr_all") == 0
3583 || strcmp (str, "spsr_all") == 0)
3584 skip = 8;
3585 else
3587 inst.error = _("CPSR or SPSR expected");
3588 return;
3591 if (* str == 's' || * str == 'S')
3592 inst.instruction |= SPSR_BIT;
3593 str += skip;
3595 end_of_line (str);
3598 /* Two possible forms:
3599 "{C|S}PSR_<field>, Rm",
3600 "{C|S}PSR_f, #expression". */
3602 static void
3603 do_msr (str)
3604 char * str;
3606 skip_whitespace (str);
3608 if (psr_required_here (& str) == FAIL)
3609 return;
3611 if (skip_past_comma (& str) == FAIL)
3613 inst.error = _("comma missing after psr flags");
3614 return;
3617 skip_whitespace (str);
3619 if (reg_required_here (& str, 0) != FAIL)
3621 inst.error = NULL;
3622 end_of_line (str);
3623 return;
3626 if (! is_immediate_prefix (* str))
3628 inst.error =
3629 _("only a register or immediate value can follow a psr flag");
3630 return;
3633 str ++;
3634 inst.error = NULL;
3636 if (my_get_expression (& inst.reloc.exp, & str))
3638 inst.error =
3639 _("only a register or immediate value can follow a psr flag");
3640 return;
3643 #if 0 /* The first edition of the ARM architecture manual stated that
3644 writing anything other than the flags with an immediate operation
3645 had UNPREDICTABLE effects. This constraint was removed in the
3646 second edition of the specification. */
3647 if ((cpu_variant & ARM_EXT_V5) != ARM_EXT_V5
3648 && inst.instruction & ((PSR_c | PSR_x | PSR_s) << PSR_SHIFT))
3650 inst.error = _("immediate value cannot be used to set this field");
3651 return;
3653 #endif
3655 inst.instruction |= INST_IMMEDIATE;
3657 if (inst.reloc.exp.X_add_symbol)
3659 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
3660 inst.reloc.pc_rel = 0;
3662 else
3664 unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
3666 if (value == (unsigned) FAIL)
3668 inst.error = _("invalid constant");
3669 return;
3672 inst.instruction |= value;
3675 inst.error = NULL;
3676 end_of_line (str);
3679 /* Long Multiply Parser
3680 UMULL RdLo, RdHi, Rm, Rs
3681 SMULL RdLo, RdHi, Rm, Rs
3682 UMLAL RdLo, RdHi, Rm, Rs
3683 SMLAL RdLo, RdHi, Rm, Rs. */
3685 static void
3686 do_mull (str)
3687 char * str;
3689 int rdlo, rdhi, rm, rs;
3691 /* Only one format "rdlo, rdhi, rm, rs". */
3692 skip_whitespace (str);
3694 if ((rdlo = reg_required_here (&str, 12)) == FAIL)
3696 inst.error = BAD_ARGS;
3697 return;
3700 if (skip_past_comma (&str) == FAIL
3701 || (rdhi = reg_required_here (&str, 16)) == FAIL)
3703 inst.error = BAD_ARGS;
3704 return;
3707 if (skip_past_comma (&str) == FAIL
3708 || (rm = reg_required_here (&str, 0)) == FAIL)
3710 inst.error = BAD_ARGS;
3711 return;
3714 /* rdhi, rdlo and rm must all be different. */
3715 if (rdlo == rdhi || rdlo == rm || rdhi == rm)
3716 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
3718 if (skip_past_comma (&str) == FAIL
3719 || (rs = reg_required_here (&str, 8)) == FAIL)
3721 inst.error = BAD_ARGS;
3722 return;
3725 if (rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC)
3727 inst.error = BAD_PC;
3728 return;
3731 end_of_line (str);
3732 return;
3735 static void
3736 do_mul (str)
3737 char * str;
3739 int rd, rm;
3741 /* Only one format "rd, rm, rs". */
3742 skip_whitespace (str);
3744 if ((rd = reg_required_here (&str, 16)) == FAIL)
3746 inst.error = BAD_ARGS;
3747 return;
3750 if (rd == REG_PC)
3752 inst.error = BAD_PC;
3753 return;
3756 if (skip_past_comma (&str) == FAIL
3757 || (rm = reg_required_here (&str, 0)) == FAIL)
3759 inst.error = BAD_ARGS;
3760 return;
3763 if (rm == REG_PC)
3765 inst.error = BAD_PC;
3766 return;
3769 if (rm == rd)
3770 as_tsktsk (_("rd and rm should be different in mul"));
3772 if (skip_past_comma (&str) == FAIL
3773 || (rm = reg_required_here (&str, 8)) == FAIL)
3775 inst.error = BAD_ARGS;
3776 return;
3779 if (rm == REG_PC)
3781 inst.error = BAD_PC;
3782 return;
3785 end_of_line (str);
3786 return;
3789 static void
3790 do_mla (str)
3791 char * str;
3793 int rd, rm;
3795 /* Only one format "rd, rm, rs, rn". */
3796 skip_whitespace (str);
3798 if ((rd = reg_required_here (&str, 16)) == FAIL)
3800 inst.error = BAD_ARGS;
3801 return;
3804 if (rd == REG_PC)
3806 inst.error = BAD_PC;
3807 return;
3810 if (skip_past_comma (&str) == FAIL
3811 || (rm = reg_required_here (&str, 0)) == FAIL)
3813 inst.error = BAD_ARGS;
3814 return;
3817 if (rm == REG_PC)
3819 inst.error = BAD_PC;
3820 return;
3823 if (rm == rd)
3824 as_tsktsk (_("rd and rm should be different in mla"));
3826 if (skip_past_comma (&str) == FAIL
3827 || (rd = reg_required_here (&str, 8)) == FAIL
3828 || skip_past_comma (&str) == FAIL
3829 || (rm = reg_required_here (&str, 12)) == FAIL)
3831 inst.error = BAD_ARGS;
3832 return;
3835 if (rd == REG_PC || rm == REG_PC)
3837 inst.error = BAD_PC;
3838 return;
3841 end_of_line (str);
3842 return;
3845 /* Expects *str -> the characters "acc0", possibly with leading blanks.
3846 Advances *str to the next non-alphanumeric.
3847 Returns 0, or else FAIL (in which case sets inst.error).
3849 (In a future XScale, there may be accumulators other than zero.
3850 At that time this routine and its callers can be upgraded to suit.) */
3852 static int
3853 accum0_required_here (str)
3854 char ** str;
3856 static char buff [128]; /* Note the address is taken. Hence, static. */
3857 char * p = * str;
3858 char c;
3859 int result = 0; /* The accum number. */
3861 skip_whitespace (p);
3863 *str = p; /* Advance caller's string pointer too. */
3864 c = *p++;
3865 while (ISALNUM (c))
3866 c = *p++;
3868 *--p = 0; /* Aap nul into input buffer at non-alnum. */
3870 if (! ( streq (*str, "acc0") || streq (*str, "ACC0")))
3872 sprintf (buff, _("acc0 expected, not '%.100s'"), *str);
3873 inst.error = buff;
3874 result = FAIL;
3877 *p = c; /* Unzap. */
3878 *str = p; /* Caller's string pointer to after match. */
3879 return result;
3882 /* Expects **str -> after a comma. May be leading blanks.
3883 Advances *str, recognizing a load mode, and setting inst.instruction.
3884 Returns rn, or else FAIL (in which case may set inst.error
3885 and not advance str)
3887 Note: doesn't know Rd, so no err checks that require such knowledge. */
3889 static int
3890 ld_mode_required_here (string)
3891 char ** string;
3893 char * str = * string;
3894 int rn;
3895 int pre_inc = 0;
3897 skip_whitespace (str);
3899 if (* str == '[')
3901 str++;
3903 skip_whitespace (str);
3905 if ((rn = reg_required_here (& str, 16)) == FAIL)
3906 return FAIL;
3908 skip_whitespace (str);
3910 if (* str == ']')
3912 str ++;
3914 if (skip_past_comma (& str) == SUCCESS)
3916 /* [Rn],... (post inc) */
3917 if (ldst_extend_v4 (&str) == FAIL)
3918 return FAIL;
3920 else /* [Rn] */
3922 skip_whitespace (str);
3924 if (* str == '!')
3926 str ++;
3927 inst.instruction |= WRITE_BACK;
3930 inst.instruction |= INDEX_UP | HWOFFSET_IMM;
3931 pre_inc = 1;
3934 else /* [Rn,...] */
3936 if (skip_past_comma (& str) == FAIL)
3938 inst.error = _("pre-indexed expression expected");
3939 return FAIL;
3942 pre_inc = 1;
3944 if (ldst_extend_v4 (&str) == FAIL)
3945 return FAIL;
3947 skip_whitespace (str);
3949 if (* str ++ != ']')
3951 inst.error = _("missing ]");
3952 return FAIL;
3955 skip_whitespace (str);
3957 if (* str == '!')
3959 str ++;
3960 inst.instruction |= WRITE_BACK;
3964 else if (* str == '=') /* ldr's "r,=label" syntax */
3965 /* We should never reach here, because <text> = <expression> is
3966 caught gas/read.c read_a_source_file() as a .set operation. */
3967 return FAIL;
3968 else /* PC +- 8 bit immediate offset. */
3970 if (my_get_expression (& inst.reloc.exp, & str))
3971 return FAIL;
3973 inst.instruction |= HWOFFSET_IMM; /* The I bit. */
3974 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
3975 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
3976 inst.reloc.pc_rel = 1;
3977 inst.instruction |= (REG_PC << 16);
3979 rn = REG_PC;
3980 pre_inc = 1;
3983 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
3984 * string = str;
3986 return rn;
3989 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
3990 SMLAxy{cond} Rd,Rm,Rs,Rn
3991 SMLAWy{cond} Rd,Rm,Rs,Rn
3992 Error if any register is R15. */
3994 static void
3995 do_smla (str)
3996 char * str;
3998 int rd, rm, rs, rn;
4000 skip_whitespace (str);
4002 if ((rd = reg_required_here (& str, 16)) == FAIL
4003 || skip_past_comma (& str) == FAIL
4004 || (rm = reg_required_here (& str, 0)) == FAIL
4005 || skip_past_comma (& str) == FAIL
4006 || (rs = reg_required_here (& str, 8)) == FAIL
4007 || skip_past_comma (& str) == FAIL
4008 || (rn = reg_required_here (& str, 12)) == FAIL)
4009 inst.error = BAD_ARGS;
4011 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC || rn == REG_PC)
4012 inst.error = BAD_PC;
4014 else
4015 end_of_line (str);
4018 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
4019 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
4020 Error if any register is R15.
4021 Warning if Rdlo == Rdhi. */
4023 static void
4024 do_smlal (str)
4025 char * str;
4027 int rdlo, rdhi, rm, rs;
4029 skip_whitespace (str);
4031 if ((rdlo = reg_required_here (& str, 12)) == FAIL
4032 || skip_past_comma (& str) == FAIL
4033 || (rdhi = reg_required_here (& str, 16)) == FAIL
4034 || skip_past_comma (& str) == FAIL
4035 || (rm = reg_required_here (& str, 0)) == FAIL
4036 || skip_past_comma (& str) == FAIL
4037 || (rs = reg_required_here (& str, 8)) == FAIL)
4039 inst.error = BAD_ARGS;
4040 return;
4043 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
4045 inst.error = BAD_PC;
4046 return;
4049 if (rdlo == rdhi)
4050 as_tsktsk (_("rdhi and rdlo must be different"));
4052 end_of_line (str);
4055 /* ARM V5E (El Segundo) signed-multiply (argument parse)
4056 SMULxy{cond} Rd,Rm,Rs
4057 Error if any register is R15. */
4059 static void
4060 do_smul (str)
4061 char * str;
4063 int rd, rm, rs;
4065 skip_whitespace (str);
4067 if ((rd = reg_required_here (& str, 16)) == FAIL
4068 || skip_past_comma (& str) == FAIL
4069 || (rm = reg_required_here (& str, 0)) == FAIL
4070 || skip_past_comma (& str) == FAIL
4071 || (rs = reg_required_here (& str, 8)) == FAIL)
4072 inst.error = BAD_ARGS;
4074 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC)
4075 inst.error = BAD_PC;
4077 else
4078 end_of_line (str);
4081 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
4082 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
4083 Error if any register is R15. */
4085 static void
4086 do_qadd (str)
4087 char * str;
4089 int rd, rm, rn;
4091 skip_whitespace (str);
4093 if ((rd = reg_required_here (& str, 12)) == FAIL
4094 || skip_past_comma (& str) == FAIL
4095 || (rm = reg_required_here (& str, 0)) == FAIL
4096 || skip_past_comma (& str) == FAIL
4097 || (rn = reg_required_here (& str, 16)) == FAIL)
4098 inst.error = BAD_ARGS;
4100 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
4101 inst.error = BAD_PC;
4103 else
4104 end_of_line (str);
4107 /* ARM V5E (el Segundo)
4108 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4109 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4111 These are equivalent to the XScale instructions MAR and MRA,
4112 respectively, when coproc == 0, opcode == 0, and CRm == 0.
4114 Result unpredicatable if Rd or Rn is R15. */
4116 static void
4117 do_co_reg2c (str)
4118 char * str;
4120 int rd, rn;
4122 skip_whitespace (str);
4124 if (co_proc_number (& str) == FAIL)
4126 if (!inst.error)
4127 inst.error = BAD_ARGS;
4128 return;
4131 if (skip_past_comma (& str) == FAIL
4132 || cp_opc_expr (& str, 4, 4) == FAIL)
4134 if (!inst.error)
4135 inst.error = BAD_ARGS;
4136 return;
4139 if (skip_past_comma (& str) == FAIL
4140 || (rd = reg_required_here (& str, 12)) == FAIL)
4142 if (!inst.error)
4143 inst.error = BAD_ARGS;
4144 return;
4147 if (skip_past_comma (& str) == FAIL
4148 || (rn = reg_required_here (& str, 16)) == FAIL)
4150 if (!inst.error)
4151 inst.error = BAD_ARGS;
4152 return;
4155 /* Unpredictable result if rd or rn is R15. */
4156 if (rd == REG_PC || rn == REG_PC)
4157 as_tsktsk
4158 (_("Warning: instruction unpredictable when using r15"));
4160 if (skip_past_comma (& str) == FAIL
4161 || cp_reg_required_here (& str, 0) == FAIL)
4163 if (!inst.error)
4164 inst.error = BAD_ARGS;
4165 return;
4168 end_of_line (str);
4171 /* ARM V5 count-leading-zeroes instruction (argument parse)
4172 CLZ{<cond>} <Rd>, <Rm>
4173 Condition defaults to COND_ALWAYS.
4174 Error if Rd or Rm are R15. */
4176 static void
4177 do_clz (str)
4178 char * str;
4180 int rd, rm;
4182 skip_whitespace (str);
4184 if (((rd = reg_required_here (& str, 12)) == FAIL)
4185 || (skip_past_comma (& str) == FAIL)
4186 || ((rm = reg_required_here (& str, 0)) == FAIL))
4187 inst.error = BAD_ARGS;
4189 else if (rd == REG_PC || rm == REG_PC )
4190 inst.error = BAD_PC;
4192 else
4193 end_of_line (str);
4196 /* ARM V5 (argument parse)
4197 LDC2{L} <coproc>, <CRd>, <addressing mode>
4198 STC2{L} <coproc>, <CRd>, <addressing mode>
4199 Instruction is not conditional, and has 0xf in the codition field.
4200 Otherwise, it's the same as LDC/STC. */
4202 static void
4203 do_lstc2 (str)
4204 char * str;
4206 skip_whitespace (str);
4208 if (co_proc_number (& str) == FAIL)
4210 if (!inst.error)
4211 inst.error = BAD_ARGS;
4213 else if (skip_past_comma (& str) == FAIL
4214 || cp_reg_required_here (& str, 12) == FAIL)
4216 if (!inst.error)
4217 inst.error = BAD_ARGS;
4219 else if (skip_past_comma (& str) == FAIL
4220 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
4222 if (! inst.error)
4223 inst.error = BAD_ARGS;
4225 else
4226 end_of_line (str);
4229 /* ARM V5 (argument parse)
4230 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
4231 Instruction is not conditional, and has 0xf in the condition field.
4232 Otherwise, it's the same as CDP. */
4234 static void
4235 do_cdp2 (str)
4236 char * str;
4238 skip_whitespace (str);
4240 if (co_proc_number (& str) == FAIL)
4242 if (!inst.error)
4243 inst.error = BAD_ARGS;
4244 return;
4247 if (skip_past_comma (& str) == FAIL
4248 || cp_opc_expr (& str, 20,4) == FAIL)
4250 if (!inst.error)
4251 inst.error = BAD_ARGS;
4252 return;
4255 if (skip_past_comma (& str) == FAIL
4256 || cp_reg_required_here (& str, 12) == FAIL)
4258 if (!inst.error)
4259 inst.error = BAD_ARGS;
4260 return;
4263 if (skip_past_comma (& str) == FAIL
4264 || cp_reg_required_here (& str, 16) == FAIL)
4266 if (!inst.error)
4267 inst.error = BAD_ARGS;
4268 return;
4271 if (skip_past_comma (& str) == FAIL
4272 || cp_reg_required_here (& str, 0) == FAIL)
4274 if (!inst.error)
4275 inst.error = BAD_ARGS;
4276 return;
4279 if (skip_past_comma (& str) == SUCCESS)
4281 if (cp_opc_expr (& str, 5, 3) == FAIL)
4283 if (!inst.error)
4284 inst.error = BAD_ARGS;
4285 return;
4289 end_of_line (str);
4292 /* ARM V5 (argument parse)
4293 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4294 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4295 Instruction is not conditional, and has 0xf in the condition field.
4296 Otherwise, it's the same as MCR/MRC. */
4298 static void
4299 do_co_reg2 (str)
4300 char * str;
4302 skip_whitespace (str);
4304 if (co_proc_number (& str) == FAIL)
4306 if (!inst.error)
4307 inst.error = BAD_ARGS;
4308 return;
4311 if (skip_past_comma (& str) == FAIL
4312 || cp_opc_expr (& str, 21, 3) == FAIL)
4314 if (!inst.error)
4315 inst.error = BAD_ARGS;
4316 return;
4319 if (skip_past_comma (& str) == FAIL
4320 || reg_required_here (& str, 12) == FAIL)
4322 if (!inst.error)
4323 inst.error = BAD_ARGS;
4324 return;
4327 if (skip_past_comma (& str) == FAIL
4328 || cp_reg_required_here (& str, 16) == FAIL)
4330 if (!inst.error)
4331 inst.error = BAD_ARGS;
4332 return;
4335 if (skip_past_comma (& str) == FAIL
4336 || cp_reg_required_here (& str, 0) == FAIL)
4338 if (!inst.error)
4339 inst.error = BAD_ARGS;
4340 return;
4343 if (skip_past_comma (& str) == SUCCESS)
4345 if (cp_opc_expr (& str, 5, 3) == FAIL)
4347 if (!inst.error)
4348 inst.error = BAD_ARGS;
4349 return;
4353 end_of_line (str);
4356 /* ARM v5TEJ. Jump to Jazelle code. */
4357 static void
4358 do_bxj (str)
4359 char * str;
4361 int reg;
4363 skip_whitespace (str);
4365 if ((reg = reg_required_here (&str, 0)) == FAIL)
4367 inst.error = BAD_ARGS;
4368 return;
4371 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
4372 if (reg == REG_PC)
4373 as_tsktsk (_("use of r15 in bxj is not really useful"));
4375 end_of_line (str);
4378 /* THUMB V5 breakpoint instruction (argument parse)
4379 BKPT <immed_8>. */
4381 static void
4382 do_t_bkpt (str)
4383 char * str;
4385 expressionS expr;
4386 unsigned long number;
4388 skip_whitespace (str);
4390 /* Allow optional leading '#'. */
4391 if (is_immediate_prefix (*str))
4392 str ++;
4394 memset (& expr, '\0', sizeof (expr));
4395 if (my_get_expression (& expr, & str)
4396 || (expr.X_op != O_constant
4397 /* As a convenience we allow 'bkpt' without an operand. */
4398 && expr.X_op != O_absent))
4400 inst.error = _("bad expression");
4401 return;
4404 number = expr.X_add_number;
4406 /* Check it fits an 8 bit unsigned. */
4407 if (number != (number & 0xff))
4409 inst.error = _("immediate value out of range");
4410 return;
4413 inst.instruction |= number;
4415 end_of_line (str);
4418 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
4419 Expects inst.instruction is set for BLX(1).
4420 Note: this is cloned from do_branch, and the reloc changed to be a
4421 new one that can cope with setting one extra bit (the H bit). */
4423 static void
4424 do_branch25 (str)
4425 char * str;
4427 if (my_get_expression (& inst.reloc.exp, & str))
4428 return;
4430 #ifdef OBJ_ELF
4432 char * save_in;
4434 /* ScottB: February 5, 1998 */
4435 /* Check to see of PLT32 reloc required for the instruction. */
4437 /* arm_parse_reloc() works on input_line_pointer.
4438 We actually want to parse the operands to the branch instruction
4439 passed in 'str'. Save the input pointer and restore it later. */
4440 save_in = input_line_pointer;
4441 input_line_pointer = str;
4443 if (inst.reloc.exp.X_op == O_symbol
4444 && *str == '('
4445 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
4447 inst.reloc.type = BFD_RELOC_ARM_PLT32;
4448 inst.reloc.pc_rel = 0;
4449 /* Modify str to point to after parsed operands, otherwise
4450 end_of_line() will complain about the (PLT) left in str. */
4451 str = input_line_pointer;
4453 else
4455 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
4456 inst.reloc.pc_rel = 1;
4459 input_line_pointer = save_in;
4461 #else
4462 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
4463 inst.reloc.pc_rel = 1;
4464 #endif /* OBJ_ELF */
4466 end_of_line (str);
4469 /* ARM V5 branch-link-exchange instruction (argument parse)
4470 BLX <target_addr> ie BLX(1)
4471 BLX{<condition>} <Rm> ie BLX(2)
4472 Unfortunately, there are two different opcodes for this mnemonic.
4473 So, the insns[].value is not used, and the code here zaps values
4474 into inst.instruction.
4475 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
4477 static void
4478 do_blx (str)
4479 char * str;
4481 char * mystr = str;
4482 int rm;
4484 skip_whitespace (mystr);
4485 rm = reg_required_here (& mystr, 0);
4487 /* The above may set inst.error. Ignore his opinion. */
4488 inst.error = 0;
4490 if (rm != FAIL)
4492 /* Arg is a register.
4493 Use the condition code our caller put in inst.instruction.
4494 Pass ourselves off as a BX with a funny opcode. */
4495 inst.instruction |= 0x012fff30;
4496 do_bx (str);
4498 else
4500 /* This must be is BLX <target address>, no condition allowed. */
4501 if (inst.instruction != COND_ALWAYS)
4503 inst.error = BAD_COND;
4504 return;
4507 inst.instruction = 0xfafffffe;
4509 /* Process like a B/BL, but with a different reloc.
4510 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
4511 do_branch25 (str);
4515 /* ARM V5 Thumb BLX (argument parse)
4516 BLX <target_addr> which is BLX(1)
4517 BLX <Rm> which is BLX(2)
4518 Unfortunately, there are two different opcodes for this mnemonic.
4519 So, the tinsns[].value is not used, and the code here zaps values
4520 into inst.instruction. */
4522 static void
4523 do_t_blx (str)
4524 char * str;
4526 char * mystr = str;
4527 int rm;
4529 skip_whitespace (mystr);
4530 inst.instruction = 0x4780;
4532 /* Note that this call is to the ARM register recognizer. BLX(2)
4533 uses the ARM register space, not the Thumb one, so a call to
4534 thumb_reg() would be wrong. */
4535 rm = reg_required_here (& mystr, 3);
4536 inst.error = 0;
4538 if (rm != FAIL)
4540 /* It's BLX(2). The .instruction was zapped with rm & is final. */
4541 inst.size = 2;
4543 else
4545 /* No ARM register. This must be BLX(1). Change the .instruction. */
4546 inst.instruction = 0xf7ffeffe;
4547 inst.size = 4;
4549 if (my_get_expression (& inst.reloc.exp, & mystr))
4550 return;
4552 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BLX;
4553 inst.reloc.pc_rel = 1;
4556 end_of_line (mystr);
4559 /* ARM V5 breakpoint instruction (argument parse)
4560 BKPT <16 bit unsigned immediate>
4561 Instruction is not conditional.
4562 The bit pattern given in insns[] has the COND_ALWAYS condition,
4563 and it is an error if the caller tried to override that. */
4565 static void
4566 do_bkpt (str)
4567 char * str;
4569 expressionS expr;
4570 unsigned long number;
4572 skip_whitespace (str);
4574 /* Allow optional leading '#'. */
4575 if (is_immediate_prefix (* str))
4576 str++;
4578 memset (& expr, '\0', sizeof (expr));
4580 if (my_get_expression (& expr, & str)
4581 || (expr.X_op != O_constant
4582 /* As a convenience we allow 'bkpt' without an operand. */
4583 && expr.X_op != O_absent))
4585 inst.error = _("bad expression");
4586 return;
4589 number = expr.X_add_number;
4591 /* Check it fits a 16 bit unsigned. */
4592 if (number != (number & 0xffff))
4594 inst.error = _("immediate value out of range");
4595 return;
4598 /* Top 12 of 16 bits to bits 19:8. */
4599 inst.instruction |= (number & 0xfff0) << 4;
4601 /* Bottom 4 of 16 bits to bits 3:0. */
4602 inst.instruction |= number & 0xf;
4604 end_of_line (str);
4607 static unsigned long check_iwmmxt_insn PARAMS ((char *, enum iwmmxt_insn_type, int));
4609 /* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
4611 static unsigned long
4612 check_iwmmxt_insn (str, insn_type, immediate_size)
4613 char * str;
4614 enum iwmmxt_insn_type insn_type;
4615 int immediate_size;
4617 int reg = 0;
4618 const char * inst_error;
4619 expressionS expr;
4620 unsigned long number;
4622 inst_error = inst.error;
4623 if (!inst.error)
4624 inst.error = BAD_ARGS;
4625 skip_whitespace (str);
4627 switch (insn_type)
4629 case check_rd:
4630 if ((reg = reg_required_here (&str, 12)) == FAIL)
4631 return FAIL;
4632 break;
4634 case check_wr:
4635 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR)) == FAIL)
4636 return FAIL;
4637 break;
4639 case check_wrwr:
4640 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
4641 || skip_past_comma (&str) == FAIL
4642 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
4643 return FAIL;
4644 break;
4646 case check_wrwrwr:
4647 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
4648 || skip_past_comma (&str) == FAIL
4649 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4650 || skip_past_comma (&str) == FAIL
4651 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
4652 return FAIL;
4653 break;
4655 case check_wrwrwcg:
4656 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
4657 || skip_past_comma (&str) == FAIL
4658 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4659 || skip_past_comma (&str) == FAIL
4660 || wreg_required_here (&str, 0, IWMMXT_REG_WCG) == FAIL))
4661 return FAIL;
4662 break;
4664 case check_tbcst:
4665 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4666 || skip_past_comma (&str) == FAIL
4667 || reg_required_here (&str, 12) == FAIL))
4668 return FAIL;
4669 break;
4671 case check_tmovmsk:
4672 if ((reg_required_here (&str, 12) == FAIL
4673 || skip_past_comma (&str) == FAIL
4674 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
4675 return FAIL;
4676 break;
4678 case check_tmia:
4679 if ((wreg_required_here (&str, 5, IWMMXT_REG_WR) == FAIL
4680 || skip_past_comma (&str) == FAIL
4681 || reg_required_here (&str, 0) == FAIL
4682 || skip_past_comma (&str) == FAIL
4683 || reg_required_here (&str, 12) == FAIL))
4684 return FAIL;
4685 break;
4687 case check_tmcrr:
4688 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
4689 || skip_past_comma (&str) == FAIL
4690 || reg_required_here (&str, 12) == FAIL
4691 || skip_past_comma (&str) == FAIL
4692 || reg_required_here (&str, 16) == FAIL))
4693 return FAIL;
4694 break;
4696 case check_tmrrc:
4697 if ((reg_required_here (&str, 12) == FAIL
4698 || skip_past_comma (&str) == FAIL
4699 || reg_required_here (&str, 16) == FAIL
4700 || skip_past_comma (&str) == FAIL
4701 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
4702 return FAIL;
4703 break;
4705 case check_tmcr:
4706 if ((wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL
4707 || skip_past_comma (&str) == FAIL
4708 || reg_required_here (&str, 12) == FAIL))
4709 return FAIL;
4710 break;
4712 case check_tmrc:
4713 if ((reg_required_here (&str, 12) == FAIL
4714 || skip_past_comma (&str) == FAIL
4715 || wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL))
4716 return FAIL;
4717 break;
4719 case check_tinsr:
4720 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4721 || skip_past_comma (&str) == FAIL
4722 || reg_required_here (&str, 12) == FAIL
4723 || skip_past_comma (&str) == FAIL))
4724 return FAIL;
4725 break;
4727 case check_textrc:
4728 if ((reg_required_here (&str, 12) == FAIL
4729 || skip_past_comma (&str) == FAIL))
4730 return FAIL;
4731 break;
4733 case check_waligni:
4734 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
4735 || skip_past_comma (&str) == FAIL
4736 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4737 || skip_past_comma (&str) == FAIL
4738 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
4739 || skip_past_comma (&str) == FAIL))
4740 return FAIL;
4741 break;
4743 case check_textrm:
4744 if ((reg_required_here (&str, 12) == FAIL
4745 || skip_past_comma (&str) == FAIL
4746 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4747 || skip_past_comma (&str) == FAIL))
4748 return FAIL;
4749 break;
4751 case check_wshufh:
4752 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
4753 || skip_past_comma (&str) == FAIL
4754 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4755 || skip_past_comma (&str) == FAIL))
4756 return FAIL;
4757 break;
4760 if (immediate_size == 0)
4762 end_of_line (str);
4763 inst.error = inst_error;
4764 return reg;
4766 else
4768 skip_whitespace (str);
4770 /* Allow optional leading '#'. */
4771 if (is_immediate_prefix (* str))
4772 str++;
4774 memset (& expr, '\0', sizeof (expr));
4776 if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
4778 inst.error = _("bad or missing expression");
4779 return FAIL;
4782 number = expr.X_add_number;
4784 if (number != (number & immediate_size))
4786 inst.error = _("immediate value out of range");
4787 return FAIL;
4789 end_of_line (str);
4790 inst.error = inst_error;
4791 return number;
4795 static void
4796 do_iwmmxt_byte_addr (str)
4797 char * str;
4799 int op = (inst.instruction & 0x300) >> 8;
4800 int reg;
4802 inst.instruction &= ~0x300;
4803 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
4805 skip_whitespace (str);
4807 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
4808 || skip_past_comma (& str) == FAIL
4809 || cp_byte_address_required_here (&str) == FAIL)
4811 if (! inst.error)
4812 inst.error = BAD_ARGS;
4814 else
4815 end_of_line (str);
4817 if (wc_register (reg))
4819 inst.instruction |= 0xf0000100;
4820 inst.instruction &= ~0x00400000;
4824 static void
4825 do_iwmmxt_tandc (str)
4826 char * str;
4828 int reg;
4830 reg = check_iwmmxt_insn (str, check_rd, 0);
4832 if (reg != REG_PC && !inst.error)
4833 inst.error = _("only r15 allowed here");
4834 return;
4837 static void
4838 do_iwmmxt_tbcst (str)
4839 char * str;
4841 check_iwmmxt_insn (str, check_tbcst, 0);
4843 return;
4846 static void
4847 do_iwmmxt_textrc (str)
4848 char * str;
4850 unsigned long number;
4852 if ((number = check_iwmmxt_insn (str, check_textrc, 7)) == (unsigned long) FAIL)
4853 return;
4855 inst.instruction |= number & 0x7;
4856 return;
4859 static void
4860 do_iwmmxt_textrm (str)
4861 char * str;
4863 unsigned long number;
4865 if ((number = check_iwmmxt_insn (str, check_textrm, 7)) == (unsigned long) FAIL)
4866 return;
4868 inst.instruction |= number & 0x7;
4871 static void
4872 do_iwmmxt_tinsr (str)
4873 char * str;
4875 unsigned long number;
4877 if ((number = check_iwmmxt_insn (str, check_tinsr, 7)) == (unsigned long) FAIL)
4878 return;
4880 inst.instruction |= number & 0x7;
4881 return;
4884 static void
4885 do_iwmmxt_tmcr (str)
4886 char * str;
4888 check_iwmmxt_insn (str, check_tmcr, 0);
4890 return;
4893 static void
4894 do_iwmmxt_tmcrr (str)
4895 char * str;
4897 check_iwmmxt_insn (str, check_tmcrr, 0);
4899 return;
4902 static void
4903 do_iwmmxt_tmia (str)
4904 char * str;
4906 check_iwmmxt_insn (str, check_tmia, 0);
4908 return;
4911 static void
4912 do_iwmmxt_tmovmsk (str)
4913 char * str;
4915 check_iwmmxt_insn (str, check_tmovmsk, 0);
4917 return;
4920 static void
4921 do_iwmmxt_tmrc (str)
4922 char * str;
4924 check_iwmmxt_insn (str, check_tmrc, 0);
4926 return;
4929 static void
4930 do_iwmmxt_tmrrc (str)
4931 char * str;
4933 check_iwmmxt_insn (str, check_tmrrc, 0);
4935 return;
4938 static void
4939 do_iwmmxt_torc (str)
4940 char * str;
4942 check_iwmmxt_insn (str, check_rd, 0);
4943 return;
4946 static void
4947 do_iwmmxt_waligni (str)
4948 char * str;
4950 unsigned long number;
4952 if ((number = check_iwmmxt_insn (str, check_waligni, 7)) == (unsigned long) FAIL)
4953 return;
4955 inst.instruction |= ((number & 0x7) << 20);
4956 return;
4959 static void
4960 do_iwmmxt_wmov (str)
4961 char * str;
4963 if (check_iwmmxt_insn (str, check_wrwr, 0) == (unsigned long) FAIL)
4964 return;
4966 inst.instruction |= ((inst.instruction >> 16) & 0xf);
4967 return;
4970 static void
4971 do_iwmmxt_word_addr (str)
4972 char * str;
4974 int op = (inst.instruction & 0x300) >> 8;
4975 int reg;
4977 inst.instruction &= ~0x300;
4978 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
4980 skip_whitespace (str);
4982 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
4983 || skip_past_comma (& str) == FAIL
4984 || cp_address_required_here (& str, CP_WB_OK) == FAIL)
4986 if (! inst.error)
4987 inst.error = BAD_ARGS;
4989 else
4990 end_of_line (str);
4992 if (wc_register (reg))
4994 inst.instruction |= 0xf0000100;
4995 inst.instruction &= ~0x00400000;
4999 static void
5000 do_iwmmxt_wrwr (str)
5001 char * str;
5003 check_iwmmxt_insn (str, check_wrwr, 0);
5005 return;
5008 static void
5009 do_iwmmxt_wrwrwcg (str)
5010 char * str;
5012 check_iwmmxt_insn (str, check_wrwrwcg, 0);
5014 return;
5017 static void
5018 do_iwmmxt_wrwrwr (str)
5019 char * str;
5021 check_iwmmxt_insn (str, check_wrwrwr, 0);
5023 return;
5026 static void
5027 do_iwmmxt_wshufh (str)
5028 char * str;
5030 unsigned long number;
5032 if ((number = check_iwmmxt_insn (str, check_wshufh, 0xff)) == (unsigned long) FAIL)
5033 return;
5035 inst.instruction |= ((number & 0xf0) << 16) | (number & 0xf);
5036 return;
5039 static void
5040 do_iwmmxt_wzero (str)
5041 char * str;
5043 if (check_iwmmxt_insn (str, check_wr, 0) == (unsigned long) FAIL)
5044 return;
5046 inst.instruction |= ((inst.instruction & 0xf) << 12) | ((inst.instruction & 0xf) << 16);
5047 return;
5050 /* Xscale multiply-accumulate (argument parse)
5051 MIAcc acc0,Rm,Rs
5052 MIAPHcc acc0,Rm,Rs
5053 MIAxycc acc0,Rm,Rs. */
5055 static void
5056 do_xsc_mia (str)
5057 char * str;
5059 int rs;
5060 int rm;
5062 if (accum0_required_here (& str) == FAIL)
5063 inst.error = ERR_NO_ACCUM;
5065 else if (skip_past_comma (& str) == FAIL
5066 || (rm = reg_required_here (& str, 0)) == FAIL)
5067 inst.error = BAD_ARGS;
5069 else if (skip_past_comma (& str) == FAIL
5070 || (rs = reg_required_here (& str, 12)) == FAIL)
5071 inst.error = BAD_ARGS;
5073 /* inst.instruction has now been zapped with both rm and rs. */
5074 else if (rm == REG_PC || rs == REG_PC)
5075 inst.error = BAD_PC; /* Undefined result if rm or rs is R15. */
5077 else
5078 end_of_line (str);
5081 /* Xscale move-accumulator-register (argument parse)
5083 MARcc acc0,RdLo,RdHi. */
5085 static void
5086 do_xsc_mar (str)
5087 char * str;
5089 int rdlo, rdhi;
5091 if (accum0_required_here (& str) == FAIL)
5092 inst.error = ERR_NO_ACCUM;
5094 else if (skip_past_comma (& str) == FAIL
5095 || (rdlo = reg_required_here (& str, 12)) == FAIL)
5096 inst.error = BAD_ARGS;
5098 else if (skip_past_comma (& str) == FAIL
5099 || (rdhi = reg_required_here (& str, 16)) == FAIL)
5100 inst.error = BAD_ARGS;
5102 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5103 else if (rdlo == REG_PC || rdhi == REG_PC)
5104 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
5106 else
5107 end_of_line (str);
5110 /* Xscale move-register-accumulator (argument parse)
5112 MRAcc RdLo,RdHi,acc0. */
5114 static void
5115 do_xsc_mra (str)
5116 char * str;
5118 int rdlo;
5119 int rdhi;
5121 skip_whitespace (str);
5123 if ((rdlo = reg_required_here (& str, 12)) == FAIL)
5124 inst.error = BAD_ARGS;
5126 else if (skip_past_comma (& str) == FAIL
5127 || (rdhi = reg_required_here (& str, 16)) == FAIL)
5128 inst.error = BAD_ARGS;
5130 else if (skip_past_comma (& str) == FAIL
5131 || accum0_required_here (& str) == FAIL)
5132 inst.error = ERR_NO_ACCUM;
5134 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5135 else if (rdlo == rdhi)
5136 inst.error = BAD_ARGS; /* Undefined result if 2 writes to same reg. */
5138 else if (rdlo == REG_PC || rdhi == REG_PC)
5139 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
5140 else
5141 end_of_line (str);
5144 /* ARMv5TE: Preload-Cache
5146 PLD <addr_mode>
5148 Syntactically, like LDR with B=1, W=0, L=1. */
5150 static void
5151 do_pld (str)
5152 char * str;
5154 int rd;
5156 skip_whitespace (str);
5158 if (* str != '[')
5160 inst.error = _("'[' expected after PLD mnemonic");
5161 return;
5164 ++str;
5165 skip_whitespace (str);
5167 if ((rd = reg_required_here (& str, 16)) == FAIL)
5168 return;
5170 skip_whitespace (str);
5172 if (*str == ']')
5174 /* [Rn], ... ? */
5175 ++str;
5176 skip_whitespace (str);
5178 /* Post-indexed addressing is not allowed with PLD. */
5179 if (skip_past_comma (&str) == SUCCESS)
5181 inst.error
5182 = _("post-indexed expression used in preload instruction");
5183 return;
5185 else if (*str == '!') /* [Rn]! */
5187 inst.error = _("writeback used in preload instruction");
5188 ++str;
5190 else /* [Rn] */
5191 inst.instruction |= INDEX_UP | PRE_INDEX;
5193 else /* [Rn, ...] */
5195 if (skip_past_comma (& str) == FAIL)
5197 inst.error = _("pre-indexed expression expected");
5198 return;
5201 if (ldst_extend (&str) == FAIL)
5202 return;
5204 skip_whitespace (str);
5206 if (* str != ']')
5208 inst.error = _("missing ]");
5209 return;
5212 ++ str;
5213 skip_whitespace (str);
5215 if (* str == '!') /* [Rn]! */
5217 inst.error = _("writeback used in preload instruction");
5218 ++ str;
5221 inst.instruction |= PRE_INDEX;
5224 end_of_line (str);
5227 /* ARMv5TE load-consecutive (argument parse)
5228 Mode is like LDRH.
5230 LDRccD R, mode
5231 STRccD R, mode. */
5233 static void
5234 do_ldrd (str)
5235 char * str;
5237 int rd;
5238 int rn;
5240 skip_whitespace (str);
5242 if ((rd = reg_required_here (& str, 12)) == FAIL)
5244 inst.error = BAD_ARGS;
5245 return;
5248 if (skip_past_comma (& str) == FAIL
5249 || (rn = ld_mode_required_here (& str)) == FAIL)
5251 if (!inst.error)
5252 inst.error = BAD_ARGS;
5253 return;
5256 /* inst.instruction has now been zapped with Rd and the addressing mode. */
5257 if (rd & 1) /* Unpredictable result if Rd is odd. */
5259 inst.error = _("destination register must be even");
5260 return;
5263 if (rd == REG_LR)
5265 inst.error = _("r14 not allowed here");
5266 return;
5269 if (((rd == rn) || (rd + 1 == rn))
5270 && ((inst.instruction & WRITE_BACK)
5271 || (!(inst.instruction & PRE_INDEX))))
5272 as_warn (_("pre/post-indexing used when modified address register is destination"));
5274 /* For an index-register load, the index register must not overlap the
5275 destination (even if not write-back). */
5276 if ((inst.instruction & V4_STR_BIT) == 0
5277 && (inst.instruction & HWOFFSET_IMM) == 0)
5279 int rm = inst.instruction & 0x0000000f;
5281 if (rm == rd || (rm == rd + 1))
5282 as_warn (_("ldrd destination registers must not overlap index register"));
5285 end_of_line (str);
5288 /* Returns the index into fp_values of a floating point number,
5289 or -1 if not in the table. */
5291 static int
5292 my_get_float_expression (str)
5293 char ** str;
5295 LITTLENUM_TYPE words[MAX_LITTLENUMS];
5296 char * save_in;
5297 expressionS exp;
5298 int i;
5299 int j;
5301 memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE));
5303 /* Look for a raw floating point number. */
5304 if ((save_in = atof_ieee (*str, 'x', words)) != NULL
5305 && is_end_of_line[(unsigned char) *save_in])
5307 for (i = 0; i < NUM_FLOAT_VALS; i++)
5309 for (j = 0; j < MAX_LITTLENUMS; j++)
5311 if (words[j] != fp_values[i][j])
5312 break;
5315 if (j == MAX_LITTLENUMS)
5317 *str = save_in;
5318 return i;
5323 /* Try and parse a more complex expression, this will probably fail
5324 unless the code uses a floating point prefix (eg "0f"). */
5325 save_in = input_line_pointer;
5326 input_line_pointer = *str;
5327 if (expression (&exp) == absolute_section
5328 && exp.X_op == O_big
5329 && exp.X_add_number < 0)
5331 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
5332 Ditto for 15. */
5333 if (gen_to_words (words, 5, (long) 15) == 0)
5335 for (i = 0; i < NUM_FLOAT_VALS; i++)
5337 for (j = 0; j < MAX_LITTLENUMS; j++)
5339 if (words[j] != fp_values[i][j])
5340 break;
5343 if (j == MAX_LITTLENUMS)
5345 *str = input_line_pointer;
5346 input_line_pointer = save_in;
5347 return i;
5353 *str = input_line_pointer;
5354 input_line_pointer = save_in;
5355 return -1;
5358 /* Return TRUE if anything in the expression is a bignum. */
5360 static int
5361 walk_no_bignums (sp)
5362 symbolS * sp;
5364 if (symbol_get_value_expression (sp)->X_op == O_big)
5365 return 1;
5367 if (symbol_get_value_expression (sp)->X_add_symbol)
5369 return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
5370 || (symbol_get_value_expression (sp)->X_op_symbol
5371 && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
5374 return 0;
5377 static int in_my_get_expression = 0;
5379 static int
5380 my_get_expression (ep, str)
5381 expressionS * ep;
5382 char ** str;
5384 char * save_in;
5385 segT seg;
5387 save_in = input_line_pointer;
5388 input_line_pointer = *str;
5389 in_my_get_expression = 1;
5390 seg = expression (ep);
5391 in_my_get_expression = 0;
5393 if (ep->X_op == O_illegal)
5395 /* We found a bad expression in md_operand(). */
5396 *str = input_line_pointer;
5397 input_line_pointer = save_in;
5398 return 1;
5401 #ifdef OBJ_AOUT
5402 if (seg != absolute_section
5403 && seg != text_section
5404 && seg != data_section
5405 && seg != bss_section
5406 && seg != undefined_section)
5408 inst.error = _("bad_segment");
5409 *str = input_line_pointer;
5410 input_line_pointer = save_in;
5411 return 1;
5413 #endif
5415 /* Get rid of any bignums now, so that we don't generate an error for which
5416 we can't establish a line number later on. Big numbers are never valid
5417 in instructions, which is where this routine is always called. */
5418 if (ep->X_op == O_big
5419 || (ep->X_add_symbol
5420 && (walk_no_bignums (ep->X_add_symbol)
5421 || (ep->X_op_symbol
5422 && walk_no_bignums (ep->X_op_symbol)))))
5424 inst.error = _("invalid constant");
5425 *str = input_line_pointer;
5426 input_line_pointer = save_in;
5427 return 1;
5430 *str = input_line_pointer;
5431 input_line_pointer = save_in;
5432 return 0;
5435 /* We handle all bad expressions here, so that we can report the faulty
5436 instruction in the error message. */
5437 void
5438 md_operand (expr)
5439 expressionS *expr;
5441 if (in_my_get_expression)
5443 expr->X_op = O_illegal;
5444 if (inst.error == NULL)
5445 inst.error = _("bad expression");
5449 /* UNRESTRICT should be one if <shift> <register> is permitted for this
5450 instruction. */
5452 static int
5453 decode_shift (str, unrestrict)
5454 char ** str;
5455 int unrestrict;
5457 const struct asm_shift_name * shift;
5458 char * p;
5459 char c;
5461 skip_whitespace (* str);
5463 for (p = * str; ISALPHA (* p); p ++)
5466 if (p == * str)
5468 inst.error = _("shift expression expected");
5469 return FAIL;
5472 c = * p;
5473 * p = '\0';
5474 shift = (const struct asm_shift_name *) hash_find (arm_shift_hsh, * str);
5475 * p = c;
5477 if (shift == NULL)
5479 inst.error = _("shift expression expected");
5480 return FAIL;
5483 assert (shift->properties->index == shift_properties[shift->properties->index].index);
5485 if (shift->properties->index == SHIFT_RRX)
5487 * str = p;
5488 inst.instruction |= shift->properties->bit_field;
5489 return SUCCESS;
5492 skip_whitespace (p);
5494 if (unrestrict && reg_required_here (& p, 8) != FAIL)
5496 inst.instruction |= shift->properties->bit_field | SHIFT_BY_REG;
5497 * str = p;
5498 return SUCCESS;
5500 else if (! is_immediate_prefix (* p))
5502 inst.error = (unrestrict
5503 ? _("shift requires register or #expression")
5504 : _("shift requires #expression"));
5505 * str = p;
5506 return FAIL;
5509 inst.error = NULL;
5510 p ++;
5512 if (my_get_expression (& inst.reloc.exp, & p))
5513 return FAIL;
5515 /* Validate some simple #expressions. */
5516 if (inst.reloc.exp.X_op == O_constant)
5518 unsigned num = inst.reloc.exp.X_add_number;
5520 /* Reject operations greater than 32. */
5521 if (num > 32
5522 /* Reject a shift of 0 unless the mode allows it. */
5523 || (num == 0 && shift->properties->allows_0 == 0)
5524 /* Reject a shift of 32 unless the mode allows it. */
5525 || (num == 32 && shift->properties->allows_32 == 0)
5528 /* As a special case we allow a shift of zero for
5529 modes that do not support it to be recoded as an
5530 logical shift left of zero (ie nothing). We warn
5531 about this though. */
5532 if (num == 0)
5534 as_warn (_("shift of 0 ignored."));
5535 shift = & shift_names[0];
5536 assert (shift->properties->index == SHIFT_LSL);
5538 else
5540 inst.error = _("invalid immediate shift");
5541 return FAIL;
5545 /* Shifts of 32 are encoded as 0, for those shifts that
5546 support it. */
5547 if (num == 32)
5548 num = 0;
5550 inst.instruction |= (num << 7) | shift->properties->bit_field;
5552 else
5554 inst.reloc.type = BFD_RELOC_ARM_SHIFT_IMM;
5555 inst.reloc.pc_rel = 0;
5556 inst.instruction |= shift->properties->bit_field;
5559 * str = p;
5560 return SUCCESS;
5563 /* Do those data_ops which can take a negative immediate constant
5564 by altering the instuction. A bit of a hack really.
5565 MOV <-> MVN
5566 AND <-> BIC
5567 ADC <-> SBC
5568 by inverting the second operand, and
5569 ADD <-> SUB
5570 CMP <-> CMN
5571 by negating the second operand. */
5573 static int
5574 negate_data_op (instruction, value)
5575 unsigned long * instruction;
5576 unsigned long value;
5578 int op, new_inst;
5579 unsigned long negated, inverted;
5581 negated = validate_immediate (-value);
5582 inverted = validate_immediate (~value);
5584 op = (*instruction >> DATA_OP_SHIFT) & 0xf;
5585 switch (op)
5587 /* First negates. */
5588 case OPCODE_SUB: /* ADD <-> SUB */
5589 new_inst = OPCODE_ADD;
5590 value = negated;
5591 break;
5593 case OPCODE_ADD:
5594 new_inst = OPCODE_SUB;
5595 value = negated;
5596 break;
5598 case OPCODE_CMP: /* CMP <-> CMN */
5599 new_inst = OPCODE_CMN;
5600 value = negated;
5601 break;
5603 case OPCODE_CMN:
5604 new_inst = OPCODE_CMP;
5605 value = negated;
5606 break;
5608 /* Now Inverted ops. */
5609 case OPCODE_MOV: /* MOV <-> MVN */
5610 new_inst = OPCODE_MVN;
5611 value = inverted;
5612 break;
5614 case OPCODE_MVN:
5615 new_inst = OPCODE_MOV;
5616 value = inverted;
5617 break;
5619 case OPCODE_AND: /* AND <-> BIC */
5620 new_inst = OPCODE_BIC;
5621 value = inverted;
5622 break;
5624 case OPCODE_BIC:
5625 new_inst = OPCODE_AND;
5626 value = inverted;
5627 break;
5629 case OPCODE_ADC: /* ADC <-> SBC */
5630 new_inst = OPCODE_SBC;
5631 value = inverted;
5632 break;
5634 case OPCODE_SBC:
5635 new_inst = OPCODE_ADC;
5636 value = inverted;
5637 break;
5639 /* We cannot do anything. */
5640 default:
5641 return FAIL;
5644 if (value == (unsigned) FAIL)
5645 return FAIL;
5647 *instruction &= OPCODE_MASK;
5648 *instruction |= new_inst << DATA_OP_SHIFT;
5649 return value;
5652 static int
5653 data_op2 (str)
5654 char ** str;
5656 int value;
5657 expressionS expr;
5659 skip_whitespace (* str);
5661 if (reg_required_here (str, 0) != FAIL)
5663 if (skip_past_comma (str) == SUCCESS)
5664 /* Shift operation on register. */
5665 return decode_shift (str, NO_SHIFT_RESTRICT);
5667 return SUCCESS;
5669 else
5671 /* Immediate expression. */
5672 if (is_immediate_prefix (**str))
5674 (*str)++;
5675 inst.error = NULL;
5677 if (my_get_expression (&inst.reloc.exp, str))
5678 return FAIL;
5680 if (inst.reloc.exp.X_add_symbol)
5682 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
5683 inst.reloc.pc_rel = 0;
5685 else
5687 if (skip_past_comma (str) == SUCCESS)
5689 /* #x, y -- ie explicit rotation by Y. */
5690 if (my_get_expression (&expr, str))
5691 return FAIL;
5693 if (expr.X_op != O_constant)
5695 inst.error = _("constant expression expected");
5696 return FAIL;
5699 /* Rotate must be a multiple of 2. */
5700 if (((unsigned) expr.X_add_number) > 30
5701 || (expr.X_add_number & 1) != 0
5702 || ((unsigned) inst.reloc.exp.X_add_number) > 255)
5704 inst.error = _("invalid constant");
5705 return FAIL;
5707 inst.instruction |= INST_IMMEDIATE;
5708 inst.instruction |= inst.reloc.exp.X_add_number;
5709 inst.instruction |= expr.X_add_number << 7;
5710 return SUCCESS;
5713 /* Implicit rotation, select a suitable one. */
5714 value = validate_immediate (inst.reloc.exp.X_add_number);
5716 if (value == FAIL)
5718 /* Can't be done. Perhaps the code reads something like
5719 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
5720 if ((value = negate_data_op (&inst.instruction,
5721 inst.reloc.exp.X_add_number))
5722 == FAIL)
5724 inst.error = _("invalid constant");
5725 return FAIL;
5729 inst.instruction |= value;
5732 inst.instruction |= INST_IMMEDIATE;
5733 return SUCCESS;
5736 (*str)++;
5737 inst.error = _("register or shift expression expected");
5738 return FAIL;
5742 static int
5743 fp_op2 (str)
5744 char ** str;
5746 skip_whitespace (* str);
5748 if (fp_reg_required_here (str, 0) != FAIL)
5749 return SUCCESS;
5750 else
5752 /* Immediate expression. */
5753 if (*((*str)++) == '#')
5755 int i;
5757 inst.error = NULL;
5759 skip_whitespace (* str);
5761 /* First try and match exact strings, this is to guarantee
5762 that some formats will work even for cross assembly. */
5764 for (i = 0; fp_const[i]; i++)
5766 if (strncmp (*str, fp_const[i], strlen (fp_const[i])) == 0)
5768 char *start = *str;
5770 *str += strlen (fp_const[i]);
5771 if (is_end_of_line[(unsigned char) **str])
5773 inst.instruction |= i + 8;
5774 return SUCCESS;
5776 *str = start;
5780 /* Just because we didn't get a match doesn't mean that the
5781 constant isn't valid, just that it is in a format that we
5782 don't automatically recognize. Try parsing it with
5783 the standard expression routines. */
5784 if ((i = my_get_float_expression (str)) >= 0)
5786 inst.instruction |= i + 8;
5787 return SUCCESS;
5790 inst.error = _("invalid floating point immediate expression");
5791 return FAIL;
5793 inst.error =
5794 _("floating point register or immediate expression expected");
5795 return FAIL;
5799 static void
5800 do_arit (str)
5801 char * str;
5803 skip_whitespace (str);
5805 if (reg_required_here (&str, 12) == FAIL
5806 || skip_past_comma (&str) == FAIL
5807 || reg_required_here (&str, 16) == FAIL
5808 || skip_past_comma (&str) == FAIL
5809 || data_op2 (&str) == FAIL)
5811 if (!inst.error)
5812 inst.error = BAD_ARGS;
5813 return;
5816 end_of_line (str);
5817 return;
5820 static void
5821 do_adr (str)
5822 char * str;
5824 /* This is a pseudo-op of the form "adr rd, label" to be converted
5825 into a relative address of the form "add rd, pc, #label-.-8". */
5826 skip_whitespace (str);
5828 if (reg_required_here (&str, 12) == FAIL
5829 || skip_past_comma (&str) == FAIL
5830 || my_get_expression (&inst.reloc.exp, &str))
5832 if (!inst.error)
5833 inst.error = BAD_ARGS;
5834 return;
5837 /* Frag hacking will turn this into a sub instruction if the offset turns
5838 out to be negative. */
5839 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
5840 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust. */
5841 inst.reloc.pc_rel = 1;
5843 end_of_line (str);
5846 static void
5847 do_adrl (str)
5848 char * str;
5850 /* This is a pseudo-op of the form "adrl rd, label" to be converted
5851 into a relative address of the form:
5852 add rd, pc, #low(label-.-8)"
5853 add rd, rd, #high(label-.-8)" */
5855 skip_whitespace (str);
5857 if (reg_required_here (&str, 12) == FAIL
5858 || skip_past_comma (&str) == FAIL
5859 || my_get_expression (&inst.reloc.exp, &str))
5861 if (!inst.error)
5862 inst.error = BAD_ARGS;
5864 return;
5867 end_of_line (str);
5868 /* Frag hacking will turn this into a sub instruction if the offset turns
5869 out to be negative. */
5870 inst.reloc.type = BFD_RELOC_ARM_ADRL_IMMEDIATE;
5871 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust */
5872 inst.reloc.pc_rel = 1;
5873 inst.size = INSN_SIZE * 2;
5875 return;
5878 static void
5879 do_cmp (str)
5880 char * str;
5882 skip_whitespace (str);
5884 if (reg_required_here (&str, 16) == FAIL)
5886 if (!inst.error)
5887 inst.error = BAD_ARGS;
5888 return;
5891 if (skip_past_comma (&str) == FAIL
5892 || data_op2 (&str) == FAIL)
5894 if (!inst.error)
5895 inst.error = BAD_ARGS;
5896 return;
5899 end_of_line (str);
5900 return;
5903 static void
5904 do_mov (str)
5905 char * str;
5907 skip_whitespace (str);
5909 if (reg_required_here (&str, 12) == FAIL)
5911 if (!inst.error)
5912 inst.error = BAD_ARGS;
5913 return;
5916 if (skip_past_comma (&str) == FAIL
5917 || data_op2 (&str) == FAIL)
5919 if (!inst.error)
5920 inst.error = BAD_ARGS;
5921 return;
5924 end_of_line (str);
5925 return;
5928 static int
5929 ldst_extend (str)
5930 char ** str;
5932 int add = INDEX_UP;
5934 switch (**str)
5936 case '#':
5937 case '$':
5938 (*str)++;
5939 if (my_get_expression (& inst.reloc.exp, str))
5940 return FAIL;
5942 if (inst.reloc.exp.X_op == O_constant)
5944 int value = inst.reloc.exp.X_add_number;
5946 if (value < -4095 || value > 4095)
5948 inst.error = _("address offset too large");
5949 return FAIL;
5952 if (value < 0)
5954 value = -value;
5955 add = 0;
5958 inst.instruction |= add | value;
5960 else
5962 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
5963 inst.reloc.pc_rel = 0;
5965 return SUCCESS;
5967 case '-':
5968 add = 0;
5969 /* Fall through. */
5971 case '+':
5972 (*str)++;
5973 /* Fall through. */
5975 default:
5976 if (reg_required_here (str, 0) == FAIL)
5977 return FAIL;
5979 inst.instruction |= add | OFFSET_REG;
5980 if (skip_past_comma (str) == SUCCESS)
5981 return decode_shift (str, SHIFT_RESTRICT);
5983 return SUCCESS;
5987 static void
5988 do_ldst (str)
5989 char * str;
5991 int pre_inc = 0;
5992 int conflict_reg;
5993 int value;
5995 skip_whitespace (str);
5997 if ((conflict_reg = reg_required_here (&str, 12)) == FAIL)
5999 if (!inst.error)
6000 inst.error = BAD_ARGS;
6001 return;
6004 if (skip_past_comma (&str) == FAIL)
6006 inst.error = _("address expected");
6007 return;
6010 if (*str == '[')
6012 int reg;
6014 str++;
6016 skip_whitespace (str);
6018 if ((reg = reg_required_here (&str, 16)) == FAIL)
6019 return;
6021 /* Conflicts can occur on stores as well as loads. */
6022 conflict_reg = (conflict_reg == reg);
6024 skip_whitespace (str);
6026 if (*str == ']')
6028 str ++;
6030 if (skip_past_comma (&str) == SUCCESS)
6032 /* [Rn],... (post inc) */
6033 if (ldst_extend (&str) == FAIL)
6034 return;
6035 if (conflict_reg)
6036 as_warn (_("%s register same as write-back base"),
6037 ((inst.instruction & LOAD_BIT)
6038 ? _("destination") : _("source")));
6040 else
6042 /* [Rn] */
6043 skip_whitespace (str);
6045 if (*str == '!')
6047 if (conflict_reg)
6048 as_warn (_("%s register same as write-back base"),
6049 ((inst.instruction & LOAD_BIT)
6050 ? _("destination") : _("source")));
6051 str++;
6052 inst.instruction |= WRITE_BACK;
6055 inst.instruction |= INDEX_UP;
6056 pre_inc = 1;
6059 else
6061 /* [Rn,...] */
6062 if (skip_past_comma (&str) == FAIL)
6064 inst.error = _("pre-indexed expression expected");
6065 return;
6068 pre_inc = 1;
6069 if (ldst_extend (&str) == FAIL)
6070 return;
6072 skip_whitespace (str);
6074 if (*str++ != ']')
6076 inst.error = _("missing ]");
6077 return;
6080 skip_whitespace (str);
6082 if (*str == '!')
6084 if (conflict_reg)
6085 as_warn (_("%s register same as write-back base"),
6086 ((inst.instruction & LOAD_BIT)
6087 ? _("destination") : _("source")));
6088 str++;
6089 inst.instruction |= WRITE_BACK;
6093 else if (*str == '=')
6095 if ((inst.instruction & LOAD_BIT) == 0)
6097 inst.error = _("invalid pseudo operation");
6098 return;
6101 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6102 str++;
6104 skip_whitespace (str);
6106 if (my_get_expression (&inst.reloc.exp, &str))
6107 return;
6109 if (inst.reloc.exp.X_op != O_constant
6110 && inst.reloc.exp.X_op != O_symbol)
6112 inst.error = _("constant expression expected");
6113 return;
6116 if (inst.reloc.exp.X_op == O_constant)
6118 value = validate_immediate (inst.reloc.exp.X_add_number);
6120 if (value != FAIL)
6122 /* This can be done with a mov instruction. */
6123 inst.instruction &= LITERAL_MASK;
6124 inst.instruction |= (INST_IMMEDIATE
6125 | (OPCODE_MOV << DATA_OP_SHIFT));
6126 inst.instruction |= value & 0xfff;
6127 end_of_line (str);
6128 return;
6131 value = validate_immediate (~inst.reloc.exp.X_add_number);
6133 if (value != FAIL)
6135 /* This can be done with a mvn instruction. */
6136 inst.instruction &= LITERAL_MASK;
6137 inst.instruction |= (INST_IMMEDIATE
6138 | (OPCODE_MVN << DATA_OP_SHIFT));
6139 inst.instruction |= value & 0xfff;
6140 end_of_line (str);
6141 return;
6145 /* Insert into literal pool. */
6146 if (add_to_lit_pool () == FAIL)
6148 if (!inst.error)
6149 inst.error = _("literal pool insertion failed");
6150 return;
6153 /* Change the instruction exp to point to the pool. */
6154 inst.reloc.type = BFD_RELOC_ARM_LITERAL;
6155 inst.reloc.pc_rel = 1;
6156 inst.instruction |= (REG_PC << 16);
6157 pre_inc = 1;
6159 else
6161 if (my_get_expression (&inst.reloc.exp, &str))
6162 return;
6164 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
6165 #ifndef TE_WINCE
6166 /* PC rel adjust. */
6167 inst.reloc.exp.X_add_number -= 8;
6168 #endif
6169 inst.reloc.pc_rel = 1;
6170 inst.instruction |= (REG_PC << 16);
6171 pre_inc = 1;
6174 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
6175 end_of_line (str);
6176 return;
6179 static void
6180 do_ldstt (str)
6181 char * str;
6183 int conflict_reg;
6185 skip_whitespace (str);
6187 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
6189 if (!inst.error)
6190 inst.error = BAD_ARGS;
6191 return;
6194 if (skip_past_comma (& str) == FAIL)
6196 inst.error = _("address expected");
6197 return;
6200 if (*str == '[')
6202 int reg;
6204 str++;
6206 skip_whitespace (str);
6208 if ((reg = reg_required_here (&str, 16)) == FAIL)
6209 return;
6211 /* ldrt/strt always use post-indexed addressing, so if the base is
6212 the same as Rd, we warn. */
6213 if (conflict_reg == reg)
6214 as_warn (_("%s register same as write-back base"),
6215 ((inst.instruction & LOAD_BIT)
6216 ? _("destination") : _("source")));
6218 skip_whitespace (str);
6220 if (*str == ']')
6222 str ++;
6224 if (skip_past_comma (&str) == SUCCESS)
6226 /* [Rn],... (post inc) */
6227 if (ldst_extend (&str) == FAIL)
6228 return;
6230 else
6232 /* [Rn] */
6233 skip_whitespace (str);
6235 /* Skip a write-back '!'. */
6236 if (*str == '!')
6237 str++;
6239 inst.instruction |= INDEX_UP;
6242 else
6244 inst.error = _("post-indexed expression expected");
6245 return;
6248 else
6250 inst.error = _("post-indexed expression expected");
6251 return;
6254 end_of_line (str);
6255 return;
6258 static int
6259 ldst_extend_v4 (str)
6260 char ** str;
6262 int add = INDEX_UP;
6264 switch (**str)
6266 case '#':
6267 case '$':
6268 (*str)++;
6269 if (my_get_expression (& inst.reloc.exp, str))
6270 return FAIL;
6272 if (inst.reloc.exp.X_op == O_constant)
6274 int value = inst.reloc.exp.X_add_number;
6276 if (value < -255 || value > 255)
6278 inst.error = _("address offset too large");
6279 return FAIL;
6282 if (value < 0)
6284 value = -value;
6285 add = 0;
6288 /* Halfword and signextension instructions have the
6289 immediate value split across bits 11..8 and bits 3..0. */
6290 inst.instruction |= (add | HWOFFSET_IMM
6291 | ((value >> 4) << 8) | (value & 0xF));
6293 else
6295 inst.instruction |= HWOFFSET_IMM;
6296 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
6297 inst.reloc.pc_rel = 0;
6299 return SUCCESS;
6301 case '-':
6302 add = 0;
6303 /* Fall through. */
6305 case '+':
6306 (*str)++;
6307 /* Fall through. */
6309 default:
6310 if (reg_required_here (str, 0) == FAIL)
6311 return FAIL;
6313 inst.instruction |= add;
6314 return SUCCESS;
6318 /* Halfword and signed-byte load/store operations. */
6319 static void
6320 do_ldstv4 (str)
6321 char * str;
6323 int pre_inc = 0;
6324 int conflict_reg;
6325 int value;
6327 skip_whitespace (str);
6329 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
6331 if (!inst.error)
6332 inst.error = BAD_ARGS;
6333 return;
6336 if (skip_past_comma (& str) == FAIL)
6338 inst.error = _("address expected");
6339 return;
6342 if (*str == '[')
6344 int reg;
6346 str++;
6348 skip_whitespace (str);
6350 if ((reg = reg_required_here (&str, 16)) == FAIL)
6351 return;
6353 /* Conflicts can occur on stores as well as loads. */
6354 conflict_reg = (conflict_reg == reg);
6356 skip_whitespace (str);
6358 if (*str == ']')
6360 str ++;
6362 if (skip_past_comma (&str) == SUCCESS)
6364 /* [Rn],... (post inc) */
6365 if (ldst_extend_v4 (&str) == FAIL)
6366 return;
6367 if (conflict_reg)
6368 as_warn (_("%s register same as write-back base"),
6369 ((inst.instruction & LOAD_BIT)
6370 ? _("destination") : _("source")));
6372 else
6374 /* [Rn] */
6375 inst.instruction |= HWOFFSET_IMM;
6377 skip_whitespace (str);
6379 if (*str == '!')
6381 if (conflict_reg)
6382 as_warn (_("%s register same as write-back base"),
6383 ((inst.instruction & LOAD_BIT)
6384 ? _("destination") : _("source")));
6385 str++;
6386 inst.instruction |= WRITE_BACK;
6389 inst.instruction |= INDEX_UP;
6390 pre_inc = 1;
6393 else
6395 /* [Rn,...] */
6396 if (skip_past_comma (&str) == FAIL)
6398 inst.error = _("pre-indexed expression expected");
6399 return;
6402 pre_inc = 1;
6403 if (ldst_extend_v4 (&str) == FAIL)
6404 return;
6406 skip_whitespace (str);
6408 if (*str++ != ']')
6410 inst.error = _("missing ]");
6411 return;
6414 skip_whitespace (str);
6416 if (*str == '!')
6418 if (conflict_reg)
6419 as_warn (_("%s register same as write-back base"),
6420 ((inst.instruction & LOAD_BIT)
6421 ? _("destination") : _("source")));
6422 str++;
6423 inst.instruction |= WRITE_BACK;
6427 else if (*str == '=')
6429 if ((inst.instruction & LOAD_BIT) == 0)
6431 inst.error = _("invalid pseudo operation");
6432 return;
6435 /* XXX Does this work correctly for half-word/byte ops? */
6436 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6437 str++;
6439 skip_whitespace (str);
6441 if (my_get_expression (&inst.reloc.exp, &str))
6442 return;
6444 if (inst.reloc.exp.X_op != O_constant
6445 && inst.reloc.exp.X_op != O_symbol)
6447 inst.error = _("constant expression expected");
6448 return;
6451 if (inst.reloc.exp.X_op == O_constant)
6453 value = validate_immediate (inst.reloc.exp.X_add_number);
6455 if (value != FAIL)
6457 /* This can be done with a mov instruction. */
6458 inst.instruction &= LITERAL_MASK;
6459 inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
6460 inst.instruction |= value & 0xfff;
6461 end_of_line (str);
6462 return;
6465 value = validate_immediate (~ inst.reloc.exp.X_add_number);
6467 if (value != FAIL)
6469 /* This can be done with a mvn instruction. */
6470 inst.instruction &= LITERAL_MASK;
6471 inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT);
6472 inst.instruction |= value & 0xfff;
6473 end_of_line (str);
6474 return;
6478 /* Insert into literal pool. */
6479 if (add_to_lit_pool () == FAIL)
6481 if (!inst.error)
6482 inst.error = _("literal pool insertion failed");
6483 return;
6486 /* Change the instruction exp to point to the pool. */
6487 inst.instruction |= HWOFFSET_IMM;
6488 inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
6489 inst.reloc.pc_rel = 1;
6490 inst.instruction |= (REG_PC << 16);
6491 pre_inc = 1;
6493 else
6495 if (my_get_expression (&inst.reloc.exp, &str))
6496 return;
6498 inst.instruction |= HWOFFSET_IMM;
6499 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
6500 #ifndef TE_WINCE
6501 /* PC rel adjust. */
6502 inst.reloc.exp.X_add_number -= 8;
6503 #endif
6504 inst.reloc.pc_rel = 1;
6505 inst.instruction |= (REG_PC << 16);
6506 pre_inc = 1;
6509 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
6510 end_of_line (str);
6511 return;
6514 static long
6515 reg_list (strp)
6516 char ** strp;
6518 char * str = * strp;
6519 long range = 0;
6520 int another_range;
6522 /* We come back here if we get ranges concatenated by '+' or '|'. */
6525 another_range = 0;
6527 if (*str == '{')
6529 int in_range = 0;
6530 int cur_reg = -1;
6532 str++;
6535 int reg;
6537 skip_whitespace (str);
6539 if ((reg = reg_required_here (& str, -1)) == FAIL)
6540 return FAIL;
6542 if (in_range)
6544 int i;
6546 if (reg <= cur_reg)
6548 inst.error = _("bad range in register list");
6549 return FAIL;
6552 for (i = cur_reg + 1; i < reg; i++)
6554 if (range & (1 << i))
6555 as_tsktsk
6556 (_("Warning: duplicated register (r%d) in register list"),
6558 else
6559 range |= 1 << i;
6561 in_range = 0;
6564 if (range & (1 << reg))
6565 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
6566 reg);
6567 else if (reg <= cur_reg)
6568 as_tsktsk (_("Warning: register range not in ascending order"));
6570 range |= 1 << reg;
6571 cur_reg = reg;
6573 while (skip_past_comma (&str) != FAIL
6574 || (in_range = 1, *str++ == '-'));
6575 str--;
6576 skip_whitespace (str);
6578 if (*str++ != '}')
6580 inst.error = _("missing `}'");
6581 return FAIL;
6584 else
6586 expressionS expr;
6588 if (my_get_expression (&expr, &str))
6589 return FAIL;
6591 if (expr.X_op == O_constant)
6593 if (expr.X_add_number
6594 != (expr.X_add_number & 0x0000ffff))
6596 inst.error = _("invalid register mask");
6597 return FAIL;
6600 if ((range & expr.X_add_number) != 0)
6602 int regno = range & expr.X_add_number;
6604 regno &= -regno;
6605 regno = (1 << regno) - 1;
6606 as_tsktsk
6607 (_("Warning: duplicated register (r%d) in register list"),
6608 regno);
6611 range |= expr.X_add_number;
6613 else
6615 if (inst.reloc.type != 0)
6617 inst.error = _("expression too complex");
6618 return FAIL;
6621 memcpy (&inst.reloc.exp, &expr, sizeof (expressionS));
6622 inst.reloc.type = BFD_RELOC_ARM_MULTI;
6623 inst.reloc.pc_rel = 0;
6627 skip_whitespace (str);
6629 if (*str == '|' || *str == '+')
6631 str++;
6632 another_range = 1;
6635 while (another_range);
6637 *strp = str;
6638 return range;
6641 static void
6642 do_ldmstm (str)
6643 char * str;
6645 int base_reg;
6646 long range;
6648 skip_whitespace (str);
6650 if ((base_reg = reg_required_here (&str, 16)) == FAIL)
6651 return;
6653 if (base_reg == REG_PC)
6655 inst.error = _("r15 not allowed as base register");
6656 return;
6659 skip_whitespace (str);
6661 if (*str == '!')
6663 inst.instruction |= WRITE_BACK;
6664 str++;
6667 if (skip_past_comma (&str) == FAIL
6668 || (range = reg_list (&str)) == FAIL)
6670 if (! inst.error)
6671 inst.error = BAD_ARGS;
6672 return;
6675 if (*str == '^')
6677 str++;
6678 inst.instruction |= LDM_TYPE_2_OR_3;
6681 if (inst.instruction & WRITE_BACK)
6683 /* Check for unpredictable uses of writeback. */
6684 if (inst.instruction & LOAD_BIT)
6686 /* Not allowed in LDM type 2. */
6687 if ((inst.instruction & LDM_TYPE_2_OR_3)
6688 && ((range & (1 << REG_PC)) == 0))
6689 as_warn (_("writeback of base register is UNPREDICTABLE"));
6690 /* Only allowed if base reg not in list for other types. */
6691 else if (range & (1 << base_reg))
6692 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
6694 else /* STM. */
6696 /* Not allowed for type 2. */
6697 if (inst.instruction & LDM_TYPE_2_OR_3)
6698 as_warn (_("writeback of base register is UNPREDICTABLE"));
6699 /* Only allowed if base reg not in list, or first in list. */
6700 else if ((range & (1 << base_reg))
6701 && (range & ((1 << base_reg) - 1)))
6702 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
6706 inst.instruction |= range;
6707 end_of_line (str);
6708 return;
6711 static void
6712 do_swi (str)
6713 char * str;
6715 skip_whitespace (str);
6717 /* Allow optional leading '#'. */
6718 if (is_immediate_prefix (*str))
6719 str++;
6721 if (my_get_expression (& inst.reloc.exp, & str))
6722 return;
6724 inst.reloc.type = BFD_RELOC_ARM_SWI;
6725 inst.reloc.pc_rel = 0;
6726 end_of_line (str);
6728 return;
6731 static void
6732 do_swap (str)
6733 char * str;
6735 int reg;
6737 skip_whitespace (str);
6739 if ((reg = reg_required_here (&str, 12)) == FAIL)
6740 return;
6742 if (reg == REG_PC)
6744 inst.error = _("r15 not allowed in swap");
6745 return;
6748 if (skip_past_comma (&str) == FAIL
6749 || (reg = reg_required_here (&str, 0)) == FAIL)
6751 if (!inst.error)
6752 inst.error = BAD_ARGS;
6753 return;
6756 if (reg == REG_PC)
6758 inst.error = _("r15 not allowed in swap");
6759 return;
6762 if (skip_past_comma (&str) == FAIL
6763 || *str++ != '[')
6765 inst.error = BAD_ARGS;
6766 return;
6769 skip_whitespace (str);
6771 if ((reg = reg_required_here (&str, 16)) == FAIL)
6772 return;
6774 if (reg == REG_PC)
6776 inst.error = BAD_PC;
6777 return;
6780 skip_whitespace (str);
6782 if (*str++ != ']')
6784 inst.error = _("missing ]");
6785 return;
6788 end_of_line (str);
6789 return;
6792 static void
6793 do_branch (str)
6794 char * str;
6796 if (my_get_expression (&inst.reloc.exp, &str))
6797 return;
6799 #ifdef OBJ_ELF
6801 char * save_in;
6803 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
6804 required for the instruction. */
6806 /* arm_parse_reloc () works on input_line_pointer.
6807 We actually want to parse the operands to the branch instruction
6808 passed in 'str'. Save the input pointer and restore it later. */
6809 save_in = input_line_pointer;
6810 input_line_pointer = str;
6811 if (inst.reloc.exp.X_op == O_symbol
6812 && *str == '('
6813 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
6815 inst.reloc.type = BFD_RELOC_ARM_PLT32;
6816 inst.reloc.pc_rel = 0;
6817 /* Modify str to point to after parsed operands, otherwise
6818 end_of_line() will complain about the (PLT) left in str. */
6819 str = input_line_pointer;
6821 else
6823 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
6824 inst.reloc.pc_rel = 1;
6826 input_line_pointer = save_in;
6828 #else
6829 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
6830 inst.reloc.pc_rel = 1;
6831 #endif /* OBJ_ELF */
6833 end_of_line (str);
6834 return;
6837 static void
6838 do_bx (str)
6839 char * str;
6841 int reg;
6843 skip_whitespace (str);
6845 if ((reg = reg_required_here (&str, 0)) == FAIL)
6847 inst.error = BAD_ARGS;
6848 return;
6851 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
6852 if (reg == REG_PC)
6853 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
6855 end_of_line (str);
6858 static void
6859 do_cdp (str)
6860 char * str;
6862 /* Co-processor data operation.
6863 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
6864 skip_whitespace (str);
6866 if (co_proc_number (&str) == FAIL)
6868 if (!inst.error)
6869 inst.error = BAD_ARGS;
6870 return;
6873 if (skip_past_comma (&str) == FAIL
6874 || cp_opc_expr (&str, 20,4) == FAIL)
6876 if (!inst.error)
6877 inst.error = BAD_ARGS;
6878 return;
6881 if (skip_past_comma (&str) == FAIL
6882 || cp_reg_required_here (&str, 12) == FAIL)
6884 if (!inst.error)
6885 inst.error = BAD_ARGS;
6886 return;
6889 if (skip_past_comma (&str) == FAIL
6890 || cp_reg_required_here (&str, 16) == FAIL)
6892 if (!inst.error)
6893 inst.error = BAD_ARGS;
6894 return;
6897 if (skip_past_comma (&str) == FAIL
6898 || cp_reg_required_here (&str, 0) == FAIL)
6900 if (!inst.error)
6901 inst.error = BAD_ARGS;
6902 return;
6905 if (skip_past_comma (&str) == SUCCESS)
6907 if (cp_opc_expr (&str, 5, 3) == FAIL)
6909 if (!inst.error)
6910 inst.error = BAD_ARGS;
6911 return;
6915 end_of_line (str);
6916 return;
6919 static void
6920 do_lstc (str)
6921 char * str;
6923 /* Co-processor register load/store.
6924 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
6926 skip_whitespace (str);
6928 if (co_proc_number (&str) == FAIL)
6930 if (!inst.error)
6931 inst.error = BAD_ARGS;
6932 return;
6935 if (skip_past_comma (&str) == FAIL
6936 || cp_reg_required_here (&str, 12) == FAIL)
6938 if (!inst.error)
6939 inst.error = BAD_ARGS;
6940 return;
6943 if (skip_past_comma (&str) == FAIL
6944 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
6946 if (! inst.error)
6947 inst.error = BAD_ARGS;
6948 return;
6951 end_of_line (str);
6952 return;
6955 static void
6956 do_co_reg (str)
6957 char * str;
6959 /* Co-processor register transfer.
6960 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
6962 skip_whitespace (str);
6964 if (co_proc_number (&str) == FAIL)
6966 if (!inst.error)
6967 inst.error = BAD_ARGS;
6968 return;
6971 if (skip_past_comma (&str) == FAIL
6972 || cp_opc_expr (&str, 21, 3) == FAIL)
6974 if (!inst.error)
6975 inst.error = BAD_ARGS;
6976 return;
6979 if (skip_past_comma (&str) == FAIL
6980 || reg_required_here (&str, 12) == FAIL)
6982 if (!inst.error)
6983 inst.error = BAD_ARGS;
6984 return;
6987 if (skip_past_comma (&str) == FAIL
6988 || cp_reg_required_here (&str, 16) == FAIL)
6990 if (!inst.error)
6991 inst.error = BAD_ARGS;
6992 return;
6995 if (skip_past_comma (&str) == FAIL
6996 || cp_reg_required_here (&str, 0) == FAIL)
6998 if (!inst.error)
6999 inst.error = BAD_ARGS;
7000 return;
7003 if (skip_past_comma (&str) == SUCCESS)
7005 if (cp_opc_expr (&str, 5, 3) == FAIL)
7007 if (!inst.error)
7008 inst.error = BAD_ARGS;
7009 return;
7013 end_of_line (str);
7014 return;
7017 static void
7018 do_fpa_ctrl (str)
7019 char * str;
7021 /* FP control registers.
7022 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
7024 skip_whitespace (str);
7026 if (reg_required_here (&str, 12) == FAIL)
7028 if (!inst.error)
7029 inst.error = BAD_ARGS;
7030 return;
7033 end_of_line (str);
7034 return;
7037 static void
7038 do_fpa_ldst (str)
7039 char * str;
7041 skip_whitespace (str);
7043 if (fp_reg_required_here (&str, 12) == FAIL)
7045 if (!inst.error)
7046 inst.error = BAD_ARGS;
7047 return;
7050 if (skip_past_comma (&str) == FAIL
7051 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
7053 if (!inst.error)
7054 inst.error = BAD_ARGS;
7055 return;
7058 end_of_line (str);
7061 static void
7062 do_fpa_ldmstm (str)
7063 char * str;
7065 int num_regs;
7067 skip_whitespace (str);
7069 if (fp_reg_required_here (&str, 12) == FAIL)
7071 if (! inst.error)
7072 inst.error = BAD_ARGS;
7073 return;
7076 /* Get Number of registers to transfer. */
7077 if (skip_past_comma (&str) == FAIL
7078 || my_get_expression (&inst.reloc.exp, &str))
7080 if (! inst.error)
7081 inst.error = _("constant expression expected");
7082 return;
7085 if (inst.reloc.exp.X_op != O_constant)
7087 inst.error = _("constant value required for number of registers");
7088 return;
7091 num_regs = inst.reloc.exp.X_add_number;
7093 if (num_regs < 1 || num_regs > 4)
7095 inst.error = _("number of registers must be in the range [1:4]");
7096 return;
7099 switch (num_regs)
7101 case 1:
7102 inst.instruction |= CP_T_X;
7103 break;
7104 case 2:
7105 inst.instruction |= CP_T_Y;
7106 break;
7107 case 3:
7108 inst.instruction |= CP_T_Y | CP_T_X;
7109 break;
7110 case 4:
7111 break;
7112 default:
7113 abort ();
7116 if (inst.instruction & (CP_T_Pre | CP_T_UD)) /* ea/fd format. */
7118 int reg;
7119 int write_back;
7120 int offset;
7122 /* The instruction specified "ea" or "fd", so we can only accept
7123 [Rn]{!}. The instruction does not really support stacking or
7124 unstacking, so we have to emulate these by setting appropriate
7125 bits and offsets. */
7126 if (skip_past_comma (&str) == FAIL
7127 || *str != '[')
7129 if (! inst.error)
7130 inst.error = BAD_ARGS;
7131 return;
7134 str++;
7135 skip_whitespace (str);
7137 if ((reg = reg_required_here (&str, 16)) == FAIL)
7138 return;
7140 skip_whitespace (str);
7142 if (*str != ']')
7144 inst.error = BAD_ARGS;
7145 return;
7148 str++;
7149 if (*str == '!')
7151 write_back = 1;
7152 str++;
7153 if (reg == REG_PC)
7155 inst.error =
7156 _("r15 not allowed as base register with write-back");
7157 return;
7160 else
7161 write_back = 0;
7163 if (inst.instruction & CP_T_Pre)
7165 /* Pre-decrement. */
7166 offset = 3 * num_regs;
7167 if (write_back)
7168 inst.instruction |= CP_T_WB;
7170 else
7172 /* Post-increment. */
7173 if (write_back)
7175 inst.instruction |= CP_T_WB;
7176 offset = 3 * num_regs;
7178 else
7180 /* No write-back, so convert this into a standard pre-increment
7181 instruction -- aesthetically more pleasing. */
7182 inst.instruction |= CP_T_Pre | CP_T_UD;
7183 offset = 0;
7187 inst.instruction |= offset;
7189 else if (skip_past_comma (&str) == FAIL
7190 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
7192 if (! inst.error)
7193 inst.error = BAD_ARGS;
7194 return;
7197 end_of_line (str);
7200 static void
7201 do_fpa_dyadic (str)
7202 char * str;
7204 skip_whitespace (str);
7206 if (fp_reg_required_here (&str, 12) == FAIL)
7208 if (! inst.error)
7209 inst.error = BAD_ARGS;
7210 return;
7213 if (skip_past_comma (&str) == FAIL
7214 || fp_reg_required_here (&str, 16) == FAIL)
7216 if (! inst.error)
7217 inst.error = BAD_ARGS;
7218 return;
7221 if (skip_past_comma (&str) == FAIL
7222 || fp_op2 (&str) == FAIL)
7224 if (! inst.error)
7225 inst.error = BAD_ARGS;
7226 return;
7229 end_of_line (str);
7230 return;
7233 static void
7234 do_fpa_monadic (str)
7235 char * str;
7237 skip_whitespace (str);
7239 if (fp_reg_required_here (&str, 12) == FAIL)
7241 if (! inst.error)
7242 inst.error = BAD_ARGS;
7243 return;
7246 if (skip_past_comma (&str) == FAIL
7247 || fp_op2 (&str) == FAIL)
7249 if (! inst.error)
7250 inst.error = BAD_ARGS;
7251 return;
7254 end_of_line (str);
7255 return;
7258 static void
7259 do_fpa_cmp (str)
7260 char * str;
7262 skip_whitespace (str);
7264 if (fp_reg_required_here (&str, 16) == FAIL)
7266 if (! inst.error)
7267 inst.error = BAD_ARGS;
7268 return;
7271 if (skip_past_comma (&str) == FAIL
7272 || fp_op2 (&str) == FAIL)
7274 if (! inst.error)
7275 inst.error = BAD_ARGS;
7276 return;
7279 end_of_line (str);
7280 return;
7283 static void
7284 do_fpa_from_reg (str)
7285 char * str;
7287 skip_whitespace (str);
7289 if (fp_reg_required_here (&str, 16) == FAIL)
7291 if (! inst.error)
7292 inst.error = BAD_ARGS;
7293 return;
7296 if (skip_past_comma (&str) == FAIL
7297 || reg_required_here (&str, 12) == FAIL)
7299 if (! inst.error)
7300 inst.error = BAD_ARGS;
7301 return;
7304 end_of_line (str);
7305 return;
7308 static void
7309 do_fpa_to_reg (str)
7310 char * str;
7312 skip_whitespace (str);
7314 if (reg_required_here (&str, 12) == FAIL)
7315 return;
7317 if (skip_past_comma (&str) == FAIL
7318 || fp_reg_required_here (&str, 0) == FAIL)
7320 if (! inst.error)
7321 inst.error = BAD_ARGS;
7322 return;
7325 end_of_line (str);
7326 return;
7329 static int
7330 vfp_sp_reg_required_here (str, pos)
7331 char **str;
7332 enum vfp_sp_reg_pos pos;
7334 int reg;
7335 char *start = *str;
7337 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab)) != FAIL)
7339 switch (pos)
7341 case VFP_REG_Sd:
7342 inst.instruction |= ((reg >> 1) << 12) | ((reg & 1) << 22);
7343 break;
7345 case VFP_REG_Sn:
7346 inst.instruction |= ((reg >> 1) << 16) | ((reg & 1) << 7);
7347 break;
7349 case VFP_REG_Sm:
7350 inst.instruction |= ((reg >> 1) << 0) | ((reg & 1) << 5);
7351 break;
7353 default:
7354 abort ();
7356 return reg;
7359 /* In the few cases where we might be able to accept something else
7360 this error can be overridden. */
7361 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
7363 /* Restore the start point. */
7364 *str = start;
7365 return FAIL;
7368 static int
7369 vfp_dp_reg_required_here (str, pos)
7370 char **str;
7371 enum vfp_dp_reg_pos pos;
7373 int reg;
7374 char *start = *str;
7376 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab)) != FAIL)
7378 switch (pos)
7380 case VFP_REG_Dd:
7381 inst.instruction |= reg << 12;
7382 break;
7384 case VFP_REG_Dn:
7385 inst.instruction |= reg << 16;
7386 break;
7388 case VFP_REG_Dm:
7389 inst.instruction |= reg << 0;
7390 break;
7392 default:
7393 abort ();
7395 return reg;
7398 /* In the few cases where we might be able to accept something else
7399 this error can be overridden. */
7400 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
7402 /* Restore the start point. */
7403 *str = start;
7404 return FAIL;
7407 static void
7408 do_vfp_sp_monadic (str)
7409 char *str;
7411 skip_whitespace (str);
7413 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7414 return;
7416 if (skip_past_comma (&str) == FAIL
7417 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
7419 if (! inst.error)
7420 inst.error = BAD_ARGS;
7421 return;
7424 end_of_line (str);
7425 return;
7428 static void
7429 do_vfp_dp_monadic (str)
7430 char *str;
7432 skip_whitespace (str);
7434 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7435 return;
7437 if (skip_past_comma (&str) == FAIL
7438 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7440 if (! inst.error)
7441 inst.error = BAD_ARGS;
7442 return;
7445 end_of_line (str);
7446 return;
7449 static void
7450 do_vfp_sp_dyadic (str)
7451 char *str;
7453 skip_whitespace (str);
7455 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7456 return;
7458 if (skip_past_comma (&str) == FAIL
7459 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL
7460 || skip_past_comma (&str) == FAIL
7461 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
7463 if (! inst.error)
7464 inst.error = BAD_ARGS;
7465 return;
7468 end_of_line (str);
7469 return;
7472 static void
7473 do_vfp_dp_dyadic (str)
7474 char *str;
7476 skip_whitespace (str);
7478 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7479 return;
7481 if (skip_past_comma (&str) == FAIL
7482 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL
7483 || skip_past_comma (&str) == FAIL
7484 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7486 if (! inst.error)
7487 inst.error = BAD_ARGS;
7488 return;
7491 end_of_line (str);
7492 return;
7495 static void
7496 do_vfp_reg_from_sp (str)
7497 char *str;
7499 skip_whitespace (str);
7501 if (reg_required_here (&str, 12) == FAIL)
7502 return;
7504 if (skip_past_comma (&str) == FAIL
7505 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
7507 if (! inst.error)
7508 inst.error = BAD_ARGS;
7509 return;
7512 end_of_line (str);
7513 return;
7516 static void
7517 do_vfp_sp_reg2 (str)
7518 char *str;
7520 skip_whitespace (str);
7522 if (reg_required_here (&str, 12) == FAIL)
7523 return;
7525 if (skip_past_comma (&str) == FAIL
7526 || reg_required_here (&str, 16) == FAIL
7527 || skip_past_comma (&str) == FAIL)
7529 if (! inst.error)
7530 inst.error = BAD_ARGS;
7531 return;
7534 /* We require exactly two consecutive SP registers. */
7535 if (vfp_sp_reg_list (&str, VFP_REG_Sm) != 2)
7537 if (! inst.error)
7538 inst.error = _("only two consecutive VFP SP registers allowed here");
7541 end_of_line (str);
7542 return;
7545 static void
7546 do_vfp_sp_from_reg (str)
7547 char *str;
7549 skip_whitespace (str);
7551 if (vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
7552 return;
7554 if (skip_past_comma (&str) == FAIL
7555 || reg_required_here (&str, 12) == FAIL)
7557 if (! inst.error)
7558 inst.error = BAD_ARGS;
7559 return;
7562 end_of_line (str);
7563 return;
7566 static void
7567 do_vfp_reg_from_dp (str)
7568 char *str;
7570 skip_whitespace (str);
7572 if (reg_required_here (&str, 12) == FAIL)
7573 return;
7575 if (skip_past_comma (&str) == FAIL
7576 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
7578 if (! inst.error)
7579 inst.error = BAD_ARGS;
7580 return;
7583 end_of_line (str);
7584 return;
7587 static void
7588 do_vfp_reg2_from_dp (str)
7589 char *str;
7591 skip_whitespace (str);
7593 if (reg_required_here (&str, 12) == FAIL)
7594 return;
7596 if (skip_past_comma (&str) == FAIL
7597 || reg_required_here (&str, 16) == FAIL
7598 || skip_past_comma (&str) == FAIL
7599 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7601 if (! inst.error)
7602 inst.error = BAD_ARGS;
7603 return;
7606 end_of_line (str);
7607 return;
7610 static void
7611 do_vfp_dp_from_reg (str)
7612 char *str;
7614 skip_whitespace (str);
7616 if (vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
7617 return;
7619 if (skip_past_comma (&str) == FAIL
7620 || reg_required_here (&str, 12) == FAIL)
7622 if (! inst.error)
7623 inst.error = BAD_ARGS;
7624 return;
7627 end_of_line (str);
7628 return;
7631 static void
7632 do_vfp_dp_from_reg2 (str)
7633 char *str;
7635 skip_whitespace (str);
7637 if (vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7638 return;
7640 if (skip_past_comma (&str) == FAIL
7641 || reg_required_here (&str, 12) == FAIL
7642 || skip_past_comma (&str) == FAIL
7643 || reg_required_here (&str, 16))
7645 if (! inst.error)
7646 inst.error = BAD_ARGS;
7647 return;
7650 end_of_line (str);
7651 return;
7654 static const struct vfp_reg *
7655 vfp_psr_parse (str)
7656 char **str;
7658 char *start = *str;
7659 char c;
7660 char *p;
7661 const struct vfp_reg *vreg;
7663 p = start;
7665 /* Find the end of the current token. */
7668 c = *p++;
7670 while (ISALPHA (c));
7672 /* Mark it. */
7673 *--p = 0;
7675 for (vreg = vfp_regs + 0;
7676 vreg < vfp_regs + sizeof (vfp_regs) / sizeof (struct vfp_reg);
7677 vreg++)
7679 if (strcmp (start, vreg->name) == 0)
7681 *p = c;
7682 *str = p;
7683 return vreg;
7687 *p = c;
7688 return NULL;
7691 static int
7692 vfp_psr_required_here (str)
7693 char **str;
7695 char *start = *str;
7696 const struct vfp_reg *vreg;
7698 vreg = vfp_psr_parse (str);
7700 if (vreg)
7702 inst.instruction |= vreg->regno;
7703 return SUCCESS;
7706 inst.error = _("VFP system register expected");
7708 *str = start;
7709 return FAIL;
7712 static void
7713 do_vfp_reg_from_ctrl (str)
7714 char *str;
7716 skip_whitespace (str);
7718 if (reg_required_here (&str, 12) == FAIL)
7719 return;
7721 if (skip_past_comma (&str) == FAIL
7722 || vfp_psr_required_here (&str) == FAIL)
7724 if (! inst.error)
7725 inst.error = BAD_ARGS;
7726 return;
7729 end_of_line (str);
7730 return;
7733 static void
7734 do_vfp_ctrl_from_reg (str)
7735 char *str;
7737 skip_whitespace (str);
7739 if (vfp_psr_required_here (&str) == FAIL)
7740 return;
7742 if (skip_past_comma (&str) == FAIL
7743 || reg_required_here (&str, 12) == FAIL)
7745 if (! inst.error)
7746 inst.error = BAD_ARGS;
7747 return;
7750 end_of_line (str);
7751 return;
7754 static void
7755 do_vfp_sp_ldst (str)
7756 char *str;
7758 skip_whitespace (str);
7760 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7762 if (!inst.error)
7763 inst.error = BAD_ARGS;
7764 return;
7767 if (skip_past_comma (&str) == FAIL
7768 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
7770 if (!inst.error)
7771 inst.error = BAD_ARGS;
7772 return;
7775 end_of_line (str);
7776 return;
7779 static void
7780 do_vfp_dp_ldst (str)
7781 char *str;
7783 skip_whitespace (str);
7785 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7787 if (!inst.error)
7788 inst.error = BAD_ARGS;
7789 return;
7792 if (skip_past_comma (&str) == FAIL
7793 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
7795 if (!inst.error)
7796 inst.error = BAD_ARGS;
7797 return;
7800 end_of_line (str);
7801 return;
7804 /* Parse and encode a VFP SP register list, storing the initial
7805 register in position POS and returning the range as the result. If
7806 the string is invalid return FAIL (an invalid range). */
7807 static long
7808 vfp_sp_reg_list (str, pos)
7809 char **str;
7810 enum vfp_sp_reg_pos pos;
7812 long range = 0;
7813 int base_reg = 0;
7814 int new_base;
7815 long base_bits = 0;
7816 int count = 0;
7817 long tempinst;
7818 unsigned long mask = 0;
7819 int warned = 0;
7821 if (**str != '{')
7822 return FAIL;
7824 (*str)++;
7825 skip_whitespace (*str);
7827 tempinst = inst.instruction;
7831 inst.instruction = 0;
7833 if ((new_base = vfp_sp_reg_required_here (str, pos)) == FAIL)
7834 return FAIL;
7836 if (count == 0 || base_reg > new_base)
7838 base_reg = new_base;
7839 base_bits = inst.instruction;
7842 if (mask & (1 << new_base))
7844 inst.error = _("invalid register list");
7845 return FAIL;
7848 if ((mask >> new_base) != 0 && ! warned)
7850 as_tsktsk (_("register list not in ascending order"));
7851 warned = 1;
7854 mask |= 1 << new_base;
7855 count++;
7857 skip_whitespace (*str);
7859 if (**str == '-') /* We have the start of a range expression */
7861 int high_range;
7863 (*str)++;
7865 if ((high_range
7866 = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab))
7867 == FAIL)
7869 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
7870 return FAIL;
7873 if (high_range <= new_base)
7875 inst.error = _("register range not in ascending order");
7876 return FAIL;
7879 for (new_base++; new_base <= high_range; new_base++)
7881 if (mask & (1 << new_base))
7883 inst.error = _("invalid register list");
7884 return FAIL;
7887 mask |= 1 << new_base;
7888 count++;
7892 while (skip_past_comma (str) != FAIL);
7894 if (**str != '}')
7896 inst.error = _("invalid register list");
7897 return FAIL;
7900 (*str)++;
7902 range = count;
7904 /* Sanity check -- should have raised a parse error above. */
7905 if (count == 0 || count > 32)
7906 abort ();
7908 /* Final test -- the registers must be consecutive. */
7909 while (count--)
7911 if ((mask & (1 << base_reg++)) == 0)
7913 inst.error = _("non-contiguous register range");
7914 return FAIL;
7918 inst.instruction = tempinst | base_bits;
7919 return range;
7922 static long
7923 vfp_dp_reg_list (str)
7924 char **str;
7926 long range = 0;
7927 int base_reg = 0;
7928 int new_base;
7929 int count = 0;
7930 long tempinst;
7931 unsigned long mask = 0;
7932 int warned = 0;
7934 if (**str != '{')
7935 return FAIL;
7937 (*str)++;
7938 skip_whitespace (*str);
7940 tempinst = inst.instruction;
7944 inst.instruction = 0;
7946 if ((new_base = vfp_dp_reg_required_here (str, VFP_REG_Dd)) == FAIL)
7947 return FAIL;
7949 if (count == 0 || base_reg > new_base)
7951 base_reg = new_base;
7952 range = inst.instruction;
7955 if (mask & (1 << new_base))
7957 inst.error = _("invalid register list");
7958 return FAIL;
7961 if ((mask >> new_base) != 0 && ! warned)
7963 as_tsktsk (_("register list not in ascending order"));
7964 warned = 1;
7967 mask |= 1 << new_base;
7968 count++;
7970 skip_whitespace (*str);
7972 if (**str == '-') /* We have the start of a range expression */
7974 int high_range;
7976 (*str)++;
7978 if ((high_range
7979 = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab))
7980 == FAIL)
7982 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
7983 return FAIL;
7986 if (high_range <= new_base)
7988 inst.error = _("register range not in ascending order");
7989 return FAIL;
7992 for (new_base++; new_base <= high_range; new_base++)
7994 if (mask & (1 << new_base))
7996 inst.error = _("invalid register list");
7997 return FAIL;
8000 mask |= 1 << new_base;
8001 count++;
8005 while (skip_past_comma (str) != FAIL);
8007 if (**str != '}')
8009 inst.error = _("invalid register list");
8010 return FAIL;
8013 (*str)++;
8015 range |= 2 * count;
8017 /* Sanity check -- should have raised a parse error above. */
8018 if (count == 0 || count > 16)
8019 abort ();
8021 /* Final test -- the registers must be consecutive. */
8022 while (count--)
8024 if ((mask & (1 << base_reg++)) == 0)
8026 inst.error = _("non-contiguous register range");
8027 return FAIL;
8031 inst.instruction = tempinst;
8032 return range;
8035 static void
8036 vfp_sp_ldstm (str, ldstm_type)
8037 char *str;
8038 enum vfp_ldstm_type ldstm_type;
8040 long range;
8042 skip_whitespace (str);
8044 if (reg_required_here (&str, 16) == FAIL)
8045 return;
8047 skip_whitespace (str);
8049 if (*str == '!')
8051 inst.instruction |= WRITE_BACK;
8052 str++;
8054 else if (ldstm_type != VFP_LDSTMIA)
8056 inst.error = _("this addressing mode requires base-register writeback");
8057 return;
8060 if (skip_past_comma (&str) == FAIL
8061 || (range = vfp_sp_reg_list (&str, VFP_REG_Sd)) == FAIL)
8063 if (!inst.error)
8064 inst.error = BAD_ARGS;
8065 return;
8068 inst.instruction |= range;
8069 end_of_line (str);
8072 static void
8073 vfp_dp_ldstm (str, ldstm_type)
8074 char *str;
8075 enum vfp_ldstm_type ldstm_type;
8077 long range;
8079 skip_whitespace (str);
8081 if (reg_required_here (&str, 16) == FAIL)
8082 return;
8084 skip_whitespace (str);
8086 if (*str == '!')
8088 inst.instruction |= WRITE_BACK;
8089 str++;
8091 else if (ldstm_type != VFP_LDSTMIA && ldstm_type != VFP_LDSTMIAX)
8093 inst.error = _("this addressing mode requires base-register writeback");
8094 return;
8097 if (skip_past_comma (&str) == FAIL
8098 || (range = vfp_dp_reg_list (&str)) == FAIL)
8100 if (!inst.error)
8101 inst.error = BAD_ARGS;
8102 return;
8105 if (ldstm_type == VFP_LDSTMIAX || ldstm_type == VFP_LDSTMDBX)
8106 range += 1;
8108 inst.instruction |= range;
8109 end_of_line (str);
8112 static void
8113 do_vfp_sp_ldstmia (str)
8114 char *str;
8116 vfp_sp_ldstm (str, VFP_LDSTMIA);
8119 static void
8120 do_vfp_sp_ldstmdb (str)
8121 char *str;
8123 vfp_sp_ldstm (str, VFP_LDSTMDB);
8126 static void
8127 do_vfp_dp_ldstmia (str)
8128 char *str;
8130 vfp_dp_ldstm (str, VFP_LDSTMIA);
8133 static void
8134 do_vfp_dp_ldstmdb (str)
8135 char *str;
8137 vfp_dp_ldstm (str, VFP_LDSTMDB);
8140 static void
8141 do_vfp_xp_ldstmia (str)
8142 char *str;
8144 vfp_dp_ldstm (str, VFP_LDSTMIAX);
8147 static void
8148 do_vfp_xp_ldstmdb (str)
8149 char *str;
8151 vfp_dp_ldstm (str, VFP_LDSTMDBX);
8154 static void
8155 do_vfp_sp_compare_z (str)
8156 char *str;
8158 skip_whitespace (str);
8160 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8162 if (!inst.error)
8163 inst.error = BAD_ARGS;
8164 return;
8167 end_of_line (str);
8168 return;
8171 static void
8172 do_vfp_dp_compare_z (str)
8173 char *str;
8175 skip_whitespace (str);
8177 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8179 if (!inst.error)
8180 inst.error = BAD_ARGS;
8181 return;
8184 end_of_line (str);
8185 return;
8188 static void
8189 do_vfp_dp_sp_cvt (str)
8190 char *str;
8192 skip_whitespace (str);
8194 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8195 return;
8197 if (skip_past_comma (&str) == FAIL
8198 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
8200 if (! inst.error)
8201 inst.error = BAD_ARGS;
8202 return;
8205 end_of_line (str);
8206 return;
8209 static void
8210 do_vfp_sp_dp_cvt (str)
8211 char *str;
8213 skip_whitespace (str);
8215 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8216 return;
8218 if (skip_past_comma (&str) == FAIL
8219 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8221 if (! inst.error)
8222 inst.error = BAD_ARGS;
8223 return;
8226 end_of_line (str);
8227 return;
8230 /* Thumb specific routines. */
8232 /* Parse and validate that a register is of the right form, this saves
8233 repeated checking of this information in many similar cases.
8234 Unlike the 32-bit case we do not insert the register into the opcode
8235 here, since the position is often unknown until the full instruction
8236 has been parsed. */
8238 static int
8239 thumb_reg (strp, hi_lo)
8240 char ** strp;
8241 int hi_lo;
8243 int reg;
8245 if ((reg = reg_required_here (strp, -1)) == FAIL)
8246 return FAIL;
8248 switch (hi_lo)
8250 case THUMB_REG_LO:
8251 if (reg > 7)
8253 inst.error = _("lo register required");
8254 return FAIL;
8256 break;
8258 case THUMB_REG_HI:
8259 if (reg < 8)
8261 inst.error = _("hi register required");
8262 return FAIL;
8264 break;
8266 default:
8267 break;
8270 return reg;
8273 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
8274 was SUB. */
8276 static void
8277 thumb_add_sub (str, subtract)
8278 char * str;
8279 int subtract;
8281 int Rd, Rs, Rn = FAIL;
8283 skip_whitespace (str);
8285 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
8286 || skip_past_comma (&str) == FAIL)
8288 if (! inst.error)
8289 inst.error = BAD_ARGS;
8290 return;
8293 if (is_immediate_prefix (*str))
8295 Rs = Rd;
8296 str++;
8297 if (my_get_expression (&inst.reloc.exp, &str))
8298 return;
8300 else
8302 if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8303 return;
8305 if (skip_past_comma (&str) == FAIL)
8307 /* Two operand format, shuffle the registers
8308 and pretend there are 3. */
8309 Rn = Rs;
8310 Rs = Rd;
8312 else if (is_immediate_prefix (*str))
8314 str++;
8315 if (my_get_expression (&inst.reloc.exp, &str))
8316 return;
8318 else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8319 return;
8322 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8323 for the latter case, EXPR contains the immediate that was found. */
8324 if (Rn != FAIL)
8326 /* All register format. */
8327 if (Rd > 7 || Rs > 7 || Rn > 7)
8329 if (Rs != Rd)
8331 inst.error = _("dest and source1 must be the same register");
8332 return;
8335 /* Can't do this for SUB. */
8336 if (subtract)
8338 inst.error = _("subtract valid only on lo regs");
8339 return;
8342 inst.instruction = (T_OPCODE_ADD_HI
8343 | (Rd > 7 ? THUMB_H1 : 0)
8344 | (Rn > 7 ? THUMB_H2 : 0));
8345 inst.instruction |= (Rd & 7) | ((Rn & 7) << 3);
8347 else
8349 inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3;
8350 inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
8353 else
8355 /* Immediate expression, now things start to get nasty. */
8357 /* First deal with HI regs, only very restricted cases allowed:
8358 Adjusting SP, and using PC or SP to get an address. */
8359 if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP))
8360 || (Rs > 7 && Rs != REG_SP && Rs != REG_PC))
8362 inst.error = _("invalid Hi register with immediate");
8363 return;
8366 if (inst.reloc.exp.X_op != O_constant)
8368 /* Value isn't known yet, all we can do is store all the fragments
8369 we know about in the instruction and let the reloc hacking
8370 work it all out. */
8371 inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs;
8372 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
8374 else
8376 int offset = inst.reloc.exp.X_add_number;
8378 if (subtract)
8379 offset = - offset;
8381 if (offset < 0)
8383 offset = - offset;
8384 subtract = 1;
8386 /* Quick check, in case offset is MIN_INT. */
8387 if (offset < 0)
8389 inst.error = _("immediate value out of range");
8390 return;
8393 /* Note - you cannot convert a subtract of 0 into an
8394 add of 0 because the carry flag is set differently. */
8395 else if (offset > 0)
8396 subtract = 0;
8398 if (Rd == REG_SP)
8400 if (offset & ~0x1fc)
8402 inst.error = _("invalid immediate value for stack adjust");
8403 return;
8405 inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
8406 inst.instruction |= offset >> 2;
8408 else if (Rs == REG_PC || Rs == REG_SP)
8410 if (subtract
8411 || (offset & ~0x3fc))
8413 inst.error = _("invalid immediate for address calculation");
8414 return;
8416 inst.instruction = (Rs == REG_PC ? T_OPCODE_ADD_PC
8417 : T_OPCODE_ADD_SP);
8418 inst.instruction |= (Rd << 8) | (offset >> 2);
8420 else if (Rs == Rd)
8422 if (offset & ~0xff)
8424 inst.error = _("immediate value out of range");
8425 return;
8427 inst.instruction = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
8428 inst.instruction |= (Rd << 8) | offset;
8430 else
8432 if (offset & ~0x7)
8434 inst.error = _("immediate value out of range");
8435 return;
8437 inst.instruction = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
8438 inst.instruction |= Rd | (Rs << 3) | (offset << 6);
8443 end_of_line (str);
8446 static void
8447 thumb_shift (str, shift)
8448 char * str;
8449 int shift;
8451 int Rd, Rs, Rn = FAIL;
8453 skip_whitespace (str);
8455 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8456 || skip_past_comma (&str) == FAIL)
8458 if (! inst.error)
8459 inst.error = BAD_ARGS;
8460 return;
8463 if (is_immediate_prefix (*str))
8465 /* Two operand immediate format, set Rs to Rd. */
8466 Rs = Rd;
8467 str ++;
8468 if (my_get_expression (&inst.reloc.exp, &str))
8469 return;
8471 else
8473 if ((Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8474 return;
8476 if (skip_past_comma (&str) == FAIL)
8478 /* Two operand format, shuffle the registers
8479 and pretend there are 3. */
8480 Rn = Rs;
8481 Rs = Rd;
8483 else if (is_immediate_prefix (*str))
8485 str++;
8486 if (my_get_expression (&inst.reloc.exp, &str))
8487 return;
8489 else if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8490 return;
8493 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8494 for the latter case, EXPR contains the immediate that was found. */
8496 if (Rn != FAIL)
8498 if (Rs != Rd)
8500 inst.error = _("source1 and dest must be same register");
8501 return;
8504 switch (shift)
8506 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_R; break;
8507 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_R; break;
8508 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_R; break;
8511 inst.instruction |= Rd | (Rn << 3);
8513 else
8515 switch (shift)
8517 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_I; break;
8518 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_I; break;
8519 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_I; break;
8522 if (inst.reloc.exp.X_op != O_constant)
8524 /* Value isn't known yet, create a dummy reloc and let reloc
8525 hacking fix it up. */
8526 inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
8528 else
8530 unsigned shift_value = inst.reloc.exp.X_add_number;
8532 if (shift_value > 32 || (shift_value == 32 && shift == THUMB_LSL))
8534 inst.error = _("invalid immediate for shift");
8535 return;
8538 /* Shifts of zero are handled by converting to LSL. */
8539 if (shift_value == 0)
8540 inst.instruction = T_OPCODE_LSL_I;
8542 /* Shifts of 32 are encoded as a shift of zero. */
8543 if (shift_value == 32)
8544 shift_value = 0;
8546 inst.instruction |= shift_value << 6;
8549 inst.instruction |= Rd | (Rs << 3);
8552 end_of_line (str);
8555 static void
8556 thumb_mov_compare (str, move)
8557 char * str;
8558 int move;
8560 int Rd, Rs = FAIL;
8562 skip_whitespace (str);
8564 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
8565 || skip_past_comma (&str) == FAIL)
8567 if (! inst.error)
8568 inst.error = BAD_ARGS;
8569 return;
8572 if (is_immediate_prefix (*str))
8574 str++;
8575 if (my_get_expression (&inst.reloc.exp, &str))
8576 return;
8578 else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8579 return;
8581 if (Rs != FAIL)
8583 if (Rs < 8 && Rd < 8)
8585 if (move == THUMB_MOVE)
8586 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
8587 since a MOV instruction produces unpredictable results. */
8588 inst.instruction = T_OPCODE_ADD_I3;
8589 else
8590 inst.instruction = T_OPCODE_CMP_LR;
8591 inst.instruction |= Rd | (Rs << 3);
8593 else
8595 if (move == THUMB_MOVE)
8596 inst.instruction = T_OPCODE_MOV_HR;
8597 else
8598 inst.instruction = T_OPCODE_CMP_HR;
8600 if (Rd > 7)
8601 inst.instruction |= THUMB_H1;
8603 if (Rs > 7)
8604 inst.instruction |= THUMB_H2;
8606 inst.instruction |= (Rd & 7) | ((Rs & 7) << 3);
8609 else
8611 if (Rd > 7)
8613 inst.error = _("only lo regs allowed with immediate");
8614 return;
8617 if (move == THUMB_MOVE)
8618 inst.instruction = T_OPCODE_MOV_I8;
8619 else
8620 inst.instruction = T_OPCODE_CMP_I8;
8622 inst.instruction |= Rd << 8;
8624 if (inst.reloc.exp.X_op != O_constant)
8625 inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
8626 else
8628 unsigned value = inst.reloc.exp.X_add_number;
8630 if (value > 255)
8632 inst.error = _("invalid immediate");
8633 return;
8636 inst.instruction |= value;
8640 end_of_line (str);
8643 static void
8644 thumb_load_store (str, load_store, size)
8645 char * str;
8646 int load_store;
8647 int size;
8649 int Rd, Rb, Ro = FAIL;
8651 skip_whitespace (str);
8653 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8654 || skip_past_comma (&str) == FAIL)
8656 if (! inst.error)
8657 inst.error = BAD_ARGS;
8658 return;
8661 if (*str == '[')
8663 str++;
8664 if ((Rb = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8665 return;
8667 if (skip_past_comma (&str) != FAIL)
8669 if (is_immediate_prefix (*str))
8671 str++;
8672 if (my_get_expression (&inst.reloc.exp, &str))
8673 return;
8675 else if ((Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8676 return;
8678 else
8680 inst.reloc.exp.X_op = O_constant;
8681 inst.reloc.exp.X_add_number = 0;
8684 if (*str != ']')
8686 inst.error = _("expected ']'");
8687 return;
8689 str++;
8691 else if (*str == '=')
8693 if (load_store != THUMB_LOAD)
8695 inst.error = _("invalid pseudo operation");
8696 return;
8699 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
8700 str++;
8702 skip_whitespace (str);
8704 if (my_get_expression (& inst.reloc.exp, & str))
8705 return;
8707 end_of_line (str);
8709 if ( inst.reloc.exp.X_op != O_constant
8710 && inst.reloc.exp.X_op != O_symbol)
8712 inst.error = "Constant expression expected";
8713 return;
8716 if (inst.reloc.exp.X_op == O_constant
8717 && ((inst.reloc.exp.X_add_number & ~0xFF) == 0))
8719 /* This can be done with a mov instruction. */
8721 inst.instruction = T_OPCODE_MOV_I8 | (Rd << 8);
8722 inst.instruction |= inst.reloc.exp.X_add_number;
8723 return;
8726 /* Insert into literal pool. */
8727 if (add_to_lit_pool () == FAIL)
8729 if (!inst.error)
8730 inst.error = "literal pool insertion failed";
8731 return;
8734 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8735 inst.reloc.pc_rel = 1;
8736 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
8737 /* Adjust ARM pipeline offset to Thumb. */
8738 inst.reloc.exp.X_add_number += 4;
8740 return;
8742 else
8744 if (my_get_expression (&inst.reloc.exp, &str))
8745 return;
8747 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
8748 inst.reloc.pc_rel = 1;
8749 inst.reloc.exp.X_add_number -= 4; /* Pipeline offset. */
8750 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8751 end_of_line (str);
8752 return;
8755 if (Rb == REG_PC || Rb == REG_SP)
8757 if (size != THUMB_WORD)
8759 inst.error = _("byte or halfword not valid for base register");
8760 return;
8762 else if (Rb == REG_PC && load_store != THUMB_LOAD)
8764 inst.error = _("r15 based store not allowed");
8765 return;
8767 else if (Ro != FAIL)
8769 inst.error = _("invalid base register for register offset");
8770 return;
8773 if (Rb == REG_PC)
8774 inst.instruction = T_OPCODE_LDR_PC;
8775 else if (load_store == THUMB_LOAD)
8776 inst.instruction = T_OPCODE_LDR_SP;
8777 else
8778 inst.instruction = T_OPCODE_STR_SP;
8780 inst.instruction |= Rd << 8;
8781 if (inst.reloc.exp.X_op == O_constant)
8783 unsigned offset = inst.reloc.exp.X_add_number;
8785 if (offset & ~0x3fc)
8787 inst.error = _("invalid offset");
8788 return;
8791 inst.instruction |= offset >> 2;
8793 else
8794 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8796 else if (Rb > 7)
8798 inst.error = _("invalid base register in load/store");
8799 return;
8801 else if (Ro == FAIL)
8803 /* Immediate offset. */
8804 if (size == THUMB_WORD)
8805 inst.instruction = (load_store == THUMB_LOAD
8806 ? T_OPCODE_LDR_IW : T_OPCODE_STR_IW);
8807 else if (size == THUMB_HALFWORD)
8808 inst.instruction = (load_store == THUMB_LOAD
8809 ? T_OPCODE_LDR_IH : T_OPCODE_STR_IH);
8810 else
8811 inst.instruction = (load_store == THUMB_LOAD
8812 ? T_OPCODE_LDR_IB : T_OPCODE_STR_IB);
8814 inst.instruction |= Rd | (Rb << 3);
8816 if (inst.reloc.exp.X_op == O_constant)
8818 unsigned offset = inst.reloc.exp.X_add_number;
8820 if (offset & ~(0x1f << size))
8822 inst.error = _("invalid offset");
8823 return;
8825 inst.instruction |= (offset >> size) << 6;
8827 else
8828 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8830 else
8832 /* Register offset. */
8833 if (size == THUMB_WORD)
8834 inst.instruction = (load_store == THUMB_LOAD
8835 ? T_OPCODE_LDR_RW : T_OPCODE_STR_RW);
8836 else if (size == THUMB_HALFWORD)
8837 inst.instruction = (load_store == THUMB_LOAD
8838 ? T_OPCODE_LDR_RH : T_OPCODE_STR_RH);
8839 else
8840 inst.instruction = (load_store == THUMB_LOAD
8841 ? T_OPCODE_LDR_RB : T_OPCODE_STR_RB);
8843 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
8846 end_of_line (str);
8849 /* A register must be given at this point.
8851 Shift is the place to put it in inst.instruction.
8853 Restores input start point on err.
8854 Returns the reg#, or FAIL. */
8856 static int
8857 mav_reg_required_here (str, shift, regtype)
8858 char ** str;
8859 int shift;
8860 enum arm_reg_type regtype;
8862 int reg;
8863 char *start = *str;
8865 if ((reg = arm_reg_parse (str, all_reg_maps[regtype].htab)) != FAIL)
8867 if (shift >= 0)
8868 inst.instruction |= reg << shift;
8870 return reg;
8873 /* Restore the start point. */
8874 *str = start;
8876 /* In the few cases where we might be able to accept something else
8877 this error can be overridden. */
8878 inst.error = _(all_reg_maps[regtype].expected);
8880 return FAIL;
8883 /* Cirrus Maverick Instructions. */
8885 /* Wrapper functions. */
8887 static void
8888 do_mav_binops_1a (str)
8889 char * str;
8891 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVF);
8894 static void
8895 do_mav_binops_1b (str)
8896 char * str;
8898 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVD);
8901 static void
8902 do_mav_binops_1c (str)
8903 char * str;
8905 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVDX);
8908 static void
8909 do_mav_binops_1d (str)
8910 char * str;
8912 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVF);
8915 static void
8916 do_mav_binops_1e (str)
8917 char * str;
8919 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVD);
8922 static void
8923 do_mav_binops_1f (str)
8924 char * str;
8926 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVF);
8929 static void
8930 do_mav_binops_1g (str)
8931 char * str;
8933 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVD);
8936 static void
8937 do_mav_binops_1h (str)
8938 char * str;
8940 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVFX);
8943 static void
8944 do_mav_binops_1i (str)
8945 char * str;
8947 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVFX);
8950 static void
8951 do_mav_binops_1j (str)
8952 char * str;
8954 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVDX);
8957 static void
8958 do_mav_binops_1k (str)
8959 char * str;
8961 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVDX);
8964 static void
8965 do_mav_binops_1l (str)
8966 char * str;
8968 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVF);
8971 static void
8972 do_mav_binops_1m (str)
8973 char * str;
8975 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVD);
8978 static void
8979 do_mav_binops_1n (str)
8980 char * str;
8982 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVFX);
8985 static void
8986 do_mav_binops_1o (str)
8987 char * str;
8989 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVDX, REG_TYPE_MVDX);
8992 static void
8993 do_mav_binops_2a (str)
8994 char * str;
8996 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVF, REG_TYPE_RN);
8999 static void
9000 do_mav_binops_2b (str)
9001 char * str;
9003 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVD, REG_TYPE_RN);
9006 static void
9007 do_mav_binops_2c (str)
9008 char * str;
9010 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVDX, REG_TYPE_RN);
9013 static void
9014 do_mav_binops_3a (str)
9015 char * str;
9017 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVFX);
9020 static void
9021 do_mav_binops_3b (str)
9022 char * str;
9024 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVFX, REG_TYPE_MVAX);
9027 static void
9028 do_mav_binops_3c (str)
9029 char * str;
9031 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVDX);
9034 static void
9035 do_mav_binops_3d (str)
9036 char * str;
9038 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVDX, REG_TYPE_MVAX);
9041 static void
9042 do_mav_triple_4a (str)
9043 char * str;
9045 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_RN);
9048 static void
9049 do_mav_triple_4b (str)
9050 char * str;
9052 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_RN);
9055 static void
9056 do_mav_triple_5a (str)
9057 char * str;
9059 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVF, REG_TYPE_MVF);
9062 static void
9063 do_mav_triple_5b (str)
9064 char * str;
9066 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVD, REG_TYPE_MVD);
9069 static void
9070 do_mav_triple_5c (str)
9071 char * str;
9073 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVFX, REG_TYPE_MVFX);
9076 static void
9077 do_mav_triple_5d (str)
9078 char * str;
9080 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVDX, REG_TYPE_MVDX);
9083 static void
9084 do_mav_triple_5e (str)
9085 char * str;
9087 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVF, REG_TYPE_MVF, REG_TYPE_MVF);
9090 static void
9091 do_mav_triple_5f (str)
9092 char * str;
9094 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVD, REG_TYPE_MVD, REG_TYPE_MVD);
9097 static void
9098 do_mav_triple_5g (str)
9099 char * str;
9101 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_MVFX);
9104 static void
9105 do_mav_triple_5h (str)
9106 char * str;
9108 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_MVDX);
9111 static void
9112 do_mav_quad_6a (str)
9113 char * str;
9115 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVFX, REG_TYPE_MVFX,
9116 REG_TYPE_MVFX);
9119 static void
9120 do_mav_quad_6b (str)
9121 char * str;
9123 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVAX, REG_TYPE_MVFX,
9124 REG_TYPE_MVFX);
9127 /* cfmvsc32<cond> DSPSC,MVFX[15:0]. */
9128 static void
9129 do_mav_dspsc_1 (str)
9130 char * str;
9132 skip_whitespace (str);
9134 /* cfmvsc32. */
9135 if (mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL
9136 || skip_past_comma (&str) == FAIL
9137 || mav_reg_required_here (&str, 16, REG_TYPE_MVFX) == FAIL)
9139 if (!inst.error)
9140 inst.error = BAD_ARGS;
9142 return;
9145 end_of_line (str);
9148 /* cfmv32sc<cond> MVFX[15:0],DSPSC. */
9149 static void
9150 do_mav_dspsc_2 (str)
9151 char * str;
9153 skip_whitespace (str);
9155 /* cfmv32sc. */
9156 if (mav_reg_required_here (&str, 0, REG_TYPE_MVFX) == FAIL
9157 || skip_past_comma (&str) == FAIL
9158 || mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL)
9160 if (!inst.error)
9161 inst.error = BAD_ARGS;
9163 return;
9166 end_of_line (str);
9169 static void
9170 do_mav_shift_1 (str)
9171 char * str;
9173 do_mav_shift (str, REG_TYPE_MVFX, REG_TYPE_MVFX);
9176 static void
9177 do_mav_shift_2 (str)
9178 char * str;
9180 do_mav_shift (str, REG_TYPE_MVDX, REG_TYPE_MVDX);
9183 static void
9184 do_mav_ldst_1 (str)
9185 char * str;
9187 do_mav_ldst (str, REG_TYPE_MVF);
9190 static void
9191 do_mav_ldst_2 (str)
9192 char * str;
9194 do_mav_ldst (str, REG_TYPE_MVD);
9197 static void
9198 do_mav_ldst_3 (str)
9199 char * str;
9201 do_mav_ldst (str, REG_TYPE_MVFX);
9204 static void
9205 do_mav_ldst_4 (str)
9206 char * str;
9208 do_mav_ldst (str, REG_TYPE_MVDX);
9211 /* Isnsn like "foo X,Y". */
9213 static void
9214 do_mav_binops (str, mode, reg0, reg1)
9215 char * str;
9216 int mode;
9217 enum arm_reg_type reg0;
9218 enum arm_reg_type reg1;
9220 int shift0, shift1;
9222 shift0 = mode & 0xff;
9223 shift1 = (mode >> 8) & 0xff;
9225 skip_whitespace (str);
9227 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
9228 || skip_past_comma (&str) == FAIL
9229 || mav_reg_required_here (&str, shift1, reg1) == FAIL)
9231 if (!inst.error)
9232 inst.error = BAD_ARGS;
9234 else
9235 end_of_line (str);
9238 /* Isnsn like "foo X,Y,Z". */
9240 static void
9241 do_mav_triple (str, mode, reg0, reg1, reg2)
9242 char * str;
9243 int mode;
9244 enum arm_reg_type reg0;
9245 enum arm_reg_type reg1;
9246 enum arm_reg_type reg2;
9248 int shift0, shift1, shift2;
9250 shift0 = mode & 0xff;
9251 shift1 = (mode >> 8) & 0xff;
9252 shift2 = (mode >> 16) & 0xff;
9254 skip_whitespace (str);
9256 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
9257 || skip_past_comma (&str) == FAIL
9258 || mav_reg_required_here (&str, shift1, reg1) == FAIL
9259 || skip_past_comma (&str) == FAIL
9260 || mav_reg_required_here (&str, shift2, reg2) == FAIL)
9262 if (!inst.error)
9263 inst.error = BAD_ARGS;
9265 else
9266 end_of_line (str);
9269 /* Isnsn like "foo W,X,Y,Z".
9270 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
9272 static void
9273 do_mav_quad (str, mode, reg0, reg1, reg2, reg3)
9274 char * str;
9275 int mode;
9276 enum arm_reg_type reg0;
9277 enum arm_reg_type reg1;
9278 enum arm_reg_type reg2;
9279 enum arm_reg_type reg3;
9281 int shift0, shift1, shift2, shift3;
9283 shift0= mode & 0xff;
9284 shift1 = (mode >> 8) & 0xff;
9285 shift2 = (mode >> 16) & 0xff;
9286 shift3 = (mode >> 24) & 0xff;
9288 skip_whitespace (str);
9290 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
9291 || skip_past_comma (&str) == FAIL
9292 || mav_reg_required_here (&str, shift1, reg1) == FAIL
9293 || skip_past_comma (&str) == FAIL
9294 || mav_reg_required_here (&str, shift2, reg2) == FAIL
9295 || skip_past_comma (&str) == FAIL
9296 || mav_reg_required_here (&str, shift3, reg3) == FAIL)
9298 if (!inst.error)
9299 inst.error = BAD_ARGS;
9301 else
9302 end_of_line (str);
9305 /* Maverick shift immediate instructions.
9306 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
9307 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
9309 static void
9310 do_mav_shift (str, reg0, reg1)
9311 char * str;
9312 enum arm_reg_type reg0;
9313 enum arm_reg_type reg1;
9315 int error;
9316 int imm, neg = 0;
9318 skip_whitespace (str);
9320 error = 0;
9322 if (mav_reg_required_here (&str, 12, reg0) == FAIL
9323 || skip_past_comma (&str) == FAIL
9324 || mav_reg_required_here (&str, 16, reg1) == FAIL
9325 || skip_past_comma (&str) == FAIL)
9327 if (!inst.error)
9328 inst.error = BAD_ARGS;
9329 return;
9332 /* Calculate the immediate operand.
9333 The operand is a 7bit signed number. */
9334 skip_whitespace (str);
9336 if (*str == '#')
9337 ++str;
9339 if (!ISDIGIT (*str) && *str != '-')
9341 inst.error = _("expecting immediate, 7bit operand");
9342 return;
9345 if (*str == '-')
9347 neg = 1;
9348 ++str;
9351 for (imm = 0; *str && ISDIGIT (*str); ++str)
9352 imm = imm * 10 + *str - '0';
9354 if (imm > 64)
9356 inst.error = _("immediate out of range");
9357 return;
9360 /* Make negative imm's into 7bit signed numbers. */
9361 if (neg)
9363 imm = -imm;
9364 imm &= 0x0000007f;
9367 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
9368 Bits 5-7 of the insn should have bits 4-6 of the immediate.
9369 Bit 4 should be 0. */
9370 imm = (imm & 0xf) | ((imm & 0x70) << 1);
9372 inst.instruction |= imm;
9373 end_of_line (str);
9376 static int
9377 mav_parse_offset (str, negative)
9378 char ** str;
9379 int *negative;
9381 char * p = *str;
9382 int offset;
9384 *negative = 0;
9386 skip_whitespace (p);
9388 if (*p == '#')
9389 ++p;
9391 if (*p == '-')
9393 *negative = 1;
9394 ++p;
9397 if (!ISDIGIT (*p))
9399 inst.error = _("offset expected");
9400 return 0;
9403 for (offset = 0; *p && ISDIGIT (*p); ++p)
9404 offset = offset * 10 + *p - '0';
9406 if (offset > 0xff)
9408 inst.error = _("offset out of range");
9409 return 0;
9412 *str = p;
9414 return *negative ? -offset : offset;
9417 /* Maverick load/store instructions.
9418 <insn><cond> CRd,[Rn,<offset>]{!}.
9419 <insn><cond> CRd,[Rn],<offset>. */
9421 static void
9422 do_mav_ldst (str, reg0)
9423 char * str;
9424 enum arm_reg_type reg0;
9426 int offset, negative;
9428 skip_whitespace (str);
9430 if (mav_reg_required_here (&str, 12, reg0) == FAIL
9431 || skip_past_comma (&str) == FAIL
9432 || *str++ != '['
9433 || reg_required_here (&str, 16) == FAIL)
9434 goto fail_ldst;
9436 if (skip_past_comma (&str) == SUCCESS)
9438 /* You are here: "<offset>]{!}". */
9439 inst.instruction |= PRE_INDEX;
9441 offset = mav_parse_offset (&str, &negative);
9443 if (inst.error)
9444 return;
9446 if (*str++ != ']')
9448 inst.error = _("missing ]");
9449 return;
9452 if (*str == '!')
9454 inst.instruction |= WRITE_BACK;
9455 ++str;
9458 else
9460 /* You are here: "], <offset>". */
9461 if (*str++ != ']')
9463 inst.error = _("missing ]");
9464 return;
9467 if (skip_past_comma (&str) == FAIL
9468 || (offset = mav_parse_offset (&str, &negative), inst.error))
9469 goto fail_ldst;
9471 inst.instruction |= CP_T_WB; /* Post indexed, set bit W. */
9474 if (negative)
9475 offset = -offset;
9476 else
9477 inst.instruction |= CP_T_UD; /* Postive, so set bit U. */
9479 inst.instruction |= offset >> 2;
9480 end_of_line (str);
9481 return;
9483 fail_ldst:
9484 if (!inst.error)
9485 inst.error = BAD_ARGS;
9486 return;
9489 static void
9490 do_t_nop (str)
9491 char * str;
9493 /* Do nothing. */
9494 end_of_line (str);
9495 return;
9498 /* Handle the Format 4 instructions that do not have equivalents in other
9499 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
9500 BIC and MVN. */
9502 static void
9503 do_t_arit (str)
9504 char * str;
9506 int Rd, Rs, Rn;
9508 skip_whitespace (str);
9510 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9511 || skip_past_comma (&str) == FAIL
9512 || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9514 inst.error = BAD_ARGS;
9515 return;
9518 if (skip_past_comma (&str) != FAIL)
9520 /* Three operand format not allowed for TST, CMN, NEG and MVN.
9521 (It isn't allowed for CMP either, but that isn't handled by this
9522 function.) */
9523 if (inst.instruction == T_OPCODE_TST
9524 || inst.instruction == T_OPCODE_CMN
9525 || inst.instruction == T_OPCODE_NEG
9526 || inst.instruction == T_OPCODE_MVN)
9528 inst.error = BAD_ARGS;
9529 return;
9532 if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9533 return;
9535 if (Rs != Rd)
9537 inst.error = _("dest and source1 must be the same register");
9538 return;
9540 Rs = Rn;
9543 if (inst.instruction == T_OPCODE_MUL
9544 && Rs == Rd)
9545 as_tsktsk (_("Rs and Rd must be different in MUL"));
9547 inst.instruction |= Rd | (Rs << 3);
9548 end_of_line (str);
9551 static void
9552 do_t_add (str)
9553 char * str;
9555 thumb_add_sub (str, 0);
9558 static void
9559 do_t_asr (str)
9560 char * str;
9562 thumb_shift (str, THUMB_ASR);
9565 static void
9566 do_t_branch9 (str)
9567 char * str;
9569 if (my_get_expression (&inst.reloc.exp, &str))
9570 return;
9571 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
9572 inst.reloc.pc_rel = 1;
9573 end_of_line (str);
9576 static void
9577 do_t_branch12 (str)
9578 char * str;
9580 if (my_get_expression (&inst.reloc.exp, &str))
9581 return;
9582 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
9583 inst.reloc.pc_rel = 1;
9584 end_of_line (str);
9587 /* Find the real, Thumb encoded start of a Thumb function. */
9589 static symbolS *
9590 find_real_start (symbolP)
9591 symbolS * symbolP;
9593 char * real_start;
9594 const char * name = S_GET_NAME (symbolP);
9595 symbolS * new_target;
9597 /* This definiton must agree with the one in gcc/config/arm/thumb.c. */
9598 #define STUB_NAME ".real_start_of"
9600 if (name == NULL)
9601 abort ();
9603 /* Names that start with '.' are local labels, not function entry points.
9604 The compiler may generate BL instructions to these labels because it
9605 needs to perform a branch to a far away location. */
9606 if (name[0] == '.')
9607 return symbolP;
9609 real_start = malloc (strlen (name) + strlen (STUB_NAME) + 1);
9610 sprintf (real_start, "%s%s", STUB_NAME, name);
9612 new_target = symbol_find (real_start);
9614 if (new_target == NULL)
9616 as_warn ("Failed to find real start of function: %s\n", name);
9617 new_target = symbolP;
9620 free (real_start);
9622 return new_target;
9625 static void
9626 do_t_branch23 (str)
9627 char * str;
9629 if (my_get_expression (& inst.reloc.exp, & str))
9630 return;
9632 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH23;
9633 inst.reloc.pc_rel = 1;
9634 end_of_line (str);
9636 /* If the destination of the branch is a defined symbol which does not have
9637 the THUMB_FUNC attribute, then we must be calling a function which has
9638 the (interfacearm) attribute. We look for the Thumb entry point to that
9639 function and change the branch to refer to that function instead. */
9640 if ( inst.reloc.exp.X_op == O_symbol
9641 && inst.reloc.exp.X_add_symbol != NULL
9642 && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
9643 && ! THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
9644 inst.reloc.exp.X_add_symbol =
9645 find_real_start (inst.reloc.exp.X_add_symbol);
9648 static void
9649 do_t_bx (str)
9650 char * str;
9652 int reg;
9654 skip_whitespace (str);
9656 if ((reg = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9657 return;
9659 /* This sets THUMB_H2 from the top bit of reg. */
9660 inst.instruction |= reg << 3;
9662 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
9663 should cause the alignment to be checked once it is known. This is
9664 because BX PC only works if the instruction is word aligned. */
9666 end_of_line (str);
9669 static void
9670 do_t_compare (str)
9671 char * str;
9673 thumb_mov_compare (str, THUMB_COMPARE);
9676 static void
9677 do_t_ldmstm (str)
9678 char * str;
9680 int Rb;
9681 long range;
9683 skip_whitespace (str);
9685 if ((Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9686 return;
9688 if (*str != '!')
9689 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
9690 else
9691 str++;
9693 if (skip_past_comma (&str) == FAIL
9694 || (range = reg_list (&str)) == FAIL)
9696 if (! inst.error)
9697 inst.error = BAD_ARGS;
9698 return;
9701 if (inst.reloc.type != BFD_RELOC_NONE)
9703 /* This really doesn't seem worth it. */
9704 inst.reloc.type = BFD_RELOC_NONE;
9705 inst.error = _("expression too complex");
9706 return;
9709 if (range & ~0xff)
9711 inst.error = _("only lo-regs valid in load/store multiple");
9712 return;
9715 inst.instruction |= (Rb << 8) | range;
9716 end_of_line (str);
9719 static void
9720 do_t_ldr (str)
9721 char * str;
9723 thumb_load_store (str, THUMB_LOAD, THUMB_WORD);
9726 static void
9727 do_t_ldrb (str)
9728 char * str;
9730 thumb_load_store (str, THUMB_LOAD, THUMB_BYTE);
9733 static void
9734 do_t_ldrh (str)
9735 char * str;
9737 thumb_load_store (str, THUMB_LOAD, THUMB_HALFWORD);
9740 static void
9741 do_t_lds (str)
9742 char * str;
9744 int Rd, Rb, Ro;
9746 skip_whitespace (str);
9748 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9749 || skip_past_comma (&str) == FAIL
9750 || *str++ != '['
9751 || (Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9752 || skip_past_comma (&str) == FAIL
9753 || (Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9754 || *str++ != ']')
9756 if (! inst.error)
9757 inst.error = _("syntax: ldrs[b] Rd, [Rb, Ro]");
9758 return;
9761 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
9762 end_of_line (str);
9765 static void
9766 do_t_lsl (str)
9767 char * str;
9769 thumb_shift (str, THUMB_LSL);
9772 static void
9773 do_t_lsr (str)
9774 char * str;
9776 thumb_shift (str, THUMB_LSR);
9779 static void
9780 do_t_mov (str)
9781 char * str;
9783 thumb_mov_compare (str, THUMB_MOVE);
9786 static void
9787 do_t_push_pop (str)
9788 char * str;
9790 long range;
9792 skip_whitespace (str);
9794 if ((range = reg_list (&str)) == FAIL)
9796 if (! inst.error)
9797 inst.error = BAD_ARGS;
9798 return;
9801 if (inst.reloc.type != BFD_RELOC_NONE)
9803 /* This really doesn't seem worth it. */
9804 inst.reloc.type = BFD_RELOC_NONE;
9805 inst.error = _("expression too complex");
9806 return;
9809 if (range & ~0xff)
9811 if ((inst.instruction == T_OPCODE_PUSH
9812 && (range & ~0xff) == 1 << REG_LR)
9813 || (inst.instruction == T_OPCODE_POP
9814 && (range & ~0xff) == 1 << REG_PC))
9816 inst.instruction |= THUMB_PP_PC_LR;
9817 range &= 0xff;
9819 else
9821 inst.error = _("invalid register list to push/pop instruction");
9822 return;
9826 inst.instruction |= range;
9827 end_of_line (str);
9830 static void
9831 do_t_str (str)
9832 char * str;
9834 thumb_load_store (str, THUMB_STORE, THUMB_WORD);
9837 static void
9838 do_t_strb (str)
9839 char * str;
9841 thumb_load_store (str, THUMB_STORE, THUMB_BYTE);
9844 static void
9845 do_t_strh (str)
9846 char * str;
9848 thumb_load_store (str, THUMB_STORE, THUMB_HALFWORD);
9851 static void
9852 do_t_sub (str)
9853 char * str;
9855 thumb_add_sub (str, 1);
9858 static void
9859 do_t_swi (str)
9860 char * str;
9862 skip_whitespace (str);
9864 if (my_get_expression (&inst.reloc.exp, &str))
9865 return;
9867 inst.reloc.type = BFD_RELOC_ARM_SWI;
9868 end_of_line (str);
9869 return;
9872 static void
9873 do_t_adr (str)
9874 char * str;
9876 int reg;
9878 /* This is a pseudo-op of the form "adr rd, label" to be converted
9879 into a relative address of the form "add rd, pc, #label-.-4". */
9880 skip_whitespace (str);
9882 /* Store Rd in temporary location inside instruction. */
9883 if ((reg = reg_required_here (&str, 4)) == FAIL
9884 || (reg > 7) /* For Thumb reg must be r0..r7. */
9885 || skip_past_comma (&str) == FAIL
9886 || my_get_expression (&inst.reloc.exp, &str))
9888 if (!inst.error)
9889 inst.error = BAD_ARGS;
9890 return;
9893 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
9894 inst.reloc.exp.X_add_number -= 4; /* PC relative adjust. */
9895 inst.reloc.pc_rel = 1;
9896 inst.instruction |= REG_PC; /* Rd is already placed into the instruction. */
9898 end_of_line (str);
9901 static void
9902 insert_reg (r, htab)
9903 const struct reg_entry *r;
9904 struct hash_control *htab;
9906 int len = strlen (r->name) + 2;
9907 char * buf = (char *) xmalloc (len);
9908 char * buf2 = (char *) xmalloc (len);
9909 int i = 0;
9911 #ifdef REGISTER_PREFIX
9912 buf[i++] = REGISTER_PREFIX;
9913 #endif
9915 strcpy (buf + i, r->name);
9917 for (i = 0; buf[i]; i++)
9918 buf2[i] = TOUPPER (buf[i]);
9920 buf2[i] = '\0';
9922 hash_insert (htab, buf, (PTR) r);
9923 hash_insert (htab, buf2, (PTR) r);
9926 static void
9927 build_reg_hsh (map)
9928 struct reg_map *map;
9930 const struct reg_entry *r;
9932 if ((map->htab = hash_new ()) == NULL)
9933 as_fatal (_("virtual memory exhausted"));
9935 for (r = map->names; r->name != NULL; r++)
9936 insert_reg (r, map->htab);
9939 static void
9940 insert_reg_alias (str, regnum, htab)
9941 char *str;
9942 int regnum;
9943 struct hash_control *htab;
9945 struct reg_entry *new =
9946 (struct reg_entry *) xmalloc (sizeof (struct reg_entry));
9947 char *name = xmalloc (strlen (str) + 1);
9948 strcpy (name, str);
9950 new->name = name;
9951 new->number = regnum;
9953 hash_insert (htab, name, (PTR) new);
9956 /* Look for the .req directive. This is of the form:
9958 newname .req existing_name
9960 If we find one, or if it looks sufficiently like one that we want to
9961 handle any error here, return non-zero. Otherwise return zero. */
9962 static int
9963 create_register_alias (newname, p)
9964 char *newname;
9965 char *p;
9967 char *q;
9968 char c;
9970 q = p;
9971 skip_whitespace (q);
9973 c = *p;
9974 *p = '\0';
9976 if (*q && !strncmp (q, ".req ", 5))
9978 char *copy_of_str;
9979 char *r;
9981 #ifdef IGNORE_OPCODE_CASE
9982 newname = original_case_string;
9983 #endif
9984 copy_of_str = newname;
9986 q += 4;
9987 skip_whitespace (q);
9989 for (r = q; *r != '\0'; r++)
9990 if (*r == ' ')
9991 break;
9993 if (r != q)
9995 enum arm_reg_type new_type, old_type;
9996 int old_regno;
9997 char d = *r;
9999 *r = '\0';
10000 old_type = arm_reg_parse_any (q);
10001 *r = d;
10003 new_type = arm_reg_parse_any (newname);
10005 if (new_type == REG_TYPE_MAX)
10007 if (old_type != REG_TYPE_MAX)
10009 old_regno = arm_reg_parse (&q, all_reg_maps[old_type].htab);
10010 insert_reg_alias (newname, old_regno,
10011 all_reg_maps[old_type].htab);
10013 else
10014 as_warn (_("register '%s' does not exist\n"), q);
10016 else if (old_type == REG_TYPE_MAX)
10018 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
10019 copy_of_str, q);
10021 else
10023 /* Do not warn about redefinitions to the same alias. */
10024 if (new_type != old_type
10025 || (arm_reg_parse (&q, all_reg_maps[old_type].htab)
10026 != arm_reg_parse (&q, all_reg_maps[new_type].htab)))
10027 as_warn (_("ignoring redefinition of register alias '%s'"),
10028 copy_of_str);
10032 else
10033 as_warn (_("ignoring incomplete .req pseuso op"));
10035 *p = c;
10036 return 1;
10038 *p = c;
10039 return 0;
10042 static void
10043 set_constant_flonums ()
10045 int i;
10047 for (i = 0; i < NUM_FLOAT_VALS; i++)
10048 if (atof_ieee ((char *) fp_const[i], 'x', fp_values[i]) == NULL)
10049 abort ();
10052 /* Iterate over the base tables to create the instruction patterns. */
10053 static void
10054 build_arm_ops_hsh ()
10056 unsigned int i;
10057 unsigned int j;
10058 static struct obstack insn_obstack;
10060 obstack_begin (&insn_obstack, 4000);
10062 for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
10064 const struct asm_opcode *insn = insns + i;
10066 if (insn->cond_offset != 0)
10068 /* Insn supports conditional execution. Build the varaints
10069 and insert them in the hash table. */
10070 for (j = 0; j < sizeof (conds) / sizeof (struct asm_cond); j++)
10072 unsigned len = strlen (insn->template);
10073 struct asm_opcode *new;
10074 char *template;
10076 new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
10077 /* All condition codes are two characters. */
10078 template = obstack_alloc (&insn_obstack, len + 3);
10080 strncpy (template, insn->template, insn->cond_offset);
10081 strcpy (template + insn->cond_offset, conds[j].template);
10082 if (len > insn->cond_offset)
10083 strcpy (template + insn->cond_offset + 2,
10084 insn->template + insn->cond_offset);
10085 new->template = template;
10086 new->cond_offset = 0;
10087 new->variant = insn->variant;
10088 new->parms = insn->parms;
10089 new->value = (insn->value & ~COND_MASK) | conds[j].value;
10091 hash_insert (arm_ops_hsh, new->template, (PTR) new);
10094 /* Finally, insert the unconditional insn in the table directly;
10095 no need to build a copy. */
10096 hash_insert (arm_ops_hsh, insn->template, (PTR) insn);
10100 #if defined OBJ_ELF || defined OBJ_COFF
10102 #ifdef OBJ_ELF
10103 #define arm_Note Elf_External_Note
10104 #else
10105 typedef struct
10107 unsigned char namesz[4]; /* Size of entry's owner string. */
10108 unsigned char descsz[4]; /* Size of the note descriptor. */
10109 unsigned char type[4]; /* Interpretation of the descriptor. */
10110 char name[1]; /* Start of the name+desc data. */
10111 } arm_Note;
10112 #endif
10114 /* The description is kept to a fix sized in order to make updating
10115 it and merging it easier. */
10116 #define ARM_NOTE_DESCRIPTION_LENGTH 8
10118 static void
10119 arm_add_note (name, description, type)
10120 const char * name;
10121 const char * description;
10122 unsigned int type;
10124 arm_Note note ATTRIBUTE_UNUSED;
10125 char * p;
10126 unsigned int name_len;
10128 name_len = (strlen (name) + 1 + 3) & ~3;
10130 p = frag_more (sizeof (note.namesz));
10131 md_number_to_chars (p, (valueT) name_len, sizeof (note.namesz));
10133 p = frag_more (sizeof (note.descsz));
10134 md_number_to_chars (p, (valueT) ARM_NOTE_DESCRIPTION_LENGTH, sizeof (note.descsz));
10136 p = frag_more (sizeof (note.type));
10137 md_number_to_chars (p, (valueT) type, sizeof (note.type));
10139 p = frag_more (name_len);
10140 strcpy (p, name);
10142 p = frag_more (ARM_NOTE_DESCRIPTION_LENGTH);
10143 strncpy (p, description, ARM_NOTE_DESCRIPTION_LENGTH);
10144 frag_align (2, 0, 0);
10146 #endif
10148 void
10149 md_begin ()
10151 unsigned mach;
10152 unsigned int i;
10154 if ( (arm_ops_hsh = hash_new ()) == NULL
10155 || (arm_tops_hsh = hash_new ()) == NULL
10156 || (arm_cond_hsh = hash_new ()) == NULL
10157 || (arm_shift_hsh = hash_new ()) == NULL
10158 || (arm_psr_hsh = hash_new ()) == NULL)
10159 as_fatal (_("virtual memory exhausted"));
10161 build_arm_ops_hsh ();
10162 for (i = 0; i < sizeof (tinsns) / sizeof (struct thumb_opcode); i++)
10163 hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
10164 for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
10165 hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
10166 for (i = 0; i < sizeof (shift_names) / sizeof (struct asm_shift_name); i++)
10167 hash_insert (arm_shift_hsh, shift_names[i].name, (PTR) (shift_names + i));
10168 for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
10169 hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
10171 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
10172 build_reg_hsh (all_reg_maps + i);
10174 set_constant_flonums ();
10176 /* Set the cpu variant based on the command-line options. We prefer
10177 -mcpu= over -march= if both are set (as for GCC); and we prefer
10178 -mfpu= over any other way of setting the floating point unit.
10179 Use of legacy options with new options are faulted. */
10180 if (legacy_cpu != -1)
10182 if (mcpu_cpu_opt != -1 || march_cpu_opt != -1)
10183 as_bad (_("use of old and new-style options to set CPU type"));
10185 mcpu_cpu_opt = legacy_cpu;
10187 else if (mcpu_cpu_opt == -1)
10188 mcpu_cpu_opt = march_cpu_opt;
10190 if (legacy_fpu != -1)
10192 if (mfpu_opt != -1)
10193 as_bad (_("use of old and new-style options to set FPU type"));
10195 mfpu_opt = legacy_fpu;
10197 else if (mfpu_opt == -1)
10199 #if !(defined (TE_LINUX) || defined (TE_NetBSD))
10200 /* Some environments specify a default FPU. If they don't, infer it
10201 from the processor. */
10202 if (mcpu_fpu_opt != -1)
10203 mfpu_opt = mcpu_fpu_opt;
10204 else
10205 mfpu_opt = march_fpu_opt;
10206 #else
10207 mfpu_opt = FPU_DEFAULT;
10208 #endif
10211 if (mfpu_opt == -1)
10213 if (mcpu_cpu_opt == -1)
10214 mfpu_opt = FPU_DEFAULT;
10215 else if (mcpu_cpu_opt & ARM_EXT_V5)
10216 mfpu_opt = FPU_ARCH_VFP_V2;
10217 else
10218 mfpu_opt = FPU_ARCH_FPA;
10221 if (mcpu_cpu_opt == -1)
10222 mcpu_cpu_opt = CPU_DEFAULT;
10224 cpu_variant = mcpu_cpu_opt | mfpu_opt;
10226 #if defined OBJ_COFF || defined OBJ_ELF
10228 unsigned int flags = 0;
10230 /* Set the flags in the private structure. */
10231 if (uses_apcs_26) flags |= F_APCS26;
10232 if (support_interwork) flags |= F_INTERWORK;
10233 if (uses_apcs_float) flags |= F_APCS_FLOAT;
10234 if (pic_code) flags |= F_PIC;
10235 if ((cpu_variant & FPU_ANY) == FPU_NONE
10236 || (cpu_variant & FPU_ANY) == FPU_ARCH_VFP) /* VFP layout only. */
10237 flags |= F_SOFT_FLOAT;
10238 /* Using VFP conventions (even if soft-float). */
10239 if (cpu_variant & FPU_VFP_EXT_NONE) flags |= F_VFP_FLOAT;
10241 #if defined OBJ_ELF
10242 if (cpu_variant & ARM_CEXT_MAVERICK)
10244 flags ^= F_SOFT_FLOAT;
10245 flags |= EF_ARM_MAVERICK_FLOAT;
10247 #endif
10249 bfd_set_private_flags (stdoutput, flags);
10251 /* We have run out flags in the COFF header to encode the
10252 status of ATPCS support, so instead we create a dummy,
10253 empty, debug section called .arm.atpcs. */
10254 if (atpcs)
10256 asection * sec;
10258 sec = bfd_make_section (stdoutput, ".arm.atpcs");
10260 if (sec != NULL)
10262 bfd_set_section_flags
10263 (stdoutput, sec, SEC_READONLY | SEC_DEBUGGING /* | SEC_HAS_CONTENTS */);
10264 bfd_set_section_size (stdoutput, sec, 0);
10265 bfd_set_section_contents (stdoutput, sec, NULL, 0, 0);
10269 #endif
10271 /* Record the CPU type as well. */
10272 switch (cpu_variant & ARM_CPU_MASK)
10274 case ARM_2:
10275 mach = bfd_mach_arm_2;
10276 break;
10278 case ARM_3: /* Also ARM_250. */
10279 mach = bfd_mach_arm_2a;
10280 break;
10282 case ARM_6: /* Also ARM_7. */
10283 mach = bfd_mach_arm_3;
10284 break;
10286 default:
10287 mach = bfd_mach_arm_unknown;
10288 break;
10291 /* Catch special cases. */
10292 if (cpu_variant & ARM_CEXT_IWMMXT)
10293 mach = bfd_mach_arm_iWMMXt;
10294 else if (cpu_variant & ARM_CEXT_XSCALE)
10295 mach = bfd_mach_arm_XScale;
10296 else if (cpu_variant & ARM_CEXT_MAVERICK)
10297 mach = bfd_mach_arm_ep9312;
10298 else if (cpu_variant & ARM_EXT_V5E)
10299 mach = bfd_mach_arm_5TE;
10300 else if (cpu_variant & ARM_EXT_V5)
10302 if (cpu_variant & ARM_EXT_V4T)
10303 mach = bfd_mach_arm_5T;
10304 else
10305 mach = bfd_mach_arm_5;
10307 else if (cpu_variant & ARM_EXT_V4)
10309 if (cpu_variant & ARM_EXT_V4T)
10310 mach = bfd_mach_arm_4T;
10311 else
10312 mach = bfd_mach_arm_4;
10314 else if (cpu_variant & ARM_EXT_V3M)
10315 mach = bfd_mach_arm_3M;
10317 #if 0 /* Suppressed - for now. */
10318 #if defined (OBJ_ELF) || defined (OBJ_COFF)
10320 /* Create a .note section to fully identify this arm binary. */
10322 #define NOTE_ARCH_STRING "arch: "
10324 #if defined OBJ_COFF && ! defined NT_VERSION
10325 #define NT_VERSION 1
10326 #define NT_ARCH 2
10327 #endif
10330 segT current_seg = now_seg;
10331 subsegT current_subseg = now_subseg;
10332 asection * arm_arch;
10333 const char * arch_string;
10335 arm_arch = bfd_make_section_old_way (stdoutput, ARM_NOTE_SECTION);
10337 #ifdef OBJ_COFF
10338 bfd_set_section_flags (stdoutput, arm_arch,
10339 SEC_DATA | SEC_ALLOC | SEC_LOAD | SEC_LINK_ONCE \
10340 | SEC_HAS_CONTENTS);
10341 #endif
10342 arm_arch->output_section = arm_arch;
10343 subseg_set (arm_arch, 0);
10345 switch (mach)
10347 default:
10348 case bfd_mach_arm_unknown: arch_string = "unknown"; break;
10349 case bfd_mach_arm_2: arch_string = "armv2"; break;
10350 case bfd_mach_arm_2a: arch_string = "armv2a"; break;
10351 case bfd_mach_arm_3: arch_string = "armv3"; break;
10352 case bfd_mach_arm_3M: arch_string = "armv3M"; break;
10353 case bfd_mach_arm_4: arch_string = "armv4"; break;
10354 case bfd_mach_arm_4T: arch_string = "armv4t"; break;
10355 case bfd_mach_arm_5: arch_string = "armv5"; break;
10356 case bfd_mach_arm_5T: arch_string = "armv5t"; break;
10357 case bfd_mach_arm_5TE: arch_string = "armv5te"; break;
10358 case bfd_mach_arm_XScale: arch_string = "XScale"; break;
10359 case bfd_mach_arm_ep9312: arch_string = "ep9312"; break;
10360 case bfd_mach_arm_iWMMXt: arch_string = "iWMMXt"; break;
10363 arm_add_note (NOTE_ARCH_STRING, arch_string, NT_ARCH);
10365 subseg_set (current_seg, current_subseg);
10367 #endif
10368 #endif /* Suppressed code. */
10370 bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
10373 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
10374 for use in the a.out file, and stores them in the array pointed to by buf.
10375 This knows about the endian-ness of the target machine and does
10376 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
10377 2 (short) and 4 (long) Floating numbers are put out as a series of
10378 LITTLENUMS (shorts, here at least). */
10380 void
10381 md_number_to_chars (buf, val, n)
10382 char * buf;
10383 valueT val;
10384 int n;
10386 if (target_big_endian)
10387 number_to_chars_bigendian (buf, val, n);
10388 else
10389 number_to_chars_littleendian (buf, val, n);
10392 static valueT
10393 md_chars_to_number (buf, n)
10394 char * buf;
10395 int n;
10397 valueT result = 0;
10398 unsigned char * where = (unsigned char *) buf;
10400 if (target_big_endian)
10402 while (n--)
10404 result <<= 8;
10405 result |= (*where++ & 255);
10408 else
10410 while (n--)
10412 result <<= 8;
10413 result |= (where[n] & 255);
10417 return result;
10420 /* Turn a string in input_line_pointer into a floating point constant
10421 of type TYPE, and store the appropriate bytes in *LITP. The number
10422 of LITTLENUMS emitted is stored in *SIZEP. An error message is
10423 returned, or NULL on OK.
10425 Note that fp constants aren't represent in the normal way on the ARM.
10426 In big endian mode, things are as expected. However, in little endian
10427 mode fp constants are big-endian word-wise, and little-endian byte-wise
10428 within the words. For example, (double) 1.1 in big endian mode is
10429 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
10430 the byte sequence 99 99 f1 3f 9a 99 99 99.
10432 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
10434 char *
10435 md_atof (type, litP, sizeP)
10436 char type;
10437 char * litP;
10438 int * sizeP;
10440 int prec;
10441 LITTLENUM_TYPE words[MAX_LITTLENUMS];
10442 char *t;
10443 int i;
10445 switch (type)
10447 case 'f':
10448 case 'F':
10449 case 's':
10450 case 'S':
10451 prec = 2;
10452 break;
10454 case 'd':
10455 case 'D':
10456 case 'r':
10457 case 'R':
10458 prec = 4;
10459 break;
10461 case 'x':
10462 case 'X':
10463 prec = 6;
10464 break;
10466 case 'p':
10467 case 'P':
10468 prec = 6;
10469 break;
10471 default:
10472 *sizeP = 0;
10473 return _("bad call to MD_ATOF()");
10476 t = atof_ieee (input_line_pointer, type, words);
10477 if (t)
10478 input_line_pointer = t;
10479 *sizeP = prec * 2;
10481 if (target_big_endian)
10483 for (i = 0; i < prec; i++)
10485 md_number_to_chars (litP, (valueT) words[i], 2);
10486 litP += 2;
10489 else
10491 if (cpu_variant & FPU_ARCH_VFP)
10492 for (i = prec - 1; i >= 0; i--)
10494 md_number_to_chars (litP, (valueT) words[i], 2);
10495 litP += 2;
10497 else
10498 /* For a 4 byte float the order of elements in `words' is 1 0.
10499 For an 8 byte float the order is 1 0 3 2. */
10500 for (i = 0; i < prec; i += 2)
10502 md_number_to_chars (litP, (valueT) words[i + 1], 2);
10503 md_number_to_chars (litP + 2, (valueT) words[i], 2);
10504 litP += 4;
10508 return 0;
10511 /* The knowledge of the PC's pipeline offset is built into the insns
10512 themselves. */
10514 long
10515 md_pcrel_from (fixP)
10516 fixS * fixP;
10518 if (fixP->fx_addsy
10519 && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section
10520 && fixP->fx_subsy == NULL)
10521 return 0;
10523 if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD))
10525 /* PC relative addressing on the Thumb is slightly odd
10526 as the bottom two bits of the PC are forced to zero
10527 for the calculation. */
10528 return (fixP->fx_where + fixP->fx_frag->fr_address) & ~3;
10531 #ifdef TE_WINCE
10532 /* The pattern was adjusted to accomodate CE's off-by-one fixups,
10533 so we un-adjust here to compensate for the accomodation. */
10534 return fixP->fx_where + fixP->fx_frag->fr_address + 8;
10535 #else
10536 return fixP->fx_where + fixP->fx_frag->fr_address;
10537 #endif
10540 /* Round up a section size to the appropriate boundary. */
10542 valueT
10543 md_section_align (segment, size)
10544 segT segment ATTRIBUTE_UNUSED;
10545 valueT size;
10547 #ifdef OBJ_ELF
10548 return size;
10549 #else
10550 /* Round all sects to multiple of 4. */
10551 return (size + 3) & ~3;
10552 #endif
10555 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
10556 Otherwise we have no need to default values of symbols. */
10558 symbolS *
10559 md_undefined_symbol (name)
10560 char * name ATTRIBUTE_UNUSED;
10562 #ifdef OBJ_ELF
10563 if (name[0] == '_' && name[1] == 'G'
10564 && streq (name, GLOBAL_OFFSET_TABLE_NAME))
10566 if (!GOT_symbol)
10568 if (symbol_find (name))
10569 as_bad ("GOT already in the symbol table");
10571 GOT_symbol = symbol_new (name, undefined_section,
10572 (valueT) 0, & zero_address_frag);
10575 return GOT_symbol;
10577 #endif
10579 return 0;
10582 /* arm_reg_parse () := if it looks like a register, return its token and
10583 advance the pointer. */
10585 static int
10586 arm_reg_parse (ccp, htab)
10587 register char ** ccp;
10588 struct hash_control *htab;
10590 char * start = * ccp;
10591 char c;
10592 char * p;
10593 struct reg_entry * reg;
10595 #ifdef REGISTER_PREFIX
10596 if (*start != REGISTER_PREFIX)
10597 return FAIL;
10598 p = start + 1;
10599 #else
10600 p = start;
10601 #ifdef OPTIONAL_REGISTER_PREFIX
10602 if (*p == OPTIONAL_REGISTER_PREFIX)
10603 p++, start++;
10604 #endif
10605 #endif
10606 if (!ISALPHA (*p) || !is_name_beginner (*p))
10607 return FAIL;
10609 c = *p++;
10610 while (ISALPHA (c) || ISDIGIT (c) || c == '_')
10611 c = *p++;
10613 *--p = 0;
10614 reg = (struct reg_entry *) hash_find (htab, start);
10615 *p = c;
10617 if (reg)
10619 *ccp = p;
10620 return reg->number;
10623 return FAIL;
10626 /* Search for the following register name in each of the possible reg name
10627 tables. Return the classification if found, or REG_TYPE_MAX if not
10628 present. */
10629 static enum arm_reg_type
10630 arm_reg_parse_any (cp)
10631 char *cp;
10633 int i;
10635 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
10636 if (arm_reg_parse (&cp, all_reg_maps[i].htab) != FAIL)
10637 return (enum arm_reg_type) i;
10639 return REG_TYPE_MAX;
10642 void
10643 md_apply_fix3 (fixP, valP, seg)
10644 fixS * fixP;
10645 valueT * valP;
10646 segT seg;
10648 offsetT value = * valP;
10649 offsetT newval;
10650 unsigned int newimm;
10651 unsigned long temp;
10652 int sign;
10653 char * buf = fixP->fx_where + fixP->fx_frag->fr_literal;
10654 arm_fix_data * arm_data = (arm_fix_data *) fixP->tc_fix_data;
10656 assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
10658 /* Note whether this will delete the relocation. */
10659 #if 0
10660 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
10661 doesn't work fully.) */
10662 if ((fixP->fx_addsy == 0 || symbol_constant_p (fixP->fx_addsy))
10663 && !fixP->fx_pcrel)
10664 #else
10665 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
10666 #endif
10667 fixP->fx_done = 1;
10669 /* If this symbol is in a different section then we need to leave it for
10670 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
10671 so we have to undo it's effects here. */
10672 if (fixP->fx_pcrel)
10674 if (fixP->fx_addsy != NULL
10675 && S_IS_DEFINED (fixP->fx_addsy)
10676 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
10678 if (target_oabi
10679 && (fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
10680 || fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
10682 value = 0;
10683 else
10684 value += md_pcrel_from (fixP);
10688 /* Remember value for emit_reloc. */
10689 fixP->fx_addnumber = value;
10691 switch (fixP->fx_r_type)
10693 case BFD_RELOC_ARM_IMMEDIATE:
10694 newimm = validate_immediate (value);
10695 temp = md_chars_to_number (buf, INSN_SIZE);
10697 /* If the instruction will fail, see if we can fix things up by
10698 changing the opcode. */
10699 if (newimm == (unsigned int) FAIL
10700 && (newimm = negate_data_op (&temp, value)) == (unsigned int) FAIL)
10702 as_bad_where (fixP->fx_file, fixP->fx_line,
10703 _("invalid constant (%lx) after fixup"),
10704 (unsigned long) value);
10705 break;
10708 newimm |= (temp & 0xfffff000);
10709 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
10710 fixP->fx_done = 1;
10711 break;
10713 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
10715 unsigned int highpart = 0;
10716 unsigned int newinsn = 0xe1a00000; /* nop. */
10718 newimm = validate_immediate (value);
10719 temp = md_chars_to_number (buf, INSN_SIZE);
10721 /* If the instruction will fail, see if we can fix things up by
10722 changing the opcode. */
10723 if (newimm == (unsigned int) FAIL
10724 && (newimm = negate_data_op (& temp, value)) == (unsigned int) FAIL)
10726 /* No ? OK - try using two ADD instructions to generate
10727 the value. */
10728 newimm = validate_immediate_twopart (value, & highpart);
10730 /* Yes - then make sure that the second instruction is
10731 also an add. */
10732 if (newimm != (unsigned int) FAIL)
10733 newinsn = temp;
10734 /* Still No ? Try using a negated value. */
10735 else if ((newimm = validate_immediate_twopart (- value, & highpart)) != (unsigned int) FAIL)
10736 temp = newinsn = (temp & OPCODE_MASK) | OPCODE_SUB << DATA_OP_SHIFT;
10737 /* Otherwise - give up. */
10738 else
10740 as_bad_where (fixP->fx_file, fixP->fx_line,
10741 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
10742 (long) value);
10743 break;
10746 /* Replace the first operand in the 2nd instruction (which
10747 is the PC) with the destination register. We have
10748 already added in the PC in the first instruction and we
10749 do not want to do it again. */
10750 newinsn &= ~ 0xf0000;
10751 newinsn |= ((newinsn & 0x0f000) << 4);
10754 newimm |= (temp & 0xfffff000);
10755 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
10757 highpart |= (newinsn & 0xfffff000);
10758 md_number_to_chars (buf + INSN_SIZE, (valueT) highpart, INSN_SIZE);
10760 break;
10762 case BFD_RELOC_ARM_OFFSET_IMM:
10763 sign = value >= 0;
10765 if (value < 0)
10766 value = - value;
10768 if (validate_offset_imm (value, 0) == FAIL)
10770 as_bad_where (fixP->fx_file, fixP->fx_line,
10771 _("bad immediate value for offset (%ld)"),
10772 (long) value);
10773 break;
10776 newval = md_chars_to_number (buf, INSN_SIZE);
10777 newval &= 0xff7ff000;
10778 newval |= value | (sign ? INDEX_UP : 0);
10779 md_number_to_chars (buf, newval, INSN_SIZE);
10780 break;
10782 case BFD_RELOC_ARM_OFFSET_IMM8:
10783 case BFD_RELOC_ARM_HWLITERAL:
10784 sign = value >= 0;
10786 if (value < 0)
10787 value = - value;
10789 if (validate_offset_imm (value, 1) == FAIL)
10791 if (fixP->fx_r_type == BFD_RELOC_ARM_HWLITERAL)
10792 as_bad_where (fixP->fx_file, fixP->fx_line,
10793 _("invalid literal constant: pool needs to be closer"));
10794 else
10795 as_bad (_("bad immediate value for half-word offset (%ld)"),
10796 (long) value);
10797 break;
10800 newval = md_chars_to_number (buf, INSN_SIZE);
10801 newval &= 0xff7ff0f0;
10802 newval |= ((value >> 4) << 8) | (value & 0xf) | (sign ? INDEX_UP : 0);
10803 md_number_to_chars (buf, newval, INSN_SIZE);
10804 break;
10806 case BFD_RELOC_ARM_LITERAL:
10807 sign = value >= 0;
10809 if (value < 0)
10810 value = - value;
10812 if (validate_offset_imm (value, 0) == FAIL)
10814 as_bad_where (fixP->fx_file, fixP->fx_line,
10815 _("invalid literal constant: pool needs to be closer"));
10816 break;
10819 newval = md_chars_to_number (buf, INSN_SIZE);
10820 newval &= 0xff7ff000;
10821 newval |= value | (sign ? INDEX_UP : 0);
10822 md_number_to_chars (buf, newval, INSN_SIZE);
10823 break;
10825 case BFD_RELOC_ARM_SHIFT_IMM:
10826 newval = md_chars_to_number (buf, INSN_SIZE);
10827 if (((unsigned long) value) > 32
10828 || (value == 32
10829 && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60)))
10831 as_bad_where (fixP->fx_file, fixP->fx_line,
10832 _("shift expression is too large"));
10833 break;
10836 if (value == 0)
10837 /* Shifts of zero must be done as lsl. */
10838 newval &= ~0x60;
10839 else if (value == 32)
10840 value = 0;
10841 newval &= 0xfffff07f;
10842 newval |= (value & 0x1f) << 7;
10843 md_number_to_chars (buf, newval, INSN_SIZE);
10844 break;
10846 case BFD_RELOC_ARM_SWI:
10847 if (arm_data->thumb_mode)
10849 if (((unsigned long) value) > 0xff)
10850 as_bad_where (fixP->fx_file, fixP->fx_line,
10851 _("invalid swi expression"));
10852 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xff00;
10853 newval |= value;
10854 md_number_to_chars (buf, newval, THUMB_SIZE);
10856 else
10858 if (((unsigned long) value) > 0x00ffffff)
10859 as_bad_where (fixP->fx_file, fixP->fx_line,
10860 _("invalid swi expression"));
10861 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
10862 newval |= value;
10863 md_number_to_chars (buf, newval, INSN_SIZE);
10865 break;
10867 case BFD_RELOC_ARM_MULTI:
10868 if (((unsigned long) value) > 0xffff)
10869 as_bad_where (fixP->fx_file, fixP->fx_line,
10870 _("invalid expression in load/store multiple"));
10871 newval = value | md_chars_to_number (buf, INSN_SIZE);
10872 md_number_to_chars (buf, newval, INSN_SIZE);
10873 break;
10875 case BFD_RELOC_ARM_PCREL_BRANCH:
10876 newval = md_chars_to_number (buf, INSN_SIZE);
10878 /* Sign-extend a 24-bit number. */
10879 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
10881 #ifdef OBJ_ELF
10882 if (! target_oabi)
10883 value = fixP->fx_offset;
10884 #endif
10886 /* We are going to store value (shifted right by two) in the
10887 instruction, in a 24 bit, signed field. Thus we need to check
10888 that none of the top 8 bits of the shifted value (top 7 bits of
10889 the unshifted, unsigned value) are set, or that they are all set. */
10890 if ((value & ~ ((offsetT) 0x1ffffff)) != 0
10891 && ((value & ~ ((offsetT) 0x1ffffff)) != ~ ((offsetT) 0x1ffffff)))
10893 #ifdef OBJ_ELF
10894 /* Normally we would be stuck at this point, since we cannot store
10895 the absolute address that is the destination of the branch in the
10896 24 bits of the branch instruction. If however, we happen to know
10897 that the destination of the branch is in the same section as the
10898 branch instruciton itself, then we can compute the relocation for
10899 ourselves and not have to bother the linker with it.
10901 FIXME: The tests for OBJ_ELF and ! target_oabi are only here
10902 because I have not worked out how to do this for OBJ_COFF or
10903 target_oabi. */
10904 if (! target_oabi
10905 && fixP->fx_addsy != NULL
10906 && S_IS_DEFINED (fixP->fx_addsy)
10907 && S_GET_SEGMENT (fixP->fx_addsy) == seg)
10909 /* Get pc relative value to go into the branch. */
10910 value = * valP;
10912 /* Permit a backward branch provided that enough bits
10913 are set. Allow a forwards branch, provided that
10914 enough bits are clear. */
10915 if ( (value & ~ ((offsetT) 0x1ffffff)) == ~ ((offsetT) 0x1ffffff)
10916 || (value & ~ ((offsetT) 0x1ffffff)) == 0)
10917 fixP->fx_done = 1;
10920 if (! fixP->fx_done)
10921 #endif
10922 as_bad_where (fixP->fx_file, fixP->fx_line,
10923 _("GAS can't handle same-section branch dest >= 0x04000000"));
10926 value >>= 2;
10927 value += SEXT24 (newval);
10929 if ( (value & ~ ((offsetT) 0xffffff)) != 0
10930 && ((value & ~ ((offsetT) 0xffffff)) != ~ ((offsetT) 0xffffff)))
10931 as_bad_where (fixP->fx_file, fixP->fx_line,
10932 _("out of range branch"));
10934 newval = (value & 0x00ffffff) | (newval & 0xff000000);
10935 md_number_to_chars (buf, newval, INSN_SIZE);
10936 break;
10938 case BFD_RELOC_ARM_PCREL_BLX:
10940 offsetT hbit;
10941 newval = md_chars_to_number (buf, INSN_SIZE);
10943 #ifdef OBJ_ELF
10944 if (! target_oabi)
10945 value = fixP->fx_offset;
10946 #endif
10947 hbit = (value >> 1) & 1;
10948 value = (value >> 2) & 0x00ffffff;
10949 value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
10950 newval = value | (newval & 0xfe000000) | (hbit << 24);
10951 md_number_to_chars (buf, newval, INSN_SIZE);
10953 break;
10955 case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch. */
10956 newval = md_chars_to_number (buf, THUMB_SIZE);
10958 addressT diff = (newval & 0xff) << 1;
10959 if (diff & 0x100)
10960 diff |= ~0xff;
10962 value += diff;
10963 if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
10964 as_bad_where (fixP->fx_file, fixP->fx_line,
10965 _("branch out of range"));
10966 newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
10968 md_number_to_chars (buf, newval, THUMB_SIZE);
10969 break;
10971 case BFD_RELOC_THUMB_PCREL_BRANCH12: /* Unconditional branch. */
10972 newval = md_chars_to_number (buf, THUMB_SIZE);
10974 addressT diff = (newval & 0x7ff) << 1;
10975 if (diff & 0x800)
10976 diff |= ~0x7ff;
10978 value += diff;
10979 if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
10980 as_bad_where (fixP->fx_file, fixP->fx_line,
10981 _("branch out of range"));
10982 newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
10984 md_number_to_chars (buf, newval, THUMB_SIZE);
10985 break;
10987 case BFD_RELOC_THUMB_PCREL_BLX:
10988 case BFD_RELOC_THUMB_PCREL_BRANCH23:
10990 offsetT newval2;
10991 addressT diff;
10993 newval = md_chars_to_number (buf, THUMB_SIZE);
10994 newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
10995 diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
10996 if (diff & 0x400000)
10997 diff |= ~0x3fffff;
10998 #ifdef OBJ_ELF
10999 value = fixP->fx_offset;
11000 #endif
11001 value += diff;
11003 if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
11004 as_bad_where (fixP->fx_file, fixP->fx_line,
11005 _("branch with link out of range"));
11007 newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12);
11008 newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
11009 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
11010 /* For a BLX instruction, make sure that the relocation is rounded up
11011 to a word boundary. This follows the semantics of the instruction
11012 which specifies that bit 1 of the target address will come from bit
11013 1 of the base address. */
11014 newval2 = (newval2 + 1) & ~ 1;
11015 md_number_to_chars (buf, newval, THUMB_SIZE);
11016 md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
11018 break;
11020 case BFD_RELOC_8:
11021 if (fixP->fx_done || fixP->fx_pcrel)
11022 md_number_to_chars (buf, value, 1);
11023 #ifdef OBJ_ELF
11024 else if (!target_oabi)
11026 value = fixP->fx_offset;
11027 md_number_to_chars (buf, value, 1);
11029 #endif
11030 break;
11032 case BFD_RELOC_16:
11033 if (fixP->fx_done || fixP->fx_pcrel)
11034 md_number_to_chars (buf, value, 2);
11035 #ifdef OBJ_ELF
11036 else if (!target_oabi)
11038 value = fixP->fx_offset;
11039 md_number_to_chars (buf, value, 2);
11041 #endif
11042 break;
11044 #ifdef OBJ_ELF
11045 case BFD_RELOC_ARM_GOT32:
11046 case BFD_RELOC_ARM_GOTOFF:
11047 md_number_to_chars (buf, 0, 4);
11048 break;
11049 #endif
11051 case BFD_RELOC_RVA:
11052 case BFD_RELOC_32:
11053 if (fixP->fx_done || fixP->fx_pcrel)
11054 md_number_to_chars (buf, value, 4);
11055 #ifdef OBJ_ELF
11056 else if (!target_oabi)
11058 value = fixP->fx_offset;
11059 md_number_to_chars (buf, value, 4);
11061 #endif
11062 break;
11064 #ifdef OBJ_ELF
11065 case BFD_RELOC_ARM_PLT32:
11066 /* It appears the instruction is fully prepared at this point. */
11067 break;
11068 #endif
11070 case BFD_RELOC_ARM_CP_OFF_IMM:
11071 sign = value >= 0;
11072 if (value < -1023 || value > 1023 || (value & 3))
11073 as_bad_where (fixP->fx_file, fixP->fx_line,
11074 _("illegal value for co-processor offset"));
11075 if (value < 0)
11076 value = -value;
11077 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
11078 newval |= (value >> 2) | (sign ? INDEX_UP : 0);
11079 md_number_to_chars (buf, newval, INSN_SIZE);
11080 break;
11082 case BFD_RELOC_ARM_CP_OFF_IMM_S2:
11083 sign = value >= 0;
11084 if (value < -255 || value > 255)
11085 as_bad_where (fixP->fx_file, fixP->fx_line,
11086 _("Illegal value for co-processor offset"));
11087 if (value < 0)
11088 value = -value;
11089 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
11090 newval |= value | (sign ? INDEX_UP : 0);
11091 md_number_to_chars (buf, newval , INSN_SIZE);
11092 break;
11094 case BFD_RELOC_ARM_THUMB_OFFSET:
11095 newval = md_chars_to_number (buf, THUMB_SIZE);
11096 /* Exactly what ranges, and where the offset is inserted depends
11097 on the type of instruction, we can establish this from the
11098 top 4 bits. */
11099 switch (newval >> 12)
11101 case 4: /* PC load. */
11102 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
11103 forced to zero for these loads, so we will need to round
11104 up the offset if the instruction address is not word
11105 aligned (since the final address produced must be, and
11106 we can only describe word-aligned immediate offsets). */
11108 if ((fixP->fx_frag->fr_address + fixP->fx_where + value) & 3)
11109 as_bad_where (fixP->fx_file, fixP->fx_line,
11110 _("invalid offset, target not word aligned (0x%08X)"),
11111 (unsigned int) (fixP->fx_frag->fr_address
11112 + fixP->fx_where + value));
11114 if ((value + 2) & ~0x3fe)
11115 as_bad_where (fixP->fx_file, fixP->fx_line,
11116 _("invalid offset, value too big (0x%08lX)"),
11117 (long) value);
11119 /* Round up, since pc will be rounded down. */
11120 newval |= (value + 2) >> 2;
11121 break;
11123 case 9: /* SP load/store. */
11124 if (value & ~0x3fc)
11125 as_bad_where (fixP->fx_file, fixP->fx_line,
11126 _("invalid offset, value too big (0x%08lX)"),
11127 (long) value);
11128 newval |= value >> 2;
11129 break;
11131 case 6: /* Word load/store. */
11132 if (value & ~0x7c)
11133 as_bad_where (fixP->fx_file, fixP->fx_line,
11134 _("invalid offset, value too big (0x%08lX)"),
11135 (long) value);
11136 newval |= value << 4; /* 6 - 2. */
11137 break;
11139 case 7: /* Byte load/store. */
11140 if (value & ~0x1f)
11141 as_bad_where (fixP->fx_file, fixP->fx_line,
11142 _("invalid offset, value too big (0x%08lX)"),
11143 (long) value);
11144 newval |= value << 6;
11145 break;
11147 case 8: /* Halfword load/store. */
11148 if (value & ~0x3e)
11149 as_bad_where (fixP->fx_file, fixP->fx_line,
11150 _("invalid offset, value too big (0x%08lX)"),
11151 (long) value);
11152 newval |= value << 5; /* 6 - 1. */
11153 break;
11155 default:
11156 as_bad_where (fixP->fx_file, fixP->fx_line,
11157 "Unable to process relocation for thumb opcode: %lx",
11158 (unsigned long) newval);
11159 break;
11161 md_number_to_chars (buf, newval, THUMB_SIZE);
11162 break;
11164 case BFD_RELOC_ARM_THUMB_ADD:
11165 /* This is a complicated relocation, since we use it for all of
11166 the following immediate relocations:
11168 3bit ADD/SUB
11169 8bit ADD/SUB
11170 9bit ADD/SUB SP word-aligned
11171 10bit ADD PC/SP word-aligned
11173 The type of instruction being processed is encoded in the
11174 instruction field:
11176 0x8000 SUB
11177 0x00F0 Rd
11178 0x000F Rs
11180 newval = md_chars_to_number (buf, THUMB_SIZE);
11182 int rd = (newval >> 4) & 0xf;
11183 int rs = newval & 0xf;
11184 int subtract = newval & 0x8000;
11186 if (rd == REG_SP)
11188 if (value & ~0x1fc)
11189 as_bad_where (fixP->fx_file, fixP->fx_line,
11190 _("invalid immediate for stack address calculation"));
11191 newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
11192 newval |= value >> 2;
11194 else if (rs == REG_PC || rs == REG_SP)
11196 if (subtract ||
11197 value & ~0x3fc)
11198 as_bad_where (fixP->fx_file, fixP->fx_line,
11199 _("invalid immediate for address calculation (value = 0x%08lX)"),
11200 (unsigned long) value);
11201 newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP);
11202 newval |= rd << 8;
11203 newval |= value >> 2;
11205 else if (rs == rd)
11207 if (value & ~0xff)
11208 as_bad_where (fixP->fx_file, fixP->fx_line,
11209 _("invalid 8bit immediate"));
11210 newval = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
11211 newval |= (rd << 8) | value;
11213 else
11215 if (value & ~0x7)
11216 as_bad_where (fixP->fx_file, fixP->fx_line,
11217 _("invalid 3bit immediate"));
11218 newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
11219 newval |= rd | (rs << 3) | (value << 6);
11222 md_number_to_chars (buf, newval, THUMB_SIZE);
11223 break;
11225 case BFD_RELOC_ARM_THUMB_IMM:
11226 newval = md_chars_to_number (buf, THUMB_SIZE);
11227 switch (newval >> 11)
11229 case 0x04: /* 8bit immediate MOV. */
11230 case 0x05: /* 8bit immediate CMP. */
11231 if (value < 0 || value > 255)
11232 as_bad_where (fixP->fx_file, fixP->fx_line,
11233 _("invalid immediate: %ld is too large"),
11234 (long) value);
11235 newval |= value;
11236 break;
11238 default:
11239 abort ();
11241 md_number_to_chars (buf, newval, THUMB_SIZE);
11242 break;
11244 case BFD_RELOC_ARM_THUMB_SHIFT:
11245 /* 5bit shift value (0..31). */
11246 if (value < 0 || value > 31)
11247 as_bad_where (fixP->fx_file, fixP->fx_line,
11248 _("illegal Thumb shift value: %ld"), (long) value);
11249 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xf03f;
11250 newval |= value << 6;
11251 md_number_to_chars (buf, newval, THUMB_SIZE);
11252 break;
11254 case BFD_RELOC_VTABLE_INHERIT:
11255 case BFD_RELOC_VTABLE_ENTRY:
11256 fixP->fx_done = 0;
11257 return;
11259 case BFD_RELOC_NONE:
11260 default:
11261 as_bad_where (fixP->fx_file, fixP->fx_line,
11262 _("bad relocation fixup type (%d)"), fixP->fx_r_type);
11266 /* Translate internal representation of relocation info to BFD target
11267 format. */
11269 arelent *
11270 tc_gen_reloc (section, fixp)
11271 asection * section ATTRIBUTE_UNUSED;
11272 fixS * fixp;
11274 arelent * reloc;
11275 bfd_reloc_code_real_type code;
11277 reloc = (arelent *) xmalloc (sizeof (arelent));
11279 reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
11280 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
11281 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
11283 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
11284 #ifndef OBJ_ELF
11285 if (fixp->fx_pcrel == 0)
11286 reloc->addend = fixp->fx_offset;
11287 else
11288 reloc->addend = fixp->fx_offset = reloc->address;
11289 #else /* OBJ_ELF */
11290 reloc->addend = fixp->fx_offset;
11291 #endif
11293 switch (fixp->fx_r_type)
11295 case BFD_RELOC_8:
11296 if (fixp->fx_pcrel)
11298 code = BFD_RELOC_8_PCREL;
11299 break;
11302 case BFD_RELOC_16:
11303 if (fixp->fx_pcrel)
11305 code = BFD_RELOC_16_PCREL;
11306 break;
11309 case BFD_RELOC_32:
11310 if (fixp->fx_pcrel)
11312 code = BFD_RELOC_32_PCREL;
11313 break;
11316 case BFD_RELOC_ARM_PCREL_BRANCH:
11317 case BFD_RELOC_ARM_PCREL_BLX:
11318 case BFD_RELOC_RVA:
11319 case BFD_RELOC_THUMB_PCREL_BRANCH9:
11320 case BFD_RELOC_THUMB_PCREL_BRANCH12:
11321 case BFD_RELOC_THUMB_PCREL_BRANCH23:
11322 case BFD_RELOC_THUMB_PCREL_BLX:
11323 case BFD_RELOC_VTABLE_ENTRY:
11324 case BFD_RELOC_VTABLE_INHERIT:
11325 code = fixp->fx_r_type;
11326 break;
11328 case BFD_RELOC_ARM_LITERAL:
11329 case BFD_RELOC_ARM_HWLITERAL:
11330 /* If this is called then the a literal has
11331 been referenced across a section boundary. */
11332 as_bad_where (fixp->fx_file, fixp->fx_line,
11333 _("literal referenced across section boundary"));
11334 return NULL;
11336 #ifdef OBJ_ELF
11337 case BFD_RELOC_ARM_GOT32:
11338 case BFD_RELOC_ARM_GOTOFF:
11339 case BFD_RELOC_ARM_PLT32:
11340 code = fixp->fx_r_type;
11341 break;
11342 #endif
11344 case BFD_RELOC_ARM_IMMEDIATE:
11345 as_bad_where (fixp->fx_file, fixp->fx_line,
11346 _("internal relocation (type: IMMEDIATE) not fixed up"));
11347 return NULL;
11349 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
11350 as_bad_where (fixp->fx_file, fixp->fx_line,
11351 _("ADRL used for a symbol not defined in the same file"));
11352 return NULL;
11354 case BFD_RELOC_ARM_OFFSET_IMM:
11355 as_bad_where (fixp->fx_file, fixp->fx_line,
11356 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
11357 return NULL;
11359 default:
11361 char * type;
11363 switch (fixp->fx_r_type)
11365 case BFD_RELOC_ARM_OFFSET_IMM8: type = "OFFSET_IMM8"; break;
11366 case BFD_RELOC_ARM_SHIFT_IMM: type = "SHIFT_IMM"; break;
11367 case BFD_RELOC_ARM_SWI: type = "SWI"; break;
11368 case BFD_RELOC_ARM_MULTI: type = "MULTI"; break;
11369 case BFD_RELOC_ARM_CP_OFF_IMM: type = "CP_OFF_IMM"; break;
11370 case BFD_RELOC_ARM_THUMB_ADD: type = "THUMB_ADD"; break;
11371 case BFD_RELOC_ARM_THUMB_SHIFT: type = "THUMB_SHIFT"; break;
11372 case BFD_RELOC_ARM_THUMB_IMM: type = "THUMB_IMM"; break;
11373 case BFD_RELOC_ARM_THUMB_OFFSET: type = "THUMB_OFFSET"; break;
11374 default: type = _("<unknown>"); break;
11376 as_bad_where (fixp->fx_file, fixp->fx_line,
11377 _("cannot represent %s relocation in this object file format"),
11378 type);
11379 return NULL;
11383 #ifdef OBJ_ELF
11384 if ((code == BFD_RELOC_32_PCREL || code == BFD_RELOC_32)
11385 && GOT_symbol
11386 && fixp->fx_addsy == GOT_symbol)
11388 code = BFD_RELOC_ARM_GOTPC;
11389 reloc->addend = fixp->fx_offset = reloc->address;
11391 #endif
11393 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
11395 if (reloc->howto == NULL)
11397 as_bad_where (fixp->fx_file, fixp->fx_line,
11398 _("cannot represent %s relocation in this object file format"),
11399 bfd_get_reloc_code_name (code));
11400 return NULL;
11403 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
11404 vtable entry to be used in the relocation's section offset. */
11405 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
11406 reloc->address = fixp->fx_offset;
11408 return reloc;
11412 md_estimate_size_before_relax (fragP, segtype)
11413 fragS * fragP ATTRIBUTE_UNUSED;
11414 segT segtype ATTRIBUTE_UNUSED;
11416 as_fatal (_("md_estimate_size_before_relax\n"));
11417 return 1;
11420 static void
11421 output_inst (str)
11422 const char *str;
11424 char * to = NULL;
11426 if (inst.error)
11428 as_bad ("%s -- `%s'", inst.error, str);
11429 return;
11432 to = frag_more (inst.size);
11434 if (thumb_mode && (inst.size > THUMB_SIZE))
11436 assert (inst.size == (2 * THUMB_SIZE));
11437 md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE);
11438 md_number_to_chars (to + THUMB_SIZE, inst.instruction, THUMB_SIZE);
11440 else if (inst.size > INSN_SIZE)
11442 assert (inst.size == (2 * INSN_SIZE));
11443 md_number_to_chars (to, inst.instruction, INSN_SIZE);
11444 md_number_to_chars (to + INSN_SIZE, inst.instruction, INSN_SIZE);
11446 else
11447 md_number_to_chars (to, inst.instruction, inst.size);
11449 if (inst.reloc.type != BFD_RELOC_NONE)
11450 fix_new_arm (frag_now, to - frag_now->fr_literal,
11451 inst.size, & inst.reloc.exp, inst.reloc.pc_rel,
11452 inst.reloc.type);
11454 #ifdef OBJ_ELF
11455 dwarf2_emit_insn (inst.size);
11456 #endif
11459 void
11460 md_assemble (str)
11461 char * str;
11463 char c;
11464 char *p;
11465 char *start;
11467 /* Align the instruction.
11468 This may not be the right thing to do but ... */
11469 #if 0
11470 arm_align (2, 0);
11471 #endif
11473 /* Align the previous label if needed. */
11474 if (last_label_seen != NULL)
11476 symbol_set_frag (last_label_seen, frag_now);
11477 S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ());
11478 S_SET_SEGMENT (last_label_seen, now_seg);
11481 memset (&inst, '\0', sizeof (inst));
11482 inst.reloc.type = BFD_RELOC_NONE;
11484 skip_whitespace (str);
11486 /* Scan up to the end of the op-code, which must end in white space or
11487 end of string. */
11488 for (start = p = str; *p != '\0'; p++)
11489 if (*p == ' ')
11490 break;
11492 if (p == str)
11494 as_bad (_("no operator -- statement `%s'\n"), str);
11495 return;
11498 if (thumb_mode)
11500 const struct thumb_opcode * opcode;
11502 c = *p;
11503 *p = '\0';
11504 opcode = (const struct thumb_opcode *) hash_find (arm_tops_hsh, str);
11505 *p = c;
11507 if (opcode)
11509 /* Check that this instruction is supported for this CPU. */
11510 if (thumb_mode == 1 && (opcode->variant & cpu_variant) == 0)
11512 as_bad (_("selected processor does not support `%s'"), str);
11513 return;
11516 inst.instruction = opcode->value;
11517 inst.size = opcode->size;
11518 (*opcode->parms) (p);
11519 output_inst (str);
11520 return;
11523 else
11525 const struct asm_opcode * opcode;
11527 c = *p;
11528 *p = '\0';
11529 opcode = (const struct asm_opcode *) hash_find (arm_ops_hsh, str);
11530 *p = c;
11532 if (opcode)
11534 /* Check that this instruction is supported for this CPU. */
11535 if ((opcode->variant & cpu_variant) == 0)
11537 as_bad (_("selected processor does not support `%s'"), str);
11538 return;
11541 inst.instruction = opcode->value;
11542 inst.size = INSN_SIZE;
11543 (*opcode->parms) (p);
11544 output_inst (str);
11545 return;
11549 /* It wasn't an instruction, but it might be a register alias of the form
11550 alias .req reg. */
11551 if (create_register_alias (str, p))
11552 return;
11554 as_bad (_("bad instruction `%s'"), start);
11557 /* md_parse_option
11558 Invocation line includes a switch not recognized by the base assembler.
11559 See if it's a processor-specific option.
11561 This routine is somewhat complicated by the need for backwards
11562 compatibility (since older releases of gcc can't be changed).
11563 The new options try to make the interface as compatible as
11564 possible with GCC.
11566 New options (supported) are:
11568 -mcpu=<cpu name> Assemble for selected processor
11569 -march=<architecture name> Assemble for selected architecture
11570 -mfpu=<fpu architecture> Assemble for selected FPU.
11571 -EB/-mbig-endian Big-endian
11572 -EL/-mlittle-endian Little-endian
11573 -k Generate PIC code
11574 -mthumb Start in Thumb mode
11575 -mthumb-interwork Code supports ARM/Thumb interworking
11577 For now we will also provide support for:
11579 -mapcs-32 32-bit Program counter
11580 -mapcs-26 26-bit Program counter
11581 -macps-float Floats passed in FP registers
11582 -mapcs-reentrant Reentrant code
11583 -matpcs
11584 (sometime these will probably be replaced with -mapcs=<list of options>
11585 and -matpcs=<list of options>)
11587 The remaining options are only supported for back-wards compatibility.
11588 Cpu variants, the arm part is optional:
11589 -m[arm]1 Currently not supported.
11590 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
11591 -m[arm]3 Arm 3 processor
11592 -m[arm]6[xx], Arm 6 processors
11593 -m[arm]7[xx][t][[d]m] Arm 7 processors
11594 -m[arm]8[10] Arm 8 processors
11595 -m[arm]9[20][tdmi] Arm 9 processors
11596 -mstrongarm[110[0]] StrongARM processors
11597 -mxscale XScale processors
11598 -m[arm]v[2345[t[e]]] Arm architectures
11599 -mall All (except the ARM1)
11600 FP variants:
11601 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
11602 -mfpe-old (No float load/store multiples)
11603 -mvfpxd VFP Single precision
11604 -mvfp All VFP
11605 -mno-fpu Disable all floating point instructions
11607 The following CPU names are recognized:
11608 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
11609 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
11610 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
11611 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
11612 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
11613 arm10t arm10e, arm1020t, arm1020e, arm10200e,
11614 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
11618 const char * md_shortopts = "m:k";
11620 #ifdef ARM_BI_ENDIAN
11621 #define OPTION_EB (OPTION_MD_BASE + 0)
11622 #define OPTION_EL (OPTION_MD_BASE + 1)
11623 #else
11624 #if TARGET_BYTES_BIG_ENDIAN
11625 #define OPTION_EB (OPTION_MD_BASE + 0)
11626 #else
11627 #define OPTION_EL (OPTION_MD_BASE + 1)
11628 #endif
11629 #endif
11631 struct option md_longopts[] =
11633 #ifdef OPTION_EB
11634 {"EB", no_argument, NULL, OPTION_EB},
11635 #endif
11636 #ifdef OPTION_EL
11637 {"EL", no_argument, NULL, OPTION_EL},
11638 #endif
11639 {NULL, no_argument, NULL, 0}
11642 size_t md_longopts_size = sizeof (md_longopts);
11644 struct arm_option_table
11646 char *option; /* Option name to match. */
11647 char *help; /* Help information. */
11648 int *var; /* Variable to change. */
11649 int value; /* What to change it to. */
11650 char *deprecated; /* If non-null, print this message. */
11653 struct arm_option_table arm_opts[] =
11655 {"k", N_("generate PIC code"), &pic_code, 1, NULL},
11656 {"mthumb", N_("assemble Thumb code"), &thumb_mode, 1, NULL},
11657 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
11658 &support_interwork, 1, NULL},
11659 {"moabi", N_("use old ABI (ELF only)"), &target_oabi, 1, NULL},
11660 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26, 0, NULL},
11661 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26, 1, NULL},
11662 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float,
11663 1, NULL},
11664 {"mapcs-reentrant", N_("re-entrant code"), &pic_code, 1, NULL},
11665 {"matpcs", N_("code is ATPCS conformant"), &atpcs, 1, NULL},
11666 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian, 1, NULL},
11667 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian, 1,
11668 NULL},
11670 /* These are recognized by the assembler, but have no affect on code. */
11671 {"mapcs-frame", N_("use frame pointer"), NULL, 0, NULL},
11672 {"mapcs-stack-check", N_("use stack size checking"), NULL, 0, NULL},
11674 /* DON'T add any new processors to this list -- we want the whole list
11675 to go away... Add them to the processors table instead. */
11676 {"marm1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
11677 {"m1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
11678 {"marm2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
11679 {"m2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
11680 {"marm250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
11681 {"m250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
11682 {"marm3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
11683 {"m3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
11684 {"marm6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
11685 {"m6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
11686 {"marm600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
11687 {"m600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
11688 {"marm610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
11689 {"m610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
11690 {"marm620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
11691 {"m620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
11692 {"marm7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
11693 {"m7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
11694 {"marm70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
11695 {"m70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
11696 {"marm700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
11697 {"m700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
11698 {"marm700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
11699 {"m700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
11700 {"marm710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
11701 {"m710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
11702 {"marm710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
11703 {"m710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
11704 {"marm720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
11705 {"m720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
11706 {"marm7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
11707 {"m7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
11708 {"marm7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
11709 {"m7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
11710 {"marm7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
11711 {"m7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
11712 {"marm7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
11713 {"m7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
11714 {"marm7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
11715 {"m7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
11716 {"marm7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
11717 {"m7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
11718 {"marm7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
11719 {"m7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
11720 {"marm7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
11721 {"m7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
11722 {"marm7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
11723 {"m7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
11724 {"marm7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
11725 {"m7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
11726 {"marm710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
11727 {"m710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
11728 {"marm720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
11729 {"m720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
11730 {"marm740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
11731 {"m740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
11732 {"marm8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
11733 {"m8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
11734 {"marm810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
11735 {"m810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
11736 {"marm9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
11737 {"m9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
11738 {"marm9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
11739 {"m9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
11740 {"marm920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
11741 {"m920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
11742 {"marm940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
11743 {"m940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
11744 {"mstrongarm", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=strongarm")},
11745 {"mstrongarm110", NULL, &legacy_cpu, ARM_ARCH_V4,
11746 N_("use -mcpu=strongarm110")},
11747 {"mstrongarm1100", NULL, &legacy_cpu, ARM_ARCH_V4,
11748 N_("use -mcpu=strongarm1100")},
11749 {"mstrongarm1110", NULL, &legacy_cpu, ARM_ARCH_V4,
11750 N_("use -mcpu=strongarm1110")},
11751 {"mxscale", NULL, &legacy_cpu, ARM_ARCH_XSCALE, N_("use -mcpu=xscale")},
11752 {"miwmmxt", NULL, &legacy_cpu, ARM_ARCH_IWMMXT, N_("use -mcpu=iwmmxt")},
11753 {"mall", NULL, &legacy_cpu, ARM_ANY, N_("use -mcpu=all")},
11755 /* Architecture variants -- don't add any more to this list either. */
11756 {"mv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
11757 {"marmv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
11758 {"mv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
11759 {"marmv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
11760 {"mv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
11761 {"marmv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
11762 {"mv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
11763 {"marmv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
11764 {"mv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
11765 {"marmv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
11766 {"mv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
11767 {"marmv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
11768 {"mv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
11769 {"marmv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
11770 {"mv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
11771 {"marmv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
11772 {"mv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
11773 {"marmv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
11775 /* Floating point variants -- don't add any more to this list either. */
11776 {"mfpe-old", NULL, &legacy_fpu, FPU_ARCH_FPE, N_("use -mfpu=fpe")},
11777 {"mfpa10", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa10")},
11778 {"mfpa11", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa11")},
11779 {"mno-fpu", NULL, &legacy_fpu, 0,
11780 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
11782 {NULL, NULL, NULL, 0, NULL}
11785 struct arm_cpu_option_table
11787 char *name;
11788 int value;
11789 /* For some CPUs we assume an FPU unless the user explicitly sets
11790 -mfpu=... */
11791 int default_fpu;
11794 /* This list should, at a minimum, contain all the cpu names
11795 recognized by GCC. */
11796 static struct arm_cpu_option_table arm_cpus[] =
11798 {"all", ARM_ANY, FPU_ARCH_FPA},
11799 {"arm1", ARM_ARCH_V1, FPU_ARCH_FPA},
11800 {"arm2", ARM_ARCH_V2, FPU_ARCH_FPA},
11801 {"arm250", ARM_ARCH_V2S, FPU_ARCH_FPA},
11802 {"arm3", ARM_ARCH_V2S, FPU_ARCH_FPA},
11803 {"arm6", ARM_ARCH_V3, FPU_ARCH_FPA},
11804 {"arm60", ARM_ARCH_V3, FPU_ARCH_FPA},
11805 {"arm600", ARM_ARCH_V3, FPU_ARCH_FPA},
11806 {"arm610", ARM_ARCH_V3, FPU_ARCH_FPA},
11807 {"arm620", ARM_ARCH_V3, FPU_ARCH_FPA},
11808 {"arm7", ARM_ARCH_V3, FPU_ARCH_FPA},
11809 {"arm7m", ARM_ARCH_V3M, FPU_ARCH_FPA},
11810 {"arm7d", ARM_ARCH_V3, FPU_ARCH_FPA},
11811 {"arm7dm", ARM_ARCH_V3M, FPU_ARCH_FPA},
11812 {"arm7di", ARM_ARCH_V3, FPU_ARCH_FPA},
11813 {"arm7dmi", ARM_ARCH_V3M, FPU_ARCH_FPA},
11814 {"arm70", ARM_ARCH_V3, FPU_ARCH_FPA},
11815 {"arm700", ARM_ARCH_V3, FPU_ARCH_FPA},
11816 {"arm700i", ARM_ARCH_V3, FPU_ARCH_FPA},
11817 {"arm710", ARM_ARCH_V3, FPU_ARCH_FPA},
11818 {"arm710t", ARM_ARCH_V4T, FPU_ARCH_FPA},
11819 {"arm720", ARM_ARCH_V3, FPU_ARCH_FPA},
11820 {"arm720t", ARM_ARCH_V4T, FPU_ARCH_FPA},
11821 {"arm740t", ARM_ARCH_V4T, FPU_ARCH_FPA},
11822 {"arm710c", ARM_ARCH_V3, FPU_ARCH_FPA},
11823 {"arm7100", ARM_ARCH_V3, FPU_ARCH_FPA},
11824 {"arm7500", ARM_ARCH_V3, FPU_ARCH_FPA},
11825 {"arm7500fe", ARM_ARCH_V3, FPU_ARCH_FPA},
11826 {"arm7t", ARM_ARCH_V4T, FPU_ARCH_FPA},
11827 {"arm7tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
11828 {"arm8", ARM_ARCH_V4, FPU_ARCH_FPA},
11829 {"arm810", ARM_ARCH_V4, FPU_ARCH_FPA},
11830 {"strongarm", ARM_ARCH_V4, FPU_ARCH_FPA},
11831 {"strongarm1", ARM_ARCH_V4, FPU_ARCH_FPA},
11832 {"strongarm110", ARM_ARCH_V4, FPU_ARCH_FPA},
11833 {"strongarm1100", ARM_ARCH_V4, FPU_ARCH_FPA},
11834 {"strongarm1110", ARM_ARCH_V4, FPU_ARCH_FPA},
11835 {"arm9", ARM_ARCH_V4T, FPU_ARCH_FPA},
11836 {"arm920", ARM_ARCH_V4T, FPU_ARCH_FPA},
11837 {"arm920t", ARM_ARCH_V4T, FPU_ARCH_FPA},
11838 {"arm922t", ARM_ARCH_V4T, FPU_ARCH_FPA},
11839 {"arm940t", ARM_ARCH_V4T, FPU_ARCH_FPA},
11840 {"arm9tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
11841 /* For V5 or later processors we default to using VFP; but the user
11842 should really set the FPU type explicitly. */
11843 {"arm9e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
11844 {"arm9e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
11845 {"arm926ej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
11846 {"arm946e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
11847 {"arm946e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
11848 {"arm966e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
11849 {"arm966e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
11850 {"arm10t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
11851 {"arm10e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
11852 {"arm1020", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
11853 {"arm1020t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
11854 {"arm1020e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
11855 /* ??? XSCALE is really an architecture. */
11856 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
11857 /* ??? iwmmxt is not a processor. */
11858 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP_V2},
11859 {"i80200", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
11860 /* Maverick */
11861 {"ep9312", ARM_ARCH_V4T | ARM_CEXT_MAVERICK, FPU_NONE},
11862 {NULL, 0, 0}
11865 struct arm_arch_option_table
11867 char *name;
11868 int value;
11869 int default_fpu;
11872 /* This list should, at a minimum, contain all the architecture names
11873 recognized by GCC. */
11874 static struct arm_arch_option_table arm_archs[] =
11876 {"all", ARM_ANY, FPU_ARCH_FPA},
11877 {"armv1", ARM_ARCH_V1, FPU_ARCH_FPA},
11878 {"armv2", ARM_ARCH_V2, FPU_ARCH_FPA},
11879 {"armv2a", ARM_ARCH_V2S, FPU_ARCH_FPA},
11880 {"armv2s", ARM_ARCH_V2S, FPU_ARCH_FPA},
11881 {"armv3", ARM_ARCH_V3, FPU_ARCH_FPA},
11882 {"armv3m", ARM_ARCH_V3M, FPU_ARCH_FPA},
11883 {"armv4", ARM_ARCH_V4, FPU_ARCH_FPA},
11884 {"armv4xm", ARM_ARCH_V4xM, FPU_ARCH_FPA},
11885 {"armv4t", ARM_ARCH_V4T, FPU_ARCH_FPA},
11886 {"armv4txm", ARM_ARCH_V4TxM, FPU_ARCH_FPA},
11887 {"armv5", ARM_ARCH_V5, FPU_ARCH_VFP},
11888 {"armv5t", ARM_ARCH_V5T, FPU_ARCH_VFP},
11889 {"armv5txm", ARM_ARCH_V5TxM, FPU_ARCH_VFP},
11890 {"armv5te", ARM_ARCH_V5TE, FPU_ARCH_VFP},
11891 {"armv5texp", ARM_ARCH_V5TExP, FPU_ARCH_VFP},
11892 {"armv5tej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP},
11893 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP},
11894 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP},
11895 {NULL, 0, 0}
11898 /* ISA extensions in the co-processor space. */
11899 struct arm_arch_extension_table
11901 char *name;
11902 int value;
11905 static struct arm_arch_extension_table arm_extensions[] =
11907 {"maverick", ARM_CEXT_MAVERICK},
11908 {"xscale", ARM_CEXT_XSCALE},
11909 {"iwmmxt", ARM_CEXT_IWMMXT},
11910 {NULL, 0}
11913 struct arm_fpu_option_table
11915 char *name;
11916 int value;
11919 /* This list should, at a minimum, contain all the fpu names
11920 recognized by GCC. */
11921 static struct arm_fpu_option_table arm_fpus[] =
11923 {"softfpa", FPU_NONE},
11924 {"fpe", FPU_ARCH_FPE},
11925 {"fpe2", FPU_ARCH_FPE},
11926 {"fpe3", FPU_ARCH_FPA}, /* Third release supports LFM/SFM. */
11927 {"fpa", FPU_ARCH_FPA},
11928 {"fpa10", FPU_ARCH_FPA},
11929 {"fpa11", FPU_ARCH_FPA},
11930 {"arm7500fe", FPU_ARCH_FPA},
11931 {"softvfp", FPU_ARCH_VFP},
11932 {"softvfp+vfp", FPU_ARCH_VFP_V2},
11933 {"vfp", FPU_ARCH_VFP_V2},
11934 {"vfp9", FPU_ARCH_VFP_V2},
11935 {"vfp10", FPU_ARCH_VFP_V2},
11936 {"vfp10-r0", FPU_ARCH_VFP_V1},
11937 {"vfpxd", FPU_ARCH_VFP_V1xD},
11938 {"arm1020t", FPU_ARCH_VFP_V1},
11939 {"arm1020e", FPU_ARCH_VFP_V2},
11940 {NULL, 0}
11943 struct arm_long_option_table
11945 char *option; /* Substring to match. */
11946 char *help; /* Help information. */
11947 int (*func) PARAMS ((char *subopt)); /* Function to decode sub-option. */
11948 char *deprecated; /* If non-null, print this message. */
11951 static int
11952 arm_parse_extension (str, opt_p)
11953 char *str;
11954 int *opt_p;
11956 while (str != NULL && *str != 0)
11958 struct arm_arch_extension_table *opt;
11959 char *ext;
11960 int optlen;
11962 if (*str != '+')
11964 as_bad (_("invalid architectural extension"));
11965 return 0;
11968 str++;
11969 ext = strchr (str, '+');
11971 if (ext != NULL)
11972 optlen = ext - str;
11973 else
11974 optlen = strlen (str);
11976 if (optlen == 0)
11978 as_bad (_("missing architectural extension"));
11979 return 0;
11982 for (opt = arm_extensions; opt->name != NULL; opt++)
11983 if (strncmp (opt->name, str, optlen) == 0)
11985 *opt_p |= opt->value;
11986 break;
11989 if (opt->name == NULL)
11991 as_bad (_("unknown architectural extnsion `%s'"), str);
11992 return 0;
11995 str = ext;
11998 return 1;
12001 static int
12002 arm_parse_cpu (str)
12003 char *str;
12005 struct arm_cpu_option_table *opt;
12006 char *ext = strchr (str, '+');
12007 int optlen;
12009 if (ext != NULL)
12010 optlen = ext - str;
12011 else
12012 optlen = strlen (str);
12014 if (optlen == 0)
12016 as_bad (_("missing cpu name `%s'"), str);
12017 return 0;
12020 for (opt = arm_cpus; opt->name != NULL; opt++)
12021 if (strncmp (opt->name, str, optlen) == 0)
12023 mcpu_cpu_opt = opt->value;
12024 mcpu_fpu_opt = opt->default_fpu;
12026 if (ext != NULL)
12027 return arm_parse_extension (ext, &mcpu_cpu_opt);
12029 return 1;
12032 as_bad (_("unknown cpu `%s'"), str);
12033 return 0;
12036 static int
12037 arm_parse_arch (str)
12038 char *str;
12040 struct arm_arch_option_table *opt;
12041 char *ext = strchr (str, '+');
12042 int optlen;
12044 if (ext != NULL)
12045 optlen = ext - str;
12046 else
12047 optlen = strlen (str);
12049 if (optlen == 0)
12051 as_bad (_("missing architecture name `%s'"), str);
12052 return 0;
12056 for (opt = arm_archs; opt->name != NULL; opt++)
12057 if (strcmp (opt->name, str) == 0)
12059 march_cpu_opt = opt->value;
12060 march_fpu_opt = opt->default_fpu;
12062 if (ext != NULL)
12063 return arm_parse_extension (ext, &march_cpu_opt);
12065 return 1;
12068 as_bad (_("unknown architecture `%s'\n"), str);
12069 return 0;
12072 static int
12073 arm_parse_fpu (str)
12074 char *str;
12076 struct arm_fpu_option_table *opt;
12078 for (opt = arm_fpus; opt->name != NULL; opt++)
12079 if (strcmp (opt->name, str) == 0)
12081 mfpu_opt = opt->value;
12082 return 1;
12085 as_bad (_("unknown floating point format `%s'\n"), str);
12086 return 0;
12089 struct arm_long_option_table arm_long_opts[] =
12091 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
12092 arm_parse_cpu, NULL},
12093 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
12094 arm_parse_arch, NULL},
12095 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
12096 arm_parse_fpu, NULL},
12097 {NULL, NULL, 0, NULL}
12101 md_parse_option (c, arg)
12102 int c;
12103 char * arg;
12105 struct arm_option_table *opt;
12106 struct arm_long_option_table *lopt;
12108 switch (c)
12110 #ifdef OPTION_EB
12111 case OPTION_EB:
12112 target_big_endian = 1;
12113 break;
12114 #endif
12116 #ifdef OPTION_EL
12117 case OPTION_EL:
12118 target_big_endian = 0;
12119 break;
12120 #endif
12122 case 'a':
12123 /* Listing option. Just ignore these, we don't support additional
12124 ones. */
12125 return 0;
12127 default:
12128 for (opt = arm_opts; opt->option != NULL; opt++)
12130 if (c == opt->option[0]
12131 && ((arg == NULL && opt->option[1] == 0)
12132 || strcmp (arg, opt->option + 1) == 0))
12134 #if WARN_DEPRECATED
12135 /* If the option is deprecated, tell the user. */
12136 if (opt->deprecated != NULL)
12137 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c,
12138 arg ? arg : "", _(opt->deprecated));
12139 #endif
12141 if (opt->var != NULL)
12142 *opt->var = opt->value;
12144 return 1;
12148 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
12150 /* These options are expected to have an argument. */
12151 if (c == lopt->option[0]
12152 && arg != NULL
12153 && strncmp (arg, lopt->option + 1,
12154 strlen (lopt->option + 1)) == 0)
12156 #if WARN_DEPRECATED
12157 /* If the option is deprecated, tell the user. */
12158 if (lopt->deprecated != NULL)
12159 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c, arg,
12160 _(lopt->deprecated));
12161 #endif
12163 /* Call the sup-option parser. */
12164 return (*lopt->func)(arg + strlen (lopt->option) - 1);
12168 as_bad (_("unrecognized option `-%c%s'"), c, arg ? arg : "");
12169 return 0;
12172 return 1;
12175 void
12176 md_show_usage (fp)
12177 FILE * fp;
12179 struct arm_option_table *opt;
12180 struct arm_long_option_table *lopt;
12182 fprintf (fp, _(" ARM-specific assembler options:\n"));
12184 for (opt = arm_opts; opt->option != NULL; opt++)
12185 if (opt->help != NULL)
12186 fprintf (fp, " -%-23s%s\n", opt->option, _(opt->help));
12188 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
12189 if (lopt->help != NULL)
12190 fprintf (fp, " -%s%s\n", lopt->option, _(lopt->help));
12192 #ifdef OPTION_EB
12193 fprintf (fp, _("\
12194 -EB assemble code for a big-endian cpu\n"));
12195 #endif
12197 #ifdef OPTION_EL
12198 fprintf (fp, _("\
12199 -EL assemble code for a little-endian cpu\n"));
12200 #endif
12203 /* We need to be able to fix up arbitrary expressions in some statements.
12204 This is so that we can handle symbols that are an arbitrary distance from
12205 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
12206 which returns part of an address in a form which will be valid for
12207 a data instruction. We do this by pushing the expression into a symbol
12208 in the expr_section, and creating a fix for that. */
12210 static void
12211 fix_new_arm (frag, where, size, exp, pc_rel, reloc)
12212 fragS * frag;
12213 int where;
12214 short int size;
12215 expressionS * exp;
12216 int pc_rel;
12217 int reloc;
12219 fixS * new_fix;
12220 arm_fix_data * arm_data;
12222 switch (exp->X_op)
12224 case O_constant:
12225 case O_symbol:
12226 case O_add:
12227 case O_subtract:
12228 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
12229 break;
12231 default:
12232 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0,
12233 pc_rel, reloc);
12234 break;
12237 /* Mark whether the fix is to a THUMB instruction, or an ARM
12238 instruction. */
12239 arm_data = (arm_fix_data *) obstack_alloc (& notes, sizeof (arm_fix_data));
12240 new_fix->tc_fix_data = (PTR) arm_data;
12241 arm_data->thumb_mode = thumb_mode;
12243 return;
12246 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
12248 void
12249 cons_fix_new_arm (frag, where, size, exp)
12250 fragS * frag;
12251 int where;
12252 int size;
12253 expressionS * exp;
12255 bfd_reloc_code_real_type type;
12256 int pcrel = 0;
12258 /* Pick a reloc.
12259 FIXME: @@ Should look at CPU word size. */
12260 switch (size)
12262 case 1:
12263 type = BFD_RELOC_8;
12264 break;
12265 case 2:
12266 type = BFD_RELOC_16;
12267 break;
12268 case 4:
12269 default:
12270 type = BFD_RELOC_32;
12271 break;
12272 case 8:
12273 type = BFD_RELOC_64;
12274 break;
12277 fix_new_exp (frag, where, (int) size, exp, pcrel, type);
12280 /* A good place to do this, although this was probably not intended
12281 for this kind of use. We need to dump the literal pool before
12282 references are made to a null symbol pointer. */
12284 void
12285 arm_cleanup ()
12287 literal_pool * pool;
12289 for (pool = list_of_pools; pool; pool = pool->next)
12291 /* Put it at the end of the relevent section. */
12292 subseg_set (pool->section, pool->sub_section);
12293 s_ltorg (0);
12297 void
12298 arm_start_line_hook ()
12300 last_label_seen = NULL;
12303 void
12304 arm_frob_label (sym)
12305 symbolS * sym;
12307 last_label_seen = sym;
12309 ARM_SET_THUMB (sym, thumb_mode);
12311 #if defined OBJ_COFF || defined OBJ_ELF
12312 ARM_SET_INTERWORK (sym, support_interwork);
12313 #endif
12315 /* Note - do not allow local symbols (.Lxxx) to be labeled
12316 as Thumb functions. This is because these labels, whilst
12317 they exist inside Thumb code, are not the entry points for
12318 possible ARM->Thumb calls. Also, these labels can be used
12319 as part of a computed goto or switch statement. eg gcc
12320 can generate code that looks like this:
12322 ldr r2, [pc, .Laaa]
12323 lsl r3, r3, #2
12324 ldr r2, [r3, r2]
12325 mov pc, r2
12327 .Lbbb: .word .Lxxx
12328 .Lccc: .word .Lyyy
12329 ..etc...
12330 .Laaa: .word Lbbb
12332 The first instruction loads the address of the jump table.
12333 The second instruction converts a table index into a byte offset.
12334 The third instruction gets the jump address out of the table.
12335 The fourth instruction performs the jump.
12337 If the address stored at .Laaa is that of a symbol which has the
12338 Thumb_Func bit set, then the linker will arrange for this address
12339 to have the bottom bit set, which in turn would mean that the
12340 address computation performed by the third instruction would end
12341 up with the bottom bit set. Since the ARM is capable of unaligned
12342 word loads, the instruction would then load the incorrect address
12343 out of the jump table, and chaos would ensue. */
12344 if (label_is_thumb_function_name
12345 && (S_GET_NAME (sym)[0] != '.' || S_GET_NAME (sym)[1] != 'L')
12346 && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
12348 /* When the address of a Thumb function is taken the bottom
12349 bit of that address should be set. This will allow
12350 interworking between Arm and Thumb functions to work
12351 correctly. */
12353 THUMB_SET_FUNC (sym, 1);
12355 label_is_thumb_function_name = FALSE;
12359 /* Adjust the symbol table. This marks Thumb symbols as distinct from
12360 ARM ones. */
12362 void
12363 arm_adjust_symtab ()
12365 #ifdef OBJ_COFF
12366 symbolS * sym;
12368 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
12370 if (ARM_IS_THUMB (sym))
12372 if (THUMB_IS_FUNC (sym))
12374 /* Mark the symbol as a Thumb function. */
12375 if ( S_GET_STORAGE_CLASS (sym) == C_STAT
12376 || S_GET_STORAGE_CLASS (sym) == C_LABEL) /* This can happen! */
12377 S_SET_STORAGE_CLASS (sym, C_THUMBSTATFUNC);
12379 else if (S_GET_STORAGE_CLASS (sym) == C_EXT)
12380 S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC);
12381 else
12382 as_bad (_("%s: unexpected function type: %d"),
12383 S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym));
12385 else switch (S_GET_STORAGE_CLASS (sym))
12387 case C_EXT:
12388 S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
12389 break;
12390 case C_STAT:
12391 S_SET_STORAGE_CLASS (sym, C_THUMBSTAT);
12392 break;
12393 case C_LABEL:
12394 S_SET_STORAGE_CLASS (sym, C_THUMBLABEL);
12395 break;
12396 default:
12397 /* Do nothing. */
12398 break;
12402 if (ARM_IS_INTERWORK (sym))
12403 coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_flags = 0xFF;
12405 #endif
12406 #ifdef OBJ_ELF
12407 symbolS * sym;
12408 char bind;
12410 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
12412 if (ARM_IS_THUMB (sym))
12414 elf_symbol_type * elf_sym;
12416 elf_sym = elf_symbol (symbol_get_bfdsym (sym));
12417 bind = ELF_ST_BIND (elf_sym);
12419 /* If it's a .thumb_func, declare it as so,
12420 otherwise tag label as .code 16. */
12421 if (THUMB_IS_FUNC (sym))
12422 elf_sym->internal_elf_sym.st_info =
12423 ELF_ST_INFO (bind, STT_ARM_TFUNC);
12424 else
12425 elf_sym->internal_elf_sym.st_info =
12426 ELF_ST_INFO (bind, STT_ARM_16BIT);
12429 #endif
12433 arm_data_in_code ()
12435 if (thumb_mode && ! strncmp (input_line_pointer + 1, "data:", 5))
12437 *input_line_pointer = '/';
12438 input_line_pointer += 5;
12439 *input_line_pointer = 0;
12440 return 1;
12443 return 0;
12446 char *
12447 arm_canonicalize_symbol_name (name)
12448 char * name;
12450 int len;
12452 if (thumb_mode && (len = strlen (name)) > 5
12453 && streq (name + len - 5, "/data"))
12454 *(name + len - 5) = 0;
12456 return name;
12459 #if defined OBJ_COFF || defined OBJ_ELF
12460 void
12461 arm_validate_fix (fixP)
12462 fixS * fixP;
12464 /* If the destination of the branch is a defined symbol which does not have
12465 the THUMB_FUNC attribute, then we must be calling a function which has
12466 the (interfacearm) attribute. We look for the Thumb entry point to that
12467 function and change the branch to refer to that function instead. */
12468 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23
12469 && fixP->fx_addsy != NULL
12470 && S_IS_DEFINED (fixP->fx_addsy)
12471 && ! THUMB_IS_FUNC (fixP->fx_addsy))
12473 fixP->fx_addsy = find_real_start (fixP->fx_addsy);
12476 #endif
12479 arm_force_relocation (fixp)
12480 struct fix * fixp;
12482 #if defined (OBJ_COFF) && defined (TE_PE)
12483 if (fixp->fx_r_type == BFD_RELOC_RVA)
12484 return 1;
12485 #endif
12486 #ifdef OBJ_ELF
12487 if (fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
12488 || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
12489 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX
12490 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23)
12491 return 1;
12492 #endif
12494 /* Resolve these relocations even if the symbol is extern or weak. */
12495 if (fixp->fx_r_type == BFD_RELOC_ARM_IMMEDIATE
12496 || fixp->fx_r_type == BFD_RELOC_ARM_OFFSET_IMM
12497 || fixp->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
12498 return 0;
12500 return generic_force_reloc (fixp);
12503 #ifdef OBJ_COFF
12504 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
12505 local labels from being added to the output symbol table when they
12506 are used with the ADRL pseudo op. The ADRL relocation should always
12507 be resolved before the binbary is emitted, so it is safe to say that
12508 it is adjustable. */
12510 bfd_boolean
12511 arm_fix_adjustable (fixP)
12512 fixS * fixP;
12514 if (fixP->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
12515 return 1;
12516 return 0;
12518 #endif
12520 #ifdef OBJ_ELF
12521 /* Relocations against Thumb function names must be left unadjusted,
12522 so that the linker can use this information to correctly set the
12523 bottom bit of their addresses. The MIPS version of this function
12524 also prevents relocations that are mips-16 specific, but I do not
12525 know why it does this.
12527 FIXME:
12528 There is one other problem that ought to be addressed here, but
12529 which currently is not: Taking the address of a label (rather
12530 than a function) and then later jumping to that address. Such
12531 addresses also ought to have their bottom bit set (assuming that
12532 they reside in Thumb code), but at the moment they will not. */
12534 bfd_boolean
12535 arm_fix_adjustable (fixP)
12536 fixS * fixP;
12538 if (fixP->fx_addsy == NULL)
12539 return 1;
12541 if (THUMB_IS_FUNC (fixP->fx_addsy)
12542 && fixP->fx_subsy == NULL)
12543 return 0;
12545 /* We need the symbol name for the VTABLE entries. */
12546 if ( fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
12547 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
12548 return 0;
12550 /* Don't allow symbols to be discarded on GOT related relocs. */
12551 if (fixP->fx_r_type == BFD_RELOC_ARM_PLT32
12552 || fixP->fx_r_type == BFD_RELOC_ARM_GOT32
12553 || fixP->fx_r_type == BFD_RELOC_ARM_GOTOFF)
12554 return 0;
12556 return 1;
12559 const char *
12560 elf32_arm_target_format ()
12562 if (target_big_endian)
12564 if (target_oabi)
12565 return "elf32-bigarm-oabi";
12566 else
12567 return "elf32-bigarm";
12569 else
12571 if (target_oabi)
12572 return "elf32-littlearm-oabi";
12573 else
12574 return "elf32-littlearm";
12578 void
12579 armelf_frob_symbol (symp, puntp)
12580 symbolS * symp;
12581 int * puntp;
12583 elf_frob_symbol (symp, puntp);
12586 static bfd_reloc_code_real_type
12587 arm_parse_reloc ()
12589 char id [16];
12590 char * ip;
12591 unsigned int i;
12592 static struct
12594 char * str;
12595 int len;
12596 bfd_reloc_code_real_type reloc;
12598 reloc_map[] =
12600 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
12601 MAP ("(got)", BFD_RELOC_ARM_GOT32),
12602 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF),
12603 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
12604 branch instructions generated by GCC for PLT relocs. */
12605 MAP ("(plt)", BFD_RELOC_ARM_PLT32),
12606 { NULL, 0, BFD_RELOC_UNUSED }
12607 #undef MAP
12610 for (i = 0, ip = input_line_pointer;
12611 i < sizeof (id) && (ISALNUM (*ip) || ISPUNCT (*ip));
12612 i++, ip++)
12613 id[i] = TOLOWER (*ip);
12615 for (i = 0; reloc_map[i].str; i++)
12616 if (strncmp (id, reloc_map[i].str, reloc_map[i].len) == 0)
12617 break;
12619 input_line_pointer += reloc_map[i].len;
12621 return reloc_map[i].reloc;
12624 static void
12625 s_arm_elf_cons (nbytes)
12626 int nbytes;
12628 expressionS exp;
12630 #ifdef md_flush_pending_output
12631 md_flush_pending_output ();
12632 #endif
12634 if (is_it_end_of_statement ())
12636 demand_empty_rest_of_line ();
12637 return;
12640 #ifdef md_cons_align
12641 md_cons_align (nbytes);
12642 #endif
12646 bfd_reloc_code_real_type reloc;
12648 expression (& exp);
12650 if (exp.X_op == O_symbol
12651 && * input_line_pointer == '('
12652 && (reloc = arm_parse_reloc ()) != BFD_RELOC_UNUSED)
12654 reloc_howto_type *howto = bfd_reloc_type_lookup (stdoutput, reloc);
12655 int size = bfd_get_reloc_size (howto);
12657 if (size > nbytes)
12658 as_bad ("%s relocations do not fit in %d bytes",
12659 howto->name, nbytes);
12660 else
12662 register char *p = frag_more ((int) nbytes);
12663 int offset = nbytes - size;
12665 fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size,
12666 &exp, 0, reloc);
12669 else
12670 emit_expr (&exp, (unsigned int) nbytes);
12672 while (*input_line_pointer++ == ',');
12674 /* Put terminator back into stream. */
12675 input_line_pointer --;
12676 demand_empty_rest_of_line ();
12679 #endif /* OBJ_ELF */
12681 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
12682 of an rs_align_code fragment. */
12684 void
12685 arm_handle_align (fragP)
12686 fragS *fragP;
12688 static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 };
12689 static char const thumb_noop[2] = { 0xc0, 0x46 };
12690 static char const arm_bigend_noop[4] = { 0xe1, 0xa0, 0x00, 0x00 };
12691 static char const thumb_bigend_noop[2] = { 0x46, 0xc0 };
12693 int bytes, fix, noop_size;
12694 char * p;
12695 const char * noop;
12697 if (fragP->fr_type != rs_align_code)
12698 return;
12700 bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
12701 p = fragP->fr_literal + fragP->fr_fix;
12702 fix = 0;
12704 if (bytes > MAX_MEM_FOR_RS_ALIGN_CODE)
12705 bytes &= MAX_MEM_FOR_RS_ALIGN_CODE;
12707 if (fragP->tc_frag_data)
12709 if (target_big_endian)
12710 noop = thumb_bigend_noop;
12711 else
12712 noop = thumb_noop;
12713 noop_size = sizeof (thumb_noop);
12715 else
12717 if (target_big_endian)
12718 noop = arm_bigend_noop;
12719 else
12720 noop = arm_noop;
12721 noop_size = sizeof (arm_noop);
12724 if (bytes & (noop_size - 1))
12726 fix = bytes & (noop_size - 1);
12727 memset (p, 0, fix);
12728 p += fix;
12729 bytes -= fix;
12732 while (bytes >= noop_size)
12734 memcpy (p, noop, noop_size);
12735 p += noop_size;
12736 bytes -= noop_size;
12737 fix += noop_size;
12740 fragP->fr_fix += fix;
12741 fragP->fr_var = noop_size;
12744 /* Called from md_do_align. Used to create an alignment
12745 frag in a code section. */
12747 void
12748 arm_frag_align_code (n, max)
12749 int n;
12750 int max;
12752 char * p;
12754 /* We assume that there will never be a requirment
12755 to support alignments greater than 32 bytes. */
12756 if (max > MAX_MEM_FOR_RS_ALIGN_CODE)
12757 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
12759 p = frag_var (rs_align_code,
12760 MAX_MEM_FOR_RS_ALIGN_CODE,
12762 (relax_substateT) max,
12763 (symbolS *) NULL,
12764 (offsetT) n,
12765 (char *) NULL);
12766 *p = 0;
12770 /* Perform target specific initialisation of a frag. */
12772 void
12773 arm_init_frag (fragP)
12774 fragS *fragP;
12776 /* Record whether this frag is in an ARM or a THUMB area. */
12777 fragP->tc_frag_data = thumb_mode;