* elf32-ppc.c (LWZU_0_X_11): Delete.
[binutils.git] / gas / config / tc-arm.c
blob4ca8d49204a38526c64a1330f3e478b234c0f317
1 /* tc-arm.c -- Assemble for the ARM
2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
3 2004, 2005
4 Free Software Foundation, Inc.
5 Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
6 Modified by David Taylor (dtaylor@armltd.co.uk)
7 Cirrus coprocessor mods by Aldy Hernandez (aldyh@redhat.com)
8 Cirrus coprocessor fixes by Petko Manolov (petkan@nucleusys.com)
9 Cirrus coprocessor fixes by Vladimir Ivanov (vladitx@nucleusys.com)
11 This file is part of GAS, the GNU Assembler.
13 GAS is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 2, or (at your option)
16 any later version.
18 GAS is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with GAS; see the file COPYING. If not, write to the Free
25 Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
26 02110-1301, USA. */
28 #include <string.h>
29 #define NO_RELOC 0
30 #include "as.h"
31 #include "safe-ctype.h"
33 /* Need TARGET_CPU. */
34 #include "config.h"
35 #include "subsegs.h"
36 #include "obstack.h"
37 #include "symbols.h"
38 #include "listing.h"
40 #include "opcode/arm.h"
42 #ifdef OBJ_ELF
43 #include "elf/arm.h"
44 #include "dwarf2dbg.h"
45 #include "dw2gencfi.h"
46 #endif
48 /* XXX Set this to 1 after the next binutils release. */
49 #define WARN_DEPRECATED 0
51 #ifdef OBJ_ELF
52 /* Must be at least the size of the largest unwind opcode (currently two). */
53 #define ARM_OPCODE_CHUNK_SIZE 8
55 /* This structure holds the unwinding state. */
57 static struct
59 symbolS * proc_start;
60 symbolS * table_entry;
61 symbolS * personality_routine;
62 int personality_index;
63 /* The segment containing the function. */
64 segT saved_seg;
65 subsegT saved_subseg;
66 /* Opcodes generated from this function. */
67 unsigned char * opcodes;
68 int opcode_count;
69 int opcode_alloc;
70 /* The number of bytes pushed to the stack. */
71 offsetT frame_size;
72 /* We don't add stack adjustment opcodes immediately so that we can merge
73 multiple adjustments. We can also omit the final adjustment
74 when using a frame pointer. */
75 offsetT pending_offset;
76 /* These two fields are set by both unwind_movsp and unwind_setfp. They
77 hold the reg+offset to use when restoring sp from a frame pointer. */
78 offsetT fp_offset;
79 int fp_reg;
80 /* Nonzero if an unwind_setfp directive has been seen. */
81 unsigned fp_used:1;
82 /* Nonzero if the last opcode restores sp from fp_reg. */
83 unsigned sp_restored:1;
84 } unwind;
86 /* Bit N indicates that an R_ARM_NONE relocation has been output for
87 __aeabi_unwind_cpp_prN already if set. This enables dependencies to be
88 emitted only once per section, to save unnecessary bloat. */
89 static unsigned int marked_pr_dependency = 0;
91 #endif /* OBJ_ELF */
93 enum arm_float_abi
95 ARM_FLOAT_ABI_HARD,
96 ARM_FLOAT_ABI_SOFTFP,
97 ARM_FLOAT_ABI_SOFT
100 /* Types of processor to assemble for. */
101 #define ARM_1 ARM_ARCH_V1
102 #define ARM_2 ARM_ARCH_V2
103 #define ARM_3 ARM_ARCH_V2S
104 #define ARM_250 ARM_ARCH_V2S
105 #define ARM_6 ARM_ARCH_V3
106 #define ARM_7 ARM_ARCH_V3
107 #define ARM_8 ARM_ARCH_V4
108 #define ARM_9 ARM_ARCH_V4T
109 #define ARM_STRONG ARM_ARCH_V4
110 #define ARM_CPU_MASK 0x0000000f /* XXX? */
112 #ifndef CPU_DEFAULT
113 #if defined __XSCALE__
114 #define CPU_DEFAULT (ARM_ARCH_XSCALE)
115 #else
116 #if defined __thumb__
117 #define CPU_DEFAULT (ARM_ARCH_V5T)
118 #else
119 #define CPU_DEFAULT ARM_ANY
120 #endif
121 #endif
122 #endif
124 #ifndef FPU_DEFAULT
125 # ifdef TE_LINUX
126 # define FPU_DEFAULT FPU_ARCH_FPA
127 # elif defined (TE_NetBSD)
128 # ifdef OBJ_ELF
129 # define FPU_DEFAULT FPU_ARCH_VFP /* Soft-float, but VFP order. */
130 # else
131 /* Legacy a.out format. */
132 # define FPU_DEFAULT FPU_ARCH_FPA /* Soft-float, but FPA order. */
133 # endif
134 # elif defined (TE_VXWORKS)
135 # define FPU_DEFAULT FPU_ARCH_VFP /* Soft-float, VFP order. */
136 # else
137 /* For backwards compatibility, default to FPA. */
138 # define FPU_DEFAULT FPU_ARCH_FPA
139 # endif
140 #endif /* ifndef FPU_DEFAULT */
142 #define streq(a, b) (strcmp (a, b) == 0)
143 #define skip_whitespace(str) while (*(str) == ' ') ++(str)
145 static unsigned long cpu_variant;
147 /* Flags stored in private area of BFD structure. */
148 static int uses_apcs_26 = FALSE;
149 static int atpcs = FALSE;
150 static int support_interwork = FALSE;
151 static int uses_apcs_float = FALSE;
152 static int pic_code = FALSE;
154 /* Variables that we set while parsing command-line options. Once all
155 options have been read we re-process these values to set the real
156 assembly flags. */
157 static int legacy_cpu = -1;
158 static int legacy_fpu = -1;
160 static int mcpu_cpu_opt = -1;
161 static int mcpu_fpu_opt = -1;
162 static int march_cpu_opt = -1;
163 static int march_fpu_opt = -1;
164 static int mfpu_opt = -1;
165 static int mfloat_abi_opt = -1;
166 #ifdef OBJ_ELF
167 # ifdef EABI_DEFAULT
168 static int meabi_flags = EABI_DEFAULT;
169 # else
170 static int meabi_flags = EF_ARM_EABI_UNKNOWN;
171 # endif
172 #endif
174 /* This array holds the chars that always start a comment. If the
175 pre-processor is disabled, these aren't very useful. */
176 const char comment_chars[] = "@";
178 /* This array holds the chars that only start a comment at the beginning of
179 a line. If the line seems to have the form '# 123 filename'
180 .line and .file directives will appear in the pre-processed output. */
181 /* Note that input_file.c hand checks for '#' at the beginning of the
182 first line of the input file. This is because the compiler outputs
183 #NO_APP at the beginning of its output. */
184 /* Also note that comments like this one will always work. */
185 const char line_comment_chars[] = "#";
187 const char line_separator_chars[] = ";";
189 /* Chars that can be used to separate mant
190 from exp in floating point numbers. */
191 const char EXP_CHARS[] = "eE";
193 /* Chars that mean this number is a floating point constant. */
194 /* As in 0f12.456 */
195 /* or 0d1.2345e12 */
197 const char FLT_CHARS[] = "rRsSfFdDxXeEpP";
199 /* Prefix characters that indicate the start of an immediate
200 value. */
201 #define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
203 #ifdef OBJ_ELF
204 /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
205 symbolS * GOT_symbol;
206 #endif
208 /* Size of relocation record. */
209 const int md_reloc_size = 8;
211 /* 0: assemble for ARM,
212 1: assemble for Thumb,
213 2: assemble for Thumb even though target CPU does not support thumb
214 instructions. */
215 static int thumb_mode = 0;
217 typedef struct arm_fix
219 int thumb_mode;
220 } arm_fix_data;
222 struct arm_it
224 const char * error;
225 unsigned long instruction;
226 int size;
227 struct
229 bfd_reloc_code_real_type type;
230 expressionS exp;
231 int pc_rel;
232 } reloc;
235 struct arm_it inst;
237 enum asm_shift_index
239 SHIFT_LSL = 0,
240 SHIFT_LSR,
241 SHIFT_ASR,
242 SHIFT_ROR,
243 SHIFT_RRX
246 struct asm_shift_properties
248 enum asm_shift_index index;
249 unsigned long bit_field;
250 unsigned int allows_0 : 1;
251 unsigned int allows_32 : 1;
254 static const struct asm_shift_properties shift_properties [] =
256 { SHIFT_LSL, 0, 1, 0},
257 { SHIFT_LSR, 0x20, 0, 1},
258 { SHIFT_ASR, 0x40, 0, 1},
259 { SHIFT_ROR, 0x60, 0, 0},
260 { SHIFT_RRX, 0x60, 0, 0}
263 struct asm_shift_name
265 const char * name;
266 const struct asm_shift_properties * properties;
269 static const struct asm_shift_name shift_names [] =
271 { "asl", shift_properties + SHIFT_LSL },
272 { "lsl", shift_properties + SHIFT_LSL },
273 { "lsr", shift_properties + SHIFT_LSR },
274 { "asr", shift_properties + SHIFT_ASR },
275 { "ror", shift_properties + SHIFT_ROR },
276 { "rrx", shift_properties + SHIFT_RRX },
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 }
285 /* Any kind of shift is accepted. */
286 #define NO_SHIFT_RESTRICT 1
287 /* The shift operand must be an immediate value, not a register. */
288 #define SHIFT_IMMEDIATE 0
289 /* The shift must be LSL or ASR and the operand must be an immediate. */
290 #define SHIFT_LSL_OR_ASR_IMMEDIATE 2
291 /* The shift must be ASR and the operand must be an immediate. */
292 #define SHIFT_ASR_IMMEDIATE 3
293 /* The shift must be LSL and the operand must be an immediate. */
294 #define SHIFT_LSL_IMMEDIATE 4
296 #define NUM_FLOAT_VALS 8
298 const char * fp_const[] =
300 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
303 /* Number of littlenums required to hold an extended precision number. */
304 #define MAX_LITTLENUMS 6
306 LITTLENUM_TYPE fp_values[NUM_FLOAT_VALS][MAX_LITTLENUMS];
308 #define FAIL (-1)
309 #define SUCCESS (0)
311 /* Whether a Co-processor load/store operation accepts write-back forms. */
312 #define CP_WB_OK 1
313 #define CP_NO_WB 0
315 #define SUFF_S 1
316 #define SUFF_D 2
317 #define SUFF_E 3
318 #define SUFF_P 4
320 #define CP_T_X 0x00008000
321 #define CP_T_Y 0x00400000
322 #define CP_T_Pre 0x01000000
323 #define CP_T_UD 0x00800000
324 #define CP_T_WB 0x00200000
326 #define CONDS_BIT 0x00100000
327 #define LOAD_BIT 0x00100000
329 #define DOUBLE_LOAD_FLAG 0x00000001
331 struct asm_cond
333 const char * template;
334 unsigned long value;
337 #define COND_ALWAYS 0xe0000000
338 #define COND_MASK 0xf0000000
340 static const struct asm_cond conds[] =
342 {"eq", 0x00000000},
343 {"ne", 0x10000000},
344 {"cs", 0x20000000}, {"hs", 0x20000000},
345 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
346 {"mi", 0x40000000},
347 {"pl", 0x50000000},
348 {"vs", 0x60000000},
349 {"vc", 0x70000000},
350 {"hi", 0x80000000},
351 {"ls", 0x90000000},
352 {"ge", 0xa0000000},
353 {"lt", 0xb0000000},
354 {"gt", 0xc0000000},
355 {"le", 0xd0000000},
356 {"al", 0xe0000000},
357 {"nv", 0xf0000000}
360 struct asm_psr
362 const char *template;
363 bfd_boolean cpsr;
364 unsigned long field;
367 /* The bit that distinguishes CPSR and SPSR. */
368 #define SPSR_BIT (1 << 22)
370 /* How many bits to shift the PSR_xxx bits up by. */
371 #define PSR_SHIFT 16
373 #define PSR_c (1 << 0)
374 #define PSR_x (1 << 1)
375 #define PSR_s (1 << 2)
376 #define PSR_f (1 << 3)
378 static const struct asm_psr psrs[] =
380 {"CPSR", TRUE, PSR_c | PSR_f},
381 {"CPSR_all", TRUE, PSR_c | PSR_f},
382 {"SPSR", FALSE, PSR_c | PSR_f},
383 {"SPSR_all", FALSE, PSR_c | PSR_f},
384 {"CPSR_flg", TRUE, PSR_f},
385 {"CPSR_f", TRUE, PSR_f},
386 {"SPSR_flg", FALSE, PSR_f},
387 {"SPSR_f", FALSE, PSR_f},
388 {"CPSR_c", TRUE, PSR_c},
389 {"CPSR_ctl", TRUE, PSR_c},
390 {"SPSR_c", FALSE, PSR_c},
391 {"SPSR_ctl", FALSE, PSR_c},
392 {"CPSR_x", TRUE, PSR_x},
393 {"CPSR_s", TRUE, PSR_s},
394 {"SPSR_x", FALSE, PSR_x},
395 {"SPSR_s", FALSE, PSR_s},
396 /* Combinations of flags. */
397 {"CPSR_fs", TRUE, PSR_f | PSR_s},
398 {"CPSR_fx", TRUE, PSR_f | PSR_x},
399 {"CPSR_fc", TRUE, PSR_f | PSR_c},
400 {"CPSR_sf", TRUE, PSR_s | PSR_f},
401 {"CPSR_sx", TRUE, PSR_s | PSR_x},
402 {"CPSR_sc", TRUE, PSR_s | PSR_c},
403 {"CPSR_xf", TRUE, PSR_x | PSR_f},
404 {"CPSR_xs", TRUE, PSR_x | PSR_s},
405 {"CPSR_xc", TRUE, PSR_x | PSR_c},
406 {"CPSR_cf", TRUE, PSR_c | PSR_f},
407 {"CPSR_cs", TRUE, PSR_c | PSR_s},
408 {"CPSR_cx", TRUE, PSR_c | PSR_x},
409 {"CPSR_fsx", TRUE, PSR_f | PSR_s | PSR_x},
410 {"CPSR_fsc", TRUE, PSR_f | PSR_s | PSR_c},
411 {"CPSR_fxs", TRUE, PSR_f | PSR_x | PSR_s},
412 {"CPSR_fxc", TRUE, PSR_f | PSR_x | PSR_c},
413 {"CPSR_fcs", TRUE, PSR_f | PSR_c | PSR_s},
414 {"CPSR_fcx", TRUE, PSR_f | PSR_c | PSR_x},
415 {"CPSR_sfx", TRUE, PSR_s | PSR_f | PSR_x},
416 {"CPSR_sfc", TRUE, PSR_s | PSR_f | PSR_c},
417 {"CPSR_sxf", TRUE, PSR_s | PSR_x | PSR_f},
418 {"CPSR_sxc", TRUE, PSR_s | PSR_x | PSR_c},
419 {"CPSR_scf", TRUE, PSR_s | PSR_c | PSR_f},
420 {"CPSR_scx", TRUE, PSR_s | PSR_c | PSR_x},
421 {"CPSR_xfs", TRUE, PSR_x | PSR_f | PSR_s},
422 {"CPSR_xfc", TRUE, PSR_x | PSR_f | PSR_c},
423 {"CPSR_xsf", TRUE, PSR_x | PSR_s | PSR_f},
424 {"CPSR_xsc", TRUE, PSR_x | PSR_s | PSR_c},
425 {"CPSR_xcf", TRUE, PSR_x | PSR_c | PSR_f},
426 {"CPSR_xcs", TRUE, PSR_x | PSR_c | PSR_s},
427 {"CPSR_cfs", TRUE, PSR_c | PSR_f | PSR_s},
428 {"CPSR_cfx", TRUE, PSR_c | PSR_f | PSR_x},
429 {"CPSR_csf", TRUE, PSR_c | PSR_s | PSR_f},
430 {"CPSR_csx", TRUE, PSR_c | PSR_s | PSR_x},
431 {"CPSR_cxf", TRUE, PSR_c | PSR_x | PSR_f},
432 {"CPSR_cxs", TRUE, PSR_c | PSR_x | PSR_s},
433 {"CPSR_fsxc", TRUE, PSR_f | PSR_s | PSR_x | PSR_c},
434 {"CPSR_fscx", TRUE, PSR_f | PSR_s | PSR_c | PSR_x},
435 {"CPSR_fxsc", TRUE, PSR_f | PSR_x | PSR_s | PSR_c},
436 {"CPSR_fxcs", TRUE, PSR_f | PSR_x | PSR_c | PSR_s},
437 {"CPSR_fcsx", TRUE, PSR_f | PSR_c | PSR_s | PSR_x},
438 {"CPSR_fcxs", TRUE, PSR_f | PSR_c | PSR_x | PSR_s},
439 {"CPSR_sfxc", TRUE, PSR_s | PSR_f | PSR_x | PSR_c},
440 {"CPSR_sfcx", TRUE, PSR_s | PSR_f | PSR_c | PSR_x},
441 {"CPSR_sxfc", TRUE, PSR_s | PSR_x | PSR_f | PSR_c},
442 {"CPSR_sxcf", TRUE, PSR_s | PSR_x | PSR_c | PSR_f},
443 {"CPSR_scfx", TRUE, PSR_s | PSR_c | PSR_f | PSR_x},
444 {"CPSR_scxf", TRUE, PSR_s | PSR_c | PSR_x | PSR_f},
445 {"CPSR_xfsc", TRUE, PSR_x | PSR_f | PSR_s | PSR_c},
446 {"CPSR_xfcs", TRUE, PSR_x | PSR_f | PSR_c | PSR_s},
447 {"CPSR_xsfc", TRUE, PSR_x | PSR_s | PSR_f | PSR_c},
448 {"CPSR_xscf", TRUE, PSR_x | PSR_s | PSR_c | PSR_f},
449 {"CPSR_xcfs", TRUE, PSR_x | PSR_c | PSR_f | PSR_s},
450 {"CPSR_xcsf", TRUE, PSR_x | PSR_c | PSR_s | PSR_f},
451 {"CPSR_cfsx", TRUE, PSR_c | PSR_f | PSR_s | PSR_x},
452 {"CPSR_cfxs", TRUE, PSR_c | PSR_f | PSR_x | PSR_s},
453 {"CPSR_csfx", TRUE, PSR_c | PSR_s | PSR_f | PSR_x},
454 {"CPSR_csxf", TRUE, PSR_c | PSR_s | PSR_x | PSR_f},
455 {"CPSR_cxfs", TRUE, PSR_c | PSR_x | PSR_f | PSR_s},
456 {"CPSR_cxsf", TRUE, PSR_c | PSR_x | PSR_s | PSR_f},
457 {"SPSR_fs", FALSE, PSR_f | PSR_s},
458 {"SPSR_fx", FALSE, PSR_f | PSR_x},
459 {"SPSR_fc", FALSE, PSR_f | PSR_c},
460 {"SPSR_sf", FALSE, PSR_s | PSR_f},
461 {"SPSR_sx", FALSE, PSR_s | PSR_x},
462 {"SPSR_sc", FALSE, PSR_s | PSR_c},
463 {"SPSR_xf", FALSE, PSR_x | PSR_f},
464 {"SPSR_xs", FALSE, PSR_x | PSR_s},
465 {"SPSR_xc", FALSE, PSR_x | PSR_c},
466 {"SPSR_cf", FALSE, PSR_c | PSR_f},
467 {"SPSR_cs", FALSE, PSR_c | PSR_s},
468 {"SPSR_cx", FALSE, PSR_c | PSR_x},
469 {"SPSR_fsx", FALSE, PSR_f | PSR_s | PSR_x},
470 {"SPSR_fsc", FALSE, PSR_f | PSR_s | PSR_c},
471 {"SPSR_fxs", FALSE, PSR_f | PSR_x | PSR_s},
472 {"SPSR_fxc", FALSE, PSR_f | PSR_x | PSR_c},
473 {"SPSR_fcs", FALSE, PSR_f | PSR_c | PSR_s},
474 {"SPSR_fcx", FALSE, PSR_f | PSR_c | PSR_x},
475 {"SPSR_sfx", FALSE, PSR_s | PSR_f | PSR_x},
476 {"SPSR_sfc", FALSE, PSR_s | PSR_f | PSR_c},
477 {"SPSR_sxf", FALSE, PSR_s | PSR_x | PSR_f},
478 {"SPSR_sxc", FALSE, PSR_s | PSR_x | PSR_c},
479 {"SPSR_scf", FALSE, PSR_s | PSR_c | PSR_f},
480 {"SPSR_scx", FALSE, PSR_s | PSR_c | PSR_x},
481 {"SPSR_xfs", FALSE, PSR_x | PSR_f | PSR_s},
482 {"SPSR_xfc", FALSE, PSR_x | PSR_f | PSR_c},
483 {"SPSR_xsf", FALSE, PSR_x | PSR_s | PSR_f},
484 {"SPSR_xsc", FALSE, PSR_x | PSR_s | PSR_c},
485 {"SPSR_xcf", FALSE, PSR_x | PSR_c | PSR_f},
486 {"SPSR_xcs", FALSE, PSR_x | PSR_c | PSR_s},
487 {"SPSR_cfs", FALSE, PSR_c | PSR_f | PSR_s},
488 {"SPSR_cfx", FALSE, PSR_c | PSR_f | PSR_x},
489 {"SPSR_csf", FALSE, PSR_c | PSR_s | PSR_f},
490 {"SPSR_csx", FALSE, PSR_c | PSR_s | PSR_x},
491 {"SPSR_cxf", FALSE, PSR_c | PSR_x | PSR_f},
492 {"SPSR_cxs", FALSE, PSR_c | PSR_x | PSR_s},
493 {"SPSR_fsxc", FALSE, PSR_f | PSR_s | PSR_x | PSR_c},
494 {"SPSR_fscx", FALSE, PSR_f | PSR_s | PSR_c | PSR_x},
495 {"SPSR_fxsc", FALSE, PSR_f | PSR_x | PSR_s | PSR_c},
496 {"SPSR_fxcs", FALSE, PSR_f | PSR_x | PSR_c | PSR_s},
497 {"SPSR_fcsx", FALSE, PSR_f | PSR_c | PSR_s | PSR_x},
498 {"SPSR_fcxs", FALSE, PSR_f | PSR_c | PSR_x | PSR_s},
499 {"SPSR_sfxc", FALSE, PSR_s | PSR_f | PSR_x | PSR_c},
500 {"SPSR_sfcx", FALSE, PSR_s | PSR_f | PSR_c | PSR_x},
501 {"SPSR_sxfc", FALSE, PSR_s | PSR_x | PSR_f | PSR_c},
502 {"SPSR_sxcf", FALSE, PSR_s | PSR_x | PSR_c | PSR_f},
503 {"SPSR_scfx", FALSE, PSR_s | PSR_c | PSR_f | PSR_x},
504 {"SPSR_scxf", FALSE, PSR_s | PSR_c | PSR_x | PSR_f},
505 {"SPSR_xfsc", FALSE, PSR_x | PSR_f | PSR_s | PSR_c},
506 {"SPSR_xfcs", FALSE, PSR_x | PSR_f | PSR_c | PSR_s},
507 {"SPSR_xsfc", FALSE, PSR_x | PSR_s | PSR_f | PSR_c},
508 {"SPSR_xscf", FALSE, PSR_x | PSR_s | PSR_c | PSR_f},
509 {"SPSR_xcfs", FALSE, PSR_x | PSR_c | PSR_f | PSR_s},
510 {"SPSR_xcsf", FALSE, PSR_x | PSR_c | PSR_s | PSR_f},
511 {"SPSR_cfsx", FALSE, PSR_c | PSR_f | PSR_s | PSR_x},
512 {"SPSR_cfxs", FALSE, PSR_c | PSR_f | PSR_x | PSR_s},
513 {"SPSR_csfx", FALSE, PSR_c | PSR_s | PSR_f | PSR_x},
514 {"SPSR_csxf", FALSE, PSR_c | PSR_s | PSR_x | PSR_f},
515 {"SPSR_cxfs", FALSE, PSR_c | PSR_x | PSR_f | PSR_s},
516 {"SPSR_cxsf", FALSE, PSR_c | PSR_x | PSR_s | PSR_f},
519 enum wreg_type
521 IWMMXT_REG_WR = 0,
522 IWMMXT_REG_WC = 1,
523 IWMMXT_REG_WR_OR_WC = 2,
524 IWMMXT_REG_WCG
527 enum iwmmxt_insn_type
529 check_rd,
530 check_wr,
531 check_wrwr,
532 check_wrwrwr,
533 check_wrwrwcg,
534 check_tbcst,
535 check_tmovmsk,
536 check_tmia,
537 check_tmcrr,
538 check_tmrrc,
539 check_tmcr,
540 check_tmrc,
541 check_tinsr,
542 check_textrc,
543 check_waligni,
544 check_textrm,
545 check_wshufh
548 enum vfp_dp_reg_pos
550 VFP_REG_Dd, VFP_REG_Dm, VFP_REG_Dn
553 enum vfp_sp_reg_pos
555 VFP_REG_Sd, VFP_REG_Sm, VFP_REG_Sn
558 enum vfp_ldstm_type
560 VFP_LDSTMIA, VFP_LDSTMDB, VFP_LDSTMIAX, VFP_LDSTMDBX
563 /* VFP system registers. */
564 struct vfp_reg
566 const char *name;
567 unsigned long regno;
570 static const struct vfp_reg vfp_regs[] =
572 {"fpsid", 0x00000000},
573 {"FPSID", 0x00000000},
574 {"fpscr", 0x00010000},
575 {"FPSCR", 0x00010000},
576 {"fpexc", 0x00080000},
577 {"FPEXC", 0x00080000}
580 /* Structure for a hash table entry for a register. */
581 struct reg_entry
583 const char * name;
584 int number;
585 bfd_boolean builtin;
588 /* Some well known registers that we refer to directly elsewhere. */
589 #define REG_SP 13
590 #define REG_LR 14
591 #define REG_PC 15
593 #define wr_register(reg) ((reg ^ WR_PREFIX) >= 0 && (reg ^ WR_PREFIX) <= 15)
594 #define wc_register(reg) ((reg ^ WC_PREFIX) >= 0 && (reg ^ WC_PREFIX) <= 15)
595 #define wcg_register(reg) ((reg ^ WC_PREFIX) >= 8 && (reg ^ WC_PREFIX) <= 11)
597 /* These are the standard names. Users can add aliases with .req.
598 and delete them with .unreq. */
600 /* Integer Register Numbers. */
601 static const struct reg_entry rn_table[] =
603 {"r0", 0, TRUE}, {"r1", 1, TRUE}, {"r2", 2, TRUE}, {"r3", 3, TRUE},
604 {"r4", 4, TRUE}, {"r5", 5, TRUE}, {"r6", 6, TRUE}, {"r7", 7, TRUE},
605 {"r8", 8, TRUE}, {"r9", 9, TRUE}, {"r10", 10, TRUE}, {"r11", 11, TRUE},
606 {"r12", 12, TRUE}, {"r13", REG_SP, TRUE}, {"r14", REG_LR, TRUE}, {"r15", REG_PC, TRUE},
607 /* ATPCS Synonyms. */
608 {"a1", 0, TRUE}, {"a2", 1, TRUE}, {"a3", 2, TRUE}, {"a4", 3, TRUE},
609 {"v1", 4, TRUE}, {"v2", 5, TRUE}, {"v3", 6, TRUE}, {"v4", 7, TRUE},
610 {"v5", 8, TRUE}, {"v6", 9, TRUE}, {"v7", 10, TRUE}, {"v8", 11, TRUE},
611 /* Well-known aliases. */
612 {"wr", 7, TRUE}, {"sb", 9, TRUE}, {"sl", 10, TRUE}, {"fp", 11, TRUE},
613 {"ip", 12, TRUE}, {"sp", REG_SP, TRUE}, {"lr", REG_LR, TRUE}, {"pc", REG_PC, TRUE},
614 {NULL, 0, TRUE}
617 #define WR_PREFIX 0x200
618 #define WC_PREFIX 0x400
620 static const struct reg_entry iwmmxt_table[] =
622 /* Intel Wireless MMX technology register names. */
623 { "wr0", 0x0 | WR_PREFIX, TRUE}, {"wr1", 0x1 | WR_PREFIX, TRUE},
624 { "wr2", 0x2 | WR_PREFIX, TRUE}, {"wr3", 0x3 | WR_PREFIX, TRUE},
625 { "wr4", 0x4 | WR_PREFIX, TRUE}, {"wr5", 0x5 | WR_PREFIX, TRUE},
626 { "wr6", 0x6 | WR_PREFIX, TRUE}, {"wr7", 0x7 | WR_PREFIX, TRUE},
627 { "wr8", 0x8 | WR_PREFIX, TRUE}, {"wr9", 0x9 | WR_PREFIX, TRUE},
628 { "wr10", 0xa | WR_PREFIX, TRUE}, {"wr11", 0xb | WR_PREFIX, TRUE},
629 { "wr12", 0xc | WR_PREFIX, TRUE}, {"wr13", 0xd | WR_PREFIX, TRUE},
630 { "wr14", 0xe | WR_PREFIX, TRUE}, {"wr15", 0xf | WR_PREFIX, TRUE},
631 { "wcid", 0x0 | WC_PREFIX, TRUE}, {"wcon", 0x1 | WC_PREFIX, TRUE},
632 {"wcssf", 0x2 | WC_PREFIX, TRUE}, {"wcasf", 0x3 | WC_PREFIX, TRUE},
633 {"wcgr0", 0x8 | WC_PREFIX, TRUE}, {"wcgr1", 0x9 | WC_PREFIX, TRUE},
634 {"wcgr2", 0xa | WC_PREFIX, TRUE}, {"wcgr3", 0xb | WC_PREFIX, TRUE},
636 { "wR0", 0x0 | WR_PREFIX, TRUE}, {"wR1", 0x1 | WR_PREFIX, TRUE},
637 { "wR2", 0x2 | WR_PREFIX, TRUE}, {"wR3", 0x3 | WR_PREFIX, TRUE},
638 { "wR4", 0x4 | WR_PREFIX, TRUE}, {"wR5", 0x5 | WR_PREFIX, TRUE},
639 { "wR6", 0x6 | WR_PREFIX, TRUE}, {"wR7", 0x7 | WR_PREFIX, TRUE},
640 { "wR8", 0x8 | WR_PREFIX, TRUE}, {"wR9", 0x9 | WR_PREFIX, TRUE},
641 { "wR10", 0xa | WR_PREFIX, TRUE}, {"wR11", 0xb | WR_PREFIX, TRUE},
642 { "wR12", 0xc | WR_PREFIX, TRUE}, {"wR13", 0xd | WR_PREFIX, TRUE},
643 { "wR14", 0xe | WR_PREFIX, TRUE}, {"wR15", 0xf | WR_PREFIX, TRUE},
644 { "wCID", 0x0 | WC_PREFIX, TRUE}, {"wCon", 0x1 | WC_PREFIX, TRUE},
645 {"wCSSF", 0x2 | WC_PREFIX, TRUE}, {"wCASF", 0x3 | WC_PREFIX, TRUE},
646 {"wCGR0", 0x8 | WC_PREFIX, TRUE}, {"wCGR1", 0x9 | WC_PREFIX, TRUE},
647 {"wCGR2", 0xa | WC_PREFIX, TRUE}, {"wCGR3", 0xb | WC_PREFIX, TRUE},
648 {NULL, 0, TRUE}
651 /* Co-processor Numbers. */
652 static const struct reg_entry cp_table[] =
654 {"p0", 0, TRUE}, {"p1", 1, TRUE}, {"p2", 2, TRUE}, {"p3", 3, TRUE},
655 {"p4", 4, TRUE}, {"p5", 5, TRUE}, {"p6", 6, TRUE}, {"p7", 7, TRUE},
656 {"p8", 8, TRUE}, {"p9", 9, TRUE}, {"p10", 10, TRUE}, {"p11", 11, TRUE},
657 {"p12", 12, TRUE}, {"p13", 13, TRUE}, {"p14", 14, TRUE}, {"p15", 15, TRUE},
658 {NULL, 0, TRUE}
661 /* Co-processor Register Numbers. */
662 static const struct reg_entry cn_table[] =
664 {"c0", 0, TRUE}, {"c1", 1, TRUE}, {"c2", 2, TRUE}, {"c3", 3, TRUE},
665 {"c4", 4, TRUE}, {"c5", 5, TRUE}, {"c6", 6, TRUE}, {"c7", 7, TRUE},
666 {"c8", 8, TRUE}, {"c9", 9, TRUE}, {"c10", 10, TRUE}, {"c11", 11, TRUE},
667 {"c12", 12, TRUE}, {"c13", 13, TRUE}, {"c14", 14, TRUE}, {"c15", 15, TRUE},
668 /* Not really valid, but kept for back-wards compatibility. */
669 {"cr0", 0, TRUE}, {"cr1", 1, TRUE}, {"cr2", 2, TRUE}, {"cr3", 3, TRUE},
670 {"cr4", 4, TRUE}, {"cr5", 5, TRUE}, {"cr6", 6, TRUE}, {"cr7", 7, TRUE},
671 {"cr8", 8, TRUE}, {"cr9", 9, TRUE}, {"cr10", 10, TRUE}, {"cr11", 11, TRUE},
672 {"cr12", 12, TRUE}, {"cr13", 13, TRUE}, {"cr14", 14, TRUE}, {"cr15", 15, TRUE},
673 {NULL, 0, TRUE}
676 /* FPA Registers. */
677 static const struct reg_entry fn_table[] =
679 {"f0", 0, TRUE}, {"f1", 1, TRUE}, {"f2", 2, TRUE}, {"f3", 3, TRUE},
680 {"f4", 4, TRUE}, {"f5", 5, TRUE}, {"f6", 6, TRUE}, {"f7", 7, TRUE},
681 {NULL, 0, TRUE}
684 /* VFP SP Registers. */
685 static const struct reg_entry sn_table[] =
687 {"s0", 0, TRUE}, {"s1", 1, TRUE}, {"s2", 2, TRUE}, {"s3", 3, TRUE},
688 {"s4", 4, TRUE}, {"s5", 5, TRUE}, {"s6", 6, TRUE}, {"s7", 7, TRUE},
689 {"s8", 8, TRUE}, {"s9", 9, TRUE}, {"s10", 10, TRUE}, {"s11", 11, TRUE},
690 {"s12", 12, TRUE}, {"s13", 13, TRUE}, {"s14", 14, TRUE}, {"s15", 15, TRUE},
691 {"s16", 16, TRUE}, {"s17", 17, TRUE}, {"s18", 18, TRUE}, {"s19", 19, TRUE},
692 {"s20", 20, TRUE}, {"s21", 21, TRUE}, {"s22", 22, TRUE}, {"s23", 23, TRUE},
693 {"s24", 24, TRUE}, {"s25", 25, TRUE}, {"s26", 26, TRUE}, {"s27", 27, TRUE},
694 {"s28", 28, TRUE}, {"s29", 29, TRUE}, {"s30", 30, TRUE}, {"s31", 31, TRUE},
695 {NULL, 0, TRUE}
698 /* VFP DP Registers. */
699 static const struct reg_entry dn_table[] =
701 {"d0", 0, TRUE}, {"d1", 1, TRUE}, {"d2", 2, TRUE}, {"d3", 3, TRUE},
702 {"d4", 4, TRUE}, {"d5", 5, TRUE}, {"d6", 6, TRUE}, {"d7", 7, TRUE},
703 {"d8", 8, TRUE}, {"d9", 9, TRUE}, {"d10", 10, TRUE}, {"d11", 11, TRUE},
704 {"d12", 12, TRUE}, {"d13", 13, TRUE}, {"d14", 14, TRUE}, {"d15", 15, TRUE},
705 {NULL, 0, TRUE}
708 /* Maverick DSP coprocessor registers. */
709 static const struct reg_entry mav_mvf_table[] =
711 {"mvf0", 0, TRUE}, {"mvf1", 1, TRUE}, {"mvf2", 2, TRUE}, {"mvf3", 3, TRUE},
712 {"mvf4", 4, TRUE}, {"mvf5", 5, TRUE}, {"mvf6", 6, TRUE}, {"mvf7", 7, TRUE},
713 {"mvf8", 8, TRUE}, {"mvf9", 9, TRUE}, {"mvf10", 10, TRUE}, {"mvf11", 11, TRUE},
714 {"mvf12", 12, TRUE}, {"mvf13", 13, TRUE}, {"mvf14", 14, TRUE}, {"mvf15", 15, TRUE},
715 {NULL, 0, TRUE}
718 static const struct reg_entry mav_mvd_table[] =
720 {"mvd0", 0, TRUE}, {"mvd1", 1, TRUE}, {"mvd2", 2, TRUE}, {"mvd3", 3, TRUE},
721 {"mvd4", 4, TRUE}, {"mvd5", 5, TRUE}, {"mvd6", 6, TRUE}, {"mvd7", 7, TRUE},
722 {"mvd8", 8, TRUE}, {"mvd9", 9, TRUE}, {"mvd10", 10, TRUE}, {"mvd11", 11, TRUE},
723 {"mvd12", 12, TRUE}, {"mvd13", 13, TRUE}, {"mvd14", 14, TRUE}, {"mvd15", 15, TRUE},
724 {NULL, 0, TRUE}
727 static const struct reg_entry mav_mvfx_table[] =
729 {"mvfx0", 0, TRUE}, {"mvfx1", 1, TRUE}, {"mvfx2", 2, TRUE}, {"mvfx3", 3, TRUE},
730 {"mvfx4", 4, TRUE}, {"mvfx5", 5, TRUE}, {"mvfx6", 6, TRUE}, {"mvfx7", 7, TRUE},
731 {"mvfx8", 8, TRUE}, {"mvfx9", 9, TRUE}, {"mvfx10", 10, TRUE}, {"mvfx11", 11, TRUE},
732 {"mvfx12", 12, TRUE}, {"mvfx13", 13, TRUE}, {"mvfx14", 14, TRUE}, {"mvfx15", 15, TRUE},
733 {NULL, 0, TRUE}
736 static const struct reg_entry mav_mvdx_table[] =
738 {"mvdx0", 0, TRUE}, {"mvdx1", 1, TRUE}, {"mvdx2", 2, TRUE}, {"mvdx3", 3, TRUE},
739 {"mvdx4", 4, TRUE}, {"mvdx5", 5, TRUE}, {"mvdx6", 6, TRUE}, {"mvdx7", 7, TRUE},
740 {"mvdx8", 8, TRUE}, {"mvdx9", 9, TRUE}, {"mvdx10", 10, TRUE}, {"mvdx11", 11, TRUE},
741 {"mvdx12", 12, TRUE}, {"mvdx13", 13, TRUE}, {"mvdx14", 14, TRUE}, {"mvdx15", 15, TRUE},
742 {NULL, 0, TRUE}
745 static const struct reg_entry mav_mvax_table[] =
747 {"mvax0", 0, TRUE}, {"mvax1", 1, TRUE}, {"mvax2", 2, TRUE}, {"mvax3", 3, TRUE},
748 {NULL, 0, TRUE}
751 static const struct reg_entry mav_dspsc_table[] =
753 {"dspsc", 0, TRUE},
754 {NULL, 0, TRUE}
757 struct reg_map
759 const struct reg_entry * names;
760 int max_regno;
761 struct hash_control * htab;
762 const char * expected;
765 struct reg_map all_reg_maps[] =
767 {rn_table, 15, NULL, N_("ARM register expected")},
768 {cp_table, 15, NULL, N_("bad or missing co-processor number")},
769 {cn_table, 15, NULL, N_("co-processor register expected")},
770 {fn_table, 7, NULL, N_("FPA register expected")},
771 {sn_table, 31, NULL, N_("VFP single precision register expected")},
772 {dn_table, 15, NULL, N_("VFP double precision register expected")},
773 {mav_mvf_table, 15, NULL, N_("Maverick MVF register expected")},
774 {mav_mvd_table, 15, NULL, N_("Maverick MVD register expected")},
775 {mav_mvfx_table, 15, NULL, N_("Maverick MVFX register expected")},
776 {mav_mvdx_table, 15, NULL, N_("Maverick MVDX register expected")},
777 {mav_mvax_table, 3, NULL, N_("Maverick MVAX register expected")},
778 {mav_dspsc_table, 0, NULL, N_("Maverick DSPSC register expected")},
779 {iwmmxt_table, 23, NULL, N_("Intel Wireless MMX technology register expected")},
782 /* Enumeration matching entries in table above. */
783 enum arm_reg_type
785 REG_TYPE_RN = 0,
786 #define REG_TYPE_FIRST REG_TYPE_RN
787 REG_TYPE_CP = 1,
788 REG_TYPE_CN = 2,
789 REG_TYPE_FN = 3,
790 REG_TYPE_SN = 4,
791 REG_TYPE_DN = 5,
792 REG_TYPE_MVF = 6,
793 REG_TYPE_MVD = 7,
794 REG_TYPE_MVFX = 8,
795 REG_TYPE_MVDX = 9,
796 REG_TYPE_MVAX = 10,
797 REG_TYPE_DSPSC = 11,
798 REG_TYPE_IWMMXT = 12,
800 REG_TYPE_MAX = 13
803 /* ARM instructions take 4bytes in the object file, Thumb instructions
804 take 2: */
805 #define INSN_SIZE 4
807 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
808 #define MAV_MODE1 0x100c
810 /* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
811 #define MAV_MODE2 0x0c10
813 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
814 #define MAV_MODE3 0x100c
816 /* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
817 #define MAV_MODE4 0x0c0010
819 /* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
820 #define MAV_MODE5 0x00100c
822 /* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
823 #define MAV_MODE6 0x00100c05
825 struct asm_opcode
827 /* Basic string to match. */
828 const char * template;
830 /* Basic instruction code. */
831 unsigned long value;
833 /* Offset into the template where the condition code (if any) will be.
834 If zero, then the instruction is never conditional. */
835 unsigned cond_offset;
837 /* Which architecture variant provides this instruction. */
838 unsigned long variant;
840 /* Function to call to parse args. */
841 void (* parms) (char *);
844 /* Defines for various bits that we will want to toggle. */
845 #define INST_IMMEDIATE 0x02000000
846 #define OFFSET_REG 0x02000000
847 #define HWOFFSET_IMM 0x00400000
848 #define SHIFT_BY_REG 0x00000010
849 #define PRE_INDEX 0x01000000
850 #define INDEX_UP 0x00800000
851 #define WRITE_BACK 0x00200000
852 #define LDM_TYPE_2_OR_3 0x00400000
854 #define LITERAL_MASK 0xf000f000
855 #define OPCODE_MASK 0xfe1fffff
856 #define V4_STR_BIT 0x00000020
858 #define DATA_OP_SHIFT 21
860 /* Codes to distinguish the arithmetic instructions. */
861 #define OPCODE_AND 0
862 #define OPCODE_EOR 1
863 #define OPCODE_SUB 2
864 #define OPCODE_RSB 3
865 #define OPCODE_ADD 4
866 #define OPCODE_ADC 5
867 #define OPCODE_SBC 6
868 #define OPCODE_RSC 7
869 #define OPCODE_TST 8
870 #define OPCODE_TEQ 9
871 #define OPCODE_CMP 10
872 #define OPCODE_CMN 11
873 #define OPCODE_ORR 12
874 #define OPCODE_MOV 13
875 #define OPCODE_BIC 14
876 #define OPCODE_MVN 15
878 #define T_OPCODE_MUL 0x4340
879 #define T_OPCODE_TST 0x4200
880 #define T_OPCODE_CMN 0x42c0
881 #define T_OPCODE_NEG 0x4240
882 #define T_OPCODE_MVN 0x43c0
884 #define T_OPCODE_ADD_R3 0x1800
885 #define T_OPCODE_SUB_R3 0x1a00
886 #define T_OPCODE_ADD_HI 0x4400
887 #define T_OPCODE_ADD_ST 0xb000
888 #define T_OPCODE_SUB_ST 0xb080
889 #define T_OPCODE_ADD_SP 0xa800
890 #define T_OPCODE_ADD_PC 0xa000
891 #define T_OPCODE_ADD_I8 0x3000
892 #define T_OPCODE_SUB_I8 0x3800
893 #define T_OPCODE_ADD_I3 0x1c00
894 #define T_OPCODE_SUB_I3 0x1e00
896 #define T_OPCODE_ASR_R 0x4100
897 #define T_OPCODE_LSL_R 0x4080
898 #define T_OPCODE_LSR_R 0x40c0
899 #define T_OPCODE_ASR_I 0x1000
900 #define T_OPCODE_LSL_I 0x0000
901 #define T_OPCODE_LSR_I 0x0800
903 #define T_OPCODE_MOV_I8 0x2000
904 #define T_OPCODE_CMP_I8 0x2800
905 #define T_OPCODE_CMP_LR 0x4280
906 #define T_OPCODE_MOV_HR 0x4600
907 #define T_OPCODE_CMP_HR 0x4500
909 #define T_OPCODE_LDR_PC 0x4800
910 #define T_OPCODE_LDR_SP 0x9800
911 #define T_OPCODE_STR_SP 0x9000
912 #define T_OPCODE_LDR_IW 0x6800
913 #define T_OPCODE_STR_IW 0x6000
914 #define T_OPCODE_LDR_IH 0x8800
915 #define T_OPCODE_STR_IH 0x8000
916 #define T_OPCODE_LDR_IB 0x7800
917 #define T_OPCODE_STR_IB 0x7000
918 #define T_OPCODE_LDR_RW 0x5800
919 #define T_OPCODE_STR_RW 0x5000
920 #define T_OPCODE_LDR_RH 0x5a00
921 #define T_OPCODE_STR_RH 0x5200
922 #define T_OPCODE_LDR_RB 0x5c00
923 #define T_OPCODE_STR_RB 0x5400
925 #define T_OPCODE_PUSH 0xb400
926 #define T_OPCODE_POP 0xbc00
928 #define T_OPCODE_BRANCH 0xe7fe
930 #define THUMB_SIZE 2 /* Size of thumb instruction. */
931 #define THUMB_REG_LO 0x1
932 #define THUMB_REG_HI 0x2
933 #define THUMB_REG_ANY 0x3
935 #define THUMB_H1 0x0080
936 #define THUMB_H2 0x0040
938 #define THUMB_ASR 0
939 #define THUMB_LSL 1
940 #define THUMB_LSR 2
942 #define THUMB_MOVE 0
943 #define THUMB_COMPARE 1
944 #define THUMB_CPY 2
946 #define THUMB_LOAD 0
947 #define THUMB_STORE 1
949 #define THUMB_PP_PC_LR 0x0100
951 /* These three are used for immediate shifts, do not alter. */
952 #define THUMB_WORD 2
953 #define THUMB_HALFWORD 1
954 #define THUMB_BYTE 0
956 struct thumb_opcode
958 /* Basic string to match. */
959 const char * template;
961 /* Basic instruction code. */
962 unsigned long value;
964 int size;
966 /* Which CPU variants this exists for. */
967 unsigned long variant;
969 /* Function to call to parse args. */
970 void (* parms) (char *);
973 #define BAD_ARGS _("bad arguments to instruction")
974 #define BAD_PC _("r15 not allowed here")
975 #define BAD_COND _("instruction is not conditional")
976 #define ERR_NO_ACCUM _("acc0 expected")
978 static struct hash_control * arm_ops_hsh = NULL;
979 static struct hash_control * arm_tops_hsh = NULL;
980 static struct hash_control * arm_cond_hsh = NULL;
981 static struct hash_control * arm_shift_hsh = NULL;
982 static struct hash_control * arm_psr_hsh = NULL;
984 /* Stuff needed to resolve the label ambiguity
987 label: <insn>
988 may differ from:
990 label:
991 <insn>
994 symbolS * last_label_seen;
995 static int label_is_thumb_function_name = FALSE;
997 /* Literal Pool stuff. */
999 #define MAX_LITERAL_POOL_SIZE 1024
1001 /* Literal pool structure. Held on a per-section
1002 and per-sub-section basis. */
1004 typedef struct literal_pool
1006 expressionS literals [MAX_LITERAL_POOL_SIZE];
1007 unsigned int next_free_entry;
1008 unsigned int id;
1009 symbolS * symbol;
1010 segT section;
1011 subsegT sub_section;
1012 struct literal_pool * next;
1013 } literal_pool;
1015 /* Pointer to a linked list of literal pools. */
1016 literal_pool * list_of_pools = NULL;
1018 static literal_pool *
1019 find_literal_pool (void)
1021 literal_pool * pool;
1023 for (pool = list_of_pools; pool != NULL; pool = pool->next)
1025 if (pool->section == now_seg
1026 && pool->sub_section == now_subseg)
1027 break;
1030 return pool;
1033 static literal_pool *
1034 find_or_make_literal_pool (void)
1036 /* Next literal pool ID number. */
1037 static unsigned int latest_pool_num = 1;
1038 literal_pool * pool;
1040 pool = find_literal_pool ();
1042 if (pool == NULL)
1044 /* Create a new pool. */
1045 pool = xmalloc (sizeof (* pool));
1046 if (! pool)
1047 return NULL;
1049 pool->next_free_entry = 0;
1050 pool->section = now_seg;
1051 pool->sub_section = now_subseg;
1052 pool->next = list_of_pools;
1053 pool->symbol = NULL;
1055 /* Add it to the list. */
1056 list_of_pools = pool;
1059 /* New pools, and emptied pools, will have a NULL symbol. */
1060 if (pool->symbol == NULL)
1062 pool->symbol = symbol_create (FAKE_LABEL_NAME, undefined_section,
1063 (valueT) 0, &zero_address_frag);
1064 pool->id = latest_pool_num ++;
1067 /* Done. */
1068 return pool;
1071 /* Add the literal in the global 'inst'
1072 structure to the relevent literal pool. */
1074 static int
1075 add_to_lit_pool (void)
1077 literal_pool * pool;
1078 unsigned int entry;
1080 pool = find_or_make_literal_pool ();
1082 /* Check if this literal value is already in the pool. */
1083 for (entry = 0; entry < pool->next_free_entry; entry ++)
1085 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
1086 && (inst.reloc.exp.X_op == O_constant)
1087 && (pool->literals[entry].X_add_number
1088 == inst.reloc.exp.X_add_number)
1089 && (pool->literals[entry].X_unsigned
1090 == inst.reloc.exp.X_unsigned))
1091 break;
1093 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
1094 && (inst.reloc.exp.X_op == O_symbol)
1095 && (pool->literals[entry].X_add_number
1096 == inst.reloc.exp.X_add_number)
1097 && (pool->literals[entry].X_add_symbol
1098 == inst.reloc.exp.X_add_symbol)
1099 && (pool->literals[entry].X_op_symbol
1100 == inst.reloc.exp.X_op_symbol))
1101 break;
1104 /* Do we need to create a new entry? */
1105 if (entry == pool->next_free_entry)
1107 if (entry >= MAX_LITERAL_POOL_SIZE)
1109 inst.error = _("literal pool overflow");
1110 return FAIL;
1113 pool->literals[entry] = inst.reloc.exp;
1114 pool->next_free_entry += 1;
1117 inst.reloc.exp.X_op = O_symbol;
1118 inst.reloc.exp.X_add_number = ((int) entry) * 4 - 8;
1119 inst.reloc.exp.X_add_symbol = pool->symbol;
1121 return SUCCESS;
1124 /* Can't use symbol_new here, so have to create a symbol and then at
1125 a later date assign it a value. Thats what these functions do. */
1127 static void
1128 symbol_locate (symbolS * symbolP,
1129 const char * name, /* It is copied, the caller can modify. */
1130 segT segment, /* Segment identifier (SEG_<something>). */
1131 valueT valu, /* Symbol value. */
1132 fragS * frag) /* Associated fragment. */
1134 unsigned int name_length;
1135 char * preserved_copy_of_name;
1137 name_length = strlen (name) + 1; /* +1 for \0. */
1138 obstack_grow (&notes, name, name_length);
1139 preserved_copy_of_name = obstack_finish (&notes);
1141 #ifdef tc_canonicalize_symbol_name
1142 preserved_copy_of_name =
1143 tc_canonicalize_symbol_name (preserved_copy_of_name);
1144 #endif
1146 S_SET_NAME (symbolP, preserved_copy_of_name);
1148 S_SET_SEGMENT (symbolP, segment);
1149 S_SET_VALUE (symbolP, valu);
1150 symbol_clear_list_pointers (symbolP);
1152 symbol_set_frag (symbolP, frag);
1154 /* Link to end of symbol chain. */
1156 extern int symbol_table_frozen;
1158 if (symbol_table_frozen)
1159 abort ();
1162 symbol_append (symbolP, symbol_lastP, & symbol_rootP, & symbol_lastP);
1164 obj_symbol_new_hook (symbolP);
1166 #ifdef tc_symbol_new_hook
1167 tc_symbol_new_hook (symbolP);
1168 #endif
1170 #ifdef DEBUG_SYMS
1171 verify_symbol_chain (symbol_rootP, symbol_lastP);
1172 #endif /* DEBUG_SYMS */
1175 /* Check that an immediate is valid.
1176 If so, convert it to the right format. */
1178 static unsigned int
1179 validate_immediate (unsigned int val)
1181 unsigned int a;
1182 unsigned int i;
1184 #define rotate_left(v, n) (v << n | v >> (32 - n))
1186 for (i = 0; i < 32; i += 2)
1187 if ((a = rotate_left (val, i)) <= 0xff)
1188 return a | (i << 7); /* 12-bit pack: [shift-cnt,const]. */
1190 return FAIL;
1193 /* Check to see if an immediate can be computed as two separate immediate
1194 values, added together. We already know that this value cannot be
1195 computed by just one ARM instruction. */
1197 static unsigned int
1198 validate_immediate_twopart (unsigned int val,
1199 unsigned int * highpart)
1201 unsigned int a;
1202 unsigned int i;
1204 for (i = 0; i < 32; i += 2)
1205 if (((a = rotate_left (val, i)) & 0xff) != 0)
1207 if (a & 0xff00)
1209 if (a & ~ 0xffff)
1210 continue;
1211 * highpart = (a >> 8) | ((i + 24) << 7);
1213 else if (a & 0xff0000)
1215 if (a & 0xff000000)
1216 continue;
1217 * highpart = (a >> 16) | ((i + 16) << 7);
1219 else
1221 assert (a & 0xff000000);
1222 * highpart = (a >> 24) | ((i + 8) << 7);
1225 return (a & 0xff) | (i << 7);
1228 return FAIL;
1231 static int
1232 validate_offset_imm (unsigned int val, int hwse)
1234 if ((hwse && val > 255) || val > 4095)
1235 return FAIL;
1236 return val;
1240 #ifdef OBJ_ELF
1241 /* This code is to handle mapping symbols as defined in the ARM ELF spec.
1242 (See "Mapping symbols", section 4.5.5, ARM AAELF version 1.0).
1243 Note that previously, $a and $t has type STT_FUNC (BSF_OBJECT flag),
1244 and $d has type STT_OBJECT (BSF_OBJECT flag). Now all three are untyped. */
1246 static enum mstate mapstate = MAP_UNDEFINED;
1248 static void
1249 mapping_state (enum mstate state)
1251 symbolS * symbolP;
1252 const char * symname;
1253 int type;
1255 if (mapstate == state)
1256 /* The mapping symbol has already been emitted.
1257 There is nothing else to do. */
1258 return;
1260 mapstate = state;
1262 switch (state)
1264 case MAP_DATA:
1265 symname = "$d";
1266 type = BSF_NO_FLAGS;
1267 break;
1268 case MAP_ARM:
1269 symname = "$a";
1270 type = BSF_NO_FLAGS;
1271 break;
1272 case MAP_THUMB:
1273 symname = "$t";
1274 type = BSF_NO_FLAGS;
1275 break;
1276 case MAP_UNDEFINED:
1277 return;
1278 default:
1279 abort ();
1282 seg_info (now_seg)->tc_segment_info_data.mapstate = state;
1284 symbolP = symbol_new (symname, now_seg, (valueT) frag_now_fix (), frag_now);
1285 symbol_table_insert (symbolP);
1286 symbol_get_bfdsym (symbolP)->flags |= type | BSF_LOCAL;
1288 switch (state)
1290 case MAP_ARM:
1291 THUMB_SET_FUNC (symbolP, 0);
1292 ARM_SET_THUMB (symbolP, 0);
1293 ARM_SET_INTERWORK (symbolP, support_interwork);
1294 break;
1296 case MAP_THUMB:
1297 THUMB_SET_FUNC (symbolP, 1);
1298 ARM_SET_THUMB (symbolP, 1);
1299 ARM_SET_INTERWORK (symbolP, support_interwork);
1300 break;
1302 case MAP_DATA:
1303 default:
1304 return;
1308 /* When we change sections we need to issue a new mapping symbol. */
1310 void
1311 arm_elf_change_section (void)
1313 flagword flags;
1314 segment_info_type *seginfo;
1316 /* Link an unlinked unwind index table section to the .text section. */
1317 if (elf_section_type (now_seg) == SHT_ARM_EXIDX
1318 && elf_linked_to_section (now_seg) == NULL)
1319 elf_linked_to_section (now_seg) = text_section;
1321 if (!SEG_NORMAL (now_seg))
1322 return;
1324 flags = bfd_get_section_flags (stdoutput, now_seg);
1326 /* We can ignore sections that only contain debug info. */
1327 if ((flags & SEC_ALLOC) == 0)
1328 return;
1330 seginfo = seg_info (now_seg);
1331 mapstate = seginfo->tc_segment_info_data.mapstate;
1332 marked_pr_dependency = seginfo->tc_segment_info_data.marked_pr_dependency;
1336 arm_elf_section_type (const char * str, size_t len)
1338 if (len == 5 && strncmp (str, "exidx", 5) == 0)
1339 return SHT_ARM_EXIDX;
1341 return -1;
1343 #else
1344 #define mapping_state(a)
1345 #endif /* OBJ_ELF */
1347 /* arm_reg_parse () := if it looks like a register, return its token and
1348 advance the pointer. */
1350 static int
1351 arm_reg_parse (char ** ccp, struct hash_control * htab)
1353 char * start = * ccp;
1354 char c;
1355 char * p;
1356 struct reg_entry * reg;
1358 #ifdef REGISTER_PREFIX
1359 if (*start != REGISTER_PREFIX)
1360 return FAIL;
1361 p = start + 1;
1362 #else
1363 p = start;
1364 #ifdef OPTIONAL_REGISTER_PREFIX
1365 if (*p == OPTIONAL_REGISTER_PREFIX)
1366 p++, start++;
1367 #endif
1368 #endif
1369 if (!ISALPHA (*p) || !is_name_beginner (*p))
1370 return FAIL;
1372 c = *p++;
1373 while (ISALPHA (c) || ISDIGIT (c) || c == '_')
1374 c = *p++;
1376 *--p = 0;
1377 reg = (struct reg_entry *) hash_find (htab, start);
1378 *p = c;
1380 if (reg)
1382 *ccp = p;
1383 return reg->number;
1386 return FAIL;
1389 /* Search for the following register name in each of the possible reg name
1390 tables. Return the classification if found, or REG_TYPE_MAX if not
1391 present. */
1393 static enum arm_reg_type
1394 arm_reg_parse_any (char *cp)
1396 int i;
1398 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
1399 if (arm_reg_parse (&cp, all_reg_maps[i].htab) != FAIL)
1400 return (enum arm_reg_type) i;
1402 return REG_TYPE_MAX;
1405 static void
1406 opcode_select (int width)
1408 switch (width)
1410 case 16:
1411 if (! thumb_mode)
1413 if (! (cpu_variant & ARM_EXT_V4T))
1414 as_bad (_("selected processor does not support THUMB opcodes"));
1416 thumb_mode = 1;
1417 /* No need to force the alignment, since we will have been
1418 coming from ARM mode, which is word-aligned. */
1419 record_alignment (now_seg, 1);
1421 mapping_state (MAP_THUMB);
1422 break;
1424 case 32:
1425 if (thumb_mode)
1427 if ((cpu_variant & ARM_ALL) == ARM_EXT_V4T)
1428 as_bad (_("selected processor does not support ARM opcodes"));
1430 thumb_mode = 0;
1432 if (!need_pass_2)
1433 frag_align (2, 0, 0);
1435 record_alignment (now_seg, 1);
1437 mapping_state (MAP_ARM);
1438 break;
1440 default:
1441 as_bad (_("invalid instruction size selected (%d)"), width);
1445 static void
1446 s_req (int a ATTRIBUTE_UNUSED)
1448 as_bad (_("invalid syntax for .req directive"));
1451 /* The .unreq directive deletes an alias which was previously defined
1452 by .req. For example:
1454 my_alias .req r11
1455 .unreq my_alias */
1457 static void
1458 s_unreq (int a ATTRIBUTE_UNUSED)
1460 char * name;
1461 char saved_char;
1463 skip_whitespace (input_line_pointer);
1464 name = input_line_pointer;
1466 while (*input_line_pointer != 0
1467 && *input_line_pointer != ' '
1468 && *input_line_pointer != '\n')
1469 ++input_line_pointer;
1471 saved_char = *input_line_pointer;
1472 *input_line_pointer = 0;
1474 if (*name)
1476 enum arm_reg_type req_type = arm_reg_parse_any (name);
1478 if (req_type != REG_TYPE_MAX)
1480 char *temp_name = name;
1481 int req_no = arm_reg_parse (&temp_name, all_reg_maps[req_type].htab);
1483 if (req_no != FAIL)
1485 struct reg_entry *req_entry;
1487 /* Check to see if this alias is a builtin one. */
1488 req_entry = hash_delete (all_reg_maps[req_type].htab, name);
1490 if (!req_entry)
1491 as_bad (_("unreq: missing hash entry for \"%s\""), name);
1492 else if (req_entry->builtin)
1493 /* FIXME: We are deleting a built in register alias which
1494 points to a const data structure, so we only need to
1495 free up the memory used by the key in the hash table.
1496 Unfortunately we have not recorded this value, so this
1497 is a memory leak. */
1498 /* FIXME: Should we issue a warning message ? */
1500 else
1502 /* Deleting a user defined alias. We need to free the
1503 key and the value, but fortunately the key is the same
1504 as the value->name field. */
1505 free ((char *) req_entry->name);
1506 free (req_entry);
1509 else
1510 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
1512 else
1513 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
1515 else
1516 as_bad (_("invalid syntax for .unreq directive"));
1518 *input_line_pointer = saved_char;
1519 demand_empty_rest_of_line ();
1522 static void
1523 s_bss (int ignore ATTRIBUTE_UNUSED)
1525 /* We don't support putting frags in the BSS segment, we fake it by
1526 marking in_bss, then looking at s_skip for clues. */
1527 subseg_set (bss_section, 0);
1528 demand_empty_rest_of_line ();
1529 mapping_state (MAP_DATA);
1532 static void
1533 s_even (int ignore ATTRIBUTE_UNUSED)
1535 /* Never make frag if expect extra pass. */
1536 if (!need_pass_2)
1537 frag_align (1, 0, 0);
1539 record_alignment (now_seg, 1);
1541 demand_empty_rest_of_line ();
1544 static void
1545 s_ltorg (int ignored ATTRIBUTE_UNUSED)
1547 unsigned int entry;
1548 literal_pool * pool;
1549 char sym_name[20];
1551 pool = find_literal_pool ();
1552 if (pool == NULL
1553 || pool->symbol == NULL
1554 || pool->next_free_entry == 0)
1555 return;
1557 mapping_state (MAP_DATA);
1559 /* Align pool as you have word accesses.
1560 Only make a frag if we have to. */
1561 if (!need_pass_2)
1562 frag_align (2, 0, 0);
1564 record_alignment (now_seg, 2);
1566 sprintf (sym_name, "$$lit_\002%x", pool->id);
1568 symbol_locate (pool->symbol, sym_name, now_seg,
1569 (valueT) frag_now_fix (), frag_now);
1570 symbol_table_insert (pool->symbol);
1572 ARM_SET_THUMB (pool->symbol, thumb_mode);
1574 #if defined OBJ_COFF || defined OBJ_ELF
1575 ARM_SET_INTERWORK (pool->symbol, support_interwork);
1576 #endif
1578 for (entry = 0; entry < pool->next_free_entry; entry ++)
1579 /* First output the expression in the instruction to the pool. */
1580 emit_expr (&(pool->literals[entry]), 4); /* .word */
1582 /* Mark the pool as empty. */
1583 pool->next_free_entry = 0;
1584 pool->symbol = NULL;
1587 /* Same as s_align_ptwo but align 0 => align 2. */
1589 static void
1590 s_align (int unused ATTRIBUTE_UNUSED)
1592 int temp;
1593 long temp_fill;
1594 long max_alignment = 15;
1596 temp = get_absolute_expression ();
1597 if (temp > max_alignment)
1598 as_bad (_("alignment too large: %d assumed"), temp = max_alignment);
1599 else if (temp < 0)
1601 as_bad (_("alignment negative. 0 assumed."));
1602 temp = 0;
1605 if (*input_line_pointer == ',')
1607 input_line_pointer++;
1608 temp_fill = get_absolute_expression ();
1610 else
1611 temp_fill = 0;
1613 if (!temp)
1614 temp = 2;
1616 /* Only make a frag if we HAVE to. */
1617 if (temp && !need_pass_2)
1618 frag_align (temp, (int) temp_fill, 0);
1619 demand_empty_rest_of_line ();
1621 record_alignment (now_seg, temp);
1624 static void
1625 s_force_thumb (int ignore ATTRIBUTE_UNUSED)
1627 /* If we are not already in thumb mode go into it, EVEN if
1628 the target processor does not support thumb instructions.
1629 This is used by gcc/config/arm/lib1funcs.asm for example
1630 to compile interworking support functions even if the
1631 target processor should not support interworking. */
1632 if (! thumb_mode)
1634 thumb_mode = 2;
1636 record_alignment (now_seg, 1);
1639 demand_empty_rest_of_line ();
1642 static void
1643 s_thumb_func (int ignore ATTRIBUTE_UNUSED)
1645 if (! thumb_mode)
1646 opcode_select (16);
1648 /* The following label is the name/address of the start of a Thumb function.
1649 We need to know this for the interworking support. */
1650 label_is_thumb_function_name = TRUE;
1652 demand_empty_rest_of_line ();
1655 /* Perform a .set directive, but also mark the alias as
1656 being a thumb function. */
1658 static void
1659 s_thumb_set (int equiv)
1661 /* XXX the following is a duplicate of the code for s_set() in read.c
1662 We cannot just call that code as we need to get at the symbol that
1663 is created. */
1664 char * name;
1665 char delim;
1666 char * end_name;
1667 symbolS * symbolP;
1669 /* Especial apologies for the random logic:
1670 This just grew, and could be parsed much more simply!
1671 Dean - in haste. */
1672 name = input_line_pointer;
1673 delim = get_symbol_end ();
1674 end_name = input_line_pointer;
1675 *end_name = delim;
1677 SKIP_WHITESPACE ();
1679 if (*input_line_pointer != ',')
1681 *end_name = 0;
1682 as_bad (_("expected comma after name \"%s\""), name);
1683 *end_name = delim;
1684 ignore_rest_of_line ();
1685 return;
1688 input_line_pointer++;
1689 *end_name = 0;
1691 if (name[0] == '.' && name[1] == '\0')
1693 /* XXX - this should not happen to .thumb_set. */
1694 abort ();
1697 if ((symbolP = symbol_find (name)) == NULL
1698 && (symbolP = md_undefined_symbol (name)) == NULL)
1700 #ifndef NO_LISTING
1701 /* When doing symbol listings, play games with dummy fragments living
1702 outside the normal fragment chain to record the file and line info
1703 for this symbol. */
1704 if (listing & LISTING_SYMBOLS)
1706 extern struct list_info_struct * listing_tail;
1707 fragS * dummy_frag = xmalloc (sizeof (fragS));
1709 memset (dummy_frag, 0, sizeof (fragS));
1710 dummy_frag->fr_type = rs_fill;
1711 dummy_frag->line = listing_tail;
1712 symbolP = symbol_new (name, undefined_section, 0, dummy_frag);
1713 dummy_frag->fr_symbol = symbolP;
1715 else
1716 #endif
1717 symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
1719 #ifdef OBJ_COFF
1720 /* "set" symbols are local unless otherwise specified. */
1721 SF_SET_LOCAL (symbolP);
1722 #endif /* OBJ_COFF */
1723 } /* Make a new symbol. */
1725 symbol_table_insert (symbolP);
1727 * end_name = delim;
1729 if (equiv
1730 && S_IS_DEFINED (symbolP)
1731 && S_GET_SEGMENT (symbolP) != reg_section)
1732 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP));
1734 pseudo_set (symbolP);
1736 demand_empty_rest_of_line ();
1738 /* XXX Now we come to the Thumb specific bit of code. */
1740 THUMB_SET_FUNC (symbolP, 1);
1741 ARM_SET_THUMB (symbolP, 1);
1742 #if defined OBJ_ELF || defined OBJ_COFF
1743 ARM_SET_INTERWORK (symbolP, support_interwork);
1744 #endif
1747 static void
1748 s_arm (int ignore ATTRIBUTE_UNUSED)
1750 opcode_select (32);
1751 demand_empty_rest_of_line ();
1754 static void
1755 s_thumb (int ignore ATTRIBUTE_UNUSED)
1757 opcode_select (16);
1758 demand_empty_rest_of_line ();
1761 static void
1762 s_code (int unused ATTRIBUTE_UNUSED)
1764 int temp;
1766 temp = get_absolute_expression ();
1767 switch (temp)
1769 case 16:
1770 case 32:
1771 opcode_select (temp);
1772 break;
1774 default:
1775 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp);
1779 static void
1780 end_of_line (char * str)
1782 skip_whitespace (str);
1784 if (*str != '\0' && !inst.error)
1785 inst.error = _("garbage following instruction");
1788 static int
1789 skip_past_comma (char ** str)
1791 char * p = * str, c;
1792 int comma = 0;
1794 while ((c = *p) == ' ' || c == ',')
1796 p++;
1797 if (c == ',' && comma++)
1798 return FAIL;
1801 if (c == '\0')
1802 return FAIL;
1804 *str = p;
1805 return comma ? SUCCESS : FAIL;
1808 /* Return TRUE if anything in the expression is a bignum. */
1810 static int
1811 walk_no_bignums (symbolS * sp)
1813 if (symbol_get_value_expression (sp)->X_op == O_big)
1814 return 1;
1816 if (symbol_get_value_expression (sp)->X_add_symbol)
1818 return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
1819 || (symbol_get_value_expression (sp)->X_op_symbol
1820 && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
1823 return 0;
1826 static int in_my_get_expression = 0;
1828 static int
1829 my_get_expression (expressionS * ep, char ** str)
1831 char * save_in;
1832 segT seg;
1834 save_in = input_line_pointer;
1835 input_line_pointer = *str;
1836 in_my_get_expression = 1;
1837 seg = expression (ep);
1838 in_my_get_expression = 0;
1840 if (ep->X_op == O_illegal)
1842 /* We found a bad expression in md_operand(). */
1843 *str = input_line_pointer;
1844 input_line_pointer = save_in;
1845 return 1;
1848 #ifdef OBJ_AOUT
1849 if (seg != absolute_section
1850 && seg != text_section
1851 && seg != data_section
1852 && seg != bss_section
1853 && seg != undefined_section)
1855 inst.error = _("bad_segment");
1856 *str = input_line_pointer;
1857 input_line_pointer = save_in;
1858 return 1;
1860 #endif
1862 /* Get rid of any bignums now, so that we don't generate an error for which
1863 we can't establish a line number later on. Big numbers are never valid
1864 in instructions, which is where this routine is always called. */
1865 if (ep->X_op == O_big
1866 || (ep->X_add_symbol
1867 && (walk_no_bignums (ep->X_add_symbol)
1868 || (ep->X_op_symbol
1869 && walk_no_bignums (ep->X_op_symbol)))))
1871 inst.error = _("invalid constant");
1872 *str = input_line_pointer;
1873 input_line_pointer = save_in;
1874 return 1;
1877 *str = input_line_pointer;
1878 input_line_pointer = save_in;
1879 return 0;
1882 /* A standard register must be given at this point.
1883 SHIFT is the place to put it in inst.instruction.
1884 Restores input start point on error.
1885 Returns the reg#, or FAIL. */
1887 static int
1888 reg_required_here (char ** str, int shift)
1890 static char buff [128]; /* XXX */
1891 int reg;
1892 char * start = * str;
1894 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_RN].htab)) != FAIL)
1896 if (shift >= 0)
1897 inst.instruction |= reg << shift;
1898 return reg;
1901 /* Restore the start point, we may have got a reg of the wrong class. */
1902 *str = start;
1904 /* In the few cases where we might be able to accept something else
1905 this error can be overridden. */
1906 sprintf (buff, _("register expected, not '%.100s'"), start);
1907 inst.error = buff;
1909 return FAIL;
1912 /* A Intel Wireless MMX technology register
1913 must be given at this point.
1914 Shift is the place to put it in inst.instruction.
1915 Restores input start point on err.
1916 Returns the reg#, or FAIL. */
1918 static int
1919 wreg_required_here (char ** str,
1920 int shift,
1921 enum wreg_type reg_type)
1923 static char buff [128];
1924 int reg;
1925 char * start = *str;
1927 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_IWMMXT].htab)) != FAIL)
1929 if (wr_register (reg)
1930 && (reg_type == IWMMXT_REG_WR || reg_type == IWMMXT_REG_WR_OR_WC))
1932 if (shift >= 0)
1933 inst.instruction |= (reg ^ WR_PREFIX) << shift;
1934 return reg;
1936 else if (wc_register (reg)
1937 && (reg_type == IWMMXT_REG_WC || reg_type == IWMMXT_REG_WR_OR_WC))
1939 if (shift >= 0)
1940 inst.instruction |= (reg ^ WC_PREFIX) << shift;
1941 return reg;
1943 else if ((wcg_register (reg) && reg_type == IWMMXT_REG_WCG))
1945 if (shift >= 0)
1946 inst.instruction |= ((reg ^ WC_PREFIX) - 8) << shift;
1947 return reg;
1951 /* Restore the start point, we may have got a reg of the wrong class. */
1952 *str = start;
1954 /* In the few cases where we might be able to accept
1955 something else this error can be overridden. */
1956 sprintf (buff, _("Intel Wireless MMX technology register expected, not '%.100s'"), start);
1957 inst.error = buff;
1959 return FAIL;
1962 static const struct asm_psr *
1963 arm_psr_parse (char ** ccp)
1965 char * start = * ccp;
1966 char c;
1967 char * p;
1968 const struct asm_psr * psr;
1970 p = start;
1972 /* Skip to the end of the next word in the input stream. */
1975 c = *p++;
1977 while (ISALPHA (c) || c == '_');
1979 /* Terminate the word. */
1980 *--p = 0;
1982 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
1983 feature for ease of use and backwards compatibility. */
1984 if (!strncmp (start, "cpsr", 4))
1985 strncpy (start, "CPSR", 4);
1986 else if (!strncmp (start, "spsr", 4))
1987 strncpy (start, "SPSR", 4);
1989 /* Now locate the word in the psr hash table. */
1990 psr = (const struct asm_psr *) hash_find (arm_psr_hsh, start);
1992 /* Restore the input stream. */
1993 *p = c;
1995 /* If we found a valid match, advance the
1996 stream pointer past the end of the word. */
1997 *ccp = p;
1999 return psr;
2002 /* Parse the input looking for a PSR flag. */
2004 static int
2005 psr_required_here (char ** str)
2007 char * start = * str;
2008 const struct asm_psr * psr;
2010 psr = arm_psr_parse (str);
2012 if (psr)
2014 /* If this is the SPSR that is being modified, set the R bit. */
2015 if (! psr->cpsr)
2016 inst.instruction |= SPSR_BIT;
2018 /* Set the psr flags in the MSR instruction. */
2019 inst.instruction |= psr->field << PSR_SHIFT;
2021 return SUCCESS;
2024 /* In the few cases where we might be able to accept
2025 something else this error can be overridden. */
2026 inst.error = _("flag for {c}psr instruction expected");
2028 /* Restore the start point. */
2029 *str = start;
2030 return FAIL;
2033 static int
2034 co_proc_number (char ** str)
2036 int processor, pchar;
2037 char *start;
2039 skip_whitespace (*str);
2040 start = *str;
2042 /* The data sheet seems to imply that just a number on its own is valid
2043 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
2044 accept either. */
2045 if ((processor = arm_reg_parse (str, all_reg_maps[REG_TYPE_CP].htab))
2046 == FAIL)
2048 *str = start;
2050 pchar = *(*str)++;
2051 if (pchar >= '0' && pchar <= '9')
2053 processor = pchar - '0';
2054 if (**str >= '0' && **str <= '9')
2056 processor = processor * 10 + *(*str)++ - '0';
2057 if (processor > 15)
2059 inst.error = _("illegal co-processor number");
2060 return FAIL;
2064 else
2066 inst.error = all_reg_maps[REG_TYPE_CP].expected;
2067 return FAIL;
2071 inst.instruction |= processor << 8;
2072 return SUCCESS;
2075 static int
2076 cp_opc_expr (char ** str, int where, int length)
2078 expressionS expr;
2080 skip_whitespace (* str);
2082 memset (&expr, '\0', sizeof (expr));
2084 if (my_get_expression (&expr, str))
2085 return FAIL;
2086 if (expr.X_op != O_constant)
2088 inst.error = _("bad or missing expression");
2089 return FAIL;
2092 if ((expr.X_add_number & ((1 << length) - 1)) != expr.X_add_number)
2094 inst.error = _("immediate co-processor expression too large");
2095 return FAIL;
2098 inst.instruction |= expr.X_add_number << where;
2099 return SUCCESS;
2102 static int
2103 cp_reg_required_here (char ** str, int where)
2105 int reg;
2106 char * start = *str;
2108 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
2110 inst.instruction |= reg << where;
2111 return reg;
2114 /* In the few cases where we might be able to accept something else
2115 this error can be overridden. */
2116 inst.error = all_reg_maps[REG_TYPE_CN].expected;
2118 /* Restore the start point. */
2119 *str = start;
2120 return FAIL;
2123 static int
2124 fp_reg_required_here (char ** str, int where)
2126 int reg;
2127 char * start = * str;
2129 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_FN].htab)) != FAIL)
2131 inst.instruction |= reg << where;
2132 return reg;
2135 /* In the few cases where we might be able to accept something else
2136 this error can be overridden. */
2137 inst.error = all_reg_maps[REG_TYPE_FN].expected;
2139 /* Restore the start point. */
2140 *str = start;
2141 return FAIL;
2144 static int
2145 cp_address_offset (char ** str)
2147 int offset;
2149 skip_whitespace (* str);
2151 if (! is_immediate_prefix (**str))
2153 inst.error = _("immediate expression expected");
2154 return FAIL;
2157 (*str)++;
2159 if (my_get_expression (& inst.reloc.exp, str))
2160 return FAIL;
2162 if (inst.reloc.exp.X_op == O_constant)
2164 offset = inst.reloc.exp.X_add_number;
2166 if (offset & 3)
2168 inst.error = _("co-processor address must be word aligned");
2169 return FAIL;
2172 if (offset > 1023 || offset < -1023)
2174 inst.error = _("offset too large");
2175 return FAIL;
2178 if (offset >= 0)
2179 inst.instruction |= INDEX_UP;
2180 else
2181 offset = -offset;
2183 inst.instruction |= offset >> 2;
2185 else
2186 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
2188 return SUCCESS;
2191 static int
2192 cp_address_required_here (char ** str, int wb_ok)
2194 char * p = * str;
2195 int pre_inc = 0;
2196 int write_back = 0;
2198 if (*p == '[')
2200 int reg;
2202 p++;
2203 skip_whitespace (p);
2205 if ((reg = reg_required_here (& p, 16)) == FAIL)
2206 return FAIL;
2208 skip_whitespace (p);
2210 if (*p == ']')
2212 p++;
2214 skip_whitespace (p);
2216 if (*p == '\0')
2218 /* As an extension to the official ARM syntax we allow:
2219 [Rn]
2220 as a short hand for:
2221 [Rn,#0] */
2222 inst.instruction |= PRE_INDEX | INDEX_UP;
2223 *str = p;
2224 return SUCCESS;
2227 if (skip_past_comma (& p) == FAIL)
2229 inst.error = _("comma expected after closing square bracket");
2230 return FAIL;
2233 skip_whitespace (p);
2235 if (*p == '#')
2237 if (wb_ok)
2239 /* [Rn], #expr */
2240 write_back = WRITE_BACK;
2242 if (reg == REG_PC)
2244 inst.error = _("pc may not be used in post-increment");
2245 return FAIL;
2248 if (cp_address_offset (& p) == FAIL)
2249 return FAIL;
2251 else
2252 pre_inc = PRE_INDEX | INDEX_UP;
2254 else if (*p == '{')
2256 int option;
2258 /* [Rn], {<expr>} */
2259 p++;
2261 skip_whitespace (p);
2263 if (my_get_expression (& inst.reloc.exp, & p))
2264 return FAIL;
2266 if (inst.reloc.exp.X_op == O_constant)
2268 option = inst.reloc.exp.X_add_number;
2270 if (option > 255 || option < 0)
2272 inst.error = _("'option' field too large");
2273 return FAIL;
2276 skip_whitespace (p);
2278 if (*p != '}')
2280 inst.error = _("'}' expected at end of 'option' field");
2281 return FAIL;
2283 else
2285 p++;
2286 inst.instruction |= option;
2287 inst.instruction |= INDEX_UP;
2290 else
2292 inst.error = _("non-constant expressions for 'option' field not supported");
2293 return FAIL;
2296 else
2298 inst.error = _("# or { expected after comma");
2299 return FAIL;
2302 else
2304 /* '['Rn, #expr']'[!] */
2306 if (skip_past_comma (& p) == FAIL)
2308 inst.error = _("pre-indexed expression expected");
2309 return FAIL;
2312 pre_inc = PRE_INDEX;
2314 if (cp_address_offset (& p) == FAIL)
2315 return FAIL;
2317 skip_whitespace (p);
2319 if (*p++ != ']')
2321 inst.error = _("missing ]");
2322 return FAIL;
2325 skip_whitespace (p);
2327 if (wb_ok && *p == '!')
2329 if (reg == REG_PC)
2331 inst.error = _("pc may not be used with write-back");
2332 return FAIL;
2335 p++;
2336 write_back = WRITE_BACK;
2340 else
2342 if (my_get_expression (&inst.reloc.exp, &p))
2343 return FAIL;
2345 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
2346 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
2347 inst.reloc.pc_rel = 1;
2348 inst.instruction |= (REG_PC << 16);
2349 pre_inc = PRE_INDEX;
2352 inst.instruction |= write_back | pre_inc;
2353 *str = p;
2354 return SUCCESS;
2357 static int
2358 cp_byte_address_offset (char ** str)
2360 int offset;
2362 skip_whitespace (* str);
2364 if (! is_immediate_prefix (**str))
2366 inst.error = _("immediate expression expected");
2367 return FAIL;
2370 (*str)++;
2372 if (my_get_expression (& inst.reloc.exp, str))
2373 return FAIL;
2375 if (inst.reloc.exp.X_op == O_constant)
2377 offset = inst.reloc.exp.X_add_number;
2379 if (offset > 255 || offset < -255)
2381 inst.error = _("offset too large");
2382 return FAIL;
2385 if (offset >= 0)
2386 inst.instruction |= INDEX_UP;
2387 else
2388 offset = -offset;
2390 inst.instruction |= offset;
2392 else
2393 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
2395 return SUCCESS;
2398 static int
2399 cp_byte_address_required_here (char ** str)
2401 char * p = * str;
2402 int pre_inc = 0;
2403 int write_back = 0;
2405 if (*p == '[')
2407 int reg;
2409 p++;
2410 skip_whitespace (p);
2412 if ((reg = reg_required_here (& p, 16)) == FAIL)
2413 return FAIL;
2415 skip_whitespace (p);
2417 if (*p == ']')
2419 p++;
2421 if (skip_past_comma (& p) == SUCCESS)
2423 /* [Rn], #expr */
2424 write_back = WRITE_BACK;
2426 if (reg == REG_PC)
2428 inst.error = _("pc may not be used in post-increment");
2429 return FAIL;
2432 if (cp_byte_address_offset (& p) == FAIL)
2433 return FAIL;
2435 else
2436 pre_inc = PRE_INDEX | INDEX_UP;
2438 else
2440 /* '['Rn, #expr']'[!] */
2442 if (skip_past_comma (& p) == FAIL)
2444 inst.error = _("pre-indexed expression expected");
2445 return FAIL;
2448 pre_inc = PRE_INDEX;
2450 if (cp_byte_address_offset (& p) == FAIL)
2451 return FAIL;
2453 skip_whitespace (p);
2455 if (*p++ != ']')
2457 inst.error = _("missing ]");
2458 return FAIL;
2461 skip_whitespace (p);
2463 if (*p == '!')
2465 if (reg == REG_PC)
2467 inst.error = _("pc may not be used with write-back");
2468 return FAIL;
2471 p++;
2472 write_back = WRITE_BACK;
2476 else
2478 if (my_get_expression (&inst.reloc.exp, &p))
2479 return FAIL;
2481 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
2482 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
2483 inst.reloc.pc_rel = 1;
2484 inst.instruction |= (REG_PC << 16);
2485 pre_inc = PRE_INDEX;
2488 inst.instruction |= write_back | pre_inc;
2489 *str = p;
2490 return SUCCESS;
2493 static void
2494 do_nop (char * str)
2496 skip_whitespace (str);
2497 if (*str == '{')
2499 str++;
2501 if (my_get_expression (&inst.reloc.exp, &str))
2502 inst.reloc.exp.X_op = O_illegal;
2503 else
2505 skip_whitespace (str);
2506 if (*str == '}')
2507 str++;
2508 else
2509 inst.reloc.exp.X_op = O_illegal;
2512 if (inst.reloc.exp.X_op != O_constant
2513 || inst.reloc.exp.X_add_number > 255
2514 || inst.reloc.exp.X_add_number < 0)
2516 inst.error = _("Invalid NOP hint");
2517 return;
2520 /* Arcitectural NOP hints are CPSR sets with no bits selected. */
2521 inst.instruction &= 0xf0000000;
2522 inst.instruction |= 0x0320f000 + inst.reloc.exp.X_add_number;
2525 end_of_line (str);
2528 static void
2529 do_empty (char * str)
2531 /* Do nothing really. */
2532 end_of_line (str);
2535 static void
2536 do_mrs (char * str)
2538 int skip = 0;
2540 /* Only one syntax. */
2541 skip_whitespace (str);
2543 if (reg_required_here (&str, 12) == FAIL)
2545 inst.error = BAD_ARGS;
2546 return;
2549 if (skip_past_comma (&str) == FAIL)
2551 inst.error = _("comma expected after register name");
2552 return;
2555 skip_whitespace (str);
2557 if ( streq (str, "CPSR")
2558 || streq (str, "SPSR")
2559 /* Lower case versions for backwards compatibility. */
2560 || streq (str, "cpsr")
2561 || streq (str, "spsr"))
2562 skip = 4;
2564 /* This is for backwards compatibility with older toolchains. */
2565 else if ( streq (str, "cpsr_all")
2566 || streq (str, "spsr_all"))
2567 skip = 8;
2568 else
2570 inst.error = _("CPSR or SPSR expected");
2571 return;
2574 if (* str == 's' || * str == 'S')
2575 inst.instruction |= SPSR_BIT;
2576 str += skip;
2578 end_of_line (str);
2581 /* Two possible forms:
2582 "{C|S}PSR_<field>, Rm",
2583 "{C|S}PSR_f, #expression". */
2585 static void
2586 do_msr (char * str)
2588 skip_whitespace (str);
2590 if (psr_required_here (& str) == FAIL)
2591 return;
2593 if (skip_past_comma (& str) == FAIL)
2595 inst.error = _("comma missing after psr flags");
2596 return;
2599 skip_whitespace (str);
2601 if (reg_required_here (& str, 0) != FAIL)
2603 inst.error = NULL;
2604 end_of_line (str);
2605 return;
2608 if (! is_immediate_prefix (* str))
2610 inst.error =
2611 _("only a register or immediate value can follow a psr flag");
2612 return;
2615 str ++;
2616 inst.error = NULL;
2618 if (my_get_expression (& inst.reloc.exp, & str))
2620 inst.error =
2621 _("only a register or immediate value can follow a psr flag");
2622 return;
2625 inst.instruction |= INST_IMMEDIATE;
2627 if (inst.reloc.exp.X_add_symbol)
2629 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
2630 inst.reloc.pc_rel = 0;
2632 else
2634 unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
2636 if (value == (unsigned) FAIL)
2638 inst.error = _("invalid constant");
2639 return;
2642 inst.instruction |= value;
2645 inst.error = NULL;
2646 end_of_line (str);
2649 /* Long Multiply Parser
2650 UMULL RdLo, RdHi, Rm, Rs
2651 SMULL RdLo, RdHi, Rm, Rs
2652 UMLAL RdLo, RdHi, Rm, Rs
2653 SMLAL RdLo, RdHi, Rm, Rs. */
2655 static void
2656 do_mull (char * str)
2658 int rdlo, rdhi, rm, rs;
2660 /* Only one format "rdlo, rdhi, rm, rs". */
2661 skip_whitespace (str);
2663 if ((rdlo = reg_required_here (&str, 12)) == FAIL)
2665 inst.error = BAD_ARGS;
2666 return;
2669 if (skip_past_comma (&str) == FAIL
2670 || (rdhi = reg_required_here (&str, 16)) == FAIL)
2672 inst.error = BAD_ARGS;
2673 return;
2676 if (skip_past_comma (&str) == FAIL
2677 || (rm = reg_required_here (&str, 0)) == FAIL)
2679 inst.error = BAD_ARGS;
2680 return;
2683 /* rdhi, rdlo and rm must all be different. */
2684 if (rdlo == rdhi || rdlo == rm || rdhi == rm)
2685 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
2687 if (skip_past_comma (&str) == FAIL
2688 || (rs = reg_required_here (&str, 8)) == FAIL)
2690 inst.error = BAD_ARGS;
2691 return;
2694 if (rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC)
2696 inst.error = BAD_PC;
2697 return;
2700 end_of_line (str);
2703 static void
2704 do_mul (char * str)
2706 int rd, rm;
2708 /* Only one format "rd, rm, rs". */
2709 skip_whitespace (str);
2711 if ((rd = reg_required_here (&str, 16)) == FAIL)
2713 inst.error = BAD_ARGS;
2714 return;
2717 if (rd == REG_PC)
2719 inst.error = BAD_PC;
2720 return;
2723 if (skip_past_comma (&str) == FAIL
2724 || (rm = reg_required_here (&str, 0)) == FAIL)
2726 inst.error = BAD_ARGS;
2727 return;
2730 if (rm == REG_PC)
2732 inst.error = BAD_PC;
2733 return;
2736 if (rm == rd)
2737 as_tsktsk (_("rd and rm should be different in mul"));
2739 if (skip_past_comma (&str) == FAIL
2740 || (rm = reg_required_here (&str, 8)) == FAIL)
2742 inst.error = BAD_ARGS;
2743 return;
2746 if (rm == REG_PC)
2748 inst.error = BAD_PC;
2749 return;
2752 end_of_line (str);
2755 static void
2756 do_mlas (char * str, bfd_boolean is_mls)
2758 int rd, rm;
2760 /* Only one format "rd, rm, rs, rn". */
2761 skip_whitespace (str);
2763 if ((rd = reg_required_here (&str, 16)) == FAIL)
2765 inst.error = BAD_ARGS;
2766 return;
2769 if (rd == REG_PC)
2771 inst.error = BAD_PC;
2772 return;
2775 if (skip_past_comma (&str) == FAIL
2776 || (rm = reg_required_here (&str, 0)) == FAIL)
2778 inst.error = BAD_ARGS;
2779 return;
2782 if (rm == REG_PC)
2784 inst.error = BAD_PC;
2785 return;
2788 /* This restriction does not apply to mls (nor to mla in v6, but
2789 that's hard to detect at present). */
2790 if (rm == rd && !is_mls)
2791 as_tsktsk (_("rd and rm should be different in mla"));
2793 if (skip_past_comma (&str) == FAIL
2794 || (rd = reg_required_here (&str, 8)) == FAIL
2795 || skip_past_comma (&str) == FAIL
2796 || (rm = reg_required_here (&str, 12)) == FAIL)
2798 inst.error = BAD_ARGS;
2799 return;
2802 if (rd == REG_PC || rm == REG_PC)
2804 inst.error = BAD_PC;
2805 return;
2808 end_of_line (str);
2811 static void
2812 do_mla (char *str)
2814 do_mlas (str, FALSE);
2817 static void
2818 do_mls (char *str)
2820 do_mlas (str, TRUE);
2823 /* Expects *str -> the characters "acc0", possibly with leading blanks.
2824 Advances *str to the next non-alphanumeric.
2825 Returns 0, or else FAIL (in which case sets inst.error).
2827 (In a future XScale, there may be accumulators other than zero.
2828 At that time this routine and its callers can be upgraded to suit.) */
2830 static int
2831 accum0_required_here (char ** str)
2833 static char buff [128]; /* Note the address is taken. Hence, static. */
2834 char * p = * str;
2835 char c;
2836 int result = 0; /* The accum number. */
2838 skip_whitespace (p);
2840 *str = p; /* Advance caller's string pointer too. */
2841 c = *p++;
2842 while (ISALNUM (c))
2843 c = *p++;
2845 *--p = 0; /* Aap nul into input buffer at non-alnum. */
2847 if (! ( streq (*str, "acc0") || streq (*str, "ACC0")))
2849 sprintf (buff, _("acc0 expected, not '%.100s'"), *str);
2850 inst.error = buff;
2851 result = FAIL;
2854 *p = c; /* Unzap. */
2855 *str = p; /* Caller's string pointer to after match. */
2856 return result;
2859 static int
2860 ldst_extend_v4 (char ** str)
2862 int add = INDEX_UP;
2864 switch (**str)
2866 case '#':
2867 case '$':
2868 (*str)++;
2869 if (my_get_expression (& inst.reloc.exp, str))
2870 return FAIL;
2872 if (inst.reloc.exp.X_op == O_constant)
2874 int value = inst.reloc.exp.X_add_number;
2876 if (value < -255 || value > 255)
2878 inst.error = _("address offset too large");
2879 return FAIL;
2882 if (value < 0)
2884 value = -value;
2885 add = 0;
2888 /* Halfword and signextension instructions have the
2889 immediate value split across bits 11..8 and bits 3..0. */
2890 inst.instruction |= (add | HWOFFSET_IMM
2891 | ((value >> 4) << 8) | (value & 0xF));
2893 else
2895 inst.instruction |= HWOFFSET_IMM;
2896 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
2897 inst.reloc.pc_rel = 0;
2899 return SUCCESS;
2901 case '-':
2902 add = 0;
2903 /* Fall through. */
2905 case '+':
2906 (*str)++;
2907 /* Fall through. */
2909 default:
2910 if (reg_required_here (str, 0) == FAIL)
2911 return FAIL;
2913 inst.instruction |= add;
2914 return SUCCESS;
2918 /* Expects **str -> after a comma. May be leading blanks.
2919 Advances *str, recognizing a load mode, and setting inst.instruction.
2920 Returns rn, or else FAIL (in which case may set inst.error
2921 and not advance str)
2923 Note: doesn't know Rd, so no err checks that require such knowledge. */
2925 static int
2926 ld_mode_required_here (char ** string)
2928 char * str = * string;
2929 int rn;
2930 int pre_inc = 0;
2932 skip_whitespace (str);
2934 if (* str == '[')
2936 str++;
2938 skip_whitespace (str);
2940 if ((rn = reg_required_here (& str, 16)) == FAIL)
2941 return FAIL;
2943 skip_whitespace (str);
2945 if (* str == ']')
2947 str ++;
2949 if (skip_past_comma (& str) == SUCCESS)
2951 /* [Rn],... (post inc) */
2952 if (ldst_extend_v4 (&str) == FAIL)
2953 return FAIL;
2955 else /* [Rn] */
2957 skip_whitespace (str);
2959 if (* str == '!')
2961 str ++;
2962 inst.instruction |= WRITE_BACK;
2965 inst.instruction |= INDEX_UP | HWOFFSET_IMM;
2966 pre_inc = 1;
2969 else /* [Rn,...] */
2971 if (skip_past_comma (& str) == FAIL)
2973 inst.error = _("pre-indexed expression expected");
2974 return FAIL;
2977 pre_inc = 1;
2979 if (ldst_extend_v4 (&str) == FAIL)
2980 return FAIL;
2982 skip_whitespace (str);
2984 if (* str ++ != ']')
2986 inst.error = _("missing ]");
2987 return FAIL;
2990 skip_whitespace (str);
2992 if (* str == '!')
2994 str ++;
2995 inst.instruction |= WRITE_BACK;
2999 else if (* str == '=') /* ldr's "r,=label" syntax */
3000 /* We should never reach here, because <text> = <expression> is
3001 caught gas/read.c read_a_source_file() as a .set operation. */
3002 return FAIL;
3003 else /* PC +- 8 bit immediate offset. */
3005 if (my_get_expression (& inst.reloc.exp, & str))
3006 return FAIL;
3008 inst.instruction |= HWOFFSET_IMM; /* The I bit. */
3009 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
3010 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
3011 inst.reloc.pc_rel = 1;
3012 inst.instruction |= (REG_PC << 16);
3014 rn = REG_PC;
3015 pre_inc = 1;
3018 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
3019 * string = str;
3021 return rn;
3024 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
3025 SMLAxy{cond} Rd,Rm,Rs,Rn
3026 SMLAWy{cond} Rd,Rm,Rs,Rn
3027 Error if any register is R15. */
3029 static void
3030 do_smla (char * str)
3032 int rd, rm, rs, rn;
3034 skip_whitespace (str);
3036 if ((rd = reg_required_here (& str, 16)) == FAIL
3037 || skip_past_comma (& str) == FAIL
3038 || (rm = reg_required_here (& str, 0)) == FAIL
3039 || skip_past_comma (& str) == FAIL
3040 || (rs = reg_required_here (& str, 8)) == FAIL
3041 || skip_past_comma (& str) == FAIL
3042 || (rn = reg_required_here (& str, 12)) == FAIL)
3043 inst.error = BAD_ARGS;
3045 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC || rn == REG_PC)
3046 inst.error = BAD_PC;
3048 else
3049 end_of_line (str);
3052 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
3053 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
3054 Error if any register is R15.
3055 Warning if Rdlo == Rdhi. */
3057 static void
3058 do_smlal (char * str)
3060 int rdlo, rdhi, rm, rs;
3062 skip_whitespace (str);
3064 if ((rdlo = reg_required_here (& str, 12)) == FAIL
3065 || skip_past_comma (& str) == FAIL
3066 || (rdhi = reg_required_here (& str, 16)) == FAIL
3067 || skip_past_comma (& str) == FAIL
3068 || (rm = reg_required_here (& str, 0)) == FAIL
3069 || skip_past_comma (& str) == FAIL
3070 || (rs = reg_required_here (& str, 8)) == FAIL)
3072 inst.error = BAD_ARGS;
3073 return;
3076 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
3078 inst.error = BAD_PC;
3079 return;
3082 if (rdlo == rdhi)
3083 as_tsktsk (_("rdhi and rdlo must be different"));
3085 end_of_line (str);
3088 /* ARM V5E (El Segundo) signed-multiply (argument parse)
3089 SMULxy{cond} Rd,Rm,Rs
3090 Error if any register is R15. */
3092 static void
3093 do_smul (char * str)
3095 int rd, rm, rs;
3097 skip_whitespace (str);
3099 if ((rd = reg_required_here (& str, 16)) == FAIL
3100 || skip_past_comma (& str) == FAIL
3101 || (rm = reg_required_here (& str, 0)) == FAIL
3102 || skip_past_comma (& str) == FAIL
3103 || (rs = reg_required_here (& str, 8)) == FAIL)
3104 inst.error = BAD_ARGS;
3106 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC)
3107 inst.error = BAD_PC;
3109 else
3110 end_of_line (str);
3113 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
3114 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
3115 Error if any register is R15. */
3117 static void
3118 do_qadd (char * str)
3120 int rd, rm, rn;
3122 skip_whitespace (str);
3124 if ((rd = reg_required_here (& str, 12)) == FAIL
3125 || skip_past_comma (& str) == FAIL
3126 || (rm = reg_required_here (& str, 0)) == FAIL
3127 || skip_past_comma (& str) == FAIL
3128 || (rn = reg_required_here (& str, 16)) == FAIL)
3129 inst.error = BAD_ARGS;
3131 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
3132 inst.error = BAD_PC;
3134 else
3135 end_of_line (str);
3138 /* ARM V5E (el Segundo)
3139 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3140 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3142 These are equivalent to the XScale instructions MAR and MRA,
3143 respectively, when coproc == 0, opcode == 0, and CRm == 0.
3145 Result unpredicatable if Rd or Rn is R15. */
3147 static void
3148 do_co_reg2c (char * str)
3150 int rd, rn;
3152 skip_whitespace (str);
3154 if (co_proc_number (& str) == FAIL)
3156 if (!inst.error)
3157 inst.error = BAD_ARGS;
3158 return;
3161 if (skip_past_comma (& str) == FAIL
3162 || cp_opc_expr (& str, 4, 4) == FAIL)
3164 if (!inst.error)
3165 inst.error = BAD_ARGS;
3166 return;
3169 if (skip_past_comma (& str) == FAIL
3170 || (rd = reg_required_here (& str, 12)) == FAIL)
3172 if (!inst.error)
3173 inst.error = BAD_ARGS;
3174 return;
3177 if (skip_past_comma (& str) == FAIL
3178 || (rn = reg_required_here (& str, 16)) == FAIL)
3180 if (!inst.error)
3181 inst.error = BAD_ARGS;
3182 return;
3185 /* Unpredictable result if rd or rn is R15. */
3186 if (rd == REG_PC || rn == REG_PC)
3187 as_tsktsk
3188 (_("Warning: instruction unpredictable when using r15"));
3190 if (skip_past_comma (& str) == FAIL
3191 || cp_reg_required_here (& str, 0) == FAIL)
3193 if (!inst.error)
3194 inst.error = BAD_ARGS;
3195 return;
3198 end_of_line (str);
3201 /* ARM V5 count-leading-zeroes instruction (argument parse)
3202 CLZ{<cond>} <Rd>, <Rm>
3203 Condition defaults to COND_ALWAYS.
3204 Error if Rd or Rm are R15. */
3206 static void
3207 do_clz (char * str)
3209 int rd, rm;
3211 skip_whitespace (str);
3213 if (((rd = reg_required_here (& str, 12)) == FAIL)
3214 || (skip_past_comma (& str) == FAIL)
3215 || ((rm = reg_required_here (& str, 0)) == FAIL))
3216 inst.error = BAD_ARGS;
3218 else if (rd == REG_PC || rm == REG_PC )
3219 inst.error = BAD_PC;
3221 else
3222 end_of_line (str);
3225 /* ARM V5 (argument parse)
3226 LDC2{L} <coproc>, <CRd>, <addressing mode>
3227 STC2{L} <coproc>, <CRd>, <addressing mode>
3228 Instruction is not conditional, and has 0xf in the condition field.
3229 Otherwise, it's the same as LDC/STC. */
3231 static void
3232 do_lstc2 (char * str)
3234 skip_whitespace (str);
3236 if (co_proc_number (& str) == FAIL)
3238 if (!inst.error)
3239 inst.error = BAD_ARGS;
3241 else if (skip_past_comma (& str) == FAIL
3242 || cp_reg_required_here (& str, 12) == FAIL)
3244 if (!inst.error)
3245 inst.error = BAD_ARGS;
3247 else if (skip_past_comma (& str) == FAIL
3248 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
3250 if (! inst.error)
3251 inst.error = BAD_ARGS;
3253 else
3254 end_of_line (str);
3257 /* ARM V5 (argument parse)
3258 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
3259 Instruction is not conditional, and has 0xf in the condition field.
3260 Otherwise, it's the same as CDP. */
3262 static void
3263 do_cdp2 (char * str)
3265 skip_whitespace (str);
3267 if (co_proc_number (& str) == FAIL)
3269 if (!inst.error)
3270 inst.error = BAD_ARGS;
3271 return;
3274 if (skip_past_comma (& str) == FAIL
3275 || cp_opc_expr (& str, 20,4) == FAIL)
3277 if (!inst.error)
3278 inst.error = BAD_ARGS;
3279 return;
3282 if (skip_past_comma (& str) == FAIL
3283 || cp_reg_required_here (& str, 12) == FAIL)
3285 if (!inst.error)
3286 inst.error = BAD_ARGS;
3287 return;
3290 if (skip_past_comma (& str) == FAIL
3291 || cp_reg_required_here (& str, 16) == FAIL)
3293 if (!inst.error)
3294 inst.error = BAD_ARGS;
3295 return;
3298 if (skip_past_comma (& str) == FAIL
3299 || cp_reg_required_here (& str, 0) == FAIL)
3301 if (!inst.error)
3302 inst.error = BAD_ARGS;
3303 return;
3306 if (skip_past_comma (& str) == SUCCESS)
3308 if (cp_opc_expr (& str, 5, 3) == FAIL)
3310 if (!inst.error)
3311 inst.error = BAD_ARGS;
3312 return;
3316 end_of_line (str);
3319 /* ARM V5 (argument parse)
3320 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3321 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3322 Instruction is not conditional, and has 0xf in the condition field.
3323 Otherwise, it's the same as MCR/MRC. */
3325 static void
3326 do_co_reg2 (char * str)
3328 skip_whitespace (str);
3330 if (co_proc_number (& str) == FAIL)
3332 if (!inst.error)
3333 inst.error = BAD_ARGS;
3334 return;
3337 if (skip_past_comma (& str) == FAIL
3338 || cp_opc_expr (& str, 21, 3) == FAIL)
3340 if (!inst.error)
3341 inst.error = BAD_ARGS;
3342 return;
3345 if (skip_past_comma (& str) == FAIL
3346 || reg_required_here (& str, 12) == FAIL)
3348 if (!inst.error)
3349 inst.error = BAD_ARGS;
3350 return;
3353 if (skip_past_comma (& str) == FAIL
3354 || cp_reg_required_here (& str, 16) == FAIL)
3356 if (!inst.error)
3357 inst.error = BAD_ARGS;
3358 return;
3361 if (skip_past_comma (& str) == FAIL
3362 || cp_reg_required_here (& str, 0) == FAIL)
3364 if (!inst.error)
3365 inst.error = BAD_ARGS;
3366 return;
3369 if (skip_past_comma (& str) == SUCCESS)
3371 if (cp_opc_expr (& str, 5, 3) == FAIL)
3373 if (!inst.error)
3374 inst.error = BAD_ARGS;
3375 return;
3379 end_of_line (str);
3382 static void
3383 do_bx (char * str)
3385 int reg;
3387 skip_whitespace (str);
3389 if ((reg = reg_required_here (&str, 0)) == FAIL)
3391 inst.error = BAD_ARGS;
3392 return;
3395 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
3396 if (reg == REG_PC)
3397 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
3399 end_of_line (str);
3402 /* ARM v5TEJ. Jump to Jazelle code. */
3404 static void
3405 do_bxj (char * str)
3407 int reg;
3409 skip_whitespace (str);
3411 if ((reg = reg_required_here (&str, 0)) == FAIL)
3413 inst.error = BAD_ARGS;
3414 return;
3417 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
3418 if (reg == REG_PC)
3419 as_tsktsk (_("use of r15 in bxj is not really useful"));
3421 end_of_line (str);
3424 /* ARM V6 umaal (argument parse). */
3426 static void
3427 do_umaal (char * str)
3429 int rdlo, rdhi, rm, rs;
3431 skip_whitespace (str);
3432 if ((rdlo = reg_required_here (& str, 12)) == FAIL
3433 || skip_past_comma (& str) == FAIL
3434 || (rdhi = reg_required_here (& str, 16)) == FAIL
3435 || skip_past_comma (& str) == FAIL
3436 || (rm = reg_required_here (& str, 0)) == FAIL
3437 || skip_past_comma (& str) == FAIL
3438 || (rs = reg_required_here (& str, 8)) == FAIL)
3440 inst.error = BAD_ARGS;
3441 return;
3444 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
3446 inst.error = BAD_PC;
3447 return;
3450 end_of_line (str);
3453 /* ARM V6 strex (argument parse). */
3455 static void
3456 do_strex (char * str)
3458 int rd, rm, rn;
3460 /* Parse Rd, Rm,. */
3461 skip_whitespace (str);
3462 if ((rd = reg_required_here (& str, 12)) == FAIL
3463 || skip_past_comma (& str) == FAIL
3464 || (rm = reg_required_here (& str, 0)) == FAIL
3465 || skip_past_comma (& str) == FAIL)
3467 inst.error = BAD_ARGS;
3468 return;
3470 if (rd == REG_PC || rm == REG_PC)
3472 inst.error = BAD_PC;
3473 return;
3475 if (rd == rm)
3477 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
3478 return;
3481 /* Skip past '['. */
3482 if ((strlen (str) >= 1)
3483 && strncmp (str, "[", 1) == 0)
3484 str += 1;
3486 skip_whitespace (str);
3488 /* Parse Rn. */
3489 if ((rn = reg_required_here (& str, 16)) == FAIL)
3491 inst.error = BAD_ARGS;
3492 return;
3494 else if (rn == REG_PC)
3496 inst.error = BAD_PC;
3497 return;
3499 if (rd == rn)
3501 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
3502 return;
3504 skip_whitespace (str);
3506 /* Skip past ']'. */
3507 if ((strlen (str) >= 1)
3508 && strncmp (str, "]", 1) == 0)
3509 str += 1;
3511 end_of_line (str);
3514 /* KIND indicates what kind of shifts are accepted. */
3516 static int
3517 decode_shift (char ** str, int kind)
3519 const struct asm_shift_name * shift;
3520 char * p;
3521 char c;
3523 skip_whitespace (* str);
3525 for (p = * str; ISALPHA (* p); p ++)
3528 if (p == * str)
3530 inst.error = _("shift expression expected");
3531 return FAIL;
3534 c = * p;
3535 * p = '\0';
3536 shift = (const struct asm_shift_name *) hash_find (arm_shift_hsh, * str);
3537 * p = c;
3539 if (shift == NULL)
3541 inst.error = _("shift expression expected");
3542 return FAIL;
3545 assert (shift->properties->index == shift_properties[shift->properties->index].index);
3547 if (kind == SHIFT_LSL_OR_ASR_IMMEDIATE
3548 && shift->properties->index != SHIFT_LSL
3549 && shift->properties->index != SHIFT_ASR)
3551 inst.error = _("'LSL' or 'ASR' required");
3552 return FAIL;
3554 else if (kind == SHIFT_LSL_IMMEDIATE
3555 && shift->properties->index != SHIFT_LSL)
3557 inst.error = _("'LSL' required");
3558 return FAIL;
3560 else if (kind == SHIFT_ASR_IMMEDIATE
3561 && shift->properties->index != SHIFT_ASR)
3563 inst.error = _("'ASR' required");
3564 return FAIL;
3567 if (shift->properties->index == SHIFT_RRX)
3569 * str = p;
3570 inst.instruction |= shift->properties->bit_field;
3571 return SUCCESS;
3574 skip_whitespace (p);
3576 if (kind == NO_SHIFT_RESTRICT && reg_required_here (& p, 8) != FAIL)
3578 inst.instruction |= shift->properties->bit_field | SHIFT_BY_REG;
3579 * str = p;
3580 return SUCCESS;
3582 else if (! is_immediate_prefix (* p))
3584 inst.error = (NO_SHIFT_RESTRICT
3585 ? _("shift requires register or #expression")
3586 : _("shift requires #expression"));
3587 * str = p;
3588 return FAIL;
3591 inst.error = NULL;
3592 p ++;
3594 if (my_get_expression (& inst.reloc.exp, & p))
3595 return FAIL;
3597 /* Validate some simple #expressions. */
3598 if (inst.reloc.exp.X_op == O_constant)
3600 unsigned num = inst.reloc.exp.X_add_number;
3602 /* Reject operations greater than 32. */
3603 if (num > 32
3604 /* Reject a shift of 0 unless the mode allows it. */
3605 || (num == 0 && shift->properties->allows_0 == 0)
3606 /* Reject a shift of 32 unless the mode allows it. */
3607 || (num == 32 && shift->properties->allows_32 == 0)
3610 /* As a special case we allow a shift of zero for
3611 modes that do not support it to be recoded as an
3612 logical shift left of zero (ie nothing). We warn
3613 about this though. */
3614 if (num == 0)
3616 as_warn (_("shift of 0 ignored."));
3617 shift = & shift_names[0];
3618 assert (shift->properties->index == SHIFT_LSL);
3620 else
3622 inst.error = _("invalid immediate shift");
3623 return FAIL;
3627 /* Shifts of 32 are encoded as 0, for those shifts that
3628 support it. */
3629 if (num == 32)
3630 num = 0;
3632 inst.instruction |= (num << 7) | shift->properties->bit_field;
3634 else
3636 inst.reloc.type = BFD_RELOC_ARM_SHIFT_IMM;
3637 inst.reloc.pc_rel = 0;
3638 inst.instruction |= shift->properties->bit_field;
3641 * str = p;
3642 return SUCCESS;
3645 static void
3646 do_sat (char ** str, int bias)
3648 int rd, rm;
3649 expressionS expr;
3651 skip_whitespace (*str);
3653 /* Parse <Rd>, field. */
3654 if ((rd = reg_required_here (str, 12)) == FAIL
3655 || skip_past_comma (str) == FAIL)
3657 inst.error = BAD_ARGS;
3658 return;
3660 if (rd == REG_PC)
3662 inst.error = BAD_PC;
3663 return;
3666 /* Parse #<immed>, field. */
3667 if (is_immediate_prefix (**str))
3668 (*str)++;
3669 else
3671 inst.error = _("immediate expression expected");
3672 return;
3674 if (my_get_expression (&expr, str))
3676 inst.error = _("bad expression");
3677 return;
3679 if (expr.X_op != O_constant)
3681 inst.error = _("constant expression expected");
3682 return;
3684 if (expr.X_add_number + bias < 0
3685 || expr.X_add_number + bias > 31)
3687 inst.error = _("immediate value out of range");
3688 return;
3690 inst.instruction |= (expr.X_add_number + bias) << 16;
3691 if (skip_past_comma (str) == FAIL)
3693 inst.error = BAD_ARGS;
3694 return;
3697 /* Parse <Rm> field. */
3698 if ((rm = reg_required_here (str, 0)) == FAIL)
3700 inst.error = BAD_ARGS;
3701 return;
3703 if (rm == REG_PC)
3705 inst.error = BAD_PC;
3706 return;
3709 if (skip_past_comma (str) == SUCCESS)
3710 decode_shift (str, SHIFT_LSL_OR_ASR_IMMEDIATE);
3713 /* ARM V6 ssat (argument parse). */
3715 static void
3716 do_ssat (char * str)
3718 do_sat (&str, /*bias=*/-1);
3719 end_of_line (str);
3722 /* ARM V6 usat (argument parse). */
3724 static void
3725 do_usat (char * str)
3727 do_sat (&str, /*bias=*/0);
3728 end_of_line (str);
3731 static void
3732 do_sat16 (char ** str, int bias)
3734 int rd, rm;
3735 expressionS expr;
3737 skip_whitespace (*str);
3739 /* Parse the <Rd> field. */
3740 if ((rd = reg_required_here (str, 12)) == FAIL
3741 || skip_past_comma (str) == FAIL)
3743 inst.error = BAD_ARGS;
3744 return;
3746 if (rd == REG_PC)
3748 inst.error = BAD_PC;
3749 return;
3752 /* Parse #<immed>, field. */
3753 if (is_immediate_prefix (**str))
3754 (*str)++;
3755 else
3757 inst.error = _("immediate expression expected");
3758 return;
3760 if (my_get_expression (&expr, str))
3762 inst.error = _("bad expression");
3763 return;
3765 if (expr.X_op != O_constant)
3767 inst.error = _("constant expression expected");
3768 return;
3770 if (expr.X_add_number + bias < 0
3771 || expr.X_add_number + bias > 15)
3773 inst.error = _("immediate value out of range");
3774 return;
3776 inst.instruction |= (expr.X_add_number + bias) << 16;
3777 if (skip_past_comma (str) == FAIL)
3779 inst.error = BAD_ARGS;
3780 return;
3783 /* Parse <Rm> field. */
3784 if ((rm = reg_required_here (str, 0)) == FAIL)
3786 inst.error = BAD_ARGS;
3787 return;
3789 if (rm == REG_PC)
3791 inst.error = BAD_PC;
3792 return;
3796 /* ARM V6 ssat16 (argument parse). */
3798 static void
3799 do_ssat16 (char * str)
3801 do_sat16 (&str, /*bias=*/-1);
3802 end_of_line (str);
3805 static void
3806 do_usat16 (char * str)
3808 do_sat16 (&str, /*bias=*/0);
3809 end_of_line (str);
3812 static void
3813 do_cps_mode (char ** str)
3815 expressionS expr;
3817 skip_whitespace (*str);
3819 if (! is_immediate_prefix (**str))
3821 inst.error = _("immediate expression expected");
3822 return;
3825 (*str)++; /* Strip off the immediate signifier. */
3826 if (my_get_expression (&expr, str))
3828 inst.error = _("bad expression");
3829 return;
3832 if (expr.X_op != O_constant)
3834 inst.error = _("constant expression expected");
3835 return;
3838 /* The mode is a 5 bit field. Valid values are 0-31. */
3839 if (((unsigned) expr.X_add_number) > 31
3840 || (inst.reloc.exp.X_add_number) < 0)
3842 inst.error = _("invalid constant");
3843 return;
3846 inst.instruction |= expr.X_add_number;
3849 /* ARM V6 srs (argument parse). */
3851 static void
3852 do_srs (char * str)
3854 char *exclam;
3855 skip_whitespace (str);
3856 exclam = strchr (str, '!');
3857 if (exclam)
3858 *exclam = '\0';
3859 do_cps_mode (&str);
3860 if (exclam)
3861 *exclam = '!';
3862 if (*str == '!')
3864 inst.instruction |= WRITE_BACK;
3865 str++;
3867 end_of_line (str);
3870 /* ARM V6 SMMUL (argument parse). */
3872 static void
3873 do_smmul (char * str)
3875 int rd, rm, rs;
3877 skip_whitespace (str);
3878 if ((rd = reg_required_here (&str, 16)) == FAIL
3879 || skip_past_comma (&str) == FAIL
3880 || (rm = reg_required_here (&str, 0)) == FAIL
3881 || skip_past_comma (&str) == FAIL
3882 || (rs = reg_required_here (&str, 8)) == FAIL)
3884 inst.error = BAD_ARGS;
3885 return;
3888 if ( rd == REG_PC
3889 || rm == REG_PC
3890 || rs == REG_PC)
3892 inst.error = BAD_PC;
3893 return;
3896 end_of_line (str);
3899 /* ARM V6 SMLALD (argument parse). */
3901 static void
3902 do_smlald (char * str)
3904 int rdlo, rdhi, rm, rs;
3906 skip_whitespace (str);
3907 if ((rdlo = reg_required_here (&str, 12)) == FAIL
3908 || skip_past_comma (&str) == FAIL
3909 || (rdhi = reg_required_here (&str, 16)) == FAIL
3910 || skip_past_comma (&str) == FAIL
3911 || (rm = reg_required_here (&str, 0)) == FAIL
3912 || skip_past_comma (&str) == FAIL
3913 || (rs = reg_required_here (&str, 8)) == FAIL)
3915 inst.error = BAD_ARGS;
3916 return;
3919 if ( rdlo == REG_PC
3920 || rdhi == REG_PC
3921 || rm == REG_PC
3922 || rs == REG_PC)
3924 inst.error = BAD_PC;
3925 return;
3928 end_of_line (str);
3931 /* ARM V6 SMLAD (argument parse). Signed multiply accumulate dual.
3932 smlad{x}{<cond>} Rd, Rm, Rs, Rn */
3934 static void
3935 do_smlad (char * str)
3937 int rd, rm, rs, rn;
3939 skip_whitespace (str);
3940 if ((rd = reg_required_here (&str, 16)) == FAIL
3941 || skip_past_comma (&str) == FAIL
3942 || (rm = reg_required_here (&str, 0)) == FAIL
3943 || skip_past_comma (&str) == FAIL
3944 || (rs = reg_required_here (&str, 8)) == FAIL
3945 || skip_past_comma (&str) == FAIL
3946 || (rn = reg_required_here (&str, 12)) == FAIL)
3948 inst.error = BAD_ARGS;
3949 return;
3952 if ( rd == REG_PC
3953 || rn == REG_PC
3954 || rs == REG_PC
3955 || rm == REG_PC)
3957 inst.error = BAD_PC;
3958 return;
3961 end_of_line (str);
3964 /* Returns true if the endian-specifier indicates big-endianness. */
3966 static int
3967 do_endian_specifier (char * str)
3969 int big_endian = 0;
3971 skip_whitespace (str);
3972 if (strlen (str) < 2)
3973 inst.error = _("missing endian specifier");
3974 else if (strncasecmp (str, "BE", 2) == 0)
3976 str += 2;
3977 big_endian = 1;
3979 else if (strncasecmp (str, "LE", 2) == 0)
3980 str += 2;
3981 else
3982 inst.error = _("valid endian specifiers are be or le");
3984 end_of_line (str);
3986 return big_endian;
3989 /* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
3990 preserving the other bits.
3992 setend <endian_specifier>, where <endian_specifier> is either
3993 BE or LE. */
3995 static void
3996 do_setend (char * str)
3998 if (do_endian_specifier (str))
3999 inst.instruction |= 0x200;
4002 /* ARM V6 SXTH.
4004 SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
4005 Condition defaults to COND_ALWAYS.
4006 Error if any register uses R15. */
4008 static void
4009 do_sxth (char * str)
4011 int rd, rm;
4012 expressionS expr;
4013 int rotation_clear_mask = 0xfffff3ff;
4014 int rotation_eight_mask = 0x00000400;
4015 int rotation_sixteen_mask = 0x00000800;
4016 int rotation_twenty_four_mask = 0x00000c00;
4018 skip_whitespace (str);
4019 if ((rd = reg_required_here (&str, 12)) == FAIL
4020 || skip_past_comma (&str) == FAIL
4021 || (rm = reg_required_here (&str, 0)) == FAIL)
4023 inst.error = BAD_ARGS;
4024 return;
4027 else if (rd == REG_PC || rm == REG_PC)
4029 inst.error = BAD_PC;
4030 return;
4033 /* Zero out the rotation field. */
4034 inst.instruction &= rotation_clear_mask;
4036 /* Check for lack of optional rotation field. */
4037 if (skip_past_comma (&str) == FAIL)
4039 end_of_line (str);
4040 return;
4043 /* Move past 'ROR'. */
4044 skip_whitespace (str);
4045 if (strncasecmp (str, "ROR", 3) == 0)
4046 str += 3;
4047 else
4049 inst.error = _("missing rotation field after comma");
4050 return;
4053 /* Get the immediate constant. */
4054 skip_whitespace (str);
4055 if (is_immediate_prefix (* str))
4056 str++;
4057 else
4059 inst.error = _("immediate expression expected");
4060 return;
4063 if (my_get_expression (&expr, &str))
4065 inst.error = _("bad expression");
4066 return;
4069 if (expr.X_op != O_constant)
4071 inst.error = _("constant expression expected");
4072 return;
4075 switch (expr.X_add_number)
4077 case 0:
4078 /* Rotation field has already been zeroed. */
4079 break;
4080 case 8:
4081 inst.instruction |= rotation_eight_mask;
4082 break;
4084 case 16:
4085 inst.instruction |= rotation_sixteen_mask;
4086 break;
4088 case 24:
4089 inst.instruction |= rotation_twenty_four_mask;
4090 break;
4092 default:
4093 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
4094 break;
4097 end_of_line (str);
4100 /* ARM V6 SXTAH extracts a 16-bit value from a register, sign
4101 extends it to 32-bits, and adds the result to a value in another
4102 register. You can specify a rotation by 0, 8, 16, or 24 bits
4103 before extracting the 16-bit value.
4104 SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
4105 Condition defaults to COND_ALWAYS.
4106 Error if any register uses R15. */
4108 static void
4109 do_sxtah (char * str)
4111 int rd, rn, rm;
4112 expressionS expr;
4113 int rotation_clear_mask = 0xfffff3ff;
4114 int rotation_eight_mask = 0x00000400;
4115 int rotation_sixteen_mask = 0x00000800;
4116 int rotation_twenty_four_mask = 0x00000c00;
4118 skip_whitespace (str);
4119 if ((rd = reg_required_here (&str, 12)) == FAIL
4120 || skip_past_comma (&str) == FAIL
4121 || (rn = reg_required_here (&str, 16)) == FAIL
4122 || skip_past_comma (&str) == FAIL
4123 || (rm = reg_required_here (&str, 0)) == FAIL)
4125 inst.error = BAD_ARGS;
4126 return;
4129 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
4131 inst.error = BAD_PC;
4132 return;
4135 /* Zero out the rotation field. */
4136 inst.instruction &= rotation_clear_mask;
4138 /* Check for lack of optional rotation field. */
4139 if (skip_past_comma (&str) == FAIL)
4141 end_of_line (str);
4142 return;
4145 /* Move past 'ROR'. */
4146 skip_whitespace (str);
4147 if (strncasecmp (str, "ROR", 3) == 0)
4148 str += 3;
4149 else
4151 inst.error = _("missing rotation field after comma");
4152 return;
4155 /* Get the immediate constant. */
4156 skip_whitespace (str);
4157 if (is_immediate_prefix (* str))
4158 str++;
4159 else
4161 inst.error = _("immediate expression expected");
4162 return;
4165 if (my_get_expression (&expr, &str))
4167 inst.error = _("bad expression");
4168 return;
4171 if (expr.X_op != O_constant)
4173 inst.error = _("constant expression expected");
4174 return;
4177 switch (expr.X_add_number)
4179 case 0:
4180 /* Rotation field has already been zeroed. */
4181 break;
4183 case 8:
4184 inst.instruction |= rotation_eight_mask;
4185 break;
4187 case 16:
4188 inst.instruction |= rotation_sixteen_mask;
4189 break;
4191 case 24:
4192 inst.instruction |= rotation_twenty_four_mask;
4193 break;
4195 default:
4196 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
4197 break;
4200 end_of_line (str);
4204 /* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
4205 word at the specified address and the following word
4206 respectively.
4207 Unconditionally executed.
4208 Error if Rn is R15. */
4210 static void
4211 do_rfe (char * str)
4213 int rn;
4215 skip_whitespace (str);
4217 if ((rn = reg_required_here (&str, 16)) == FAIL)
4218 return;
4220 if (rn == REG_PC)
4222 inst.error = BAD_PC;
4223 return;
4226 skip_whitespace (str);
4228 if (*str == '!')
4230 inst.instruction |= WRITE_BACK;
4231 str++;
4233 end_of_line (str);
4236 /* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
4237 register (argument parse).
4238 REV{<cond>} Rd, Rm.
4239 Condition defaults to COND_ALWAYS.
4240 Error if Rd or Rm are R15. */
4242 static void
4243 do_rev (char * str)
4245 int rd, rm;
4247 skip_whitespace (str);
4249 if ((rd = reg_required_here (&str, 12)) == FAIL
4250 || skip_past_comma (&str) == FAIL
4251 || (rm = reg_required_here (&str, 0)) == FAIL)
4252 inst.error = BAD_ARGS;
4254 else if (rd == REG_PC || rm == REG_PC)
4255 inst.error = BAD_PC;
4257 else
4258 end_of_line (str);
4261 /* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
4262 QADD16{<cond>} <Rd>, <Rn>, <Rm>
4263 Condition defaults to COND_ALWAYS.
4264 Error if Rd, Rn or Rm are R15. */
4266 static void
4267 do_qadd16 (char * str)
4269 int rd, rm, rn;
4271 skip_whitespace (str);
4273 if ((rd = reg_required_here (&str, 12)) == FAIL
4274 || skip_past_comma (&str) == FAIL
4275 || (rn = reg_required_here (&str, 16)) == FAIL
4276 || skip_past_comma (&str) == FAIL
4277 || (rm = reg_required_here (&str, 0)) == FAIL)
4278 inst.error = BAD_ARGS;
4280 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
4281 inst.error = BAD_PC;
4283 else
4284 end_of_line (str);
4287 static void
4288 do_pkh_core (char * str, int shift)
4290 int rd, rn, rm;
4292 skip_whitespace (str);
4293 if (((rd = reg_required_here (&str, 12)) == FAIL)
4294 || (skip_past_comma (&str) == FAIL)
4295 || ((rn = reg_required_here (&str, 16)) == FAIL)
4296 || (skip_past_comma (&str) == FAIL)
4297 || ((rm = reg_required_here (&str, 0)) == FAIL))
4299 inst.error = BAD_ARGS;
4300 return;
4303 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
4305 inst.error = BAD_PC;
4306 return;
4309 /* Check for optional shift immediate constant. */
4310 if (skip_past_comma (&str) == FAIL)
4312 if (shift == SHIFT_ASR_IMMEDIATE)
4314 /* If the shift specifier is ommited, turn the instruction
4315 into pkhbt rd, rm, rn. First, switch the instruction
4316 code, and clear the rn and rm fields. */
4317 inst.instruction &= 0xfff0f010;
4318 /* Now, re-encode the registers. */
4319 inst.instruction |= (rm << 16) | rn;
4321 return;
4324 decode_shift (&str, shift);
4327 /* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
4328 PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
4329 Condition defaults to COND_ALWAYS.
4330 Error if Rd, Rn or Rm are R15. */
4332 static void
4333 do_pkhbt (char * str)
4335 do_pkh_core (str, SHIFT_LSL_IMMEDIATE);
4338 /* ARM V6 PKHTB (Argument Parse). */
4340 static void
4341 do_pkhtb (char * str)
4343 do_pkh_core (str, SHIFT_ASR_IMMEDIATE);
4346 /* ARM V6 Load Register Exclusive instruction (argument parse).
4347 LDREX{,B,D,H}{<cond>} <Rd, [<Rn>]
4348 Condition defaults to COND_ALWAYS.
4349 Error if Rd or Rn are R15.
4350 See ARMARMv6 A4.1.27: LDREX. */
4352 static void
4353 do_ldrex (char * str)
4355 int rd, rn;
4357 skip_whitespace (str);
4359 /* Parse Rd. */
4360 if (((rd = reg_required_here (&str, 12)) == FAIL)
4361 || (skip_past_comma (&str) == FAIL))
4363 inst.error = BAD_ARGS;
4364 return;
4366 else if (rd == REG_PC)
4368 inst.error = BAD_PC;
4369 return;
4371 skip_whitespace (str);
4373 /* Skip past '['. */
4374 if ((strlen (str) >= 1)
4375 &&strncmp (str, "[", 1) == 0)
4376 str += 1;
4377 skip_whitespace (str);
4379 /* Parse Rn. */
4380 if ((rn = reg_required_here (&str, 16)) == FAIL)
4382 inst.error = BAD_ARGS;
4383 return;
4385 else if (rn == REG_PC)
4387 inst.error = BAD_PC;
4388 return;
4390 skip_whitespace (str);
4392 /* Skip past ']'. */
4393 if ((strlen (str) >= 1)
4394 && strncmp (str, "]", 1) == 0)
4395 str += 1;
4397 end_of_line (str);
4400 /* ARM V6 change processor state instruction (argument parse)
4401 CPS, CPSIE, CSPID . */
4403 static void
4404 do_cps (char * str)
4406 do_cps_mode (&str);
4407 end_of_line (str);
4410 static void
4411 do_cps_flags (char ** str, int thumb_p)
4413 struct cps_flag
4415 char character;
4416 unsigned long arm_value;
4417 unsigned long thumb_value;
4419 static struct cps_flag flag_table[] =
4421 {'a', 0x100, 0x4 },
4422 {'i', 0x080, 0x2 },
4423 {'f', 0x040, 0x1 }
4426 int saw_a_flag = 0;
4428 skip_whitespace (*str);
4430 /* Get the a, f and i flags. */
4431 while (**str && **str != ',')
4433 struct cps_flag *p;
4434 struct cps_flag *q = flag_table + sizeof (flag_table)/sizeof (*p);
4436 for (p = flag_table; p < q; ++p)
4437 if (strncasecmp (*str, &p->character, 1) == 0)
4439 inst.instruction |= (thumb_p ? p->thumb_value : p->arm_value);
4440 saw_a_flag = 1;
4441 break;
4443 if (p == q)
4445 inst.error = _("unrecognized flag");
4446 return;
4448 (*str)++;
4451 if (!saw_a_flag)
4452 inst.error = _("no 'a', 'i', or 'f' flags for 'cps'");
4455 static void
4456 do_cpsi (char * str)
4458 do_cps_flags (&str, /*thumb_p=*/0);
4460 if (skip_past_comma (&str) == SUCCESS)
4462 skip_whitespace (str);
4463 do_cps_mode (&str);
4465 end_of_line (str);
4468 /* ARM V6T2 bitfield manipulation instructions. */
4470 static int
4471 five_bit_unsigned_immediate (char **str)
4473 expressionS expr;
4475 skip_whitespace (*str);
4476 if (!is_immediate_prefix (**str))
4478 inst.error = _("immediate expression expected");
4479 return -1;
4481 (*str)++;
4482 if (my_get_expression (&expr, str))
4484 inst.error = _("bad expression");
4485 return -1;
4487 if (expr.X_op != O_constant)
4489 inst.error = _("constant expression expected");
4490 return -1;
4492 if (expr.X_add_number < 0 || expr.X_add_number > 32)
4494 inst.error = _("immediate value out of range");
4495 return -1;
4498 return expr.X_add_number;
4501 static void
4502 bfci_lsb_and_width (char *str)
4504 int lsb, width;
4506 if ((lsb = five_bit_unsigned_immediate (&str)) == -1)
4507 return;
4509 if (skip_past_comma (&str) == FAIL)
4511 inst.error = BAD_ARGS;
4512 return;
4514 if ((width = five_bit_unsigned_immediate (&str)) == -1)
4515 return;
4517 end_of_line (str);
4519 if (width == 0 || lsb == 32)
4521 inst.error = _("immediate value out of range");
4522 return;
4524 else if (width + lsb > 32)
4526 inst.error = _("bit-field extends past end of register");
4527 return;
4530 /* Convert to LSB/MSB and write to register. */
4531 inst.instruction |= lsb << 7;
4532 inst.instruction |= (width + lsb - 1) << 16;
4535 static void
4536 do_bfc (char *str)
4538 int rd;
4540 /* Rd. */
4541 skip_whitespace (str);
4542 if (((rd = reg_required_here (&str, 12)) == FAIL)
4543 || (skip_past_comma (&str) == FAIL))
4545 inst.error = BAD_ARGS;
4546 return;
4548 else if (rd == REG_PC)
4550 inst.error = BAD_PC;
4551 return;
4554 bfci_lsb_and_width (str);
4557 static void
4558 do_bfi (char *str)
4560 int rd, rm;
4562 /* Rd. */
4563 skip_whitespace (str);
4564 if (((rd = reg_required_here (&str, 12)) == FAIL)
4565 || (skip_past_comma (&str) == FAIL))
4567 inst.error = BAD_ARGS;
4568 return;
4570 else if (rd == REG_PC)
4572 inst.error = BAD_PC;
4573 return;
4576 /* Rm. Accept #0 in this position as an alternative syntax for bfc. */
4577 skip_whitespace (str);
4578 if (is_immediate_prefix (*str))
4580 expressionS expr;
4581 str++;
4582 if (my_get_expression (&expr, &str))
4584 inst.error = _("bad expression");
4585 return;
4587 if (expr.X_op != O_constant)
4589 inst.error = _("constant expression expected");
4590 return;
4592 if (expr.X_add_number != 0)
4594 inst.error = _("immediate value out of range");
4595 return;
4597 inst.instruction |= 0x0000000f; /* Rm = PC -> bfc, not bfi. */
4599 else
4601 if ((rm = reg_required_here (&str, 0)) == FAIL)
4603 inst.error = BAD_ARGS;
4604 return;
4606 else if (rm == REG_PC)
4608 inst.error = BAD_PC;
4609 return;
4612 if (skip_past_comma (&str) == FAIL)
4614 inst.error = BAD_ARGS;
4615 return;
4618 bfci_lsb_and_width (str);
4621 static void
4622 do_bfx (char *str)
4624 int lsb, width;
4626 /* Rd. */
4627 skip_whitespace (str);
4628 if (reg_required_here (&str, 12) == FAIL
4629 || skip_past_comma (&str) == FAIL)
4631 inst.error = BAD_ARGS;
4632 return;
4635 /* Rm. */
4636 skip_whitespace (str);
4637 if (reg_required_here (&str, 0) == FAIL
4638 || skip_past_comma (&str) == FAIL)
4640 inst.error = BAD_ARGS;
4641 return;
4644 if ((lsb = five_bit_unsigned_immediate (&str)) == -1)
4645 return;
4647 if (skip_past_comma (&str) == FAIL)
4649 inst.error = BAD_ARGS;
4650 return;
4652 if ((width = five_bit_unsigned_immediate (&str)) == -1)
4653 return;
4655 end_of_line (str);
4657 if (width == 0 || lsb == 32)
4659 inst.error = _("immediate value out of range");
4660 return;
4662 else if (width + lsb > 32)
4664 inst.error = _("bit-field extends past end of register");
4665 return;
4668 inst.instruction |= lsb << 7;
4669 inst.instruction |= (width - 1) << 16;
4672 static void
4673 do_rbit (char *str)
4675 /* Rd. */
4676 skip_whitespace (str);
4677 if (reg_required_here (&str, 12) == FAIL
4678 || skip_past_comma (&str) == FAIL)
4680 inst.error = BAD_ARGS;
4681 return;
4684 /* Rm. */
4685 skip_whitespace (str);
4686 if (reg_required_here (&str, 0) == FAIL)
4688 inst.error = BAD_ARGS;
4689 return;
4692 end_of_line (str);
4695 /* ARM V6T2 16-bit immediate register load: MOV[WT]{cond} Rd, #<imm16>. */
4696 static void
4697 do_mov16 (char *str)
4699 int rd;
4700 expressionS expr;
4702 /* Rd. */
4703 skip_whitespace (str);
4704 if (((rd = reg_required_here (&str, 12)) == FAIL)
4705 || (skip_past_comma (&str) == FAIL))
4707 inst.error = BAD_ARGS;
4708 return;
4710 else if (rd == REG_PC)
4712 inst.error = BAD_PC;
4713 return;
4716 /* Imm16. */
4717 skip_whitespace (str);
4718 if (!is_immediate_prefix (*str))
4720 inst.error = _("immediate expression expected");
4721 return;
4723 str++;
4724 if (my_get_expression (&expr, &str))
4726 inst.error = _("bad expression");
4727 return;
4729 if (expr.X_op != O_constant)
4731 inst.error = _("constant expression expected");
4732 return;
4734 if (expr.X_add_number < 0 || expr.X_add_number > 65535)
4736 inst.error = _("immediate value out of range");
4737 return;
4740 end_of_line (str);
4742 /* The value is in two pieces: 0:11, 16:19. */
4743 inst.instruction |= (expr.X_add_number & 0x00000fff);
4744 inst.instruction |= (expr.X_add_number & 0x0000f000) << 4;
4748 /* THUMB V5 breakpoint instruction (argument parse)
4749 BKPT <immed_8>. */
4751 static void
4752 do_t_bkpt (char * str)
4754 expressionS expr;
4755 unsigned long number;
4757 skip_whitespace (str);
4759 /* Allow optional leading '#'. */
4760 if (is_immediate_prefix (*str))
4761 str ++;
4763 memset (& expr, '\0', sizeof (expr));
4764 if (my_get_expression (& expr, & str)
4765 || (expr.X_op != O_constant
4766 /* As a convenience we allow 'bkpt' without an operand. */
4767 && expr.X_op != O_absent))
4769 inst.error = _("bad expression");
4770 return;
4773 number = expr.X_add_number;
4775 /* Check it fits an 8 bit unsigned. */
4776 if (number != (number & 0xff))
4778 inst.error = _("immediate value out of range");
4779 return;
4782 inst.instruction |= number;
4784 end_of_line (str);
4787 #ifdef OBJ_ELF
4788 static bfd_reloc_code_real_type
4789 arm_parse_reloc (void)
4791 char id [16];
4792 char * ip;
4793 unsigned int i;
4794 static struct
4796 char * str;
4797 int len;
4798 bfd_reloc_code_real_type reloc;
4800 reloc_map[] =
4802 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
4803 MAP ("(got)", BFD_RELOC_ARM_GOT32),
4804 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF),
4805 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
4806 branch instructions generated by GCC for PLT relocs. */
4807 MAP ("(plt)", BFD_RELOC_ARM_PLT32),
4808 MAP ("(target1)", BFD_RELOC_ARM_TARGET1),
4809 MAP ("(sbrel)", BFD_RELOC_ARM_SBREL32),
4810 MAP ("(target2)", BFD_RELOC_ARM_TARGET2),
4811 MAP ("(tlsgd)", BFD_RELOC_ARM_TLS_GD32),
4812 MAP ("(tlsldm)", BFD_RELOC_ARM_TLS_LDM32),
4813 MAP ("(tlsldo)", BFD_RELOC_ARM_TLS_LDO32),
4814 MAP ("(gottpoff)", BFD_RELOC_ARM_TLS_IE32),
4815 MAP ("(tpoff)", BFD_RELOC_ARM_TLS_LE32),
4816 { NULL, 0, BFD_RELOC_UNUSED }
4817 #undef MAP
4820 for (i = 0, ip = input_line_pointer;
4821 i < sizeof (id) && (ISALNUM (*ip) || ISPUNCT (*ip));
4822 i++, ip++)
4823 id[i] = TOLOWER (*ip);
4825 for (i = 0; reloc_map[i].str; i++)
4826 if (strncmp (id, reloc_map[i].str, reloc_map[i].len) == 0)
4827 break;
4829 input_line_pointer += reloc_map[i].len;
4831 return reloc_map[i].reloc;
4833 #endif
4835 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
4836 Expects inst.instruction is set for BLX(1).
4837 Note: this is cloned from do_branch, and the reloc changed to be a
4838 new one that can cope with setting one extra bit (the H bit). */
4840 static void
4841 do_branch25 (char * str)
4843 if (my_get_expression (& inst.reloc.exp, & str))
4844 return;
4846 #ifdef OBJ_ELF
4848 char * save_in;
4850 /* ScottB: February 5, 1998 */
4851 /* Check to see of PLT32 reloc required for the instruction. */
4853 /* arm_parse_reloc() works on input_line_pointer.
4854 We actually want to parse the operands to the branch instruction
4855 passed in 'str'. Save the input pointer and restore it later. */
4856 save_in = input_line_pointer;
4857 input_line_pointer = str;
4859 if (inst.reloc.exp.X_op == O_symbol
4860 && *str == '('
4861 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
4863 inst.reloc.type = BFD_RELOC_ARM_PLT32;
4864 inst.reloc.pc_rel = 0;
4865 /* Modify str to point to after parsed operands, otherwise
4866 end_of_line() will complain about the (PLT) left in str. */
4867 str = input_line_pointer;
4869 else
4871 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
4872 inst.reloc.pc_rel = 1;
4875 input_line_pointer = save_in;
4877 #else
4878 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
4879 inst.reloc.pc_rel = 1;
4880 #endif /* OBJ_ELF */
4882 end_of_line (str);
4885 /* ARM V5 branch-link-exchange instruction (argument parse)
4886 BLX <target_addr> ie BLX(1)
4887 BLX{<condition>} <Rm> ie BLX(2)
4888 Unfortunately, there are two different opcodes for this mnemonic.
4889 So, the insns[].value is not used, and the code here zaps values
4890 into inst.instruction.
4891 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
4893 static void
4894 do_blx (char * str)
4896 char * mystr = str;
4897 int rm;
4899 skip_whitespace (mystr);
4900 rm = reg_required_here (& mystr, 0);
4902 /* The above may set inst.error. Ignore his opinion. */
4903 inst.error = 0;
4905 if (rm != FAIL)
4907 /* Arg is a register.
4908 Use the condition code our caller put in inst.instruction.
4909 Pass ourselves off as a BX with a funny opcode. */
4910 inst.instruction |= 0x012fff30;
4911 do_bx (str);
4913 else
4915 /* This must be is BLX <target address>, no condition allowed. */
4916 if (inst.instruction != COND_ALWAYS)
4918 inst.error = BAD_COND;
4919 return;
4922 inst.instruction = 0xfafffffe;
4924 /* Process like a B/BL, but with a different reloc.
4925 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
4926 do_branch25 (str);
4930 /* ARM V5 Thumb BLX (argument parse)
4931 BLX <target_addr> which is BLX(1)
4932 BLX <Rm> which is BLX(2)
4933 Unfortunately, there are two different opcodes for this mnemonic.
4934 So, the tinsns[].value is not used, and the code here zaps values
4935 into inst.instruction. */
4937 static void
4938 do_t_blx (char * str)
4940 char * mystr = str;
4941 int rm;
4943 skip_whitespace (mystr);
4944 inst.instruction = 0x4780;
4946 /* Note that this call is to the ARM register recognizer. BLX(2)
4947 uses the ARM register space, not the Thumb one, so a call to
4948 thumb_reg() would be wrong. */
4949 rm = reg_required_here (& mystr, 3);
4950 inst.error = 0;
4952 if (rm != FAIL)
4954 /* It's BLX(2). The .instruction was zapped with rm & is final. */
4955 inst.size = 2;
4957 else
4959 /* No ARM register. This must be BLX(1). Change the .instruction. */
4960 inst.instruction = 0xf7ffeffe;
4961 inst.size = 4;
4963 if (my_get_expression (& inst.reloc.exp, & mystr))
4964 return;
4966 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BLX;
4967 inst.reloc.pc_rel = 1;
4970 end_of_line (mystr);
4973 /* ARM V5 breakpoint instruction (argument parse)
4974 BKPT <16 bit unsigned immediate>
4975 Instruction is not conditional.
4976 The bit pattern given in insns[] has the COND_ALWAYS condition,
4977 and it is an error if the caller tried to override that. */
4979 static void
4980 do_bkpt (char * str)
4982 expressionS expr;
4983 unsigned long number;
4985 skip_whitespace (str);
4987 /* Allow optional leading '#'. */
4988 if (is_immediate_prefix (* str))
4989 str++;
4991 memset (& expr, '\0', sizeof (expr));
4993 if (my_get_expression (& expr, & str)
4994 || (expr.X_op != O_constant
4995 /* As a convenience we allow 'bkpt' without an operand. */
4996 && expr.X_op != O_absent))
4998 inst.error = _("bad expression");
4999 return;
5002 number = expr.X_add_number;
5004 /* Check it fits a 16 bit unsigned. */
5005 if (number != (number & 0xffff))
5007 inst.error = _("immediate value out of range");
5008 return;
5011 /* Top 12 of 16 bits to bits 19:8. */
5012 inst.instruction |= (number & 0xfff0) << 4;
5014 /* Bottom 4 of 16 bits to bits 3:0. */
5015 inst.instruction |= number & 0xf;
5017 end_of_line (str);
5020 /* THUMB CPS instruction (argument parse). */
5022 static void
5023 do_t_cps (char * str)
5025 do_cps_flags (&str, /*thumb_p=*/1);
5026 end_of_line (str);
5029 /* Parse and validate that a register is of the right form, this saves
5030 repeated checking of this information in many similar cases.
5031 Unlike the 32-bit case we do not insert the register into the opcode
5032 here, since the position is often unknown until the full instruction
5033 has been parsed. */
5035 static int
5036 thumb_reg (char ** strp, int hi_lo)
5038 int reg;
5040 if ((reg = reg_required_here (strp, -1)) == FAIL)
5041 return FAIL;
5043 switch (hi_lo)
5045 case THUMB_REG_LO:
5046 if (reg > 7)
5048 inst.error = _("lo register required");
5049 return FAIL;
5051 break;
5053 case THUMB_REG_HI:
5054 if (reg < 8)
5056 inst.error = _("hi register required");
5057 return FAIL;
5059 break;
5061 default:
5062 break;
5065 return reg;
5068 static void
5069 thumb_mov_compare (char * str, int move)
5071 int Rd, Rs = FAIL;
5073 skip_whitespace (str);
5075 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
5076 || skip_past_comma (&str) == FAIL)
5078 if (! inst.error)
5079 inst.error = BAD_ARGS;
5080 return;
5083 if (move != THUMB_CPY && is_immediate_prefix (*str))
5085 str++;
5086 if (my_get_expression (&inst.reloc.exp, &str))
5087 return;
5089 else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
5090 return;
5092 if (Rs != FAIL)
5094 if (move != THUMB_CPY && Rs < 8 && Rd < 8)
5096 if (move == THUMB_MOVE)
5097 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
5098 since a MOV instruction produces unpredictable results. */
5099 inst.instruction = T_OPCODE_ADD_I3;
5100 else
5101 inst.instruction = T_OPCODE_CMP_LR;
5102 inst.instruction |= Rd | (Rs << 3);
5104 else
5106 if (move == THUMB_MOVE)
5107 inst.instruction = T_OPCODE_MOV_HR;
5108 else if (move != THUMB_CPY)
5109 inst.instruction = T_OPCODE_CMP_HR;
5111 if (Rd > 7)
5112 inst.instruction |= THUMB_H1;
5114 if (Rs > 7)
5115 inst.instruction |= THUMB_H2;
5117 inst.instruction |= (Rd & 7) | ((Rs & 7) << 3);
5120 else
5122 if (Rd > 7)
5124 inst.error = _("only lo regs allowed with immediate");
5125 return;
5128 if (move == THUMB_MOVE)
5129 inst.instruction = T_OPCODE_MOV_I8;
5130 else
5131 inst.instruction = T_OPCODE_CMP_I8;
5133 inst.instruction |= Rd << 8;
5135 if (inst.reloc.exp.X_op != O_constant)
5136 inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
5137 else
5139 unsigned value = inst.reloc.exp.X_add_number;
5141 if (value > 255)
5143 inst.error = _("invalid immediate");
5144 return;
5147 inst.instruction |= value;
5151 end_of_line (str);
5154 /* THUMB CPY instruction (argument parse). */
5156 static void
5157 do_t_cpy (char * str)
5159 thumb_mov_compare (str, THUMB_CPY);
5162 /* THUMB SETEND instruction (argument parse). */
5164 static void
5165 do_t_setend (char * str)
5167 if (do_endian_specifier (str))
5168 inst.instruction |= 0x8;
5171 /* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
5173 static unsigned long
5174 check_iwmmxt_insn (char * str,
5175 enum iwmmxt_insn_type insn_type,
5176 int immediate_size)
5178 int reg = 0;
5179 const char * inst_error;
5180 expressionS expr;
5181 unsigned long number;
5183 inst_error = inst.error;
5184 if (!inst.error)
5185 inst.error = BAD_ARGS;
5186 skip_whitespace (str);
5188 switch (insn_type)
5190 case check_rd:
5191 if ((reg = reg_required_here (&str, 12)) == FAIL)
5192 return FAIL;
5193 break;
5195 case check_wr:
5196 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR)) == FAIL)
5197 return FAIL;
5198 break;
5200 case check_wrwr:
5201 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5202 || skip_past_comma (&str) == FAIL
5203 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
5204 return FAIL;
5205 break;
5207 case check_wrwrwr:
5208 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5209 || skip_past_comma (&str) == FAIL
5210 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5211 || skip_past_comma (&str) == FAIL
5212 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
5213 return FAIL;
5214 break;
5216 case check_wrwrwcg:
5217 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5218 || skip_past_comma (&str) == FAIL
5219 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5220 || skip_past_comma (&str) == FAIL
5221 || wreg_required_here (&str, 0, IWMMXT_REG_WCG) == FAIL))
5222 return FAIL;
5223 break;
5225 case check_tbcst:
5226 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5227 || skip_past_comma (&str) == FAIL
5228 || reg_required_here (&str, 12) == FAIL))
5229 return FAIL;
5230 break;
5232 case check_tmovmsk:
5233 if ((reg_required_here (&str, 12) == FAIL
5234 || skip_past_comma (&str) == FAIL
5235 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
5236 return FAIL;
5237 break;
5239 case check_tmia:
5240 if ((wreg_required_here (&str, 5, IWMMXT_REG_WR) == FAIL
5241 || skip_past_comma (&str) == FAIL
5242 || reg_required_here (&str, 0) == FAIL
5243 || skip_past_comma (&str) == FAIL
5244 || reg_required_here (&str, 12) == FAIL))
5245 return FAIL;
5246 break;
5248 case check_tmcrr:
5249 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
5250 || skip_past_comma (&str) == FAIL
5251 || reg_required_here (&str, 12) == FAIL
5252 || skip_past_comma (&str) == FAIL
5253 || reg_required_here (&str, 16) == FAIL))
5254 return FAIL;
5255 break;
5257 case check_tmrrc:
5258 if ((reg_required_here (&str, 12) == FAIL
5259 || skip_past_comma (&str) == FAIL
5260 || reg_required_here (&str, 16) == FAIL
5261 || skip_past_comma (&str) == FAIL
5262 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
5263 return FAIL;
5264 break;
5266 case check_tmcr:
5267 if ((wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL
5268 || skip_past_comma (&str) == FAIL
5269 || reg_required_here (&str, 12) == FAIL))
5270 return FAIL;
5271 break;
5273 case check_tmrc:
5274 if ((reg_required_here (&str, 12) == FAIL
5275 || skip_past_comma (&str) == FAIL
5276 || wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL))
5277 return FAIL;
5278 break;
5280 case check_tinsr:
5281 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5282 || skip_past_comma (&str) == FAIL
5283 || reg_required_here (&str, 12) == FAIL
5284 || skip_past_comma (&str) == FAIL))
5285 return FAIL;
5286 break;
5288 case check_textrc:
5289 if ((reg_required_here (&str, 12) == FAIL
5290 || skip_past_comma (&str) == FAIL))
5291 return FAIL;
5292 break;
5294 case check_waligni:
5295 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5296 || skip_past_comma (&str) == FAIL
5297 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5298 || skip_past_comma (&str) == FAIL
5299 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
5300 || skip_past_comma (&str) == FAIL))
5301 return FAIL;
5302 break;
5304 case check_textrm:
5305 if ((reg_required_here (&str, 12) == FAIL
5306 || skip_past_comma (&str) == FAIL
5307 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5308 || skip_past_comma (&str) == FAIL))
5309 return FAIL;
5310 break;
5312 case check_wshufh:
5313 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5314 || skip_past_comma (&str) == FAIL
5315 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5316 || skip_past_comma (&str) == FAIL))
5317 return FAIL;
5318 break;
5321 if (immediate_size == 0)
5323 end_of_line (str);
5324 inst.error = inst_error;
5325 return reg;
5327 else
5329 skip_whitespace (str);
5331 /* Allow optional leading '#'. */
5332 if (is_immediate_prefix (* str))
5333 str++;
5335 memset (& expr, '\0', sizeof (expr));
5337 if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
5339 inst.error = _("bad or missing expression");
5340 return FAIL;
5343 number = expr.X_add_number;
5345 if (number != (number & immediate_size))
5347 inst.error = _("immediate value out of range");
5348 return FAIL;
5350 end_of_line (str);
5351 inst.error = inst_error;
5352 return number;
5356 static void
5357 do_iwmmxt_byte_addr (char * str)
5359 int op = (inst.instruction & 0x300) >> 8;
5360 int reg;
5362 inst.instruction &= ~0x300;
5363 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
5365 skip_whitespace (str);
5367 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
5368 || skip_past_comma (& str) == FAIL
5369 || cp_byte_address_required_here (&str) == FAIL)
5371 if (! inst.error)
5372 inst.error = BAD_ARGS;
5374 else
5375 end_of_line (str);
5377 if (wc_register (reg))
5379 as_bad (_("non-word size not supported with control register"));
5380 inst.instruction |= 0xf0000100;
5381 inst.instruction &= ~0x00400000;
5385 static void
5386 do_iwmmxt_tandc (char * str)
5388 int reg;
5390 reg = check_iwmmxt_insn (str, check_rd, 0);
5392 if (reg != REG_PC && !inst.error)
5393 inst.error = _("only r15 allowed here");
5396 static void
5397 do_iwmmxt_tbcst (char * str)
5399 check_iwmmxt_insn (str, check_tbcst, 0);
5402 static void
5403 do_iwmmxt_textrc (char * str)
5405 unsigned long number;
5407 if ((number = check_iwmmxt_insn (str, check_textrc, 7)) == (unsigned long) FAIL)
5408 return;
5410 inst.instruction |= number & 0x7;
5413 static void
5414 do_iwmmxt_textrm (char * str)
5416 unsigned long number;
5418 if ((number = check_iwmmxt_insn (str, check_textrm, 7)) == (unsigned long) FAIL)
5419 return;
5421 inst.instruction |= number & 0x7;
5424 static void
5425 do_iwmmxt_tinsr (char * str)
5427 unsigned long number;
5429 if ((number = check_iwmmxt_insn (str, check_tinsr, 7)) == (unsigned long) FAIL)
5430 return;
5432 inst.instruction |= number & 0x7;
5435 static void
5436 do_iwmmxt_tmcr (char * str)
5438 check_iwmmxt_insn (str, check_tmcr, 0);
5441 static void
5442 do_iwmmxt_tmcrr (char * str)
5444 check_iwmmxt_insn (str, check_tmcrr, 0);
5447 static void
5448 do_iwmmxt_tmia (char * str)
5450 check_iwmmxt_insn (str, check_tmia, 0);
5453 static void
5454 do_iwmmxt_tmovmsk (char * str)
5456 check_iwmmxt_insn (str, check_tmovmsk, 0);
5459 static void
5460 do_iwmmxt_tmrc (char * str)
5462 check_iwmmxt_insn (str, check_tmrc, 0);
5465 static void
5466 do_iwmmxt_tmrrc (char * str)
5468 check_iwmmxt_insn (str, check_tmrrc, 0);
5471 static void
5472 do_iwmmxt_torc (char * str)
5474 check_iwmmxt_insn (str, check_rd, 0);
5477 static void
5478 do_iwmmxt_waligni (char * str)
5480 unsigned long number;
5482 if ((number = check_iwmmxt_insn (str, check_waligni, 7)) == (unsigned long) FAIL)
5483 return;
5485 inst.instruction |= ((number & 0x7) << 20);
5488 static void
5489 do_iwmmxt_wmov (char * str)
5491 if (check_iwmmxt_insn (str, check_wrwr, 0) == (unsigned long) FAIL)
5492 return;
5494 inst.instruction |= ((inst.instruction >> 16) & 0xf);
5497 static void
5498 do_iwmmxt_word_addr (char * str)
5500 int op = (inst.instruction & 0x300) >> 8;
5501 int reg;
5503 inst.instruction &= ~0x300;
5504 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
5506 skip_whitespace (str);
5508 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
5509 || skip_past_comma (& str) == FAIL
5510 || cp_address_required_here (& str, CP_WB_OK) == FAIL)
5512 if (! inst.error)
5513 inst.error = BAD_ARGS;
5515 else
5516 end_of_line (str);
5518 if (wc_register (reg))
5520 if ((inst.instruction & COND_MASK) != COND_ALWAYS)
5521 as_bad (_("conditional execution not supported with control register"));
5522 if (op != 2)
5523 as_bad (_("non-word size not supported with control register"));
5524 inst.instruction |= 0xf0000100;
5525 inst.instruction &= ~0x00400000;
5529 static void
5530 do_iwmmxt_wrwr (char * str)
5532 check_iwmmxt_insn (str, check_wrwr, 0);
5535 static void
5536 do_iwmmxt_wrwrwcg (char * str)
5538 check_iwmmxt_insn (str, check_wrwrwcg, 0);
5541 static void
5542 do_iwmmxt_wrwrwr (char * str)
5544 check_iwmmxt_insn (str, check_wrwrwr, 0);
5547 static void
5548 do_iwmmxt_wshufh (char * str)
5550 unsigned long number;
5552 if ((number = check_iwmmxt_insn (str, check_wshufh, 0xff)) == (unsigned long) FAIL)
5553 return;
5555 inst.instruction |= ((number & 0xf0) << 16) | (number & 0xf);
5558 static void
5559 do_iwmmxt_wzero (char * str)
5561 if (check_iwmmxt_insn (str, check_wr, 0) == (unsigned long) FAIL)
5562 return;
5564 inst.instruction |= ((inst.instruction & 0xf) << 12) | ((inst.instruction & 0xf) << 16);
5567 /* Xscale multiply-accumulate (argument parse)
5568 MIAcc acc0,Rm,Rs
5569 MIAPHcc acc0,Rm,Rs
5570 MIAxycc acc0,Rm,Rs. */
5572 static void
5573 do_xsc_mia (char * str)
5575 int rs;
5576 int rm;
5578 if (accum0_required_here (& str) == FAIL)
5579 inst.error = ERR_NO_ACCUM;
5581 else if (skip_past_comma (& str) == FAIL
5582 || (rm = reg_required_here (& str, 0)) == FAIL)
5583 inst.error = BAD_ARGS;
5585 else if (skip_past_comma (& str) == FAIL
5586 || (rs = reg_required_here (& str, 12)) == FAIL)
5587 inst.error = BAD_ARGS;
5589 /* inst.instruction has now been zapped with both rm and rs. */
5590 else if (rm == REG_PC || rs == REG_PC)
5591 inst.error = BAD_PC; /* Undefined result if rm or rs is R15. */
5593 else
5594 end_of_line (str);
5597 /* Xscale move-accumulator-register (argument parse)
5599 MARcc acc0,RdLo,RdHi. */
5601 static void
5602 do_xsc_mar (char * str)
5604 int rdlo, rdhi;
5606 if (accum0_required_here (& str) == FAIL)
5607 inst.error = ERR_NO_ACCUM;
5609 else if (skip_past_comma (& str) == FAIL
5610 || (rdlo = reg_required_here (& str, 12)) == FAIL)
5611 inst.error = BAD_ARGS;
5613 else if (skip_past_comma (& str) == FAIL
5614 || (rdhi = reg_required_here (& str, 16)) == FAIL)
5615 inst.error = BAD_ARGS;
5617 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5618 else if (rdlo == REG_PC || rdhi == REG_PC)
5619 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
5621 else
5622 end_of_line (str);
5625 /* Xscale move-register-accumulator (argument parse)
5627 MRAcc RdLo,RdHi,acc0. */
5629 static void
5630 do_xsc_mra (char * str)
5632 int rdlo;
5633 int rdhi;
5635 skip_whitespace (str);
5637 if ((rdlo = reg_required_here (& str, 12)) == FAIL)
5638 inst.error = BAD_ARGS;
5640 else if (skip_past_comma (& str) == FAIL
5641 || (rdhi = reg_required_here (& str, 16)) == FAIL)
5642 inst.error = BAD_ARGS;
5644 else if (skip_past_comma (& str) == FAIL
5645 || accum0_required_here (& str) == FAIL)
5646 inst.error = ERR_NO_ACCUM;
5648 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5649 else if (rdlo == rdhi)
5650 inst.error = BAD_ARGS; /* Undefined result if 2 writes to same reg. */
5652 else if (rdlo == REG_PC || rdhi == REG_PC)
5653 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
5654 else
5655 end_of_line (str);
5658 static int
5659 ldst_extend (char ** str)
5661 int add = INDEX_UP;
5663 switch (**str)
5665 case '#':
5666 case '$':
5667 (*str)++;
5668 if (my_get_expression (& inst.reloc.exp, str))
5669 return FAIL;
5671 if (inst.reloc.exp.X_op == O_constant)
5673 int value = inst.reloc.exp.X_add_number;
5675 if (value < -4095 || value > 4095)
5677 inst.error = _("address offset too large");
5678 return FAIL;
5681 if (value < 0)
5683 value = -value;
5684 add = 0;
5687 inst.instruction |= add | value;
5689 else
5691 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
5692 inst.reloc.pc_rel = 0;
5694 return SUCCESS;
5696 case '-':
5697 add = 0;
5698 /* Fall through. */
5700 case '+':
5701 (*str)++;
5702 /* Fall through. */
5704 default:
5705 if (reg_required_here (str, 0) == FAIL)
5706 return FAIL;
5708 inst.instruction |= add | OFFSET_REG;
5709 if (skip_past_comma (str) == SUCCESS)
5710 return decode_shift (str, SHIFT_IMMEDIATE);
5712 return SUCCESS;
5716 /* ARMv5TE: Preload-Cache
5718 PLD <addr_mode>
5720 Syntactically, like LDR with B=1, W=0, L=1. */
5722 static void
5723 do_pld (char * str)
5725 int rd;
5727 skip_whitespace (str);
5729 if (* str != '[')
5731 inst.error = _("'[' expected after PLD mnemonic");
5732 return;
5735 ++str;
5736 skip_whitespace (str);
5738 if ((rd = reg_required_here (& str, 16)) == FAIL)
5739 return;
5741 skip_whitespace (str);
5743 if (*str == ']')
5745 /* [Rn], ... ? */
5746 ++str;
5747 skip_whitespace (str);
5749 /* Post-indexed addressing is not allowed with PLD. */
5750 if (skip_past_comma (&str) == SUCCESS)
5752 inst.error
5753 = _("post-indexed expression used in preload instruction");
5754 return;
5756 else if (*str == '!') /* [Rn]! */
5758 inst.error = _("writeback used in preload instruction");
5759 ++str;
5761 else /* [Rn] */
5762 inst.instruction |= INDEX_UP | PRE_INDEX;
5764 else /* [Rn, ...] */
5766 if (skip_past_comma (& str) == FAIL)
5768 inst.error = _("pre-indexed expression expected");
5769 return;
5772 if (ldst_extend (&str) == FAIL)
5773 return;
5775 skip_whitespace (str);
5777 if (* str != ']')
5779 inst.error = _("missing ]");
5780 return;
5783 ++ str;
5784 skip_whitespace (str);
5786 if (* str == '!') /* [Rn]! */
5788 inst.error = _("writeback used in preload instruction");
5789 ++ str;
5792 inst.instruction |= PRE_INDEX;
5795 end_of_line (str);
5798 /* ARMv5TE load-consecutive (argument parse)
5799 Mode is like LDRH.
5801 LDRccD R, mode
5802 STRccD R, mode. */
5804 static void
5805 do_ldrd (char * str)
5807 int rd;
5808 int rn;
5810 skip_whitespace (str);
5812 if ((rd = reg_required_here (& str, 12)) == FAIL)
5814 inst.error = BAD_ARGS;
5815 return;
5818 if (skip_past_comma (& str) == FAIL
5819 || (rn = ld_mode_required_here (& str)) == FAIL)
5821 if (!inst.error)
5822 inst.error = BAD_ARGS;
5823 return;
5826 /* inst.instruction has now been zapped with Rd and the addressing mode. */
5827 if (rd & 1) /* Unpredictable result if Rd is odd. */
5829 inst.error = _("destination register must be even");
5830 return;
5833 if (rd == REG_LR)
5835 inst.error = _("r14 not allowed here");
5836 return;
5839 if (((rd == rn) || (rd + 1 == rn))
5840 && ((inst.instruction & WRITE_BACK)
5841 || (!(inst.instruction & PRE_INDEX))))
5842 as_warn (_("pre/post-indexing used when modified address register is destination"));
5844 /* For an index-register load, the index register must not overlap the
5845 destination (even if not write-back). */
5846 if ((inst.instruction & V4_STR_BIT) == 0
5847 && (inst.instruction & HWOFFSET_IMM) == 0)
5849 int rm = inst.instruction & 0x0000000f;
5851 if (rm == rd || (rm == rd + 1))
5852 as_warn (_("ldrd destination registers must not overlap index register"));
5855 end_of_line (str);
5858 /* Returns the index into fp_values of a floating point number,
5859 or -1 if not in the table. */
5861 static int
5862 my_get_float_expression (char ** str)
5864 LITTLENUM_TYPE words[MAX_LITTLENUMS];
5865 char * save_in;
5866 expressionS exp;
5867 int i;
5868 int j;
5870 memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE));
5872 /* Look for a raw floating point number. */
5873 if ((save_in = atof_ieee (*str, 'x', words)) != NULL
5874 && is_end_of_line[(unsigned char) *save_in])
5876 for (i = 0; i < NUM_FLOAT_VALS; i++)
5878 for (j = 0; j < MAX_LITTLENUMS; j++)
5880 if (words[j] != fp_values[i][j])
5881 break;
5884 if (j == MAX_LITTLENUMS)
5886 *str = save_in;
5887 return i;
5892 /* Try and parse a more complex expression, this will probably fail
5893 unless the code uses a floating point prefix (eg "0f"). */
5894 save_in = input_line_pointer;
5895 input_line_pointer = *str;
5896 if (expression (&exp) == absolute_section
5897 && exp.X_op == O_big
5898 && exp.X_add_number < 0)
5900 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
5901 Ditto for 15. */
5902 if (gen_to_words (words, 5, (long) 15) == 0)
5904 for (i = 0; i < NUM_FLOAT_VALS; i++)
5906 for (j = 0; j < MAX_LITTLENUMS; j++)
5908 if (words[j] != fp_values[i][j])
5909 break;
5912 if (j == MAX_LITTLENUMS)
5914 *str = input_line_pointer;
5915 input_line_pointer = save_in;
5916 return i;
5922 *str = input_line_pointer;
5923 input_line_pointer = save_in;
5924 return -1;
5927 /* We handle all bad expressions here, so that we can report the faulty
5928 instruction in the error message. */
5929 void
5930 md_operand (expressionS * expr)
5932 if (in_my_get_expression)
5934 expr->X_op = O_illegal;
5935 if (inst.error == NULL)
5936 inst.error = _("bad expression");
5940 /* Do those data_ops which can take a negative immediate constant
5941 by altering the instruction. A bit of a hack really.
5942 MOV <-> MVN
5943 AND <-> BIC
5944 ADC <-> SBC
5945 by inverting the second operand, and
5946 ADD <-> SUB
5947 CMP <-> CMN
5948 by negating the second operand. */
5950 static int
5951 negate_data_op (unsigned long * instruction,
5952 unsigned long value)
5954 int op, new_inst;
5955 unsigned long negated, inverted;
5957 negated = validate_immediate (-value);
5958 inverted = validate_immediate (~value);
5960 op = (*instruction >> DATA_OP_SHIFT) & 0xf;
5961 switch (op)
5963 /* First negates. */
5964 case OPCODE_SUB: /* ADD <-> SUB */
5965 new_inst = OPCODE_ADD;
5966 value = negated;
5967 break;
5969 case OPCODE_ADD:
5970 new_inst = OPCODE_SUB;
5971 value = negated;
5972 break;
5974 case OPCODE_CMP: /* CMP <-> CMN */
5975 new_inst = OPCODE_CMN;
5976 value = negated;
5977 break;
5979 case OPCODE_CMN:
5980 new_inst = OPCODE_CMP;
5981 value = negated;
5982 break;
5984 /* Now Inverted ops. */
5985 case OPCODE_MOV: /* MOV <-> MVN */
5986 new_inst = OPCODE_MVN;
5987 value = inverted;
5988 break;
5990 case OPCODE_MVN:
5991 new_inst = OPCODE_MOV;
5992 value = inverted;
5993 break;
5995 case OPCODE_AND: /* AND <-> BIC */
5996 new_inst = OPCODE_BIC;
5997 value = inverted;
5998 break;
6000 case OPCODE_BIC:
6001 new_inst = OPCODE_AND;
6002 value = inverted;
6003 break;
6005 case OPCODE_ADC: /* ADC <-> SBC */
6006 new_inst = OPCODE_SBC;
6007 value = inverted;
6008 break;
6010 case OPCODE_SBC:
6011 new_inst = OPCODE_ADC;
6012 value = inverted;
6013 break;
6015 /* We cannot do anything. */
6016 default:
6017 return FAIL;
6020 if (value == (unsigned) FAIL)
6021 return FAIL;
6023 *instruction &= OPCODE_MASK;
6024 *instruction |= new_inst << DATA_OP_SHIFT;
6025 return value;
6028 static int
6029 data_op2 (char ** str)
6031 int value;
6032 expressionS expr;
6034 skip_whitespace (* str);
6036 if (reg_required_here (str, 0) != FAIL)
6038 if (skip_past_comma (str) == SUCCESS)
6039 /* Shift operation on register. */
6040 return decode_shift (str, NO_SHIFT_RESTRICT);
6042 return SUCCESS;
6044 else
6046 /* Immediate expression. */
6047 if (is_immediate_prefix (**str))
6049 (*str)++;
6050 inst.error = NULL;
6052 if (my_get_expression (&inst.reloc.exp, str))
6053 return FAIL;
6055 if (inst.reloc.exp.X_add_symbol)
6057 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
6058 inst.reloc.pc_rel = 0;
6060 else
6062 if (skip_past_comma (str) == SUCCESS)
6064 /* #x, y -- ie explicit rotation by Y. */
6065 if (my_get_expression (&expr, str))
6066 return FAIL;
6068 if (expr.X_op != O_constant)
6070 inst.error = _("constant expression expected");
6071 return FAIL;
6074 /* Rotate must be a multiple of 2. */
6075 if (((unsigned) expr.X_add_number) > 30
6076 || (expr.X_add_number & 1) != 0
6077 || ((unsigned) inst.reloc.exp.X_add_number) > 255)
6079 inst.error = _("invalid constant");
6080 return FAIL;
6082 inst.instruction |= INST_IMMEDIATE;
6083 inst.instruction |= inst.reloc.exp.X_add_number;
6084 inst.instruction |= expr.X_add_number << 7;
6085 return SUCCESS;
6088 /* Implicit rotation, select a suitable one. */
6089 value = validate_immediate (inst.reloc.exp.X_add_number);
6091 if (value == FAIL)
6093 /* Can't be done. Perhaps the code reads something like
6094 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
6095 if ((value = negate_data_op (&inst.instruction,
6096 inst.reloc.exp.X_add_number))
6097 == FAIL)
6099 inst.error = _("invalid constant");
6100 return FAIL;
6104 inst.instruction |= value;
6107 inst.instruction |= INST_IMMEDIATE;
6108 return SUCCESS;
6111 (*str)++;
6112 inst.error = _("register or shift expression expected");
6113 return FAIL;
6117 static int
6118 fp_op2 (char ** str)
6120 skip_whitespace (* str);
6122 if (fp_reg_required_here (str, 0) != FAIL)
6123 return SUCCESS;
6124 else
6126 /* Immediate expression. */
6127 if (*((*str)++) == '#')
6129 int i;
6131 inst.error = NULL;
6133 skip_whitespace (* str);
6135 /* First try and match exact strings, this is to guarantee
6136 that some formats will work even for cross assembly. */
6138 for (i = 0; fp_const[i]; i++)
6140 if (strncmp (*str, fp_const[i], strlen (fp_const[i])) == 0)
6142 char *start = *str;
6144 *str += strlen (fp_const[i]);
6145 if (is_end_of_line[(unsigned char) **str])
6147 inst.instruction |= i + 8;
6148 return SUCCESS;
6150 *str = start;
6154 /* Just because we didn't get a match doesn't mean that the
6155 constant isn't valid, just that it is in a format that we
6156 don't automatically recognize. Try parsing it with
6157 the standard expression routines. */
6158 if ((i = my_get_float_expression (str)) >= 0)
6160 inst.instruction |= i + 8;
6161 return SUCCESS;
6164 inst.error = _("invalid floating point immediate expression");
6165 return FAIL;
6167 inst.error =
6168 _("floating point register or immediate expression expected");
6169 return FAIL;
6173 static void
6174 do_arit (char * str)
6176 skip_whitespace (str);
6178 if (reg_required_here (&str, 12) == FAIL
6179 || skip_past_comma (&str) == FAIL
6180 || reg_required_here (&str, 16) == FAIL
6181 || skip_past_comma (&str) == FAIL
6182 || data_op2 (&str) == FAIL)
6184 if (!inst.error)
6185 inst.error = BAD_ARGS;
6186 return;
6189 end_of_line (str);
6192 static void
6193 do_adr (char * str)
6195 /* This is a pseudo-op of the form "adr rd, label" to be converted
6196 into a relative address of the form "add rd, pc, #label-.-8". */
6197 skip_whitespace (str);
6199 if (reg_required_here (&str, 12) == FAIL
6200 || skip_past_comma (&str) == FAIL
6201 || my_get_expression (&inst.reloc.exp, &str))
6203 if (!inst.error)
6204 inst.error = BAD_ARGS;
6205 return;
6208 /* Frag hacking will turn this into a sub instruction if the offset turns
6209 out to be negative. */
6210 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
6211 #ifndef TE_WINCE
6212 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust. */
6213 #endif
6214 inst.reloc.pc_rel = 1;
6216 end_of_line (str);
6219 static void
6220 do_adrl (char * str)
6222 /* This is a pseudo-op of the form "adrl rd, label" to be converted
6223 into a relative address of the form:
6224 add rd, pc, #low(label-.-8)"
6225 add rd, rd, #high(label-.-8)" */
6227 skip_whitespace (str);
6229 if (reg_required_here (&str, 12) == FAIL
6230 || skip_past_comma (&str) == FAIL
6231 || my_get_expression (&inst.reloc.exp, &str))
6233 if (!inst.error)
6234 inst.error = BAD_ARGS;
6236 return;
6239 end_of_line (str);
6240 /* Frag hacking will turn this into a sub instruction if the offset turns
6241 out to be negative. */
6242 inst.reloc.type = BFD_RELOC_ARM_ADRL_IMMEDIATE;
6243 #ifndef TE_WINCE
6244 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust */
6245 #endif
6246 inst.reloc.pc_rel = 1;
6247 inst.size = INSN_SIZE * 2;
6250 static void
6251 do_cmp (char * str)
6253 skip_whitespace (str);
6255 if (reg_required_here (&str, 16) == FAIL)
6257 if (!inst.error)
6258 inst.error = BAD_ARGS;
6259 return;
6262 if (skip_past_comma (&str) == FAIL
6263 || data_op2 (&str) == FAIL)
6265 if (!inst.error)
6266 inst.error = BAD_ARGS;
6267 return;
6270 end_of_line (str);
6273 static void
6274 do_mov (char * str)
6276 skip_whitespace (str);
6278 if (reg_required_here (&str, 12) == FAIL)
6280 if (!inst.error)
6281 inst.error = BAD_ARGS;
6282 return;
6285 if (skip_past_comma (&str) == FAIL
6286 || data_op2 (&str) == FAIL)
6288 if (!inst.error)
6289 inst.error = BAD_ARGS;
6290 return;
6293 end_of_line (str);
6296 static void
6297 do_ldst (char * str)
6299 int pre_inc = 0;
6300 int conflict_reg;
6301 int value;
6303 skip_whitespace (str);
6305 if ((conflict_reg = reg_required_here (&str, 12)) == FAIL)
6307 if (!inst.error)
6308 inst.error = BAD_ARGS;
6309 return;
6312 if (skip_past_comma (&str) == FAIL)
6314 inst.error = _("address expected");
6315 return;
6318 if (*str == '[')
6320 int reg;
6322 str++;
6324 skip_whitespace (str);
6326 if ((reg = reg_required_here (&str, 16)) == FAIL)
6327 return;
6329 /* Conflicts can occur on stores as well as loads. */
6330 conflict_reg = (conflict_reg == reg);
6332 skip_whitespace (str);
6334 if (*str == ']')
6336 str ++;
6338 if (skip_past_comma (&str) == SUCCESS)
6340 /* [Rn],... (post inc) */
6341 if (ldst_extend (&str) == FAIL)
6342 return;
6343 if (conflict_reg)
6344 as_warn (_("%s register same as write-back base"),
6345 ((inst.instruction & LOAD_BIT)
6346 ? _("destination") : _("source")));
6348 else
6350 /* [Rn] */
6351 skip_whitespace (str);
6353 if (*str == '!')
6355 if (conflict_reg)
6356 as_warn (_("%s register same as write-back base"),
6357 ((inst.instruction & LOAD_BIT)
6358 ? _("destination") : _("source")));
6359 str++;
6360 inst.instruction |= WRITE_BACK;
6363 inst.instruction |= INDEX_UP;
6364 pre_inc = 1;
6367 else
6369 /* [Rn,...] */
6370 if (skip_past_comma (&str) == FAIL)
6372 inst.error = _("pre-indexed expression expected");
6373 return;
6376 pre_inc = 1;
6377 if (ldst_extend (&str) == FAIL)
6378 return;
6380 skip_whitespace (str);
6382 if (*str++ != ']')
6384 inst.error = _("missing ]");
6385 return;
6388 skip_whitespace (str);
6390 if (*str == '!')
6392 if (conflict_reg)
6393 as_warn (_("%s register same as write-back base"),
6394 ((inst.instruction & LOAD_BIT)
6395 ? _("destination") : _("source")));
6396 str++;
6397 inst.instruction |= WRITE_BACK;
6401 else if (*str == '=')
6403 if ((inst.instruction & LOAD_BIT) == 0)
6405 inst.error = _("invalid pseudo operation");
6406 return;
6409 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6410 str++;
6412 skip_whitespace (str);
6414 if (my_get_expression (&inst.reloc.exp, &str))
6415 return;
6417 if (inst.reloc.exp.X_op != O_constant
6418 && inst.reloc.exp.X_op != O_symbol)
6420 inst.error = _("constant expression expected");
6421 return;
6424 if (inst.reloc.exp.X_op == O_constant)
6426 value = validate_immediate (inst.reloc.exp.X_add_number);
6428 if (value != FAIL)
6430 /* This can be done with a mov instruction. */
6431 inst.instruction &= LITERAL_MASK;
6432 inst.instruction |= (INST_IMMEDIATE
6433 | (OPCODE_MOV << DATA_OP_SHIFT));
6434 inst.instruction |= value & 0xfff;
6435 end_of_line (str);
6436 return;
6439 value = validate_immediate (~inst.reloc.exp.X_add_number);
6441 if (value != FAIL)
6443 /* This can be done with a mvn instruction. */
6444 inst.instruction &= LITERAL_MASK;
6445 inst.instruction |= (INST_IMMEDIATE
6446 | (OPCODE_MVN << DATA_OP_SHIFT));
6447 inst.instruction |= value & 0xfff;
6448 end_of_line (str);
6449 return;
6453 /* Insert into literal pool. */
6454 if (add_to_lit_pool () == FAIL)
6456 if (!inst.error)
6457 inst.error = _("literal pool insertion failed");
6458 return;
6461 /* Change the instruction exp to point to the pool. */
6462 inst.reloc.type = BFD_RELOC_ARM_LITERAL;
6463 inst.reloc.pc_rel = 1;
6464 inst.instruction |= (REG_PC << 16);
6465 pre_inc = 1;
6467 else
6469 if (my_get_expression (&inst.reloc.exp, &str))
6470 return;
6472 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
6473 #ifndef TE_WINCE
6474 /* PC rel adjust. */
6475 inst.reloc.exp.X_add_number -= 8;
6476 #endif
6477 inst.reloc.pc_rel = 1;
6478 inst.instruction |= (REG_PC << 16);
6479 pre_inc = 1;
6482 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
6483 end_of_line (str);
6486 static void
6487 do_ldstt (char * str)
6489 int conflict_reg;
6491 skip_whitespace (str);
6493 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
6495 if (!inst.error)
6496 inst.error = BAD_ARGS;
6497 return;
6500 if (skip_past_comma (& str) == FAIL)
6502 inst.error = _("address expected");
6503 return;
6506 if (*str == '[')
6508 int reg;
6510 str++;
6512 skip_whitespace (str);
6514 if ((reg = reg_required_here (&str, 16)) == FAIL)
6515 return;
6517 /* ldrt/strt always use post-indexed addressing, so if the base is
6518 the same as Rd, we warn. */
6519 if (conflict_reg == reg)
6520 as_warn (_("%s register same as write-back base"),
6521 ((inst.instruction & LOAD_BIT)
6522 ? _("destination") : _("source")));
6524 skip_whitespace (str);
6526 if (*str == ']')
6528 str ++;
6530 if (skip_past_comma (&str) == SUCCESS)
6532 /* [Rn],... (post inc) */
6533 if (ldst_extend (&str) == FAIL)
6534 return;
6536 else
6538 /* [Rn] */
6539 skip_whitespace (str);
6541 /* Skip a write-back '!'. */
6542 if (*str == '!')
6543 str++;
6545 inst.instruction |= INDEX_UP;
6548 else
6550 inst.error = _("post-indexed expression expected");
6551 return;
6554 else
6556 inst.error = _("post-indexed expression expected");
6557 return;
6560 end_of_line (str);
6563 /* Halfword and signed-byte load/store operations. */
6565 static void
6566 do_ldstv4 (char * str)
6568 int pre_inc = 0;
6569 int conflict_reg;
6570 int value;
6572 skip_whitespace (str);
6574 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
6576 if (!inst.error)
6577 inst.error = BAD_ARGS;
6578 return;
6581 if (skip_past_comma (& str) == FAIL)
6583 inst.error = _("address expected");
6584 return;
6587 if (*str == '[')
6589 int reg;
6591 str++;
6593 skip_whitespace (str);
6595 if ((reg = reg_required_here (&str, 16)) == FAIL)
6596 return;
6598 /* Conflicts can occur on stores as well as loads. */
6599 conflict_reg = (conflict_reg == reg);
6601 skip_whitespace (str);
6603 if (*str == ']')
6605 str ++;
6607 if (skip_past_comma (&str) == SUCCESS)
6609 /* [Rn],... (post inc) */
6610 if (ldst_extend_v4 (&str) == FAIL)
6611 return;
6612 if (conflict_reg)
6613 as_warn (_("%s register same as write-back base"),
6614 ((inst.instruction & LOAD_BIT)
6615 ? _("destination") : _("source")));
6617 else
6619 /* [Rn] */
6620 inst.instruction |= HWOFFSET_IMM;
6622 skip_whitespace (str);
6624 if (*str == '!')
6626 if (conflict_reg)
6627 as_warn (_("%s register same as write-back base"),
6628 ((inst.instruction & LOAD_BIT)
6629 ? _("destination") : _("source")));
6630 str++;
6631 inst.instruction |= WRITE_BACK;
6634 inst.instruction |= INDEX_UP;
6635 pre_inc = 1;
6638 else
6640 /* [Rn,...] */
6641 if (skip_past_comma (&str) == FAIL)
6643 inst.error = _("pre-indexed expression expected");
6644 return;
6647 pre_inc = 1;
6648 if (ldst_extend_v4 (&str) == FAIL)
6649 return;
6651 skip_whitespace (str);
6653 if (*str++ != ']')
6655 inst.error = _("missing ]");
6656 return;
6659 skip_whitespace (str);
6661 if (*str == '!')
6663 if (conflict_reg)
6664 as_warn (_("%s register same as write-back base"),
6665 ((inst.instruction & LOAD_BIT)
6666 ? _("destination") : _("source")));
6667 str++;
6668 inst.instruction |= WRITE_BACK;
6672 else if (*str == '=')
6674 if ((inst.instruction & LOAD_BIT) == 0)
6676 inst.error = _("invalid pseudo operation");
6677 return;
6680 /* XXX Does this work correctly for half-word/byte ops? */
6681 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6682 str++;
6684 skip_whitespace (str);
6686 if (my_get_expression (&inst.reloc.exp, &str))
6687 return;
6689 if (inst.reloc.exp.X_op != O_constant
6690 && inst.reloc.exp.X_op != O_symbol)
6692 inst.error = _("constant expression expected");
6693 return;
6696 if (inst.reloc.exp.X_op == O_constant)
6698 value = validate_immediate (inst.reloc.exp.X_add_number);
6700 if (value != FAIL)
6702 /* This can be done with a mov instruction. */
6703 inst.instruction &= LITERAL_MASK;
6704 inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
6705 inst.instruction |= value & 0xfff;
6706 end_of_line (str);
6707 return;
6710 value = validate_immediate (~ inst.reloc.exp.X_add_number);
6712 if (value != FAIL)
6714 /* This can be done with a mvn instruction. */
6715 inst.instruction &= LITERAL_MASK;
6716 inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT);
6717 inst.instruction |= value & 0xfff;
6718 end_of_line (str);
6719 return;
6723 /* Insert into literal pool. */
6724 if (add_to_lit_pool () == FAIL)
6726 if (!inst.error)
6727 inst.error = _("literal pool insertion failed");
6728 return;
6731 /* Change the instruction exp to point to the pool. */
6732 inst.instruction |= HWOFFSET_IMM;
6733 inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
6734 inst.reloc.pc_rel = 1;
6735 inst.instruction |= (REG_PC << 16);
6736 pre_inc = 1;
6738 else
6740 if (my_get_expression (&inst.reloc.exp, &str))
6741 return;
6743 inst.instruction |= HWOFFSET_IMM;
6744 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
6745 #ifndef TE_WINCE
6746 /* PC rel adjust. */
6747 inst.reloc.exp.X_add_number -= 8;
6748 #endif
6749 inst.reloc.pc_rel = 1;
6750 inst.instruction |= (REG_PC << 16);
6751 pre_inc = 1;
6754 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
6755 end_of_line (str);
6758 static void
6759 do_ldsttv4 (char * str)
6761 int conflict_reg;
6763 skip_whitespace (str);
6765 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
6767 if (!inst.error)
6768 inst.error = BAD_ARGS;
6769 return;
6772 if (skip_past_comma (& str) == FAIL)
6774 inst.error = _("address expected");
6775 return;
6778 if (*str == '[')
6780 int reg;
6782 str++;
6784 skip_whitespace (str);
6786 if ((reg = reg_required_here (&str, 16)) == FAIL)
6787 return;
6789 /* ldrt/strt always use post-indexed addressing, so if the base is
6790 the same as Rd, we warn. */
6791 if (conflict_reg == reg)
6792 as_warn (_("%s register same as write-back base"),
6793 ((inst.instruction & LOAD_BIT)
6794 ? _("destination") : _("source")));
6796 skip_whitespace (str);
6798 if (*str == ']')
6800 str ++;
6802 if (skip_past_comma (&str) == SUCCESS)
6804 /* [Rn],... (post inc) */
6805 if (ldst_extend_v4 (&str) == FAIL)
6806 return;
6808 else
6810 /* [Rn] */
6811 skip_whitespace (str);
6813 /* Skip a write-back '!'. */
6814 if (*str == '!')
6815 str++;
6817 inst.instruction |= (INDEX_UP|HWOFFSET_IMM);
6820 else
6822 inst.error = _("post-indexed expression expected");
6823 return;
6826 else
6828 inst.error = _("post-indexed expression expected");
6829 return;
6832 end_of_line (str);
6836 static long
6837 reg_list (char ** strp)
6839 char * str = * strp;
6840 long range = 0;
6841 int another_range;
6843 /* We come back here if we get ranges concatenated by '+' or '|'. */
6846 another_range = 0;
6848 if (*str == '{')
6850 int in_range = 0;
6851 int cur_reg = -1;
6853 str++;
6856 int reg;
6858 skip_whitespace (str);
6860 if ((reg = reg_required_here (& str, -1)) == FAIL)
6861 return FAIL;
6863 if (in_range)
6865 int i;
6867 if (reg <= cur_reg)
6869 inst.error = _("bad range in register list");
6870 return FAIL;
6873 for (i = cur_reg + 1; i < reg; i++)
6875 if (range & (1 << i))
6876 as_tsktsk
6877 (_("Warning: duplicated register (r%d) in register list"),
6879 else
6880 range |= 1 << i;
6882 in_range = 0;
6885 if (range & (1 << reg))
6886 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
6887 reg);
6888 else if (reg <= cur_reg)
6889 as_tsktsk (_("Warning: register range not in ascending order"));
6891 range |= 1 << reg;
6892 cur_reg = reg;
6894 while (skip_past_comma (&str) != FAIL
6895 || (in_range = 1, *str++ == '-'));
6896 str--;
6897 skip_whitespace (str);
6899 if (*str++ != '}')
6901 inst.error = _("missing `}'");
6902 return FAIL;
6905 else
6907 expressionS expr;
6909 if (my_get_expression (&expr, &str))
6910 return FAIL;
6912 if (expr.X_op == O_constant)
6914 if (expr.X_add_number
6915 != (expr.X_add_number & 0x0000ffff))
6917 inst.error = _("invalid register mask");
6918 return FAIL;
6921 if ((range & expr.X_add_number) != 0)
6923 int regno = range & expr.X_add_number;
6925 regno &= -regno;
6926 regno = (1 << regno) - 1;
6927 as_tsktsk
6928 (_("Warning: duplicated register (r%d) in register list"),
6929 regno);
6932 range |= expr.X_add_number;
6934 else
6936 if (inst.reloc.type != 0)
6938 inst.error = _("expression too complex");
6939 return FAIL;
6942 memcpy (&inst.reloc.exp, &expr, sizeof (expressionS));
6943 inst.reloc.type = BFD_RELOC_ARM_MULTI;
6944 inst.reloc.pc_rel = 0;
6948 skip_whitespace (str);
6950 if (*str == '|' || *str == '+')
6952 str++;
6953 another_range = 1;
6956 while (another_range);
6958 *strp = str;
6959 return range;
6962 static void
6963 do_ldmstm (char * str)
6965 int base_reg;
6966 long range;
6968 skip_whitespace (str);
6970 if ((base_reg = reg_required_here (&str, 16)) == FAIL)
6971 return;
6973 if (base_reg == REG_PC)
6975 inst.error = _("r15 not allowed as base register");
6976 return;
6979 skip_whitespace (str);
6981 if (*str == '!')
6983 inst.instruction |= WRITE_BACK;
6984 str++;
6987 if (skip_past_comma (&str) == FAIL
6988 || (range = reg_list (&str)) == FAIL)
6990 if (! inst.error)
6991 inst.error = BAD_ARGS;
6992 return;
6995 if (*str == '^')
6997 str++;
6998 inst.instruction |= LDM_TYPE_2_OR_3;
7001 if (inst.instruction & WRITE_BACK)
7003 /* Check for unpredictable uses of writeback. */
7004 if (inst.instruction & LOAD_BIT)
7006 /* Not allowed in LDM type 2. */
7007 if ((inst.instruction & LDM_TYPE_2_OR_3)
7008 && ((range & (1 << REG_PC)) == 0))
7009 as_warn (_("writeback of base register is UNPREDICTABLE"));
7010 /* Only allowed if base reg not in list for other types. */
7011 else if (range & (1 << base_reg))
7012 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
7014 else /* STM. */
7016 /* Not allowed for type 2. */
7017 if (inst.instruction & LDM_TYPE_2_OR_3)
7018 as_warn (_("writeback of base register is UNPREDICTABLE"));
7019 /* Only allowed if base reg not in list, or first in list. */
7020 else if ((range & (1 << base_reg))
7021 && (range & ((1 << base_reg) - 1)))
7022 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
7026 inst.instruction |= range;
7027 end_of_line (str);
7030 static void
7031 do_smi (char * str)
7033 skip_whitespace (str);
7035 /* Allow optional leading '#'. */
7036 if (is_immediate_prefix (*str))
7037 str++;
7039 if (my_get_expression (& inst.reloc.exp, & str))
7040 return;
7042 inst.reloc.type = BFD_RELOC_ARM_SMI;
7043 inst.reloc.pc_rel = 0;
7044 end_of_line (str);
7047 static void
7048 do_swi (char * str)
7050 skip_whitespace (str);
7052 /* Allow optional leading '#'. */
7053 if (is_immediate_prefix (*str))
7054 str++;
7056 if (my_get_expression (& inst.reloc.exp, & str))
7057 return;
7059 inst.reloc.type = BFD_RELOC_ARM_SWI;
7060 inst.reloc.pc_rel = 0;
7061 end_of_line (str);
7064 static void
7065 do_swap (char * str)
7067 int reg;
7069 skip_whitespace (str);
7071 if ((reg = reg_required_here (&str, 12)) == FAIL)
7072 return;
7074 if (reg == REG_PC)
7076 inst.error = _("r15 not allowed in swap");
7077 return;
7080 if (skip_past_comma (&str) == FAIL
7081 || (reg = reg_required_here (&str, 0)) == FAIL)
7083 if (!inst.error)
7084 inst.error = BAD_ARGS;
7085 return;
7088 if (reg == REG_PC)
7090 inst.error = _("r15 not allowed in swap");
7091 return;
7094 if (skip_past_comma (&str) == FAIL
7095 || *str++ != '[')
7097 inst.error = BAD_ARGS;
7098 return;
7101 skip_whitespace (str);
7103 if ((reg = reg_required_here (&str, 16)) == FAIL)
7104 return;
7106 if (reg == REG_PC)
7108 inst.error = BAD_PC;
7109 return;
7112 skip_whitespace (str);
7114 if (*str++ != ']')
7116 inst.error = _("missing ]");
7117 return;
7120 end_of_line (str);
7123 static void
7124 do_branch (char * str)
7126 if (my_get_expression (&inst.reloc.exp, &str))
7127 return;
7129 #ifdef OBJ_ELF
7131 char * save_in;
7133 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
7134 required for the instruction. */
7136 /* arm_parse_reloc () works on input_line_pointer.
7137 We actually want to parse the operands to the branch instruction
7138 passed in 'str'. Save the input pointer and restore it later. */
7139 save_in = input_line_pointer;
7140 input_line_pointer = str;
7141 if (inst.reloc.exp.X_op == O_symbol
7142 && *str == '('
7143 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
7145 inst.reloc.type = BFD_RELOC_ARM_PLT32;
7146 inst.reloc.pc_rel = 0;
7147 /* Modify str to point to after parsed operands, otherwise
7148 end_of_line() will complain about the (PLT) left in str. */
7149 str = input_line_pointer;
7151 else
7153 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
7154 inst.reloc.pc_rel = 1;
7156 input_line_pointer = save_in;
7158 #else
7159 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
7160 inst.reloc.pc_rel = 1;
7161 #endif /* OBJ_ELF */
7163 end_of_line (str);
7166 static void
7167 do_cdp (char * str)
7169 /* Co-processor data operation.
7170 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
7171 skip_whitespace (str);
7173 if (co_proc_number (&str) == FAIL)
7175 if (!inst.error)
7176 inst.error = BAD_ARGS;
7177 return;
7180 if (skip_past_comma (&str) == FAIL
7181 || cp_opc_expr (&str, 20,4) == FAIL)
7183 if (!inst.error)
7184 inst.error = BAD_ARGS;
7185 return;
7188 if (skip_past_comma (&str) == FAIL
7189 || cp_reg_required_here (&str, 12) == FAIL)
7191 if (!inst.error)
7192 inst.error = BAD_ARGS;
7193 return;
7196 if (skip_past_comma (&str) == FAIL
7197 || cp_reg_required_here (&str, 16) == FAIL)
7199 if (!inst.error)
7200 inst.error = BAD_ARGS;
7201 return;
7204 if (skip_past_comma (&str) == FAIL
7205 || cp_reg_required_here (&str, 0) == FAIL)
7207 if (!inst.error)
7208 inst.error = BAD_ARGS;
7209 return;
7212 if (skip_past_comma (&str) == SUCCESS)
7214 if (cp_opc_expr (&str, 5, 3) == FAIL)
7216 if (!inst.error)
7217 inst.error = BAD_ARGS;
7218 return;
7222 end_of_line (str);
7225 static void
7226 do_lstc (char * str)
7228 /* Co-processor register load/store.
7229 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
7231 skip_whitespace (str);
7233 if (co_proc_number (&str) == FAIL)
7235 if (!inst.error)
7236 inst.error = BAD_ARGS;
7237 return;
7240 if (skip_past_comma (&str) == FAIL
7241 || cp_reg_required_here (&str, 12) == FAIL)
7243 if (!inst.error)
7244 inst.error = BAD_ARGS;
7245 return;
7248 if (skip_past_comma (&str) == FAIL
7249 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
7251 if (! inst.error)
7252 inst.error = BAD_ARGS;
7253 return;
7256 end_of_line (str);
7259 static void
7260 do_co_reg (char * str)
7262 /* Co-processor register transfer.
7263 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
7265 skip_whitespace (str);
7267 if (co_proc_number (&str) == FAIL)
7269 if (!inst.error)
7270 inst.error = BAD_ARGS;
7271 return;
7274 if (skip_past_comma (&str) == FAIL
7275 || cp_opc_expr (&str, 21, 3) == FAIL)
7277 if (!inst.error)
7278 inst.error = BAD_ARGS;
7279 return;
7282 if (skip_past_comma (&str) == FAIL
7283 || reg_required_here (&str, 12) == FAIL)
7285 if (!inst.error)
7286 inst.error = BAD_ARGS;
7287 return;
7290 if (skip_past_comma (&str) == FAIL
7291 || cp_reg_required_here (&str, 16) == FAIL)
7293 if (!inst.error)
7294 inst.error = BAD_ARGS;
7295 return;
7298 if (skip_past_comma (&str) == FAIL
7299 || cp_reg_required_here (&str, 0) == FAIL)
7301 if (!inst.error)
7302 inst.error = BAD_ARGS;
7303 return;
7306 if (skip_past_comma (&str) == SUCCESS)
7308 if (cp_opc_expr (&str, 5, 3) == FAIL)
7310 if (!inst.error)
7311 inst.error = BAD_ARGS;
7312 return;
7316 end_of_line (str);
7319 static void
7320 do_fpa_ctrl (char * str)
7322 /* FP control registers.
7323 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
7325 skip_whitespace (str);
7327 if (reg_required_here (&str, 12) == FAIL)
7329 if (!inst.error)
7330 inst.error = BAD_ARGS;
7331 return;
7334 end_of_line (str);
7337 static void
7338 do_fpa_ldst (char * str)
7340 skip_whitespace (str);
7342 if (fp_reg_required_here (&str, 12) == FAIL)
7344 if (!inst.error)
7345 inst.error = BAD_ARGS;
7346 return;
7349 if (skip_past_comma (&str) == FAIL
7350 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
7352 if (!inst.error)
7353 inst.error = BAD_ARGS;
7354 return;
7357 end_of_line (str);
7360 static void
7361 do_fpa_ldmstm (char * str)
7363 int num_regs;
7365 skip_whitespace (str);
7367 if (fp_reg_required_here (&str, 12) == FAIL)
7369 if (! inst.error)
7370 inst.error = BAD_ARGS;
7371 return;
7374 /* Get Number of registers to transfer. */
7375 if (skip_past_comma (&str) == FAIL
7376 || my_get_expression (&inst.reloc.exp, &str))
7378 if (! inst.error)
7379 inst.error = _("constant expression expected");
7380 return;
7383 if (inst.reloc.exp.X_op != O_constant)
7385 inst.error = _("constant value required for number of registers");
7386 return;
7389 num_regs = inst.reloc.exp.X_add_number;
7391 if (num_regs < 1 || num_regs > 4)
7393 inst.error = _("number of registers must be in the range [1:4]");
7394 return;
7397 switch (num_regs)
7399 case 1:
7400 inst.instruction |= CP_T_X;
7401 break;
7402 case 2:
7403 inst.instruction |= CP_T_Y;
7404 break;
7405 case 3:
7406 inst.instruction |= CP_T_Y | CP_T_X;
7407 break;
7408 case 4:
7409 break;
7410 default:
7411 abort ();
7414 if (inst.instruction & (CP_T_Pre | CP_T_UD)) /* ea/fd format. */
7416 int reg;
7417 int write_back;
7418 int offset;
7420 /* The instruction specified "ea" or "fd", so we can only accept
7421 [Rn]{!}. The instruction does not really support stacking or
7422 unstacking, so we have to emulate these by setting appropriate
7423 bits and offsets. */
7424 if (skip_past_comma (&str) == FAIL
7425 || *str != '[')
7427 if (! inst.error)
7428 inst.error = BAD_ARGS;
7429 return;
7432 str++;
7433 skip_whitespace (str);
7435 if ((reg = reg_required_here (&str, 16)) == FAIL)
7436 return;
7438 skip_whitespace (str);
7440 if (*str != ']')
7442 inst.error = BAD_ARGS;
7443 return;
7446 str++;
7447 if (*str == '!')
7449 write_back = 1;
7450 str++;
7451 if (reg == REG_PC)
7453 inst.error =
7454 _("r15 not allowed as base register with write-back");
7455 return;
7458 else
7459 write_back = 0;
7461 if (inst.instruction & CP_T_Pre)
7463 /* Pre-decrement. */
7464 offset = 3 * num_regs;
7465 if (write_back)
7466 inst.instruction |= CP_T_WB;
7468 else
7470 /* Post-increment. */
7471 if (write_back)
7473 inst.instruction |= CP_T_WB;
7474 offset = 3 * num_regs;
7476 else
7478 /* No write-back, so convert this into a standard pre-increment
7479 instruction -- aesthetically more pleasing. */
7480 inst.instruction |= CP_T_Pre | CP_T_UD;
7481 offset = 0;
7485 inst.instruction |= offset;
7487 else if (skip_past_comma (&str) == FAIL
7488 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
7490 if (! inst.error)
7491 inst.error = BAD_ARGS;
7492 return;
7495 end_of_line (str);
7498 static void
7499 do_fpa_dyadic (char * str)
7501 skip_whitespace (str);
7503 if (fp_reg_required_here (&str, 12) == FAIL)
7505 if (! inst.error)
7506 inst.error = BAD_ARGS;
7507 return;
7510 if (skip_past_comma (&str) == FAIL
7511 || fp_reg_required_here (&str, 16) == FAIL)
7513 if (! inst.error)
7514 inst.error = BAD_ARGS;
7515 return;
7518 if (skip_past_comma (&str) == FAIL
7519 || fp_op2 (&str) == FAIL)
7521 if (! inst.error)
7522 inst.error = BAD_ARGS;
7523 return;
7526 end_of_line (str);
7529 static void
7530 do_fpa_monadic (char * str)
7532 skip_whitespace (str);
7534 if (fp_reg_required_here (&str, 12) == FAIL)
7536 if (! inst.error)
7537 inst.error = BAD_ARGS;
7538 return;
7541 if (skip_past_comma (&str) == FAIL
7542 || fp_op2 (&str) == FAIL)
7544 if (! inst.error)
7545 inst.error = BAD_ARGS;
7546 return;
7549 end_of_line (str);
7552 static void
7553 do_fpa_cmp (char * str)
7555 skip_whitespace (str);
7557 if (fp_reg_required_here (&str, 16) == FAIL)
7559 if (! inst.error)
7560 inst.error = BAD_ARGS;
7561 return;
7564 if (skip_past_comma (&str) == FAIL
7565 || fp_op2 (&str) == FAIL)
7567 if (! inst.error)
7568 inst.error = BAD_ARGS;
7569 return;
7572 end_of_line (str);
7575 static void
7576 do_fpa_from_reg (char * str)
7578 skip_whitespace (str);
7580 if (fp_reg_required_here (&str, 16) == FAIL)
7582 if (! inst.error)
7583 inst.error = BAD_ARGS;
7584 return;
7587 if (skip_past_comma (&str) == FAIL
7588 || reg_required_here (&str, 12) == FAIL)
7590 if (! inst.error)
7591 inst.error = BAD_ARGS;
7592 return;
7595 end_of_line (str);
7598 static void
7599 do_fpa_to_reg (char * str)
7601 skip_whitespace (str);
7603 if (reg_required_here (&str, 12) == FAIL)
7604 return;
7606 if (skip_past_comma (&str) == FAIL
7607 || fp_reg_required_here (&str, 0) == FAIL)
7609 if (! inst.error)
7610 inst.error = BAD_ARGS;
7611 return;
7614 end_of_line (str);
7617 /* Encode a VFP SP register number. */
7619 static void
7620 vfp_sp_encode_reg (int reg, enum vfp_sp_reg_pos pos)
7622 switch (pos)
7624 case VFP_REG_Sd:
7625 inst.instruction |= ((reg >> 1) << 12) | ((reg & 1) << 22);
7626 break;
7628 case VFP_REG_Sn:
7629 inst.instruction |= ((reg >> 1) << 16) | ((reg & 1) << 7);
7630 break;
7632 case VFP_REG_Sm:
7633 inst.instruction |= ((reg >> 1) << 0) | ((reg & 1) << 5);
7634 break;
7636 default:
7637 abort ();
7641 static int
7642 vfp_sp_reg_required_here (char ** str,
7643 enum vfp_sp_reg_pos pos)
7645 int reg;
7646 char * start = *str;
7648 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab)) != FAIL)
7650 vfp_sp_encode_reg (reg, pos);
7651 return reg;
7654 /* In the few cases where we might be able to accept something else
7655 this error can be overridden. */
7656 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
7658 /* Restore the start point. */
7659 *str = start;
7660 return FAIL;
7663 static int
7664 vfp_dp_reg_required_here (char ** str,
7665 enum vfp_dp_reg_pos pos)
7667 int reg;
7668 char * start = *str;
7670 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab)) != FAIL)
7672 switch (pos)
7674 case VFP_REG_Dd:
7675 inst.instruction |= reg << 12;
7676 break;
7678 case VFP_REG_Dn:
7679 inst.instruction |= reg << 16;
7680 break;
7682 case VFP_REG_Dm:
7683 inst.instruction |= reg << 0;
7684 break;
7686 default:
7687 abort ();
7689 return reg;
7692 /* In the few cases where we might be able to accept something else
7693 this error can be overridden. */
7694 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
7696 /* Restore the start point. */
7697 *str = start;
7698 return FAIL;
7701 static void
7702 do_vfp_sp_monadic (char * str)
7704 skip_whitespace (str);
7706 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7707 return;
7709 if (skip_past_comma (&str) == FAIL
7710 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
7712 if (! inst.error)
7713 inst.error = BAD_ARGS;
7714 return;
7717 end_of_line (str);
7720 static void
7721 do_vfp_dp_monadic (char * str)
7723 skip_whitespace (str);
7725 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7726 return;
7728 if (skip_past_comma (&str) == FAIL
7729 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7731 if (! inst.error)
7732 inst.error = BAD_ARGS;
7733 return;
7736 end_of_line (str);
7739 static void
7740 do_vfp_sp_dyadic (char * str)
7742 skip_whitespace (str);
7744 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7745 return;
7747 if (skip_past_comma (&str) == FAIL
7748 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL
7749 || skip_past_comma (&str) == FAIL
7750 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
7752 if (! inst.error)
7753 inst.error = BAD_ARGS;
7754 return;
7757 end_of_line (str);
7760 static void
7761 do_vfp_dp_dyadic (char * str)
7763 skip_whitespace (str);
7765 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7766 return;
7768 if (skip_past_comma (&str) == FAIL
7769 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL
7770 || skip_past_comma (&str) == FAIL
7771 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7773 if (! inst.error)
7774 inst.error = BAD_ARGS;
7775 return;
7778 end_of_line (str);
7781 static void
7782 do_vfp_reg_from_sp (char * str)
7784 skip_whitespace (str);
7786 if (reg_required_here (&str, 12) == FAIL)
7787 return;
7789 if (skip_past_comma (&str) == FAIL
7790 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
7792 if (! inst.error)
7793 inst.error = BAD_ARGS;
7794 return;
7797 end_of_line (str);
7800 /* Parse a VFP register list. If the string is invalid return FAIL.
7801 Otherwise return the number of registers, and set PBASE to the first
7802 register. Double precision registers are matched if DP is nonzero. */
7804 static int
7805 vfp_parse_reg_list (char **str, int *pbase, int dp)
7807 int base_reg;
7808 int new_base;
7809 int regtype;
7810 int max_regs;
7811 int count = 0;
7812 int warned = 0;
7813 unsigned long mask = 0;
7814 int i;
7816 if (**str != '{')
7817 return FAIL;
7819 (*str)++;
7820 skip_whitespace (*str);
7822 if (dp)
7824 regtype = REG_TYPE_DN;
7825 max_regs = 16;
7827 else
7829 regtype = REG_TYPE_SN;
7830 max_regs = 32;
7833 base_reg = max_regs;
7837 new_base = arm_reg_parse (str, all_reg_maps[regtype].htab);
7838 if (new_base == FAIL)
7840 inst.error = _(all_reg_maps[regtype].expected);
7841 return FAIL;
7844 if (new_base < base_reg)
7845 base_reg = new_base;
7847 if (mask & (1 << new_base))
7849 inst.error = _("invalid register list");
7850 return FAIL;
7853 if ((mask >> new_base) != 0 && ! warned)
7855 as_tsktsk (_("register list not in ascending order"));
7856 warned = 1;
7859 mask |= 1 << new_base;
7860 count++;
7862 skip_whitespace (*str);
7864 if (**str == '-') /* We have the start of a range expression */
7866 int high_range;
7868 (*str)++;
7870 if ((high_range
7871 = arm_reg_parse (str, all_reg_maps[regtype].htab))
7872 == FAIL)
7874 inst.error = _(all_reg_maps[regtype].expected);
7875 return FAIL;
7878 if (high_range <= new_base)
7880 inst.error = _("register range not in ascending order");
7881 return FAIL;
7884 for (new_base++; new_base <= high_range; new_base++)
7886 if (mask & (1 << new_base))
7888 inst.error = _("invalid register list");
7889 return FAIL;
7892 mask |= 1 << new_base;
7893 count++;
7897 while (skip_past_comma (str) != FAIL);
7899 (*str)++;
7901 /* Sanity check -- should have raised a parse error above. */
7902 if (count == 0 || count > max_regs)
7903 abort ();
7905 *pbase = base_reg;
7907 /* Final test -- the registers must be consecutive. */
7908 mask >>= base_reg;
7909 for (i = 0; i < count; i++)
7911 if ((mask & (1u << i)) == 0)
7913 inst.error = _("non-contiguous register range");
7914 return FAIL;
7918 return count;
7921 static void
7922 do_vfp_reg2_from_sp2 (char * str)
7924 int reg;
7926 skip_whitespace (str);
7928 if (reg_required_here (&str, 12) == FAIL
7929 || skip_past_comma (&str) == FAIL
7930 || reg_required_here (&str, 16) == FAIL
7931 || skip_past_comma (&str) == FAIL)
7933 if (! inst.error)
7934 inst.error = BAD_ARGS;
7935 return;
7938 /* We require exactly two consecutive SP registers. */
7939 if (vfp_parse_reg_list (&str, &reg, 0) != 2)
7941 if (! inst.error)
7942 inst.error = _("only two consecutive VFP SP registers allowed here");
7944 vfp_sp_encode_reg (reg, VFP_REG_Sm);
7946 end_of_line (str);
7949 static void
7950 do_vfp_sp_from_reg (char * str)
7952 skip_whitespace (str);
7954 if (vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
7955 return;
7957 if (skip_past_comma (&str) == FAIL
7958 || reg_required_here (&str, 12) == FAIL)
7960 if (! inst.error)
7961 inst.error = BAD_ARGS;
7962 return;
7965 end_of_line (str);
7968 static void
7969 do_vfp_sp2_from_reg2 (char * str)
7971 int reg;
7973 skip_whitespace (str);
7975 /* We require exactly two consecutive SP registers. */
7976 if (vfp_parse_reg_list (&str, &reg, 0) != 2)
7978 if (! inst.error)
7979 inst.error = _("only two consecutive VFP SP registers allowed here");
7981 vfp_sp_encode_reg (reg, VFP_REG_Sm);
7983 if (skip_past_comma (&str) == FAIL
7984 || reg_required_here (&str, 12) == FAIL
7985 || skip_past_comma (&str) == FAIL
7986 || reg_required_here (&str, 16) == FAIL)
7988 if (! inst.error)
7989 inst.error = BAD_ARGS;
7990 return;
7993 end_of_line (str);
7996 static void
7997 do_vfp_reg_from_dp (char * str)
7999 skip_whitespace (str);
8001 if (reg_required_here (&str, 12) == FAIL)
8002 return;
8004 if (skip_past_comma (&str) == FAIL
8005 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
8007 if (! inst.error)
8008 inst.error = BAD_ARGS;
8009 return;
8012 end_of_line (str);
8015 static void
8016 do_vfp_reg2_from_dp (char * str)
8018 skip_whitespace (str);
8020 if (reg_required_here (&str, 12) == FAIL)
8021 return;
8023 if (skip_past_comma (&str) == FAIL
8024 || reg_required_here (&str, 16) == FAIL
8025 || skip_past_comma (&str) == FAIL
8026 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8028 if (! inst.error)
8029 inst.error = BAD_ARGS;
8030 return;
8033 end_of_line (str);
8036 static void
8037 do_vfp_dp_from_reg (char * str)
8039 skip_whitespace (str);
8041 if (vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
8042 return;
8044 if (skip_past_comma (&str) == FAIL
8045 || reg_required_here (&str, 12) == FAIL)
8047 if (! inst.error)
8048 inst.error = BAD_ARGS;
8049 return;
8052 end_of_line (str);
8055 static void
8056 do_vfp_dp_from_reg2 (char * str)
8058 skip_whitespace (str);
8060 if (vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8061 return;
8063 if (skip_past_comma (&str) == FAIL
8064 || reg_required_here (&str, 12) == FAIL
8065 || skip_past_comma (&str) == FAIL
8066 || reg_required_here (&str, 16) == FAIL)
8068 if (! inst.error)
8069 inst.error = BAD_ARGS;
8070 return;
8073 end_of_line (str);
8076 static const struct vfp_reg *
8077 vfp_psr_parse (char ** str)
8079 char *start = *str;
8080 char c;
8081 char *p;
8082 const struct vfp_reg *vreg;
8084 p = start;
8086 /* Find the end of the current token. */
8089 c = *p++;
8091 while (ISALPHA (c));
8093 /* Mark it. */
8094 *--p = 0;
8096 for (vreg = vfp_regs + 0;
8097 vreg < vfp_regs + sizeof (vfp_regs) / sizeof (struct vfp_reg);
8098 vreg++)
8100 if (streq (start, vreg->name))
8102 *p = c;
8103 *str = p;
8104 return vreg;
8108 *p = c;
8109 return NULL;
8112 static int
8113 vfp_psr_required_here (char ** str)
8115 char *start = *str;
8116 const struct vfp_reg *vreg;
8118 vreg = vfp_psr_parse (str);
8120 if (vreg)
8122 inst.instruction |= vreg->regno;
8123 return SUCCESS;
8126 inst.error = _("VFP system register expected");
8128 *str = start;
8129 return FAIL;
8132 static void
8133 do_vfp_reg_from_ctrl (char * str)
8135 skip_whitespace (str);
8137 if (reg_required_here (&str, 12) == FAIL)
8138 return;
8140 if (skip_past_comma (&str) == FAIL
8141 || vfp_psr_required_here (&str) == FAIL)
8143 if (! inst.error)
8144 inst.error = BAD_ARGS;
8145 return;
8148 end_of_line (str);
8151 static void
8152 do_vfp_ctrl_from_reg (char * str)
8154 skip_whitespace (str);
8156 if (vfp_psr_required_here (&str) == FAIL)
8157 return;
8159 if (skip_past_comma (&str) == FAIL
8160 || reg_required_here (&str, 12) == FAIL)
8162 if (! inst.error)
8163 inst.error = BAD_ARGS;
8164 return;
8167 end_of_line (str);
8170 static void
8171 do_vfp_sp_ldst (char * str)
8173 skip_whitespace (str);
8175 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8177 if (!inst.error)
8178 inst.error = BAD_ARGS;
8179 return;
8182 if (skip_past_comma (&str) == FAIL
8183 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
8185 if (!inst.error)
8186 inst.error = BAD_ARGS;
8187 return;
8190 end_of_line (str);
8193 static void
8194 do_vfp_dp_ldst (char * str)
8196 skip_whitespace (str);
8198 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8200 if (!inst.error)
8201 inst.error = BAD_ARGS;
8202 return;
8205 if (skip_past_comma (&str) == FAIL
8206 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
8208 if (!inst.error)
8209 inst.error = BAD_ARGS;
8210 return;
8213 end_of_line (str);
8217 static void
8218 vfp_sp_ldstm (char * str, enum vfp_ldstm_type ldstm_type)
8220 int count;
8221 int reg;
8223 skip_whitespace (str);
8225 if (reg_required_here (&str, 16) == FAIL)
8226 return;
8228 skip_whitespace (str);
8230 if (*str == '!')
8232 inst.instruction |= WRITE_BACK;
8233 str++;
8235 else if (ldstm_type != VFP_LDSTMIA)
8237 inst.error = _("this addressing mode requires base-register writeback");
8238 return;
8241 if (skip_past_comma (&str) == FAIL
8242 || (count = vfp_parse_reg_list (&str, &reg, 0)) == FAIL)
8244 if (!inst.error)
8245 inst.error = BAD_ARGS;
8246 return;
8248 vfp_sp_encode_reg (reg, VFP_REG_Sd);
8250 inst.instruction |= count;
8251 end_of_line (str);
8254 static void
8255 vfp_dp_ldstm (char * str, enum vfp_ldstm_type ldstm_type)
8257 int count;
8258 int reg;
8260 skip_whitespace (str);
8262 if (reg_required_here (&str, 16) == FAIL)
8263 return;
8265 skip_whitespace (str);
8267 if (*str == '!')
8269 inst.instruction |= WRITE_BACK;
8270 str++;
8272 else if (ldstm_type != VFP_LDSTMIA && ldstm_type != VFP_LDSTMIAX)
8274 inst.error = _("this addressing mode requires base-register writeback");
8275 return;
8278 if (skip_past_comma (&str) == FAIL
8279 || (count = vfp_parse_reg_list (&str, &reg, 1)) == FAIL)
8281 if (!inst.error)
8282 inst.error = BAD_ARGS;
8283 return;
8286 count <<= 1;
8287 if (ldstm_type == VFP_LDSTMIAX || ldstm_type == VFP_LDSTMDBX)
8288 count += 1;
8290 inst.instruction |= (reg << 12) | count;
8291 end_of_line (str);
8294 static void
8295 do_vfp_sp_ldstmia (char * str)
8297 vfp_sp_ldstm (str, VFP_LDSTMIA);
8300 static void
8301 do_vfp_sp_ldstmdb (char * str)
8303 vfp_sp_ldstm (str, VFP_LDSTMDB);
8306 static void
8307 do_vfp_dp_ldstmia (char * str)
8309 vfp_dp_ldstm (str, VFP_LDSTMIA);
8312 static void
8313 do_vfp_dp_ldstmdb (char * str)
8315 vfp_dp_ldstm (str, VFP_LDSTMDB);
8318 static void
8319 do_vfp_xp_ldstmia (char *str)
8321 vfp_dp_ldstm (str, VFP_LDSTMIAX);
8324 static void
8325 do_vfp_xp_ldstmdb (char * str)
8327 vfp_dp_ldstm (str, VFP_LDSTMDBX);
8330 static void
8331 do_vfp_sp_compare_z (char * str)
8333 skip_whitespace (str);
8335 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8337 if (!inst.error)
8338 inst.error = BAD_ARGS;
8339 return;
8342 end_of_line (str);
8345 static void
8346 do_vfp_dp_compare_z (char * str)
8348 skip_whitespace (str);
8350 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8352 if (!inst.error)
8353 inst.error = BAD_ARGS;
8354 return;
8357 end_of_line (str);
8360 static void
8361 do_vfp_dp_sp_cvt (char * str)
8363 skip_whitespace (str);
8365 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8366 return;
8368 if (skip_past_comma (&str) == FAIL
8369 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
8371 if (! inst.error)
8372 inst.error = BAD_ARGS;
8373 return;
8376 end_of_line (str);
8379 static void
8380 do_vfp_sp_dp_cvt (char * str)
8382 skip_whitespace (str);
8384 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8385 return;
8387 if (skip_past_comma (&str) == FAIL
8388 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8390 if (! inst.error)
8391 inst.error = BAD_ARGS;
8392 return;
8395 end_of_line (str);
8398 /* Thumb specific routines. */
8400 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
8401 was SUB. */
8403 static void
8404 thumb_add_sub (char * str, int subtract)
8406 int Rd, Rs, Rn = FAIL;
8408 skip_whitespace (str);
8410 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
8411 || skip_past_comma (&str) == FAIL)
8413 if (! inst.error)
8414 inst.error = BAD_ARGS;
8415 return;
8418 if (is_immediate_prefix (*str))
8420 Rs = Rd;
8421 str++;
8422 if (my_get_expression (&inst.reloc.exp, &str))
8423 return;
8425 else
8427 if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8428 return;
8430 if (skip_past_comma (&str) == FAIL)
8432 /* Two operand format, shuffle the registers
8433 and pretend there are 3. */
8434 Rn = Rs;
8435 Rs = Rd;
8437 else if (is_immediate_prefix (*str))
8439 str++;
8440 if (my_get_expression (&inst.reloc.exp, &str))
8441 return;
8443 else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8444 return;
8447 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8448 for the latter case, EXPR contains the immediate that was found. */
8449 if (Rn != FAIL)
8451 /* All register format. */
8452 if (Rd > 7 || Rs > 7 || Rn > 7)
8454 if (Rs != Rd)
8456 inst.error = _("dest and source1 must be the same register");
8457 return;
8460 /* Can't do this for SUB. */
8461 if (subtract)
8463 inst.error = _("subtract valid only on lo regs");
8464 return;
8467 inst.instruction = (T_OPCODE_ADD_HI
8468 | (Rd > 7 ? THUMB_H1 : 0)
8469 | (Rn > 7 ? THUMB_H2 : 0));
8470 inst.instruction |= (Rd & 7) | ((Rn & 7) << 3);
8472 else
8474 inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3;
8475 inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
8478 else
8480 /* Immediate expression, now things start to get nasty. */
8482 /* First deal with HI regs, only very restricted cases allowed:
8483 Adjusting SP, and using PC or SP to get an address. */
8484 if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP))
8485 || (Rs > 7 && Rs != REG_SP && Rs != REG_PC))
8487 inst.error = _("invalid Hi register with immediate");
8488 return;
8491 if (inst.reloc.exp.X_op != O_constant)
8493 /* Value isn't known yet, all we can do is store all the fragments
8494 we know about in the instruction and let the reloc hacking
8495 work it all out. */
8496 inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs;
8497 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
8499 else
8501 int offset = inst.reloc.exp.X_add_number;
8503 if (subtract)
8504 offset = - offset;
8506 if (offset < 0)
8508 offset = - offset;
8509 subtract = 1;
8511 /* Quick check, in case offset is MIN_INT. */
8512 if (offset < 0)
8514 inst.error = _("immediate value out of range");
8515 return;
8518 /* Note - you cannot convert a subtract of 0 into an
8519 add of 0 because the carry flag is set differently. */
8520 else if (offset > 0)
8521 subtract = 0;
8523 if (Rd == REG_SP)
8525 if (offset & ~0x1fc)
8527 inst.error = _("invalid immediate value for stack adjust");
8528 return;
8530 inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
8531 inst.instruction |= offset >> 2;
8533 else if (Rs == REG_PC || Rs == REG_SP)
8535 if (subtract
8536 || (offset & ~0x3fc))
8538 inst.error = _("invalid immediate for address calculation");
8539 return;
8541 inst.instruction = (Rs == REG_PC ? T_OPCODE_ADD_PC
8542 : T_OPCODE_ADD_SP);
8543 inst.instruction |= (Rd << 8) | (offset >> 2);
8545 else if (Rs == Rd)
8547 if (offset & ~0xff)
8549 inst.error = _("immediate value out of range");
8550 return;
8552 inst.instruction = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
8553 inst.instruction |= (Rd << 8) | offset;
8555 else
8557 if (offset & ~0x7)
8559 inst.error = _("immediate value out of range");
8560 return;
8562 inst.instruction = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
8563 inst.instruction |= Rd | (Rs << 3) | (offset << 6);
8568 end_of_line (str);
8571 static void
8572 thumb_shift (char * str, int shift)
8574 int Rd, Rs, Rn = FAIL;
8576 skip_whitespace (str);
8578 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8579 || skip_past_comma (&str) == FAIL)
8581 if (! inst.error)
8582 inst.error = BAD_ARGS;
8583 return;
8586 if (is_immediate_prefix (*str))
8588 /* Two operand immediate format, set Rs to Rd. */
8589 Rs = Rd;
8590 str ++;
8591 if (my_get_expression (&inst.reloc.exp, &str))
8592 return;
8594 else
8596 if ((Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8597 return;
8599 if (skip_past_comma (&str) == FAIL)
8601 /* Two operand format, shuffle the registers
8602 and pretend there are 3. */
8603 Rn = Rs;
8604 Rs = Rd;
8606 else if (is_immediate_prefix (*str))
8608 str++;
8609 if (my_get_expression (&inst.reloc.exp, &str))
8610 return;
8612 else if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8613 return;
8616 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8617 for the latter case, EXPR contains the immediate that was found. */
8619 if (Rn != FAIL)
8621 if (Rs != Rd)
8623 inst.error = _("source1 and dest must be same register");
8624 return;
8627 switch (shift)
8629 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_R; break;
8630 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_R; break;
8631 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_R; break;
8634 inst.instruction |= Rd | (Rn << 3);
8636 else
8638 switch (shift)
8640 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_I; break;
8641 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_I; break;
8642 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_I; break;
8645 if (inst.reloc.exp.X_op != O_constant)
8647 /* Value isn't known yet, create a dummy reloc and let reloc
8648 hacking fix it up. */
8649 inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
8651 else
8653 unsigned shift_value = inst.reloc.exp.X_add_number;
8655 if (shift_value > 32 || (shift_value == 32 && shift == THUMB_LSL))
8657 inst.error = _("invalid immediate for shift");
8658 return;
8661 /* Shifts of zero are handled by converting to LSL. */
8662 if (shift_value == 0)
8663 inst.instruction = T_OPCODE_LSL_I;
8665 /* Shifts of 32 are encoded as a shift of zero. */
8666 if (shift_value == 32)
8667 shift_value = 0;
8669 inst.instruction |= shift_value << 6;
8672 inst.instruction |= Rd | (Rs << 3);
8675 end_of_line (str);
8678 static void
8679 thumb_load_store (char * str, int load_store, int size)
8681 int Rd, Rb, Ro = FAIL;
8683 skip_whitespace (str);
8685 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8686 || skip_past_comma (&str) == FAIL)
8688 if (! inst.error)
8689 inst.error = BAD_ARGS;
8690 return;
8693 if (*str == '[')
8695 str++;
8696 if ((Rb = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8697 return;
8699 if (skip_past_comma (&str) != FAIL)
8701 if (is_immediate_prefix (*str))
8703 str++;
8704 if (my_get_expression (&inst.reloc.exp, &str))
8705 return;
8707 else if ((Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8708 return;
8710 else
8712 inst.reloc.exp.X_op = O_constant;
8713 inst.reloc.exp.X_add_number = 0;
8716 if (*str != ']')
8718 inst.error = _("expected ']'");
8719 return;
8721 str++;
8723 else if (*str == '=')
8725 if (load_store != THUMB_LOAD)
8727 inst.error = _("invalid pseudo operation");
8728 return;
8731 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
8732 str++;
8734 skip_whitespace (str);
8736 if (my_get_expression (& inst.reloc.exp, & str))
8737 return;
8739 end_of_line (str);
8741 if ( inst.reloc.exp.X_op != O_constant
8742 && inst.reloc.exp.X_op != O_symbol)
8744 inst.error = "Constant expression expected";
8745 return;
8748 if (inst.reloc.exp.X_op == O_constant
8749 && ((inst.reloc.exp.X_add_number & ~0xFF) == 0))
8751 /* This can be done with a mov instruction. */
8753 inst.instruction = T_OPCODE_MOV_I8 | (Rd << 8);
8754 inst.instruction |= inst.reloc.exp.X_add_number;
8755 return;
8758 /* Insert into literal pool. */
8759 if (add_to_lit_pool () == FAIL)
8761 if (!inst.error)
8762 inst.error = "literal pool insertion failed";
8763 return;
8766 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8767 inst.reloc.pc_rel = 1;
8768 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
8769 /* Adjust ARM pipeline offset to Thumb. */
8770 inst.reloc.exp.X_add_number += 4;
8772 return;
8774 else
8776 if (my_get_expression (&inst.reloc.exp, &str))
8777 return;
8779 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
8780 inst.reloc.pc_rel = 1;
8781 inst.reloc.exp.X_add_number -= 4; /* Pipeline offset. */
8782 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8783 end_of_line (str);
8784 return;
8787 if (Rb == REG_PC || Rb == REG_SP)
8789 if (size != THUMB_WORD)
8791 inst.error = _("byte or halfword not valid for base register");
8792 return;
8794 else if (Rb == REG_PC && load_store != THUMB_LOAD)
8796 inst.error = _("r15 based store not allowed");
8797 return;
8799 else if (Ro != FAIL)
8801 inst.error = _("invalid base register for register offset");
8802 return;
8805 if (Rb == REG_PC)
8806 inst.instruction = T_OPCODE_LDR_PC;
8807 else if (load_store == THUMB_LOAD)
8808 inst.instruction = T_OPCODE_LDR_SP;
8809 else
8810 inst.instruction = T_OPCODE_STR_SP;
8812 inst.instruction |= Rd << 8;
8813 if (inst.reloc.exp.X_op == O_constant)
8815 unsigned offset = inst.reloc.exp.X_add_number;
8817 if (offset & ~0x3fc)
8819 inst.error = _("invalid offset");
8820 return;
8823 inst.instruction |= offset >> 2;
8825 else
8826 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8828 else if (Rb > 7)
8830 inst.error = _("invalid base register in load/store");
8831 return;
8833 else if (Ro == FAIL)
8835 /* Immediate offset. */
8836 if (size == THUMB_WORD)
8837 inst.instruction = (load_store == THUMB_LOAD
8838 ? T_OPCODE_LDR_IW : T_OPCODE_STR_IW);
8839 else if (size == THUMB_HALFWORD)
8840 inst.instruction = (load_store == THUMB_LOAD
8841 ? T_OPCODE_LDR_IH : T_OPCODE_STR_IH);
8842 else
8843 inst.instruction = (load_store == THUMB_LOAD
8844 ? T_OPCODE_LDR_IB : T_OPCODE_STR_IB);
8846 inst.instruction |= Rd | (Rb << 3);
8848 if (inst.reloc.exp.X_op == O_constant)
8850 unsigned offset = inst.reloc.exp.X_add_number;
8852 if (offset & ~(0x1f << size))
8854 inst.error = _("invalid offset");
8855 return;
8857 inst.instruction |= (offset >> size) << 6;
8859 else
8860 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8862 else
8864 /* Register offset. */
8865 if (size == THUMB_WORD)
8866 inst.instruction = (load_store == THUMB_LOAD
8867 ? T_OPCODE_LDR_RW : T_OPCODE_STR_RW);
8868 else if (size == THUMB_HALFWORD)
8869 inst.instruction = (load_store == THUMB_LOAD
8870 ? T_OPCODE_LDR_RH : T_OPCODE_STR_RH);
8871 else
8872 inst.instruction = (load_store == THUMB_LOAD
8873 ? T_OPCODE_LDR_RB : T_OPCODE_STR_RB);
8875 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
8878 end_of_line (str);
8881 /* A register must be given at this point.
8883 Shift is the place to put it in inst.instruction.
8885 Restores input start point on err.
8886 Returns the reg#, or FAIL. */
8888 static int
8889 mav_reg_required_here (char ** str, int shift, enum arm_reg_type regtype)
8891 int reg;
8892 char *start = *str;
8894 if ((reg = arm_reg_parse (str, all_reg_maps[regtype].htab)) != FAIL)
8896 if (shift >= 0)
8897 inst.instruction |= reg << shift;
8899 return reg;
8902 /* Restore the start point. */
8903 *str = start;
8905 /* Try generic coprocessor name if applicable. */
8906 if (regtype == REG_TYPE_MVF ||
8907 regtype == REG_TYPE_MVD ||
8908 regtype == REG_TYPE_MVFX ||
8909 regtype == REG_TYPE_MVDX)
8911 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
8913 if (shift >= 0)
8914 inst.instruction |= reg << shift;
8916 return reg;
8919 /* Restore the start point. */
8920 *str = start;
8923 /* In the few cases where we might be able to accept something else
8924 this error can be overridden. */
8925 inst.error = _(all_reg_maps[regtype].expected);
8927 return FAIL;
8930 /* Cirrus Maverick Instructions. */
8932 /* Isnsn like "foo X,Y". */
8934 static void
8935 do_mav_binops (char * str,
8936 int mode,
8937 enum arm_reg_type reg0,
8938 enum arm_reg_type reg1)
8940 int shift0, shift1;
8942 shift0 = mode & 0xff;
8943 shift1 = (mode >> 8) & 0xff;
8945 skip_whitespace (str);
8947 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
8948 || skip_past_comma (&str) == FAIL
8949 || mav_reg_required_here (&str, shift1, reg1) == FAIL)
8951 if (!inst.error)
8952 inst.error = BAD_ARGS;
8954 else
8955 end_of_line (str);
8958 /* Isnsn like "foo X,Y,Z". */
8960 static void
8961 do_mav_triple (char * str,
8962 int mode,
8963 enum arm_reg_type reg0,
8964 enum arm_reg_type reg1,
8965 enum arm_reg_type reg2)
8967 int shift0, shift1, shift2;
8969 shift0 = mode & 0xff;
8970 shift1 = (mode >> 8) & 0xff;
8971 shift2 = (mode >> 16) & 0xff;
8973 skip_whitespace (str);
8975 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
8976 || skip_past_comma (&str) == FAIL
8977 || mav_reg_required_here (&str, shift1, reg1) == FAIL
8978 || skip_past_comma (&str) == FAIL
8979 || mav_reg_required_here (&str, shift2, reg2) == FAIL)
8981 if (!inst.error)
8982 inst.error = BAD_ARGS;
8984 else
8985 end_of_line (str);
8988 /* Wrapper functions. */
8990 static void
8991 do_mav_binops_1a (char * str)
8993 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVF);
8996 static void
8997 do_mav_binops_1b (char * str)
8999 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVD);
9002 static void
9003 do_mav_binops_1c (char * str)
9005 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVDX);
9008 static void
9009 do_mav_binops_1d (char * str)
9011 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVF);
9014 static void
9015 do_mav_binops_1e (char * str)
9017 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVD);
9020 static void
9021 do_mav_binops_1f (char * str)
9023 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVF);
9026 static void
9027 do_mav_binops_1g (char * str)
9029 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVD);
9032 static void
9033 do_mav_binops_1h (char * str)
9035 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVFX);
9038 static void
9039 do_mav_binops_1i (char * str)
9041 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVFX);
9044 static void
9045 do_mav_binops_1j (char * str)
9047 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVDX);
9050 static void
9051 do_mav_binops_1k (char * str)
9053 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVDX);
9056 static void
9057 do_mav_binops_1l (char * str)
9059 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVF);
9062 static void
9063 do_mav_binops_1m (char * str)
9065 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVD);
9068 static void
9069 do_mav_binops_1n (char * str)
9071 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVFX);
9074 static void
9075 do_mav_binops_1o (char * str)
9077 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVDX, REG_TYPE_MVDX);
9080 static void
9081 do_mav_binops_2a (char * str)
9083 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVF, REG_TYPE_RN);
9086 static void
9087 do_mav_binops_2b (char * str)
9089 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVD, REG_TYPE_RN);
9092 static void
9093 do_mav_binops_2c (char * str)
9095 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVDX, REG_TYPE_RN);
9098 static void
9099 do_mav_binops_3a (char * str)
9101 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVFX);
9104 static void
9105 do_mav_binops_3b (char * str)
9107 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVFX, REG_TYPE_MVAX);
9110 static void
9111 do_mav_binops_3c (char * str)
9113 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVDX);
9116 static void
9117 do_mav_binops_3d (char * str)
9119 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVDX, REG_TYPE_MVAX);
9122 static void
9123 do_mav_triple_4a (char * str)
9125 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_RN);
9128 static void
9129 do_mav_triple_4b (char * str)
9131 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_RN);
9134 static void
9135 do_mav_triple_5a (char * str)
9137 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVF, REG_TYPE_MVF);
9140 static void
9141 do_mav_triple_5b (char * str)
9143 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVD, REG_TYPE_MVD);
9146 static void
9147 do_mav_triple_5c (char * str)
9149 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVFX, REG_TYPE_MVFX);
9152 static void
9153 do_mav_triple_5d (char * str)
9155 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVDX, REG_TYPE_MVDX);
9158 static void
9159 do_mav_triple_5e (char * str)
9161 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVF, REG_TYPE_MVF, REG_TYPE_MVF);
9164 static void
9165 do_mav_triple_5f (char * str)
9167 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVD, REG_TYPE_MVD, REG_TYPE_MVD);
9170 static void
9171 do_mav_triple_5g (char * str)
9173 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_MVFX);
9176 static void
9177 do_mav_triple_5h (char * str)
9179 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_MVDX);
9182 /* Isnsn like "foo W,X,Y,Z".
9183 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
9185 static void
9186 do_mav_quad (char * str,
9187 int mode,
9188 enum arm_reg_type reg0,
9189 enum arm_reg_type reg1,
9190 enum arm_reg_type reg2,
9191 enum arm_reg_type reg3)
9193 int shift0, shift1, shift2, shift3;
9195 shift0= mode & 0xff;
9196 shift1 = (mode >> 8) & 0xff;
9197 shift2 = (mode >> 16) & 0xff;
9198 shift3 = (mode >> 24) & 0xff;
9200 skip_whitespace (str);
9202 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
9203 || skip_past_comma (&str) == FAIL
9204 || mav_reg_required_here (&str, shift1, reg1) == FAIL
9205 || skip_past_comma (&str) == FAIL
9206 || mav_reg_required_here (&str, shift2, reg2) == FAIL
9207 || skip_past_comma (&str) == FAIL
9208 || mav_reg_required_here (&str, shift3, reg3) == FAIL)
9210 if (!inst.error)
9211 inst.error = BAD_ARGS;
9213 else
9214 end_of_line (str);
9217 static void
9218 do_mav_quad_6a (char * str)
9220 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVFX, REG_TYPE_MVFX,
9221 REG_TYPE_MVFX);
9224 static void
9225 do_mav_quad_6b (char * str)
9227 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVAX, REG_TYPE_MVFX,
9228 REG_TYPE_MVFX);
9231 /* cfmvsc32<cond> DSPSC,MVDX[15:0]. */
9232 static void
9233 do_mav_dspsc_1 (char * str)
9235 skip_whitespace (str);
9237 /* cfmvsc32. */
9238 if (mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL
9239 || skip_past_comma (&str) == FAIL
9240 || mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL)
9242 if (!inst.error)
9243 inst.error = BAD_ARGS;
9245 return;
9248 end_of_line (str);
9251 /* cfmv32sc<cond> MVDX[15:0],DSPSC. */
9252 static void
9253 do_mav_dspsc_2 (char * str)
9255 skip_whitespace (str);
9257 /* cfmv32sc. */
9258 if (mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL
9259 || skip_past_comma (&str) == FAIL
9260 || mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL)
9262 if (!inst.error)
9263 inst.error = BAD_ARGS;
9265 return;
9268 end_of_line (str);
9271 /* Maverick shift immediate instructions.
9272 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
9273 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
9275 static void
9276 do_mav_shift (char * str,
9277 enum arm_reg_type reg0,
9278 enum arm_reg_type reg1)
9280 int error;
9281 int imm, neg = 0;
9283 skip_whitespace (str);
9285 error = 0;
9287 if (mav_reg_required_here (&str, 12, reg0) == FAIL
9288 || skip_past_comma (&str) == FAIL
9289 || mav_reg_required_here (&str, 16, reg1) == FAIL
9290 || skip_past_comma (&str) == FAIL)
9292 if (!inst.error)
9293 inst.error = BAD_ARGS;
9294 return;
9297 /* Calculate the immediate operand.
9298 The operand is a 7bit signed number. */
9299 skip_whitespace (str);
9301 if (*str == '#')
9302 ++str;
9304 if (!ISDIGIT (*str) && *str != '-')
9306 inst.error = _("expecting immediate, 7bit operand");
9307 return;
9310 if (*str == '-')
9312 neg = 1;
9313 ++str;
9316 for (imm = 0; *str && ISDIGIT (*str); ++str)
9317 imm = imm * 10 + *str - '0';
9319 if (imm > 64)
9321 inst.error = _("immediate out of range");
9322 return;
9325 /* Make negative imm's into 7bit signed numbers. */
9326 if (neg)
9328 imm = -imm;
9329 imm &= 0x0000007f;
9332 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
9333 Bits 5-7 of the insn should have bits 4-6 of the immediate.
9334 Bit 4 should be 0. */
9335 imm = (imm & 0xf) | ((imm & 0x70) << 1);
9337 inst.instruction |= imm;
9338 end_of_line (str);
9341 static void
9342 do_mav_shift_1 (char * str)
9344 do_mav_shift (str, REG_TYPE_MVFX, REG_TYPE_MVFX);
9347 static void
9348 do_mav_shift_2 (char * str)
9350 do_mav_shift (str, REG_TYPE_MVDX, REG_TYPE_MVDX);
9353 static int
9354 mav_parse_offset (char ** str, int * negative)
9356 char * p = *str;
9357 int offset;
9359 *negative = 0;
9361 skip_whitespace (p);
9363 if (*p == '#')
9364 ++p;
9366 if (*p == '-')
9368 *negative = 1;
9369 ++p;
9372 if (!ISDIGIT (*p))
9374 inst.error = _("offset expected");
9375 return 0;
9378 for (offset = 0; *p && ISDIGIT (*p); ++p)
9379 offset = offset * 10 + *p - '0';
9381 if (offset > 0x3fc)
9383 inst.error = _("offset out of range");
9384 return 0;
9386 if (offset & 0x3)
9388 inst.error = _("offset not a multiple of 4");
9389 return 0;
9392 *str = p;
9394 return *negative ? -offset : offset;
9397 /* Maverick load/store instructions.
9398 <insn><cond> CRd,[Rn,<offset>]{!}.
9399 <insn><cond> CRd,[Rn],<offset>. */
9401 static void
9402 do_mav_ldst (char * str, enum arm_reg_type reg0)
9404 int offset, negative;
9406 skip_whitespace (str);
9408 if (mav_reg_required_here (&str, 12, reg0) == FAIL
9409 || skip_past_comma (&str) == FAIL
9410 || *str++ != '['
9411 || reg_required_here (&str, 16) == FAIL)
9412 goto fail_ldst;
9414 if (skip_past_comma (&str) == SUCCESS)
9416 /* You are here: "<offset>]{!}". */
9417 inst.instruction |= PRE_INDEX;
9419 offset = mav_parse_offset (&str, &negative);
9421 if (inst.error)
9422 return;
9424 if (*str++ != ']')
9426 inst.error = _("missing ]");
9427 return;
9430 if (*str == '!')
9432 inst.instruction |= WRITE_BACK;
9433 ++str;
9436 else
9438 /* You are here: "], <offset>". */
9439 if (*str++ != ']')
9441 inst.error = _("missing ]");
9442 return;
9445 if (skip_past_comma (&str) == FAIL
9446 || (offset = mav_parse_offset (&str, &negative), inst.error))
9447 goto fail_ldst;
9449 inst.instruction |= CP_T_WB; /* Post indexed, set bit W. */
9452 if (negative)
9453 offset = -offset;
9454 else
9455 inst.instruction |= CP_T_UD; /* Positive, so set bit U. */
9457 inst.instruction |= offset >> 2;
9458 end_of_line (str);
9459 return;
9461 fail_ldst:
9462 if (!inst.error)
9463 inst.error = BAD_ARGS;
9466 static void
9467 do_mav_ldst_1 (char * str)
9469 do_mav_ldst (str, REG_TYPE_MVF);
9472 static void
9473 do_mav_ldst_2 (char * str)
9475 do_mav_ldst (str, REG_TYPE_MVD);
9478 static void
9479 do_mav_ldst_3 (char * str)
9481 do_mav_ldst (str, REG_TYPE_MVFX);
9484 static void
9485 do_mav_ldst_4 (char * str)
9487 do_mav_ldst (str, REG_TYPE_MVDX);
9490 static void
9491 do_t_nop (char * str)
9493 /* Do nothing. */
9494 end_of_line (str);
9497 /* Handle the Format 4 instructions that do not have equivalents in other
9498 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
9499 BIC and MVN. */
9501 static void
9502 do_t_arit (char * str)
9504 int Rd, Rs, Rn;
9506 skip_whitespace (str);
9508 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9509 || skip_past_comma (&str) == FAIL
9510 || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9512 inst.error = BAD_ARGS;
9513 return;
9516 if (skip_past_comma (&str) != FAIL)
9518 /* Three operand format not allowed for TST, CMN, NEG and MVN.
9519 (It isn't allowed for CMP either, but that isn't handled by this
9520 function.) */
9521 if (inst.instruction == T_OPCODE_TST
9522 || inst.instruction == T_OPCODE_CMN
9523 || inst.instruction == T_OPCODE_NEG
9524 || inst.instruction == T_OPCODE_MVN)
9526 inst.error = BAD_ARGS;
9527 return;
9530 if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9531 return;
9533 if (Rs != Rd)
9535 inst.error = _("dest and source1 must be the same register");
9536 return;
9538 Rs = Rn;
9541 if (inst.instruction == T_OPCODE_MUL
9542 && Rs == Rd)
9543 as_tsktsk (_("Rs and Rd must be different in MUL"));
9545 inst.instruction |= Rd | (Rs << 3);
9546 end_of_line (str);
9549 static void
9550 do_t_add (char * str)
9552 thumb_add_sub (str, 0);
9555 static void
9556 do_t_asr (char * str)
9558 thumb_shift (str, THUMB_ASR);
9561 static void
9562 do_t_branch9 (char * str)
9564 if (my_get_expression (&inst.reloc.exp, &str))
9565 return;
9566 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
9567 inst.reloc.pc_rel = 1;
9568 end_of_line (str);
9571 static void
9572 do_t_branch12 (char * str)
9574 if (my_get_expression (&inst.reloc.exp, &str))
9575 return;
9576 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
9577 inst.reloc.pc_rel = 1;
9578 end_of_line (str);
9581 /* Find the real, Thumb encoded start of a Thumb function. */
9583 static symbolS *
9584 find_real_start (symbolS * symbolP)
9586 char * real_start;
9587 const char * name = S_GET_NAME (symbolP);
9588 symbolS * new_target;
9590 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
9591 #define STUB_NAME ".real_start_of"
9593 if (name == NULL)
9594 abort ();
9596 /* Names that start with '.' are local labels, not function entry points.
9597 The compiler may generate BL instructions to these labels because it
9598 needs to perform a branch to a far away location. */
9599 if (name[0] == '.')
9600 return symbolP;
9602 real_start = malloc (strlen (name) + strlen (STUB_NAME) + 1);
9603 sprintf (real_start, "%s%s", STUB_NAME, name);
9605 new_target = symbol_find (real_start);
9607 if (new_target == NULL)
9609 as_warn ("Failed to find real start of function: %s\n", name);
9610 new_target = symbolP;
9613 free (real_start);
9615 return new_target;
9618 static void
9619 do_t_branch23 (char * str)
9621 if (my_get_expression (& inst.reloc.exp, & str))
9622 return;
9624 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH23;
9625 inst.reloc.pc_rel = 1;
9626 end_of_line (str);
9628 /* If the destination of the branch is a defined symbol which does not have
9629 the THUMB_FUNC attribute, then we must be calling a function which has
9630 the (interfacearm) attribute. We look for the Thumb entry point to that
9631 function and change the branch to refer to that function instead. */
9632 if ( inst.reloc.exp.X_op == O_symbol
9633 && inst.reloc.exp.X_add_symbol != NULL
9634 && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
9635 && ! THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
9636 inst.reloc.exp.X_add_symbol =
9637 find_real_start (inst.reloc.exp.X_add_symbol);
9640 static void
9641 do_t_bx (char * str)
9643 int reg;
9645 skip_whitespace (str);
9647 if ((reg = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9648 return;
9650 /* This sets THUMB_H2 from the top bit of reg. */
9651 inst.instruction |= reg << 3;
9653 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
9654 should cause the alignment to be checked once it is known. This is
9655 because BX PC only works if the instruction is word aligned. */
9657 end_of_line (str);
9660 static void
9661 do_t_compare (char * str)
9663 thumb_mov_compare (str, THUMB_COMPARE);
9666 static void
9667 do_t_ldmstm (char * str)
9669 int Rb;
9670 long range;
9672 skip_whitespace (str);
9674 if ((Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9675 return;
9677 if (*str != '!')
9678 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
9679 else
9680 str++;
9682 if (skip_past_comma (&str) == FAIL
9683 || (range = reg_list (&str)) == FAIL)
9685 if (! inst.error)
9686 inst.error = BAD_ARGS;
9687 return;
9690 if (inst.reloc.type != BFD_RELOC_UNUSED)
9692 /* This really doesn't seem worth it. */
9693 inst.reloc.type = BFD_RELOC_UNUSED;
9694 inst.error = _("expression too complex");
9695 return;
9698 if (range & ~0xff)
9700 inst.error = _("only lo-regs valid in load/store multiple");
9701 return;
9704 inst.instruction |= (Rb << 8) | range;
9705 end_of_line (str);
9708 static void
9709 do_t_ldr (char * str)
9711 thumb_load_store (str, THUMB_LOAD, THUMB_WORD);
9714 static void
9715 do_t_ldrb (char * str)
9717 thumb_load_store (str, THUMB_LOAD, THUMB_BYTE);
9720 static void
9721 do_t_ldrh (char * str)
9723 thumb_load_store (str, THUMB_LOAD, THUMB_HALFWORD);
9726 static void
9727 do_t_lds (char * str)
9729 int Rd, Rb, Ro;
9731 skip_whitespace (str);
9733 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9734 || skip_past_comma (&str) == FAIL
9735 || *str++ != '['
9736 || (Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9737 || skip_past_comma (&str) == FAIL
9738 || (Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9739 || *str++ != ']')
9741 if (! inst.error)
9742 inst.error = _("syntax: ldrs[b] Rd, [Rb, Ro]");
9743 return;
9746 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
9747 end_of_line (str);
9750 static void
9751 do_t_lsl (char * str)
9753 thumb_shift (str, THUMB_LSL);
9756 static void
9757 do_t_lsr (char * str)
9759 thumb_shift (str, THUMB_LSR);
9762 static void
9763 do_t_mov (char * str)
9765 thumb_mov_compare (str, THUMB_MOVE);
9768 static void
9769 do_t_push_pop (char * str)
9771 long range;
9773 skip_whitespace (str);
9775 if ((range = reg_list (&str)) == FAIL)
9777 if (! inst.error)
9778 inst.error = BAD_ARGS;
9779 return;
9782 if (inst.reloc.type != BFD_RELOC_UNUSED)
9784 /* This really doesn't seem worth it. */
9785 inst.reloc.type = BFD_RELOC_UNUSED;
9786 inst.error = _("expression too complex");
9787 return;
9790 if (range & ~0xff)
9792 if ((inst.instruction == T_OPCODE_PUSH
9793 && (range & ~0xff) == 1 << REG_LR)
9794 || (inst.instruction == T_OPCODE_POP
9795 && (range & ~0xff) == 1 << REG_PC))
9797 inst.instruction |= THUMB_PP_PC_LR;
9798 range &= 0xff;
9800 else
9802 inst.error = _("invalid register list to push/pop instruction");
9803 return;
9807 inst.instruction |= range;
9808 end_of_line (str);
9811 static void
9812 do_t_str (char * str)
9814 thumb_load_store (str, THUMB_STORE, THUMB_WORD);
9817 static void
9818 do_t_strb (char * str)
9820 thumb_load_store (str, THUMB_STORE, THUMB_BYTE);
9823 static void
9824 do_t_strh (char * str)
9826 thumb_load_store (str, THUMB_STORE, THUMB_HALFWORD);
9829 static void
9830 do_t_sub (char * str)
9832 thumb_add_sub (str, 1);
9835 static void
9836 do_t_swi (char * str)
9838 skip_whitespace (str);
9840 if (my_get_expression (&inst.reloc.exp, &str))
9841 return;
9843 inst.reloc.type = BFD_RELOC_ARM_SWI;
9844 end_of_line (str);
9847 static void
9848 do_t_adr (char * str)
9850 int reg;
9852 /* This is a pseudo-op of the form "adr rd, label" to be converted
9853 into a relative address of the form "add rd, pc, #label-.-4". */
9854 skip_whitespace (str);
9856 /* Store Rd in temporary location inside instruction. */
9857 if ((reg = reg_required_here (&str, 4)) == FAIL
9858 || (reg > 7) /* For Thumb reg must be r0..r7. */
9859 || skip_past_comma (&str) == FAIL
9860 || my_get_expression (&inst.reloc.exp, &str))
9862 if (!inst.error)
9863 inst.error = BAD_ARGS;
9864 return;
9867 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
9868 inst.reloc.exp.X_add_number -= 4; /* PC relative adjust. */
9869 inst.reloc.pc_rel = 1;
9870 inst.instruction |= REG_PC; /* Rd is already placed into the instruction. */
9872 end_of_line (str);
9875 static void
9876 insert_reg (const struct reg_entry * r,
9877 struct hash_control * htab)
9879 int len = strlen (r->name) + 2;
9880 char * buf = xmalloc (len);
9881 char * buf2 = xmalloc (len);
9882 int i = 0;
9884 #ifdef REGISTER_PREFIX
9885 buf[i++] = REGISTER_PREFIX;
9886 #endif
9888 strcpy (buf + i, r->name);
9890 for (i = 0; buf[i]; i++)
9891 buf2[i] = TOUPPER (buf[i]);
9893 buf2[i] = '\0';
9895 hash_insert (htab, buf, (PTR) r);
9896 hash_insert (htab, buf2, (PTR) r);
9899 static void
9900 build_reg_hsh (struct reg_map * map)
9902 const struct reg_entry *r;
9904 if ((map->htab = hash_new ()) == NULL)
9905 as_fatal (_("virtual memory exhausted"));
9907 for (r = map->names; r->name != NULL; r++)
9908 insert_reg (r, map->htab);
9911 static void
9912 insert_reg_alias (char * str,
9913 int regnum,
9914 struct hash_control *htab)
9916 const char * error;
9917 struct reg_entry * new = xmalloc (sizeof (struct reg_entry));
9918 const char * name = xmalloc (strlen (str) + 1);
9920 strcpy ((char *) name, str);
9922 new->name = name;
9923 new->number = regnum;
9924 new->builtin = FALSE;
9926 error = hash_insert (htab, name, (PTR) new);
9927 if (error)
9929 as_bad (_("failed to create an alias for %s, reason: %s"),
9930 str, error);
9931 free ((char *) name);
9932 free (new);
9936 /* Look for the .req directive. This is of the form:
9938 new_register_name .req existing_register_name
9940 If we find one, or if it looks sufficiently like one that we want to
9941 handle any error here, return non-zero. Otherwise return zero. */
9943 static int
9944 create_register_alias (char * newname, char * p)
9946 char * q;
9947 char c;
9949 q = p;
9950 skip_whitespace (q);
9952 c = *p;
9953 *p = '\0';
9955 if (*q && !strncmp (q, ".req ", 5))
9957 char *copy_of_str;
9958 char *r;
9960 #ifndef IGNORE_OPCODE_CASE
9961 newname = original_case_string;
9962 #endif
9963 copy_of_str = newname;
9965 q += 4;
9966 skip_whitespace (q);
9968 for (r = q; *r != '\0'; r++)
9969 if (*r == ' ')
9970 break;
9972 if (r != q)
9974 enum arm_reg_type new_type, old_type;
9975 int old_regno;
9976 char d = *r;
9978 *r = '\0';
9979 old_type = arm_reg_parse_any (q);
9980 *r = d;
9982 new_type = arm_reg_parse_any (newname);
9984 if (new_type == REG_TYPE_MAX)
9986 if (old_type != REG_TYPE_MAX)
9988 old_regno = arm_reg_parse (&q, all_reg_maps[old_type].htab);
9989 insert_reg_alias (newname, old_regno,
9990 all_reg_maps[old_type].htab);
9992 else
9993 as_warn (_("register '%s' does not exist\n"), q);
9995 else if (old_type == REG_TYPE_MAX)
9997 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
9998 copy_of_str, q);
10000 else
10002 /* Do not warn about redefinitions to the same alias. */
10003 if (new_type != old_type
10004 || (arm_reg_parse (&q, all_reg_maps[old_type].htab)
10005 != arm_reg_parse (&q, all_reg_maps[new_type].htab)))
10006 as_warn (_("ignoring redefinition of register alias '%s'"),
10007 copy_of_str);
10011 else
10012 as_warn (_("ignoring incomplete .req pseuso op"));
10014 *p = c;
10015 return 1;
10018 *p = c;
10019 return 0;
10022 static void
10023 set_constant_flonums (void)
10025 int i;
10027 for (i = 0; i < NUM_FLOAT_VALS; i++)
10028 if (atof_ieee ((char *) fp_const[i], 'x', fp_values[i]) == NULL)
10029 abort ();
10033 static const struct asm_opcode insns[] =
10035 /* Core ARM Instructions. */
10036 {"and", 0xe0000000, 3, ARM_EXT_V1, do_arit},
10037 {"ands", 0xe0100000, 3, ARM_EXT_V1, do_arit},
10038 {"eor", 0xe0200000, 3, ARM_EXT_V1, do_arit},
10039 {"eors", 0xe0300000, 3, ARM_EXT_V1, do_arit},
10040 {"sub", 0xe0400000, 3, ARM_EXT_V1, do_arit},
10041 {"subs", 0xe0500000, 3, ARM_EXT_V1, do_arit},
10042 {"rsb", 0xe0600000, 3, ARM_EXT_V1, do_arit},
10043 {"rsbs", 0xe0700000, 3, ARM_EXT_V1, do_arit},
10044 {"add", 0xe0800000, 3, ARM_EXT_V1, do_arit},
10045 {"adds", 0xe0900000, 3, ARM_EXT_V1, do_arit},
10046 {"adc", 0xe0a00000, 3, ARM_EXT_V1, do_arit},
10047 {"adcs", 0xe0b00000, 3, ARM_EXT_V1, do_arit},
10048 {"sbc", 0xe0c00000, 3, ARM_EXT_V1, do_arit},
10049 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1, do_arit},
10050 {"rsc", 0xe0e00000, 3, ARM_EXT_V1, do_arit},
10051 {"rscs", 0xe0f00000, 3, ARM_EXT_V1, do_arit},
10052 {"orr", 0xe1800000, 3, ARM_EXT_V1, do_arit},
10053 {"orrs", 0xe1900000, 3, ARM_EXT_V1, do_arit},
10054 {"bic", 0xe1c00000, 3, ARM_EXT_V1, do_arit},
10055 {"bics", 0xe1d00000, 3, ARM_EXT_V1, do_arit},
10057 {"tst", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
10058 {"tsts", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
10059 {"tstp", 0xe110f000, 3, ARM_EXT_V1, do_cmp},
10060 {"teq", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
10061 {"teqs", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
10062 {"teqp", 0xe130f000, 3, ARM_EXT_V1, do_cmp},
10063 {"cmp", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
10064 {"cmps", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
10065 {"cmpp", 0xe150f000, 3, ARM_EXT_V1, do_cmp},
10066 {"cmn", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
10067 {"cmns", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
10068 {"cmnp", 0xe170f000, 3, ARM_EXT_V1, do_cmp},
10070 {"mov", 0xe1a00000, 3, ARM_EXT_V1, do_mov},
10071 {"movs", 0xe1b00000, 3, ARM_EXT_V1, do_mov},
10072 {"mvn", 0xe1e00000, 3, ARM_EXT_V1, do_mov},
10073 {"mvns", 0xe1f00000, 3, ARM_EXT_V1, do_mov},
10075 {"ldr", 0xe4100000, 3, ARM_EXT_V1, do_ldst},
10076 {"ldrb", 0xe4500000, 3, ARM_EXT_V1, do_ldst},
10077 {"ldrt", 0xe4300000, 3, ARM_EXT_V1, do_ldstt},
10078 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1, do_ldstt},
10079 {"str", 0xe4000000, 3, ARM_EXT_V1, do_ldst},
10080 {"strb", 0xe4400000, 3, ARM_EXT_V1, do_ldst},
10081 {"strt", 0xe4200000, 3, ARM_EXT_V1, do_ldstt},
10082 {"strbt", 0xe4600000, 3, ARM_EXT_V1, do_ldstt},
10084 {"stmia", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
10085 {"stmib", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
10086 {"stmda", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
10087 {"stmdb", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
10088 {"stmfd", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
10089 {"stmfa", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
10090 {"stmea", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
10091 {"stmed", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
10093 {"ldmia", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
10094 {"ldmib", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
10095 {"ldmda", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
10096 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
10097 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
10098 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
10099 {"ldmea", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
10100 {"ldmed", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
10102 {"swi", 0xef000000, 3, ARM_EXT_V1, do_swi},
10103 #ifdef TE_WINCE
10104 /* XXX This is the wrong place to do this. Think multi-arch. */
10105 {"bl", 0xeb000000, 2, ARM_EXT_V1, do_branch},
10106 {"b", 0xea000000, 1, ARM_EXT_V1, do_branch},
10107 #else
10108 {"bl", 0xebfffffe, 2, ARM_EXT_V1, do_branch},
10109 {"b", 0xeafffffe, 1, ARM_EXT_V1, do_branch},
10110 #endif
10112 /* Pseudo ops. */
10113 {"adr", 0xe28f0000, 3, ARM_EXT_V1, do_adr},
10114 {"adrl", 0xe28f0000, 3, ARM_EXT_V1, do_adrl},
10115 {"nop", 0xe1a00000, 3, ARM_EXT_V1, do_nop},
10117 /* ARM 2 multiplies. */
10118 {"mul", 0xe0000090, 3, ARM_EXT_V2, do_mul},
10119 {"muls", 0xe0100090, 3, ARM_EXT_V2, do_mul},
10120 {"mla", 0xe0200090, 3, ARM_EXT_V2, do_mla},
10121 {"mlas", 0xe0300090, 3, ARM_EXT_V2, do_mla},
10123 /* Generic coprocessor instructions. */
10124 {"cdp", 0xee000000, 3, ARM_EXT_V2, do_cdp},
10125 {"ldc", 0xec100000, 3, ARM_EXT_V2, do_lstc},
10126 {"ldcl", 0xec500000, 3, ARM_EXT_V2, do_lstc},
10127 {"stc", 0xec000000, 3, ARM_EXT_V2, do_lstc},
10128 {"stcl", 0xec400000, 3, ARM_EXT_V2, do_lstc},
10129 {"mcr", 0xee000010, 3, ARM_EXT_V2, do_co_reg},
10130 {"mrc", 0xee100010, 3, ARM_EXT_V2, do_co_reg},
10132 /* ARM 3 - swp instructions. */
10133 {"swp", 0xe1000090, 3, ARM_EXT_V2S, do_swap},
10134 {"swpb", 0xe1400090, 3, ARM_EXT_V2S, do_swap},
10136 /* ARM 6 Status register instructions. */
10137 {"mrs", 0xe10f0000, 3, ARM_EXT_V3, do_mrs},
10138 {"msr", 0xe120f000, 3, ARM_EXT_V3, do_msr},
10139 /* ScottB: our code uses 0xe128f000 for msr.
10140 NickC: but this is wrong because the bits 16 through 19 are
10141 handled by the PSR_xxx defines above. */
10143 /* ARM 7M long multiplies. */
10144 {"smull", 0xe0c00090, 5, ARM_EXT_V3M, do_mull},
10145 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M, do_mull},
10146 {"umull", 0xe0800090, 5, ARM_EXT_V3M, do_mull},
10147 {"umulls", 0xe0900090, 5, ARM_EXT_V3M, do_mull},
10148 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M, do_mull},
10149 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M, do_mull},
10150 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M, do_mull},
10151 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M, do_mull},
10153 /* ARM Architecture 4. */
10154 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4, do_ldstv4},
10155 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4, do_ldstv4},
10156 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4, do_ldstv4},
10157 {"strh", 0xe00000b0, 3, ARM_EXT_V4, do_ldstv4},
10159 /* ARM Architecture 4T. */
10160 /* Note: bx (and blx) are required on V5, even if the processor does
10161 not support Thumb. */
10162 {"bx", 0xe12fff10, 2, ARM_EXT_V4T | ARM_EXT_V5, do_bx},
10164 /* ARM Architecture 5T. */
10165 /* Note: blx has 2 variants, so the .value is set dynamically.
10166 Only one of the variants has conditional execution. */
10167 {"blx", 0xe0000000, 3, ARM_EXT_V5, do_blx},
10168 {"clz", 0xe16f0f10, 3, ARM_EXT_V5, do_clz},
10169 {"bkpt", 0xe1200070, 0, ARM_EXT_V5, do_bkpt},
10170 {"ldc2", 0xfc100000, 0, ARM_EXT_V5, do_lstc2},
10171 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5, do_lstc2},
10172 {"stc2", 0xfc000000, 0, ARM_EXT_V5, do_lstc2},
10173 {"stc2l", 0xfc400000, 0, ARM_EXT_V5, do_lstc2},
10174 {"cdp2", 0xfe000000, 0, ARM_EXT_V5, do_cdp2},
10175 {"mcr2", 0xfe000010, 0, ARM_EXT_V5, do_co_reg2},
10176 {"mrc2", 0xfe100010, 0, ARM_EXT_V5, do_co_reg2},
10178 /* ARM Architecture 5TExP. */
10179 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP, do_smla},
10180 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP, do_smla},
10181 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP, do_smla},
10182 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP, do_smla},
10184 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP, do_smla},
10185 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP, do_smla},
10187 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP, do_smlal},
10188 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP, do_smlal},
10189 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP, do_smlal},
10190 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP, do_smlal},
10192 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP, do_smul},
10193 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP, do_smul},
10194 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP, do_smul},
10195 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP, do_smul},
10197 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP, do_smul},
10198 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP, do_smul},
10200 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP, do_qadd},
10201 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP, do_qadd},
10202 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP, do_qadd},
10203 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP, do_qadd},
10205 /* ARM Architecture 5TE. */
10206 {"pld", 0xf450f000, 0, ARM_EXT_V5E, do_pld},
10207 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E, do_ldrd},
10208 {"strd", 0xe00000f0, 3, ARM_EXT_V5E, do_ldrd},
10210 {"mcrr", 0xec400000, 4, ARM_EXT_V5E, do_co_reg2c},
10211 {"mrrc", 0xec500000, 4, ARM_EXT_V5E, do_co_reg2c},
10213 /* ARM Architecture 5TEJ. */
10214 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J, do_bxj},
10216 /* ARM V6. */
10217 { "cps", 0xf1020000, 0, ARM_EXT_V6, do_cps},
10218 { "cpsie", 0xf1080000, 0, ARM_EXT_V6, do_cpsi},
10219 { "cpsid", 0xf10C0000, 0, ARM_EXT_V6, do_cpsi},
10220 { "ldrex", 0xe1900f9f, 5, ARM_EXT_V6, do_ldrex},
10221 { "mcrr2", 0xfc400000, 0, ARM_EXT_V6, do_co_reg2c},
10222 { "mrrc2", 0xfc500000, 0, ARM_EXT_V6, do_co_reg2c},
10223 { "pkhbt", 0xe6800010, 5, ARM_EXT_V6, do_pkhbt},
10224 { "pkhtb", 0xe6800050, 5, ARM_EXT_V6, do_pkhtb},
10225 { "qadd16", 0xe6200f10, 6, ARM_EXT_V6, do_qadd16},
10226 { "qadd8", 0xe6200f90, 5, ARM_EXT_V6, do_qadd16},
10227 { "qaddsubx", 0xe6200f30, 8, ARM_EXT_V6, do_qadd16},
10228 { "qsub16", 0xe6200f70, 6, ARM_EXT_V6, do_qadd16},
10229 { "qsub8", 0xe6200ff0, 5, ARM_EXT_V6, do_qadd16},
10230 { "qsubaddx", 0xe6200f50, 8, ARM_EXT_V6, do_qadd16},
10231 { "sadd16", 0xe6100f10, 6, ARM_EXT_V6, do_qadd16},
10232 { "sadd8", 0xe6100f90, 5, ARM_EXT_V6, do_qadd16},
10233 { "saddsubx", 0xe6100f30, 8, ARM_EXT_V6, do_qadd16},
10234 { "shadd16", 0xe6300f10, 7, ARM_EXT_V6, do_qadd16},
10235 { "shadd8", 0xe6300f90, 6, ARM_EXT_V6, do_qadd16},
10236 { "shaddsubx", 0xe6300f30, 9, ARM_EXT_V6, do_qadd16},
10237 { "shsub16", 0xe6300f70, 7, ARM_EXT_V6, do_qadd16},
10238 { "shsub8", 0xe6300ff0, 6, ARM_EXT_V6, do_qadd16},
10239 { "shsubaddx", 0xe6300f50, 9, ARM_EXT_V6, do_qadd16},
10240 { "ssub16", 0xe6100f70, 6, ARM_EXT_V6, do_qadd16},
10241 { "ssub8", 0xe6100ff0, 5, ARM_EXT_V6, do_qadd16},
10242 { "ssubaddx", 0xe6100f50, 8, ARM_EXT_V6, do_qadd16},
10243 { "uadd16", 0xe6500f10, 6, ARM_EXT_V6, do_qadd16},
10244 { "uadd8", 0xe6500f90, 5, ARM_EXT_V6, do_qadd16},
10245 { "uaddsubx", 0xe6500f30, 8, ARM_EXT_V6, do_qadd16},
10246 { "uhadd16", 0xe6700f10, 7, ARM_EXT_V6, do_qadd16},
10247 { "uhadd8", 0xe6700f90, 6, ARM_EXT_V6, do_qadd16},
10248 { "uhaddsubx", 0xe6700f30, 9, ARM_EXT_V6, do_qadd16},
10249 { "uhsub16", 0xe6700f70, 7, ARM_EXT_V6, do_qadd16},
10250 { "uhsub8", 0xe6700ff0, 6, ARM_EXT_V6, do_qadd16},
10251 { "uhsubaddx", 0xe6700f50, 9, ARM_EXT_V6, do_qadd16},
10252 { "uqadd16", 0xe6600f10, 7, ARM_EXT_V6, do_qadd16},
10253 { "uqadd8", 0xe6600f90, 6, ARM_EXT_V6, do_qadd16},
10254 { "uqaddsubx", 0xe6600f30, 9, ARM_EXT_V6, do_qadd16},
10255 { "uqsub16", 0xe6600f70, 7, ARM_EXT_V6, do_qadd16},
10256 { "uqsub8", 0xe6600ff0, 6, ARM_EXT_V6, do_qadd16},
10257 { "uqsubaddx", 0xe6600f50, 9, ARM_EXT_V6, do_qadd16},
10258 { "usub16", 0xe6500f70, 6, ARM_EXT_V6, do_qadd16},
10259 { "usub8", 0xe6500ff0, 5, ARM_EXT_V6, do_qadd16},
10260 { "usubaddx", 0xe6500f50, 8, ARM_EXT_V6, do_qadd16},
10261 { "rev", 0xe6bf0f30, 3, ARM_EXT_V6, do_rev},
10262 { "rev16", 0xe6bf0fb0, 5, ARM_EXT_V6, do_rev},
10263 { "revsh", 0xe6ff0fb0, 5, ARM_EXT_V6, do_rev},
10264 { "rfeia", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
10265 { "rfeib", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
10266 { "rfeda", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
10267 { "rfedb", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
10268 { "rfefd", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
10269 { "rfefa", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
10270 { "rfeea", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
10271 { "rfeed", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
10272 { "sxtah", 0xe6b00070, 5, ARM_EXT_V6, do_sxtah},
10273 { "sxtab16", 0xe6800070, 7, ARM_EXT_V6, do_sxtah},
10274 { "sxtab", 0xe6a00070, 5, ARM_EXT_V6, do_sxtah},
10275 { "sxth", 0xe6bf0070, 4, ARM_EXT_V6, do_sxth},
10276 { "sxtb16", 0xe68f0070, 6, ARM_EXT_V6, do_sxth},
10277 { "sxtb", 0xe6af0070, 4, ARM_EXT_V6, do_sxth},
10278 { "uxtah", 0xe6f00070, 5, ARM_EXT_V6, do_sxtah},
10279 { "uxtab16", 0xe6c00070, 7, ARM_EXT_V6, do_sxtah},
10280 { "uxtab", 0xe6e00070, 5, ARM_EXT_V6, do_sxtah},
10281 { "uxth", 0xe6ff0070, 4, ARM_EXT_V6, do_sxth},
10282 { "uxtb16", 0xe6cf0070, 6, ARM_EXT_V6, do_sxth},
10283 { "uxtb", 0xe6ef0070, 4, ARM_EXT_V6, do_sxth},
10284 { "sel", 0xe68000b0, 3, ARM_EXT_V6, do_qadd16},
10285 { "setend", 0xf1010000, 0, ARM_EXT_V6, do_setend},
10286 { "smlad", 0xe7000010, 5, ARM_EXT_V6, do_smlad},
10287 { "smladx", 0xe7000030, 6, ARM_EXT_V6, do_smlad},
10288 { "smlald", 0xe7400010, 6, ARM_EXT_V6, do_smlald},
10289 { "smlaldx", 0xe7400030, 7, ARM_EXT_V6, do_smlald},
10290 { "smlsd", 0xe7000050, 5, ARM_EXT_V6, do_smlad},
10291 { "smlsdx", 0xe7000070, 6, ARM_EXT_V6, do_smlad},
10292 { "smlsld", 0xe7400050, 6, ARM_EXT_V6, do_smlald},
10293 { "smlsldx", 0xe7400070, 7, ARM_EXT_V6, do_smlald},
10294 { "smmla", 0xe7500010, 5, ARM_EXT_V6, do_smlad},
10295 { "smmlar", 0xe7500030, 6, ARM_EXT_V6, do_smlad},
10296 { "smmls", 0xe75000d0, 5, ARM_EXT_V6, do_smlad},
10297 { "smmlsr", 0xe75000f0, 6, ARM_EXT_V6, do_smlad},
10298 { "smmul", 0xe750f010, 5, ARM_EXT_V6, do_smmul},
10299 { "smmulr", 0xe750f030, 6, ARM_EXT_V6, do_smmul},
10300 { "smuad", 0xe700f010, 5, ARM_EXT_V6, do_smmul},
10301 { "smuadx", 0xe700f030, 6, ARM_EXT_V6, do_smmul},
10302 { "smusd", 0xe700f050, 5, ARM_EXT_V6, do_smmul},
10303 { "smusdx", 0xe700f070, 6, ARM_EXT_V6, do_smmul},
10304 { "srsia", 0xf8cd0500, 0, ARM_EXT_V6, do_srs},
10305 { "srsib", 0xf9cd0500, 0, ARM_EXT_V6, do_srs},
10306 { "srsda", 0xf84d0500, 0, ARM_EXT_V6, do_srs},
10307 { "srsdb", 0xf94d0500, 0, ARM_EXT_V6, do_srs},
10308 { "ssat", 0xe6a00010, 4, ARM_EXT_V6, do_ssat},
10309 { "ssat16", 0xe6a00f30, 6, ARM_EXT_V6, do_ssat16},
10310 { "strex", 0xe1800f90, 5, ARM_EXT_V6, do_strex},
10311 { "umaal", 0xe0400090, 5, ARM_EXT_V6, do_umaal},
10312 { "usad8", 0xe780f010, 5, ARM_EXT_V6, do_smmul},
10313 { "usada8", 0xe7800010, 6, ARM_EXT_V6, do_smlad},
10314 { "usat", 0xe6e00010, 4, ARM_EXT_V6, do_usat},
10315 { "usat16", 0xe6e00f30, 6, ARM_EXT_V6, do_usat16},
10317 /* ARM V6K. */
10318 { "clrex", 0xf57ff01f, 0, ARM_EXT_V6K, do_empty},
10319 { "ldrexb", 0xe1d00f9f, 6, ARM_EXT_V6K, do_ldrex},
10320 { "ldrexd", 0xe1b00f9f, 6, ARM_EXT_V6K, do_ldrex},
10321 { "ldrexh", 0xe1f00f9f, 6, ARM_EXT_V6K, do_ldrex},
10322 { "sev", 0xe320f004, 3, ARM_EXT_V6K, do_empty},
10323 { "strexb", 0xe1c00f90, 6, ARM_EXT_V6K, do_strex},
10324 { "strexd", 0xe1a00f90, 6, ARM_EXT_V6K, do_strex},
10325 { "strexh", 0xe1e00f90, 6, ARM_EXT_V6K, do_strex},
10326 { "wfe", 0xe320f002, 3, ARM_EXT_V6K, do_empty},
10327 { "wfi", 0xe320f003, 3, ARM_EXT_V6K, do_empty},
10328 { "yield", 0xe320f001, 5, ARM_EXT_V6K, do_empty},
10330 /* ARM V6Z. */
10331 { "smi", 0xe1600070, 3, ARM_EXT_V6Z, do_smi},
10333 /* ARM V6T2. */
10334 { "bfc", 0xe7c0001f, 3, ARM_EXT_V6T2, do_bfc},
10335 { "bfi", 0xe7c00010, 3, ARM_EXT_V6T2, do_bfi},
10336 { "mls", 0xe0600090, 3, ARM_EXT_V6T2, do_mls},
10337 { "movw", 0xe3000000, 4, ARM_EXT_V6T2, do_mov16},
10338 { "movt", 0xe3400000, 4, ARM_EXT_V6T2, do_mov16},
10339 { "rbit", 0xe3ff0f30, 4, ARM_EXT_V6T2, do_rbit},
10340 { "sbfx", 0xe7a00050, 4, ARM_EXT_V6T2, do_bfx},
10341 { "ubfx", 0xe7e00050, 4, ARM_EXT_V6T2, do_bfx},
10343 { "ldrht", 0xe03000b0, 3, ARM_EXT_V6T2, do_ldsttv4},
10344 { "ldrsht", 0xe03000f0, 3, ARM_EXT_V6T2, do_ldsttv4},
10345 { "ldrsbt", 0xe03000d0, 3, ARM_EXT_V6T2, do_ldsttv4},
10346 { "strht", 0xe02000b0, 3, ARM_EXT_V6T2, do_ldsttv4},
10348 /* Core FPA instruction set (V1). */
10349 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10350 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10351 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10352 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10354 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10355 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10356 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10357 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10359 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10360 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10361 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10362 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10364 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10365 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10366 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10367 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10368 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10369 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10370 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10371 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10372 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10373 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10374 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10375 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10377 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10378 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10379 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10380 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10381 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10382 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10383 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10384 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10385 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10386 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10387 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10388 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10390 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10391 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10392 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10393 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10394 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10395 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10396 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10397 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10398 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10399 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10400 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10401 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10403 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10404 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10405 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10406 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10407 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10408 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10409 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10410 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10411 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10412 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10413 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10414 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10416 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10417 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10418 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10419 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10420 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10421 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10422 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10423 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10424 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10425 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10426 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10427 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10429 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10430 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10431 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10432 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10433 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10434 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10435 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10436 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10437 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10438 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10439 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10440 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10442 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10443 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10444 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10445 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10446 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10447 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10448 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10449 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10450 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10451 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10452 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10453 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10455 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10456 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10457 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10458 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10459 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10460 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10461 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10462 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10463 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10464 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10465 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10466 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10468 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10469 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10470 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10471 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10472 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10473 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10474 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10475 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10476 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10477 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10478 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10479 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10481 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10482 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10483 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10484 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10485 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10486 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10487 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10488 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10489 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10490 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10491 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10492 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10494 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10495 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10496 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10497 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10498 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10499 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10500 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10501 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10502 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10503 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10504 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10505 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10507 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10508 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10509 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10510 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10511 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10512 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10513 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10514 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10515 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10516 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10517 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10518 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10520 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10521 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10522 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10523 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10524 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10525 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10526 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10527 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10528 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10529 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10530 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10531 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10533 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10534 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10535 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10536 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10537 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10538 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10539 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10540 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10541 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10542 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10543 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10544 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10546 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10547 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10548 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10549 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10550 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10551 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10552 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10553 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10554 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10555 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10556 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10557 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10559 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10560 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10561 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10562 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10563 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10564 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10565 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10566 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10567 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10568 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10569 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10570 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10572 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10573 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10574 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10575 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10576 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10577 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10578 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10579 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10580 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10581 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10582 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10583 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10585 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10586 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10587 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10588 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10589 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10590 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10591 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10592 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10593 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10594 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10595 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10596 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10598 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10599 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10600 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10601 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10602 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10603 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10604 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10605 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10606 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10607 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10608 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10609 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10611 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10612 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10613 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10614 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10615 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10616 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10617 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10618 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10619 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10620 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10621 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10622 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10624 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10625 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10626 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10627 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10628 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10629 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10630 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10631 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10632 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10633 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10634 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10635 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10637 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10638 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10639 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10640 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10641 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10642 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10643 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10644 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10645 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10646 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10647 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10648 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10650 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10651 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10652 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10653 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10654 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10655 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10656 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10657 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10658 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10659 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10660 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10661 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10663 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10664 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10665 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10666 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10667 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10668 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10669 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10670 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10671 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10672 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10673 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10674 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10676 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10677 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10678 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10679 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10680 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10681 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10682 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10683 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10684 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10685 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10686 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10687 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10689 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10690 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10691 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10692 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10693 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10694 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10695 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10696 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10697 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10698 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10699 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10700 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10702 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10703 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10704 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10705 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10706 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10707 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10708 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10709 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10710 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10711 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10712 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10713 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10715 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10716 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10717 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10718 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10719 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10720 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10721 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10722 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10723 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10724 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10725 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10726 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10728 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10729 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10730 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10731 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10732 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10733 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10734 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10735 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10736 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10737 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10738 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10739 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10741 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10742 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10743 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10744 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10745 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
10746 not be an optional suffix, but part of the instruction. To be
10747 compatible, we accept either. */
10748 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
10749 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
10751 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10752 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10753 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10754 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10755 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10756 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10757 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10758 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10759 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10760 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10761 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10762 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10764 /* The implementation of the FIX instruction is broken on some
10765 assemblers, in that it accepts a precision specifier as well as a
10766 rounding specifier, despite the fact that this is meaningless.
10767 To be more compatible, we accept it as well, though of course it
10768 does not set any bits. */
10769 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10770 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10771 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10772 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10773 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10774 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10775 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10776 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10777 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10778 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10779 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10780 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10781 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10783 /* Instructions that were new with the real FPA, call them V2. */
10784 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10785 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10786 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10787 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10788 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10789 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10791 /* VFP V1xD (single precision). */
10792 /* Moves and type conversions. */
10793 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10794 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_sp},
10795 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_from_reg},
10796 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD, do_empty},
10797 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10798 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10799 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10800 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10801 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10802 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10803 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_ctrl},
10804 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_ctrl_from_reg},
10806 /* Memory operations. */
10807 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
10808 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
10809 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10810 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10811 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10812 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10813 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10814 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10815 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10816 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10817 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10818 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10819 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10820 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10821 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10822 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10823 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10824 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10826 /* Monadic operations. */
10827 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10828 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10829 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10831 /* Dyadic operations. */
10832 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10833 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10834 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10835 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10836 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10837 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10838 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10839 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10840 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10842 /* Comparisons. */
10843 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10844 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
10845 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10846 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
10848 /* VFP V1 (Double precision). */
10849 /* Moves and type conversions. */
10850 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10851 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
10852 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10853 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
10854 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
10855 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
10856 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
10857 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
10858 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
10859 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10860 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10861 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10862 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10864 /* Memory operations. */
10865 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
10866 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
10867 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10868 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10869 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10870 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10871 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10872 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10873 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10874 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10876 /* Monadic operations. */
10877 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10878 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10879 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10881 /* Dyadic operations. */
10882 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10883 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10884 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10885 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10886 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10887 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10888 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10889 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10890 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10892 /* Comparisons. */
10893 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10894 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
10895 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10896 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
10898 /* VFP V2. */
10899 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2, do_vfp_sp2_from_reg2},
10900 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_sp2},
10901 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2, do_vfp_dp_from_reg2},
10902 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_dp},
10904 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
10905 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE, do_xsc_mia},
10906 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10907 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10908 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10909 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10910 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10911 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE, do_xsc_mar},
10912 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE, do_xsc_mra},
10914 /* Intel Wireless MMX technology instructions. */
10915 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
10916 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
10917 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
10918 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
10919 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
10920 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
10921 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
10922 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
10923 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
10924 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10925 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10926 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10927 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10928 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10929 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10930 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
10931 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
10932 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
10933 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmcr},
10934 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmcrr},
10935 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10936 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10937 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10938 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10939 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10940 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10941 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
10942 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
10943 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
10944 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmrc},
10945 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmrrc},
10946 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
10947 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
10948 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
10949 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10950 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10951 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10952 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10953 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10954 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10955 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10956 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10957 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10958 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10959 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10960 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10961 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT, do_iwmmxt_waligni},
10962 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10963 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10964 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10965 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10966 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10967 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10968 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10969 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10970 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10971 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10972 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10973 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10974 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10975 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10976 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10977 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10978 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10979 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10980 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10981 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
10982 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
10983 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
10984 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
10985 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10986 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10987 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10988 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10989 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10990 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10991 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10992 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10993 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10994 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10995 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10996 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10997 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10998 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10999 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11000 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11001 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11002 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11003 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wmov},
11004 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11005 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11006 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11007 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11008 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11009 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11010 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11011 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11012 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11013 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11014 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11015 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11016 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11017 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11018 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11019 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11020 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11021 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11022 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11023 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11024 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11025 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wshufh},
11026 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11027 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11028 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11029 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11030 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11031 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11032 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11033 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11034 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11035 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11036 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11037 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11038 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11039 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11040 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11041 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11042 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11043 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11044 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
11045 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
11046 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
11047 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
11048 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11049 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11050 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11051 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11052 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11053 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11054 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11055 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11056 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11057 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11058 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11059 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11060 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11061 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11062 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11063 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11064 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11065 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11066 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11067 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11068 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11069 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11070 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11071 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11072 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11073 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11074 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11075 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11076 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wzero},
11078 /* Cirrus Maverick instructions. */
11079 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
11080 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
11081 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
11082 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
11083 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
11084 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
11085 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
11086 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
11087 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK, do_mav_binops_2a},
11088 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK, do_mav_binops_1a},
11089 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
11090 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
11091 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
11092 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
11093 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
11094 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
11095 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
11096 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
11097 {"cfmval32", 0xee200440, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
11098 {"cfmv32al", 0xee100440, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
11099 {"cfmvam32", 0xee200460, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
11100 {"cfmv32am", 0xee100460, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
11101 {"cfmvah32", 0xee200480, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
11102 {"cfmv32ah", 0xee100480, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
11103 {"cfmva32", 0xee2004a0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3a},
11104 {"cfmv32a", 0xee1004a0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3b},
11105 {"cfmva64", 0xee2004c0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3c},
11106 {"cfmv64a", 0xee1004c0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3d},
11107 {"cfmvsc32", 0xee2004e0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_1},
11108 {"cfmv32sc", 0xee1004e0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_2},
11109 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
11110 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
11111 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK, do_mav_binops_1f},
11112 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK, do_mav_binops_1g},
11113 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK, do_mav_binops_1h},
11114 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1i},
11115 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1j},
11116 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1k},
11117 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK, do_mav_binops_1l},
11118 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1m},
11119 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1l},
11120 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1m},
11121 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK, do_mav_triple_4a},
11122 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK, do_mav_triple_4b},
11123 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK, do_mav_shift_1},
11124 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK, do_mav_shift_2},
11125 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK, do_mav_triple_5a},
11126 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5b},
11127 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK, do_mav_triple_5c},
11128 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5d},
11129 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
11130 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
11131 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
11132 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
11133 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
11134 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
11135 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
11136 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
11137 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
11138 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
11139 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
11140 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
11141 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
11142 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
11143 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
11144 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
11145 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
11146 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
11147 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
11148 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
11149 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
11150 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
11151 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
11152 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
11153 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
11154 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
11157 /* Iterate over the base tables to create the instruction patterns. */
11159 static void
11160 build_arm_ops_hsh (void)
11162 unsigned int i;
11163 unsigned int j;
11164 static struct obstack insn_obstack;
11166 obstack_begin (&insn_obstack, 4000);
11168 for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
11170 const struct asm_opcode *insn = insns + i;
11172 if (insn->cond_offset != 0)
11174 /* Insn supports conditional execution. Build the varaints
11175 and insert them in the hash table. */
11176 for (j = 0; j < sizeof (conds) / sizeof (struct asm_cond); j++)
11178 unsigned len = strlen (insn->template);
11179 struct asm_opcode *new;
11180 char *template;
11182 new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
11183 /* All condition codes are two characters. */
11184 template = obstack_alloc (&insn_obstack, len + 3);
11186 strncpy (template, insn->template, insn->cond_offset);
11187 strcpy (template + insn->cond_offset, conds[j].template);
11188 if (len > insn->cond_offset)
11189 strcpy (template + insn->cond_offset + 2,
11190 insn->template + insn->cond_offset);
11191 new->template = template;
11192 new->cond_offset = 0;
11193 new->variant = insn->variant;
11194 new->parms = insn->parms;
11195 new->value = (insn->value & ~COND_MASK) | conds[j].value;
11197 hash_insert (arm_ops_hsh, new->template, (PTR) new);
11200 /* Finally, insert the unconditional insn in the table directly;
11201 no need to build a copy. */
11202 hash_insert (arm_ops_hsh, insn->template, (PTR) insn);
11207 static const struct thumb_opcode tinsns[] =
11209 /* Thumb v1 (ARMv4T). */
11210 {"adc", 0x4140, 2, ARM_EXT_V4T, do_t_arit},
11211 {"add", 0x0000, 2, ARM_EXT_V4T, do_t_add},
11212 {"and", 0x4000, 2, ARM_EXT_V4T, do_t_arit},
11213 {"asr", 0x0000, 2, ARM_EXT_V4T, do_t_asr},
11214 {"b", T_OPCODE_BRANCH, 2, ARM_EXT_V4T, do_t_branch12},
11215 {"beq", 0xd0fe, 2, ARM_EXT_V4T, do_t_branch9},
11216 {"bne", 0xd1fe, 2, ARM_EXT_V4T, do_t_branch9},
11217 {"bcs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
11218 {"bhs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
11219 {"bcc", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
11220 {"bul", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
11221 {"blo", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
11222 {"bmi", 0xd4fe, 2, ARM_EXT_V4T, do_t_branch9},
11223 {"bpl", 0xd5fe, 2, ARM_EXT_V4T, do_t_branch9},
11224 {"bvs", 0xd6fe, 2, ARM_EXT_V4T, do_t_branch9},
11225 {"bvc", 0xd7fe, 2, ARM_EXT_V4T, do_t_branch9},
11226 {"bhi", 0xd8fe, 2, ARM_EXT_V4T, do_t_branch9},
11227 {"bls", 0xd9fe, 2, ARM_EXT_V4T, do_t_branch9},
11228 {"bge", 0xdafe, 2, ARM_EXT_V4T, do_t_branch9},
11229 {"blt", 0xdbfe, 2, ARM_EXT_V4T, do_t_branch9},
11230 {"bgt", 0xdcfe, 2, ARM_EXT_V4T, do_t_branch9},
11231 {"ble", 0xddfe, 2, ARM_EXT_V4T, do_t_branch9},
11232 {"bal", 0xdefe, 2, ARM_EXT_V4T, do_t_branch9},
11233 {"bic", 0x4380, 2, ARM_EXT_V4T, do_t_arit},
11234 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T, do_t_branch23},
11235 {"bx", 0x4700, 2, ARM_EXT_V4T, do_t_bx},
11236 {"cmn", T_OPCODE_CMN, 2, ARM_EXT_V4T, do_t_arit},
11237 {"cmp", 0x0000, 2, ARM_EXT_V4T, do_t_compare},
11238 {"eor", 0x4040, 2, ARM_EXT_V4T, do_t_arit},
11239 {"ldmia", 0xc800, 2, ARM_EXT_V4T, do_t_ldmstm},
11240 {"ldr", 0x0000, 2, ARM_EXT_V4T, do_t_ldr},
11241 {"ldrb", 0x0000, 2, ARM_EXT_V4T, do_t_ldrb},
11242 {"ldrh", 0x0000, 2, ARM_EXT_V4T, do_t_ldrh},
11243 {"ldrsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
11244 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
11245 {"ldsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
11246 {"ldsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
11247 {"lsl", 0x0000, 2, ARM_EXT_V4T, do_t_lsl},
11248 {"lsr", 0x0000, 2, ARM_EXT_V4T, do_t_lsr},
11249 {"mov", 0x0000, 2, ARM_EXT_V4T, do_t_mov},
11250 {"mul", T_OPCODE_MUL, 2, ARM_EXT_V4T, do_t_arit},
11251 {"mvn", T_OPCODE_MVN, 2, ARM_EXT_V4T, do_t_arit},
11252 {"neg", T_OPCODE_NEG, 2, ARM_EXT_V4T, do_t_arit},
11253 {"orr", 0x4300, 2, ARM_EXT_V4T, do_t_arit},
11254 {"pop", 0xbc00, 2, ARM_EXT_V4T, do_t_push_pop},
11255 {"push", 0xb400, 2, ARM_EXT_V4T, do_t_push_pop},
11256 {"ror", 0x41c0, 2, ARM_EXT_V4T, do_t_arit},
11257 {"sbc", 0x4180, 2, ARM_EXT_V4T, do_t_arit},
11258 {"stmia", 0xc000, 2, ARM_EXT_V4T, do_t_ldmstm},
11259 {"str", 0x0000, 2, ARM_EXT_V4T, do_t_str},
11260 {"strb", 0x0000, 2, ARM_EXT_V4T, do_t_strb},
11261 {"strh", 0x0000, 2, ARM_EXT_V4T, do_t_strh},
11262 {"swi", 0xdf00, 2, ARM_EXT_V4T, do_t_swi},
11263 {"sub", 0x0000, 2, ARM_EXT_V4T, do_t_sub},
11264 {"tst", T_OPCODE_TST, 2, ARM_EXT_V4T, do_t_arit},
11265 /* Pseudo ops: */
11266 {"adr", 0x0000, 2, ARM_EXT_V4T, do_t_adr},
11267 {"nop", 0x46C0, 2, ARM_EXT_V4T, do_t_nop}, /* mov r8,r8 */
11268 /* Thumb v2 (ARMv5T). */
11269 {"blx", 0, 0, ARM_EXT_V5T, do_t_blx},
11270 {"bkpt", 0xbe00, 2, ARM_EXT_V5T, do_t_bkpt},
11272 /* ARM V6. */
11273 {"cpsie", 0xb660, 2, ARM_EXT_V6, do_t_cps},
11274 {"cpsid", 0xb670, 2, ARM_EXT_V6, do_t_cps},
11275 {"cpy", 0x4600, 2, ARM_EXT_V6, do_t_cpy},
11276 {"rev", 0xba00, 2, ARM_EXT_V6, do_t_arit},
11277 {"rev16", 0xba40, 2, ARM_EXT_V6, do_t_arit},
11278 {"revsh", 0xbac0, 2, ARM_EXT_V6, do_t_arit},
11279 {"setend", 0xb650, 2, ARM_EXT_V6, do_t_setend},
11280 {"sxth", 0xb200, 2, ARM_EXT_V6, do_t_arit},
11281 {"sxtb", 0xb240, 2, ARM_EXT_V6, do_t_arit},
11282 {"uxth", 0xb280, 2, ARM_EXT_V6, do_t_arit},
11283 {"uxtb", 0xb2c0, 2, ARM_EXT_V6, do_t_arit},
11285 /* ARM V6K. */
11286 {"sev", 0xbf40, 2, ARM_EXT_V6K, do_empty},
11287 {"wfe", 0xbf20, 2, ARM_EXT_V6K, do_empty},
11288 {"wfi", 0xbf30, 2, ARM_EXT_V6K, do_empty},
11289 {"yield", 0xbf10, 2, ARM_EXT_V6K, do_empty},
11292 void
11293 md_begin (void)
11295 unsigned mach;
11296 unsigned int i;
11298 if ( (arm_ops_hsh = hash_new ()) == NULL
11299 || (arm_tops_hsh = hash_new ()) == NULL
11300 || (arm_cond_hsh = hash_new ()) == NULL
11301 || (arm_shift_hsh = hash_new ()) == NULL
11302 || (arm_psr_hsh = hash_new ()) == NULL)
11303 as_fatal (_("virtual memory exhausted"));
11305 build_arm_ops_hsh ();
11306 for (i = 0; i < sizeof (tinsns) / sizeof (struct thumb_opcode); i++)
11307 hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
11308 for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
11309 hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
11310 for (i = 0; i < sizeof (shift_names) / sizeof (struct asm_shift_name); i++)
11311 hash_insert (arm_shift_hsh, shift_names[i].name, (PTR) (shift_names + i));
11312 for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
11313 hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
11315 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
11316 build_reg_hsh (all_reg_maps + i);
11318 set_constant_flonums ();
11320 /* Set the cpu variant based on the command-line options. We prefer
11321 -mcpu= over -march= if both are set (as for GCC); and we prefer
11322 -mfpu= over any other way of setting the floating point unit.
11323 Use of legacy options with new options are faulted. */
11324 if (legacy_cpu != -1)
11326 if (mcpu_cpu_opt != -1 || march_cpu_opt != -1)
11327 as_bad (_("use of old and new-style options to set CPU type"));
11329 mcpu_cpu_opt = legacy_cpu;
11331 else if (mcpu_cpu_opt == -1)
11332 mcpu_cpu_opt = march_cpu_opt;
11334 if (legacy_fpu != -1)
11336 if (mfpu_opt != -1)
11337 as_bad (_("use of old and new-style options to set FPU type"));
11339 mfpu_opt = legacy_fpu;
11341 else if (mfpu_opt == -1)
11343 #if !(defined (TE_LINUX) || defined (TE_NetBSD) || defined (TE_VXWORKS))
11344 /* Some environments specify a default FPU. If they don't, infer it
11345 from the processor. */
11346 if (mcpu_fpu_opt != -1)
11347 mfpu_opt = mcpu_fpu_opt;
11348 else
11349 mfpu_opt = march_fpu_opt;
11350 #else
11351 mfpu_opt = FPU_DEFAULT;
11352 #endif
11355 if (mfpu_opt == -1)
11357 if (mcpu_cpu_opt == -1)
11358 mfpu_opt = FPU_DEFAULT;
11359 else if (mcpu_cpu_opt & ARM_EXT_V5)
11360 mfpu_opt = FPU_ARCH_VFP_V2;
11361 else
11362 mfpu_opt = FPU_ARCH_FPA;
11365 if (mcpu_cpu_opt == -1)
11366 mcpu_cpu_opt = CPU_DEFAULT;
11368 cpu_variant = mcpu_cpu_opt | mfpu_opt;
11370 #if defined OBJ_COFF || defined OBJ_ELF
11372 unsigned int flags = 0;
11374 #if defined OBJ_ELF
11375 flags = meabi_flags;
11377 switch (meabi_flags)
11379 case EF_ARM_EABI_UNKNOWN:
11380 #endif
11381 /* Set the flags in the private structure. */
11382 if (uses_apcs_26) flags |= F_APCS26;
11383 if (support_interwork) flags |= F_INTERWORK;
11384 if (uses_apcs_float) flags |= F_APCS_FLOAT;
11385 if (pic_code) flags |= F_PIC;
11386 if ((cpu_variant & FPU_ANY) == FPU_NONE
11387 || (cpu_variant & FPU_ANY) == FPU_ARCH_VFP) /* VFP layout only. */
11388 flags |= F_SOFT_FLOAT;
11390 switch (mfloat_abi_opt)
11392 case ARM_FLOAT_ABI_SOFT:
11393 case ARM_FLOAT_ABI_SOFTFP:
11394 flags |= F_SOFT_FLOAT;
11395 break;
11397 case ARM_FLOAT_ABI_HARD:
11398 if (flags & F_SOFT_FLOAT)
11399 as_bad (_("hard-float conflicts with specified fpu"));
11400 break;
11403 /* Using VFP conventions (even if soft-float). */
11404 if (cpu_variant & FPU_VFP_EXT_NONE)
11405 flags |= F_VFP_FLOAT;
11407 #if defined OBJ_ELF
11408 if (cpu_variant & FPU_ARCH_MAVERICK)
11409 flags |= EF_ARM_MAVERICK_FLOAT;
11410 break;
11412 case EF_ARM_EABI_VER4:
11413 /* No additional flags to set. */
11414 break;
11416 default:
11417 abort ();
11419 #endif
11420 bfd_set_private_flags (stdoutput, flags);
11422 /* We have run out flags in the COFF header to encode the
11423 status of ATPCS support, so instead we create a dummy,
11424 empty, debug section called .arm.atpcs. */
11425 if (atpcs)
11427 asection * sec;
11429 sec = bfd_make_section (stdoutput, ".arm.atpcs");
11431 if (sec != NULL)
11433 bfd_set_section_flags
11434 (stdoutput, sec, SEC_READONLY | SEC_DEBUGGING /* | SEC_HAS_CONTENTS */);
11435 bfd_set_section_size (stdoutput, sec, 0);
11436 bfd_set_section_contents (stdoutput, sec, NULL, 0, 0);
11440 #endif
11442 /* Record the CPU type as well. */
11443 switch (cpu_variant & ARM_CPU_MASK)
11445 case ARM_2:
11446 mach = bfd_mach_arm_2;
11447 break;
11449 case ARM_3: /* Also ARM_250. */
11450 mach = bfd_mach_arm_2a;
11451 break;
11453 case ARM_6: /* Also ARM_7. */
11454 mach = bfd_mach_arm_3;
11455 break;
11457 default:
11458 mach = bfd_mach_arm_unknown;
11459 break;
11462 /* Catch special cases. */
11463 if (cpu_variant & ARM_CEXT_IWMMXT)
11464 mach = bfd_mach_arm_iWMMXt;
11465 else if (cpu_variant & ARM_CEXT_XSCALE)
11466 mach = bfd_mach_arm_XScale;
11467 else if (cpu_variant & ARM_CEXT_MAVERICK)
11468 mach = bfd_mach_arm_ep9312;
11469 else if (cpu_variant & ARM_EXT_V5E)
11470 mach = bfd_mach_arm_5TE;
11471 else if (cpu_variant & ARM_EXT_V5)
11473 if (cpu_variant & ARM_EXT_V4T)
11474 mach = bfd_mach_arm_5T;
11475 else
11476 mach = bfd_mach_arm_5;
11478 else if (cpu_variant & ARM_EXT_V4)
11480 if (cpu_variant & ARM_EXT_V4T)
11481 mach = bfd_mach_arm_4T;
11482 else
11483 mach = bfd_mach_arm_4;
11485 else if (cpu_variant & ARM_EXT_V3M)
11486 mach = bfd_mach_arm_3M;
11488 bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
11491 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11492 for use in the a.out file, and stores them in the array pointed to by buf.
11493 This knows about the endian-ness of the target machine and does
11494 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11495 2 (short) and 4 (long) Floating numbers are put out as a series of
11496 LITTLENUMS (shorts, here at least). */
11498 void
11499 md_number_to_chars (char * buf, valueT val, int n)
11501 if (target_big_endian)
11502 number_to_chars_bigendian (buf, val, n);
11503 else
11504 number_to_chars_littleendian (buf, val, n);
11507 static valueT
11508 md_chars_to_number (char * buf, int n)
11510 valueT result = 0;
11511 unsigned char * where = (unsigned char *) buf;
11513 if (target_big_endian)
11515 while (n--)
11517 result <<= 8;
11518 result |= (*where++ & 255);
11521 else
11523 while (n--)
11525 result <<= 8;
11526 result |= (where[n] & 255);
11530 return result;
11533 /* Turn a string in input_line_pointer into a floating point constant
11534 of type TYPE, and store the appropriate bytes in *LITP. The number
11535 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11536 returned, or NULL on OK.
11538 Note that fp constants aren't represent in the normal way on the ARM.
11539 In big endian mode, things are as expected. However, in little endian
11540 mode fp constants are big-endian word-wise, and little-endian byte-wise
11541 within the words. For example, (double) 1.1 in big endian mode is
11542 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11543 the byte sequence 99 99 f1 3f 9a 99 99 99.
11545 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11547 char *
11548 md_atof (int type, char * litP, int * sizeP)
11550 int prec;
11551 LITTLENUM_TYPE words[MAX_LITTLENUMS];
11552 char *t;
11553 int i;
11555 switch (type)
11557 case 'f':
11558 case 'F':
11559 case 's':
11560 case 'S':
11561 prec = 2;
11562 break;
11564 case 'd':
11565 case 'D':
11566 case 'r':
11567 case 'R':
11568 prec = 4;
11569 break;
11571 case 'x':
11572 case 'X':
11573 prec = 6;
11574 break;
11576 case 'p':
11577 case 'P':
11578 prec = 6;
11579 break;
11581 default:
11582 *sizeP = 0;
11583 return _("bad call to MD_ATOF()");
11586 t = atof_ieee (input_line_pointer, type, words);
11587 if (t)
11588 input_line_pointer = t;
11589 *sizeP = prec * 2;
11591 if (target_big_endian)
11593 for (i = 0; i < prec; i++)
11595 md_number_to_chars (litP, (valueT) words[i], 2);
11596 litP += 2;
11599 else
11601 if (cpu_variant & FPU_ARCH_VFP)
11602 for (i = prec - 1; i >= 0; i--)
11604 md_number_to_chars (litP, (valueT) words[i], 2);
11605 litP += 2;
11607 else
11608 /* For a 4 byte float the order of elements in `words' is 1 0.
11609 For an 8 byte float the order is 1 0 3 2. */
11610 for (i = 0; i < prec; i += 2)
11612 md_number_to_chars (litP, (valueT) words[i + 1], 2);
11613 md_number_to_chars (litP + 2, (valueT) words[i], 2);
11614 litP += 4;
11618 return 0;
11621 /* The knowledge of the PC's pipeline offset is built into the insns
11622 themselves. */
11624 long
11625 md_pcrel_from (fixS * fixP)
11627 if (fixP->fx_addsy
11628 && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section
11629 && fixP->fx_subsy == NULL)
11630 return 0;
11632 if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD))
11634 /* PC relative addressing on the Thumb is slightly odd
11635 as the bottom two bits of the PC are forced to zero
11636 for the calculation. */
11637 return (fixP->fx_where + fixP->fx_frag->fr_address) & ~3;
11640 #ifdef TE_WINCE
11641 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
11642 so we un-adjust here to compensate for the accommodation. */
11643 return fixP->fx_where + fixP->fx_frag->fr_address + 8;
11644 #else
11645 return fixP->fx_where + fixP->fx_frag->fr_address;
11646 #endif
11649 /* Round up a section size to the appropriate boundary. */
11651 valueT
11652 md_section_align (segT segment ATTRIBUTE_UNUSED,
11653 valueT size)
11655 #ifdef OBJ_ELF
11656 return size;
11657 #else
11658 /* Round all sects to multiple of 4. */
11659 return (size + 3) & ~3;
11660 #endif
11663 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
11664 Otherwise we have no need to default values of symbols. */
11666 symbolS *
11667 md_undefined_symbol (char * name ATTRIBUTE_UNUSED)
11669 #ifdef OBJ_ELF
11670 if (name[0] == '_' && name[1] == 'G'
11671 && streq (name, GLOBAL_OFFSET_TABLE_NAME))
11673 if (!GOT_symbol)
11675 if (symbol_find (name))
11676 as_bad ("GOT already in the symbol table");
11678 GOT_symbol = symbol_new (name, undefined_section,
11679 (valueT) 0, & zero_address_frag);
11682 return GOT_symbol;
11684 #endif
11686 return 0;
11689 void
11690 md_apply_fix3 (fixS * fixP,
11691 valueT * valP,
11692 segT seg)
11694 offsetT value = * valP;
11695 offsetT newval;
11696 unsigned int newimm;
11697 unsigned long temp;
11698 int sign;
11699 char * buf = fixP->fx_where + fixP->fx_frag->fr_literal;
11700 arm_fix_data * arm_data = (arm_fix_data *) fixP->tc_fix_data;
11702 assert (fixP->fx_r_type <= BFD_RELOC_UNUSED);
11704 /* Note whether this will delete the relocation. */
11705 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
11706 fixP->fx_done = 1;
11708 /* If this symbol is in a different section then we need to leave it for
11709 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
11710 so we have to undo it's effects here. */
11711 if (fixP->fx_pcrel)
11713 if (fixP->fx_addsy != NULL
11714 && S_IS_DEFINED (fixP->fx_addsy)
11715 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
11716 value += md_pcrel_from (fixP);
11719 /* Remember value for emit_reloc. */
11720 fixP->fx_addnumber = value;
11722 switch (fixP->fx_r_type)
11724 case BFD_RELOC_NONE:
11725 /* This will need to go in the object file. */
11726 fixP->fx_done = 0;
11727 break;
11729 case BFD_RELOC_ARM_IMMEDIATE:
11730 /* We claim that this fixup has been processed here,
11731 even if in fact we generate an error because we do
11732 not have a reloc for it, so tc_gen_reloc will reject it. */
11733 fixP->fx_done = 1;
11735 if (fixP->fx_addsy
11736 && ! S_IS_DEFINED (fixP->fx_addsy))
11738 as_bad_where (fixP->fx_file, fixP->fx_line,
11739 _("undefined symbol %s used as an immediate value"),
11740 S_GET_NAME (fixP->fx_addsy));
11741 break;
11744 newimm = validate_immediate (value);
11745 temp = md_chars_to_number (buf, INSN_SIZE);
11747 /* If the instruction will fail, see if we can fix things up by
11748 changing the opcode. */
11749 if (newimm == (unsigned int) FAIL
11750 && (newimm = negate_data_op (&temp, value)) == (unsigned int) FAIL)
11752 as_bad_where (fixP->fx_file, fixP->fx_line,
11753 _("invalid constant (%lx) after fixup"),
11754 (unsigned long) value);
11755 break;
11758 newimm |= (temp & 0xfffff000);
11759 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
11760 break;
11762 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
11764 unsigned int highpart = 0;
11765 unsigned int newinsn = 0xe1a00000; /* nop. */
11767 newimm = validate_immediate (value);
11768 temp = md_chars_to_number (buf, INSN_SIZE);
11770 /* If the instruction will fail, see if we can fix things up by
11771 changing the opcode. */
11772 if (newimm == (unsigned int) FAIL
11773 && (newimm = negate_data_op (& temp, value)) == (unsigned int) FAIL)
11775 /* No ? OK - try using two ADD instructions to generate
11776 the value. */
11777 newimm = validate_immediate_twopart (value, & highpart);
11779 /* Yes - then make sure that the second instruction is
11780 also an add. */
11781 if (newimm != (unsigned int) FAIL)
11782 newinsn = temp;
11783 /* Still No ? Try using a negated value. */
11784 else if ((newimm = validate_immediate_twopart (- value, & highpart)) != (unsigned int) FAIL)
11785 temp = newinsn = (temp & OPCODE_MASK) | OPCODE_SUB << DATA_OP_SHIFT;
11786 /* Otherwise - give up. */
11787 else
11789 as_bad_where (fixP->fx_file, fixP->fx_line,
11790 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
11791 (long) value);
11792 break;
11795 /* Replace the first operand in the 2nd instruction (which
11796 is the PC) with the destination register. We have
11797 already added in the PC in the first instruction and we
11798 do not want to do it again. */
11799 newinsn &= ~ 0xf0000;
11800 newinsn |= ((newinsn & 0x0f000) << 4);
11803 newimm |= (temp & 0xfffff000);
11804 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
11806 highpart |= (newinsn & 0xfffff000);
11807 md_number_to_chars (buf + INSN_SIZE, (valueT) highpart, INSN_SIZE);
11809 break;
11811 case BFD_RELOC_ARM_OFFSET_IMM:
11812 sign = value >= 0;
11814 if (value < 0)
11815 value = - value;
11817 if (validate_offset_imm (value, 0) == FAIL)
11819 as_bad_where (fixP->fx_file, fixP->fx_line,
11820 _("bad immediate value for offset (%ld)"),
11821 (long) value);
11822 break;
11825 newval = md_chars_to_number (buf, INSN_SIZE);
11826 newval &= 0xff7ff000;
11827 newval |= value | (sign ? INDEX_UP : 0);
11828 md_number_to_chars (buf, newval, INSN_SIZE);
11829 break;
11831 case BFD_RELOC_ARM_OFFSET_IMM8:
11832 case BFD_RELOC_ARM_HWLITERAL:
11833 sign = value >= 0;
11835 if (value < 0)
11836 value = - value;
11838 if (validate_offset_imm (value, 1) == FAIL)
11840 if (fixP->fx_r_type == BFD_RELOC_ARM_HWLITERAL)
11841 as_bad_where (fixP->fx_file, fixP->fx_line,
11842 _("invalid literal constant: pool needs to be closer"));
11843 else
11844 as_bad (_("bad immediate value for half-word offset (%ld)"),
11845 (long) value);
11846 break;
11849 newval = md_chars_to_number (buf, INSN_SIZE);
11850 newval &= 0xff7ff0f0;
11851 newval |= ((value >> 4) << 8) | (value & 0xf) | (sign ? INDEX_UP : 0);
11852 md_number_to_chars (buf, newval, INSN_SIZE);
11853 break;
11855 case BFD_RELOC_ARM_LITERAL:
11856 sign = value >= 0;
11858 if (value < 0)
11859 value = - value;
11861 if (validate_offset_imm (value, 0) == FAIL)
11863 as_bad_where (fixP->fx_file, fixP->fx_line,
11864 _("invalid literal constant: pool needs to be closer"));
11865 break;
11868 newval = md_chars_to_number (buf, INSN_SIZE);
11869 newval &= 0xff7ff000;
11870 newval |= value | (sign ? INDEX_UP : 0);
11871 md_number_to_chars (buf, newval, INSN_SIZE);
11872 break;
11874 case BFD_RELOC_ARM_SHIFT_IMM:
11875 newval = md_chars_to_number (buf, INSN_SIZE);
11876 if (((unsigned long) value) > 32
11877 || (value == 32
11878 && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60)))
11880 as_bad_where (fixP->fx_file, fixP->fx_line,
11881 _("shift expression is too large"));
11882 break;
11885 if (value == 0)
11886 /* Shifts of zero must be done as lsl. */
11887 newval &= ~0x60;
11888 else if (value == 32)
11889 value = 0;
11890 newval &= 0xfffff07f;
11891 newval |= (value & 0x1f) << 7;
11892 md_number_to_chars (buf, newval, INSN_SIZE);
11893 break;
11895 case BFD_RELOC_ARM_SMI:
11896 if (((unsigned long) value) > 0xffff)
11897 as_bad_where (fixP->fx_file, fixP->fx_line,
11898 _("invalid smi expression"));
11899 newval = md_chars_to_number (buf, INSN_SIZE) & 0xfff000f0;
11900 newval |= (value & 0xf) | ((value & 0xfff0) << 4);
11901 md_number_to_chars (buf, newval, INSN_SIZE);
11902 break;
11904 case BFD_RELOC_ARM_SWI:
11905 if (arm_data->thumb_mode)
11907 if (((unsigned long) value) > 0xff)
11908 as_bad_where (fixP->fx_file, fixP->fx_line,
11909 _("invalid swi expression"));
11910 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xff00;
11911 newval |= value;
11912 md_number_to_chars (buf, newval, THUMB_SIZE);
11914 else
11916 if (((unsigned long) value) > 0x00ffffff)
11917 as_bad_where (fixP->fx_file, fixP->fx_line,
11918 _("invalid swi expression"));
11919 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
11920 newval |= value;
11921 md_number_to_chars (buf, newval, INSN_SIZE);
11923 break;
11925 case BFD_RELOC_ARM_MULTI:
11926 if (((unsigned long) value) > 0xffff)
11927 as_bad_where (fixP->fx_file, fixP->fx_line,
11928 _("invalid expression in load/store multiple"));
11929 newval = value | md_chars_to_number (buf, INSN_SIZE);
11930 md_number_to_chars (buf, newval, INSN_SIZE);
11931 break;
11933 case BFD_RELOC_ARM_PCREL_BRANCH:
11934 newval = md_chars_to_number (buf, INSN_SIZE);
11936 /* Sign-extend a 24-bit number. */
11937 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
11939 #ifdef OBJ_ELF
11940 value = fixP->fx_offset;
11941 #endif
11943 /* We are going to store value (shifted right by two) in the
11944 instruction, in a 24 bit, signed field. Thus we need to check
11945 that none of the top 8 bits of the shifted value (top 7 bits of
11946 the unshifted, unsigned value) are set, or that they are all set. */
11947 if ((value & ~ ((offsetT) 0x1ffffff)) != 0
11948 && ((value & ~ ((offsetT) 0x1ffffff)) != ~ ((offsetT) 0x1ffffff)))
11950 #ifdef OBJ_ELF
11951 /* Normally we would be stuck at this point, since we cannot store
11952 the absolute address that is the destination of the branch in the
11953 24 bits of the branch instruction. If however, we happen to know
11954 that the destination of the branch is in the same section as the
11955 branch instruction itself, then we can compute the relocation for
11956 ourselves and not have to bother the linker with it.
11958 FIXME: The test for OBJ_ELF is only here because I have not
11959 worked out how to do this for OBJ_COFF. */
11960 if (fixP->fx_addsy != NULL
11961 && S_IS_DEFINED (fixP->fx_addsy)
11962 && S_GET_SEGMENT (fixP->fx_addsy) == seg)
11964 /* Get pc relative value to go into the branch. */
11965 value = * valP;
11967 /* Permit a backward branch provided that enough bits
11968 are set. Allow a forwards branch, provided that
11969 enough bits are clear. */
11970 if ( (value & ~ ((offsetT) 0x1ffffff)) == ~ ((offsetT) 0x1ffffff)
11971 || (value & ~ ((offsetT) 0x1ffffff)) == 0)
11972 fixP->fx_done = 1;
11975 if (! fixP->fx_done)
11976 #endif
11977 as_bad_where (fixP->fx_file, fixP->fx_line,
11978 _("GAS can't handle same-section branch dest >= 0x04000000"));
11981 value >>= 2;
11982 value += SEXT24 (newval);
11984 if ( (value & ~ ((offsetT) 0xffffff)) != 0
11985 && ((value & ~ ((offsetT) 0xffffff)) != ~ ((offsetT) 0xffffff)))
11986 as_bad_where (fixP->fx_file, fixP->fx_line,
11987 _("out of range branch"));
11989 if (seg->use_rela_p && !fixP->fx_done)
11991 /* Must unshift the value before storing it in the addend. */
11992 value <<= 2;
11993 #ifdef OBJ_ELF
11994 fixP->fx_offset = value;
11995 #endif
11996 fixP->fx_addnumber = value;
11997 newval = newval & 0xff000000;
11999 else
12000 newval = (value & 0x00ffffff) | (newval & 0xff000000);
12001 md_number_to_chars (buf, newval, INSN_SIZE);
12002 break;
12004 case BFD_RELOC_ARM_PCREL_BLX:
12006 offsetT hbit;
12007 newval = md_chars_to_number (buf, INSN_SIZE);
12009 #ifdef OBJ_ELF
12010 value = fixP->fx_offset;
12011 #endif
12012 hbit = (value >> 1) & 1;
12013 value = (value >> 2) & 0x00ffffff;
12014 value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
12016 if (seg->use_rela_p && !fixP->fx_done)
12018 /* Must sign-extend and unshift the value before storing
12019 it in the addend. */
12020 value = SEXT24 (value);
12021 value = (value << 2) | hbit;
12022 #ifdef OBJ_ELF
12023 fixP->fx_offset = value;
12024 #endif
12025 fixP->fx_addnumber = value;
12026 newval = newval & 0xfe000000;
12028 else
12029 newval = value | (newval & 0xfe000000) | (hbit << 24);
12030 md_number_to_chars (buf, newval, INSN_SIZE);
12032 break;
12034 case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch. */
12035 newval = md_chars_to_number (buf, THUMB_SIZE);
12037 addressT diff = (newval & 0xff) << 1;
12038 if (diff & 0x100)
12039 diff |= ~0xff;
12041 value += diff;
12042 if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
12043 as_bad_where (fixP->fx_file, fixP->fx_line,
12044 _("branch out of range"));
12045 if (seg->use_rela_p && !fixP->fx_done)
12047 #ifdef OBJ_ELF
12048 fixP->fx_offset = value;
12049 #endif
12050 fixP->fx_addnumber = value;
12051 newval = newval & 0xff00;
12053 else
12054 newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
12056 md_number_to_chars (buf, newval, THUMB_SIZE);
12057 break;
12059 case BFD_RELOC_THUMB_PCREL_BRANCH12: /* Unconditional branch. */
12060 newval = md_chars_to_number (buf, THUMB_SIZE);
12062 addressT diff = (newval & 0x7ff) << 1;
12063 if (diff & 0x800)
12064 diff |= ~0x7ff;
12066 value += diff;
12067 if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
12068 as_bad_where (fixP->fx_file, fixP->fx_line,
12069 _("branch out of range"));
12070 if (seg->use_rela_p && !fixP->fx_done)
12072 #ifdef OBJ_ELF
12073 fixP->fx_offset = value;
12074 #endif
12075 fixP->fx_addnumber = value;
12076 newval = newval & 0xf800;
12078 else
12079 newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
12081 md_number_to_chars (buf, newval, THUMB_SIZE);
12082 break;
12084 case BFD_RELOC_THUMB_PCREL_BLX:
12085 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12087 offsetT newval2;
12088 addressT diff;
12090 newval = md_chars_to_number (buf, THUMB_SIZE);
12091 newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
12092 diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
12093 if (diff & 0x400000)
12094 diff |= ~0x3fffff;
12095 #ifdef OBJ_ELF
12096 value = fixP->fx_offset;
12097 #endif
12098 value += diff;
12100 if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
12101 as_bad_where (fixP->fx_file, fixP->fx_line,
12102 _("branch with link out of range"));
12104 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
12105 /* For a BLX instruction, make sure that the relocation is rounded up
12106 to a word boundary. This follows the semantics of the instruction
12107 which specifies that bit 1 of the target address will come from bit
12108 1 of the base address. */
12109 value = (value + 1) & ~ 1;
12111 if (seg->use_rela_p && !fixP->fx_done)
12113 #ifdef OBJ_ELF
12114 fixP->fx_offset = value;
12115 #endif
12116 fixP->fx_addnumber = value;
12117 newval = newval & 0xf800;
12118 newval2 = newval2 & 0xf800;
12120 else
12122 newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12);
12123 newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
12125 md_number_to_chars (buf, newval, THUMB_SIZE);
12126 md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
12128 break;
12130 case BFD_RELOC_8:
12131 if (seg->use_rela_p && !fixP->fx_done)
12132 break;
12133 if (fixP->fx_done || fixP->fx_pcrel)
12134 md_number_to_chars (buf, value, 1);
12135 #ifdef OBJ_ELF
12136 else
12138 value = fixP->fx_offset;
12139 md_number_to_chars (buf, value, 1);
12141 #endif
12142 break;
12144 case BFD_RELOC_16:
12145 if (seg->use_rela_p && !fixP->fx_done)
12146 break;
12147 if (fixP->fx_done || fixP->fx_pcrel)
12148 md_number_to_chars (buf, value, 2);
12149 #ifdef OBJ_ELF
12150 else
12152 value = fixP->fx_offset;
12153 md_number_to_chars (buf, value, 2);
12155 #endif
12156 break;
12158 #ifdef OBJ_ELF
12159 case BFD_RELOC_ARM_TLS_GD32:
12160 case BFD_RELOC_ARM_TLS_LE32:
12161 case BFD_RELOC_ARM_TLS_IE32:
12162 case BFD_RELOC_ARM_TLS_LDM32:
12163 case BFD_RELOC_ARM_TLS_LDO32:
12164 S_SET_THREAD_LOCAL (fixP->fx_addsy);
12165 /* fall through */
12167 case BFD_RELOC_ARM_GOT32:
12168 case BFD_RELOC_ARM_GOTOFF:
12169 case BFD_RELOC_ARM_TARGET2:
12170 if (seg->use_rela_p && !fixP->fx_done)
12171 break;
12172 md_number_to_chars (buf, 0, 4);
12173 break;
12174 #endif
12176 case BFD_RELOC_RVA:
12177 case BFD_RELOC_32:
12178 case BFD_RELOC_ARM_TARGET1:
12179 case BFD_RELOC_ARM_ROSEGREL32:
12180 case BFD_RELOC_ARM_SBREL32:
12181 case BFD_RELOC_32_PCREL:
12182 if (seg->use_rela_p && !fixP->fx_done)
12183 break;
12184 if (fixP->fx_done || fixP->fx_pcrel)
12185 md_number_to_chars (buf, value, 4);
12186 #ifdef OBJ_ELF
12187 else
12189 value = fixP->fx_offset;
12190 md_number_to_chars (buf, value, 4);
12192 #endif
12193 break;
12195 #ifdef OBJ_ELF
12196 case BFD_RELOC_ARM_PREL31:
12197 if (fixP->fx_done || fixP->fx_pcrel)
12199 newval = md_chars_to_number (buf, 4) & 0x80000000;
12200 if ((value ^ (value >> 1)) & 0x40000000)
12202 as_bad_where (fixP->fx_file, fixP->fx_line,
12203 _("rel31 relocation overflow"));
12205 newval |= value & 0x7fffffff;
12206 md_number_to_chars (buf, newval, 4);
12208 break;
12210 case BFD_RELOC_ARM_PLT32:
12211 /* It appears the instruction is fully prepared at this point. */
12212 break;
12213 #endif
12215 case BFD_RELOC_ARM_CP_OFF_IMM:
12216 sign = value >= 0;
12217 if (value < -1023 || value > 1023 || (value & 3))
12218 as_bad_where (fixP->fx_file, fixP->fx_line,
12219 _("illegal value for co-processor offset"));
12220 if (value < 0)
12221 value = -value;
12222 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
12223 newval |= (value >> 2) | (sign ? INDEX_UP : 0);
12224 md_number_to_chars (buf, newval, INSN_SIZE);
12225 break;
12227 case BFD_RELOC_ARM_CP_OFF_IMM_S2:
12228 sign = value >= 0;
12229 if (value < -255 || value > 255)
12230 as_bad_where (fixP->fx_file, fixP->fx_line,
12231 _("Illegal value for co-processor offset"));
12232 if (value < 0)
12233 value = -value;
12234 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
12235 newval |= value | (sign ? INDEX_UP : 0);
12236 md_number_to_chars (buf, newval , INSN_SIZE);
12237 break;
12239 case BFD_RELOC_ARM_THUMB_OFFSET:
12240 newval = md_chars_to_number (buf, THUMB_SIZE);
12241 /* Exactly what ranges, and where the offset is inserted depends
12242 on the type of instruction, we can establish this from the
12243 top 4 bits. */
12244 switch (newval >> 12)
12246 case 4: /* PC load. */
12247 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
12248 forced to zero for these loads, so we will need to round
12249 up the offset if the instruction address is not word
12250 aligned (since the final address produced must be, and
12251 we can only describe word-aligned immediate offsets). */
12253 if ((fixP->fx_frag->fr_address + fixP->fx_where + value) & 3)
12254 as_bad_where (fixP->fx_file, fixP->fx_line,
12255 _("invalid offset, target not word aligned (0x%08X)"),
12256 (unsigned int) (fixP->fx_frag->fr_address
12257 + fixP->fx_where + value));
12259 if ((value + 2) & ~0x3fe)
12260 as_bad_where (fixP->fx_file, fixP->fx_line,
12261 _("invalid offset, value too big (0x%08lX)"),
12262 (long) value);
12264 /* Round up, since pc will be rounded down. */
12265 newval |= (value + 2) >> 2;
12266 break;
12268 case 9: /* SP load/store. */
12269 if (value & ~0x3fc)
12270 as_bad_where (fixP->fx_file, fixP->fx_line,
12271 _("invalid offset, value too big (0x%08lX)"),
12272 (long) value);
12273 newval |= value >> 2;
12274 break;
12276 case 6: /* Word load/store. */
12277 if (value & ~0x7c)
12278 as_bad_where (fixP->fx_file, fixP->fx_line,
12279 _("invalid offset, value too big (0x%08lX)"),
12280 (long) value);
12281 newval |= value << 4; /* 6 - 2. */
12282 break;
12284 case 7: /* Byte load/store. */
12285 if (value & ~0x1f)
12286 as_bad_where (fixP->fx_file, fixP->fx_line,
12287 _("invalid offset, value too big (0x%08lX)"),
12288 (long) value);
12289 newval |= value << 6;
12290 break;
12292 case 8: /* Halfword load/store. */
12293 if (value & ~0x3e)
12294 as_bad_where (fixP->fx_file, fixP->fx_line,
12295 _("invalid offset, value too big (0x%08lX)"),
12296 (long) value);
12297 newval |= value << 5; /* 6 - 1. */
12298 break;
12300 default:
12301 as_bad_where (fixP->fx_file, fixP->fx_line,
12302 "Unable to process relocation for thumb opcode: %lx",
12303 (unsigned long) newval);
12304 break;
12306 md_number_to_chars (buf, newval, THUMB_SIZE);
12307 break;
12309 case BFD_RELOC_ARM_THUMB_ADD:
12310 /* This is a complicated relocation, since we use it for all of
12311 the following immediate relocations:
12313 3bit ADD/SUB
12314 8bit ADD/SUB
12315 9bit ADD/SUB SP word-aligned
12316 10bit ADD PC/SP word-aligned
12318 The type of instruction being processed is encoded in the
12319 instruction field:
12321 0x8000 SUB
12322 0x00F0 Rd
12323 0x000F Rs
12325 newval = md_chars_to_number (buf, THUMB_SIZE);
12327 int rd = (newval >> 4) & 0xf;
12328 int rs = newval & 0xf;
12329 int subtract = newval & 0x8000;
12331 if (rd == REG_SP)
12333 if (value & ~0x1fc)
12334 as_bad_where (fixP->fx_file, fixP->fx_line,
12335 _("invalid immediate for stack address calculation"));
12336 newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
12337 newval |= value >> 2;
12339 else if (rs == REG_PC || rs == REG_SP)
12341 if (subtract ||
12342 value & ~0x3fc)
12343 as_bad_where (fixP->fx_file, fixP->fx_line,
12344 _("invalid immediate for address calculation (value = 0x%08lX)"),
12345 (unsigned long) value);
12346 newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP);
12347 newval |= rd << 8;
12348 newval |= value >> 2;
12350 else if (rs == rd)
12352 if (value & ~0xff)
12353 as_bad_where (fixP->fx_file, fixP->fx_line,
12354 _("invalid 8bit immediate"));
12355 newval = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
12356 newval |= (rd << 8) | value;
12358 else
12360 if (value & ~0x7)
12361 as_bad_where (fixP->fx_file, fixP->fx_line,
12362 _("invalid 3bit immediate"));
12363 newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
12364 newval |= rd | (rs << 3) | (value << 6);
12367 md_number_to_chars (buf, newval, THUMB_SIZE);
12368 break;
12370 case BFD_RELOC_ARM_THUMB_IMM:
12371 newval = md_chars_to_number (buf, THUMB_SIZE);
12372 switch (newval >> 11)
12374 case 0x04: /* 8bit immediate MOV. */
12375 case 0x05: /* 8bit immediate CMP. */
12376 if (value < 0 || value > 255)
12377 as_bad_where (fixP->fx_file, fixP->fx_line,
12378 _("invalid immediate: %ld is too large"),
12379 (long) value);
12380 newval |= value;
12381 break;
12383 default:
12384 abort ();
12386 md_number_to_chars (buf, newval, THUMB_SIZE);
12387 break;
12389 case BFD_RELOC_ARM_THUMB_SHIFT:
12390 /* 5bit shift value (0..31). */
12391 if (value < 0 || value > 31)
12392 as_bad_where (fixP->fx_file, fixP->fx_line,
12393 _("illegal Thumb shift value: %ld"), (long) value);
12394 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xf03f;
12395 newval |= value << 6;
12396 md_number_to_chars (buf, newval, THUMB_SIZE);
12397 break;
12399 case BFD_RELOC_VTABLE_INHERIT:
12400 case BFD_RELOC_VTABLE_ENTRY:
12401 fixP->fx_done = 0;
12402 return;
12404 case BFD_RELOC_UNUSED:
12405 default:
12406 as_bad_where (fixP->fx_file, fixP->fx_line,
12407 _("bad relocation fixup type (%d)"), fixP->fx_r_type);
12411 /* Translate internal representation of relocation info to BFD target
12412 format. */
12414 arelent *
12415 tc_gen_reloc (asection * section ATTRIBUTE_UNUSED,
12416 fixS * fixp)
12418 arelent * reloc;
12419 bfd_reloc_code_real_type code;
12421 reloc = xmalloc (sizeof (arelent));
12423 reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
12424 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
12425 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
12427 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12428 #ifndef OBJ_ELF
12429 if (fixp->fx_pcrel == 0)
12430 reloc->addend = fixp->fx_offset;
12431 else
12432 reloc->addend = fixp->fx_offset = reloc->address;
12433 #else /* OBJ_ELF */
12434 reloc->addend = fixp->fx_offset;
12435 #endif
12437 switch (fixp->fx_r_type)
12439 case BFD_RELOC_8:
12440 if (fixp->fx_pcrel)
12442 code = BFD_RELOC_8_PCREL;
12443 break;
12446 case BFD_RELOC_16:
12447 if (fixp->fx_pcrel)
12449 code = BFD_RELOC_16_PCREL;
12450 break;
12453 case BFD_RELOC_32:
12454 if (fixp->fx_pcrel)
12456 code = BFD_RELOC_32_PCREL;
12457 break;
12460 case BFD_RELOC_NONE:
12461 case BFD_RELOC_ARM_PCREL_BRANCH:
12462 case BFD_RELOC_ARM_PCREL_BLX:
12463 case BFD_RELOC_RVA:
12464 case BFD_RELOC_THUMB_PCREL_BRANCH9:
12465 case BFD_RELOC_THUMB_PCREL_BRANCH12:
12466 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12467 case BFD_RELOC_THUMB_PCREL_BLX:
12468 case BFD_RELOC_VTABLE_ENTRY:
12469 case BFD_RELOC_VTABLE_INHERIT:
12470 code = fixp->fx_r_type;
12471 break;
12473 case BFD_RELOC_ARM_LITERAL:
12474 case BFD_RELOC_ARM_HWLITERAL:
12475 /* If this is called then the a literal has
12476 been referenced across a section boundary. */
12477 as_bad_where (fixp->fx_file, fixp->fx_line,
12478 _("literal referenced across section boundary"));
12479 return NULL;
12481 #ifdef OBJ_ELF
12482 case BFD_RELOC_ARM_GOT32:
12483 case BFD_RELOC_ARM_GOTOFF:
12484 case BFD_RELOC_ARM_PLT32:
12485 case BFD_RELOC_ARM_TARGET1:
12486 case BFD_RELOC_ARM_ROSEGREL32:
12487 case BFD_RELOC_ARM_SBREL32:
12488 case BFD_RELOC_ARM_PREL31:
12489 case BFD_RELOC_ARM_TARGET2:
12490 case BFD_RELOC_ARM_TLS_LE32:
12491 case BFD_RELOC_ARM_TLS_LDO32:
12492 code = fixp->fx_r_type;
12493 break;
12495 case BFD_RELOC_ARM_TLS_GD32:
12496 case BFD_RELOC_ARM_TLS_IE32:
12497 case BFD_RELOC_ARM_TLS_LDM32:
12498 /* BFD will include the symbol's address in the addend.
12499 But we don't want that, so subtract it out again here. */
12500 if (!S_IS_COMMON (fixp->fx_addsy))
12501 reloc->addend -= (*reloc->sym_ptr_ptr)->value;
12502 code = fixp->fx_r_type;
12503 break;
12504 #endif
12506 case BFD_RELOC_ARM_IMMEDIATE:
12507 as_bad_where (fixp->fx_file, fixp->fx_line,
12508 _("internal relocation (type: IMMEDIATE) not fixed up"));
12509 return NULL;
12511 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
12512 as_bad_where (fixp->fx_file, fixp->fx_line,
12513 _("ADRL used for a symbol not defined in the same file"));
12514 return NULL;
12516 case BFD_RELOC_ARM_OFFSET_IMM:
12517 if (fixp->fx_addsy != NULL
12518 && !S_IS_DEFINED (fixp->fx_addsy)
12519 && S_IS_LOCAL (fixp->fx_addsy))
12521 as_bad_where (fixp->fx_file, fixp->fx_line,
12522 _("undefined local label `%s'"),
12523 S_GET_NAME (fixp->fx_addsy));
12524 return NULL;
12527 as_bad_where (fixp->fx_file, fixp->fx_line,
12528 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
12529 return NULL;
12531 default:
12533 char * type;
12535 switch (fixp->fx_r_type)
12537 case BFD_RELOC_NONE: type = "NONE"; break;
12538 case BFD_RELOC_ARM_OFFSET_IMM8: type = "OFFSET_IMM8"; break;
12539 case BFD_RELOC_ARM_SHIFT_IMM: type = "SHIFT_IMM"; break;
12540 case BFD_RELOC_ARM_SMI: type = "SMI"; break;
12541 case BFD_RELOC_ARM_SWI: type = "SWI"; break;
12542 case BFD_RELOC_ARM_MULTI: type = "MULTI"; break;
12543 case BFD_RELOC_ARM_CP_OFF_IMM: type = "CP_OFF_IMM"; break;
12544 case BFD_RELOC_ARM_THUMB_ADD: type = "THUMB_ADD"; break;
12545 case BFD_RELOC_ARM_THUMB_SHIFT: type = "THUMB_SHIFT"; break;
12546 case BFD_RELOC_ARM_THUMB_IMM: type = "THUMB_IMM"; break;
12547 case BFD_RELOC_ARM_THUMB_OFFSET: type = "THUMB_OFFSET"; break;
12548 default: type = _("<unknown>"); break;
12550 as_bad_where (fixp->fx_file, fixp->fx_line,
12551 _("cannot represent %s relocation in this object file format"),
12552 type);
12553 return NULL;
12557 #ifdef OBJ_ELF
12558 if ((code == BFD_RELOC_32_PCREL || code == BFD_RELOC_32)
12559 && GOT_symbol
12560 && fixp->fx_addsy == GOT_symbol)
12562 code = BFD_RELOC_ARM_GOTPC;
12563 reloc->addend = fixp->fx_offset = reloc->address;
12565 #endif
12567 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
12569 if (reloc->howto == NULL)
12571 as_bad_where (fixp->fx_file, fixp->fx_line,
12572 _("cannot represent %s relocation in this object file format"),
12573 bfd_get_reloc_code_name (code));
12574 return NULL;
12577 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12578 vtable entry to be used in the relocation's section offset. */
12579 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
12580 reloc->address = fixp->fx_offset;
12582 return reloc;
12586 md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED,
12587 segT segtype ATTRIBUTE_UNUSED)
12589 as_fatal (_("md_estimate_size_before_relax\n"));
12590 return 1;
12593 /* We need to be able to fix up arbitrary expressions in some statements.
12594 This is so that we can handle symbols that are an arbitrary distance from
12595 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
12596 which returns part of an address in a form which will be valid for
12597 a data instruction. We do this by pushing the expression into a symbol
12598 in the expr_section, and creating a fix for that. */
12600 static void
12601 fix_new_arm (fragS * frag,
12602 int where,
12603 short int size,
12604 expressionS * exp,
12605 int pc_rel,
12606 int reloc)
12608 fixS * new_fix;
12609 arm_fix_data * arm_data;
12611 switch (exp->X_op)
12613 case O_constant:
12614 case O_symbol:
12615 case O_add:
12616 case O_subtract:
12617 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
12618 break;
12620 default:
12621 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0,
12622 pc_rel, reloc);
12623 break;
12626 /* Mark whether the fix is to a THUMB instruction, or an ARM
12627 instruction. */
12628 arm_data = obstack_alloc (& notes, sizeof (arm_fix_data));
12629 new_fix->tc_fix_data = (PTR) arm_data;
12630 arm_data->thumb_mode = thumb_mode;
12633 static void
12634 output_inst (const char * str)
12636 char * to = NULL;
12638 if (inst.error)
12640 as_bad ("%s -- `%s'", inst.error, str);
12641 return;
12644 to = frag_more (inst.size);
12646 if (thumb_mode && (inst.size > THUMB_SIZE))
12648 assert (inst.size == (2 * THUMB_SIZE));
12649 md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE);
12650 md_number_to_chars (to + THUMB_SIZE, inst.instruction, THUMB_SIZE);
12652 else if (inst.size > INSN_SIZE)
12654 assert (inst.size == (2 * INSN_SIZE));
12655 md_number_to_chars (to, inst.instruction, INSN_SIZE);
12656 md_number_to_chars (to + INSN_SIZE, inst.instruction, INSN_SIZE);
12658 else
12659 md_number_to_chars (to, inst.instruction, inst.size);
12661 if (inst.reloc.type != BFD_RELOC_UNUSED)
12662 fix_new_arm (frag_now, to - frag_now->fr_literal,
12663 inst.size, & inst.reloc.exp, inst.reloc.pc_rel,
12664 inst.reloc.type);
12666 #ifdef OBJ_ELF
12667 dwarf2_emit_insn (inst.size);
12668 #endif
12671 void
12672 md_assemble (char * str)
12674 char c;
12675 char *p;
12676 char *start;
12678 /* Align the previous label if needed. */
12679 if (last_label_seen != NULL)
12681 symbol_set_frag (last_label_seen, frag_now);
12682 S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ());
12683 S_SET_SEGMENT (last_label_seen, now_seg);
12686 memset (&inst, '\0', sizeof (inst));
12687 inst.reloc.type = BFD_RELOC_UNUSED;
12689 skip_whitespace (str);
12691 /* Scan up to the end of the op-code, which must end in white space or
12692 end of string. */
12693 for (start = p = str; *p != '\0'; p++)
12694 if (*p == ' ')
12695 break;
12697 if (p == str)
12699 as_bad (_("no operator -- statement `%s'\n"), str);
12700 return;
12703 if (thumb_mode)
12705 const struct thumb_opcode * opcode;
12707 c = *p;
12708 *p = '\0';
12709 opcode = (const struct thumb_opcode *) hash_find (arm_tops_hsh, str);
12710 *p = c;
12712 if (opcode)
12714 /* Check that this instruction is supported for this CPU. */
12715 if (thumb_mode == 1 && (opcode->variant & cpu_variant) == 0)
12717 as_bad (_("selected processor does not support `%s'"), str);
12718 return;
12721 mapping_state (MAP_THUMB);
12722 inst.instruction = opcode->value;
12723 inst.size = opcode->size;
12724 opcode->parms (p);
12725 output_inst (str);
12726 return;
12729 else
12731 const struct asm_opcode * opcode;
12733 c = *p;
12734 *p = '\0';
12735 opcode = (const struct asm_opcode *) hash_find (arm_ops_hsh, str);
12736 *p = c;
12738 if (opcode)
12740 /* Check that this instruction is supported for this CPU. */
12741 if ((opcode->variant & cpu_variant) == 0)
12743 as_bad (_("selected processor does not support `%s'"), str);
12744 return;
12747 mapping_state (MAP_ARM);
12748 inst.instruction = opcode->value;
12749 inst.size = INSN_SIZE;
12750 opcode->parms (p);
12751 output_inst (str);
12752 return;
12756 /* It wasn't an instruction, but it might be a register alias of the form
12757 alias .req reg. */
12758 if (create_register_alias (str, p))
12759 return;
12761 as_bad (_("bad instruction `%s'"), start);
12764 /* md_parse_option
12765 Invocation line includes a switch not recognized by the base assembler.
12766 See if it's a processor-specific option.
12768 This routine is somewhat complicated by the need for backwards
12769 compatibility (since older releases of gcc can't be changed).
12770 The new options try to make the interface as compatible as
12771 possible with GCC.
12773 New options (supported) are:
12775 -mcpu=<cpu name> Assemble for selected processor
12776 -march=<architecture name> Assemble for selected architecture
12777 -mfpu=<fpu architecture> Assemble for selected FPU.
12778 -EB/-mbig-endian Big-endian
12779 -EL/-mlittle-endian Little-endian
12780 -k Generate PIC code
12781 -mthumb Start in Thumb mode
12782 -mthumb-interwork Code supports ARM/Thumb interworking
12784 For now we will also provide support for:
12786 -mapcs-32 32-bit Program counter
12787 -mapcs-26 26-bit Program counter
12788 -macps-float Floats passed in FP registers
12789 -mapcs-reentrant Reentrant code
12790 -matpcs
12791 (sometime these will probably be replaced with -mapcs=<list of options>
12792 and -matpcs=<list of options>)
12794 The remaining options are only supported for back-wards compatibility.
12795 Cpu variants, the arm part is optional:
12796 -m[arm]1 Currently not supported.
12797 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
12798 -m[arm]3 Arm 3 processor
12799 -m[arm]6[xx], Arm 6 processors
12800 -m[arm]7[xx][t][[d]m] Arm 7 processors
12801 -m[arm]8[10] Arm 8 processors
12802 -m[arm]9[20][tdmi] Arm 9 processors
12803 -mstrongarm[110[0]] StrongARM processors
12804 -mxscale XScale processors
12805 -m[arm]v[2345[t[e]]] Arm architectures
12806 -mall All (except the ARM1)
12807 FP variants:
12808 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
12809 -mfpe-old (No float load/store multiples)
12810 -mvfpxd VFP Single precision
12811 -mvfp All VFP
12812 -mno-fpu Disable all floating point instructions
12814 The following CPU names are recognized:
12815 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
12816 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
12817 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
12818 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
12819 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
12820 arm10t arm10e, arm1020t, arm1020e, arm10200e,
12821 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
12825 const char * md_shortopts = "m:k";
12827 #ifdef ARM_BI_ENDIAN
12828 #define OPTION_EB (OPTION_MD_BASE + 0)
12829 #define OPTION_EL (OPTION_MD_BASE + 1)
12830 #else
12831 #if TARGET_BYTES_BIG_ENDIAN
12832 #define OPTION_EB (OPTION_MD_BASE + 0)
12833 #else
12834 #define OPTION_EL (OPTION_MD_BASE + 1)
12835 #endif
12836 #endif
12838 struct option md_longopts[] =
12840 #ifdef OPTION_EB
12841 {"EB", no_argument, NULL, OPTION_EB},
12842 #endif
12843 #ifdef OPTION_EL
12844 {"EL", no_argument, NULL, OPTION_EL},
12845 #endif
12846 {NULL, no_argument, NULL, 0}
12849 size_t md_longopts_size = sizeof (md_longopts);
12851 struct arm_option_table
12853 char *option; /* Option name to match. */
12854 char *help; /* Help information. */
12855 int *var; /* Variable to change. */
12856 int value; /* What to change it to. */
12857 char *deprecated; /* If non-null, print this message. */
12860 struct arm_option_table arm_opts[] =
12862 {"k", N_("generate PIC code"), &pic_code, 1, NULL},
12863 {"mthumb", N_("assemble Thumb code"), &thumb_mode, 1, NULL},
12864 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
12865 &support_interwork, 1, NULL},
12866 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26, 0, NULL},
12867 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26, 1, NULL},
12868 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float,
12869 1, NULL},
12870 {"mapcs-reentrant", N_("re-entrant code"), &pic_code, 1, NULL},
12871 {"matpcs", N_("code is ATPCS conformant"), &atpcs, 1, NULL},
12872 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian, 1, NULL},
12873 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian, 0,
12874 NULL},
12876 /* These are recognized by the assembler, but have no affect on code. */
12877 {"mapcs-frame", N_("use frame pointer"), NULL, 0, NULL},
12878 {"mapcs-stack-check", N_("use stack size checking"), NULL, 0, NULL},
12880 /* DON'T add any new processors to this list -- we want the whole list
12881 to go away... Add them to the processors table instead. */
12882 {"marm1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
12883 {"m1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
12884 {"marm2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
12885 {"m2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
12886 {"marm250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
12887 {"m250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
12888 {"marm3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
12889 {"m3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
12890 {"marm6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
12891 {"m6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
12892 {"marm600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
12893 {"m600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
12894 {"marm610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
12895 {"m610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
12896 {"marm620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
12897 {"m620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
12898 {"marm7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
12899 {"m7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
12900 {"marm70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
12901 {"m70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
12902 {"marm700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
12903 {"m700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
12904 {"marm700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
12905 {"m700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
12906 {"marm710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
12907 {"m710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
12908 {"marm710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
12909 {"m710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
12910 {"marm720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
12911 {"m720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
12912 {"marm7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
12913 {"m7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
12914 {"marm7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
12915 {"m7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
12916 {"marm7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
12917 {"m7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
12918 {"marm7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
12919 {"m7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
12920 {"marm7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
12921 {"m7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
12922 {"marm7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
12923 {"m7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
12924 {"marm7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
12925 {"m7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
12926 {"marm7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
12927 {"m7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
12928 {"marm7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12929 {"m7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12930 {"marm7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12931 {"m7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12932 {"marm710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
12933 {"m710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
12934 {"marm720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
12935 {"m720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
12936 {"marm740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
12937 {"m740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
12938 {"marm8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
12939 {"m8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
12940 {"marm810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
12941 {"m810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
12942 {"marm9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
12943 {"m9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
12944 {"marm9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
12945 {"m9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
12946 {"marm920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
12947 {"m920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
12948 {"marm940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
12949 {"m940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
12950 {"mstrongarm", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=strongarm")},
12951 {"mstrongarm110", NULL, &legacy_cpu, ARM_ARCH_V4,
12952 N_("use -mcpu=strongarm110")},
12953 {"mstrongarm1100", NULL, &legacy_cpu, ARM_ARCH_V4,
12954 N_("use -mcpu=strongarm1100")},
12955 {"mstrongarm1110", NULL, &legacy_cpu, ARM_ARCH_V4,
12956 N_("use -mcpu=strongarm1110")},
12957 {"mxscale", NULL, &legacy_cpu, ARM_ARCH_XSCALE, N_("use -mcpu=xscale")},
12958 {"miwmmxt", NULL, &legacy_cpu, ARM_ARCH_IWMMXT, N_("use -mcpu=iwmmxt")},
12959 {"mall", NULL, &legacy_cpu, ARM_ANY, N_("use -mcpu=all")},
12961 /* Architecture variants -- don't add any more to this list either. */
12962 {"mv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
12963 {"marmv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
12964 {"mv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
12965 {"marmv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
12966 {"mv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
12967 {"marmv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
12968 {"mv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
12969 {"marmv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
12970 {"mv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
12971 {"marmv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
12972 {"mv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
12973 {"marmv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
12974 {"mv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
12975 {"marmv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
12976 {"mv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
12977 {"marmv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
12978 {"mv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
12979 {"marmv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
12981 /* Floating point variants -- don't add any more to this list either. */
12982 {"mfpe-old", NULL, &legacy_fpu, FPU_ARCH_FPE, N_("use -mfpu=fpe")},
12983 {"mfpa10", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa10")},
12984 {"mfpa11", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa11")},
12985 {"mno-fpu", NULL, &legacy_fpu, 0,
12986 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
12988 {NULL, NULL, NULL, 0, NULL}
12991 struct arm_cpu_option_table
12993 char *name;
12994 int value;
12995 /* For some CPUs we assume an FPU unless the user explicitly sets
12996 -mfpu=... */
12997 int default_fpu;
13000 /* This list should, at a minimum, contain all the cpu names
13001 recognized by GCC. */
13002 static struct arm_cpu_option_table arm_cpus[] =
13004 {"all", ARM_ANY, FPU_ARCH_FPA},
13005 {"arm1", ARM_ARCH_V1, FPU_ARCH_FPA},
13006 {"arm2", ARM_ARCH_V2, FPU_ARCH_FPA},
13007 {"arm250", ARM_ARCH_V2S, FPU_ARCH_FPA},
13008 {"arm3", ARM_ARCH_V2S, FPU_ARCH_FPA},
13009 {"arm6", ARM_ARCH_V3, FPU_ARCH_FPA},
13010 {"arm60", ARM_ARCH_V3, FPU_ARCH_FPA},
13011 {"arm600", ARM_ARCH_V3, FPU_ARCH_FPA},
13012 {"arm610", ARM_ARCH_V3, FPU_ARCH_FPA},
13013 {"arm620", ARM_ARCH_V3, FPU_ARCH_FPA},
13014 {"arm7", ARM_ARCH_V3, FPU_ARCH_FPA},
13015 {"arm7m", ARM_ARCH_V3M, FPU_ARCH_FPA},
13016 {"arm7d", ARM_ARCH_V3, FPU_ARCH_FPA},
13017 {"arm7dm", ARM_ARCH_V3M, FPU_ARCH_FPA},
13018 {"arm7di", ARM_ARCH_V3, FPU_ARCH_FPA},
13019 {"arm7dmi", ARM_ARCH_V3M, FPU_ARCH_FPA},
13020 {"arm70", ARM_ARCH_V3, FPU_ARCH_FPA},
13021 {"arm700", ARM_ARCH_V3, FPU_ARCH_FPA},
13022 {"arm700i", ARM_ARCH_V3, FPU_ARCH_FPA},
13023 {"arm710", ARM_ARCH_V3, FPU_ARCH_FPA},
13024 {"arm710t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13025 {"arm720", ARM_ARCH_V3, FPU_ARCH_FPA},
13026 {"arm720t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13027 {"arm740t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13028 {"arm710c", ARM_ARCH_V3, FPU_ARCH_FPA},
13029 {"arm7100", ARM_ARCH_V3, FPU_ARCH_FPA},
13030 {"arm7500", ARM_ARCH_V3, FPU_ARCH_FPA},
13031 {"arm7500fe", ARM_ARCH_V3, FPU_ARCH_FPA},
13032 {"arm7t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13033 {"arm7tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
13034 {"arm7tdmi-s", ARM_ARCH_V4T, FPU_ARCH_FPA},
13035 {"arm8", ARM_ARCH_V4, FPU_ARCH_FPA},
13036 {"arm810", ARM_ARCH_V4, FPU_ARCH_FPA},
13037 {"strongarm", ARM_ARCH_V4, FPU_ARCH_FPA},
13038 {"strongarm1", ARM_ARCH_V4, FPU_ARCH_FPA},
13039 {"strongarm110", ARM_ARCH_V4, FPU_ARCH_FPA},
13040 {"strongarm1100", ARM_ARCH_V4, FPU_ARCH_FPA},
13041 {"strongarm1110", ARM_ARCH_V4, FPU_ARCH_FPA},
13042 {"arm9", ARM_ARCH_V4T, FPU_ARCH_FPA},
13043 {"arm920", ARM_ARCH_V4T, FPU_ARCH_FPA},
13044 {"arm920t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13045 {"arm922t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13046 {"arm940t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13047 {"arm9tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
13048 /* For V5 or later processors we default to using VFP; but the user
13049 should really set the FPU type explicitly. */
13050 {"arm9e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13051 {"arm9e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13052 {"arm926ej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
13053 {"arm926ejs", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
13054 {"arm926ej-s", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
13055 {"arm946e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13056 {"arm946e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13057 {"arm966e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13058 {"arm966e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13059 {"arm10t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
13060 {"arm10e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13061 {"arm1020", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13062 {"arm1020t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
13063 {"arm1020e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13064 {"arm1026ejs", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
13065 {"arm1026ej-s", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
13066 {"arm1136js", ARM_ARCH_V6, FPU_NONE},
13067 {"arm1136j-s", ARM_ARCH_V6, FPU_NONE},
13068 {"arm1136jfs", ARM_ARCH_V6, FPU_ARCH_VFP_V2},
13069 {"arm1136jf-s", ARM_ARCH_V6, FPU_ARCH_VFP_V2},
13070 {"mpcore", ARM_ARCH_V6K, FPU_ARCH_VFP_V2},
13071 {"mpcorenovfp", ARM_ARCH_V6K, FPU_NONE},
13072 {"arm1176jz-s", ARM_ARCH_V6ZK, FPU_NONE},
13073 {"arm1176jzf-s", ARM_ARCH_V6ZK, FPU_ARCH_VFP_V2},
13074 /* ??? XSCALE is really an architecture. */
13075 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
13076 /* ??? iwmmxt is not a processor. */
13077 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP_V2},
13078 {"i80200", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
13079 /* Maverick */
13080 {"ep9312", ARM_ARCH_V4T | ARM_CEXT_MAVERICK, FPU_ARCH_MAVERICK},
13081 {NULL, 0, 0}
13084 struct arm_arch_option_table
13086 char *name;
13087 int value;
13088 int default_fpu;
13091 /* This list should, at a minimum, contain all the architecture names
13092 recognized by GCC. */
13093 static struct arm_arch_option_table arm_archs[] =
13095 {"all", ARM_ANY, FPU_ARCH_FPA},
13096 {"armv1", ARM_ARCH_V1, FPU_ARCH_FPA},
13097 {"armv2", ARM_ARCH_V2, FPU_ARCH_FPA},
13098 {"armv2a", ARM_ARCH_V2S, FPU_ARCH_FPA},
13099 {"armv2s", ARM_ARCH_V2S, FPU_ARCH_FPA},
13100 {"armv3", ARM_ARCH_V3, FPU_ARCH_FPA},
13101 {"armv3m", ARM_ARCH_V3M, FPU_ARCH_FPA},
13102 {"armv4", ARM_ARCH_V4, FPU_ARCH_FPA},
13103 {"armv4xm", ARM_ARCH_V4xM, FPU_ARCH_FPA},
13104 {"armv4t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13105 {"armv4txm", ARM_ARCH_V4TxM, FPU_ARCH_FPA},
13106 {"armv5", ARM_ARCH_V5, FPU_ARCH_VFP},
13107 {"armv5t", ARM_ARCH_V5T, FPU_ARCH_VFP},
13108 {"armv5txm", ARM_ARCH_V5TxM, FPU_ARCH_VFP},
13109 {"armv5te", ARM_ARCH_V5TE, FPU_ARCH_VFP},
13110 {"armv5texp", ARM_ARCH_V5TExP, FPU_ARCH_VFP},
13111 {"armv5tej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP},
13112 {"armv6", ARM_ARCH_V6, FPU_ARCH_VFP},
13113 {"armv6j", ARM_ARCH_V6, FPU_ARCH_VFP},
13114 {"armv6k", ARM_ARCH_V6K, FPU_ARCH_VFP},
13115 {"armv6z", ARM_ARCH_V6Z, FPU_ARCH_VFP},
13116 {"armv6zk", ARM_ARCH_V6ZK, FPU_ARCH_VFP},
13117 {"armv6t2", ARM_ARCH_V6T2, FPU_ARCH_VFP},
13118 {"armv6kt2", ARM_ARCH_V6KT2, FPU_ARCH_VFP},
13119 {"armv6zt2", ARM_ARCH_V6ZT2, FPU_ARCH_VFP},
13120 {"armv6zkt2", ARM_ARCH_V6ZKT2, FPU_ARCH_VFP},
13121 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP},
13122 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP},
13123 {NULL, 0, 0}
13126 /* ISA extensions in the co-processor space. */
13127 struct arm_arch_extension_table
13129 char *name;
13130 int value;
13133 static struct arm_arch_extension_table arm_extensions[] =
13135 {"maverick", ARM_CEXT_MAVERICK},
13136 {"xscale", ARM_CEXT_XSCALE},
13137 {"iwmmxt", ARM_CEXT_IWMMXT},
13138 {NULL, 0}
13141 struct arm_fpu_option_table
13143 char *name;
13144 int value;
13147 /* This list should, at a minimum, contain all the fpu names
13148 recognized by GCC. */
13149 static struct arm_fpu_option_table arm_fpus[] =
13151 {"softfpa", FPU_NONE},
13152 {"fpe", FPU_ARCH_FPE},
13153 {"fpe2", FPU_ARCH_FPE},
13154 {"fpe3", FPU_ARCH_FPA}, /* Third release supports LFM/SFM. */
13155 {"fpa", FPU_ARCH_FPA},
13156 {"fpa10", FPU_ARCH_FPA},
13157 {"fpa11", FPU_ARCH_FPA},
13158 {"arm7500fe", FPU_ARCH_FPA},
13159 {"softvfp", FPU_ARCH_VFP},
13160 {"softvfp+vfp", FPU_ARCH_VFP_V2},
13161 {"vfp", FPU_ARCH_VFP_V2},
13162 {"vfp9", FPU_ARCH_VFP_V2},
13163 {"vfp10", FPU_ARCH_VFP_V2},
13164 {"vfp10-r0", FPU_ARCH_VFP_V1},
13165 {"vfpxd", FPU_ARCH_VFP_V1xD},
13166 {"arm1020t", FPU_ARCH_VFP_V1},
13167 {"arm1020e", FPU_ARCH_VFP_V2},
13168 {"arm1136jfs", FPU_ARCH_VFP_V2},
13169 {"arm1136jf-s", FPU_ARCH_VFP_V2},
13170 {"maverick", FPU_ARCH_MAVERICK},
13171 {NULL, 0}
13174 struct arm_float_abi_option_table
13176 char *name;
13177 int value;
13180 static struct arm_float_abi_option_table arm_float_abis[] =
13182 {"hard", ARM_FLOAT_ABI_HARD},
13183 {"softfp", ARM_FLOAT_ABI_SOFTFP},
13184 {"soft", ARM_FLOAT_ABI_SOFT},
13185 {NULL, 0}
13188 struct arm_eabi_option_table
13190 char *name;
13191 unsigned int value;
13194 #ifdef OBJ_ELF
13195 /* We only know how to output GNU and ver 4 (AAELF) formats. */
13196 static struct arm_eabi_option_table arm_eabis[] =
13198 {"gnu", EF_ARM_EABI_UNKNOWN},
13199 {"4", EF_ARM_EABI_VER4},
13200 {NULL, 0}
13202 #endif
13204 struct arm_long_option_table
13206 char * option; /* Substring to match. */
13207 char * help; /* Help information. */
13208 int (* func) (char * subopt); /* Function to decode sub-option. */
13209 char * deprecated; /* If non-null, print this message. */
13212 static int
13213 arm_parse_extension (char * str, int * opt_p)
13215 while (str != NULL && *str != 0)
13217 struct arm_arch_extension_table * opt;
13218 char * ext;
13219 int optlen;
13221 if (*str != '+')
13223 as_bad (_("invalid architectural extension"));
13224 return 0;
13227 str++;
13228 ext = strchr (str, '+');
13230 if (ext != NULL)
13231 optlen = ext - str;
13232 else
13233 optlen = strlen (str);
13235 if (optlen == 0)
13237 as_bad (_("missing architectural extension"));
13238 return 0;
13241 for (opt = arm_extensions; opt->name != NULL; opt++)
13242 if (strncmp (opt->name, str, optlen) == 0)
13244 *opt_p |= opt->value;
13245 break;
13248 if (opt->name == NULL)
13250 as_bad (_("unknown architectural extnsion `%s'"), str);
13251 return 0;
13254 str = ext;
13257 return 1;
13260 static int
13261 arm_parse_cpu (char * str)
13263 struct arm_cpu_option_table * opt;
13264 char * ext = strchr (str, '+');
13265 int optlen;
13267 if (ext != NULL)
13268 optlen = ext - str;
13269 else
13270 optlen = strlen (str);
13272 if (optlen == 0)
13274 as_bad (_("missing cpu name `%s'"), str);
13275 return 0;
13278 for (opt = arm_cpus; opt->name != NULL; opt++)
13279 if (strncmp (opt->name, str, optlen) == 0)
13281 mcpu_cpu_opt = opt->value;
13282 mcpu_fpu_opt = opt->default_fpu;
13284 if (ext != NULL)
13285 return arm_parse_extension (ext, &mcpu_cpu_opt);
13287 return 1;
13290 as_bad (_("unknown cpu `%s'"), str);
13291 return 0;
13294 static int
13295 arm_parse_arch (char * str)
13297 struct arm_arch_option_table *opt;
13298 char *ext = strchr (str, '+');
13299 int optlen;
13301 if (ext != NULL)
13302 optlen = ext - str;
13303 else
13304 optlen = strlen (str);
13306 if (optlen == 0)
13308 as_bad (_("missing architecture name `%s'"), str);
13309 return 0;
13313 for (opt = arm_archs; opt->name != NULL; opt++)
13314 if (streq (opt->name, str))
13316 march_cpu_opt = opt->value;
13317 march_fpu_opt = opt->default_fpu;
13319 if (ext != NULL)
13320 return arm_parse_extension (ext, &march_cpu_opt);
13322 return 1;
13325 as_bad (_("unknown architecture `%s'\n"), str);
13326 return 0;
13329 static int
13330 arm_parse_fpu (char * str)
13332 struct arm_fpu_option_table * opt;
13334 for (opt = arm_fpus; opt->name != NULL; opt++)
13335 if (streq (opt->name, str))
13337 mfpu_opt = opt->value;
13338 return 1;
13341 as_bad (_("unknown floating point format `%s'\n"), str);
13342 return 0;
13345 static int
13346 arm_parse_float_abi (char * str)
13348 struct arm_float_abi_option_table * opt;
13350 for (opt = arm_float_abis; opt->name != NULL; opt++)
13351 if (streq (opt->name, str))
13353 mfloat_abi_opt = opt->value;
13354 return 1;
13357 as_bad (_("unknown floating point abi `%s'\n"), str);
13358 return 0;
13361 #ifdef OBJ_ELF
13362 static int
13363 arm_parse_eabi (char * str)
13365 struct arm_eabi_option_table *opt;
13367 for (opt = arm_eabis; opt->name != NULL; opt++)
13368 if (streq (opt->name, str))
13370 meabi_flags = opt->value;
13371 return 1;
13373 as_bad (_("unknown EABI `%s'\n"), str);
13374 return 0;
13376 #endif
13378 struct arm_long_option_table arm_long_opts[] =
13380 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13381 arm_parse_cpu, NULL},
13382 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13383 arm_parse_arch, NULL},
13384 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13385 arm_parse_fpu, NULL},
13386 {"mfloat-abi=", N_("<abi>\t assemble for floating point ABI <abi>"),
13387 arm_parse_float_abi, NULL},
13388 #ifdef OBJ_ELF
13389 {"meabi=", N_("<ver>\t assemble for eabi version <ver>"),
13390 arm_parse_eabi, NULL},
13391 #endif
13392 {NULL, NULL, 0, NULL}
13396 md_parse_option (int c, char * arg)
13398 struct arm_option_table *opt;
13399 struct arm_long_option_table *lopt;
13401 switch (c)
13403 #ifdef OPTION_EB
13404 case OPTION_EB:
13405 target_big_endian = 1;
13406 break;
13407 #endif
13409 #ifdef OPTION_EL
13410 case OPTION_EL:
13411 target_big_endian = 0;
13412 break;
13413 #endif
13415 case 'a':
13416 /* Listing option. Just ignore these, we don't support additional
13417 ones. */
13418 return 0;
13420 default:
13421 for (opt = arm_opts; opt->option != NULL; opt++)
13423 if (c == opt->option[0]
13424 && ((arg == NULL && opt->option[1] == 0)
13425 || streq (arg, opt->option + 1)))
13427 #if WARN_DEPRECATED
13428 /* If the option is deprecated, tell the user. */
13429 if (opt->deprecated != NULL)
13430 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c,
13431 arg ? arg : "", _(opt->deprecated));
13432 #endif
13434 if (opt->var != NULL)
13435 *opt->var = opt->value;
13437 return 1;
13441 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13443 /* These options are expected to have an argument. */
13444 if (c == lopt->option[0]
13445 && arg != NULL
13446 && strncmp (arg, lopt->option + 1,
13447 strlen (lopt->option + 1)) == 0)
13449 #if WARN_DEPRECATED
13450 /* If the option is deprecated, tell the user. */
13451 if (lopt->deprecated != NULL)
13452 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c, arg,
13453 _(lopt->deprecated));
13454 #endif
13456 /* Call the sup-option parser. */
13457 return lopt->func (arg + strlen (lopt->option) - 1);
13461 return 0;
13464 return 1;
13467 void
13468 md_show_usage (FILE * fp)
13470 struct arm_option_table *opt;
13471 struct arm_long_option_table *lopt;
13473 fprintf (fp, _(" ARM-specific assembler options:\n"));
13475 for (opt = arm_opts; opt->option != NULL; opt++)
13476 if (opt->help != NULL)
13477 fprintf (fp, " -%-23s%s\n", opt->option, _(opt->help));
13479 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13480 if (lopt->help != NULL)
13481 fprintf (fp, " -%s%s\n", lopt->option, _(lopt->help));
13483 #ifdef OPTION_EB
13484 fprintf (fp, _("\
13485 -EB assemble code for a big-endian cpu\n"));
13486 #endif
13488 #ifdef OPTION_EL
13489 fprintf (fp, _("\
13490 -EL assemble code for a little-endian cpu\n"));
13491 #endif
13494 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13496 void
13497 cons_fix_new_arm (fragS * frag,
13498 int where,
13499 int size,
13500 expressionS * exp)
13502 bfd_reloc_code_real_type type;
13503 int pcrel = 0;
13505 /* Pick a reloc.
13506 FIXME: @@ Should look at CPU word size. */
13507 switch (size)
13509 case 1:
13510 type = BFD_RELOC_8;
13511 break;
13512 case 2:
13513 type = BFD_RELOC_16;
13514 break;
13515 case 4:
13516 default:
13517 type = BFD_RELOC_32;
13518 break;
13519 case 8:
13520 type = BFD_RELOC_64;
13521 break;
13524 fix_new_exp (frag, where, (int) size, exp, pcrel, type);
13527 /* A good place to do this, although this was probably not intended
13528 for this kind of use. We need to dump the literal pool before
13529 references are made to a null symbol pointer. */
13531 void
13532 arm_cleanup (void)
13534 literal_pool * pool;
13536 for (pool = list_of_pools; pool; pool = pool->next)
13538 /* Put it at the end of the relevent section. */
13539 subseg_set (pool->section, pool->sub_section);
13540 #ifdef OBJ_ELF
13541 arm_elf_change_section ();
13542 #endif
13543 s_ltorg (0);
13547 void
13548 arm_start_line_hook (void)
13550 last_label_seen = NULL;
13553 void
13554 arm_frob_label (symbolS * sym)
13556 last_label_seen = sym;
13558 ARM_SET_THUMB (sym, thumb_mode);
13560 #if defined OBJ_COFF || defined OBJ_ELF
13561 ARM_SET_INTERWORK (sym, support_interwork);
13562 #endif
13564 /* Note - do not allow local symbols (.Lxxx) to be labeled
13565 as Thumb functions. This is because these labels, whilst
13566 they exist inside Thumb code, are not the entry points for
13567 possible ARM->Thumb calls. Also, these labels can be used
13568 as part of a computed goto or switch statement. eg gcc
13569 can generate code that looks like this:
13571 ldr r2, [pc, .Laaa]
13572 lsl r3, r3, #2
13573 ldr r2, [r3, r2]
13574 mov pc, r2
13576 .Lbbb: .word .Lxxx
13577 .Lccc: .word .Lyyy
13578 ..etc...
13579 .Laaa: .word Lbbb
13581 The first instruction loads the address of the jump table.
13582 The second instruction converts a table index into a byte offset.
13583 The third instruction gets the jump address out of the table.
13584 The fourth instruction performs the jump.
13586 If the address stored at .Laaa is that of a symbol which has the
13587 Thumb_Func bit set, then the linker will arrange for this address
13588 to have the bottom bit set, which in turn would mean that the
13589 address computation performed by the third instruction would end
13590 up with the bottom bit set. Since the ARM is capable of unaligned
13591 word loads, the instruction would then load the incorrect address
13592 out of the jump table, and chaos would ensue. */
13593 if (label_is_thumb_function_name
13594 && (S_GET_NAME (sym)[0] != '.' || S_GET_NAME (sym)[1] != 'L')
13595 && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
13597 /* When the address of a Thumb function is taken the bottom
13598 bit of that address should be set. This will allow
13599 interworking between Arm and Thumb functions to work
13600 correctly. */
13602 THUMB_SET_FUNC (sym, 1);
13604 label_is_thumb_function_name = FALSE;
13608 /* Adjust the symbol table. This marks Thumb symbols as distinct from
13609 ARM ones. */
13611 void
13612 arm_adjust_symtab (void)
13614 #ifdef OBJ_COFF
13615 symbolS * sym;
13617 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13619 if (ARM_IS_THUMB (sym))
13621 if (THUMB_IS_FUNC (sym))
13623 /* Mark the symbol as a Thumb function. */
13624 if ( S_GET_STORAGE_CLASS (sym) == C_STAT
13625 || S_GET_STORAGE_CLASS (sym) == C_LABEL) /* This can happen! */
13626 S_SET_STORAGE_CLASS (sym, C_THUMBSTATFUNC);
13628 else if (S_GET_STORAGE_CLASS (sym) == C_EXT)
13629 S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC);
13630 else
13631 as_bad (_("%s: unexpected function type: %d"),
13632 S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym));
13634 else switch (S_GET_STORAGE_CLASS (sym))
13636 case C_EXT:
13637 S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
13638 break;
13639 case C_STAT:
13640 S_SET_STORAGE_CLASS (sym, C_THUMBSTAT);
13641 break;
13642 case C_LABEL:
13643 S_SET_STORAGE_CLASS (sym, C_THUMBLABEL);
13644 break;
13645 default:
13646 /* Do nothing. */
13647 break;
13651 if (ARM_IS_INTERWORK (sym))
13652 coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_flags = 0xFF;
13654 #endif
13655 #ifdef OBJ_ELF
13656 symbolS * sym;
13657 char bind;
13659 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13661 if (ARM_IS_THUMB (sym))
13663 elf_symbol_type * elf_sym;
13665 elf_sym = elf_symbol (symbol_get_bfdsym (sym));
13666 bind = ELF_ST_BIND (elf_sym->internal_elf_sym.st_info);
13668 if (! bfd_is_arm_mapping_symbol_name (elf_sym->symbol.name))
13670 /* If it's a .thumb_func, declare it as so,
13671 otherwise tag label as .code 16. */
13672 if (THUMB_IS_FUNC (sym))
13673 elf_sym->internal_elf_sym.st_info =
13674 ELF_ST_INFO (bind, STT_ARM_TFUNC);
13675 else
13676 elf_sym->internal_elf_sym.st_info =
13677 ELF_ST_INFO (bind, STT_ARM_16BIT);
13681 #endif
13685 arm_data_in_code (void)
13687 if (thumb_mode && ! strncmp (input_line_pointer + 1, "data:", 5))
13689 *input_line_pointer = '/';
13690 input_line_pointer += 5;
13691 *input_line_pointer = 0;
13692 return 1;
13695 return 0;
13698 char *
13699 arm_canonicalize_symbol_name (char * name)
13701 int len;
13703 if (thumb_mode && (len = strlen (name)) > 5
13704 && streq (name + len - 5, "/data"))
13705 *(name + len - 5) = 0;
13707 return name;
13710 #if defined OBJ_COFF || defined OBJ_ELF
13711 void
13712 arm_validate_fix (fixS * fixP)
13714 /* If the destination of the branch is a defined symbol which does not have
13715 the THUMB_FUNC attribute, then we must be calling a function which has
13716 the (interfacearm) attribute. We look for the Thumb entry point to that
13717 function and change the branch to refer to that function instead. */
13718 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23
13719 && fixP->fx_addsy != NULL
13720 && S_IS_DEFINED (fixP->fx_addsy)
13721 && ! THUMB_IS_FUNC (fixP->fx_addsy))
13723 fixP->fx_addsy = find_real_start (fixP->fx_addsy);
13726 #endif
13729 arm_force_relocation (struct fix * fixp)
13731 #if defined (OBJ_COFF) && defined (TE_PE)
13732 if (fixp->fx_r_type == BFD_RELOC_RVA)
13733 return 1;
13734 #endif
13735 #ifdef OBJ_ELF
13736 if (fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
13737 || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
13738 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX
13739 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23)
13740 return 1;
13741 #endif
13743 /* Resolve these relocations even if the symbol is extern or weak. */
13744 if (fixp->fx_r_type == BFD_RELOC_ARM_IMMEDIATE
13745 || fixp->fx_r_type == BFD_RELOC_ARM_OFFSET_IMM
13746 || fixp->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
13747 return 0;
13749 return generic_force_reloc (fixp);
13752 #ifdef OBJ_COFF
13753 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
13754 local labels from being added to the output symbol table when they
13755 are used with the ADRL pseudo op. The ADRL relocation should always
13756 be resolved before the binbary is emitted, so it is safe to say that
13757 it is adjustable. */
13759 bfd_boolean
13760 arm_fix_adjustable (fixS * fixP)
13762 if (fixP->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
13763 return 1;
13764 return 0;
13766 #endif
13768 #ifdef OBJ_ELF
13769 /* Relocations against Thumb function names must be left unadjusted,
13770 so that the linker can use this information to correctly set the
13771 bottom bit of their addresses. The MIPS version of this function
13772 also prevents relocations that are mips-16 specific, but I do not
13773 know why it does this.
13775 FIXME:
13776 There is one other problem that ought to be addressed here, but
13777 which currently is not: Taking the address of a label (rather
13778 than a function) and then later jumping to that address. Such
13779 addresses also ought to have their bottom bit set (assuming that
13780 they reside in Thumb code), but at the moment they will not. */
13782 bfd_boolean
13783 arm_fix_adjustable (fixS * fixP)
13785 if (fixP->fx_addsy == NULL)
13786 return 1;
13788 if (THUMB_IS_FUNC (fixP->fx_addsy)
13789 && fixP->fx_subsy == NULL)
13790 return 0;
13792 /* We need the symbol name for the VTABLE entries. */
13793 if ( fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
13794 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
13795 return 0;
13797 /* Don't allow symbols to be discarded on GOT related relocs. */
13798 if (fixP->fx_r_type == BFD_RELOC_ARM_PLT32
13799 || fixP->fx_r_type == BFD_RELOC_ARM_GOT32
13800 || fixP->fx_r_type == BFD_RELOC_ARM_GOTOFF
13801 || fixP->fx_r_type == BFD_RELOC_ARM_TLS_GD32
13802 || fixP->fx_r_type == BFD_RELOC_ARM_TLS_LE32
13803 || fixP->fx_r_type == BFD_RELOC_ARM_TLS_IE32
13804 || fixP->fx_r_type == BFD_RELOC_ARM_TLS_LDM32
13805 || fixP->fx_r_type == BFD_RELOC_ARM_TLS_LDO32
13806 || fixP->fx_r_type == BFD_RELOC_ARM_TARGET2)
13807 return 0;
13809 return 1;
13812 const char *
13813 elf32_arm_target_format (void)
13815 #ifdef TE_SYMBIAN
13816 return (target_big_endian
13817 ? "elf32-bigarm-symbian"
13818 : "elf32-littlearm-symbian");
13819 #elif defined (TE_VXWORKS)
13820 return (target_big_endian
13821 ? "elf32-bigarm-vxworks"
13822 : "elf32-littlearm-vxworks");
13823 #else
13824 if (target_big_endian)
13825 return "elf32-bigarm";
13826 else
13827 return "elf32-littlearm";
13828 #endif
13831 void
13832 armelf_frob_symbol (symbolS * symp,
13833 int * puntp)
13835 elf_frob_symbol (symp, puntp);
13838 static void
13839 s_arm_elf_cons (int nbytes)
13841 expressionS exp;
13843 #ifdef md_flush_pending_output
13844 md_flush_pending_output ();
13845 #endif
13847 if (is_it_end_of_statement ())
13849 demand_empty_rest_of_line ();
13850 return;
13853 #ifdef md_cons_align
13854 md_cons_align (nbytes);
13855 #endif
13857 mapping_state (MAP_DATA);
13860 bfd_reloc_code_real_type reloc;
13861 char *sym_start;
13862 int sym_len;
13864 sym_start = input_line_pointer;
13865 expression (& exp);
13866 sym_len = input_line_pointer - sym_start;
13868 if (exp.X_op == O_symbol
13869 && * input_line_pointer == '('
13870 && (reloc = arm_parse_reloc ()) != BFD_RELOC_UNUSED)
13872 reloc_howto_type *howto = bfd_reloc_type_lookup (stdoutput, reloc);
13873 int size = bfd_get_reloc_size (howto);
13875 if (size > nbytes)
13876 as_bad ("%s relocations do not fit in %d bytes",
13877 howto->name, nbytes);
13878 else
13880 char *p;
13881 int offset = nbytes - size;
13882 char *saved_buf = alloca (sym_len), *saved_input;
13884 /* We've parsed an expression stopping at O_symbol. But there
13885 may be more expression left now that we have parsed the
13886 relocation marker. Parse it again. */
13887 saved_input = input_line_pointer - sym_len;
13888 memcpy (saved_buf, saved_input, sym_len);
13889 memmove (saved_input, sym_start, sym_len);
13890 input_line_pointer = saved_input;
13891 expression (& exp);
13892 memcpy (saved_input, saved_buf, sym_len);
13893 assert (input_line_pointer >= saved_input + sym_len);
13895 p = frag_more ((int) nbytes);
13896 fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size,
13897 &exp, 0, reloc);
13900 else
13901 emit_expr (&exp, (unsigned int) nbytes);
13903 while (*input_line_pointer++ == ',');
13905 /* Put terminator back into stream. */
13906 input_line_pointer --;
13907 demand_empty_rest_of_line ();
13911 /* Parse a .rel31 directive. */
13913 static void
13914 s_arm_rel31 (int ignored ATTRIBUTE_UNUSED)
13916 expressionS exp;
13917 char *p;
13918 valueT highbit;
13920 SKIP_WHITESPACE ();
13922 highbit = 0;
13923 if (*input_line_pointer == '1')
13924 highbit = 0x80000000;
13925 else if (*input_line_pointer != '0')
13926 as_bad (_("expected 0 or 1"));
13928 input_line_pointer++;
13929 SKIP_WHITESPACE ();
13930 if (*input_line_pointer != ',')
13931 as_bad (_("missing comma"));
13932 input_line_pointer++;
13934 #ifdef md_flush_pending_output
13935 md_flush_pending_output ();
13936 #endif
13938 #ifdef md_cons_align
13939 md_cons_align (4);
13940 #endif
13942 mapping_state (MAP_DATA);
13944 expression (&exp);
13946 p = frag_more (4);
13947 md_number_to_chars (p, highbit, 4);
13948 fix_new_arm (frag_now, p - frag_now->fr_literal, 4, &exp, 1,
13949 BFD_RELOC_ARM_PREL31);
13951 demand_empty_rest_of_line ();
13954 /* Code to deal with unwinding tables. */
13956 static void add_unwind_adjustsp (offsetT);
13958 /* Switch to section NAME and create section if necessary. It's
13959 rather ugly that we have to manipulate input_line_pointer but I
13960 don't see any other way to accomplish the same thing without
13961 changing obj-elf.c (which may be the Right Thing, in the end).
13962 Copied from tc-ia64.c. */
13964 static void
13965 set_section (char *name)
13967 char *saved_input_line_pointer;
13969 saved_input_line_pointer = input_line_pointer;
13970 input_line_pointer = name;
13971 obj_elf_section (0);
13972 input_line_pointer = saved_input_line_pointer;
13975 /* Cenerate and deferred unwind frame offset. */
13977 static void
13978 flush_pending_unwind (void)
13980 offsetT offset;
13982 offset = unwind.pending_offset;
13983 unwind.pending_offset = 0;
13984 if (offset != 0)
13985 add_unwind_adjustsp (offset);
13988 /* Add an opcode to this list for this function. Two-byte opcodes should
13989 be passed as op[0] << 8 | op[1]. The list of opcodes is built in reverse
13990 order. */
13992 static void
13993 add_unwind_opcode (valueT op, int length)
13995 /* Add any deferred stack adjustment. */
13996 if (unwind.pending_offset)
13997 flush_pending_unwind ();
13999 unwind.sp_restored = 0;
14001 if (unwind.opcode_count + length > unwind.opcode_alloc)
14003 unwind.opcode_alloc += ARM_OPCODE_CHUNK_SIZE;
14004 if (unwind.opcodes)
14005 unwind.opcodes = xrealloc (unwind.opcodes,
14006 unwind.opcode_alloc);
14007 else
14008 unwind.opcodes = xmalloc (unwind.opcode_alloc);
14010 while (length > 0)
14012 length--;
14013 unwind.opcodes[unwind.opcode_count] = op & 0xff;
14014 op >>= 8;
14015 unwind.opcode_count++;
14019 /* Add unwind opcodes to adjust the stack pointer. */
14021 static void
14022 add_unwind_adjustsp (offsetT offset)
14024 valueT op;
14026 if (offset > 0x200)
14028 /* We need at most 5 bytes to hold a 32-bit value in a uleb128. */
14029 char bytes[5];
14030 int n;
14031 valueT o;
14033 /* Long form: 0xb2, uleb128. */
14034 /* This might not fit in a word so add the individual bytes,
14035 remembering the list is built in reverse order. */
14036 o = (valueT) ((offset - 0x204) >> 2);
14037 if (o == 0)
14038 add_unwind_opcode (0, 1);
14040 /* Calculate the uleb128 encoding of the offset. */
14041 n = 0;
14042 while (o)
14044 bytes[n] = o & 0x7f;
14045 o >>= 7;
14046 if (o)
14047 bytes[n] |= 0x80;
14048 n++;
14050 /* Add the insn. */
14051 for (; n; n--)
14052 add_unwind_opcode (bytes[n - 1], 1);
14053 add_unwind_opcode (0xb2, 1);
14055 else if (offset > 0x100)
14057 /* Two short opcodes. */
14058 add_unwind_opcode (0x3f, 1);
14059 op = (offset - 0x104) >> 2;
14060 add_unwind_opcode (op, 1);
14062 else if (offset > 0)
14064 /* Short opcode. */
14065 op = (offset - 4) >> 2;
14066 add_unwind_opcode (op, 1);
14068 else if (offset < 0)
14070 offset = -offset;
14071 while (offset > 0x100)
14073 add_unwind_opcode (0x7f, 1);
14074 offset -= 0x100;
14076 op = ((offset - 4) >> 2) | 0x40;
14077 add_unwind_opcode (op, 1);
14081 /* Finish the list of unwind opcodes for this function. */
14082 static void
14083 finish_unwind_opcodes (void)
14085 valueT op;
14087 if (unwind.fp_used)
14089 /* Adjust sp as neccessary. */
14090 unwind.pending_offset += unwind.fp_offset - unwind.frame_size;
14091 flush_pending_unwind ();
14093 /* After restoring sp from the frame pointer. */
14094 op = 0x90 | unwind.fp_reg;
14095 add_unwind_opcode (op, 1);
14097 else
14098 flush_pending_unwind ();
14102 /* Start an exception table entry. If idx is nonzero this is an index table
14103 entry. */
14105 static void
14106 start_unwind_section (const segT text_seg, int idx)
14108 const char * text_name;
14109 const char * prefix;
14110 const char * prefix_once;
14111 size_t prefix_len;
14112 size_t text_len;
14113 char * sec_name;
14114 size_t sec_name_len;
14116 if (idx)
14118 prefix = ELF_STRING_ARM_unwind;
14119 prefix_once = ELF_STRING_ARM_unwind_once;
14121 else
14123 prefix = ELF_STRING_ARM_unwind_info;
14124 prefix_once = ELF_STRING_ARM_unwind_info_once;
14127 text_name = segment_name (text_seg);
14128 if (streq (text_name, ".text"))
14129 text_name = "";
14131 if (strncmp (text_name, ".gnu.linkonce.t.",
14132 strlen (".gnu.linkonce.t.")) == 0)
14134 prefix = prefix_once;
14135 text_name += strlen (".gnu.linkonce.t.");
14138 prefix_len = strlen (prefix);
14139 text_len = strlen (text_name);
14140 sec_name_len = prefix_len + text_len;
14141 sec_name = alloca (sec_name_len + 1);
14142 memcpy (sec_name, prefix, prefix_len);
14143 memcpy (sec_name + prefix_len, text_name, text_len);
14144 sec_name[prefix_len + text_len] = '\0';
14146 /* Handle COMDAT group. */
14147 if (prefix != prefix_once && (text_seg->flags & SEC_LINK_ONCE) != 0)
14149 char *section;
14150 size_t len, group_name_len;
14151 const char *group_name = elf_group_name (text_seg);
14153 if (group_name == NULL)
14155 as_bad ("Group section `%s' has no group signature",
14156 segment_name (text_seg));
14157 ignore_rest_of_line ();
14158 return;
14160 /* We have to construct a fake section directive. */
14161 group_name_len = strlen (group_name);
14162 if (idx)
14163 prefix_len = 13;
14164 else
14165 prefix_len = 16;
14167 len = (sec_name_len
14168 + prefix_len /* ,"aG",%sectiontype, */
14169 + group_name_len /* ,group_name */
14170 + 7); /* ,comdat */
14172 section = alloca (len + 1);
14173 memcpy (section, sec_name, sec_name_len);
14174 if (idx)
14175 memcpy (section + sec_name_len, ",\"aG\",%exidx,", 13);
14176 else
14177 memcpy (section + sec_name_len, ",\"aG\",%progbits,", 16);
14178 memcpy (section + sec_name_len + prefix_len, group_name, group_name_len);
14179 memcpy (section + len - 7, ",comdat", 7);
14180 section [len] = '\0';
14181 set_section (section);
14183 else
14185 set_section (sec_name);
14186 bfd_set_section_flags (stdoutput, now_seg,
14187 SEC_LOAD | SEC_ALLOC | SEC_READONLY);
14190 /* Set the setion link for index tables. */
14191 if (idx)
14192 elf_linked_to_section (now_seg) = text_seg;
14196 /* Start an unwind table entry. HAVE_DATA is nonzero if we have additional
14197 personality routine data. Returns zero, or the index table value for
14198 and inline entry. */
14200 static valueT
14201 create_unwind_entry (int have_data)
14203 int size;
14204 addressT where;
14205 char *ptr;
14206 /* The current word of data. */
14207 valueT data;
14208 /* The number of bytes left in this word. */
14209 int n;
14211 finish_unwind_opcodes ();
14213 /* Remember the current text section. */
14214 unwind.saved_seg = now_seg;
14215 unwind.saved_subseg = now_subseg;
14217 start_unwind_section (now_seg, 0);
14219 if (unwind.personality_routine == NULL)
14221 if (unwind.personality_index == -2)
14223 if (have_data)
14224 as_bad (_("handerdata in cantunwind frame"));
14225 return 1; /* EXIDX_CANTUNWIND. */
14228 /* Use a default personality routine if none is specified. */
14229 if (unwind.personality_index == -1)
14231 if (unwind.opcode_count > 3)
14232 unwind.personality_index = 1;
14233 else
14234 unwind.personality_index = 0;
14237 /* Space for the personality routine entry. */
14238 if (unwind.personality_index == 0)
14240 if (unwind.opcode_count > 3)
14241 as_bad (_("too many unwind opcodes for personality routine 0"));
14243 if (!have_data)
14245 /* All the data is inline in the index table. */
14246 data = 0x80;
14247 n = 3;
14248 while (unwind.opcode_count > 0)
14250 unwind.opcode_count--;
14251 data = (data << 8) | unwind.opcodes[unwind.opcode_count];
14252 n--;
14255 /* Pad with "finish" opcodes. */
14256 while (n--)
14257 data = (data << 8) | 0xb0;
14259 return data;
14261 size = 0;
14263 else
14264 /* We get two opcodes "free" in the first word. */
14265 size = unwind.opcode_count - 2;
14267 else
14268 /* An extra byte is required for the opcode count. */
14269 size = unwind.opcode_count + 1;
14271 size = (size + 3) >> 2;
14272 if (size > 0xff)
14273 as_bad (_("too many unwind opcodes"));
14275 frag_align (2, 0, 0);
14276 record_alignment (now_seg, 2);
14277 unwind.table_entry = expr_build_dot ();
14279 /* Allocate the table entry. */
14280 ptr = frag_more ((size << 2) + 4);
14281 where = frag_now_fix () - ((size << 2) + 4);
14283 switch (unwind.personality_index)
14285 case -1:
14286 /* ??? Should this be a PLT generating relocation? */
14287 /* Custom personality routine. */
14288 fix_new (frag_now, where, 4, unwind.personality_routine, 0, 1,
14289 BFD_RELOC_ARM_PREL31);
14291 where += 4;
14292 ptr += 4;
14294 /* Set the first byte to the number of additional words. */
14295 data = size - 1;
14296 n = 3;
14297 break;
14299 /* ABI defined personality routines. */
14300 case 0:
14301 /* Three opcodes bytes are packed into the first word. */
14302 data = 0x80;
14303 n = 3;
14304 break;
14306 case 1:
14307 case 2:
14308 /* The size and first two opcode bytes go in the first word. */
14309 data = ((0x80 + unwind.personality_index) << 8) | size;
14310 n = 2;
14311 break;
14313 default:
14314 /* Should never happen. */
14315 abort ();
14318 /* Pack the opcodes into words (MSB first), reversing the list at the same
14319 time. */
14320 while (unwind.opcode_count > 0)
14322 if (n == 0)
14324 md_number_to_chars (ptr, data, 4);
14325 ptr += 4;
14326 n = 4;
14327 data = 0;
14329 unwind.opcode_count--;
14330 n--;
14331 data = (data << 8) | unwind.opcodes[unwind.opcode_count];
14334 /* Finish off the last word. */
14335 if (n < 4)
14337 /* Pad with "finish" opcodes. */
14338 while (n--)
14339 data = (data << 8) | 0xb0;
14341 md_number_to_chars (ptr, data, 4);
14344 if (!have_data)
14346 /* Add an empty descriptor if there is no user-specified data. */
14347 ptr = frag_more (4);
14348 md_number_to_chars (ptr, 0, 4);
14351 return 0;
14355 /* Parse an unwind_fnstart directive. Simply records the current location. */
14357 static void
14358 s_arm_unwind_fnstart (int ignored ATTRIBUTE_UNUSED)
14360 demand_empty_rest_of_line ();
14361 /* Mark the start of the function. */
14362 unwind.proc_start = expr_build_dot ();
14364 /* Reset the rest of the unwind info. */
14365 unwind.opcode_count = 0;
14366 unwind.table_entry = NULL;
14367 unwind.personality_routine = NULL;
14368 unwind.personality_index = -1;
14369 unwind.frame_size = 0;
14370 unwind.fp_offset = 0;
14371 unwind.fp_reg = 13;
14372 unwind.fp_used = 0;
14373 unwind.sp_restored = 0;
14377 /* Parse a handlerdata directive. Creates the exception handling table entry
14378 for the function. */
14380 static void
14381 s_arm_unwind_handlerdata (int ignored ATTRIBUTE_UNUSED)
14383 demand_empty_rest_of_line ();
14384 if (unwind.table_entry)
14385 as_bad (_("dupicate .handlerdata directive"));
14387 create_unwind_entry (1);
14390 /* Parse an unwind_fnend directive. Generates the index table entry. */
14392 static void
14393 s_arm_unwind_fnend (int ignored ATTRIBUTE_UNUSED)
14395 long where;
14396 char *ptr;
14397 valueT val;
14399 demand_empty_rest_of_line ();
14401 /* Add eh table entry. */
14402 if (unwind.table_entry == NULL)
14403 val = create_unwind_entry (0);
14404 else
14405 val = 0;
14407 /* Add index table entry. This is two words. */
14408 start_unwind_section (unwind.saved_seg, 1);
14409 frag_align (2, 0, 0);
14410 record_alignment (now_seg, 2);
14412 ptr = frag_more (8);
14413 where = frag_now_fix () - 8;
14415 /* Self relative offset of the function start. */
14416 fix_new (frag_now, where, 4, unwind.proc_start, 0, 1,
14417 BFD_RELOC_ARM_PREL31);
14419 /* Indicate dependency on EHABI-defined personality routines to the
14420 linker, if it hasn't been done already. */
14421 if (unwind.personality_index >= 0 && unwind.personality_index < 3)
14423 char *name[] = { "__aeabi_unwind_cpp_pr0",
14424 "__aeabi_unwind_cpp_pr1",
14425 "__aeabi_unwind_cpp_pr2" };
14426 if (!(marked_pr_dependency & (1 << unwind.personality_index)))
14428 symbolS *pr = symbol_find_or_make (name[unwind.personality_index]);
14429 fix_new (frag_now, where, 0, pr, 0, 1, BFD_RELOC_NONE);
14430 marked_pr_dependency |= 1 << unwind.personality_index;
14431 seg_info (now_seg)->tc_segment_info_data.marked_pr_dependency
14432 = marked_pr_dependency;
14436 if (val)
14437 /* Inline exception table entry. */
14438 md_number_to_chars (ptr + 4, val, 4);
14439 else
14440 /* Self relative offset of the table entry. */
14441 fix_new (frag_now, where + 4, 4, unwind.table_entry, 0, 1,
14442 BFD_RELOC_ARM_PREL31);
14444 /* Restore the original section. */
14445 subseg_set (unwind.saved_seg, unwind.saved_subseg);
14449 /* Parse an unwind_cantunwind directive. */
14451 static void
14452 s_arm_unwind_cantunwind (int ignored ATTRIBUTE_UNUSED)
14454 demand_empty_rest_of_line ();
14455 if (unwind.personality_routine || unwind.personality_index != -1)
14456 as_bad (_("personality routine specified for cantunwind frame"));
14458 unwind.personality_index = -2;
14462 /* Parse a personalityindex directive. */
14464 static void
14465 s_arm_unwind_personalityindex (int ignored ATTRIBUTE_UNUSED)
14467 expressionS exp;
14469 if (unwind.personality_routine || unwind.personality_index != -1)
14470 as_bad (_("duplicate .personalityindex directive"));
14472 SKIP_WHITESPACE ();
14474 expression (&exp);
14476 if (exp.X_op != O_constant
14477 || exp.X_add_number < 0 || exp.X_add_number > 15)
14479 as_bad (_("bad personality routine number"));
14480 ignore_rest_of_line ();
14481 return;
14484 unwind.personality_index = exp.X_add_number;
14486 demand_empty_rest_of_line ();
14490 /* Parse a personality directive. */
14492 static void
14493 s_arm_unwind_personality (int ignored ATTRIBUTE_UNUSED)
14495 char *name, *p, c;
14497 if (unwind.personality_routine || unwind.personality_index != -1)
14498 as_bad (_("duplicate .personality directive"));
14500 SKIP_WHITESPACE ();
14501 name = input_line_pointer;
14502 c = get_symbol_end ();
14503 p = input_line_pointer;
14504 unwind.personality_routine = symbol_find_or_make (name);
14505 *p = c;
14506 SKIP_WHITESPACE ();
14507 demand_empty_rest_of_line ();
14511 /* Parse a directive saving core registers. */
14513 static void
14514 s_arm_unwind_save_core (void)
14516 valueT op;
14517 long range;
14518 int n;
14520 SKIP_WHITESPACE ();
14521 range = reg_list (&input_line_pointer);
14522 if (range == FAIL)
14524 as_bad (_("expected register list"));
14525 ignore_rest_of_line ();
14526 return;
14529 demand_empty_rest_of_line ();
14531 /* Turn .unwind_movsp ip followed by .unwind_save {..., ip, ...}
14532 into .unwind_save {..., sp...}. We aren't bothered about the value of
14533 ip because it is clobbered by calls. */
14534 if (unwind.sp_restored && unwind.fp_reg == 12
14535 && (range & 0x3000) == 0x1000)
14537 unwind.opcode_count--;
14538 unwind.sp_restored = 0;
14539 range = (range | 0x2000) & ~0x1000;
14540 unwind.pending_offset = 0;
14543 /* See if we can use the short opcodes. These pop a block of upto 8
14544 registers starting with r4, plus maybe r14. */
14545 for (n = 0; n < 8; n++)
14547 /* Break at the first non-saved register. */
14548 if ((range & (1 << (n + 4))) == 0)
14549 break;
14551 /* See if there are any other bits set. */
14552 if (n == 0 || (range & (0xfff0 << n) & 0xbff0) != 0)
14554 /* Use the long form. */
14555 op = 0x8000 | ((range >> 4) & 0xfff);
14556 add_unwind_opcode (op, 2);
14558 else
14560 /* Use the short form. */
14561 if (range & 0x4000)
14562 op = 0xa8; /* Pop r14. */
14563 else
14564 op = 0xa0; /* Do not pop r14. */
14565 op |= (n - 1);
14566 add_unwind_opcode (op, 1);
14569 /* Pop r0-r3. */
14570 if (range & 0xf)
14572 op = 0xb100 | (range & 0xf);
14573 add_unwind_opcode (op, 2);
14576 /* Record the number of bytes pushed. */
14577 for (n = 0; n < 16; n++)
14579 if (range & (1 << n))
14580 unwind.frame_size += 4;
14585 /* Parse a directive saving FPA registers. */
14587 static void
14588 s_arm_unwind_save_fpa (int reg)
14590 expressionS exp;
14591 int num_regs;
14592 valueT op;
14594 /* Get Number of registers to transfer. */
14595 if (skip_past_comma (&input_line_pointer) != FAIL)
14596 expression (&exp);
14597 else
14598 exp.X_op = O_illegal;
14600 if (exp.X_op != O_constant)
14602 as_bad (_("expected , <constant>"));
14603 ignore_rest_of_line ();
14604 return;
14607 num_regs = exp.X_add_number;
14609 if (num_regs < 1 || num_regs > 4)
14611 as_bad (_("number of registers must be in the range [1:4]"));
14612 ignore_rest_of_line ();
14613 return;
14616 demand_empty_rest_of_line ();
14618 if (reg == 4)
14620 /* Short form. */
14621 op = 0xb4 | (num_regs - 1);
14622 add_unwind_opcode (op, 1);
14624 else
14626 /* Long form. */
14627 op = 0xc800 | (reg << 4) | (num_regs - 1);
14628 add_unwind_opcode (op, 2);
14630 unwind.frame_size += num_regs * 12;
14634 /* Parse a directive saving VFP registers. */
14636 static void
14637 s_arm_unwind_save_vfp (void)
14639 int count;
14640 int reg;
14641 valueT op;
14643 count = vfp_parse_reg_list (&input_line_pointer, &reg, 1);
14644 if (count == FAIL)
14646 as_bad (_("expected register list"));
14647 ignore_rest_of_line ();
14648 return;
14651 demand_empty_rest_of_line ();
14653 if (reg == 8)
14655 /* Short form. */
14656 op = 0xb8 | (count - 1);
14657 add_unwind_opcode (op, 1);
14659 else
14661 /* Long form. */
14662 op = 0xb300 | (reg << 4) | (count - 1);
14663 add_unwind_opcode (op, 2);
14665 unwind.frame_size += count * 8 + 4;
14669 /* Parse a directive saving iWMMXt registers. */
14671 static void
14672 s_arm_unwind_save_wmmx (void)
14674 int reg;
14675 int hi_reg;
14676 int i;
14677 unsigned wcg_mask;
14678 unsigned wr_mask;
14679 valueT op;
14681 if (*input_line_pointer == '{')
14682 input_line_pointer++;
14684 wcg_mask = 0;
14685 wr_mask = 0;
14688 reg = arm_reg_parse (&input_line_pointer,
14689 all_reg_maps[REG_TYPE_IWMMXT].htab);
14691 if (wr_register (reg))
14693 i = reg & ~WR_PREFIX;
14694 if (wr_mask >> i)
14695 as_tsktsk (_("register list not in ascending order"));
14696 wr_mask |= 1 << i;
14698 else if (wcg_register (reg))
14700 i = (reg & ~WC_PREFIX) - 8;
14701 if (wcg_mask >> i)
14702 as_tsktsk (_("register list not in ascending order"));
14703 wcg_mask |= 1 << i;
14705 else
14707 as_bad (_("expected wr or wcgr"));
14708 goto error;
14711 SKIP_WHITESPACE ();
14712 if (*input_line_pointer == '-')
14714 hi_reg = arm_reg_parse (&input_line_pointer,
14715 all_reg_maps[REG_TYPE_IWMMXT].htab);
14716 if (wr_register (reg) && wr_register (hi_reg))
14718 for (; reg < hi_reg; reg++)
14719 wr_mask |= 1 << (reg & ~WR_PREFIX);
14721 else if (wcg_register (reg) && wcg_register (hi_reg))
14723 for (; reg < hi_reg; reg++)
14724 wcg_mask |= 1 << ((reg & ~WC_PREFIX) - 8);
14726 else
14728 as_bad (_("bad register range"));
14729 goto error;
14733 while (skip_past_comma (&input_line_pointer) != FAIL);
14735 SKIP_WHITESPACE ();
14736 if (*input_line_pointer == '}')
14737 input_line_pointer++;
14739 demand_empty_rest_of_line ();
14741 if (wr_mask && wcg_mask)
14743 as_bad (_("inconsistent register types"));
14744 goto error;
14747 /* Generate any deferred opcodes becuuse we're going to be looking at
14748 the list. */
14749 flush_pending_unwind ();
14751 if (wcg_mask)
14753 for (i = 0; i < 16; i++)
14755 if (wcg_mask & (1 << i))
14756 unwind.frame_size += 4;
14758 op = 0xc700 | wcg_mask;
14759 add_unwind_opcode (op, 2);
14761 else
14763 for (i = 0; i < 16; i++)
14765 if (wr_mask & (1 << i))
14766 unwind.frame_size += 8;
14768 /* Attempt to combine with a previous opcode. We do this because gcc
14769 likes to output separate unwind directives for a single block of
14770 registers. */
14771 if (unwind.opcode_count > 0)
14773 i = unwind.opcodes[unwind.opcode_count - 1];
14774 if ((i & 0xf8) == 0xc0)
14776 i &= 7;
14777 /* Only merge if the blocks are contiguous. */
14778 if (i < 6)
14780 if ((wr_mask & 0xfe00) == (1 << 9))
14782 wr_mask |= ((1 << (i + 11)) - 1) & 0xfc00;
14783 unwind.opcode_count--;
14786 else if (i == 6 && unwind.opcode_count >= 2)
14788 i = unwind.opcodes[unwind.opcode_count - 2];
14789 reg = i >> 4;
14790 i &= 0xf;
14792 op = 0xffff << (reg - 1);
14793 if (reg > 0
14794 || ((wr_mask & op) == (1u << (reg - 1))))
14796 op = (1 << (reg + i + 1)) - 1;
14797 op &= ~((1 << reg) - 1);
14798 wr_mask |= op;
14799 unwind.opcode_count -= 2;
14805 hi_reg = 15;
14806 /* We want to generate opcodes in the order the registers have been
14807 saved, ie. descending order. */
14808 for (reg = 15; reg >= -1; reg--)
14810 /* Save registers in blocks. */
14811 if (reg < 0
14812 || !(wr_mask & (1 << reg)))
14814 /* We found an unsaved reg. Generate opcodes to save the
14815 preceeding block. */
14816 if (reg != hi_reg)
14818 if (reg == 9)
14820 /* Short form. */
14821 op = 0xc0 | (hi_reg - 10);
14822 add_unwind_opcode (op, 1);
14824 else
14826 /* Long form. */
14827 op = 0xc600 | ((reg + 1) << 4) | ((hi_reg - reg) - 1);
14828 add_unwind_opcode (op, 2);
14831 hi_reg = reg - 1;
14835 return;
14836 error:
14837 ignore_rest_of_line ();
14841 /* Parse an unwind_save directive. */
14843 static void
14844 s_arm_unwind_save (int ignored ATTRIBUTE_UNUSED)
14846 char *saved_ptr;
14847 int reg;
14849 /* Figure out what sort of save we have. */
14850 SKIP_WHITESPACE ();
14851 saved_ptr = input_line_pointer;
14853 reg = arm_reg_parse (&input_line_pointer, all_reg_maps[REG_TYPE_FN].htab);
14854 if (reg != FAIL)
14856 s_arm_unwind_save_fpa (reg);
14857 return;
14860 if (*input_line_pointer == '{')
14861 input_line_pointer++;
14863 SKIP_WHITESPACE ();
14865 reg = arm_reg_parse (&input_line_pointer, all_reg_maps[REG_TYPE_RN].htab);
14866 if (reg != FAIL)
14868 input_line_pointer = saved_ptr;
14869 s_arm_unwind_save_core ();
14870 return;
14873 reg = arm_reg_parse (&input_line_pointer, all_reg_maps[REG_TYPE_DN].htab);
14874 if (reg != FAIL)
14876 input_line_pointer = saved_ptr;
14877 s_arm_unwind_save_vfp ();
14878 return;
14881 reg = arm_reg_parse (&input_line_pointer,
14882 all_reg_maps[REG_TYPE_IWMMXT].htab);
14883 if (reg != FAIL)
14885 input_line_pointer = saved_ptr;
14886 s_arm_unwind_save_wmmx ();
14887 return;
14890 /* TODO: Maverick registers. */
14891 as_bad (_("unrecognised register"));
14895 /* Parse an unwind_movsp directive. */
14897 static void
14898 s_arm_unwind_movsp (int ignored ATTRIBUTE_UNUSED)
14900 int reg;
14901 valueT op;
14903 SKIP_WHITESPACE ();
14904 reg = reg_required_here (&input_line_pointer, -1);
14905 if (reg == FAIL)
14907 as_bad (_("ARM register expected"));
14908 ignore_rest_of_line ();
14909 return;
14912 if (reg == 13 || reg == 15)
14914 as_bad (_("r%d not permitted in .unwind_movsp directive"), reg);
14915 ignore_rest_of_line ();
14916 return;
14919 if (unwind.fp_reg != 13)
14920 as_bad (_("unexpected .unwind_movsp directive"));
14922 /* Generate opcode to restore the value. */
14923 op = 0x90 | reg;
14924 add_unwind_opcode (op, 1);
14926 /* Record the information for later. */
14927 unwind.fp_reg = reg;
14928 unwind.fp_offset = unwind.frame_size;
14929 unwind.sp_restored = 1;
14930 demand_empty_rest_of_line ();
14934 /* Parse #<number>. */
14936 static int
14937 require_hashconst (int * val)
14939 expressionS exp;
14941 SKIP_WHITESPACE ();
14942 if (*input_line_pointer == '#')
14944 input_line_pointer++;
14945 expression (&exp);
14947 else
14948 exp.X_op = O_illegal;
14950 if (exp.X_op != O_constant)
14952 as_bad (_("expected #constant"));
14953 ignore_rest_of_line ();
14954 return FAIL;
14956 *val = exp.X_add_number;
14957 return SUCCESS;
14960 /* Parse an unwind_pad directive. */
14962 static void
14963 s_arm_unwind_pad (int ignored ATTRIBUTE_UNUSED)
14965 int offset;
14967 if (require_hashconst (&offset) == FAIL)
14968 return;
14970 if (offset & 3)
14972 as_bad (_("stack increment must be multiple of 4"));
14973 ignore_rest_of_line ();
14974 return;
14977 /* Don't generate any opcodes, just record the details for later. */
14978 unwind.frame_size += offset;
14979 unwind.pending_offset += offset;
14981 demand_empty_rest_of_line ();
14984 /* Parse an unwind_setfp directive. */
14986 static void
14987 s_arm_unwind_setfp (int ignored ATTRIBUTE_UNUSED)
14989 int sp_reg;
14990 int fp_reg;
14991 int offset;
14993 fp_reg = reg_required_here (&input_line_pointer, -1);
14994 if (skip_past_comma (&input_line_pointer) == FAIL)
14995 sp_reg = FAIL;
14996 else
14997 sp_reg = reg_required_here (&input_line_pointer, -1);
14999 if (fp_reg == FAIL || sp_reg == FAIL)
15001 as_bad (_("expected <reg>, <reg>"));
15002 ignore_rest_of_line ();
15003 return;
15006 /* Optonal constant. */
15007 if (skip_past_comma (&input_line_pointer) != FAIL)
15009 if (require_hashconst (&offset) == FAIL)
15010 return;
15012 else
15013 offset = 0;
15015 demand_empty_rest_of_line ();
15017 if (sp_reg != 13 && sp_reg != unwind.fp_reg)
15019 as_bad (_("register must be either sp or set by a previous"
15020 "unwind_movsp directive"));
15021 return;
15024 /* Don't generate any opcodes, just record the information for later. */
15025 unwind.fp_reg = fp_reg;
15026 unwind.fp_used = 1;
15027 if (sp_reg == 13)
15028 unwind.fp_offset = unwind.frame_size - offset;
15029 else
15030 unwind.fp_offset -= offset;
15033 /* Parse an unwind_raw directive. */
15035 static void
15036 s_arm_unwind_raw (int ignored ATTRIBUTE_UNUSED)
15038 expressionS exp;
15039 /* This is an arbitary limit. */
15040 unsigned char op[16];
15041 int count;
15043 SKIP_WHITESPACE ();
15044 expression (&exp);
15045 if (exp.X_op == O_constant
15046 && skip_past_comma (&input_line_pointer) != FAIL)
15048 unwind.frame_size += exp.X_add_number;
15049 expression (&exp);
15051 else
15052 exp.X_op = O_illegal;
15054 if (exp.X_op != O_constant)
15056 as_bad (_("expected <offset>, <opcode>"));
15057 ignore_rest_of_line ();
15058 return;
15061 count = 0;
15063 /* Parse the opcode. */
15064 for (;;)
15066 if (count >= 16)
15068 as_bad (_("unwind opcode too long"));
15069 ignore_rest_of_line ();
15071 if (exp.X_op != O_constant || exp.X_add_number & ~0xff)
15073 as_bad (_("invalid unwind opcode"));
15074 ignore_rest_of_line ();
15075 return;
15077 op[count++] = exp.X_add_number;
15079 /* Parse the next byte. */
15080 if (skip_past_comma (&input_line_pointer) == FAIL)
15081 break;
15083 expression (&exp);
15086 /* Add the opcode bytes in reverse order. */
15087 while (count--)
15088 add_unwind_opcode (op[count], 1);
15090 demand_empty_rest_of_line ();
15093 #endif /* OBJ_ELF */
15095 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
15096 of an rs_align_code fragment. */
15098 void
15099 arm_handle_align (fragS * fragP)
15101 static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 };
15102 static char const thumb_noop[2] = { 0xc0, 0x46 };
15103 static char const arm_bigend_noop[4] = { 0xe1, 0xa0, 0x00, 0x00 };
15104 static char const thumb_bigend_noop[2] = { 0x46, 0xc0 };
15106 int bytes, fix, noop_size;
15107 char * p;
15108 const char * noop;
15110 if (fragP->fr_type != rs_align_code)
15111 return;
15113 bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
15114 p = fragP->fr_literal + fragP->fr_fix;
15115 fix = 0;
15117 if (bytes > MAX_MEM_FOR_RS_ALIGN_CODE)
15118 bytes &= MAX_MEM_FOR_RS_ALIGN_CODE;
15120 if (fragP->tc_frag_data)
15122 if (target_big_endian)
15123 noop = thumb_bigend_noop;
15124 else
15125 noop = thumb_noop;
15126 noop_size = sizeof (thumb_noop);
15128 else
15130 if (target_big_endian)
15131 noop = arm_bigend_noop;
15132 else
15133 noop = arm_noop;
15134 noop_size = sizeof (arm_noop);
15137 if (bytes & (noop_size - 1))
15139 fix = bytes & (noop_size - 1);
15140 memset (p, 0, fix);
15141 p += fix;
15142 bytes -= fix;
15145 while (bytes >= noop_size)
15147 memcpy (p, noop, noop_size);
15148 p += noop_size;
15149 bytes -= noop_size;
15150 fix += noop_size;
15153 fragP->fr_fix += fix;
15154 fragP->fr_var = noop_size;
15157 /* Called from md_do_align. Used to create an alignment
15158 frag in a code section. */
15160 void
15161 arm_frag_align_code (int n, int max)
15163 char * p;
15165 /* We assume that there will never be a requirement
15166 to support alignments greater than 32 bytes. */
15167 if (max > MAX_MEM_FOR_RS_ALIGN_CODE)
15168 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
15170 p = frag_var (rs_align_code,
15171 MAX_MEM_FOR_RS_ALIGN_CODE,
15173 (relax_substateT) max,
15174 (symbolS *) NULL,
15175 (offsetT) n,
15176 (char *) NULL);
15177 *p = 0;
15180 /* Perform target specific initialisation of a frag. */
15182 void
15183 arm_init_frag (fragS * fragP)
15185 /* Record whether this frag is in an ARM or a THUMB area. */
15186 fragP->tc_frag_data = thumb_mode;
15189 #ifdef OBJ_ELF
15191 /* Convert REGNAME to a DWARF-2 register number. */
15194 tc_arm_regname_to_dw2regnum (const char *regname)
15196 unsigned int i;
15198 for (i = 0; rn_table[i].name; i++)
15199 if (streq (regname, rn_table[i].name))
15200 return rn_table[i].number;
15202 return -1;
15205 /* Initialize the DWARF-2 unwind information for this procedure. */
15207 void
15208 tc_arm_frame_initial_instructions (void)
15210 cfi_add_CFA_def_cfa (REG_SP, 0);
15212 #endif
15214 /* This table describes all the machine specific pseudo-ops the assembler
15215 has to support. The fields are:
15216 pseudo-op name without dot
15217 function to call to execute this pseudo-op
15218 Integer arg to pass to the function. */
15220 const pseudo_typeS md_pseudo_table[] =
15222 /* Never called because '.req' does not start a line. */
15223 { "req", s_req, 0 },
15224 { "unreq", s_unreq, 0 },
15225 { "bss", s_bss, 0 },
15226 { "align", s_align, 0 },
15227 { "arm", s_arm, 0 },
15228 { "thumb", s_thumb, 0 },
15229 { "code", s_code, 0 },
15230 { "force_thumb", s_force_thumb, 0 },
15231 { "thumb_func", s_thumb_func, 0 },
15232 { "thumb_set", s_thumb_set, 0 },
15233 { "even", s_even, 0 },
15234 { "ltorg", s_ltorg, 0 },
15235 { "pool", s_ltorg, 0 },
15236 #ifdef OBJ_ELF
15237 { "word", s_arm_elf_cons, 4 },
15238 { "long", s_arm_elf_cons, 4 },
15239 { "rel31", s_arm_rel31, 0 },
15240 { "fnstart", s_arm_unwind_fnstart, 0 },
15241 { "fnend", s_arm_unwind_fnend, 0 },
15242 { "cantunwind", s_arm_unwind_cantunwind, 0 },
15243 { "personality", s_arm_unwind_personality, 0 },
15244 { "personalityindex", s_arm_unwind_personalityindex, 0 },
15245 { "handlerdata", s_arm_unwind_handlerdata, 0 },
15246 { "save", s_arm_unwind_save, 0 },
15247 { "movsp", s_arm_unwind_movsp, 0 },
15248 { "pad", s_arm_unwind_pad, 0 },
15249 { "setfp", s_arm_unwind_setfp, 0 },
15250 { "unwind_raw", s_arm_unwind_raw, 0 },
15251 #else
15252 { "word", cons, 4},
15253 #endif
15254 { "extend", float_cons, 'x' },
15255 { "ldouble", float_cons, 'x' },
15256 { "packed", float_cons, 'p' },
15257 { 0, 0, 0 }