* bfd/bfd-in.h (bfd_is_arm_mapping_symbol_name): Add prototype.
[binutils.git] / gas / config / tc-arm.c
blob298468fd01d5bd630f84436b1b9ce4e8f89500a9
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, 59 Temple Place - Suite 330, Boston, MA
26 02111-1307, 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);
1140 #ifdef STRIP_UNDERSCORE
1141 if (preserved_copy_of_name[0] == '_')
1142 preserved_copy_of_name++;
1143 #endif
1145 #ifdef tc_canonicalize_symbol_name
1146 preserved_copy_of_name =
1147 tc_canonicalize_symbol_name (preserved_copy_of_name);
1148 #endif
1150 S_SET_NAME (symbolP, preserved_copy_of_name);
1152 S_SET_SEGMENT (symbolP, segment);
1153 S_SET_VALUE (symbolP, valu);
1154 symbol_clear_list_pointers (symbolP);
1156 symbol_set_frag (symbolP, frag);
1158 /* Link to end of symbol chain. */
1160 extern int symbol_table_frozen;
1162 if (symbol_table_frozen)
1163 abort ();
1166 symbol_append (symbolP, symbol_lastP, & symbol_rootP, & symbol_lastP);
1168 obj_symbol_new_hook (symbolP);
1170 #ifdef tc_symbol_new_hook
1171 tc_symbol_new_hook (symbolP);
1172 #endif
1174 #ifdef DEBUG_SYMS
1175 verify_symbol_chain (symbol_rootP, symbol_lastP);
1176 #endif /* DEBUG_SYMS */
1179 /* Check that an immediate is valid.
1180 If so, convert it to the right format. */
1182 static unsigned int
1183 validate_immediate (unsigned int val)
1185 unsigned int a;
1186 unsigned int i;
1188 #define rotate_left(v, n) (v << n | v >> (32 - n))
1190 for (i = 0; i < 32; i += 2)
1191 if ((a = rotate_left (val, i)) <= 0xff)
1192 return a | (i << 7); /* 12-bit pack: [shift-cnt,const]. */
1194 return FAIL;
1197 /* Check to see if an immediate can be computed as two separate immediate
1198 values, added together. We already know that this value cannot be
1199 computed by just one ARM instruction. */
1201 static unsigned int
1202 validate_immediate_twopart (unsigned int val,
1203 unsigned int * highpart)
1205 unsigned int a;
1206 unsigned int i;
1208 for (i = 0; i < 32; i += 2)
1209 if (((a = rotate_left (val, i)) & 0xff) != 0)
1211 if (a & 0xff00)
1213 if (a & ~ 0xffff)
1214 continue;
1215 * highpart = (a >> 8) | ((i + 24) << 7);
1217 else if (a & 0xff0000)
1219 if (a & 0xff000000)
1220 continue;
1221 * highpart = (a >> 16) | ((i + 16) << 7);
1223 else
1225 assert (a & 0xff000000);
1226 * highpart = (a >> 24) | ((i + 8) << 7);
1229 return (a & 0xff) | (i << 7);
1232 return FAIL;
1235 static int
1236 validate_offset_imm (unsigned int val, int hwse)
1238 if ((hwse && val > 255) || val > 4095)
1239 return FAIL;
1240 return val;
1244 #ifdef OBJ_ELF
1245 /* This code is to handle mapping symbols as defined in the ARM ELF spec.
1246 (See "Mapping symbols", section 4.5.5, ARM AAELF version 1.0).
1247 Note that previously, $a and $t has type STT_FUNC (BSF_OBJECT flag),
1248 and $d has type STT_OBJECT (BSF_OBJECT flag). Now all three are untyped. */
1250 static enum mstate mapstate = MAP_UNDEFINED;
1252 static void
1253 mapping_state (enum mstate state)
1255 symbolS * symbolP;
1256 const char * symname;
1257 int type;
1259 if (mapstate == state)
1260 /* The mapping symbol has already been emitted.
1261 There is nothing else to do. */
1262 return;
1264 mapstate = state;
1266 switch (state)
1268 case MAP_DATA:
1269 symname = "$d";
1270 type = BSF_NO_FLAGS;
1271 break;
1272 case MAP_ARM:
1273 symname = "$a";
1274 type = BSF_NO_FLAGS;
1275 break;
1276 case MAP_THUMB:
1277 symname = "$t";
1278 type = BSF_NO_FLAGS;
1279 break;
1280 case MAP_UNDEFINED:
1281 return;
1282 default:
1283 abort ();
1286 seg_info (now_seg)->tc_segment_info_data.mapstate = state;
1288 symbolP = symbol_new (symname, now_seg, (valueT) frag_now_fix (), frag_now);
1289 symbol_table_insert (symbolP);
1290 symbol_get_bfdsym (symbolP)->flags |= type | BSF_LOCAL;
1292 switch (state)
1294 case MAP_ARM:
1295 THUMB_SET_FUNC (symbolP, 0);
1296 ARM_SET_THUMB (symbolP, 0);
1297 ARM_SET_INTERWORK (symbolP, support_interwork);
1298 break;
1300 case MAP_THUMB:
1301 THUMB_SET_FUNC (symbolP, 1);
1302 ARM_SET_THUMB (symbolP, 1);
1303 ARM_SET_INTERWORK (symbolP, support_interwork);
1304 break;
1306 case MAP_DATA:
1307 default:
1308 return;
1312 /* When we change sections we need to issue a new mapping symbol. */
1314 void
1315 arm_elf_change_section (void)
1317 flagword flags;
1318 segment_info_type *seginfo;
1320 /* Link an unlinked unwind index table section to the .text section. */
1321 if (elf_section_type (now_seg) == SHT_ARM_EXIDX
1322 && elf_linked_to_section (now_seg) == NULL)
1323 elf_linked_to_section (now_seg) = text_section;
1325 if (!SEG_NORMAL (now_seg))
1326 return;
1328 flags = bfd_get_section_flags (stdoutput, now_seg);
1330 /* We can ignore sections that only contain debug info. */
1331 if ((flags & SEC_ALLOC) == 0)
1332 return;
1334 seginfo = seg_info (now_seg);
1335 mapstate = seginfo->tc_segment_info_data.mapstate;
1336 marked_pr_dependency = seginfo->tc_segment_info_data.marked_pr_dependency;
1340 arm_elf_section_type (const char * str, size_t len)
1342 if (len == 5 && strncmp (str, "exidx", 5) == 0)
1343 return SHT_ARM_EXIDX;
1345 return -1;
1347 #else
1348 #define mapping_state(a)
1349 #endif /* OBJ_ELF */
1351 /* arm_reg_parse () := if it looks like a register, return its token and
1352 advance the pointer. */
1354 static int
1355 arm_reg_parse (char ** ccp, struct hash_control * htab)
1357 char * start = * ccp;
1358 char c;
1359 char * p;
1360 struct reg_entry * reg;
1362 #ifdef REGISTER_PREFIX
1363 if (*start != REGISTER_PREFIX)
1364 return FAIL;
1365 p = start + 1;
1366 #else
1367 p = start;
1368 #ifdef OPTIONAL_REGISTER_PREFIX
1369 if (*p == OPTIONAL_REGISTER_PREFIX)
1370 p++, start++;
1371 #endif
1372 #endif
1373 if (!ISALPHA (*p) || !is_name_beginner (*p))
1374 return FAIL;
1376 c = *p++;
1377 while (ISALPHA (c) || ISDIGIT (c) || c == '_')
1378 c = *p++;
1380 *--p = 0;
1381 reg = (struct reg_entry *) hash_find (htab, start);
1382 *p = c;
1384 if (reg)
1386 *ccp = p;
1387 return reg->number;
1390 return FAIL;
1393 /* Search for the following register name in each of the possible reg name
1394 tables. Return the classification if found, or REG_TYPE_MAX if not
1395 present. */
1397 static enum arm_reg_type
1398 arm_reg_parse_any (char *cp)
1400 int i;
1402 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
1403 if (arm_reg_parse (&cp, all_reg_maps[i].htab) != FAIL)
1404 return (enum arm_reg_type) i;
1406 return REG_TYPE_MAX;
1409 static void
1410 opcode_select (int width)
1412 switch (width)
1414 case 16:
1415 if (! thumb_mode)
1417 if (! (cpu_variant & ARM_EXT_V4T))
1418 as_bad (_("selected processor does not support THUMB opcodes"));
1420 thumb_mode = 1;
1421 /* No need to force the alignment, since we will have been
1422 coming from ARM mode, which is word-aligned. */
1423 record_alignment (now_seg, 1);
1425 mapping_state (MAP_THUMB);
1426 break;
1428 case 32:
1429 if (thumb_mode)
1431 if ((cpu_variant & ARM_ALL) == ARM_EXT_V4T)
1432 as_bad (_("selected processor does not support ARM opcodes"));
1434 thumb_mode = 0;
1436 if (!need_pass_2)
1437 frag_align (2, 0, 0);
1439 record_alignment (now_seg, 1);
1441 mapping_state (MAP_ARM);
1442 break;
1444 default:
1445 as_bad (_("invalid instruction size selected (%d)"), width);
1449 static void
1450 s_req (int a ATTRIBUTE_UNUSED)
1452 as_bad (_("invalid syntax for .req directive"));
1455 /* The .unreq directive deletes an alias which was previously defined
1456 by .req. For example:
1458 my_alias .req r11
1459 .unreq my_alias */
1461 static void
1462 s_unreq (int a ATTRIBUTE_UNUSED)
1464 char * name;
1465 char saved_char;
1467 skip_whitespace (input_line_pointer);
1468 name = input_line_pointer;
1470 while (*input_line_pointer != 0
1471 && *input_line_pointer != ' '
1472 && *input_line_pointer != '\n')
1473 ++input_line_pointer;
1475 saved_char = *input_line_pointer;
1476 *input_line_pointer = 0;
1478 if (*name)
1480 enum arm_reg_type req_type = arm_reg_parse_any (name);
1482 if (req_type != REG_TYPE_MAX)
1484 char *temp_name = name;
1485 int req_no = arm_reg_parse (&temp_name, all_reg_maps[req_type].htab);
1487 if (req_no != FAIL)
1489 struct reg_entry *req_entry;
1491 /* Check to see if this alias is a builtin one. */
1492 req_entry = hash_delete (all_reg_maps[req_type].htab, name);
1494 if (!req_entry)
1495 as_bad (_("unreq: missing hash entry for \"%s\""), name);
1496 else if (req_entry->builtin)
1497 /* FIXME: We are deleting a built in register alias which
1498 points to a const data structure, so we only need to
1499 free up the memory used by the key in the hash table.
1500 Unfortunately we have not recorded this value, so this
1501 is a memory leak. */
1502 /* FIXME: Should we issue a warning message ? */
1504 else
1506 /* Deleting a user defined alias. We need to free the
1507 key and the value, but fortunately the key is the same
1508 as the value->name field. */
1509 free ((char *) req_entry->name);
1510 free (req_entry);
1513 else
1514 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
1516 else
1517 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
1519 else
1520 as_bad (_("invalid syntax for .unreq directive"));
1522 *input_line_pointer = saved_char;
1523 demand_empty_rest_of_line ();
1526 static void
1527 s_bss (int ignore ATTRIBUTE_UNUSED)
1529 /* We don't support putting frags in the BSS segment, we fake it by
1530 marking in_bss, then looking at s_skip for clues. */
1531 subseg_set (bss_section, 0);
1532 demand_empty_rest_of_line ();
1533 mapping_state (MAP_DATA);
1536 static void
1537 s_even (int ignore ATTRIBUTE_UNUSED)
1539 /* Never make frag if expect extra pass. */
1540 if (!need_pass_2)
1541 frag_align (1, 0, 0);
1543 record_alignment (now_seg, 1);
1545 demand_empty_rest_of_line ();
1548 static void
1549 s_ltorg (int ignored ATTRIBUTE_UNUSED)
1551 unsigned int entry;
1552 literal_pool * pool;
1553 char sym_name[20];
1555 pool = find_literal_pool ();
1556 if (pool == NULL
1557 || pool->symbol == NULL
1558 || pool->next_free_entry == 0)
1559 return;
1561 mapping_state (MAP_DATA);
1563 /* Align pool as you have word accesses.
1564 Only make a frag if we have to. */
1565 if (!need_pass_2)
1566 frag_align (2, 0, 0);
1568 record_alignment (now_seg, 2);
1570 sprintf (sym_name, "$$lit_\002%x", pool->id);
1572 symbol_locate (pool->symbol, sym_name, now_seg,
1573 (valueT) frag_now_fix (), frag_now);
1574 symbol_table_insert (pool->symbol);
1576 ARM_SET_THUMB (pool->symbol, thumb_mode);
1578 #if defined OBJ_COFF || defined OBJ_ELF
1579 ARM_SET_INTERWORK (pool->symbol, support_interwork);
1580 #endif
1582 for (entry = 0; entry < pool->next_free_entry; entry ++)
1583 /* First output the expression in the instruction to the pool. */
1584 emit_expr (&(pool->literals[entry]), 4); /* .word */
1586 /* Mark the pool as empty. */
1587 pool->next_free_entry = 0;
1588 pool->symbol = NULL;
1591 /* Same as s_align_ptwo but align 0 => align 2. */
1593 static void
1594 s_align (int unused ATTRIBUTE_UNUSED)
1596 int temp;
1597 long temp_fill;
1598 long max_alignment = 15;
1600 temp = get_absolute_expression ();
1601 if (temp > max_alignment)
1602 as_bad (_("alignment too large: %d assumed"), temp = max_alignment);
1603 else if (temp < 0)
1605 as_bad (_("alignment negative. 0 assumed."));
1606 temp = 0;
1609 if (*input_line_pointer == ',')
1611 input_line_pointer++;
1612 temp_fill = get_absolute_expression ();
1614 else
1615 temp_fill = 0;
1617 if (!temp)
1618 temp = 2;
1620 /* Only make a frag if we HAVE to. */
1621 if (temp && !need_pass_2)
1622 frag_align (temp, (int) temp_fill, 0);
1623 demand_empty_rest_of_line ();
1625 record_alignment (now_seg, temp);
1628 static void
1629 s_force_thumb (int ignore ATTRIBUTE_UNUSED)
1631 /* If we are not already in thumb mode go into it, EVEN if
1632 the target processor does not support thumb instructions.
1633 This is used by gcc/config/arm/lib1funcs.asm for example
1634 to compile interworking support functions even if the
1635 target processor should not support interworking. */
1636 if (! thumb_mode)
1638 thumb_mode = 2;
1640 record_alignment (now_seg, 1);
1643 demand_empty_rest_of_line ();
1646 static void
1647 s_thumb_func (int ignore ATTRIBUTE_UNUSED)
1649 if (! thumb_mode)
1650 opcode_select (16);
1652 /* The following label is the name/address of the start of a Thumb function.
1653 We need to know this for the interworking support. */
1654 label_is_thumb_function_name = TRUE;
1656 demand_empty_rest_of_line ();
1659 /* Perform a .set directive, but also mark the alias as
1660 being a thumb function. */
1662 static void
1663 s_thumb_set (int equiv)
1665 /* XXX the following is a duplicate of the code for s_set() in read.c
1666 We cannot just call that code as we need to get at the symbol that
1667 is created. */
1668 char * name;
1669 char delim;
1670 char * end_name;
1671 symbolS * symbolP;
1673 /* Especial apologies for the random logic:
1674 This just grew, and could be parsed much more simply!
1675 Dean - in haste. */
1676 name = input_line_pointer;
1677 delim = get_symbol_end ();
1678 end_name = input_line_pointer;
1679 *end_name = delim;
1681 SKIP_WHITESPACE ();
1683 if (*input_line_pointer != ',')
1685 *end_name = 0;
1686 as_bad (_("expected comma after name \"%s\""), name);
1687 *end_name = delim;
1688 ignore_rest_of_line ();
1689 return;
1692 input_line_pointer++;
1693 *end_name = 0;
1695 if (name[0] == '.' && name[1] == '\0')
1697 /* XXX - this should not happen to .thumb_set. */
1698 abort ();
1701 if ((symbolP = symbol_find (name)) == NULL
1702 && (symbolP = md_undefined_symbol (name)) == NULL)
1704 #ifndef NO_LISTING
1705 /* When doing symbol listings, play games with dummy fragments living
1706 outside the normal fragment chain to record the file and line info
1707 for this symbol. */
1708 if (listing & LISTING_SYMBOLS)
1710 extern struct list_info_struct * listing_tail;
1711 fragS * dummy_frag = xmalloc (sizeof (fragS));
1713 memset (dummy_frag, 0, sizeof (fragS));
1714 dummy_frag->fr_type = rs_fill;
1715 dummy_frag->line = listing_tail;
1716 symbolP = symbol_new (name, undefined_section, 0, dummy_frag);
1717 dummy_frag->fr_symbol = symbolP;
1719 else
1720 #endif
1721 symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
1723 #ifdef OBJ_COFF
1724 /* "set" symbols are local unless otherwise specified. */
1725 SF_SET_LOCAL (symbolP);
1726 #endif /* OBJ_COFF */
1727 } /* Make a new symbol. */
1729 symbol_table_insert (symbolP);
1731 * end_name = delim;
1733 if (equiv
1734 && S_IS_DEFINED (symbolP)
1735 && S_GET_SEGMENT (symbolP) != reg_section)
1736 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP));
1738 pseudo_set (symbolP);
1740 demand_empty_rest_of_line ();
1742 /* XXX Now we come to the Thumb specific bit of code. */
1744 THUMB_SET_FUNC (symbolP, 1);
1745 ARM_SET_THUMB (symbolP, 1);
1746 #if defined OBJ_ELF || defined OBJ_COFF
1747 ARM_SET_INTERWORK (symbolP, support_interwork);
1748 #endif
1751 static void
1752 s_arm (int ignore ATTRIBUTE_UNUSED)
1754 opcode_select (32);
1755 demand_empty_rest_of_line ();
1758 static void
1759 s_thumb (int ignore ATTRIBUTE_UNUSED)
1761 opcode_select (16);
1762 demand_empty_rest_of_line ();
1765 static void
1766 s_code (int unused ATTRIBUTE_UNUSED)
1768 int temp;
1770 temp = get_absolute_expression ();
1771 switch (temp)
1773 case 16:
1774 case 32:
1775 opcode_select (temp);
1776 break;
1778 default:
1779 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp);
1783 static void
1784 end_of_line (char * str)
1786 skip_whitespace (str);
1788 if (*str != '\0' && !inst.error)
1789 inst.error = _("garbage following instruction");
1792 static int
1793 skip_past_comma (char ** str)
1795 char * p = * str, c;
1796 int comma = 0;
1798 while ((c = *p) == ' ' || c == ',')
1800 p++;
1801 if (c == ',' && comma++)
1802 return FAIL;
1805 if (c == '\0')
1806 return FAIL;
1808 *str = p;
1809 return comma ? SUCCESS : FAIL;
1812 /* Return TRUE if anything in the expression is a bignum. */
1814 static int
1815 walk_no_bignums (symbolS * sp)
1817 if (symbol_get_value_expression (sp)->X_op == O_big)
1818 return 1;
1820 if (symbol_get_value_expression (sp)->X_add_symbol)
1822 return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
1823 || (symbol_get_value_expression (sp)->X_op_symbol
1824 && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
1827 return 0;
1830 static int in_my_get_expression = 0;
1832 static int
1833 my_get_expression (expressionS * ep, char ** str)
1835 char * save_in;
1836 segT seg;
1838 save_in = input_line_pointer;
1839 input_line_pointer = *str;
1840 in_my_get_expression = 1;
1841 seg = expression (ep);
1842 in_my_get_expression = 0;
1844 if (ep->X_op == O_illegal)
1846 /* We found a bad expression in md_operand(). */
1847 *str = input_line_pointer;
1848 input_line_pointer = save_in;
1849 return 1;
1852 #ifdef OBJ_AOUT
1853 if (seg != absolute_section
1854 && seg != text_section
1855 && seg != data_section
1856 && seg != bss_section
1857 && seg != undefined_section)
1859 inst.error = _("bad_segment");
1860 *str = input_line_pointer;
1861 input_line_pointer = save_in;
1862 return 1;
1864 #endif
1866 /* Get rid of any bignums now, so that we don't generate an error for which
1867 we can't establish a line number later on. Big numbers are never valid
1868 in instructions, which is where this routine is always called. */
1869 if (ep->X_op == O_big
1870 || (ep->X_add_symbol
1871 && (walk_no_bignums (ep->X_add_symbol)
1872 || (ep->X_op_symbol
1873 && walk_no_bignums (ep->X_op_symbol)))))
1875 inst.error = _("invalid constant");
1876 *str = input_line_pointer;
1877 input_line_pointer = save_in;
1878 return 1;
1881 *str = input_line_pointer;
1882 input_line_pointer = save_in;
1883 return 0;
1886 /* A standard register must be given at this point.
1887 SHIFT is the place to put it in inst.instruction.
1888 Restores input start point on error.
1889 Returns the reg#, or FAIL. */
1891 static int
1892 reg_required_here (char ** str, int shift)
1894 static char buff [128]; /* XXX */
1895 int reg;
1896 char * start = * str;
1898 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_RN].htab)) != FAIL)
1900 if (shift >= 0)
1901 inst.instruction |= reg << shift;
1902 return reg;
1905 /* Restore the start point, we may have got a reg of the wrong class. */
1906 *str = start;
1908 /* In the few cases where we might be able to accept something else
1909 this error can be overridden. */
1910 sprintf (buff, _("register expected, not '%.100s'"), start);
1911 inst.error = buff;
1913 return FAIL;
1916 /* A Intel Wireless MMX technology register
1917 must be given at this point.
1918 Shift is the place to put it in inst.instruction.
1919 Restores input start point on err.
1920 Returns the reg#, or FAIL. */
1922 static int
1923 wreg_required_here (char ** str,
1924 int shift,
1925 enum wreg_type reg_type)
1927 static char buff [128];
1928 int reg;
1929 char * start = *str;
1931 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_IWMMXT].htab)) != FAIL)
1933 if (wr_register (reg)
1934 && (reg_type == IWMMXT_REG_WR || reg_type == IWMMXT_REG_WR_OR_WC))
1936 if (shift >= 0)
1937 inst.instruction |= (reg ^ WR_PREFIX) << shift;
1938 return reg;
1940 else if (wc_register (reg)
1941 && (reg_type == IWMMXT_REG_WC || reg_type == IWMMXT_REG_WR_OR_WC))
1943 if (shift >= 0)
1944 inst.instruction |= (reg ^ WC_PREFIX) << shift;
1945 return reg;
1947 else if ((wcg_register (reg) && reg_type == IWMMXT_REG_WCG))
1949 if (shift >= 0)
1950 inst.instruction |= ((reg ^ WC_PREFIX) - 8) << shift;
1951 return reg;
1955 /* Restore the start point, we may have got a reg of the wrong class. */
1956 *str = start;
1958 /* In the few cases where we might be able to accept
1959 something else this error can be overridden. */
1960 sprintf (buff, _("Intel Wireless MMX technology register expected, not '%.100s'"), start);
1961 inst.error = buff;
1963 return FAIL;
1966 static const struct asm_psr *
1967 arm_psr_parse (char ** ccp)
1969 char * start = * ccp;
1970 char c;
1971 char * p;
1972 const struct asm_psr * psr;
1974 p = start;
1976 /* Skip to the end of the next word in the input stream. */
1979 c = *p++;
1981 while (ISALPHA (c) || c == '_');
1983 /* Terminate the word. */
1984 *--p = 0;
1986 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
1987 feature for ease of use and backwards compatibility. */
1988 if (!strncmp (start, "cpsr", 4))
1989 strncpy (start, "CPSR", 4);
1990 else if (!strncmp (start, "spsr", 4))
1991 strncpy (start, "SPSR", 4);
1993 /* Now locate the word in the psr hash table. */
1994 psr = (const struct asm_psr *) hash_find (arm_psr_hsh, start);
1996 /* Restore the input stream. */
1997 *p = c;
1999 /* If we found a valid match, advance the
2000 stream pointer past the end of the word. */
2001 *ccp = p;
2003 return psr;
2006 /* Parse the input looking for a PSR flag. */
2008 static int
2009 psr_required_here (char ** str)
2011 char * start = * str;
2012 const struct asm_psr * psr;
2014 psr = arm_psr_parse (str);
2016 if (psr)
2018 /* If this is the SPSR that is being modified, set the R bit. */
2019 if (! psr->cpsr)
2020 inst.instruction |= SPSR_BIT;
2022 /* Set the psr flags in the MSR instruction. */
2023 inst.instruction |= psr->field << PSR_SHIFT;
2025 return SUCCESS;
2028 /* In the few cases where we might be able to accept
2029 something else this error can be overridden. */
2030 inst.error = _("flag for {c}psr instruction expected");
2032 /* Restore the start point. */
2033 *str = start;
2034 return FAIL;
2037 static int
2038 co_proc_number (char ** str)
2040 int processor, pchar;
2041 char *start;
2043 skip_whitespace (*str);
2044 start = *str;
2046 /* The data sheet seems to imply that just a number on its own is valid
2047 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
2048 accept either. */
2049 if ((processor = arm_reg_parse (str, all_reg_maps[REG_TYPE_CP].htab))
2050 == FAIL)
2052 *str = start;
2054 pchar = *(*str)++;
2055 if (pchar >= '0' && pchar <= '9')
2057 processor = pchar - '0';
2058 if (**str >= '0' && **str <= '9')
2060 processor = processor * 10 + *(*str)++ - '0';
2061 if (processor > 15)
2063 inst.error = _("illegal co-processor number");
2064 return FAIL;
2068 else
2070 inst.error = all_reg_maps[REG_TYPE_CP].expected;
2071 return FAIL;
2075 inst.instruction |= processor << 8;
2076 return SUCCESS;
2079 static int
2080 cp_opc_expr (char ** str, int where, int length)
2082 expressionS expr;
2084 skip_whitespace (* str);
2086 memset (&expr, '\0', sizeof (expr));
2088 if (my_get_expression (&expr, str))
2089 return FAIL;
2090 if (expr.X_op != O_constant)
2092 inst.error = _("bad or missing expression");
2093 return FAIL;
2096 if ((expr.X_add_number & ((1 << length) - 1)) != expr.X_add_number)
2098 inst.error = _("immediate co-processor expression too large");
2099 return FAIL;
2102 inst.instruction |= expr.X_add_number << where;
2103 return SUCCESS;
2106 static int
2107 cp_reg_required_here (char ** str, int where)
2109 int reg;
2110 char * start = *str;
2112 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
2114 inst.instruction |= reg << where;
2115 return reg;
2118 /* In the few cases where we might be able to accept something else
2119 this error can be overridden. */
2120 inst.error = all_reg_maps[REG_TYPE_CN].expected;
2122 /* Restore the start point. */
2123 *str = start;
2124 return FAIL;
2127 static int
2128 fp_reg_required_here (char ** str, int where)
2130 int reg;
2131 char * start = * str;
2133 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_FN].htab)) != FAIL)
2135 inst.instruction |= reg << where;
2136 return reg;
2139 /* In the few cases where we might be able to accept something else
2140 this error can be overridden. */
2141 inst.error = all_reg_maps[REG_TYPE_FN].expected;
2143 /* Restore the start point. */
2144 *str = start;
2145 return FAIL;
2148 static int
2149 cp_address_offset (char ** str)
2151 int offset;
2153 skip_whitespace (* str);
2155 if (! is_immediate_prefix (**str))
2157 inst.error = _("immediate expression expected");
2158 return FAIL;
2161 (*str)++;
2163 if (my_get_expression (& inst.reloc.exp, str))
2164 return FAIL;
2166 if (inst.reloc.exp.X_op == O_constant)
2168 offset = inst.reloc.exp.X_add_number;
2170 if (offset & 3)
2172 inst.error = _("co-processor address must be word aligned");
2173 return FAIL;
2176 if (offset > 1023 || offset < -1023)
2178 inst.error = _("offset too large");
2179 return FAIL;
2182 if (offset >= 0)
2183 inst.instruction |= INDEX_UP;
2184 else
2185 offset = -offset;
2187 inst.instruction |= offset >> 2;
2189 else
2190 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
2192 return SUCCESS;
2195 static int
2196 cp_address_required_here (char ** str, int wb_ok)
2198 char * p = * str;
2199 int pre_inc = 0;
2200 int write_back = 0;
2202 if (*p == '[')
2204 int reg;
2206 p++;
2207 skip_whitespace (p);
2209 if ((reg = reg_required_here (& p, 16)) == FAIL)
2210 return FAIL;
2212 skip_whitespace (p);
2214 if (*p == ']')
2216 p++;
2218 skip_whitespace (p);
2220 if (*p == '\0')
2222 /* As an extension to the official ARM syntax we allow:
2223 [Rn]
2224 as a short hand for:
2225 [Rn,#0] */
2226 inst.instruction |= PRE_INDEX | INDEX_UP;
2227 *str = p;
2228 return SUCCESS;
2231 if (skip_past_comma (& p) == FAIL)
2233 inst.error = _("comma expected after closing square bracket");
2234 return FAIL;
2237 skip_whitespace (p);
2239 if (*p == '#')
2241 if (wb_ok)
2243 /* [Rn], #expr */
2244 write_back = WRITE_BACK;
2246 if (reg == REG_PC)
2248 inst.error = _("pc may not be used in post-increment");
2249 return FAIL;
2252 if (cp_address_offset (& p) == FAIL)
2253 return FAIL;
2255 else
2256 pre_inc = PRE_INDEX | INDEX_UP;
2258 else if (*p == '{')
2260 int option;
2262 /* [Rn], {<expr>} */
2263 p++;
2265 skip_whitespace (p);
2267 if (my_get_expression (& inst.reloc.exp, & p))
2268 return FAIL;
2270 if (inst.reloc.exp.X_op == O_constant)
2272 option = inst.reloc.exp.X_add_number;
2274 if (option > 255 || option < 0)
2276 inst.error = _("'option' field too large");
2277 return FAIL;
2280 skip_whitespace (p);
2282 if (*p != '}')
2284 inst.error = _("'}' expected at end of 'option' field");
2285 return FAIL;
2287 else
2289 p++;
2290 inst.instruction |= option;
2291 inst.instruction |= INDEX_UP;
2294 else
2296 inst.error = _("non-constant expressions for 'option' field not supported");
2297 return FAIL;
2300 else
2302 inst.error = _("# or { expected after comma");
2303 return FAIL;
2306 else
2308 /* '['Rn, #expr']'[!] */
2310 if (skip_past_comma (& p) == FAIL)
2312 inst.error = _("pre-indexed expression expected");
2313 return FAIL;
2316 pre_inc = PRE_INDEX;
2318 if (cp_address_offset (& p) == FAIL)
2319 return FAIL;
2321 skip_whitespace (p);
2323 if (*p++ != ']')
2325 inst.error = _("missing ]");
2326 return FAIL;
2329 skip_whitespace (p);
2331 if (wb_ok && *p == '!')
2333 if (reg == REG_PC)
2335 inst.error = _("pc may not be used with write-back");
2336 return FAIL;
2339 p++;
2340 write_back = WRITE_BACK;
2344 else
2346 if (my_get_expression (&inst.reloc.exp, &p))
2347 return FAIL;
2349 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
2350 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
2351 inst.reloc.pc_rel = 1;
2352 inst.instruction |= (REG_PC << 16);
2353 pre_inc = PRE_INDEX;
2356 inst.instruction |= write_back | pre_inc;
2357 *str = p;
2358 return SUCCESS;
2361 static int
2362 cp_byte_address_offset (char ** str)
2364 int offset;
2366 skip_whitespace (* str);
2368 if (! is_immediate_prefix (**str))
2370 inst.error = _("immediate expression expected");
2371 return FAIL;
2374 (*str)++;
2376 if (my_get_expression (& inst.reloc.exp, str))
2377 return FAIL;
2379 if (inst.reloc.exp.X_op == O_constant)
2381 offset = inst.reloc.exp.X_add_number;
2383 if (offset > 255 || offset < -255)
2385 inst.error = _("offset too large");
2386 return FAIL;
2389 if (offset >= 0)
2390 inst.instruction |= INDEX_UP;
2391 else
2392 offset = -offset;
2394 inst.instruction |= offset;
2396 else
2397 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
2399 return SUCCESS;
2402 static int
2403 cp_byte_address_required_here (char ** str)
2405 char * p = * str;
2406 int pre_inc = 0;
2407 int write_back = 0;
2409 if (*p == '[')
2411 int reg;
2413 p++;
2414 skip_whitespace (p);
2416 if ((reg = reg_required_here (& p, 16)) == FAIL)
2417 return FAIL;
2419 skip_whitespace (p);
2421 if (*p == ']')
2423 p++;
2425 if (skip_past_comma (& p) == SUCCESS)
2427 /* [Rn], #expr */
2428 write_back = WRITE_BACK;
2430 if (reg == REG_PC)
2432 inst.error = _("pc may not be used in post-increment");
2433 return FAIL;
2436 if (cp_byte_address_offset (& p) == FAIL)
2437 return FAIL;
2439 else
2440 pre_inc = PRE_INDEX | INDEX_UP;
2442 else
2444 /* '['Rn, #expr']'[!] */
2446 if (skip_past_comma (& p) == FAIL)
2448 inst.error = _("pre-indexed expression expected");
2449 return FAIL;
2452 pre_inc = PRE_INDEX;
2454 if (cp_byte_address_offset (& p) == FAIL)
2455 return FAIL;
2457 skip_whitespace (p);
2459 if (*p++ != ']')
2461 inst.error = _("missing ]");
2462 return FAIL;
2465 skip_whitespace (p);
2467 if (*p == '!')
2469 if (reg == REG_PC)
2471 inst.error = _("pc may not be used with write-back");
2472 return FAIL;
2475 p++;
2476 write_back = WRITE_BACK;
2480 else
2482 if (my_get_expression (&inst.reloc.exp, &p))
2483 return FAIL;
2485 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
2486 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
2487 inst.reloc.pc_rel = 1;
2488 inst.instruction |= (REG_PC << 16);
2489 pre_inc = PRE_INDEX;
2492 inst.instruction |= write_back | pre_inc;
2493 *str = p;
2494 return SUCCESS;
2497 static void
2498 do_nop (char * str)
2500 skip_whitespace (str);
2501 if (*str == '{')
2503 str++;
2505 if (my_get_expression (&inst.reloc.exp, &str))
2506 inst.reloc.exp.X_op = O_illegal;
2507 else
2509 skip_whitespace (str);
2510 if (*str == '}')
2511 str++;
2512 else
2513 inst.reloc.exp.X_op = O_illegal;
2516 if (inst.reloc.exp.X_op != O_constant
2517 || inst.reloc.exp.X_add_number > 255
2518 || inst.reloc.exp.X_add_number < 0)
2520 inst.error = _("Invalid NOP hint");
2521 return;
2524 /* Arcitectural NOP hints are CPSR sets with no bits selected. */
2525 inst.instruction &= 0xf0000000;
2526 inst.instruction |= 0x0320f000 + inst.reloc.exp.X_add_number;
2529 end_of_line (str);
2532 static void
2533 do_empty (char * str)
2535 /* Do nothing really. */
2536 end_of_line (str);
2539 static void
2540 do_mrs (char * str)
2542 int skip = 0;
2544 /* Only one syntax. */
2545 skip_whitespace (str);
2547 if (reg_required_here (&str, 12) == FAIL)
2549 inst.error = BAD_ARGS;
2550 return;
2553 if (skip_past_comma (&str) == FAIL)
2555 inst.error = _("comma expected after register name");
2556 return;
2559 skip_whitespace (str);
2561 if ( streq (str, "CPSR")
2562 || streq (str, "SPSR")
2563 /* Lower case versions for backwards compatibility. */
2564 || streq (str, "cpsr")
2565 || streq (str, "spsr"))
2566 skip = 4;
2568 /* This is for backwards compatibility with older toolchains. */
2569 else if ( streq (str, "cpsr_all")
2570 || streq (str, "spsr_all"))
2571 skip = 8;
2572 else
2574 inst.error = _("CPSR or SPSR expected");
2575 return;
2578 if (* str == 's' || * str == 'S')
2579 inst.instruction |= SPSR_BIT;
2580 str += skip;
2582 end_of_line (str);
2585 /* Two possible forms:
2586 "{C|S}PSR_<field>, Rm",
2587 "{C|S}PSR_f, #expression". */
2589 static void
2590 do_msr (char * str)
2592 skip_whitespace (str);
2594 if (psr_required_here (& str) == FAIL)
2595 return;
2597 if (skip_past_comma (& str) == FAIL)
2599 inst.error = _("comma missing after psr flags");
2600 return;
2603 skip_whitespace (str);
2605 if (reg_required_here (& str, 0) != FAIL)
2607 inst.error = NULL;
2608 end_of_line (str);
2609 return;
2612 if (! is_immediate_prefix (* str))
2614 inst.error =
2615 _("only a register or immediate value can follow a psr flag");
2616 return;
2619 str ++;
2620 inst.error = NULL;
2622 if (my_get_expression (& inst.reloc.exp, & str))
2624 inst.error =
2625 _("only a register or immediate value can follow a psr flag");
2626 return;
2629 inst.instruction |= INST_IMMEDIATE;
2631 if (inst.reloc.exp.X_add_symbol)
2633 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
2634 inst.reloc.pc_rel = 0;
2636 else
2638 unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
2640 if (value == (unsigned) FAIL)
2642 inst.error = _("invalid constant");
2643 return;
2646 inst.instruction |= value;
2649 inst.error = NULL;
2650 end_of_line (str);
2653 /* Long Multiply Parser
2654 UMULL RdLo, RdHi, Rm, Rs
2655 SMULL RdLo, RdHi, Rm, Rs
2656 UMLAL RdLo, RdHi, Rm, Rs
2657 SMLAL RdLo, RdHi, Rm, Rs. */
2659 static void
2660 do_mull (char * str)
2662 int rdlo, rdhi, rm, rs;
2664 /* Only one format "rdlo, rdhi, rm, rs". */
2665 skip_whitespace (str);
2667 if ((rdlo = reg_required_here (&str, 12)) == FAIL)
2669 inst.error = BAD_ARGS;
2670 return;
2673 if (skip_past_comma (&str) == FAIL
2674 || (rdhi = reg_required_here (&str, 16)) == FAIL)
2676 inst.error = BAD_ARGS;
2677 return;
2680 if (skip_past_comma (&str) == FAIL
2681 || (rm = reg_required_here (&str, 0)) == FAIL)
2683 inst.error = BAD_ARGS;
2684 return;
2687 /* rdhi, rdlo and rm must all be different. */
2688 if (rdlo == rdhi || rdlo == rm || rdhi == rm)
2689 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
2691 if (skip_past_comma (&str) == FAIL
2692 || (rs = reg_required_here (&str, 8)) == FAIL)
2694 inst.error = BAD_ARGS;
2695 return;
2698 if (rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC)
2700 inst.error = BAD_PC;
2701 return;
2704 end_of_line (str);
2707 static void
2708 do_mul (char * str)
2710 int rd, rm;
2712 /* Only one format "rd, rm, rs". */
2713 skip_whitespace (str);
2715 if ((rd = reg_required_here (&str, 16)) == FAIL)
2717 inst.error = BAD_ARGS;
2718 return;
2721 if (rd == REG_PC)
2723 inst.error = BAD_PC;
2724 return;
2727 if (skip_past_comma (&str) == FAIL
2728 || (rm = reg_required_here (&str, 0)) == FAIL)
2730 inst.error = BAD_ARGS;
2731 return;
2734 if (rm == REG_PC)
2736 inst.error = BAD_PC;
2737 return;
2740 if (rm == rd)
2741 as_tsktsk (_("rd and rm should be different in mul"));
2743 if (skip_past_comma (&str) == FAIL
2744 || (rm = reg_required_here (&str, 8)) == FAIL)
2746 inst.error = BAD_ARGS;
2747 return;
2750 if (rm == REG_PC)
2752 inst.error = BAD_PC;
2753 return;
2756 end_of_line (str);
2759 static void
2760 do_mlas (char * str, bfd_boolean is_mls)
2762 int rd, rm;
2764 /* Only one format "rd, rm, rs, rn". */
2765 skip_whitespace (str);
2767 if ((rd = reg_required_here (&str, 16)) == FAIL)
2769 inst.error = BAD_ARGS;
2770 return;
2773 if (rd == REG_PC)
2775 inst.error = BAD_PC;
2776 return;
2779 if (skip_past_comma (&str) == FAIL
2780 || (rm = reg_required_here (&str, 0)) == FAIL)
2782 inst.error = BAD_ARGS;
2783 return;
2786 if (rm == REG_PC)
2788 inst.error = BAD_PC;
2789 return;
2792 /* This restriction does not apply to mls (nor to mla in v6, but
2793 that's hard to detect at present). */
2794 if (rm == rd && !is_mls)
2795 as_tsktsk (_("rd and rm should be different in mla"));
2797 if (skip_past_comma (&str) == FAIL
2798 || (rd = reg_required_here (&str, 8)) == FAIL
2799 || skip_past_comma (&str) == FAIL
2800 || (rm = reg_required_here (&str, 12)) == FAIL)
2802 inst.error = BAD_ARGS;
2803 return;
2806 if (rd == REG_PC || rm == REG_PC)
2808 inst.error = BAD_PC;
2809 return;
2812 end_of_line (str);
2815 static void
2816 do_mla (char *str)
2818 do_mlas (str, FALSE);
2821 static void
2822 do_mls (char *str)
2824 do_mlas (str, TRUE);
2827 /* Expects *str -> the characters "acc0", possibly with leading blanks.
2828 Advances *str to the next non-alphanumeric.
2829 Returns 0, or else FAIL (in which case sets inst.error).
2831 (In a future XScale, there may be accumulators other than zero.
2832 At that time this routine and its callers can be upgraded to suit.) */
2834 static int
2835 accum0_required_here (char ** str)
2837 static char buff [128]; /* Note the address is taken. Hence, static. */
2838 char * p = * str;
2839 char c;
2840 int result = 0; /* The accum number. */
2842 skip_whitespace (p);
2844 *str = p; /* Advance caller's string pointer too. */
2845 c = *p++;
2846 while (ISALNUM (c))
2847 c = *p++;
2849 *--p = 0; /* Aap nul into input buffer at non-alnum. */
2851 if (! ( streq (*str, "acc0") || streq (*str, "ACC0")))
2853 sprintf (buff, _("acc0 expected, not '%.100s'"), *str);
2854 inst.error = buff;
2855 result = FAIL;
2858 *p = c; /* Unzap. */
2859 *str = p; /* Caller's string pointer to after match. */
2860 return result;
2863 static int
2864 ldst_extend_v4 (char ** str)
2866 int add = INDEX_UP;
2868 switch (**str)
2870 case '#':
2871 case '$':
2872 (*str)++;
2873 if (my_get_expression (& inst.reloc.exp, str))
2874 return FAIL;
2876 if (inst.reloc.exp.X_op == O_constant)
2878 int value = inst.reloc.exp.X_add_number;
2880 if (value < -255 || value > 255)
2882 inst.error = _("address offset too large");
2883 return FAIL;
2886 if (value < 0)
2888 value = -value;
2889 add = 0;
2892 /* Halfword and signextension instructions have the
2893 immediate value split across bits 11..8 and bits 3..0. */
2894 inst.instruction |= (add | HWOFFSET_IMM
2895 | ((value >> 4) << 8) | (value & 0xF));
2897 else
2899 inst.instruction |= HWOFFSET_IMM;
2900 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
2901 inst.reloc.pc_rel = 0;
2903 return SUCCESS;
2905 case '-':
2906 add = 0;
2907 /* Fall through. */
2909 case '+':
2910 (*str)++;
2911 /* Fall through. */
2913 default:
2914 if (reg_required_here (str, 0) == FAIL)
2915 return FAIL;
2917 inst.instruction |= add;
2918 return SUCCESS;
2922 /* Expects **str -> after a comma. May be leading blanks.
2923 Advances *str, recognizing a load mode, and setting inst.instruction.
2924 Returns rn, or else FAIL (in which case may set inst.error
2925 and not advance str)
2927 Note: doesn't know Rd, so no err checks that require such knowledge. */
2929 static int
2930 ld_mode_required_here (char ** string)
2932 char * str = * string;
2933 int rn;
2934 int pre_inc = 0;
2936 skip_whitespace (str);
2938 if (* str == '[')
2940 str++;
2942 skip_whitespace (str);
2944 if ((rn = reg_required_here (& str, 16)) == FAIL)
2945 return FAIL;
2947 skip_whitespace (str);
2949 if (* str == ']')
2951 str ++;
2953 if (skip_past_comma (& str) == SUCCESS)
2955 /* [Rn],... (post inc) */
2956 if (ldst_extend_v4 (&str) == FAIL)
2957 return FAIL;
2959 else /* [Rn] */
2961 skip_whitespace (str);
2963 if (* str == '!')
2965 str ++;
2966 inst.instruction |= WRITE_BACK;
2969 inst.instruction |= INDEX_UP | HWOFFSET_IMM;
2970 pre_inc = 1;
2973 else /* [Rn,...] */
2975 if (skip_past_comma (& str) == FAIL)
2977 inst.error = _("pre-indexed expression expected");
2978 return FAIL;
2981 pre_inc = 1;
2983 if (ldst_extend_v4 (&str) == FAIL)
2984 return FAIL;
2986 skip_whitespace (str);
2988 if (* str ++ != ']')
2990 inst.error = _("missing ]");
2991 return FAIL;
2994 skip_whitespace (str);
2996 if (* str == '!')
2998 str ++;
2999 inst.instruction |= WRITE_BACK;
3003 else if (* str == '=') /* ldr's "r,=label" syntax */
3004 /* We should never reach here, because <text> = <expression> is
3005 caught gas/read.c read_a_source_file() as a .set operation. */
3006 return FAIL;
3007 else /* PC +- 8 bit immediate offset. */
3009 if (my_get_expression (& inst.reloc.exp, & str))
3010 return FAIL;
3012 inst.instruction |= HWOFFSET_IMM; /* The I bit. */
3013 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
3014 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
3015 inst.reloc.pc_rel = 1;
3016 inst.instruction |= (REG_PC << 16);
3018 rn = REG_PC;
3019 pre_inc = 1;
3022 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
3023 * string = str;
3025 return rn;
3028 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
3029 SMLAxy{cond} Rd,Rm,Rs,Rn
3030 SMLAWy{cond} Rd,Rm,Rs,Rn
3031 Error if any register is R15. */
3033 static void
3034 do_smla (char * str)
3036 int rd, rm, rs, rn;
3038 skip_whitespace (str);
3040 if ((rd = reg_required_here (& str, 16)) == FAIL
3041 || skip_past_comma (& str) == FAIL
3042 || (rm = reg_required_here (& str, 0)) == FAIL
3043 || skip_past_comma (& str) == FAIL
3044 || (rs = reg_required_here (& str, 8)) == FAIL
3045 || skip_past_comma (& str) == FAIL
3046 || (rn = reg_required_here (& str, 12)) == FAIL)
3047 inst.error = BAD_ARGS;
3049 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC || rn == REG_PC)
3050 inst.error = BAD_PC;
3052 else
3053 end_of_line (str);
3056 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
3057 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
3058 Error if any register is R15.
3059 Warning if Rdlo == Rdhi. */
3061 static void
3062 do_smlal (char * str)
3064 int rdlo, rdhi, rm, rs;
3066 skip_whitespace (str);
3068 if ((rdlo = reg_required_here (& str, 12)) == FAIL
3069 || skip_past_comma (& str) == FAIL
3070 || (rdhi = reg_required_here (& str, 16)) == FAIL
3071 || skip_past_comma (& str) == FAIL
3072 || (rm = reg_required_here (& str, 0)) == FAIL
3073 || skip_past_comma (& str) == FAIL
3074 || (rs = reg_required_here (& str, 8)) == FAIL)
3076 inst.error = BAD_ARGS;
3077 return;
3080 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
3082 inst.error = BAD_PC;
3083 return;
3086 if (rdlo == rdhi)
3087 as_tsktsk (_("rdhi and rdlo must be different"));
3089 end_of_line (str);
3092 /* ARM V5E (El Segundo) signed-multiply (argument parse)
3093 SMULxy{cond} Rd,Rm,Rs
3094 Error if any register is R15. */
3096 static void
3097 do_smul (char * str)
3099 int rd, rm, rs;
3101 skip_whitespace (str);
3103 if ((rd = reg_required_here (& str, 16)) == FAIL
3104 || skip_past_comma (& str) == FAIL
3105 || (rm = reg_required_here (& str, 0)) == FAIL
3106 || skip_past_comma (& str) == FAIL
3107 || (rs = reg_required_here (& str, 8)) == FAIL)
3108 inst.error = BAD_ARGS;
3110 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC)
3111 inst.error = BAD_PC;
3113 else
3114 end_of_line (str);
3117 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
3118 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
3119 Error if any register is R15. */
3121 static void
3122 do_qadd (char * str)
3124 int rd, rm, rn;
3126 skip_whitespace (str);
3128 if ((rd = reg_required_here (& str, 12)) == FAIL
3129 || skip_past_comma (& str) == FAIL
3130 || (rm = reg_required_here (& str, 0)) == FAIL
3131 || skip_past_comma (& str) == FAIL
3132 || (rn = reg_required_here (& str, 16)) == FAIL)
3133 inst.error = BAD_ARGS;
3135 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
3136 inst.error = BAD_PC;
3138 else
3139 end_of_line (str);
3142 /* ARM V5E (el Segundo)
3143 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3144 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3146 These are equivalent to the XScale instructions MAR and MRA,
3147 respectively, when coproc == 0, opcode == 0, and CRm == 0.
3149 Result unpredicatable if Rd or Rn is R15. */
3151 static void
3152 do_co_reg2c (char * str)
3154 int rd, rn;
3156 skip_whitespace (str);
3158 if (co_proc_number (& str) == FAIL)
3160 if (!inst.error)
3161 inst.error = BAD_ARGS;
3162 return;
3165 if (skip_past_comma (& str) == FAIL
3166 || cp_opc_expr (& str, 4, 4) == FAIL)
3168 if (!inst.error)
3169 inst.error = BAD_ARGS;
3170 return;
3173 if (skip_past_comma (& str) == FAIL
3174 || (rd = reg_required_here (& str, 12)) == FAIL)
3176 if (!inst.error)
3177 inst.error = BAD_ARGS;
3178 return;
3181 if (skip_past_comma (& str) == FAIL
3182 || (rn = reg_required_here (& str, 16)) == FAIL)
3184 if (!inst.error)
3185 inst.error = BAD_ARGS;
3186 return;
3189 /* Unpredictable result if rd or rn is R15. */
3190 if (rd == REG_PC || rn == REG_PC)
3191 as_tsktsk
3192 (_("Warning: instruction unpredictable when using r15"));
3194 if (skip_past_comma (& str) == FAIL
3195 || cp_reg_required_here (& str, 0) == FAIL)
3197 if (!inst.error)
3198 inst.error = BAD_ARGS;
3199 return;
3202 end_of_line (str);
3205 /* ARM V5 count-leading-zeroes instruction (argument parse)
3206 CLZ{<cond>} <Rd>, <Rm>
3207 Condition defaults to COND_ALWAYS.
3208 Error if Rd or Rm are R15. */
3210 static void
3211 do_clz (char * str)
3213 int rd, rm;
3215 skip_whitespace (str);
3217 if (((rd = reg_required_here (& str, 12)) == FAIL)
3218 || (skip_past_comma (& str) == FAIL)
3219 || ((rm = reg_required_here (& str, 0)) == FAIL))
3220 inst.error = BAD_ARGS;
3222 else if (rd == REG_PC || rm == REG_PC )
3223 inst.error = BAD_PC;
3225 else
3226 end_of_line (str);
3229 /* ARM V5 (argument parse)
3230 LDC2{L} <coproc>, <CRd>, <addressing mode>
3231 STC2{L} <coproc>, <CRd>, <addressing mode>
3232 Instruction is not conditional, and has 0xf in the condition field.
3233 Otherwise, it's the same as LDC/STC. */
3235 static void
3236 do_lstc2 (char * str)
3238 skip_whitespace (str);
3240 if (co_proc_number (& str) == FAIL)
3242 if (!inst.error)
3243 inst.error = BAD_ARGS;
3245 else if (skip_past_comma (& str) == FAIL
3246 || cp_reg_required_here (& str, 12) == FAIL)
3248 if (!inst.error)
3249 inst.error = BAD_ARGS;
3251 else if (skip_past_comma (& str) == FAIL
3252 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
3254 if (! inst.error)
3255 inst.error = BAD_ARGS;
3257 else
3258 end_of_line (str);
3261 /* ARM V5 (argument parse)
3262 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
3263 Instruction is not conditional, and has 0xf in the condition field.
3264 Otherwise, it's the same as CDP. */
3266 static void
3267 do_cdp2 (char * str)
3269 skip_whitespace (str);
3271 if (co_proc_number (& str) == FAIL)
3273 if (!inst.error)
3274 inst.error = BAD_ARGS;
3275 return;
3278 if (skip_past_comma (& str) == FAIL
3279 || cp_opc_expr (& str, 20,4) == FAIL)
3281 if (!inst.error)
3282 inst.error = BAD_ARGS;
3283 return;
3286 if (skip_past_comma (& str) == FAIL
3287 || cp_reg_required_here (& str, 12) == FAIL)
3289 if (!inst.error)
3290 inst.error = BAD_ARGS;
3291 return;
3294 if (skip_past_comma (& str) == FAIL
3295 || cp_reg_required_here (& str, 16) == FAIL)
3297 if (!inst.error)
3298 inst.error = BAD_ARGS;
3299 return;
3302 if (skip_past_comma (& str) == FAIL
3303 || cp_reg_required_here (& str, 0) == FAIL)
3305 if (!inst.error)
3306 inst.error = BAD_ARGS;
3307 return;
3310 if (skip_past_comma (& str) == SUCCESS)
3312 if (cp_opc_expr (& str, 5, 3) == FAIL)
3314 if (!inst.error)
3315 inst.error = BAD_ARGS;
3316 return;
3320 end_of_line (str);
3323 /* ARM V5 (argument parse)
3324 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3325 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3326 Instruction is not conditional, and has 0xf in the condition field.
3327 Otherwise, it's the same as MCR/MRC. */
3329 static void
3330 do_co_reg2 (char * str)
3332 skip_whitespace (str);
3334 if (co_proc_number (& str) == FAIL)
3336 if (!inst.error)
3337 inst.error = BAD_ARGS;
3338 return;
3341 if (skip_past_comma (& str) == FAIL
3342 || cp_opc_expr (& str, 21, 3) == FAIL)
3344 if (!inst.error)
3345 inst.error = BAD_ARGS;
3346 return;
3349 if (skip_past_comma (& str) == FAIL
3350 || reg_required_here (& str, 12) == FAIL)
3352 if (!inst.error)
3353 inst.error = BAD_ARGS;
3354 return;
3357 if (skip_past_comma (& str) == FAIL
3358 || cp_reg_required_here (& str, 16) == FAIL)
3360 if (!inst.error)
3361 inst.error = BAD_ARGS;
3362 return;
3365 if (skip_past_comma (& str) == FAIL
3366 || cp_reg_required_here (& str, 0) == FAIL)
3368 if (!inst.error)
3369 inst.error = BAD_ARGS;
3370 return;
3373 if (skip_past_comma (& str) == SUCCESS)
3375 if (cp_opc_expr (& str, 5, 3) == FAIL)
3377 if (!inst.error)
3378 inst.error = BAD_ARGS;
3379 return;
3383 end_of_line (str);
3386 static void
3387 do_bx (char * str)
3389 int reg;
3391 skip_whitespace (str);
3393 if ((reg = reg_required_here (&str, 0)) == FAIL)
3395 inst.error = BAD_ARGS;
3396 return;
3399 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
3400 if (reg == REG_PC)
3401 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
3403 end_of_line (str);
3406 /* ARM v5TEJ. Jump to Jazelle code. */
3408 static void
3409 do_bxj (char * str)
3411 int reg;
3413 skip_whitespace (str);
3415 if ((reg = reg_required_here (&str, 0)) == FAIL)
3417 inst.error = BAD_ARGS;
3418 return;
3421 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
3422 if (reg == REG_PC)
3423 as_tsktsk (_("use of r15 in bxj is not really useful"));
3425 end_of_line (str);
3428 /* ARM V6 umaal (argument parse). */
3430 static void
3431 do_umaal (char * str)
3433 int rdlo, rdhi, rm, rs;
3435 skip_whitespace (str);
3436 if ((rdlo = reg_required_here (& str, 12)) == FAIL
3437 || skip_past_comma (& str) == FAIL
3438 || (rdhi = reg_required_here (& str, 16)) == FAIL
3439 || skip_past_comma (& str) == FAIL
3440 || (rm = reg_required_here (& str, 0)) == FAIL
3441 || skip_past_comma (& str) == FAIL
3442 || (rs = reg_required_here (& str, 8)) == FAIL)
3444 inst.error = BAD_ARGS;
3445 return;
3448 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
3450 inst.error = BAD_PC;
3451 return;
3454 end_of_line (str);
3457 /* ARM V6 strex (argument parse). */
3459 static void
3460 do_strex (char * str)
3462 int rd, rm, rn;
3464 /* Parse Rd, Rm,. */
3465 skip_whitespace (str);
3466 if ((rd = reg_required_here (& str, 12)) == FAIL
3467 || skip_past_comma (& str) == FAIL
3468 || (rm = reg_required_here (& str, 0)) == FAIL
3469 || skip_past_comma (& str) == FAIL)
3471 inst.error = BAD_ARGS;
3472 return;
3474 if (rd == REG_PC || rm == REG_PC)
3476 inst.error = BAD_PC;
3477 return;
3479 if (rd == rm)
3481 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
3482 return;
3485 /* Skip past '['. */
3486 if ((strlen (str) >= 1)
3487 && strncmp (str, "[", 1) == 0)
3488 str += 1;
3490 skip_whitespace (str);
3492 /* Parse Rn. */
3493 if ((rn = reg_required_here (& str, 16)) == FAIL)
3495 inst.error = BAD_ARGS;
3496 return;
3498 else if (rn == REG_PC)
3500 inst.error = BAD_PC;
3501 return;
3503 if (rd == rn)
3505 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
3506 return;
3508 skip_whitespace (str);
3510 /* Skip past ']'. */
3511 if ((strlen (str) >= 1)
3512 && strncmp (str, "]", 1) == 0)
3513 str += 1;
3515 end_of_line (str);
3518 /* KIND indicates what kind of shifts are accepted. */
3520 static int
3521 decode_shift (char ** str, int kind)
3523 const struct asm_shift_name * shift;
3524 char * p;
3525 char c;
3527 skip_whitespace (* str);
3529 for (p = * str; ISALPHA (* p); p ++)
3532 if (p == * str)
3534 inst.error = _("shift expression expected");
3535 return FAIL;
3538 c = * p;
3539 * p = '\0';
3540 shift = (const struct asm_shift_name *) hash_find (arm_shift_hsh, * str);
3541 * p = c;
3543 if (shift == NULL)
3545 inst.error = _("shift expression expected");
3546 return FAIL;
3549 assert (shift->properties->index == shift_properties[shift->properties->index].index);
3551 if (kind == SHIFT_LSL_OR_ASR_IMMEDIATE
3552 && shift->properties->index != SHIFT_LSL
3553 && shift->properties->index != SHIFT_ASR)
3555 inst.error = _("'LSL' or 'ASR' required");
3556 return FAIL;
3558 else if (kind == SHIFT_LSL_IMMEDIATE
3559 && shift->properties->index != SHIFT_LSL)
3561 inst.error = _("'LSL' required");
3562 return FAIL;
3564 else if (kind == SHIFT_ASR_IMMEDIATE
3565 && shift->properties->index != SHIFT_ASR)
3567 inst.error = _("'ASR' required");
3568 return FAIL;
3571 if (shift->properties->index == SHIFT_RRX)
3573 * str = p;
3574 inst.instruction |= shift->properties->bit_field;
3575 return SUCCESS;
3578 skip_whitespace (p);
3580 if (kind == NO_SHIFT_RESTRICT && reg_required_here (& p, 8) != FAIL)
3582 inst.instruction |= shift->properties->bit_field | SHIFT_BY_REG;
3583 * str = p;
3584 return SUCCESS;
3586 else if (! is_immediate_prefix (* p))
3588 inst.error = (NO_SHIFT_RESTRICT
3589 ? _("shift requires register or #expression")
3590 : _("shift requires #expression"));
3591 * str = p;
3592 return FAIL;
3595 inst.error = NULL;
3596 p ++;
3598 if (my_get_expression (& inst.reloc.exp, & p))
3599 return FAIL;
3601 /* Validate some simple #expressions. */
3602 if (inst.reloc.exp.X_op == O_constant)
3604 unsigned num = inst.reloc.exp.X_add_number;
3606 /* Reject operations greater than 32. */
3607 if (num > 32
3608 /* Reject a shift of 0 unless the mode allows it. */
3609 || (num == 0 && shift->properties->allows_0 == 0)
3610 /* Reject a shift of 32 unless the mode allows it. */
3611 || (num == 32 && shift->properties->allows_32 == 0)
3614 /* As a special case we allow a shift of zero for
3615 modes that do not support it to be recoded as an
3616 logical shift left of zero (ie nothing). We warn
3617 about this though. */
3618 if (num == 0)
3620 as_warn (_("shift of 0 ignored."));
3621 shift = & shift_names[0];
3622 assert (shift->properties->index == SHIFT_LSL);
3624 else
3626 inst.error = _("invalid immediate shift");
3627 return FAIL;
3631 /* Shifts of 32 are encoded as 0, for those shifts that
3632 support it. */
3633 if (num == 32)
3634 num = 0;
3636 inst.instruction |= (num << 7) | shift->properties->bit_field;
3638 else
3640 inst.reloc.type = BFD_RELOC_ARM_SHIFT_IMM;
3641 inst.reloc.pc_rel = 0;
3642 inst.instruction |= shift->properties->bit_field;
3645 * str = p;
3646 return SUCCESS;
3649 static void
3650 do_sat (char ** str, int bias)
3652 int rd, rm;
3653 expressionS expr;
3655 skip_whitespace (*str);
3657 /* Parse <Rd>, field. */
3658 if ((rd = reg_required_here (str, 12)) == FAIL
3659 || skip_past_comma (str) == FAIL)
3661 inst.error = BAD_ARGS;
3662 return;
3664 if (rd == REG_PC)
3666 inst.error = BAD_PC;
3667 return;
3670 /* Parse #<immed>, field. */
3671 if (is_immediate_prefix (**str))
3672 (*str)++;
3673 else
3675 inst.error = _("immediate expression expected");
3676 return;
3678 if (my_get_expression (&expr, str))
3680 inst.error = _("bad expression");
3681 return;
3683 if (expr.X_op != O_constant)
3685 inst.error = _("constant expression expected");
3686 return;
3688 if (expr.X_add_number + bias < 0
3689 || expr.X_add_number + bias > 31)
3691 inst.error = _("immediate value out of range");
3692 return;
3694 inst.instruction |= (expr.X_add_number + bias) << 16;
3695 if (skip_past_comma (str) == FAIL)
3697 inst.error = BAD_ARGS;
3698 return;
3701 /* Parse <Rm> field. */
3702 if ((rm = reg_required_here (str, 0)) == FAIL)
3704 inst.error = BAD_ARGS;
3705 return;
3707 if (rm == REG_PC)
3709 inst.error = BAD_PC;
3710 return;
3713 if (skip_past_comma (str) == SUCCESS)
3714 decode_shift (str, SHIFT_LSL_OR_ASR_IMMEDIATE);
3717 /* ARM V6 ssat (argument parse). */
3719 static void
3720 do_ssat (char * str)
3722 do_sat (&str, /*bias=*/-1);
3723 end_of_line (str);
3726 /* ARM V6 usat (argument parse). */
3728 static void
3729 do_usat (char * str)
3731 do_sat (&str, /*bias=*/0);
3732 end_of_line (str);
3735 static void
3736 do_sat16 (char ** str, int bias)
3738 int rd, rm;
3739 expressionS expr;
3741 skip_whitespace (*str);
3743 /* Parse the <Rd> field. */
3744 if ((rd = reg_required_here (str, 12)) == FAIL
3745 || skip_past_comma (str) == FAIL)
3747 inst.error = BAD_ARGS;
3748 return;
3750 if (rd == REG_PC)
3752 inst.error = BAD_PC;
3753 return;
3756 /* Parse #<immed>, field. */
3757 if (is_immediate_prefix (**str))
3758 (*str)++;
3759 else
3761 inst.error = _("immediate expression expected");
3762 return;
3764 if (my_get_expression (&expr, str))
3766 inst.error = _("bad expression");
3767 return;
3769 if (expr.X_op != O_constant)
3771 inst.error = _("constant expression expected");
3772 return;
3774 if (expr.X_add_number + bias < 0
3775 || expr.X_add_number + bias > 15)
3777 inst.error = _("immediate value out of range");
3778 return;
3780 inst.instruction |= (expr.X_add_number + bias) << 16;
3781 if (skip_past_comma (str) == FAIL)
3783 inst.error = BAD_ARGS;
3784 return;
3787 /* Parse <Rm> field. */
3788 if ((rm = reg_required_here (str, 0)) == FAIL)
3790 inst.error = BAD_ARGS;
3791 return;
3793 if (rm == REG_PC)
3795 inst.error = BAD_PC;
3796 return;
3800 /* ARM V6 ssat16 (argument parse). */
3802 static void
3803 do_ssat16 (char * str)
3805 do_sat16 (&str, /*bias=*/-1);
3806 end_of_line (str);
3809 static void
3810 do_usat16 (char * str)
3812 do_sat16 (&str, /*bias=*/0);
3813 end_of_line (str);
3816 static void
3817 do_cps_mode (char ** str)
3819 expressionS expr;
3821 skip_whitespace (*str);
3823 if (! is_immediate_prefix (**str))
3825 inst.error = _("immediate expression expected");
3826 return;
3829 (*str)++; /* Strip off the immediate signifier. */
3830 if (my_get_expression (&expr, str))
3832 inst.error = _("bad expression");
3833 return;
3836 if (expr.X_op != O_constant)
3838 inst.error = _("constant expression expected");
3839 return;
3842 /* The mode is a 5 bit field. Valid values are 0-31. */
3843 if (((unsigned) expr.X_add_number) > 31
3844 || (inst.reloc.exp.X_add_number) < 0)
3846 inst.error = _("invalid constant");
3847 return;
3850 inst.instruction |= expr.X_add_number;
3853 /* ARM V6 srs (argument parse). */
3855 static void
3856 do_srs (char * str)
3858 char *exclam;
3859 skip_whitespace (str);
3860 exclam = strchr (str, '!');
3861 if (exclam)
3862 *exclam = '\0';
3863 do_cps_mode (&str);
3864 if (exclam)
3865 *exclam = '!';
3866 if (*str == '!')
3868 inst.instruction |= WRITE_BACK;
3869 str++;
3871 end_of_line (str);
3874 /* ARM V6 SMMUL (argument parse). */
3876 static void
3877 do_smmul (char * str)
3879 int rd, rm, rs;
3881 skip_whitespace (str);
3882 if ((rd = reg_required_here (&str, 16)) == FAIL
3883 || skip_past_comma (&str) == FAIL
3884 || (rm = reg_required_here (&str, 0)) == FAIL
3885 || skip_past_comma (&str) == FAIL
3886 || (rs = reg_required_here (&str, 8)) == FAIL)
3888 inst.error = BAD_ARGS;
3889 return;
3892 if ( rd == REG_PC
3893 || rm == REG_PC
3894 || rs == REG_PC)
3896 inst.error = BAD_PC;
3897 return;
3900 end_of_line (str);
3903 /* ARM V6 SMLALD (argument parse). */
3905 static void
3906 do_smlald (char * str)
3908 int rdlo, rdhi, rm, rs;
3910 skip_whitespace (str);
3911 if ((rdlo = reg_required_here (&str, 12)) == FAIL
3912 || skip_past_comma (&str) == FAIL
3913 || (rdhi = reg_required_here (&str, 16)) == FAIL
3914 || skip_past_comma (&str) == FAIL
3915 || (rm = reg_required_here (&str, 0)) == FAIL
3916 || skip_past_comma (&str) == FAIL
3917 || (rs = reg_required_here (&str, 8)) == FAIL)
3919 inst.error = BAD_ARGS;
3920 return;
3923 if ( rdlo == REG_PC
3924 || rdhi == REG_PC
3925 || rm == REG_PC
3926 || rs == REG_PC)
3928 inst.error = BAD_PC;
3929 return;
3932 end_of_line (str);
3935 /* ARM V6 SMLAD (argument parse). Signed multiply accumulate dual.
3936 smlad{x}{<cond>} Rd, Rm, Rs, Rn */
3938 static void
3939 do_smlad (char * str)
3941 int rd, rm, rs, rn;
3943 skip_whitespace (str);
3944 if ((rd = reg_required_here (&str, 16)) == FAIL
3945 || skip_past_comma (&str) == FAIL
3946 || (rm = reg_required_here (&str, 0)) == FAIL
3947 || skip_past_comma (&str) == FAIL
3948 || (rs = reg_required_here (&str, 8)) == FAIL
3949 || skip_past_comma (&str) == FAIL
3950 || (rn = reg_required_here (&str, 12)) == FAIL)
3952 inst.error = BAD_ARGS;
3953 return;
3956 if ( rd == REG_PC
3957 || rn == REG_PC
3958 || rs == REG_PC
3959 || rm == REG_PC)
3961 inst.error = BAD_PC;
3962 return;
3965 end_of_line (str);
3968 /* Returns true if the endian-specifier indicates big-endianness. */
3970 static int
3971 do_endian_specifier (char * str)
3973 int big_endian = 0;
3975 skip_whitespace (str);
3976 if (strlen (str) < 2)
3977 inst.error = _("missing endian specifier");
3978 else if (strncasecmp (str, "BE", 2) == 0)
3980 str += 2;
3981 big_endian = 1;
3983 else if (strncasecmp (str, "LE", 2) == 0)
3984 str += 2;
3985 else
3986 inst.error = _("valid endian specifiers are be or le");
3988 end_of_line (str);
3990 return big_endian;
3993 /* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
3994 preserving the other bits.
3996 setend <endian_specifier>, where <endian_specifier> is either
3997 BE or LE. */
3999 static void
4000 do_setend (char * str)
4002 if (do_endian_specifier (str))
4003 inst.instruction |= 0x200;
4006 /* ARM V6 SXTH.
4008 SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
4009 Condition defaults to COND_ALWAYS.
4010 Error if any register uses R15. */
4012 static void
4013 do_sxth (char * str)
4015 int rd, rm;
4016 expressionS expr;
4017 int rotation_clear_mask = 0xfffff3ff;
4018 int rotation_eight_mask = 0x00000400;
4019 int rotation_sixteen_mask = 0x00000800;
4020 int rotation_twenty_four_mask = 0x00000c00;
4022 skip_whitespace (str);
4023 if ((rd = reg_required_here (&str, 12)) == FAIL
4024 || skip_past_comma (&str) == FAIL
4025 || (rm = reg_required_here (&str, 0)) == FAIL)
4027 inst.error = BAD_ARGS;
4028 return;
4031 else if (rd == REG_PC || rm == REG_PC)
4033 inst.error = BAD_PC;
4034 return;
4037 /* Zero out the rotation field. */
4038 inst.instruction &= rotation_clear_mask;
4040 /* Check for lack of optional rotation field. */
4041 if (skip_past_comma (&str) == FAIL)
4043 end_of_line (str);
4044 return;
4047 /* Move past 'ROR'. */
4048 skip_whitespace (str);
4049 if (strncasecmp (str, "ROR", 3) == 0)
4050 str += 3;
4051 else
4053 inst.error = _("missing rotation field after comma");
4054 return;
4057 /* Get the immediate constant. */
4058 skip_whitespace (str);
4059 if (is_immediate_prefix (* str))
4060 str++;
4061 else
4063 inst.error = _("immediate expression expected");
4064 return;
4067 if (my_get_expression (&expr, &str))
4069 inst.error = _("bad expression");
4070 return;
4073 if (expr.X_op != O_constant)
4075 inst.error = _("constant expression expected");
4076 return;
4079 switch (expr.X_add_number)
4081 case 0:
4082 /* Rotation field has already been zeroed. */
4083 break;
4084 case 8:
4085 inst.instruction |= rotation_eight_mask;
4086 break;
4088 case 16:
4089 inst.instruction |= rotation_sixteen_mask;
4090 break;
4092 case 24:
4093 inst.instruction |= rotation_twenty_four_mask;
4094 break;
4096 default:
4097 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
4098 break;
4101 end_of_line (str);
4104 /* ARM V6 SXTAH extracts a 16-bit value from a register, sign
4105 extends it to 32-bits, and adds the result to a value in another
4106 register. You can specify a rotation by 0, 8, 16, or 24 bits
4107 before extracting the 16-bit value.
4108 SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
4109 Condition defaults to COND_ALWAYS.
4110 Error if any register uses R15. */
4112 static void
4113 do_sxtah (char * str)
4115 int rd, rn, rm;
4116 expressionS expr;
4117 int rotation_clear_mask = 0xfffff3ff;
4118 int rotation_eight_mask = 0x00000400;
4119 int rotation_sixteen_mask = 0x00000800;
4120 int rotation_twenty_four_mask = 0x00000c00;
4122 skip_whitespace (str);
4123 if ((rd = reg_required_here (&str, 12)) == FAIL
4124 || skip_past_comma (&str) == FAIL
4125 || (rn = reg_required_here (&str, 16)) == FAIL
4126 || skip_past_comma (&str) == FAIL
4127 || (rm = reg_required_here (&str, 0)) == FAIL)
4129 inst.error = BAD_ARGS;
4130 return;
4133 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
4135 inst.error = BAD_PC;
4136 return;
4139 /* Zero out the rotation field. */
4140 inst.instruction &= rotation_clear_mask;
4142 /* Check for lack of optional rotation field. */
4143 if (skip_past_comma (&str) == FAIL)
4145 end_of_line (str);
4146 return;
4149 /* Move past 'ROR'. */
4150 skip_whitespace (str);
4151 if (strncasecmp (str, "ROR", 3) == 0)
4152 str += 3;
4153 else
4155 inst.error = _("missing rotation field after comma");
4156 return;
4159 /* Get the immediate constant. */
4160 skip_whitespace (str);
4161 if (is_immediate_prefix (* str))
4162 str++;
4163 else
4165 inst.error = _("immediate expression expected");
4166 return;
4169 if (my_get_expression (&expr, &str))
4171 inst.error = _("bad expression");
4172 return;
4175 if (expr.X_op != O_constant)
4177 inst.error = _("constant expression expected");
4178 return;
4181 switch (expr.X_add_number)
4183 case 0:
4184 /* Rotation field has already been zeroed. */
4185 break;
4187 case 8:
4188 inst.instruction |= rotation_eight_mask;
4189 break;
4191 case 16:
4192 inst.instruction |= rotation_sixteen_mask;
4193 break;
4195 case 24:
4196 inst.instruction |= rotation_twenty_four_mask;
4197 break;
4199 default:
4200 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
4201 break;
4204 end_of_line (str);
4208 /* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
4209 word at the specified address and the following word
4210 respectively.
4211 Unconditionally executed.
4212 Error if Rn is R15. */
4214 static void
4215 do_rfe (char * str)
4217 int rn;
4219 skip_whitespace (str);
4221 if ((rn = reg_required_here (&str, 16)) == FAIL)
4222 return;
4224 if (rn == REG_PC)
4226 inst.error = BAD_PC;
4227 return;
4230 skip_whitespace (str);
4232 if (*str == '!')
4234 inst.instruction |= WRITE_BACK;
4235 str++;
4237 end_of_line (str);
4240 /* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
4241 register (argument parse).
4242 REV{<cond>} Rd, Rm.
4243 Condition defaults to COND_ALWAYS.
4244 Error if Rd or Rm are R15. */
4246 static void
4247 do_rev (char * str)
4249 int rd, rm;
4251 skip_whitespace (str);
4253 if ((rd = reg_required_here (&str, 12)) == FAIL
4254 || skip_past_comma (&str) == FAIL
4255 || (rm = reg_required_here (&str, 0)) == FAIL)
4256 inst.error = BAD_ARGS;
4258 else if (rd == REG_PC || rm == REG_PC)
4259 inst.error = BAD_PC;
4261 else
4262 end_of_line (str);
4265 /* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
4266 QADD16{<cond>} <Rd>, <Rn>, <Rm>
4267 Condition defaults to COND_ALWAYS.
4268 Error if Rd, Rn or Rm are R15. */
4270 static void
4271 do_qadd16 (char * str)
4273 int rd, rm, rn;
4275 skip_whitespace (str);
4277 if ((rd = reg_required_here (&str, 12)) == FAIL
4278 || skip_past_comma (&str) == FAIL
4279 || (rn = reg_required_here (&str, 16)) == FAIL
4280 || skip_past_comma (&str) == FAIL
4281 || (rm = reg_required_here (&str, 0)) == FAIL)
4282 inst.error = BAD_ARGS;
4284 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
4285 inst.error = BAD_PC;
4287 else
4288 end_of_line (str);
4291 static void
4292 do_pkh_core (char * str, int shift)
4294 int rd, rn, rm;
4296 skip_whitespace (str);
4297 if (((rd = reg_required_here (&str, 12)) == FAIL)
4298 || (skip_past_comma (&str) == FAIL)
4299 || ((rn = reg_required_here (&str, 16)) == FAIL)
4300 || (skip_past_comma (&str) == FAIL)
4301 || ((rm = reg_required_here (&str, 0)) == FAIL))
4303 inst.error = BAD_ARGS;
4304 return;
4307 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
4309 inst.error = BAD_PC;
4310 return;
4313 /* Check for optional shift immediate constant. */
4314 if (skip_past_comma (&str) == FAIL)
4316 if (shift == SHIFT_ASR_IMMEDIATE)
4318 /* If the shift specifier is ommited, turn the instruction
4319 into pkhbt rd, rm, rn. First, switch the instruction
4320 code, and clear the rn and rm fields. */
4321 inst.instruction &= 0xfff0f010;
4322 /* Now, re-encode the registers. */
4323 inst.instruction |= (rm << 16) | rn;
4325 return;
4328 decode_shift (&str, shift);
4331 /* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
4332 PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
4333 Condition defaults to COND_ALWAYS.
4334 Error if Rd, Rn or Rm are R15. */
4336 static void
4337 do_pkhbt (char * str)
4339 do_pkh_core (str, SHIFT_LSL_IMMEDIATE);
4342 /* ARM V6 PKHTB (Argument Parse). */
4344 static void
4345 do_pkhtb (char * str)
4347 do_pkh_core (str, SHIFT_ASR_IMMEDIATE);
4350 /* ARM V6 Load Register Exclusive instruction (argument parse).
4351 LDREX{,B,D,H}{<cond>} <Rd, [<Rn>]
4352 Condition defaults to COND_ALWAYS.
4353 Error if Rd or Rn are R15.
4354 See ARMARMv6 A4.1.27: LDREX. */
4356 static void
4357 do_ldrex (char * str)
4359 int rd, rn;
4361 skip_whitespace (str);
4363 /* Parse Rd. */
4364 if (((rd = reg_required_here (&str, 12)) == FAIL)
4365 || (skip_past_comma (&str) == FAIL))
4367 inst.error = BAD_ARGS;
4368 return;
4370 else if (rd == REG_PC)
4372 inst.error = BAD_PC;
4373 return;
4375 skip_whitespace (str);
4377 /* Skip past '['. */
4378 if ((strlen (str) >= 1)
4379 &&strncmp (str, "[", 1) == 0)
4380 str += 1;
4381 skip_whitespace (str);
4383 /* Parse Rn. */
4384 if ((rn = reg_required_here (&str, 16)) == FAIL)
4386 inst.error = BAD_ARGS;
4387 return;
4389 else if (rn == REG_PC)
4391 inst.error = BAD_PC;
4392 return;
4394 skip_whitespace (str);
4396 /* Skip past ']'. */
4397 if ((strlen (str) >= 1)
4398 && strncmp (str, "]", 1) == 0)
4399 str += 1;
4401 end_of_line (str);
4404 /* ARM V6 change processor state instruction (argument parse)
4405 CPS, CPSIE, CSPID . */
4407 static void
4408 do_cps (char * str)
4410 do_cps_mode (&str);
4411 end_of_line (str);
4414 static void
4415 do_cps_flags (char ** str, int thumb_p)
4417 struct cps_flag
4419 char character;
4420 unsigned long arm_value;
4421 unsigned long thumb_value;
4423 static struct cps_flag flag_table[] =
4425 {'a', 0x100, 0x4 },
4426 {'i', 0x080, 0x2 },
4427 {'f', 0x040, 0x1 }
4430 int saw_a_flag = 0;
4432 skip_whitespace (*str);
4434 /* Get the a, f and i flags. */
4435 while (**str && **str != ',')
4437 struct cps_flag *p;
4438 struct cps_flag *q = flag_table + sizeof (flag_table)/sizeof (*p);
4440 for (p = flag_table; p < q; ++p)
4441 if (strncasecmp (*str, &p->character, 1) == 0)
4443 inst.instruction |= (thumb_p ? p->thumb_value : p->arm_value);
4444 saw_a_flag = 1;
4445 break;
4447 if (p == q)
4449 inst.error = _("unrecognized flag");
4450 return;
4452 (*str)++;
4455 if (!saw_a_flag)
4456 inst.error = _("no 'a', 'i', or 'f' flags for 'cps'");
4459 static void
4460 do_cpsi (char * str)
4462 do_cps_flags (&str, /*thumb_p=*/0);
4464 if (skip_past_comma (&str) == SUCCESS)
4466 skip_whitespace (str);
4467 do_cps_mode (&str);
4469 end_of_line (str);
4472 /* ARM V6T2 bitfield manipulation instructions. */
4474 static int
4475 five_bit_unsigned_immediate (char **str)
4477 expressionS expr;
4479 skip_whitespace (*str);
4480 if (!is_immediate_prefix (**str))
4482 inst.error = _("immediate expression expected");
4483 return -1;
4485 (*str)++;
4486 if (my_get_expression (&expr, str))
4488 inst.error = _("bad expression");
4489 return -1;
4491 if (expr.X_op != O_constant)
4493 inst.error = _("constant expression expected");
4494 return -1;
4496 if (expr.X_add_number < 0 || expr.X_add_number > 32)
4498 inst.error = _("immediate value out of range");
4499 return -1;
4502 return expr.X_add_number;
4505 static void
4506 bfci_lsb_and_width (char *str)
4508 int lsb, width;
4510 if ((lsb = five_bit_unsigned_immediate (&str)) == -1)
4511 return;
4513 if (skip_past_comma (&str) == FAIL)
4515 inst.error = BAD_ARGS;
4516 return;
4518 if ((width = five_bit_unsigned_immediate (&str)) == -1)
4519 return;
4521 end_of_line (str);
4523 if (width == 0 || lsb == 32)
4525 inst.error = _("immediate value out of range");
4526 return;
4528 else if (width + lsb > 32)
4530 inst.error = _("bit-field extends past end of register");
4531 return;
4534 /* Convert to LSB/MSB and write to register. */
4535 inst.instruction |= lsb << 7;
4536 inst.instruction |= (width + lsb - 1) << 16;
4539 static void
4540 do_bfc (char *str)
4542 int rd;
4544 /* Rd. */
4545 skip_whitespace (str);
4546 if (((rd = reg_required_here (&str, 12)) == FAIL)
4547 || (skip_past_comma (&str) == FAIL))
4549 inst.error = BAD_ARGS;
4550 return;
4552 else if (rd == REG_PC)
4554 inst.error = BAD_PC;
4555 return;
4558 bfci_lsb_and_width (str);
4561 static void
4562 do_bfi (char *str)
4564 int rd, rm;
4566 /* Rd. */
4567 skip_whitespace (str);
4568 if (((rd = reg_required_here (&str, 12)) == FAIL)
4569 || (skip_past_comma (&str) == FAIL))
4571 inst.error = BAD_ARGS;
4572 return;
4574 else if (rd == REG_PC)
4576 inst.error = BAD_PC;
4577 return;
4580 /* Rm. Accept #0 in this position as an alternative syntax for bfc. */
4581 skip_whitespace (str);
4582 if (is_immediate_prefix (*str))
4584 expressionS expr;
4585 str++;
4586 if (my_get_expression (&expr, &str))
4588 inst.error = _("bad expression");
4589 return;
4591 if (expr.X_op != O_constant)
4593 inst.error = _("constant expression expected");
4594 return;
4596 if (expr.X_add_number != 0)
4598 inst.error = _("immediate value out of range");
4599 return;
4601 inst.instruction |= 0x0000000f; /* Rm = PC -> bfc, not bfi. */
4603 else
4605 if ((rm = reg_required_here (&str, 0)) == FAIL)
4607 inst.error = BAD_ARGS;
4608 return;
4610 else if (rm == REG_PC)
4612 inst.error = BAD_PC;
4613 return;
4616 if (skip_past_comma (&str) == FAIL)
4618 inst.error = BAD_ARGS;
4619 return;
4622 bfci_lsb_and_width (str);
4625 static void
4626 do_bfx (char *str)
4628 int lsb, width;
4630 /* Rd. */
4631 skip_whitespace (str);
4632 if (reg_required_here (&str, 12) == FAIL
4633 || skip_past_comma (&str) == FAIL)
4635 inst.error = BAD_ARGS;
4636 return;
4639 /* Rm. */
4640 skip_whitespace (str);
4641 if (reg_required_here (&str, 0) == FAIL
4642 || skip_past_comma (&str) == FAIL)
4644 inst.error = BAD_ARGS;
4645 return;
4648 if ((lsb = five_bit_unsigned_immediate (&str)) == -1)
4649 return;
4651 if (skip_past_comma (&str) == FAIL)
4653 inst.error = BAD_ARGS;
4654 return;
4656 if ((width = five_bit_unsigned_immediate (&str)) == -1)
4657 return;
4659 end_of_line (str);
4661 if (width == 0 || lsb == 32)
4663 inst.error = _("immediate value out of range");
4664 return;
4666 else if (width + lsb > 32)
4668 inst.error = _("bit-field extends past end of register");
4669 return;
4672 inst.instruction |= lsb << 7;
4673 inst.instruction |= (width - 1) << 16;
4676 static void
4677 do_rbit (char *str)
4679 /* Rd. */
4680 skip_whitespace (str);
4681 if (reg_required_here (&str, 12) == FAIL
4682 || skip_past_comma (&str) == FAIL)
4684 inst.error = BAD_ARGS;
4685 return;
4688 /* Rm. */
4689 skip_whitespace (str);
4690 if (reg_required_here (&str, 0) == FAIL)
4692 inst.error = BAD_ARGS;
4693 return;
4696 end_of_line (str);
4699 /* ARM V6T2 16-bit immediate register load: MOV[WT]{cond} Rd, #<imm16>. */
4700 static void
4701 do_mov16 (char *str)
4703 int rd;
4704 expressionS expr;
4706 /* Rd. */
4707 skip_whitespace (str);
4708 if (((rd = reg_required_here (&str, 12)) == FAIL)
4709 || (skip_past_comma (&str) == FAIL))
4711 inst.error = BAD_ARGS;
4712 return;
4714 else if (rd == REG_PC)
4716 inst.error = BAD_PC;
4717 return;
4720 /* Imm16. */
4721 skip_whitespace (str);
4722 if (!is_immediate_prefix (*str))
4724 inst.error = _("immediate expression expected");
4725 return;
4727 str++;
4728 if (my_get_expression (&expr, &str))
4730 inst.error = _("bad expression");
4731 return;
4733 if (expr.X_op != O_constant)
4735 inst.error = _("constant expression expected");
4736 return;
4738 if (expr.X_add_number < 0 || expr.X_add_number > 65535)
4740 inst.error = _("immediate value out of range");
4741 return;
4744 end_of_line (str);
4746 /* The value is in two pieces: 0:11, 16:19. */
4747 inst.instruction |= (expr.X_add_number & 0x00000fff);
4748 inst.instruction |= (expr.X_add_number & 0x0000f000) << 4;
4752 /* THUMB V5 breakpoint instruction (argument parse)
4753 BKPT <immed_8>. */
4755 static void
4756 do_t_bkpt (char * str)
4758 expressionS expr;
4759 unsigned long number;
4761 skip_whitespace (str);
4763 /* Allow optional leading '#'. */
4764 if (is_immediate_prefix (*str))
4765 str ++;
4767 memset (& expr, '\0', sizeof (expr));
4768 if (my_get_expression (& expr, & str)
4769 || (expr.X_op != O_constant
4770 /* As a convenience we allow 'bkpt' without an operand. */
4771 && expr.X_op != O_absent))
4773 inst.error = _("bad expression");
4774 return;
4777 number = expr.X_add_number;
4779 /* Check it fits an 8 bit unsigned. */
4780 if (number != (number & 0xff))
4782 inst.error = _("immediate value out of range");
4783 return;
4786 inst.instruction |= number;
4788 end_of_line (str);
4791 #ifdef OBJ_ELF
4792 static bfd_reloc_code_real_type
4793 arm_parse_reloc (void)
4795 char id [16];
4796 char * ip;
4797 unsigned int i;
4798 static struct
4800 char * str;
4801 int len;
4802 bfd_reloc_code_real_type reloc;
4804 reloc_map[] =
4806 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
4807 MAP ("(got)", BFD_RELOC_ARM_GOT32),
4808 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF),
4809 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
4810 branch instructions generated by GCC for PLT relocs. */
4811 MAP ("(plt)", BFD_RELOC_ARM_PLT32),
4812 MAP ("(target1)", BFD_RELOC_ARM_TARGET1),
4813 MAP ("(sbrel)", BFD_RELOC_ARM_SBREL32),
4814 MAP ("(target2)", BFD_RELOC_ARM_TARGET2),
4815 MAP ("(tlsgd)", BFD_RELOC_ARM_TLS_GD32),
4816 MAP ("(tlsldm)", BFD_RELOC_ARM_TLS_LDM32),
4817 MAP ("(tlsldo)", BFD_RELOC_ARM_TLS_LDO32),
4818 MAP ("(gottpoff)", BFD_RELOC_ARM_TLS_IE32),
4819 MAP ("(tpoff)", BFD_RELOC_ARM_TLS_LE32),
4820 { NULL, 0, BFD_RELOC_UNUSED }
4821 #undef MAP
4824 for (i = 0, ip = input_line_pointer;
4825 i < sizeof (id) && (ISALNUM (*ip) || ISPUNCT (*ip));
4826 i++, ip++)
4827 id[i] = TOLOWER (*ip);
4829 for (i = 0; reloc_map[i].str; i++)
4830 if (strncmp (id, reloc_map[i].str, reloc_map[i].len) == 0)
4831 break;
4833 input_line_pointer += reloc_map[i].len;
4835 return reloc_map[i].reloc;
4837 #endif
4839 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
4840 Expects inst.instruction is set for BLX(1).
4841 Note: this is cloned from do_branch, and the reloc changed to be a
4842 new one that can cope with setting one extra bit (the H bit). */
4844 static void
4845 do_branch25 (char * str)
4847 if (my_get_expression (& inst.reloc.exp, & str))
4848 return;
4850 #ifdef OBJ_ELF
4852 char * save_in;
4854 /* ScottB: February 5, 1998 */
4855 /* Check to see of PLT32 reloc required for the instruction. */
4857 /* arm_parse_reloc() works on input_line_pointer.
4858 We actually want to parse the operands to the branch instruction
4859 passed in 'str'. Save the input pointer and restore it later. */
4860 save_in = input_line_pointer;
4861 input_line_pointer = str;
4863 if (inst.reloc.exp.X_op == O_symbol
4864 && *str == '('
4865 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
4867 inst.reloc.type = BFD_RELOC_ARM_PLT32;
4868 inst.reloc.pc_rel = 0;
4869 /* Modify str to point to after parsed operands, otherwise
4870 end_of_line() will complain about the (PLT) left in str. */
4871 str = input_line_pointer;
4873 else
4875 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
4876 inst.reloc.pc_rel = 1;
4879 input_line_pointer = save_in;
4881 #else
4882 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
4883 inst.reloc.pc_rel = 1;
4884 #endif /* OBJ_ELF */
4886 end_of_line (str);
4889 /* ARM V5 branch-link-exchange instruction (argument parse)
4890 BLX <target_addr> ie BLX(1)
4891 BLX{<condition>} <Rm> ie BLX(2)
4892 Unfortunately, there are two different opcodes for this mnemonic.
4893 So, the insns[].value is not used, and the code here zaps values
4894 into inst.instruction.
4895 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
4897 static void
4898 do_blx (char * str)
4900 char * mystr = str;
4901 int rm;
4903 skip_whitespace (mystr);
4904 rm = reg_required_here (& mystr, 0);
4906 /* The above may set inst.error. Ignore his opinion. */
4907 inst.error = 0;
4909 if (rm != FAIL)
4911 /* Arg is a register.
4912 Use the condition code our caller put in inst.instruction.
4913 Pass ourselves off as a BX with a funny opcode. */
4914 inst.instruction |= 0x012fff30;
4915 do_bx (str);
4917 else
4919 /* This must be is BLX <target address>, no condition allowed. */
4920 if (inst.instruction != COND_ALWAYS)
4922 inst.error = BAD_COND;
4923 return;
4926 inst.instruction = 0xfafffffe;
4928 /* Process like a B/BL, but with a different reloc.
4929 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
4930 do_branch25 (str);
4934 /* ARM V5 Thumb BLX (argument parse)
4935 BLX <target_addr> which is BLX(1)
4936 BLX <Rm> which is BLX(2)
4937 Unfortunately, there are two different opcodes for this mnemonic.
4938 So, the tinsns[].value is not used, and the code here zaps values
4939 into inst.instruction. */
4941 static void
4942 do_t_blx (char * str)
4944 char * mystr = str;
4945 int rm;
4947 skip_whitespace (mystr);
4948 inst.instruction = 0x4780;
4950 /* Note that this call is to the ARM register recognizer. BLX(2)
4951 uses the ARM register space, not the Thumb one, so a call to
4952 thumb_reg() would be wrong. */
4953 rm = reg_required_here (& mystr, 3);
4954 inst.error = 0;
4956 if (rm != FAIL)
4958 /* It's BLX(2). The .instruction was zapped with rm & is final. */
4959 inst.size = 2;
4961 else
4963 /* No ARM register. This must be BLX(1). Change the .instruction. */
4964 inst.instruction = 0xf7ffeffe;
4965 inst.size = 4;
4967 if (my_get_expression (& inst.reloc.exp, & mystr))
4968 return;
4970 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BLX;
4971 inst.reloc.pc_rel = 1;
4974 end_of_line (mystr);
4977 /* ARM V5 breakpoint instruction (argument parse)
4978 BKPT <16 bit unsigned immediate>
4979 Instruction is not conditional.
4980 The bit pattern given in insns[] has the COND_ALWAYS condition,
4981 and it is an error if the caller tried to override that. */
4983 static void
4984 do_bkpt (char * str)
4986 expressionS expr;
4987 unsigned long number;
4989 skip_whitespace (str);
4991 /* Allow optional leading '#'. */
4992 if (is_immediate_prefix (* str))
4993 str++;
4995 memset (& expr, '\0', sizeof (expr));
4997 if (my_get_expression (& expr, & str)
4998 || (expr.X_op != O_constant
4999 /* As a convenience we allow 'bkpt' without an operand. */
5000 && expr.X_op != O_absent))
5002 inst.error = _("bad expression");
5003 return;
5006 number = expr.X_add_number;
5008 /* Check it fits a 16 bit unsigned. */
5009 if (number != (number & 0xffff))
5011 inst.error = _("immediate value out of range");
5012 return;
5015 /* Top 12 of 16 bits to bits 19:8. */
5016 inst.instruction |= (number & 0xfff0) << 4;
5018 /* Bottom 4 of 16 bits to bits 3:0. */
5019 inst.instruction |= number & 0xf;
5021 end_of_line (str);
5024 /* THUMB CPS instruction (argument parse). */
5026 static void
5027 do_t_cps (char * str)
5029 do_cps_flags (&str, /*thumb_p=*/1);
5030 end_of_line (str);
5033 /* Parse and validate that a register is of the right form, this saves
5034 repeated checking of this information in many similar cases.
5035 Unlike the 32-bit case we do not insert the register into the opcode
5036 here, since the position is often unknown until the full instruction
5037 has been parsed. */
5039 static int
5040 thumb_reg (char ** strp, int hi_lo)
5042 int reg;
5044 if ((reg = reg_required_here (strp, -1)) == FAIL)
5045 return FAIL;
5047 switch (hi_lo)
5049 case THUMB_REG_LO:
5050 if (reg > 7)
5052 inst.error = _("lo register required");
5053 return FAIL;
5055 break;
5057 case THUMB_REG_HI:
5058 if (reg < 8)
5060 inst.error = _("hi register required");
5061 return FAIL;
5063 break;
5065 default:
5066 break;
5069 return reg;
5072 static void
5073 thumb_mov_compare (char * str, int move)
5075 int Rd, Rs = FAIL;
5077 skip_whitespace (str);
5079 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
5080 || skip_past_comma (&str) == FAIL)
5082 if (! inst.error)
5083 inst.error = BAD_ARGS;
5084 return;
5087 if (move != THUMB_CPY && is_immediate_prefix (*str))
5089 str++;
5090 if (my_get_expression (&inst.reloc.exp, &str))
5091 return;
5093 else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
5094 return;
5096 if (Rs != FAIL)
5098 if (move != THUMB_CPY && Rs < 8 && Rd < 8)
5100 if (move == THUMB_MOVE)
5101 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
5102 since a MOV instruction produces unpredictable results. */
5103 inst.instruction = T_OPCODE_ADD_I3;
5104 else
5105 inst.instruction = T_OPCODE_CMP_LR;
5106 inst.instruction |= Rd | (Rs << 3);
5108 else
5110 if (move == THUMB_MOVE)
5111 inst.instruction = T_OPCODE_MOV_HR;
5112 else if (move != THUMB_CPY)
5113 inst.instruction = T_OPCODE_CMP_HR;
5115 if (Rd > 7)
5116 inst.instruction |= THUMB_H1;
5118 if (Rs > 7)
5119 inst.instruction |= THUMB_H2;
5121 inst.instruction |= (Rd & 7) | ((Rs & 7) << 3);
5124 else
5126 if (Rd > 7)
5128 inst.error = _("only lo regs allowed with immediate");
5129 return;
5132 if (move == THUMB_MOVE)
5133 inst.instruction = T_OPCODE_MOV_I8;
5134 else
5135 inst.instruction = T_OPCODE_CMP_I8;
5137 inst.instruction |= Rd << 8;
5139 if (inst.reloc.exp.X_op != O_constant)
5140 inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
5141 else
5143 unsigned value = inst.reloc.exp.X_add_number;
5145 if (value > 255)
5147 inst.error = _("invalid immediate");
5148 return;
5151 inst.instruction |= value;
5155 end_of_line (str);
5158 /* THUMB CPY instruction (argument parse). */
5160 static void
5161 do_t_cpy (char * str)
5163 thumb_mov_compare (str, THUMB_CPY);
5166 /* THUMB SETEND instruction (argument parse). */
5168 static void
5169 do_t_setend (char * str)
5171 if (do_endian_specifier (str))
5172 inst.instruction |= 0x8;
5175 /* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
5177 static unsigned long
5178 check_iwmmxt_insn (char * str,
5179 enum iwmmxt_insn_type insn_type,
5180 int immediate_size)
5182 int reg = 0;
5183 const char * inst_error;
5184 expressionS expr;
5185 unsigned long number;
5187 inst_error = inst.error;
5188 if (!inst.error)
5189 inst.error = BAD_ARGS;
5190 skip_whitespace (str);
5192 switch (insn_type)
5194 case check_rd:
5195 if ((reg = reg_required_here (&str, 12)) == FAIL)
5196 return FAIL;
5197 break;
5199 case check_wr:
5200 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR)) == FAIL)
5201 return FAIL;
5202 break;
5204 case check_wrwr:
5205 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5206 || skip_past_comma (&str) == FAIL
5207 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
5208 return FAIL;
5209 break;
5211 case check_wrwrwr:
5212 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5213 || skip_past_comma (&str) == FAIL
5214 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5215 || skip_past_comma (&str) == FAIL
5216 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
5217 return FAIL;
5218 break;
5220 case check_wrwrwcg:
5221 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5222 || skip_past_comma (&str) == FAIL
5223 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5224 || skip_past_comma (&str) == FAIL
5225 || wreg_required_here (&str, 0, IWMMXT_REG_WCG) == FAIL))
5226 return FAIL;
5227 break;
5229 case check_tbcst:
5230 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5231 || skip_past_comma (&str) == FAIL
5232 || reg_required_here (&str, 12) == FAIL))
5233 return FAIL;
5234 break;
5236 case check_tmovmsk:
5237 if ((reg_required_here (&str, 12) == FAIL
5238 || skip_past_comma (&str) == FAIL
5239 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
5240 return FAIL;
5241 break;
5243 case check_tmia:
5244 if ((wreg_required_here (&str, 5, IWMMXT_REG_WR) == FAIL
5245 || skip_past_comma (&str) == FAIL
5246 || reg_required_here (&str, 0) == FAIL
5247 || skip_past_comma (&str) == FAIL
5248 || reg_required_here (&str, 12) == FAIL))
5249 return FAIL;
5250 break;
5252 case check_tmcrr:
5253 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
5254 || skip_past_comma (&str) == FAIL
5255 || reg_required_here (&str, 12) == FAIL
5256 || skip_past_comma (&str) == FAIL
5257 || reg_required_here (&str, 16) == FAIL))
5258 return FAIL;
5259 break;
5261 case check_tmrrc:
5262 if ((reg_required_here (&str, 12) == FAIL
5263 || skip_past_comma (&str) == FAIL
5264 || reg_required_here (&str, 16) == FAIL
5265 || skip_past_comma (&str) == FAIL
5266 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
5267 return FAIL;
5268 break;
5270 case check_tmcr:
5271 if ((wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL
5272 || skip_past_comma (&str) == FAIL
5273 || reg_required_here (&str, 12) == FAIL))
5274 return FAIL;
5275 break;
5277 case check_tmrc:
5278 if ((reg_required_here (&str, 12) == FAIL
5279 || skip_past_comma (&str) == FAIL
5280 || wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL))
5281 return FAIL;
5282 break;
5284 case check_tinsr:
5285 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5286 || skip_past_comma (&str) == FAIL
5287 || reg_required_here (&str, 12) == FAIL
5288 || skip_past_comma (&str) == FAIL))
5289 return FAIL;
5290 break;
5292 case check_textrc:
5293 if ((reg_required_here (&str, 12) == FAIL
5294 || skip_past_comma (&str) == FAIL))
5295 return FAIL;
5296 break;
5298 case check_waligni:
5299 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5300 || skip_past_comma (&str) == FAIL
5301 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5302 || skip_past_comma (&str) == FAIL
5303 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
5304 || skip_past_comma (&str) == FAIL))
5305 return FAIL;
5306 break;
5308 case check_textrm:
5309 if ((reg_required_here (&str, 12) == FAIL
5310 || skip_past_comma (&str) == FAIL
5311 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5312 || skip_past_comma (&str) == FAIL))
5313 return FAIL;
5314 break;
5316 case check_wshufh:
5317 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5318 || skip_past_comma (&str) == FAIL
5319 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5320 || skip_past_comma (&str) == FAIL))
5321 return FAIL;
5322 break;
5325 if (immediate_size == 0)
5327 end_of_line (str);
5328 inst.error = inst_error;
5329 return reg;
5331 else
5333 skip_whitespace (str);
5335 /* Allow optional leading '#'. */
5336 if (is_immediate_prefix (* str))
5337 str++;
5339 memset (& expr, '\0', sizeof (expr));
5341 if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
5343 inst.error = _("bad or missing expression");
5344 return FAIL;
5347 number = expr.X_add_number;
5349 if (number != (number & immediate_size))
5351 inst.error = _("immediate value out of range");
5352 return FAIL;
5354 end_of_line (str);
5355 inst.error = inst_error;
5356 return number;
5360 static void
5361 do_iwmmxt_byte_addr (char * str)
5363 int op = (inst.instruction & 0x300) >> 8;
5364 int reg;
5366 inst.instruction &= ~0x300;
5367 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
5369 skip_whitespace (str);
5371 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
5372 || skip_past_comma (& str) == FAIL
5373 || cp_byte_address_required_here (&str) == FAIL)
5375 if (! inst.error)
5376 inst.error = BAD_ARGS;
5378 else
5379 end_of_line (str);
5381 if (wc_register (reg))
5383 as_bad (_("non-word size not supported with control register"));
5384 inst.instruction |= 0xf0000100;
5385 inst.instruction &= ~0x00400000;
5389 static void
5390 do_iwmmxt_tandc (char * str)
5392 int reg;
5394 reg = check_iwmmxt_insn (str, check_rd, 0);
5396 if (reg != REG_PC && !inst.error)
5397 inst.error = _("only r15 allowed here");
5400 static void
5401 do_iwmmxt_tbcst (char * str)
5403 check_iwmmxt_insn (str, check_tbcst, 0);
5406 static void
5407 do_iwmmxt_textrc (char * str)
5409 unsigned long number;
5411 if ((number = check_iwmmxt_insn (str, check_textrc, 7)) == (unsigned long) FAIL)
5412 return;
5414 inst.instruction |= number & 0x7;
5417 static void
5418 do_iwmmxt_textrm (char * str)
5420 unsigned long number;
5422 if ((number = check_iwmmxt_insn (str, check_textrm, 7)) == (unsigned long) FAIL)
5423 return;
5425 inst.instruction |= number & 0x7;
5428 static void
5429 do_iwmmxt_tinsr (char * str)
5431 unsigned long number;
5433 if ((number = check_iwmmxt_insn (str, check_tinsr, 7)) == (unsigned long) FAIL)
5434 return;
5436 inst.instruction |= number & 0x7;
5439 static void
5440 do_iwmmxt_tmcr (char * str)
5442 check_iwmmxt_insn (str, check_tmcr, 0);
5445 static void
5446 do_iwmmxt_tmcrr (char * str)
5448 check_iwmmxt_insn (str, check_tmcrr, 0);
5451 static void
5452 do_iwmmxt_tmia (char * str)
5454 check_iwmmxt_insn (str, check_tmia, 0);
5457 static void
5458 do_iwmmxt_tmovmsk (char * str)
5460 check_iwmmxt_insn (str, check_tmovmsk, 0);
5463 static void
5464 do_iwmmxt_tmrc (char * str)
5466 check_iwmmxt_insn (str, check_tmrc, 0);
5469 static void
5470 do_iwmmxt_tmrrc (char * str)
5472 check_iwmmxt_insn (str, check_tmrrc, 0);
5475 static void
5476 do_iwmmxt_torc (char * str)
5478 check_iwmmxt_insn (str, check_rd, 0);
5481 static void
5482 do_iwmmxt_waligni (char * str)
5484 unsigned long number;
5486 if ((number = check_iwmmxt_insn (str, check_waligni, 7)) == (unsigned long) FAIL)
5487 return;
5489 inst.instruction |= ((number & 0x7) << 20);
5492 static void
5493 do_iwmmxt_wmov (char * str)
5495 if (check_iwmmxt_insn (str, check_wrwr, 0) == (unsigned long) FAIL)
5496 return;
5498 inst.instruction |= ((inst.instruction >> 16) & 0xf);
5501 static void
5502 do_iwmmxt_word_addr (char * str)
5504 int op = (inst.instruction & 0x300) >> 8;
5505 int reg;
5507 inst.instruction &= ~0x300;
5508 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
5510 skip_whitespace (str);
5512 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
5513 || skip_past_comma (& str) == FAIL
5514 || cp_address_required_here (& str, CP_WB_OK) == FAIL)
5516 if (! inst.error)
5517 inst.error = BAD_ARGS;
5519 else
5520 end_of_line (str);
5522 if (wc_register (reg))
5524 if ((inst.instruction & COND_MASK) != COND_ALWAYS)
5525 as_bad (_("conditional execution not supported with control register"));
5526 if (op != 2)
5527 as_bad (_("non-word size not supported with control register"));
5528 inst.instruction |= 0xf0000100;
5529 inst.instruction &= ~0x00400000;
5533 static void
5534 do_iwmmxt_wrwr (char * str)
5536 check_iwmmxt_insn (str, check_wrwr, 0);
5539 static void
5540 do_iwmmxt_wrwrwcg (char * str)
5542 check_iwmmxt_insn (str, check_wrwrwcg, 0);
5545 static void
5546 do_iwmmxt_wrwrwr (char * str)
5548 check_iwmmxt_insn (str, check_wrwrwr, 0);
5551 static void
5552 do_iwmmxt_wshufh (char * str)
5554 unsigned long number;
5556 if ((number = check_iwmmxt_insn (str, check_wshufh, 0xff)) == (unsigned long) FAIL)
5557 return;
5559 inst.instruction |= ((number & 0xf0) << 16) | (number & 0xf);
5562 static void
5563 do_iwmmxt_wzero (char * str)
5565 if (check_iwmmxt_insn (str, check_wr, 0) == (unsigned long) FAIL)
5566 return;
5568 inst.instruction |= ((inst.instruction & 0xf) << 12) | ((inst.instruction & 0xf) << 16);
5571 /* Xscale multiply-accumulate (argument parse)
5572 MIAcc acc0,Rm,Rs
5573 MIAPHcc acc0,Rm,Rs
5574 MIAxycc acc0,Rm,Rs. */
5576 static void
5577 do_xsc_mia (char * str)
5579 int rs;
5580 int rm;
5582 if (accum0_required_here (& str) == FAIL)
5583 inst.error = ERR_NO_ACCUM;
5585 else if (skip_past_comma (& str) == FAIL
5586 || (rm = reg_required_here (& str, 0)) == FAIL)
5587 inst.error = BAD_ARGS;
5589 else if (skip_past_comma (& str) == FAIL
5590 || (rs = reg_required_here (& str, 12)) == FAIL)
5591 inst.error = BAD_ARGS;
5593 /* inst.instruction has now been zapped with both rm and rs. */
5594 else if (rm == REG_PC || rs == REG_PC)
5595 inst.error = BAD_PC; /* Undefined result if rm or rs is R15. */
5597 else
5598 end_of_line (str);
5601 /* Xscale move-accumulator-register (argument parse)
5603 MARcc acc0,RdLo,RdHi. */
5605 static void
5606 do_xsc_mar (char * str)
5608 int rdlo, rdhi;
5610 if (accum0_required_here (& str) == FAIL)
5611 inst.error = ERR_NO_ACCUM;
5613 else if (skip_past_comma (& str) == FAIL
5614 || (rdlo = reg_required_here (& str, 12)) == FAIL)
5615 inst.error = BAD_ARGS;
5617 else if (skip_past_comma (& str) == FAIL
5618 || (rdhi = reg_required_here (& str, 16)) == FAIL)
5619 inst.error = BAD_ARGS;
5621 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5622 else if (rdlo == REG_PC || rdhi == REG_PC)
5623 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
5625 else
5626 end_of_line (str);
5629 /* Xscale move-register-accumulator (argument parse)
5631 MRAcc RdLo,RdHi,acc0. */
5633 static void
5634 do_xsc_mra (char * str)
5636 int rdlo;
5637 int rdhi;
5639 skip_whitespace (str);
5641 if ((rdlo = reg_required_here (& str, 12)) == FAIL)
5642 inst.error = BAD_ARGS;
5644 else if (skip_past_comma (& str) == FAIL
5645 || (rdhi = reg_required_here (& str, 16)) == FAIL)
5646 inst.error = BAD_ARGS;
5648 else if (skip_past_comma (& str) == FAIL
5649 || accum0_required_here (& str) == FAIL)
5650 inst.error = ERR_NO_ACCUM;
5652 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5653 else if (rdlo == rdhi)
5654 inst.error = BAD_ARGS; /* Undefined result if 2 writes to same reg. */
5656 else if (rdlo == REG_PC || rdhi == REG_PC)
5657 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
5658 else
5659 end_of_line (str);
5662 static int
5663 ldst_extend (char ** str)
5665 int add = INDEX_UP;
5667 switch (**str)
5669 case '#':
5670 case '$':
5671 (*str)++;
5672 if (my_get_expression (& inst.reloc.exp, str))
5673 return FAIL;
5675 if (inst.reloc.exp.X_op == O_constant)
5677 int value = inst.reloc.exp.X_add_number;
5679 if (value < -4095 || value > 4095)
5681 inst.error = _("address offset too large");
5682 return FAIL;
5685 if (value < 0)
5687 value = -value;
5688 add = 0;
5691 inst.instruction |= add | value;
5693 else
5695 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
5696 inst.reloc.pc_rel = 0;
5698 return SUCCESS;
5700 case '-':
5701 add = 0;
5702 /* Fall through. */
5704 case '+':
5705 (*str)++;
5706 /* Fall through. */
5708 default:
5709 if (reg_required_here (str, 0) == FAIL)
5710 return FAIL;
5712 inst.instruction |= add | OFFSET_REG;
5713 if (skip_past_comma (str) == SUCCESS)
5714 return decode_shift (str, SHIFT_IMMEDIATE);
5716 return SUCCESS;
5720 /* ARMv5TE: Preload-Cache
5722 PLD <addr_mode>
5724 Syntactically, like LDR with B=1, W=0, L=1. */
5726 static void
5727 do_pld (char * str)
5729 int rd;
5731 skip_whitespace (str);
5733 if (* str != '[')
5735 inst.error = _("'[' expected after PLD mnemonic");
5736 return;
5739 ++str;
5740 skip_whitespace (str);
5742 if ((rd = reg_required_here (& str, 16)) == FAIL)
5743 return;
5745 skip_whitespace (str);
5747 if (*str == ']')
5749 /* [Rn], ... ? */
5750 ++str;
5751 skip_whitespace (str);
5753 /* Post-indexed addressing is not allowed with PLD. */
5754 if (skip_past_comma (&str) == SUCCESS)
5756 inst.error
5757 = _("post-indexed expression used in preload instruction");
5758 return;
5760 else if (*str == '!') /* [Rn]! */
5762 inst.error = _("writeback used in preload instruction");
5763 ++str;
5765 else /* [Rn] */
5766 inst.instruction |= INDEX_UP | PRE_INDEX;
5768 else /* [Rn, ...] */
5770 if (skip_past_comma (& str) == FAIL)
5772 inst.error = _("pre-indexed expression expected");
5773 return;
5776 if (ldst_extend (&str) == FAIL)
5777 return;
5779 skip_whitespace (str);
5781 if (* str != ']')
5783 inst.error = _("missing ]");
5784 return;
5787 ++ str;
5788 skip_whitespace (str);
5790 if (* str == '!') /* [Rn]! */
5792 inst.error = _("writeback used in preload instruction");
5793 ++ str;
5796 inst.instruction |= PRE_INDEX;
5799 end_of_line (str);
5802 /* ARMv5TE load-consecutive (argument parse)
5803 Mode is like LDRH.
5805 LDRccD R, mode
5806 STRccD R, mode. */
5808 static void
5809 do_ldrd (char * str)
5811 int rd;
5812 int rn;
5814 skip_whitespace (str);
5816 if ((rd = reg_required_here (& str, 12)) == FAIL)
5818 inst.error = BAD_ARGS;
5819 return;
5822 if (skip_past_comma (& str) == FAIL
5823 || (rn = ld_mode_required_here (& str)) == FAIL)
5825 if (!inst.error)
5826 inst.error = BAD_ARGS;
5827 return;
5830 /* inst.instruction has now been zapped with Rd and the addressing mode. */
5831 if (rd & 1) /* Unpredictable result if Rd is odd. */
5833 inst.error = _("destination register must be even");
5834 return;
5837 if (rd == REG_LR)
5839 inst.error = _("r14 not allowed here");
5840 return;
5843 if (((rd == rn) || (rd + 1 == rn))
5844 && ((inst.instruction & WRITE_BACK)
5845 || (!(inst.instruction & PRE_INDEX))))
5846 as_warn (_("pre/post-indexing used when modified address register is destination"));
5848 /* For an index-register load, the index register must not overlap the
5849 destination (even if not write-back). */
5850 if ((inst.instruction & V4_STR_BIT) == 0
5851 && (inst.instruction & HWOFFSET_IMM) == 0)
5853 int rm = inst.instruction & 0x0000000f;
5855 if (rm == rd || (rm == rd + 1))
5856 as_warn (_("ldrd destination registers must not overlap index register"));
5859 end_of_line (str);
5862 /* Returns the index into fp_values of a floating point number,
5863 or -1 if not in the table. */
5865 static int
5866 my_get_float_expression (char ** str)
5868 LITTLENUM_TYPE words[MAX_LITTLENUMS];
5869 char * save_in;
5870 expressionS exp;
5871 int i;
5872 int j;
5874 memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE));
5876 /* Look for a raw floating point number. */
5877 if ((save_in = atof_ieee (*str, 'x', words)) != NULL
5878 && is_end_of_line[(unsigned char) *save_in])
5880 for (i = 0; i < NUM_FLOAT_VALS; i++)
5882 for (j = 0; j < MAX_LITTLENUMS; j++)
5884 if (words[j] != fp_values[i][j])
5885 break;
5888 if (j == MAX_LITTLENUMS)
5890 *str = save_in;
5891 return i;
5896 /* Try and parse a more complex expression, this will probably fail
5897 unless the code uses a floating point prefix (eg "0f"). */
5898 save_in = input_line_pointer;
5899 input_line_pointer = *str;
5900 if (expression (&exp) == absolute_section
5901 && exp.X_op == O_big
5902 && exp.X_add_number < 0)
5904 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
5905 Ditto for 15. */
5906 if (gen_to_words (words, 5, (long) 15) == 0)
5908 for (i = 0; i < NUM_FLOAT_VALS; i++)
5910 for (j = 0; j < MAX_LITTLENUMS; j++)
5912 if (words[j] != fp_values[i][j])
5913 break;
5916 if (j == MAX_LITTLENUMS)
5918 *str = input_line_pointer;
5919 input_line_pointer = save_in;
5920 return i;
5926 *str = input_line_pointer;
5927 input_line_pointer = save_in;
5928 return -1;
5931 /* We handle all bad expressions here, so that we can report the faulty
5932 instruction in the error message. */
5933 void
5934 md_operand (expressionS * expr)
5936 if (in_my_get_expression)
5938 expr->X_op = O_illegal;
5939 if (inst.error == NULL)
5940 inst.error = _("bad expression");
5944 /* Do those data_ops which can take a negative immediate constant
5945 by altering the instruction. A bit of a hack really.
5946 MOV <-> MVN
5947 AND <-> BIC
5948 ADC <-> SBC
5949 by inverting the second operand, and
5950 ADD <-> SUB
5951 CMP <-> CMN
5952 by negating the second operand. */
5954 static int
5955 negate_data_op (unsigned long * instruction,
5956 unsigned long value)
5958 int op, new_inst;
5959 unsigned long negated, inverted;
5961 negated = validate_immediate (-value);
5962 inverted = validate_immediate (~value);
5964 op = (*instruction >> DATA_OP_SHIFT) & 0xf;
5965 switch (op)
5967 /* First negates. */
5968 case OPCODE_SUB: /* ADD <-> SUB */
5969 new_inst = OPCODE_ADD;
5970 value = negated;
5971 break;
5973 case OPCODE_ADD:
5974 new_inst = OPCODE_SUB;
5975 value = negated;
5976 break;
5978 case OPCODE_CMP: /* CMP <-> CMN */
5979 new_inst = OPCODE_CMN;
5980 value = negated;
5981 break;
5983 case OPCODE_CMN:
5984 new_inst = OPCODE_CMP;
5985 value = negated;
5986 break;
5988 /* Now Inverted ops. */
5989 case OPCODE_MOV: /* MOV <-> MVN */
5990 new_inst = OPCODE_MVN;
5991 value = inverted;
5992 break;
5994 case OPCODE_MVN:
5995 new_inst = OPCODE_MOV;
5996 value = inverted;
5997 break;
5999 case OPCODE_AND: /* AND <-> BIC */
6000 new_inst = OPCODE_BIC;
6001 value = inverted;
6002 break;
6004 case OPCODE_BIC:
6005 new_inst = OPCODE_AND;
6006 value = inverted;
6007 break;
6009 case OPCODE_ADC: /* ADC <-> SBC */
6010 new_inst = OPCODE_SBC;
6011 value = inverted;
6012 break;
6014 case OPCODE_SBC:
6015 new_inst = OPCODE_ADC;
6016 value = inverted;
6017 break;
6019 /* We cannot do anything. */
6020 default:
6021 return FAIL;
6024 if (value == (unsigned) FAIL)
6025 return FAIL;
6027 *instruction &= OPCODE_MASK;
6028 *instruction |= new_inst << DATA_OP_SHIFT;
6029 return value;
6032 static int
6033 data_op2 (char ** str)
6035 int value;
6036 expressionS expr;
6038 skip_whitespace (* str);
6040 if (reg_required_here (str, 0) != FAIL)
6042 if (skip_past_comma (str) == SUCCESS)
6043 /* Shift operation on register. */
6044 return decode_shift (str, NO_SHIFT_RESTRICT);
6046 return SUCCESS;
6048 else
6050 /* Immediate expression. */
6051 if (is_immediate_prefix (**str))
6053 (*str)++;
6054 inst.error = NULL;
6056 if (my_get_expression (&inst.reloc.exp, str))
6057 return FAIL;
6059 if (inst.reloc.exp.X_add_symbol)
6061 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
6062 inst.reloc.pc_rel = 0;
6064 else
6066 if (skip_past_comma (str) == SUCCESS)
6068 /* #x, y -- ie explicit rotation by Y. */
6069 if (my_get_expression (&expr, str))
6070 return FAIL;
6072 if (expr.X_op != O_constant)
6074 inst.error = _("constant expression expected");
6075 return FAIL;
6078 /* Rotate must be a multiple of 2. */
6079 if (((unsigned) expr.X_add_number) > 30
6080 || (expr.X_add_number & 1) != 0
6081 || ((unsigned) inst.reloc.exp.X_add_number) > 255)
6083 inst.error = _("invalid constant");
6084 return FAIL;
6086 inst.instruction |= INST_IMMEDIATE;
6087 inst.instruction |= inst.reloc.exp.X_add_number;
6088 inst.instruction |= expr.X_add_number << 7;
6089 return SUCCESS;
6092 /* Implicit rotation, select a suitable one. */
6093 value = validate_immediate (inst.reloc.exp.X_add_number);
6095 if (value == FAIL)
6097 /* Can't be done. Perhaps the code reads something like
6098 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
6099 if ((value = negate_data_op (&inst.instruction,
6100 inst.reloc.exp.X_add_number))
6101 == FAIL)
6103 inst.error = _("invalid constant");
6104 return FAIL;
6108 inst.instruction |= value;
6111 inst.instruction |= INST_IMMEDIATE;
6112 return SUCCESS;
6115 (*str)++;
6116 inst.error = _("register or shift expression expected");
6117 return FAIL;
6121 static int
6122 fp_op2 (char ** str)
6124 skip_whitespace (* str);
6126 if (fp_reg_required_here (str, 0) != FAIL)
6127 return SUCCESS;
6128 else
6130 /* Immediate expression. */
6131 if (*((*str)++) == '#')
6133 int i;
6135 inst.error = NULL;
6137 skip_whitespace (* str);
6139 /* First try and match exact strings, this is to guarantee
6140 that some formats will work even for cross assembly. */
6142 for (i = 0; fp_const[i]; i++)
6144 if (strncmp (*str, fp_const[i], strlen (fp_const[i])) == 0)
6146 char *start = *str;
6148 *str += strlen (fp_const[i]);
6149 if (is_end_of_line[(unsigned char) **str])
6151 inst.instruction |= i + 8;
6152 return SUCCESS;
6154 *str = start;
6158 /* Just because we didn't get a match doesn't mean that the
6159 constant isn't valid, just that it is in a format that we
6160 don't automatically recognize. Try parsing it with
6161 the standard expression routines. */
6162 if ((i = my_get_float_expression (str)) >= 0)
6164 inst.instruction |= i + 8;
6165 return SUCCESS;
6168 inst.error = _("invalid floating point immediate expression");
6169 return FAIL;
6171 inst.error =
6172 _("floating point register or immediate expression expected");
6173 return FAIL;
6177 static void
6178 do_arit (char * str)
6180 skip_whitespace (str);
6182 if (reg_required_here (&str, 12) == FAIL
6183 || skip_past_comma (&str) == FAIL
6184 || reg_required_here (&str, 16) == FAIL
6185 || skip_past_comma (&str) == FAIL
6186 || data_op2 (&str) == FAIL)
6188 if (!inst.error)
6189 inst.error = BAD_ARGS;
6190 return;
6193 end_of_line (str);
6196 static void
6197 do_adr (char * str)
6199 /* This is a pseudo-op of the form "adr rd, label" to be converted
6200 into a relative address of the form "add rd, pc, #label-.-8". */
6201 skip_whitespace (str);
6203 if (reg_required_here (&str, 12) == FAIL
6204 || skip_past_comma (&str) == FAIL
6205 || my_get_expression (&inst.reloc.exp, &str))
6207 if (!inst.error)
6208 inst.error = BAD_ARGS;
6209 return;
6212 /* Frag hacking will turn this into a sub instruction if the offset turns
6213 out to be negative. */
6214 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
6215 #ifndef TE_WINCE
6216 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust. */
6217 #endif
6218 inst.reloc.pc_rel = 1;
6220 end_of_line (str);
6223 static void
6224 do_adrl (char * str)
6226 /* This is a pseudo-op of the form "adrl rd, label" to be converted
6227 into a relative address of the form:
6228 add rd, pc, #low(label-.-8)"
6229 add rd, rd, #high(label-.-8)" */
6231 skip_whitespace (str);
6233 if (reg_required_here (&str, 12) == FAIL
6234 || skip_past_comma (&str) == FAIL
6235 || my_get_expression (&inst.reloc.exp, &str))
6237 if (!inst.error)
6238 inst.error = BAD_ARGS;
6240 return;
6243 end_of_line (str);
6244 /* Frag hacking will turn this into a sub instruction if the offset turns
6245 out to be negative. */
6246 inst.reloc.type = BFD_RELOC_ARM_ADRL_IMMEDIATE;
6247 #ifndef TE_WINCE
6248 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust */
6249 #endif
6250 inst.reloc.pc_rel = 1;
6251 inst.size = INSN_SIZE * 2;
6254 static void
6255 do_cmp (char * str)
6257 skip_whitespace (str);
6259 if (reg_required_here (&str, 16) == FAIL)
6261 if (!inst.error)
6262 inst.error = BAD_ARGS;
6263 return;
6266 if (skip_past_comma (&str) == FAIL
6267 || data_op2 (&str) == FAIL)
6269 if (!inst.error)
6270 inst.error = BAD_ARGS;
6271 return;
6274 end_of_line (str);
6277 static void
6278 do_mov (char * str)
6280 skip_whitespace (str);
6282 if (reg_required_here (&str, 12) == FAIL)
6284 if (!inst.error)
6285 inst.error = BAD_ARGS;
6286 return;
6289 if (skip_past_comma (&str) == FAIL
6290 || data_op2 (&str) == FAIL)
6292 if (!inst.error)
6293 inst.error = BAD_ARGS;
6294 return;
6297 end_of_line (str);
6300 static void
6301 do_ldst (char * str)
6303 int pre_inc = 0;
6304 int conflict_reg;
6305 int value;
6307 skip_whitespace (str);
6309 if ((conflict_reg = reg_required_here (&str, 12)) == FAIL)
6311 if (!inst.error)
6312 inst.error = BAD_ARGS;
6313 return;
6316 if (skip_past_comma (&str) == FAIL)
6318 inst.error = _("address expected");
6319 return;
6322 if (*str == '[')
6324 int reg;
6326 str++;
6328 skip_whitespace (str);
6330 if ((reg = reg_required_here (&str, 16)) == FAIL)
6331 return;
6333 /* Conflicts can occur on stores as well as loads. */
6334 conflict_reg = (conflict_reg == reg);
6336 skip_whitespace (str);
6338 if (*str == ']')
6340 str ++;
6342 if (skip_past_comma (&str) == SUCCESS)
6344 /* [Rn],... (post inc) */
6345 if (ldst_extend (&str) == FAIL)
6346 return;
6347 if (conflict_reg)
6348 as_warn (_("%s register same as write-back base"),
6349 ((inst.instruction & LOAD_BIT)
6350 ? _("destination") : _("source")));
6352 else
6354 /* [Rn] */
6355 skip_whitespace (str);
6357 if (*str == '!')
6359 if (conflict_reg)
6360 as_warn (_("%s register same as write-back base"),
6361 ((inst.instruction & LOAD_BIT)
6362 ? _("destination") : _("source")));
6363 str++;
6364 inst.instruction |= WRITE_BACK;
6367 inst.instruction |= INDEX_UP;
6368 pre_inc = 1;
6371 else
6373 /* [Rn,...] */
6374 if (skip_past_comma (&str) == FAIL)
6376 inst.error = _("pre-indexed expression expected");
6377 return;
6380 pre_inc = 1;
6381 if (ldst_extend (&str) == FAIL)
6382 return;
6384 skip_whitespace (str);
6386 if (*str++ != ']')
6388 inst.error = _("missing ]");
6389 return;
6392 skip_whitespace (str);
6394 if (*str == '!')
6396 if (conflict_reg)
6397 as_warn (_("%s register same as write-back base"),
6398 ((inst.instruction & LOAD_BIT)
6399 ? _("destination") : _("source")));
6400 str++;
6401 inst.instruction |= WRITE_BACK;
6405 else if (*str == '=')
6407 if ((inst.instruction & LOAD_BIT) == 0)
6409 inst.error = _("invalid pseudo operation");
6410 return;
6413 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6414 str++;
6416 skip_whitespace (str);
6418 if (my_get_expression (&inst.reloc.exp, &str))
6419 return;
6421 if (inst.reloc.exp.X_op != O_constant
6422 && inst.reloc.exp.X_op != O_symbol)
6424 inst.error = _("constant expression expected");
6425 return;
6428 if (inst.reloc.exp.X_op == O_constant)
6430 value = validate_immediate (inst.reloc.exp.X_add_number);
6432 if (value != FAIL)
6434 /* This can be done with a mov instruction. */
6435 inst.instruction &= LITERAL_MASK;
6436 inst.instruction |= (INST_IMMEDIATE
6437 | (OPCODE_MOV << DATA_OP_SHIFT));
6438 inst.instruction |= value & 0xfff;
6439 end_of_line (str);
6440 return;
6443 value = validate_immediate (~inst.reloc.exp.X_add_number);
6445 if (value != FAIL)
6447 /* This can be done with a mvn instruction. */
6448 inst.instruction &= LITERAL_MASK;
6449 inst.instruction |= (INST_IMMEDIATE
6450 | (OPCODE_MVN << DATA_OP_SHIFT));
6451 inst.instruction |= value & 0xfff;
6452 end_of_line (str);
6453 return;
6457 /* Insert into literal pool. */
6458 if (add_to_lit_pool () == FAIL)
6460 if (!inst.error)
6461 inst.error = _("literal pool insertion failed");
6462 return;
6465 /* Change the instruction exp to point to the pool. */
6466 inst.reloc.type = BFD_RELOC_ARM_LITERAL;
6467 inst.reloc.pc_rel = 1;
6468 inst.instruction |= (REG_PC << 16);
6469 pre_inc = 1;
6471 else
6473 if (my_get_expression (&inst.reloc.exp, &str))
6474 return;
6476 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
6477 #ifndef TE_WINCE
6478 /* PC rel adjust. */
6479 inst.reloc.exp.X_add_number -= 8;
6480 #endif
6481 inst.reloc.pc_rel = 1;
6482 inst.instruction |= (REG_PC << 16);
6483 pre_inc = 1;
6486 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
6487 end_of_line (str);
6490 static void
6491 do_ldstt (char * str)
6493 int conflict_reg;
6495 skip_whitespace (str);
6497 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
6499 if (!inst.error)
6500 inst.error = BAD_ARGS;
6501 return;
6504 if (skip_past_comma (& str) == FAIL)
6506 inst.error = _("address expected");
6507 return;
6510 if (*str == '[')
6512 int reg;
6514 str++;
6516 skip_whitespace (str);
6518 if ((reg = reg_required_here (&str, 16)) == FAIL)
6519 return;
6521 /* ldrt/strt always use post-indexed addressing, so if the base is
6522 the same as Rd, we warn. */
6523 if (conflict_reg == reg)
6524 as_warn (_("%s register same as write-back base"),
6525 ((inst.instruction & LOAD_BIT)
6526 ? _("destination") : _("source")));
6528 skip_whitespace (str);
6530 if (*str == ']')
6532 str ++;
6534 if (skip_past_comma (&str) == SUCCESS)
6536 /* [Rn],... (post inc) */
6537 if (ldst_extend (&str) == FAIL)
6538 return;
6540 else
6542 /* [Rn] */
6543 skip_whitespace (str);
6545 /* Skip a write-back '!'. */
6546 if (*str == '!')
6547 str++;
6549 inst.instruction |= INDEX_UP;
6552 else
6554 inst.error = _("post-indexed expression expected");
6555 return;
6558 else
6560 inst.error = _("post-indexed expression expected");
6561 return;
6564 end_of_line (str);
6567 /* Halfword and signed-byte load/store operations. */
6569 static void
6570 do_ldstv4 (char * str)
6572 int pre_inc = 0;
6573 int conflict_reg;
6574 int value;
6576 skip_whitespace (str);
6578 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
6580 if (!inst.error)
6581 inst.error = BAD_ARGS;
6582 return;
6585 if (skip_past_comma (& str) == FAIL)
6587 inst.error = _("address expected");
6588 return;
6591 if (*str == '[')
6593 int reg;
6595 str++;
6597 skip_whitespace (str);
6599 if ((reg = reg_required_here (&str, 16)) == FAIL)
6600 return;
6602 /* Conflicts can occur on stores as well as loads. */
6603 conflict_reg = (conflict_reg == reg);
6605 skip_whitespace (str);
6607 if (*str == ']')
6609 str ++;
6611 if (skip_past_comma (&str) == SUCCESS)
6613 /* [Rn],... (post inc) */
6614 if (ldst_extend_v4 (&str) == FAIL)
6615 return;
6616 if (conflict_reg)
6617 as_warn (_("%s register same as write-back base"),
6618 ((inst.instruction & LOAD_BIT)
6619 ? _("destination") : _("source")));
6621 else
6623 /* [Rn] */
6624 inst.instruction |= HWOFFSET_IMM;
6626 skip_whitespace (str);
6628 if (*str == '!')
6630 if (conflict_reg)
6631 as_warn (_("%s register same as write-back base"),
6632 ((inst.instruction & LOAD_BIT)
6633 ? _("destination") : _("source")));
6634 str++;
6635 inst.instruction |= WRITE_BACK;
6638 inst.instruction |= INDEX_UP;
6639 pre_inc = 1;
6642 else
6644 /* [Rn,...] */
6645 if (skip_past_comma (&str) == FAIL)
6647 inst.error = _("pre-indexed expression expected");
6648 return;
6651 pre_inc = 1;
6652 if (ldst_extend_v4 (&str) == FAIL)
6653 return;
6655 skip_whitespace (str);
6657 if (*str++ != ']')
6659 inst.error = _("missing ]");
6660 return;
6663 skip_whitespace (str);
6665 if (*str == '!')
6667 if (conflict_reg)
6668 as_warn (_("%s register same as write-back base"),
6669 ((inst.instruction & LOAD_BIT)
6670 ? _("destination") : _("source")));
6671 str++;
6672 inst.instruction |= WRITE_BACK;
6676 else if (*str == '=')
6678 if ((inst.instruction & LOAD_BIT) == 0)
6680 inst.error = _("invalid pseudo operation");
6681 return;
6684 /* XXX Does this work correctly for half-word/byte ops? */
6685 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6686 str++;
6688 skip_whitespace (str);
6690 if (my_get_expression (&inst.reloc.exp, &str))
6691 return;
6693 if (inst.reloc.exp.X_op != O_constant
6694 && inst.reloc.exp.X_op != O_symbol)
6696 inst.error = _("constant expression expected");
6697 return;
6700 if (inst.reloc.exp.X_op == O_constant)
6702 value = validate_immediate (inst.reloc.exp.X_add_number);
6704 if (value != FAIL)
6706 /* This can be done with a mov instruction. */
6707 inst.instruction &= LITERAL_MASK;
6708 inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
6709 inst.instruction |= value & 0xfff;
6710 end_of_line (str);
6711 return;
6714 value = validate_immediate (~ inst.reloc.exp.X_add_number);
6716 if (value != FAIL)
6718 /* This can be done with a mvn instruction. */
6719 inst.instruction &= LITERAL_MASK;
6720 inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT);
6721 inst.instruction |= value & 0xfff;
6722 end_of_line (str);
6723 return;
6727 /* Insert into literal pool. */
6728 if (add_to_lit_pool () == FAIL)
6730 if (!inst.error)
6731 inst.error = _("literal pool insertion failed");
6732 return;
6735 /* Change the instruction exp to point to the pool. */
6736 inst.instruction |= HWOFFSET_IMM;
6737 inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
6738 inst.reloc.pc_rel = 1;
6739 inst.instruction |= (REG_PC << 16);
6740 pre_inc = 1;
6742 else
6744 if (my_get_expression (&inst.reloc.exp, &str))
6745 return;
6747 inst.instruction |= HWOFFSET_IMM;
6748 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
6749 #ifndef TE_WINCE
6750 /* PC rel adjust. */
6751 inst.reloc.exp.X_add_number -= 8;
6752 #endif
6753 inst.reloc.pc_rel = 1;
6754 inst.instruction |= (REG_PC << 16);
6755 pre_inc = 1;
6758 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
6759 end_of_line (str);
6762 static void
6763 do_ldsttv4 (char * str)
6765 int conflict_reg;
6767 skip_whitespace (str);
6769 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
6771 if (!inst.error)
6772 inst.error = BAD_ARGS;
6773 return;
6776 if (skip_past_comma (& str) == FAIL)
6778 inst.error = _("address expected");
6779 return;
6782 if (*str == '[')
6784 int reg;
6786 str++;
6788 skip_whitespace (str);
6790 if ((reg = reg_required_here (&str, 16)) == FAIL)
6791 return;
6793 /* ldrt/strt always use post-indexed addressing, so if the base is
6794 the same as Rd, we warn. */
6795 if (conflict_reg == reg)
6796 as_warn (_("%s register same as write-back base"),
6797 ((inst.instruction & LOAD_BIT)
6798 ? _("destination") : _("source")));
6800 skip_whitespace (str);
6802 if (*str == ']')
6804 str ++;
6806 if (skip_past_comma (&str) == SUCCESS)
6808 /* [Rn],... (post inc) */
6809 if (ldst_extend_v4 (&str) == FAIL)
6810 return;
6812 else
6814 /* [Rn] */
6815 skip_whitespace (str);
6817 /* Skip a write-back '!'. */
6818 if (*str == '!')
6819 str++;
6821 inst.instruction |= (INDEX_UP|HWOFFSET_IMM);
6824 else
6826 inst.error = _("post-indexed expression expected");
6827 return;
6830 else
6832 inst.error = _("post-indexed expression expected");
6833 return;
6836 end_of_line (str);
6840 static long
6841 reg_list (char ** strp)
6843 char * str = * strp;
6844 long range = 0;
6845 int another_range;
6847 /* We come back here if we get ranges concatenated by '+' or '|'. */
6850 another_range = 0;
6852 if (*str == '{')
6854 int in_range = 0;
6855 int cur_reg = -1;
6857 str++;
6860 int reg;
6862 skip_whitespace (str);
6864 if ((reg = reg_required_here (& str, -1)) == FAIL)
6865 return FAIL;
6867 if (in_range)
6869 int i;
6871 if (reg <= cur_reg)
6873 inst.error = _("bad range in register list");
6874 return FAIL;
6877 for (i = cur_reg + 1; i < reg; i++)
6879 if (range & (1 << i))
6880 as_tsktsk
6881 (_("Warning: duplicated register (r%d) in register list"),
6883 else
6884 range |= 1 << i;
6886 in_range = 0;
6889 if (range & (1 << reg))
6890 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
6891 reg);
6892 else if (reg <= cur_reg)
6893 as_tsktsk (_("Warning: register range not in ascending order"));
6895 range |= 1 << reg;
6896 cur_reg = reg;
6898 while (skip_past_comma (&str) != FAIL
6899 || (in_range = 1, *str++ == '-'));
6900 str--;
6901 skip_whitespace (str);
6903 if (*str++ != '}')
6905 inst.error = _("missing `}'");
6906 return FAIL;
6909 else
6911 expressionS expr;
6913 if (my_get_expression (&expr, &str))
6914 return FAIL;
6916 if (expr.X_op == O_constant)
6918 if (expr.X_add_number
6919 != (expr.X_add_number & 0x0000ffff))
6921 inst.error = _("invalid register mask");
6922 return FAIL;
6925 if ((range & expr.X_add_number) != 0)
6927 int regno = range & expr.X_add_number;
6929 regno &= -regno;
6930 regno = (1 << regno) - 1;
6931 as_tsktsk
6932 (_("Warning: duplicated register (r%d) in register list"),
6933 regno);
6936 range |= expr.X_add_number;
6938 else
6940 if (inst.reloc.type != 0)
6942 inst.error = _("expression too complex");
6943 return FAIL;
6946 memcpy (&inst.reloc.exp, &expr, sizeof (expressionS));
6947 inst.reloc.type = BFD_RELOC_ARM_MULTI;
6948 inst.reloc.pc_rel = 0;
6952 skip_whitespace (str);
6954 if (*str == '|' || *str == '+')
6956 str++;
6957 another_range = 1;
6960 while (another_range);
6962 *strp = str;
6963 return range;
6966 static void
6967 do_ldmstm (char * str)
6969 int base_reg;
6970 long range;
6972 skip_whitespace (str);
6974 if ((base_reg = reg_required_here (&str, 16)) == FAIL)
6975 return;
6977 if (base_reg == REG_PC)
6979 inst.error = _("r15 not allowed as base register");
6980 return;
6983 skip_whitespace (str);
6985 if (*str == '!')
6987 inst.instruction |= WRITE_BACK;
6988 str++;
6991 if (skip_past_comma (&str) == FAIL
6992 || (range = reg_list (&str)) == FAIL)
6994 if (! inst.error)
6995 inst.error = BAD_ARGS;
6996 return;
6999 if (*str == '^')
7001 str++;
7002 inst.instruction |= LDM_TYPE_2_OR_3;
7005 if (inst.instruction & WRITE_BACK)
7007 /* Check for unpredictable uses of writeback. */
7008 if (inst.instruction & LOAD_BIT)
7010 /* Not allowed in LDM type 2. */
7011 if ((inst.instruction & LDM_TYPE_2_OR_3)
7012 && ((range & (1 << REG_PC)) == 0))
7013 as_warn (_("writeback of base register is UNPREDICTABLE"));
7014 /* Only allowed if base reg not in list for other types. */
7015 else if (range & (1 << base_reg))
7016 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
7018 else /* STM. */
7020 /* Not allowed for type 2. */
7021 if (inst.instruction & LDM_TYPE_2_OR_3)
7022 as_warn (_("writeback of base register is UNPREDICTABLE"));
7023 /* Only allowed if base reg not in list, or first in list. */
7024 else if ((range & (1 << base_reg))
7025 && (range & ((1 << base_reg) - 1)))
7026 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
7030 inst.instruction |= range;
7031 end_of_line (str);
7034 static void
7035 do_smi (char * str)
7037 skip_whitespace (str);
7039 /* Allow optional leading '#'. */
7040 if (is_immediate_prefix (*str))
7041 str++;
7043 if (my_get_expression (& inst.reloc.exp, & str))
7044 return;
7046 inst.reloc.type = BFD_RELOC_ARM_SMI;
7047 inst.reloc.pc_rel = 0;
7048 end_of_line (str);
7051 static void
7052 do_swi (char * str)
7054 skip_whitespace (str);
7056 /* Allow optional leading '#'. */
7057 if (is_immediate_prefix (*str))
7058 str++;
7060 if (my_get_expression (& inst.reloc.exp, & str))
7061 return;
7063 inst.reloc.type = BFD_RELOC_ARM_SWI;
7064 inst.reloc.pc_rel = 0;
7065 end_of_line (str);
7068 static void
7069 do_swap (char * str)
7071 int reg;
7073 skip_whitespace (str);
7075 if ((reg = reg_required_here (&str, 12)) == FAIL)
7076 return;
7078 if (reg == REG_PC)
7080 inst.error = _("r15 not allowed in swap");
7081 return;
7084 if (skip_past_comma (&str) == FAIL
7085 || (reg = reg_required_here (&str, 0)) == FAIL)
7087 if (!inst.error)
7088 inst.error = BAD_ARGS;
7089 return;
7092 if (reg == REG_PC)
7094 inst.error = _("r15 not allowed in swap");
7095 return;
7098 if (skip_past_comma (&str) == FAIL
7099 || *str++ != '[')
7101 inst.error = BAD_ARGS;
7102 return;
7105 skip_whitespace (str);
7107 if ((reg = reg_required_here (&str, 16)) == FAIL)
7108 return;
7110 if (reg == REG_PC)
7112 inst.error = BAD_PC;
7113 return;
7116 skip_whitespace (str);
7118 if (*str++ != ']')
7120 inst.error = _("missing ]");
7121 return;
7124 end_of_line (str);
7127 static void
7128 do_branch (char * str)
7130 if (my_get_expression (&inst.reloc.exp, &str))
7131 return;
7133 #ifdef OBJ_ELF
7135 char * save_in;
7137 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
7138 required for the instruction. */
7140 /* arm_parse_reloc () works on input_line_pointer.
7141 We actually want to parse the operands to the branch instruction
7142 passed in 'str'. Save the input pointer and restore it later. */
7143 save_in = input_line_pointer;
7144 input_line_pointer = str;
7145 if (inst.reloc.exp.X_op == O_symbol
7146 && *str == '('
7147 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
7149 inst.reloc.type = BFD_RELOC_ARM_PLT32;
7150 inst.reloc.pc_rel = 0;
7151 /* Modify str to point to after parsed operands, otherwise
7152 end_of_line() will complain about the (PLT) left in str. */
7153 str = input_line_pointer;
7155 else
7157 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
7158 inst.reloc.pc_rel = 1;
7160 input_line_pointer = save_in;
7162 #else
7163 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
7164 inst.reloc.pc_rel = 1;
7165 #endif /* OBJ_ELF */
7167 end_of_line (str);
7170 static void
7171 do_cdp (char * str)
7173 /* Co-processor data operation.
7174 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
7175 skip_whitespace (str);
7177 if (co_proc_number (&str) == FAIL)
7179 if (!inst.error)
7180 inst.error = BAD_ARGS;
7181 return;
7184 if (skip_past_comma (&str) == FAIL
7185 || cp_opc_expr (&str, 20,4) == FAIL)
7187 if (!inst.error)
7188 inst.error = BAD_ARGS;
7189 return;
7192 if (skip_past_comma (&str) == FAIL
7193 || cp_reg_required_here (&str, 12) == FAIL)
7195 if (!inst.error)
7196 inst.error = BAD_ARGS;
7197 return;
7200 if (skip_past_comma (&str) == FAIL
7201 || cp_reg_required_here (&str, 16) == FAIL)
7203 if (!inst.error)
7204 inst.error = BAD_ARGS;
7205 return;
7208 if (skip_past_comma (&str) == FAIL
7209 || cp_reg_required_here (&str, 0) == FAIL)
7211 if (!inst.error)
7212 inst.error = BAD_ARGS;
7213 return;
7216 if (skip_past_comma (&str) == SUCCESS)
7218 if (cp_opc_expr (&str, 5, 3) == FAIL)
7220 if (!inst.error)
7221 inst.error = BAD_ARGS;
7222 return;
7226 end_of_line (str);
7229 static void
7230 do_lstc (char * str)
7232 /* Co-processor register load/store.
7233 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
7235 skip_whitespace (str);
7237 if (co_proc_number (&str) == FAIL)
7239 if (!inst.error)
7240 inst.error = BAD_ARGS;
7241 return;
7244 if (skip_past_comma (&str) == FAIL
7245 || cp_reg_required_here (&str, 12) == FAIL)
7247 if (!inst.error)
7248 inst.error = BAD_ARGS;
7249 return;
7252 if (skip_past_comma (&str) == FAIL
7253 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
7255 if (! inst.error)
7256 inst.error = BAD_ARGS;
7257 return;
7260 end_of_line (str);
7263 static void
7264 do_co_reg (char * str)
7266 /* Co-processor register transfer.
7267 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
7269 skip_whitespace (str);
7271 if (co_proc_number (&str) == FAIL)
7273 if (!inst.error)
7274 inst.error = BAD_ARGS;
7275 return;
7278 if (skip_past_comma (&str) == FAIL
7279 || cp_opc_expr (&str, 21, 3) == FAIL)
7281 if (!inst.error)
7282 inst.error = BAD_ARGS;
7283 return;
7286 if (skip_past_comma (&str) == FAIL
7287 || reg_required_here (&str, 12) == FAIL)
7289 if (!inst.error)
7290 inst.error = BAD_ARGS;
7291 return;
7294 if (skip_past_comma (&str) == FAIL
7295 || cp_reg_required_here (&str, 16) == FAIL)
7297 if (!inst.error)
7298 inst.error = BAD_ARGS;
7299 return;
7302 if (skip_past_comma (&str) == FAIL
7303 || cp_reg_required_here (&str, 0) == FAIL)
7305 if (!inst.error)
7306 inst.error = BAD_ARGS;
7307 return;
7310 if (skip_past_comma (&str) == SUCCESS)
7312 if (cp_opc_expr (&str, 5, 3) == FAIL)
7314 if (!inst.error)
7315 inst.error = BAD_ARGS;
7316 return;
7320 end_of_line (str);
7323 static void
7324 do_fpa_ctrl (char * str)
7326 /* FP control registers.
7327 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
7329 skip_whitespace (str);
7331 if (reg_required_here (&str, 12) == FAIL)
7333 if (!inst.error)
7334 inst.error = BAD_ARGS;
7335 return;
7338 end_of_line (str);
7341 static void
7342 do_fpa_ldst (char * str)
7344 skip_whitespace (str);
7346 if (fp_reg_required_here (&str, 12) == FAIL)
7348 if (!inst.error)
7349 inst.error = BAD_ARGS;
7350 return;
7353 if (skip_past_comma (&str) == FAIL
7354 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
7356 if (!inst.error)
7357 inst.error = BAD_ARGS;
7358 return;
7361 end_of_line (str);
7364 static void
7365 do_fpa_ldmstm (char * str)
7367 int num_regs;
7369 skip_whitespace (str);
7371 if (fp_reg_required_here (&str, 12) == FAIL)
7373 if (! inst.error)
7374 inst.error = BAD_ARGS;
7375 return;
7378 /* Get Number of registers to transfer. */
7379 if (skip_past_comma (&str) == FAIL
7380 || my_get_expression (&inst.reloc.exp, &str))
7382 if (! inst.error)
7383 inst.error = _("constant expression expected");
7384 return;
7387 if (inst.reloc.exp.X_op != O_constant)
7389 inst.error = _("constant value required for number of registers");
7390 return;
7393 num_regs = inst.reloc.exp.X_add_number;
7395 if (num_regs < 1 || num_regs > 4)
7397 inst.error = _("number of registers must be in the range [1:4]");
7398 return;
7401 switch (num_regs)
7403 case 1:
7404 inst.instruction |= CP_T_X;
7405 break;
7406 case 2:
7407 inst.instruction |= CP_T_Y;
7408 break;
7409 case 3:
7410 inst.instruction |= CP_T_Y | CP_T_X;
7411 break;
7412 case 4:
7413 break;
7414 default:
7415 abort ();
7418 if (inst.instruction & (CP_T_Pre | CP_T_UD)) /* ea/fd format. */
7420 int reg;
7421 int write_back;
7422 int offset;
7424 /* The instruction specified "ea" or "fd", so we can only accept
7425 [Rn]{!}. The instruction does not really support stacking or
7426 unstacking, so we have to emulate these by setting appropriate
7427 bits and offsets. */
7428 if (skip_past_comma (&str) == FAIL
7429 || *str != '[')
7431 if (! inst.error)
7432 inst.error = BAD_ARGS;
7433 return;
7436 str++;
7437 skip_whitespace (str);
7439 if ((reg = reg_required_here (&str, 16)) == FAIL)
7440 return;
7442 skip_whitespace (str);
7444 if (*str != ']')
7446 inst.error = BAD_ARGS;
7447 return;
7450 str++;
7451 if (*str == '!')
7453 write_back = 1;
7454 str++;
7455 if (reg == REG_PC)
7457 inst.error =
7458 _("r15 not allowed as base register with write-back");
7459 return;
7462 else
7463 write_back = 0;
7465 if (inst.instruction & CP_T_Pre)
7467 /* Pre-decrement. */
7468 offset = 3 * num_regs;
7469 if (write_back)
7470 inst.instruction |= CP_T_WB;
7472 else
7474 /* Post-increment. */
7475 if (write_back)
7477 inst.instruction |= CP_T_WB;
7478 offset = 3 * num_regs;
7480 else
7482 /* No write-back, so convert this into a standard pre-increment
7483 instruction -- aesthetically more pleasing. */
7484 inst.instruction |= CP_T_Pre | CP_T_UD;
7485 offset = 0;
7489 inst.instruction |= offset;
7491 else if (skip_past_comma (&str) == FAIL
7492 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
7494 if (! inst.error)
7495 inst.error = BAD_ARGS;
7496 return;
7499 end_of_line (str);
7502 static void
7503 do_fpa_dyadic (char * str)
7505 skip_whitespace (str);
7507 if (fp_reg_required_here (&str, 12) == FAIL)
7509 if (! inst.error)
7510 inst.error = BAD_ARGS;
7511 return;
7514 if (skip_past_comma (&str) == FAIL
7515 || fp_reg_required_here (&str, 16) == FAIL)
7517 if (! inst.error)
7518 inst.error = BAD_ARGS;
7519 return;
7522 if (skip_past_comma (&str) == FAIL
7523 || fp_op2 (&str) == FAIL)
7525 if (! inst.error)
7526 inst.error = BAD_ARGS;
7527 return;
7530 end_of_line (str);
7533 static void
7534 do_fpa_monadic (char * str)
7536 skip_whitespace (str);
7538 if (fp_reg_required_here (&str, 12) == FAIL)
7540 if (! inst.error)
7541 inst.error = BAD_ARGS;
7542 return;
7545 if (skip_past_comma (&str) == FAIL
7546 || fp_op2 (&str) == FAIL)
7548 if (! inst.error)
7549 inst.error = BAD_ARGS;
7550 return;
7553 end_of_line (str);
7556 static void
7557 do_fpa_cmp (char * str)
7559 skip_whitespace (str);
7561 if (fp_reg_required_here (&str, 16) == FAIL)
7563 if (! inst.error)
7564 inst.error = BAD_ARGS;
7565 return;
7568 if (skip_past_comma (&str) == FAIL
7569 || fp_op2 (&str) == FAIL)
7571 if (! inst.error)
7572 inst.error = BAD_ARGS;
7573 return;
7576 end_of_line (str);
7579 static void
7580 do_fpa_from_reg (char * str)
7582 skip_whitespace (str);
7584 if (fp_reg_required_here (&str, 16) == FAIL)
7586 if (! inst.error)
7587 inst.error = BAD_ARGS;
7588 return;
7591 if (skip_past_comma (&str) == FAIL
7592 || reg_required_here (&str, 12) == FAIL)
7594 if (! inst.error)
7595 inst.error = BAD_ARGS;
7596 return;
7599 end_of_line (str);
7602 static void
7603 do_fpa_to_reg (char * str)
7605 skip_whitespace (str);
7607 if (reg_required_here (&str, 12) == FAIL)
7608 return;
7610 if (skip_past_comma (&str) == FAIL
7611 || fp_reg_required_here (&str, 0) == FAIL)
7613 if (! inst.error)
7614 inst.error = BAD_ARGS;
7615 return;
7618 end_of_line (str);
7621 /* Encode a VFP SP register number. */
7623 static void
7624 vfp_sp_encode_reg (int reg, enum vfp_sp_reg_pos pos)
7626 switch (pos)
7628 case VFP_REG_Sd:
7629 inst.instruction |= ((reg >> 1) << 12) | ((reg & 1) << 22);
7630 break;
7632 case VFP_REG_Sn:
7633 inst.instruction |= ((reg >> 1) << 16) | ((reg & 1) << 7);
7634 break;
7636 case VFP_REG_Sm:
7637 inst.instruction |= ((reg >> 1) << 0) | ((reg & 1) << 5);
7638 break;
7640 default:
7641 abort ();
7645 static int
7646 vfp_sp_reg_required_here (char ** str,
7647 enum vfp_sp_reg_pos pos)
7649 int reg;
7650 char * start = *str;
7652 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab)) != FAIL)
7654 vfp_sp_encode_reg (reg, pos);
7655 return reg;
7658 /* In the few cases where we might be able to accept something else
7659 this error can be overridden. */
7660 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
7662 /* Restore the start point. */
7663 *str = start;
7664 return FAIL;
7667 static int
7668 vfp_dp_reg_required_here (char ** str,
7669 enum vfp_dp_reg_pos pos)
7671 int reg;
7672 char * start = *str;
7674 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab)) != FAIL)
7676 switch (pos)
7678 case VFP_REG_Dd:
7679 inst.instruction |= reg << 12;
7680 break;
7682 case VFP_REG_Dn:
7683 inst.instruction |= reg << 16;
7684 break;
7686 case VFP_REG_Dm:
7687 inst.instruction |= reg << 0;
7688 break;
7690 default:
7691 abort ();
7693 return reg;
7696 /* In the few cases where we might be able to accept something else
7697 this error can be overridden. */
7698 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
7700 /* Restore the start point. */
7701 *str = start;
7702 return FAIL;
7705 static void
7706 do_vfp_sp_monadic (char * str)
7708 skip_whitespace (str);
7710 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7711 return;
7713 if (skip_past_comma (&str) == FAIL
7714 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
7716 if (! inst.error)
7717 inst.error = BAD_ARGS;
7718 return;
7721 end_of_line (str);
7724 static void
7725 do_vfp_dp_monadic (char * str)
7727 skip_whitespace (str);
7729 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7730 return;
7732 if (skip_past_comma (&str) == FAIL
7733 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7735 if (! inst.error)
7736 inst.error = BAD_ARGS;
7737 return;
7740 end_of_line (str);
7743 static void
7744 do_vfp_sp_dyadic (char * str)
7746 skip_whitespace (str);
7748 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7749 return;
7751 if (skip_past_comma (&str) == FAIL
7752 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL
7753 || skip_past_comma (&str) == FAIL
7754 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
7756 if (! inst.error)
7757 inst.error = BAD_ARGS;
7758 return;
7761 end_of_line (str);
7764 static void
7765 do_vfp_dp_dyadic (char * str)
7767 skip_whitespace (str);
7769 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7770 return;
7772 if (skip_past_comma (&str) == FAIL
7773 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL
7774 || skip_past_comma (&str) == FAIL
7775 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7777 if (! inst.error)
7778 inst.error = BAD_ARGS;
7779 return;
7782 end_of_line (str);
7785 static void
7786 do_vfp_reg_from_sp (char * str)
7788 skip_whitespace (str);
7790 if (reg_required_here (&str, 12) == FAIL)
7791 return;
7793 if (skip_past_comma (&str) == FAIL
7794 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
7796 if (! inst.error)
7797 inst.error = BAD_ARGS;
7798 return;
7801 end_of_line (str);
7804 /* Parse a VFP register list. If the string is invalid return FAIL.
7805 Otherwise return the number of registers, and set PBASE to the first
7806 register. Double precision registers are matched if DP is nonzero. */
7808 static int
7809 vfp_parse_reg_list (char **str, int *pbase, int dp)
7811 int base_reg;
7812 int new_base;
7813 int regtype;
7814 int max_regs;
7815 int count = 0;
7816 int warned = 0;
7817 unsigned long mask = 0;
7818 int i;
7820 if (**str != '{')
7821 return FAIL;
7823 (*str)++;
7824 skip_whitespace (*str);
7826 if (dp)
7828 regtype = REG_TYPE_DN;
7829 max_regs = 16;
7831 else
7833 regtype = REG_TYPE_SN;
7834 max_regs = 32;
7837 base_reg = max_regs;
7841 new_base = arm_reg_parse (str, all_reg_maps[regtype].htab);
7842 if (new_base == FAIL)
7844 inst.error = _(all_reg_maps[regtype].expected);
7845 return FAIL;
7848 if (new_base < base_reg)
7849 base_reg = new_base;
7851 if (mask & (1 << new_base))
7853 inst.error = _("invalid register list");
7854 return FAIL;
7857 if ((mask >> new_base) != 0 && ! warned)
7859 as_tsktsk (_("register list not in ascending order"));
7860 warned = 1;
7863 mask |= 1 << new_base;
7864 count++;
7866 skip_whitespace (*str);
7868 if (**str == '-') /* We have the start of a range expression */
7870 int high_range;
7872 (*str)++;
7874 if ((high_range
7875 = arm_reg_parse (str, all_reg_maps[regtype].htab))
7876 == FAIL)
7878 inst.error = _(all_reg_maps[regtype].expected);
7879 return FAIL;
7882 if (high_range <= new_base)
7884 inst.error = _("register range not in ascending order");
7885 return FAIL;
7888 for (new_base++; new_base <= high_range; new_base++)
7890 if (mask & (1 << new_base))
7892 inst.error = _("invalid register list");
7893 return FAIL;
7896 mask |= 1 << new_base;
7897 count++;
7901 while (skip_past_comma (str) != FAIL);
7903 (*str)++;
7905 /* Sanity check -- should have raised a parse error above. */
7906 if (count == 0 || count > max_regs)
7907 abort ();
7909 *pbase = base_reg;
7911 /* Final test -- the registers must be consecutive. */
7912 mask >>= base_reg;
7913 for (i = 0; i < count; i++)
7915 if ((mask & (1u << i)) == 0)
7917 inst.error = _("non-contiguous register range");
7918 return FAIL;
7922 return count;
7925 static void
7926 do_vfp_reg2_from_sp2 (char * str)
7928 int reg;
7930 skip_whitespace (str);
7932 if (reg_required_here (&str, 12) == FAIL
7933 || skip_past_comma (&str) == FAIL
7934 || reg_required_here (&str, 16) == FAIL
7935 || skip_past_comma (&str) == FAIL)
7937 if (! inst.error)
7938 inst.error = BAD_ARGS;
7939 return;
7942 /* We require exactly two consecutive SP registers. */
7943 if (vfp_parse_reg_list (&str, &reg, 0) != 2)
7945 if (! inst.error)
7946 inst.error = _("only two consecutive VFP SP registers allowed here");
7948 vfp_sp_encode_reg (reg, VFP_REG_Sm);
7950 end_of_line (str);
7953 static void
7954 do_vfp_sp_from_reg (char * str)
7956 skip_whitespace (str);
7958 if (vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
7959 return;
7961 if (skip_past_comma (&str) == FAIL
7962 || reg_required_here (&str, 12) == FAIL)
7964 if (! inst.error)
7965 inst.error = BAD_ARGS;
7966 return;
7969 end_of_line (str);
7972 static void
7973 do_vfp_sp2_from_reg2 (char * str)
7975 int reg;
7977 skip_whitespace (str);
7979 /* We require exactly two consecutive SP registers. */
7980 if (vfp_parse_reg_list (&str, &reg, 0) != 2)
7982 if (! inst.error)
7983 inst.error = _("only two consecutive VFP SP registers allowed here");
7985 vfp_sp_encode_reg (reg, VFP_REG_Sm);
7987 if (skip_past_comma (&str) == FAIL
7988 || reg_required_here (&str, 12) == FAIL
7989 || skip_past_comma (&str) == FAIL
7990 || reg_required_here (&str, 16) == FAIL)
7992 if (! inst.error)
7993 inst.error = BAD_ARGS;
7994 return;
7997 end_of_line (str);
8000 static void
8001 do_vfp_reg_from_dp (char * str)
8003 skip_whitespace (str);
8005 if (reg_required_here (&str, 12) == FAIL)
8006 return;
8008 if (skip_past_comma (&str) == FAIL
8009 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
8011 if (! inst.error)
8012 inst.error = BAD_ARGS;
8013 return;
8016 end_of_line (str);
8019 static void
8020 do_vfp_reg2_from_dp (char * str)
8022 skip_whitespace (str);
8024 if (reg_required_here (&str, 12) == FAIL)
8025 return;
8027 if (skip_past_comma (&str) == FAIL
8028 || reg_required_here (&str, 16) == FAIL
8029 || skip_past_comma (&str) == FAIL
8030 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8032 if (! inst.error)
8033 inst.error = BAD_ARGS;
8034 return;
8037 end_of_line (str);
8040 static void
8041 do_vfp_dp_from_reg (char * str)
8043 skip_whitespace (str);
8045 if (vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
8046 return;
8048 if (skip_past_comma (&str) == FAIL
8049 || reg_required_here (&str, 12) == FAIL)
8051 if (! inst.error)
8052 inst.error = BAD_ARGS;
8053 return;
8056 end_of_line (str);
8059 static void
8060 do_vfp_dp_from_reg2 (char * str)
8062 skip_whitespace (str);
8064 if (vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8065 return;
8067 if (skip_past_comma (&str) == FAIL
8068 || reg_required_here (&str, 12) == FAIL
8069 || skip_past_comma (&str) == FAIL
8070 || reg_required_here (&str, 16) == FAIL)
8072 if (! inst.error)
8073 inst.error = BAD_ARGS;
8074 return;
8077 end_of_line (str);
8080 static const struct vfp_reg *
8081 vfp_psr_parse (char ** str)
8083 char *start = *str;
8084 char c;
8085 char *p;
8086 const struct vfp_reg *vreg;
8088 p = start;
8090 /* Find the end of the current token. */
8093 c = *p++;
8095 while (ISALPHA (c));
8097 /* Mark it. */
8098 *--p = 0;
8100 for (vreg = vfp_regs + 0;
8101 vreg < vfp_regs + sizeof (vfp_regs) / sizeof (struct vfp_reg);
8102 vreg++)
8104 if (streq (start, vreg->name))
8106 *p = c;
8107 *str = p;
8108 return vreg;
8112 *p = c;
8113 return NULL;
8116 static int
8117 vfp_psr_required_here (char ** str)
8119 char *start = *str;
8120 const struct vfp_reg *vreg;
8122 vreg = vfp_psr_parse (str);
8124 if (vreg)
8126 inst.instruction |= vreg->regno;
8127 return SUCCESS;
8130 inst.error = _("VFP system register expected");
8132 *str = start;
8133 return FAIL;
8136 static void
8137 do_vfp_reg_from_ctrl (char * str)
8139 skip_whitespace (str);
8141 if (reg_required_here (&str, 12) == FAIL)
8142 return;
8144 if (skip_past_comma (&str) == FAIL
8145 || vfp_psr_required_here (&str) == FAIL)
8147 if (! inst.error)
8148 inst.error = BAD_ARGS;
8149 return;
8152 end_of_line (str);
8155 static void
8156 do_vfp_ctrl_from_reg (char * str)
8158 skip_whitespace (str);
8160 if (vfp_psr_required_here (&str) == FAIL)
8161 return;
8163 if (skip_past_comma (&str) == FAIL
8164 || reg_required_here (&str, 12) == FAIL)
8166 if (! inst.error)
8167 inst.error = BAD_ARGS;
8168 return;
8171 end_of_line (str);
8174 static void
8175 do_vfp_sp_ldst (char * str)
8177 skip_whitespace (str);
8179 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8181 if (!inst.error)
8182 inst.error = BAD_ARGS;
8183 return;
8186 if (skip_past_comma (&str) == FAIL
8187 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
8189 if (!inst.error)
8190 inst.error = BAD_ARGS;
8191 return;
8194 end_of_line (str);
8197 static void
8198 do_vfp_dp_ldst (char * str)
8200 skip_whitespace (str);
8202 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8204 if (!inst.error)
8205 inst.error = BAD_ARGS;
8206 return;
8209 if (skip_past_comma (&str) == FAIL
8210 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
8212 if (!inst.error)
8213 inst.error = BAD_ARGS;
8214 return;
8217 end_of_line (str);
8221 static void
8222 vfp_sp_ldstm (char * str, enum vfp_ldstm_type ldstm_type)
8224 int count;
8225 int reg;
8227 skip_whitespace (str);
8229 if (reg_required_here (&str, 16) == FAIL)
8230 return;
8232 skip_whitespace (str);
8234 if (*str == '!')
8236 inst.instruction |= WRITE_BACK;
8237 str++;
8239 else if (ldstm_type != VFP_LDSTMIA)
8241 inst.error = _("this addressing mode requires base-register writeback");
8242 return;
8245 if (skip_past_comma (&str) == FAIL
8246 || (count = vfp_parse_reg_list (&str, &reg, 0)) == FAIL)
8248 if (!inst.error)
8249 inst.error = BAD_ARGS;
8250 return;
8252 vfp_sp_encode_reg (reg, VFP_REG_Sd);
8254 inst.instruction |= count;
8255 end_of_line (str);
8258 static void
8259 vfp_dp_ldstm (char * str, enum vfp_ldstm_type ldstm_type)
8261 int count;
8262 int reg;
8264 skip_whitespace (str);
8266 if (reg_required_here (&str, 16) == FAIL)
8267 return;
8269 skip_whitespace (str);
8271 if (*str == '!')
8273 inst.instruction |= WRITE_BACK;
8274 str++;
8276 else if (ldstm_type != VFP_LDSTMIA && ldstm_type != VFP_LDSTMIAX)
8278 inst.error = _("this addressing mode requires base-register writeback");
8279 return;
8282 if (skip_past_comma (&str) == FAIL
8283 || (count = vfp_parse_reg_list (&str, &reg, 1)) == FAIL)
8285 if (!inst.error)
8286 inst.error = BAD_ARGS;
8287 return;
8290 count <<= 1;
8291 if (ldstm_type == VFP_LDSTMIAX || ldstm_type == VFP_LDSTMDBX)
8292 count += 1;
8294 inst.instruction |= (reg << 12) | count;
8295 end_of_line (str);
8298 static void
8299 do_vfp_sp_ldstmia (char * str)
8301 vfp_sp_ldstm (str, VFP_LDSTMIA);
8304 static void
8305 do_vfp_sp_ldstmdb (char * str)
8307 vfp_sp_ldstm (str, VFP_LDSTMDB);
8310 static void
8311 do_vfp_dp_ldstmia (char * str)
8313 vfp_dp_ldstm (str, VFP_LDSTMIA);
8316 static void
8317 do_vfp_dp_ldstmdb (char * str)
8319 vfp_dp_ldstm (str, VFP_LDSTMDB);
8322 static void
8323 do_vfp_xp_ldstmia (char *str)
8325 vfp_dp_ldstm (str, VFP_LDSTMIAX);
8328 static void
8329 do_vfp_xp_ldstmdb (char * str)
8331 vfp_dp_ldstm (str, VFP_LDSTMDBX);
8334 static void
8335 do_vfp_sp_compare_z (char * str)
8337 skip_whitespace (str);
8339 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8341 if (!inst.error)
8342 inst.error = BAD_ARGS;
8343 return;
8346 end_of_line (str);
8349 static void
8350 do_vfp_dp_compare_z (char * str)
8352 skip_whitespace (str);
8354 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8356 if (!inst.error)
8357 inst.error = BAD_ARGS;
8358 return;
8361 end_of_line (str);
8364 static void
8365 do_vfp_dp_sp_cvt (char * str)
8367 skip_whitespace (str);
8369 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8370 return;
8372 if (skip_past_comma (&str) == FAIL
8373 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
8375 if (! inst.error)
8376 inst.error = BAD_ARGS;
8377 return;
8380 end_of_line (str);
8383 static void
8384 do_vfp_sp_dp_cvt (char * str)
8386 skip_whitespace (str);
8388 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8389 return;
8391 if (skip_past_comma (&str) == FAIL
8392 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8394 if (! inst.error)
8395 inst.error = BAD_ARGS;
8396 return;
8399 end_of_line (str);
8402 /* Thumb specific routines. */
8404 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
8405 was SUB. */
8407 static void
8408 thumb_add_sub (char * str, int subtract)
8410 int Rd, Rs, Rn = FAIL;
8412 skip_whitespace (str);
8414 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
8415 || skip_past_comma (&str) == FAIL)
8417 if (! inst.error)
8418 inst.error = BAD_ARGS;
8419 return;
8422 if (is_immediate_prefix (*str))
8424 Rs = Rd;
8425 str++;
8426 if (my_get_expression (&inst.reloc.exp, &str))
8427 return;
8429 else
8431 if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8432 return;
8434 if (skip_past_comma (&str) == FAIL)
8436 /* Two operand format, shuffle the registers
8437 and pretend there are 3. */
8438 Rn = Rs;
8439 Rs = Rd;
8441 else if (is_immediate_prefix (*str))
8443 str++;
8444 if (my_get_expression (&inst.reloc.exp, &str))
8445 return;
8447 else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8448 return;
8451 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8452 for the latter case, EXPR contains the immediate that was found. */
8453 if (Rn != FAIL)
8455 /* All register format. */
8456 if (Rd > 7 || Rs > 7 || Rn > 7)
8458 if (Rs != Rd)
8460 inst.error = _("dest and source1 must be the same register");
8461 return;
8464 /* Can't do this for SUB. */
8465 if (subtract)
8467 inst.error = _("subtract valid only on lo regs");
8468 return;
8471 inst.instruction = (T_OPCODE_ADD_HI
8472 | (Rd > 7 ? THUMB_H1 : 0)
8473 | (Rn > 7 ? THUMB_H2 : 0));
8474 inst.instruction |= (Rd & 7) | ((Rn & 7) << 3);
8476 else
8478 inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3;
8479 inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
8482 else
8484 /* Immediate expression, now things start to get nasty. */
8486 /* First deal with HI regs, only very restricted cases allowed:
8487 Adjusting SP, and using PC or SP to get an address. */
8488 if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP))
8489 || (Rs > 7 && Rs != REG_SP && Rs != REG_PC))
8491 inst.error = _("invalid Hi register with immediate");
8492 return;
8495 if (inst.reloc.exp.X_op != O_constant)
8497 /* Value isn't known yet, all we can do is store all the fragments
8498 we know about in the instruction and let the reloc hacking
8499 work it all out. */
8500 inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs;
8501 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
8503 else
8505 int offset = inst.reloc.exp.X_add_number;
8507 if (subtract)
8508 offset = - offset;
8510 if (offset < 0)
8512 offset = - offset;
8513 subtract = 1;
8515 /* Quick check, in case offset is MIN_INT. */
8516 if (offset < 0)
8518 inst.error = _("immediate value out of range");
8519 return;
8522 /* Note - you cannot convert a subtract of 0 into an
8523 add of 0 because the carry flag is set differently. */
8524 else if (offset > 0)
8525 subtract = 0;
8527 if (Rd == REG_SP)
8529 if (offset & ~0x1fc)
8531 inst.error = _("invalid immediate value for stack adjust");
8532 return;
8534 inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
8535 inst.instruction |= offset >> 2;
8537 else if (Rs == REG_PC || Rs == REG_SP)
8539 if (subtract
8540 || (offset & ~0x3fc))
8542 inst.error = _("invalid immediate for address calculation");
8543 return;
8545 inst.instruction = (Rs == REG_PC ? T_OPCODE_ADD_PC
8546 : T_OPCODE_ADD_SP);
8547 inst.instruction |= (Rd << 8) | (offset >> 2);
8549 else if (Rs == Rd)
8551 if (offset & ~0xff)
8553 inst.error = _("immediate value out of range");
8554 return;
8556 inst.instruction = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
8557 inst.instruction |= (Rd << 8) | offset;
8559 else
8561 if (offset & ~0x7)
8563 inst.error = _("immediate value out of range");
8564 return;
8566 inst.instruction = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
8567 inst.instruction |= Rd | (Rs << 3) | (offset << 6);
8572 end_of_line (str);
8575 static void
8576 thumb_shift (char * str, int shift)
8578 int Rd, Rs, Rn = FAIL;
8580 skip_whitespace (str);
8582 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8583 || skip_past_comma (&str) == FAIL)
8585 if (! inst.error)
8586 inst.error = BAD_ARGS;
8587 return;
8590 if (is_immediate_prefix (*str))
8592 /* Two operand immediate format, set Rs to Rd. */
8593 Rs = Rd;
8594 str ++;
8595 if (my_get_expression (&inst.reloc.exp, &str))
8596 return;
8598 else
8600 if ((Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8601 return;
8603 if (skip_past_comma (&str) == FAIL)
8605 /* Two operand format, shuffle the registers
8606 and pretend there are 3. */
8607 Rn = Rs;
8608 Rs = Rd;
8610 else if (is_immediate_prefix (*str))
8612 str++;
8613 if (my_get_expression (&inst.reloc.exp, &str))
8614 return;
8616 else if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8617 return;
8620 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8621 for the latter case, EXPR contains the immediate that was found. */
8623 if (Rn != FAIL)
8625 if (Rs != Rd)
8627 inst.error = _("source1 and dest must be same register");
8628 return;
8631 switch (shift)
8633 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_R; break;
8634 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_R; break;
8635 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_R; break;
8638 inst.instruction |= Rd | (Rn << 3);
8640 else
8642 switch (shift)
8644 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_I; break;
8645 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_I; break;
8646 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_I; break;
8649 if (inst.reloc.exp.X_op != O_constant)
8651 /* Value isn't known yet, create a dummy reloc and let reloc
8652 hacking fix it up. */
8653 inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
8655 else
8657 unsigned shift_value = inst.reloc.exp.X_add_number;
8659 if (shift_value > 32 || (shift_value == 32 && shift == THUMB_LSL))
8661 inst.error = _("invalid immediate for shift");
8662 return;
8665 /* Shifts of zero are handled by converting to LSL. */
8666 if (shift_value == 0)
8667 inst.instruction = T_OPCODE_LSL_I;
8669 /* Shifts of 32 are encoded as a shift of zero. */
8670 if (shift_value == 32)
8671 shift_value = 0;
8673 inst.instruction |= shift_value << 6;
8676 inst.instruction |= Rd | (Rs << 3);
8679 end_of_line (str);
8682 static void
8683 thumb_load_store (char * str, int load_store, int size)
8685 int Rd, Rb, Ro = FAIL;
8687 skip_whitespace (str);
8689 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8690 || skip_past_comma (&str) == FAIL)
8692 if (! inst.error)
8693 inst.error = BAD_ARGS;
8694 return;
8697 if (*str == '[')
8699 str++;
8700 if ((Rb = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8701 return;
8703 if (skip_past_comma (&str) != FAIL)
8705 if (is_immediate_prefix (*str))
8707 str++;
8708 if (my_get_expression (&inst.reloc.exp, &str))
8709 return;
8711 else if ((Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8712 return;
8714 else
8716 inst.reloc.exp.X_op = O_constant;
8717 inst.reloc.exp.X_add_number = 0;
8720 if (*str != ']')
8722 inst.error = _("expected ']'");
8723 return;
8725 str++;
8727 else if (*str == '=')
8729 if (load_store != THUMB_LOAD)
8731 inst.error = _("invalid pseudo operation");
8732 return;
8735 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
8736 str++;
8738 skip_whitespace (str);
8740 if (my_get_expression (& inst.reloc.exp, & str))
8741 return;
8743 end_of_line (str);
8745 if ( inst.reloc.exp.X_op != O_constant
8746 && inst.reloc.exp.X_op != O_symbol)
8748 inst.error = "Constant expression expected";
8749 return;
8752 if (inst.reloc.exp.X_op == O_constant
8753 && ((inst.reloc.exp.X_add_number & ~0xFF) == 0))
8755 /* This can be done with a mov instruction. */
8757 inst.instruction = T_OPCODE_MOV_I8 | (Rd << 8);
8758 inst.instruction |= inst.reloc.exp.X_add_number;
8759 return;
8762 /* Insert into literal pool. */
8763 if (add_to_lit_pool () == FAIL)
8765 if (!inst.error)
8766 inst.error = "literal pool insertion failed";
8767 return;
8770 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8771 inst.reloc.pc_rel = 1;
8772 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
8773 /* Adjust ARM pipeline offset to Thumb. */
8774 inst.reloc.exp.X_add_number += 4;
8776 return;
8778 else
8780 if (my_get_expression (&inst.reloc.exp, &str))
8781 return;
8783 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
8784 inst.reloc.pc_rel = 1;
8785 inst.reloc.exp.X_add_number -= 4; /* Pipeline offset. */
8786 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8787 end_of_line (str);
8788 return;
8791 if (Rb == REG_PC || Rb == REG_SP)
8793 if (size != THUMB_WORD)
8795 inst.error = _("byte or halfword not valid for base register");
8796 return;
8798 else if (Rb == REG_PC && load_store != THUMB_LOAD)
8800 inst.error = _("r15 based store not allowed");
8801 return;
8803 else if (Ro != FAIL)
8805 inst.error = _("invalid base register for register offset");
8806 return;
8809 if (Rb == REG_PC)
8810 inst.instruction = T_OPCODE_LDR_PC;
8811 else if (load_store == THUMB_LOAD)
8812 inst.instruction = T_OPCODE_LDR_SP;
8813 else
8814 inst.instruction = T_OPCODE_STR_SP;
8816 inst.instruction |= Rd << 8;
8817 if (inst.reloc.exp.X_op == O_constant)
8819 unsigned offset = inst.reloc.exp.X_add_number;
8821 if (offset & ~0x3fc)
8823 inst.error = _("invalid offset");
8824 return;
8827 inst.instruction |= offset >> 2;
8829 else
8830 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8832 else if (Rb > 7)
8834 inst.error = _("invalid base register in load/store");
8835 return;
8837 else if (Ro == FAIL)
8839 /* Immediate offset. */
8840 if (size == THUMB_WORD)
8841 inst.instruction = (load_store == THUMB_LOAD
8842 ? T_OPCODE_LDR_IW : T_OPCODE_STR_IW);
8843 else if (size == THUMB_HALFWORD)
8844 inst.instruction = (load_store == THUMB_LOAD
8845 ? T_OPCODE_LDR_IH : T_OPCODE_STR_IH);
8846 else
8847 inst.instruction = (load_store == THUMB_LOAD
8848 ? T_OPCODE_LDR_IB : T_OPCODE_STR_IB);
8850 inst.instruction |= Rd | (Rb << 3);
8852 if (inst.reloc.exp.X_op == O_constant)
8854 unsigned offset = inst.reloc.exp.X_add_number;
8856 if (offset & ~(0x1f << size))
8858 inst.error = _("invalid offset");
8859 return;
8861 inst.instruction |= (offset >> size) << 6;
8863 else
8864 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8866 else
8868 /* Register offset. */
8869 if (size == THUMB_WORD)
8870 inst.instruction = (load_store == THUMB_LOAD
8871 ? T_OPCODE_LDR_RW : T_OPCODE_STR_RW);
8872 else if (size == THUMB_HALFWORD)
8873 inst.instruction = (load_store == THUMB_LOAD
8874 ? T_OPCODE_LDR_RH : T_OPCODE_STR_RH);
8875 else
8876 inst.instruction = (load_store == THUMB_LOAD
8877 ? T_OPCODE_LDR_RB : T_OPCODE_STR_RB);
8879 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
8882 end_of_line (str);
8885 /* A register must be given at this point.
8887 Shift is the place to put it in inst.instruction.
8889 Restores input start point on err.
8890 Returns the reg#, or FAIL. */
8892 static int
8893 mav_reg_required_here (char ** str, int shift, enum arm_reg_type regtype)
8895 int reg;
8896 char *start = *str;
8898 if ((reg = arm_reg_parse (str, all_reg_maps[regtype].htab)) != FAIL)
8900 if (shift >= 0)
8901 inst.instruction |= reg << shift;
8903 return reg;
8906 /* Restore the start point. */
8907 *str = start;
8909 /* Try generic coprocessor name if applicable. */
8910 if (regtype == REG_TYPE_MVF ||
8911 regtype == REG_TYPE_MVD ||
8912 regtype == REG_TYPE_MVFX ||
8913 regtype == REG_TYPE_MVDX)
8915 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
8917 if (shift >= 0)
8918 inst.instruction |= reg << shift;
8920 return reg;
8923 /* Restore the start point. */
8924 *str = start;
8927 /* In the few cases where we might be able to accept something else
8928 this error can be overridden. */
8929 inst.error = _(all_reg_maps[regtype].expected);
8931 return FAIL;
8934 /* Cirrus Maverick Instructions. */
8936 /* Isnsn like "foo X,Y". */
8938 static void
8939 do_mav_binops (char * str,
8940 int mode,
8941 enum arm_reg_type reg0,
8942 enum arm_reg_type reg1)
8944 int shift0, shift1;
8946 shift0 = mode & 0xff;
8947 shift1 = (mode >> 8) & 0xff;
8949 skip_whitespace (str);
8951 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
8952 || skip_past_comma (&str) == FAIL
8953 || mav_reg_required_here (&str, shift1, reg1) == FAIL)
8955 if (!inst.error)
8956 inst.error = BAD_ARGS;
8958 else
8959 end_of_line (str);
8962 /* Isnsn like "foo X,Y,Z". */
8964 static void
8965 do_mav_triple (char * str,
8966 int mode,
8967 enum arm_reg_type reg0,
8968 enum arm_reg_type reg1,
8969 enum arm_reg_type reg2)
8971 int shift0, shift1, shift2;
8973 shift0 = mode & 0xff;
8974 shift1 = (mode >> 8) & 0xff;
8975 shift2 = (mode >> 16) & 0xff;
8977 skip_whitespace (str);
8979 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
8980 || skip_past_comma (&str) == FAIL
8981 || mav_reg_required_here (&str, shift1, reg1) == FAIL
8982 || skip_past_comma (&str) == FAIL
8983 || mav_reg_required_here (&str, shift2, reg2) == FAIL)
8985 if (!inst.error)
8986 inst.error = BAD_ARGS;
8988 else
8989 end_of_line (str);
8992 /* Wrapper functions. */
8994 static void
8995 do_mav_binops_1a (char * str)
8997 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVF);
9000 static void
9001 do_mav_binops_1b (char * str)
9003 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVD);
9006 static void
9007 do_mav_binops_1c (char * str)
9009 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVDX);
9012 static void
9013 do_mav_binops_1d (char * str)
9015 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVF);
9018 static void
9019 do_mav_binops_1e (char * str)
9021 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVD);
9024 static void
9025 do_mav_binops_1f (char * str)
9027 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVF);
9030 static void
9031 do_mav_binops_1g (char * str)
9033 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVD);
9036 static void
9037 do_mav_binops_1h (char * str)
9039 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVFX);
9042 static void
9043 do_mav_binops_1i (char * str)
9045 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVFX);
9048 static void
9049 do_mav_binops_1j (char * str)
9051 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVDX);
9054 static void
9055 do_mav_binops_1k (char * str)
9057 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVDX);
9060 static void
9061 do_mav_binops_1l (char * str)
9063 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVF);
9066 static void
9067 do_mav_binops_1m (char * str)
9069 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVD);
9072 static void
9073 do_mav_binops_1n (char * str)
9075 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVFX);
9078 static void
9079 do_mav_binops_1o (char * str)
9081 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVDX, REG_TYPE_MVDX);
9084 static void
9085 do_mav_binops_2a (char * str)
9087 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVF, REG_TYPE_RN);
9090 static void
9091 do_mav_binops_2b (char * str)
9093 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVD, REG_TYPE_RN);
9096 static void
9097 do_mav_binops_2c (char * str)
9099 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVDX, REG_TYPE_RN);
9102 static void
9103 do_mav_binops_3a (char * str)
9105 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVFX);
9108 static void
9109 do_mav_binops_3b (char * str)
9111 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVFX, REG_TYPE_MVAX);
9114 static void
9115 do_mav_binops_3c (char * str)
9117 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVDX);
9120 static void
9121 do_mav_binops_3d (char * str)
9123 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVDX, REG_TYPE_MVAX);
9126 static void
9127 do_mav_triple_4a (char * str)
9129 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_RN);
9132 static void
9133 do_mav_triple_4b (char * str)
9135 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_RN);
9138 static void
9139 do_mav_triple_5a (char * str)
9141 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVF, REG_TYPE_MVF);
9144 static void
9145 do_mav_triple_5b (char * str)
9147 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVD, REG_TYPE_MVD);
9150 static void
9151 do_mav_triple_5c (char * str)
9153 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVFX, REG_TYPE_MVFX);
9156 static void
9157 do_mav_triple_5d (char * str)
9159 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVDX, REG_TYPE_MVDX);
9162 static void
9163 do_mav_triple_5e (char * str)
9165 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVF, REG_TYPE_MVF, REG_TYPE_MVF);
9168 static void
9169 do_mav_triple_5f (char * str)
9171 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVD, REG_TYPE_MVD, REG_TYPE_MVD);
9174 static void
9175 do_mav_triple_5g (char * str)
9177 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_MVFX);
9180 static void
9181 do_mav_triple_5h (char * str)
9183 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_MVDX);
9186 /* Isnsn like "foo W,X,Y,Z".
9187 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
9189 static void
9190 do_mav_quad (char * str,
9191 int mode,
9192 enum arm_reg_type reg0,
9193 enum arm_reg_type reg1,
9194 enum arm_reg_type reg2,
9195 enum arm_reg_type reg3)
9197 int shift0, shift1, shift2, shift3;
9199 shift0= mode & 0xff;
9200 shift1 = (mode >> 8) & 0xff;
9201 shift2 = (mode >> 16) & 0xff;
9202 shift3 = (mode >> 24) & 0xff;
9204 skip_whitespace (str);
9206 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
9207 || skip_past_comma (&str) == FAIL
9208 || mav_reg_required_here (&str, shift1, reg1) == FAIL
9209 || skip_past_comma (&str) == FAIL
9210 || mav_reg_required_here (&str, shift2, reg2) == FAIL
9211 || skip_past_comma (&str) == FAIL
9212 || mav_reg_required_here (&str, shift3, reg3) == FAIL)
9214 if (!inst.error)
9215 inst.error = BAD_ARGS;
9217 else
9218 end_of_line (str);
9221 static void
9222 do_mav_quad_6a (char * str)
9224 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVFX, REG_TYPE_MVFX,
9225 REG_TYPE_MVFX);
9228 static void
9229 do_mav_quad_6b (char * str)
9231 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVAX, REG_TYPE_MVFX,
9232 REG_TYPE_MVFX);
9235 /* cfmvsc32<cond> DSPSC,MVDX[15:0]. */
9236 static void
9237 do_mav_dspsc_1 (char * str)
9239 skip_whitespace (str);
9241 /* cfmvsc32. */
9242 if (mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL
9243 || skip_past_comma (&str) == FAIL
9244 || mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL)
9246 if (!inst.error)
9247 inst.error = BAD_ARGS;
9249 return;
9252 end_of_line (str);
9255 /* cfmv32sc<cond> MVDX[15:0],DSPSC. */
9256 static void
9257 do_mav_dspsc_2 (char * str)
9259 skip_whitespace (str);
9261 /* cfmv32sc. */
9262 if (mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL
9263 || skip_past_comma (&str) == FAIL
9264 || mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL)
9266 if (!inst.error)
9267 inst.error = BAD_ARGS;
9269 return;
9272 end_of_line (str);
9275 /* Maverick shift immediate instructions.
9276 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
9277 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
9279 static void
9280 do_mav_shift (char * str,
9281 enum arm_reg_type reg0,
9282 enum arm_reg_type reg1)
9284 int error;
9285 int imm, neg = 0;
9287 skip_whitespace (str);
9289 error = 0;
9291 if (mav_reg_required_here (&str, 12, reg0) == FAIL
9292 || skip_past_comma (&str) == FAIL
9293 || mav_reg_required_here (&str, 16, reg1) == FAIL
9294 || skip_past_comma (&str) == FAIL)
9296 if (!inst.error)
9297 inst.error = BAD_ARGS;
9298 return;
9301 /* Calculate the immediate operand.
9302 The operand is a 7bit signed number. */
9303 skip_whitespace (str);
9305 if (*str == '#')
9306 ++str;
9308 if (!ISDIGIT (*str) && *str != '-')
9310 inst.error = _("expecting immediate, 7bit operand");
9311 return;
9314 if (*str == '-')
9316 neg = 1;
9317 ++str;
9320 for (imm = 0; *str && ISDIGIT (*str); ++str)
9321 imm = imm * 10 + *str - '0';
9323 if (imm > 64)
9325 inst.error = _("immediate out of range");
9326 return;
9329 /* Make negative imm's into 7bit signed numbers. */
9330 if (neg)
9332 imm = -imm;
9333 imm &= 0x0000007f;
9336 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
9337 Bits 5-7 of the insn should have bits 4-6 of the immediate.
9338 Bit 4 should be 0. */
9339 imm = (imm & 0xf) | ((imm & 0x70) << 1);
9341 inst.instruction |= imm;
9342 end_of_line (str);
9345 static void
9346 do_mav_shift_1 (char * str)
9348 do_mav_shift (str, REG_TYPE_MVFX, REG_TYPE_MVFX);
9351 static void
9352 do_mav_shift_2 (char * str)
9354 do_mav_shift (str, REG_TYPE_MVDX, REG_TYPE_MVDX);
9357 static int
9358 mav_parse_offset (char ** str, int * negative)
9360 char * p = *str;
9361 int offset;
9363 *negative = 0;
9365 skip_whitespace (p);
9367 if (*p == '#')
9368 ++p;
9370 if (*p == '-')
9372 *negative = 1;
9373 ++p;
9376 if (!ISDIGIT (*p))
9378 inst.error = _("offset expected");
9379 return 0;
9382 for (offset = 0; *p && ISDIGIT (*p); ++p)
9383 offset = offset * 10 + *p - '0';
9385 if (offset > 0x3fc)
9387 inst.error = _("offset out of range");
9388 return 0;
9390 if (offset & 0x3)
9392 inst.error = _("offset not a multiple of 4");
9393 return 0;
9396 *str = p;
9398 return *negative ? -offset : offset;
9401 /* Maverick load/store instructions.
9402 <insn><cond> CRd,[Rn,<offset>]{!}.
9403 <insn><cond> CRd,[Rn],<offset>. */
9405 static void
9406 do_mav_ldst (char * str, enum arm_reg_type reg0)
9408 int offset, negative;
9410 skip_whitespace (str);
9412 if (mav_reg_required_here (&str, 12, reg0) == FAIL
9413 || skip_past_comma (&str) == FAIL
9414 || *str++ != '['
9415 || reg_required_here (&str, 16) == FAIL)
9416 goto fail_ldst;
9418 if (skip_past_comma (&str) == SUCCESS)
9420 /* You are here: "<offset>]{!}". */
9421 inst.instruction |= PRE_INDEX;
9423 offset = mav_parse_offset (&str, &negative);
9425 if (inst.error)
9426 return;
9428 if (*str++ != ']')
9430 inst.error = _("missing ]");
9431 return;
9434 if (*str == '!')
9436 inst.instruction |= WRITE_BACK;
9437 ++str;
9440 else
9442 /* You are here: "], <offset>". */
9443 if (*str++ != ']')
9445 inst.error = _("missing ]");
9446 return;
9449 if (skip_past_comma (&str) == FAIL
9450 || (offset = mav_parse_offset (&str, &negative), inst.error))
9451 goto fail_ldst;
9453 inst.instruction |= CP_T_WB; /* Post indexed, set bit W. */
9456 if (negative)
9457 offset = -offset;
9458 else
9459 inst.instruction |= CP_T_UD; /* Positive, so set bit U. */
9461 inst.instruction |= offset >> 2;
9462 end_of_line (str);
9463 return;
9465 fail_ldst:
9466 if (!inst.error)
9467 inst.error = BAD_ARGS;
9470 static void
9471 do_mav_ldst_1 (char * str)
9473 do_mav_ldst (str, REG_TYPE_MVF);
9476 static void
9477 do_mav_ldst_2 (char * str)
9479 do_mav_ldst (str, REG_TYPE_MVD);
9482 static void
9483 do_mav_ldst_3 (char * str)
9485 do_mav_ldst (str, REG_TYPE_MVFX);
9488 static void
9489 do_mav_ldst_4 (char * str)
9491 do_mav_ldst (str, REG_TYPE_MVDX);
9494 static void
9495 do_t_nop (char * str)
9497 /* Do nothing. */
9498 end_of_line (str);
9501 /* Handle the Format 4 instructions that do not have equivalents in other
9502 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
9503 BIC and MVN. */
9505 static void
9506 do_t_arit (char * str)
9508 int Rd, Rs, Rn;
9510 skip_whitespace (str);
9512 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9513 || skip_past_comma (&str) == FAIL
9514 || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9516 inst.error = BAD_ARGS;
9517 return;
9520 if (skip_past_comma (&str) != FAIL)
9522 /* Three operand format not allowed for TST, CMN, NEG and MVN.
9523 (It isn't allowed for CMP either, but that isn't handled by this
9524 function.) */
9525 if (inst.instruction == T_OPCODE_TST
9526 || inst.instruction == T_OPCODE_CMN
9527 || inst.instruction == T_OPCODE_NEG
9528 || inst.instruction == T_OPCODE_MVN)
9530 inst.error = BAD_ARGS;
9531 return;
9534 if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9535 return;
9537 if (Rs != Rd)
9539 inst.error = _("dest and source1 must be the same register");
9540 return;
9542 Rs = Rn;
9545 if (inst.instruction == T_OPCODE_MUL
9546 && Rs == Rd)
9547 as_tsktsk (_("Rs and Rd must be different in MUL"));
9549 inst.instruction |= Rd | (Rs << 3);
9550 end_of_line (str);
9553 static void
9554 do_t_add (char * str)
9556 thumb_add_sub (str, 0);
9559 static void
9560 do_t_asr (char * str)
9562 thumb_shift (str, THUMB_ASR);
9565 static void
9566 do_t_branch9 (char * str)
9568 if (my_get_expression (&inst.reloc.exp, &str))
9569 return;
9570 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
9571 inst.reloc.pc_rel = 1;
9572 end_of_line (str);
9575 static void
9576 do_t_branch12 (char * str)
9578 if (my_get_expression (&inst.reloc.exp, &str))
9579 return;
9580 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
9581 inst.reloc.pc_rel = 1;
9582 end_of_line (str);
9585 /* Find the real, Thumb encoded start of a Thumb function. */
9587 static symbolS *
9588 find_real_start (symbolS * symbolP)
9590 char * real_start;
9591 const char * name = S_GET_NAME (symbolP);
9592 symbolS * new_target;
9594 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
9595 #define STUB_NAME ".real_start_of"
9597 if (name == NULL)
9598 abort ();
9600 /* Names that start with '.' are local labels, not function entry points.
9601 The compiler may generate BL instructions to these labels because it
9602 needs to perform a branch to a far away location. */
9603 if (name[0] == '.')
9604 return symbolP;
9606 real_start = malloc (strlen (name) + strlen (STUB_NAME) + 1);
9607 sprintf (real_start, "%s%s", STUB_NAME, name);
9609 new_target = symbol_find (real_start);
9611 if (new_target == NULL)
9613 as_warn ("Failed to find real start of function: %s\n", name);
9614 new_target = symbolP;
9617 free (real_start);
9619 return new_target;
9622 static void
9623 do_t_branch23 (char * str)
9625 if (my_get_expression (& inst.reloc.exp, & str))
9626 return;
9628 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH23;
9629 inst.reloc.pc_rel = 1;
9630 end_of_line (str);
9632 /* If the destination of the branch is a defined symbol which does not have
9633 the THUMB_FUNC attribute, then we must be calling a function which has
9634 the (interfacearm) attribute. We look for the Thumb entry point to that
9635 function and change the branch to refer to that function instead. */
9636 if ( inst.reloc.exp.X_op == O_symbol
9637 && inst.reloc.exp.X_add_symbol != NULL
9638 && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
9639 && ! THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
9640 inst.reloc.exp.X_add_symbol =
9641 find_real_start (inst.reloc.exp.X_add_symbol);
9644 static void
9645 do_t_bx (char * str)
9647 int reg;
9649 skip_whitespace (str);
9651 if ((reg = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9652 return;
9654 /* This sets THUMB_H2 from the top bit of reg. */
9655 inst.instruction |= reg << 3;
9657 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
9658 should cause the alignment to be checked once it is known. This is
9659 because BX PC only works if the instruction is word aligned. */
9661 end_of_line (str);
9664 static void
9665 do_t_compare (char * str)
9667 thumb_mov_compare (str, THUMB_COMPARE);
9670 static void
9671 do_t_ldmstm (char * str)
9673 int Rb;
9674 long range;
9676 skip_whitespace (str);
9678 if ((Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9679 return;
9681 if (*str != '!')
9682 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
9683 else
9684 str++;
9686 if (skip_past_comma (&str) == FAIL
9687 || (range = reg_list (&str)) == FAIL)
9689 if (! inst.error)
9690 inst.error = BAD_ARGS;
9691 return;
9694 if (inst.reloc.type != BFD_RELOC_UNUSED)
9696 /* This really doesn't seem worth it. */
9697 inst.reloc.type = BFD_RELOC_UNUSED;
9698 inst.error = _("expression too complex");
9699 return;
9702 if (range & ~0xff)
9704 inst.error = _("only lo-regs valid in load/store multiple");
9705 return;
9708 inst.instruction |= (Rb << 8) | range;
9709 end_of_line (str);
9712 static void
9713 do_t_ldr (char * str)
9715 thumb_load_store (str, THUMB_LOAD, THUMB_WORD);
9718 static void
9719 do_t_ldrb (char * str)
9721 thumb_load_store (str, THUMB_LOAD, THUMB_BYTE);
9724 static void
9725 do_t_ldrh (char * str)
9727 thumb_load_store (str, THUMB_LOAD, THUMB_HALFWORD);
9730 static void
9731 do_t_lds (char * str)
9733 int Rd, Rb, Ro;
9735 skip_whitespace (str);
9737 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9738 || skip_past_comma (&str) == FAIL
9739 || *str++ != '['
9740 || (Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9741 || skip_past_comma (&str) == FAIL
9742 || (Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9743 || *str++ != ']')
9745 if (! inst.error)
9746 inst.error = _("syntax: ldrs[b] Rd, [Rb, Ro]");
9747 return;
9750 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
9751 end_of_line (str);
9754 static void
9755 do_t_lsl (char * str)
9757 thumb_shift (str, THUMB_LSL);
9760 static void
9761 do_t_lsr (char * str)
9763 thumb_shift (str, THUMB_LSR);
9766 static void
9767 do_t_mov (char * str)
9769 thumb_mov_compare (str, THUMB_MOVE);
9772 static void
9773 do_t_push_pop (char * str)
9775 long range;
9777 skip_whitespace (str);
9779 if ((range = reg_list (&str)) == FAIL)
9781 if (! inst.error)
9782 inst.error = BAD_ARGS;
9783 return;
9786 if (inst.reloc.type != BFD_RELOC_UNUSED)
9788 /* This really doesn't seem worth it. */
9789 inst.reloc.type = BFD_RELOC_UNUSED;
9790 inst.error = _("expression too complex");
9791 return;
9794 if (range & ~0xff)
9796 if ((inst.instruction == T_OPCODE_PUSH
9797 && (range & ~0xff) == 1 << REG_LR)
9798 || (inst.instruction == T_OPCODE_POP
9799 && (range & ~0xff) == 1 << REG_PC))
9801 inst.instruction |= THUMB_PP_PC_LR;
9802 range &= 0xff;
9804 else
9806 inst.error = _("invalid register list to push/pop instruction");
9807 return;
9811 inst.instruction |= range;
9812 end_of_line (str);
9815 static void
9816 do_t_str (char * str)
9818 thumb_load_store (str, THUMB_STORE, THUMB_WORD);
9821 static void
9822 do_t_strb (char * str)
9824 thumb_load_store (str, THUMB_STORE, THUMB_BYTE);
9827 static void
9828 do_t_strh (char * str)
9830 thumb_load_store (str, THUMB_STORE, THUMB_HALFWORD);
9833 static void
9834 do_t_sub (char * str)
9836 thumb_add_sub (str, 1);
9839 static void
9840 do_t_swi (char * str)
9842 skip_whitespace (str);
9844 if (my_get_expression (&inst.reloc.exp, &str))
9845 return;
9847 inst.reloc.type = BFD_RELOC_ARM_SWI;
9848 end_of_line (str);
9851 static void
9852 do_t_adr (char * str)
9854 int reg;
9856 /* This is a pseudo-op of the form "adr rd, label" to be converted
9857 into a relative address of the form "add rd, pc, #label-.-4". */
9858 skip_whitespace (str);
9860 /* Store Rd in temporary location inside instruction. */
9861 if ((reg = reg_required_here (&str, 4)) == FAIL
9862 || (reg > 7) /* For Thumb reg must be r0..r7. */
9863 || skip_past_comma (&str) == FAIL
9864 || my_get_expression (&inst.reloc.exp, &str))
9866 if (!inst.error)
9867 inst.error = BAD_ARGS;
9868 return;
9871 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
9872 inst.reloc.exp.X_add_number -= 4; /* PC relative adjust. */
9873 inst.reloc.pc_rel = 1;
9874 inst.instruction |= REG_PC; /* Rd is already placed into the instruction. */
9876 end_of_line (str);
9879 static void
9880 insert_reg (const struct reg_entry * r,
9881 struct hash_control * htab)
9883 int len = strlen (r->name) + 2;
9884 char * buf = xmalloc (len);
9885 char * buf2 = xmalloc (len);
9886 int i = 0;
9888 #ifdef REGISTER_PREFIX
9889 buf[i++] = REGISTER_PREFIX;
9890 #endif
9892 strcpy (buf + i, r->name);
9894 for (i = 0; buf[i]; i++)
9895 buf2[i] = TOUPPER (buf[i]);
9897 buf2[i] = '\0';
9899 hash_insert (htab, buf, (PTR) r);
9900 hash_insert (htab, buf2, (PTR) r);
9903 static void
9904 build_reg_hsh (struct reg_map * map)
9906 const struct reg_entry *r;
9908 if ((map->htab = hash_new ()) == NULL)
9909 as_fatal (_("virtual memory exhausted"));
9911 for (r = map->names; r->name != NULL; r++)
9912 insert_reg (r, map->htab);
9915 static void
9916 insert_reg_alias (char * str,
9917 int regnum,
9918 struct hash_control *htab)
9920 const char * error;
9921 struct reg_entry * new = xmalloc (sizeof (struct reg_entry));
9922 const char * name = xmalloc (strlen (str) + 1);
9924 strcpy ((char *) name, str);
9926 new->name = name;
9927 new->number = regnum;
9928 new->builtin = FALSE;
9930 error = hash_insert (htab, name, (PTR) new);
9931 if (error)
9933 as_bad (_("failed to create an alias for %s, reason: %s"),
9934 str, error);
9935 free ((char *) name);
9936 free (new);
9940 /* Look for the .req directive. This is of the form:
9942 new_register_name .req existing_register_name
9944 If we find one, or if it looks sufficiently like one that we want to
9945 handle any error here, return non-zero. Otherwise return zero. */
9947 static int
9948 create_register_alias (char * newname, char * p)
9950 char * q;
9951 char c;
9953 q = p;
9954 skip_whitespace (q);
9956 c = *p;
9957 *p = '\0';
9959 if (*q && !strncmp (q, ".req ", 5))
9961 char *copy_of_str;
9962 char *r;
9964 #ifndef IGNORE_OPCODE_CASE
9965 newname = original_case_string;
9966 #endif
9967 copy_of_str = newname;
9969 q += 4;
9970 skip_whitespace (q);
9972 for (r = q; *r != '\0'; r++)
9973 if (*r == ' ')
9974 break;
9976 if (r != q)
9978 enum arm_reg_type new_type, old_type;
9979 int old_regno;
9980 char d = *r;
9982 *r = '\0';
9983 old_type = arm_reg_parse_any (q);
9984 *r = d;
9986 new_type = arm_reg_parse_any (newname);
9988 if (new_type == REG_TYPE_MAX)
9990 if (old_type != REG_TYPE_MAX)
9992 old_regno = arm_reg_parse (&q, all_reg_maps[old_type].htab);
9993 insert_reg_alias (newname, old_regno,
9994 all_reg_maps[old_type].htab);
9996 else
9997 as_warn (_("register '%s' does not exist\n"), q);
9999 else if (old_type == REG_TYPE_MAX)
10001 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
10002 copy_of_str, q);
10004 else
10006 /* Do not warn about redefinitions to the same alias. */
10007 if (new_type != old_type
10008 || (arm_reg_parse (&q, all_reg_maps[old_type].htab)
10009 != arm_reg_parse (&q, all_reg_maps[new_type].htab)))
10010 as_warn (_("ignoring redefinition of register alias '%s'"),
10011 copy_of_str);
10015 else
10016 as_warn (_("ignoring incomplete .req pseuso op"));
10018 *p = c;
10019 return 1;
10022 *p = c;
10023 return 0;
10026 static void
10027 set_constant_flonums (void)
10029 int i;
10031 for (i = 0; i < NUM_FLOAT_VALS; i++)
10032 if (atof_ieee ((char *) fp_const[i], 'x', fp_values[i]) == NULL)
10033 abort ();
10037 static const struct asm_opcode insns[] =
10039 /* Core ARM Instructions. */
10040 {"and", 0xe0000000, 3, ARM_EXT_V1, do_arit},
10041 {"ands", 0xe0100000, 3, ARM_EXT_V1, do_arit},
10042 {"eor", 0xe0200000, 3, ARM_EXT_V1, do_arit},
10043 {"eors", 0xe0300000, 3, ARM_EXT_V1, do_arit},
10044 {"sub", 0xe0400000, 3, ARM_EXT_V1, do_arit},
10045 {"subs", 0xe0500000, 3, ARM_EXT_V1, do_arit},
10046 {"rsb", 0xe0600000, 3, ARM_EXT_V1, do_arit},
10047 {"rsbs", 0xe0700000, 3, ARM_EXT_V1, do_arit},
10048 {"add", 0xe0800000, 3, ARM_EXT_V1, do_arit},
10049 {"adds", 0xe0900000, 3, ARM_EXT_V1, do_arit},
10050 {"adc", 0xe0a00000, 3, ARM_EXT_V1, do_arit},
10051 {"adcs", 0xe0b00000, 3, ARM_EXT_V1, do_arit},
10052 {"sbc", 0xe0c00000, 3, ARM_EXT_V1, do_arit},
10053 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1, do_arit},
10054 {"rsc", 0xe0e00000, 3, ARM_EXT_V1, do_arit},
10055 {"rscs", 0xe0f00000, 3, ARM_EXT_V1, do_arit},
10056 {"orr", 0xe1800000, 3, ARM_EXT_V1, do_arit},
10057 {"orrs", 0xe1900000, 3, ARM_EXT_V1, do_arit},
10058 {"bic", 0xe1c00000, 3, ARM_EXT_V1, do_arit},
10059 {"bics", 0xe1d00000, 3, ARM_EXT_V1, do_arit},
10061 {"tst", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
10062 {"tsts", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
10063 {"tstp", 0xe110f000, 3, ARM_EXT_V1, do_cmp},
10064 {"teq", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
10065 {"teqs", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
10066 {"teqp", 0xe130f000, 3, ARM_EXT_V1, do_cmp},
10067 {"cmp", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
10068 {"cmps", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
10069 {"cmpp", 0xe150f000, 3, ARM_EXT_V1, do_cmp},
10070 {"cmn", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
10071 {"cmns", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
10072 {"cmnp", 0xe170f000, 3, ARM_EXT_V1, do_cmp},
10074 {"mov", 0xe1a00000, 3, ARM_EXT_V1, do_mov},
10075 {"movs", 0xe1b00000, 3, ARM_EXT_V1, do_mov},
10076 {"mvn", 0xe1e00000, 3, ARM_EXT_V1, do_mov},
10077 {"mvns", 0xe1f00000, 3, ARM_EXT_V1, do_mov},
10079 {"ldr", 0xe4100000, 3, ARM_EXT_V1, do_ldst},
10080 {"ldrb", 0xe4500000, 3, ARM_EXT_V1, do_ldst},
10081 {"ldrt", 0xe4300000, 3, ARM_EXT_V1, do_ldstt},
10082 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1, do_ldstt},
10083 {"str", 0xe4000000, 3, ARM_EXT_V1, do_ldst},
10084 {"strb", 0xe4400000, 3, ARM_EXT_V1, do_ldst},
10085 {"strt", 0xe4200000, 3, ARM_EXT_V1, do_ldstt},
10086 {"strbt", 0xe4600000, 3, ARM_EXT_V1, do_ldstt},
10088 {"stmia", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
10089 {"stmib", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
10090 {"stmda", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
10091 {"stmdb", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
10092 {"stmfd", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
10093 {"stmfa", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
10094 {"stmea", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
10095 {"stmed", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
10097 {"ldmia", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
10098 {"ldmib", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
10099 {"ldmda", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
10100 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
10101 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
10102 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
10103 {"ldmea", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
10104 {"ldmed", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
10106 {"swi", 0xef000000, 3, ARM_EXT_V1, do_swi},
10107 #ifdef TE_WINCE
10108 /* XXX This is the wrong place to do this. Think multi-arch. */
10109 {"bl", 0xeb000000, 2, ARM_EXT_V1, do_branch},
10110 {"b", 0xea000000, 1, ARM_EXT_V1, do_branch},
10111 #else
10112 {"bl", 0xebfffffe, 2, ARM_EXT_V1, do_branch},
10113 {"b", 0xeafffffe, 1, ARM_EXT_V1, do_branch},
10114 #endif
10116 /* Pseudo ops. */
10117 {"adr", 0xe28f0000, 3, ARM_EXT_V1, do_adr},
10118 {"adrl", 0xe28f0000, 3, ARM_EXT_V1, do_adrl},
10119 {"nop", 0xe1a00000, 3, ARM_EXT_V1, do_nop},
10121 /* ARM 2 multiplies. */
10122 {"mul", 0xe0000090, 3, ARM_EXT_V2, do_mul},
10123 {"muls", 0xe0100090, 3, ARM_EXT_V2, do_mul},
10124 {"mla", 0xe0200090, 3, ARM_EXT_V2, do_mla},
10125 {"mlas", 0xe0300090, 3, ARM_EXT_V2, do_mla},
10127 /* Generic coprocessor instructions. */
10128 {"cdp", 0xee000000, 3, ARM_EXT_V2, do_cdp},
10129 {"ldc", 0xec100000, 3, ARM_EXT_V2, do_lstc},
10130 {"ldcl", 0xec500000, 3, ARM_EXT_V2, do_lstc},
10131 {"stc", 0xec000000, 3, ARM_EXT_V2, do_lstc},
10132 {"stcl", 0xec400000, 3, ARM_EXT_V2, do_lstc},
10133 {"mcr", 0xee000010, 3, ARM_EXT_V2, do_co_reg},
10134 {"mrc", 0xee100010, 3, ARM_EXT_V2, do_co_reg},
10136 /* ARM 3 - swp instructions. */
10137 {"swp", 0xe1000090, 3, ARM_EXT_V2S, do_swap},
10138 {"swpb", 0xe1400090, 3, ARM_EXT_V2S, do_swap},
10140 /* ARM 6 Status register instructions. */
10141 {"mrs", 0xe10f0000, 3, ARM_EXT_V3, do_mrs},
10142 {"msr", 0xe120f000, 3, ARM_EXT_V3, do_msr},
10143 /* ScottB: our code uses 0xe128f000 for msr.
10144 NickC: but this is wrong because the bits 16 through 19 are
10145 handled by the PSR_xxx defines above. */
10147 /* ARM 7M long multiplies. */
10148 {"smull", 0xe0c00090, 5, ARM_EXT_V3M, do_mull},
10149 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M, do_mull},
10150 {"umull", 0xe0800090, 5, ARM_EXT_V3M, do_mull},
10151 {"umulls", 0xe0900090, 5, ARM_EXT_V3M, do_mull},
10152 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M, do_mull},
10153 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M, do_mull},
10154 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M, do_mull},
10155 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M, do_mull},
10157 /* ARM Architecture 4. */
10158 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4, do_ldstv4},
10159 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4, do_ldstv4},
10160 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4, do_ldstv4},
10161 {"strh", 0xe00000b0, 3, ARM_EXT_V4, do_ldstv4},
10163 /* ARM Architecture 4T. */
10164 /* Note: bx (and blx) are required on V5, even if the processor does
10165 not support Thumb. */
10166 {"bx", 0xe12fff10, 2, ARM_EXT_V4T | ARM_EXT_V5, do_bx},
10168 /* ARM Architecture 5T. */
10169 /* Note: blx has 2 variants, so the .value is set dynamically.
10170 Only one of the variants has conditional execution. */
10171 {"blx", 0xe0000000, 3, ARM_EXT_V5, do_blx},
10172 {"clz", 0xe16f0f10, 3, ARM_EXT_V5, do_clz},
10173 {"bkpt", 0xe1200070, 0, ARM_EXT_V5, do_bkpt},
10174 {"ldc2", 0xfc100000, 0, ARM_EXT_V5, do_lstc2},
10175 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5, do_lstc2},
10176 {"stc2", 0xfc000000, 0, ARM_EXT_V5, do_lstc2},
10177 {"stc2l", 0xfc400000, 0, ARM_EXT_V5, do_lstc2},
10178 {"cdp2", 0xfe000000, 0, ARM_EXT_V5, do_cdp2},
10179 {"mcr2", 0xfe000010, 0, ARM_EXT_V5, do_co_reg2},
10180 {"mrc2", 0xfe100010, 0, ARM_EXT_V5, do_co_reg2},
10182 /* ARM Architecture 5TExP. */
10183 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP, do_smla},
10184 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP, do_smla},
10185 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP, do_smla},
10186 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP, do_smla},
10188 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP, do_smla},
10189 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP, do_smla},
10191 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP, do_smlal},
10192 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP, do_smlal},
10193 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP, do_smlal},
10194 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP, do_smlal},
10196 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP, do_smul},
10197 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP, do_smul},
10198 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP, do_smul},
10199 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP, do_smul},
10201 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP, do_smul},
10202 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP, do_smul},
10204 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP, do_qadd},
10205 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP, do_qadd},
10206 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP, do_qadd},
10207 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP, do_qadd},
10209 /* ARM Architecture 5TE. */
10210 {"pld", 0xf450f000, 0, ARM_EXT_V5E, do_pld},
10211 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E, do_ldrd},
10212 {"strd", 0xe00000f0, 3, ARM_EXT_V5E, do_ldrd},
10214 {"mcrr", 0xec400000, 4, ARM_EXT_V5E, do_co_reg2c},
10215 {"mrrc", 0xec500000, 4, ARM_EXT_V5E, do_co_reg2c},
10217 /* ARM Architecture 5TEJ. */
10218 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J, do_bxj},
10220 /* ARM V6. */
10221 { "cps", 0xf1020000, 0, ARM_EXT_V6, do_cps},
10222 { "cpsie", 0xf1080000, 0, ARM_EXT_V6, do_cpsi},
10223 { "cpsid", 0xf10C0000, 0, ARM_EXT_V6, do_cpsi},
10224 { "ldrex", 0xe1900f9f, 5, ARM_EXT_V6, do_ldrex},
10225 { "mcrr2", 0xfc400000, 0, ARM_EXT_V6, do_co_reg2c},
10226 { "mrrc2", 0xfc500000, 0, ARM_EXT_V6, do_co_reg2c},
10227 { "pkhbt", 0xe6800010, 5, ARM_EXT_V6, do_pkhbt},
10228 { "pkhtb", 0xe6800050, 5, ARM_EXT_V6, do_pkhtb},
10229 { "qadd16", 0xe6200f10, 6, ARM_EXT_V6, do_qadd16},
10230 { "qadd8", 0xe6200f90, 5, ARM_EXT_V6, do_qadd16},
10231 { "qaddsubx", 0xe6200f30, 8, ARM_EXT_V6, do_qadd16},
10232 { "qsub16", 0xe6200f70, 6, ARM_EXT_V6, do_qadd16},
10233 { "qsub8", 0xe6200ff0, 5, ARM_EXT_V6, do_qadd16},
10234 { "qsubaddx", 0xe6200f50, 8, ARM_EXT_V6, do_qadd16},
10235 { "sadd16", 0xe6100f10, 6, ARM_EXT_V6, do_qadd16},
10236 { "sadd8", 0xe6100f90, 5, ARM_EXT_V6, do_qadd16},
10237 { "saddsubx", 0xe6100f30, 8, ARM_EXT_V6, do_qadd16},
10238 { "shadd16", 0xe6300f10, 7, ARM_EXT_V6, do_qadd16},
10239 { "shadd8", 0xe6300f90, 6, ARM_EXT_V6, do_qadd16},
10240 { "shaddsubx", 0xe6300f30, 9, ARM_EXT_V6, do_qadd16},
10241 { "shsub16", 0xe6300f70, 7, ARM_EXT_V6, do_qadd16},
10242 { "shsub8", 0xe6300ff0, 6, ARM_EXT_V6, do_qadd16},
10243 { "shsubaddx", 0xe6300f50, 9, ARM_EXT_V6, do_qadd16},
10244 { "ssub16", 0xe6100f70, 6, ARM_EXT_V6, do_qadd16},
10245 { "ssub8", 0xe6100ff0, 5, ARM_EXT_V6, do_qadd16},
10246 { "ssubaddx", 0xe6100f50, 8, ARM_EXT_V6, do_qadd16},
10247 { "uadd16", 0xe6500f10, 6, ARM_EXT_V6, do_qadd16},
10248 { "uadd8", 0xe6500f90, 5, ARM_EXT_V6, do_qadd16},
10249 { "uaddsubx", 0xe6500f30, 8, ARM_EXT_V6, do_qadd16},
10250 { "uhadd16", 0xe6700f10, 7, ARM_EXT_V6, do_qadd16},
10251 { "uhadd8", 0xe6700f90, 6, ARM_EXT_V6, do_qadd16},
10252 { "uhaddsubx", 0xe6700f30, 9, ARM_EXT_V6, do_qadd16},
10253 { "uhsub16", 0xe6700f70, 7, ARM_EXT_V6, do_qadd16},
10254 { "uhsub8", 0xe6700ff0, 6, ARM_EXT_V6, do_qadd16},
10255 { "uhsubaddx", 0xe6700f50, 9, ARM_EXT_V6, do_qadd16},
10256 { "uqadd16", 0xe6600f10, 7, ARM_EXT_V6, do_qadd16},
10257 { "uqadd8", 0xe6600f90, 6, ARM_EXT_V6, do_qadd16},
10258 { "uqaddsubx", 0xe6600f30, 9, ARM_EXT_V6, do_qadd16},
10259 { "uqsub16", 0xe6600f70, 7, ARM_EXT_V6, do_qadd16},
10260 { "uqsub8", 0xe6600ff0, 6, ARM_EXT_V6, do_qadd16},
10261 { "uqsubaddx", 0xe6600f50, 9, ARM_EXT_V6, do_qadd16},
10262 { "usub16", 0xe6500f70, 6, ARM_EXT_V6, do_qadd16},
10263 { "usub8", 0xe6500ff0, 5, ARM_EXT_V6, do_qadd16},
10264 { "usubaddx", 0xe6500f50, 8, ARM_EXT_V6, do_qadd16},
10265 { "rev", 0xe6bf0f30, 3, ARM_EXT_V6, do_rev},
10266 { "rev16", 0xe6bf0fb0, 5, ARM_EXT_V6, do_rev},
10267 { "revsh", 0xe6ff0fb0, 5, ARM_EXT_V6, do_rev},
10268 { "rfeia", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
10269 { "rfeib", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
10270 { "rfeda", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
10271 { "rfedb", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
10272 { "rfefd", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
10273 { "rfefa", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
10274 { "rfeea", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
10275 { "rfeed", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
10276 { "sxtah", 0xe6b00070, 5, ARM_EXT_V6, do_sxtah},
10277 { "sxtab16", 0xe6800070, 7, ARM_EXT_V6, do_sxtah},
10278 { "sxtab", 0xe6a00070, 5, ARM_EXT_V6, do_sxtah},
10279 { "sxth", 0xe6bf0070, 4, ARM_EXT_V6, do_sxth},
10280 { "sxtb16", 0xe68f0070, 6, ARM_EXT_V6, do_sxth},
10281 { "sxtb", 0xe6af0070, 4, ARM_EXT_V6, do_sxth},
10282 { "uxtah", 0xe6f00070, 5, ARM_EXT_V6, do_sxtah},
10283 { "uxtab16", 0xe6c00070, 7, ARM_EXT_V6, do_sxtah},
10284 { "uxtab", 0xe6e00070, 5, ARM_EXT_V6, do_sxtah},
10285 { "uxth", 0xe6ff0070, 4, ARM_EXT_V6, do_sxth},
10286 { "uxtb16", 0xe6cf0070, 6, ARM_EXT_V6, do_sxth},
10287 { "uxtb", 0xe6ef0070, 4, ARM_EXT_V6, do_sxth},
10288 { "sel", 0xe68000b0, 3, ARM_EXT_V6, do_qadd16},
10289 { "setend", 0xf1010000, 0, ARM_EXT_V6, do_setend},
10290 { "smlad", 0xe7000010, 5, ARM_EXT_V6, do_smlad},
10291 { "smladx", 0xe7000030, 6, ARM_EXT_V6, do_smlad},
10292 { "smlald", 0xe7400010, 6, ARM_EXT_V6, do_smlald},
10293 { "smlaldx", 0xe7400030, 7, ARM_EXT_V6, do_smlald},
10294 { "smlsd", 0xe7000050, 5, ARM_EXT_V6, do_smlad},
10295 { "smlsdx", 0xe7000070, 6, ARM_EXT_V6, do_smlad},
10296 { "smlsld", 0xe7400050, 6, ARM_EXT_V6, do_smlald},
10297 { "smlsldx", 0xe7400070, 7, ARM_EXT_V6, do_smlald},
10298 { "smmla", 0xe7500010, 5, ARM_EXT_V6, do_smlad},
10299 { "smmlar", 0xe7500030, 6, ARM_EXT_V6, do_smlad},
10300 { "smmls", 0xe75000d0, 5, ARM_EXT_V6, do_smlad},
10301 { "smmlsr", 0xe75000f0, 6, ARM_EXT_V6, do_smlad},
10302 { "smmul", 0xe750f010, 5, ARM_EXT_V6, do_smmul},
10303 { "smmulr", 0xe750f030, 6, ARM_EXT_V6, do_smmul},
10304 { "smuad", 0xe700f010, 5, ARM_EXT_V6, do_smmul},
10305 { "smuadx", 0xe700f030, 6, ARM_EXT_V6, do_smmul},
10306 { "smusd", 0xe700f050, 5, ARM_EXT_V6, do_smmul},
10307 { "smusdx", 0xe700f070, 6, ARM_EXT_V6, do_smmul},
10308 { "srsia", 0xf8cd0500, 0, ARM_EXT_V6, do_srs},
10309 { "srsib", 0xf9cd0500, 0, ARM_EXT_V6, do_srs},
10310 { "srsda", 0xf84d0500, 0, ARM_EXT_V6, do_srs},
10311 { "srsdb", 0xf94d0500, 0, ARM_EXT_V6, do_srs},
10312 { "ssat", 0xe6a00010, 4, ARM_EXT_V6, do_ssat},
10313 { "ssat16", 0xe6a00f30, 6, ARM_EXT_V6, do_ssat16},
10314 { "strex", 0xe1800f90, 5, ARM_EXT_V6, do_strex},
10315 { "umaal", 0xe0400090, 5, ARM_EXT_V6, do_umaal},
10316 { "usad8", 0xe780f010, 5, ARM_EXT_V6, do_smmul},
10317 { "usada8", 0xe7800010, 6, ARM_EXT_V6, do_smlad},
10318 { "usat", 0xe6e00010, 4, ARM_EXT_V6, do_usat},
10319 { "usat16", 0xe6e00f30, 6, ARM_EXT_V6, do_usat16},
10321 /* ARM V6K. */
10322 { "clrex", 0xf57ff01f, 0, ARM_EXT_V6K, do_empty},
10323 { "ldrexb", 0xe1d00f9f, 6, ARM_EXT_V6K, do_ldrex},
10324 { "ldrexd", 0xe1b00f9f, 6, ARM_EXT_V6K, do_ldrex},
10325 { "ldrexh", 0xe1f00f9f, 6, ARM_EXT_V6K, do_ldrex},
10326 { "sev", 0xe320f004, 3, ARM_EXT_V6K, do_empty},
10327 { "strexb", 0xe1c00f90, 6, ARM_EXT_V6K, do_strex},
10328 { "strexd", 0xe1a00f90, 6, ARM_EXT_V6K, do_strex},
10329 { "strexh", 0xe1e00f90, 6, ARM_EXT_V6K, do_strex},
10330 { "wfe", 0xe320f002, 3, ARM_EXT_V6K, do_empty},
10331 { "wfi", 0xe320f003, 3, ARM_EXT_V6K, do_empty},
10332 { "yield", 0xe320f001, 5, ARM_EXT_V6K, do_empty},
10334 /* ARM V6Z. */
10335 { "smi", 0xe1600070, 3, ARM_EXT_V6Z, do_smi},
10337 /* ARM V6T2. */
10338 { "bfc", 0xe7c0001f, 3, ARM_EXT_V6T2, do_bfc},
10339 { "bfi", 0xe7c00010, 3, ARM_EXT_V6T2, do_bfi},
10340 { "mls", 0xe0600090, 3, ARM_EXT_V6T2, do_mls},
10341 { "movw", 0xe3000000, 4, ARM_EXT_V6T2, do_mov16},
10342 { "movt", 0xe3400000, 4, ARM_EXT_V6T2, do_mov16},
10343 { "rbit", 0xe3ff0f30, 4, ARM_EXT_V6T2, do_rbit},
10344 { "sbfx", 0xe7a00050, 4, ARM_EXT_V6T2, do_bfx},
10345 { "ubfx", 0xe7e00050, 4, ARM_EXT_V6T2, do_bfx},
10347 { "ldrht", 0xe03000b0, 3, ARM_EXT_V6T2, do_ldsttv4},
10348 { "ldrsht", 0xe03000f0, 3, ARM_EXT_V6T2, do_ldsttv4},
10349 { "ldrsbt", 0xe03000d0, 3, ARM_EXT_V6T2, do_ldsttv4},
10350 { "strht", 0xe02000b0, 3, ARM_EXT_V6T2, do_ldsttv4},
10352 /* Core FPA instruction set (V1). */
10353 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10354 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10355 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10356 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10358 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10359 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10360 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10361 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10363 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10364 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10365 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10366 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10368 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10369 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10370 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10371 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10372 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10373 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10374 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10375 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10376 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10377 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10378 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10379 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10381 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10382 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10383 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10384 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10385 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10386 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10387 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10388 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10389 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10390 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10391 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10392 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10394 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10395 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10396 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10397 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10398 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10399 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10400 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10401 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10402 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10403 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10404 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10405 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10407 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10408 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10409 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10410 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10411 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10412 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10413 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10414 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10415 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10416 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10417 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10418 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10420 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10421 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10422 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10423 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10424 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10425 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10426 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10427 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10428 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10429 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10430 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10431 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10433 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10434 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10435 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10436 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10437 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10438 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10439 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10440 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10441 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10442 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10443 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10444 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10446 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10447 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10448 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10449 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10450 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10451 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10452 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10453 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10454 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10455 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10456 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10457 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10459 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10460 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10461 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10462 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10463 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10464 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10465 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10466 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10467 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10468 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10469 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10470 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10472 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10473 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10474 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10475 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10476 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10477 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10478 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10479 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10480 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10481 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10482 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10483 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10485 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10486 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10487 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10488 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10489 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10490 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10491 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10492 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10493 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10494 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10495 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10496 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10498 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10499 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10500 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10501 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10502 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10503 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10504 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10505 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10506 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10507 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10508 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10509 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10511 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10512 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10513 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10514 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10515 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10516 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10517 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10518 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10519 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10520 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10521 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10522 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10524 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10525 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10526 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10527 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10528 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10529 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10530 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10531 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10532 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10533 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10534 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10535 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10537 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10538 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10539 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10540 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10541 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10542 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10543 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10544 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10545 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10546 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10547 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10548 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10550 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10551 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10552 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10553 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10554 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10555 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10556 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10557 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10558 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10559 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10560 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10561 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10563 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10564 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10565 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10566 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10567 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10568 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10569 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10570 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10571 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10572 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10573 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10574 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10576 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10577 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10578 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10579 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10580 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10581 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10582 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10583 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10584 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10585 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10586 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10587 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10589 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10590 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10591 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10592 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10593 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10594 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10595 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10596 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10597 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10598 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10599 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10600 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10602 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10603 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10604 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10605 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10606 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10607 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10608 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10609 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10610 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10611 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10612 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10613 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10615 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10616 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10617 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10618 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10619 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10620 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10621 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10622 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10623 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10624 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10625 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10626 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10628 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10629 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10630 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10631 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10632 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10633 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10634 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10635 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10636 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10637 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10638 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10639 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10641 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10642 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10643 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10644 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10645 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10646 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10647 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10648 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10649 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10650 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10651 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10652 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10654 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10655 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10656 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10657 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10658 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10659 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10660 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10661 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10662 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10663 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10664 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10665 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10667 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10668 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10669 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10670 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10671 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10672 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10673 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10674 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10675 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10676 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10677 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10678 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10680 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10681 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10682 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10683 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10684 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10685 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10686 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10687 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10688 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10689 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10690 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10691 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10693 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10694 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10695 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10696 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10697 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10698 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10699 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10700 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10701 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10702 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10703 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10704 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10706 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10707 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10708 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10709 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10710 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10711 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10712 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10713 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10714 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10715 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10716 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10717 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10719 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10720 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10721 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10722 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10723 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10724 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10725 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10726 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10727 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10728 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10729 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10730 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10732 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10733 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10734 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10735 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10736 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10737 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10738 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10739 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10740 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10741 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10742 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10743 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10745 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10746 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10747 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10748 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10749 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
10750 not be an optional suffix, but part of the instruction. To be
10751 compatible, we accept either. */
10752 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
10753 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
10755 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10756 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10757 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10758 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10759 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10760 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10761 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10762 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10763 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10764 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10765 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10766 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10768 /* The implementation of the FIX instruction is broken on some
10769 assemblers, in that it accepts a precision specifier as well as a
10770 rounding specifier, despite the fact that this is meaningless.
10771 To be more compatible, we accept it as well, though of course it
10772 does not set any bits. */
10773 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10774 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10775 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10776 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10777 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10778 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10779 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10780 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10781 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10782 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10783 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10784 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10785 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10787 /* Instructions that were new with the real FPA, call them V2. */
10788 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10789 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10790 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10791 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10792 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10793 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10795 /* VFP V1xD (single precision). */
10796 /* Moves and type conversions. */
10797 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10798 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_sp},
10799 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_from_reg},
10800 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD, do_empty},
10801 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10802 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10803 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10804 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10805 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10806 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10807 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_ctrl},
10808 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_ctrl_from_reg},
10810 /* Memory operations. */
10811 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
10812 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
10813 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10814 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10815 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10816 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10817 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10818 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10819 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10820 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10821 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10822 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10823 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10824 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10825 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10826 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10827 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10828 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10830 /* Monadic operations. */
10831 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10832 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10833 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10835 /* Dyadic operations. */
10836 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10837 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10838 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10839 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10840 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10841 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10842 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10843 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10844 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10846 /* Comparisons. */
10847 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10848 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
10849 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10850 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
10852 /* VFP V1 (Double precision). */
10853 /* Moves and type conversions. */
10854 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10855 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
10856 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10857 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
10858 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
10859 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
10860 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
10861 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
10862 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
10863 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10864 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10865 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10866 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10868 /* Memory operations. */
10869 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
10870 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
10871 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10872 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10873 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10874 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10875 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10876 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10877 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10878 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10880 /* Monadic operations. */
10881 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10882 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10883 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10885 /* Dyadic operations. */
10886 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10887 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10888 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10889 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10890 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10891 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10892 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10893 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10894 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10896 /* Comparisons. */
10897 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10898 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
10899 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10900 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
10902 /* VFP V2. */
10903 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2, do_vfp_sp2_from_reg2},
10904 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_sp2},
10905 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2, do_vfp_dp_from_reg2},
10906 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_dp},
10908 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
10909 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE, do_xsc_mia},
10910 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10911 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10912 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10913 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10914 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10915 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE, do_xsc_mar},
10916 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE, do_xsc_mra},
10918 /* Intel Wireless MMX technology instructions. */
10919 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
10920 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
10921 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
10922 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
10923 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
10924 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
10925 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
10926 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
10927 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
10928 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10929 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10930 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10931 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10932 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10933 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10934 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
10935 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
10936 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
10937 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmcr},
10938 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmcrr},
10939 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10940 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10941 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10942 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10943 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10944 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10945 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
10946 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
10947 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
10948 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmrc},
10949 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmrrc},
10950 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
10951 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
10952 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
10953 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10954 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10955 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10956 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10957 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10958 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10959 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10960 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10961 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10962 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10963 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10964 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10965 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT, do_iwmmxt_waligni},
10966 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10967 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10968 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10969 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10970 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10971 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10972 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10973 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10974 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10975 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10976 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10977 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10978 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10979 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10980 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10981 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10982 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10983 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10984 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10985 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
10986 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
10987 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
10988 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
10989 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10990 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10991 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10992 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10993 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10994 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10995 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10996 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10997 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10998 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10999 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11000 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11001 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11002 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11003 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11004 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11005 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11006 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11007 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wmov},
11008 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11009 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11010 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11011 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11012 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11013 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11014 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11015 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11016 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11017 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11018 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11019 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11020 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11021 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11022 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11023 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11024 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11025 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11026 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11027 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11028 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11029 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wshufh},
11030 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11031 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11032 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11033 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11034 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11035 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11036 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11037 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11038 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11039 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11040 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11041 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11042 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11043 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11044 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11045 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11046 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11047 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11048 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
11049 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
11050 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
11051 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
11052 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11053 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11054 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11055 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11056 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11057 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11058 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11059 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11060 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11061 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11062 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11063 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11064 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11065 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11066 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11067 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11068 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11069 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11070 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11071 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11072 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11073 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11074 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11075 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11076 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11077 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11078 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11079 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11080 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wzero},
11082 /* Cirrus Maverick instructions. */
11083 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
11084 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
11085 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
11086 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
11087 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
11088 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
11089 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
11090 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
11091 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK, do_mav_binops_2a},
11092 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK, do_mav_binops_1a},
11093 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
11094 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
11095 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
11096 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
11097 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
11098 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
11099 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
11100 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
11101 {"cfmval32", 0xee200440, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
11102 {"cfmv32al", 0xee100440, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
11103 {"cfmvam32", 0xee200460, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
11104 {"cfmv32am", 0xee100460, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
11105 {"cfmvah32", 0xee200480, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
11106 {"cfmv32ah", 0xee100480, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
11107 {"cfmva32", 0xee2004a0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3a},
11108 {"cfmv32a", 0xee1004a0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3b},
11109 {"cfmva64", 0xee2004c0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3c},
11110 {"cfmv64a", 0xee1004c0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3d},
11111 {"cfmvsc32", 0xee2004e0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_1},
11112 {"cfmv32sc", 0xee1004e0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_2},
11113 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
11114 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
11115 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK, do_mav_binops_1f},
11116 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK, do_mav_binops_1g},
11117 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK, do_mav_binops_1h},
11118 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1i},
11119 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1j},
11120 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1k},
11121 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK, do_mav_binops_1l},
11122 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1m},
11123 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1l},
11124 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1m},
11125 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK, do_mav_triple_4a},
11126 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK, do_mav_triple_4b},
11127 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK, do_mav_shift_1},
11128 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK, do_mav_shift_2},
11129 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK, do_mav_triple_5a},
11130 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5b},
11131 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK, do_mav_triple_5c},
11132 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5d},
11133 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
11134 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
11135 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
11136 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
11137 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
11138 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
11139 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
11140 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
11141 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
11142 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
11143 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
11144 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
11145 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
11146 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
11147 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
11148 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
11149 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
11150 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
11151 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
11152 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
11153 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
11154 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
11155 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
11156 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
11157 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
11158 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
11161 /* Iterate over the base tables to create the instruction patterns. */
11163 static void
11164 build_arm_ops_hsh (void)
11166 unsigned int i;
11167 unsigned int j;
11168 static struct obstack insn_obstack;
11170 obstack_begin (&insn_obstack, 4000);
11172 for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
11174 const struct asm_opcode *insn = insns + i;
11176 if (insn->cond_offset != 0)
11178 /* Insn supports conditional execution. Build the varaints
11179 and insert them in the hash table. */
11180 for (j = 0; j < sizeof (conds) / sizeof (struct asm_cond); j++)
11182 unsigned len = strlen (insn->template);
11183 struct asm_opcode *new;
11184 char *template;
11186 new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
11187 /* All condition codes are two characters. */
11188 template = obstack_alloc (&insn_obstack, len + 3);
11190 strncpy (template, insn->template, insn->cond_offset);
11191 strcpy (template + insn->cond_offset, conds[j].template);
11192 if (len > insn->cond_offset)
11193 strcpy (template + insn->cond_offset + 2,
11194 insn->template + insn->cond_offset);
11195 new->template = template;
11196 new->cond_offset = 0;
11197 new->variant = insn->variant;
11198 new->parms = insn->parms;
11199 new->value = (insn->value & ~COND_MASK) | conds[j].value;
11201 hash_insert (arm_ops_hsh, new->template, (PTR) new);
11204 /* Finally, insert the unconditional insn in the table directly;
11205 no need to build a copy. */
11206 hash_insert (arm_ops_hsh, insn->template, (PTR) insn);
11211 static const struct thumb_opcode tinsns[] =
11213 /* Thumb v1 (ARMv4T). */
11214 {"adc", 0x4140, 2, ARM_EXT_V4T, do_t_arit},
11215 {"add", 0x0000, 2, ARM_EXT_V4T, do_t_add},
11216 {"and", 0x4000, 2, ARM_EXT_V4T, do_t_arit},
11217 {"asr", 0x0000, 2, ARM_EXT_V4T, do_t_asr},
11218 {"b", T_OPCODE_BRANCH, 2, ARM_EXT_V4T, do_t_branch12},
11219 {"beq", 0xd0fe, 2, ARM_EXT_V4T, do_t_branch9},
11220 {"bne", 0xd1fe, 2, ARM_EXT_V4T, do_t_branch9},
11221 {"bcs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
11222 {"bhs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
11223 {"bcc", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
11224 {"bul", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
11225 {"blo", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
11226 {"bmi", 0xd4fe, 2, ARM_EXT_V4T, do_t_branch9},
11227 {"bpl", 0xd5fe, 2, ARM_EXT_V4T, do_t_branch9},
11228 {"bvs", 0xd6fe, 2, ARM_EXT_V4T, do_t_branch9},
11229 {"bvc", 0xd7fe, 2, ARM_EXT_V4T, do_t_branch9},
11230 {"bhi", 0xd8fe, 2, ARM_EXT_V4T, do_t_branch9},
11231 {"bls", 0xd9fe, 2, ARM_EXT_V4T, do_t_branch9},
11232 {"bge", 0xdafe, 2, ARM_EXT_V4T, do_t_branch9},
11233 {"blt", 0xdbfe, 2, ARM_EXT_V4T, do_t_branch9},
11234 {"bgt", 0xdcfe, 2, ARM_EXT_V4T, do_t_branch9},
11235 {"ble", 0xddfe, 2, ARM_EXT_V4T, do_t_branch9},
11236 {"bal", 0xdefe, 2, ARM_EXT_V4T, do_t_branch9},
11237 {"bic", 0x4380, 2, ARM_EXT_V4T, do_t_arit},
11238 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T, do_t_branch23},
11239 {"bx", 0x4700, 2, ARM_EXT_V4T, do_t_bx},
11240 {"cmn", T_OPCODE_CMN, 2, ARM_EXT_V4T, do_t_arit},
11241 {"cmp", 0x0000, 2, ARM_EXT_V4T, do_t_compare},
11242 {"eor", 0x4040, 2, ARM_EXT_V4T, do_t_arit},
11243 {"ldmia", 0xc800, 2, ARM_EXT_V4T, do_t_ldmstm},
11244 {"ldr", 0x0000, 2, ARM_EXT_V4T, do_t_ldr},
11245 {"ldrb", 0x0000, 2, ARM_EXT_V4T, do_t_ldrb},
11246 {"ldrh", 0x0000, 2, ARM_EXT_V4T, do_t_ldrh},
11247 {"ldrsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
11248 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
11249 {"ldsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
11250 {"ldsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
11251 {"lsl", 0x0000, 2, ARM_EXT_V4T, do_t_lsl},
11252 {"lsr", 0x0000, 2, ARM_EXT_V4T, do_t_lsr},
11253 {"mov", 0x0000, 2, ARM_EXT_V4T, do_t_mov},
11254 {"mul", T_OPCODE_MUL, 2, ARM_EXT_V4T, do_t_arit},
11255 {"mvn", T_OPCODE_MVN, 2, ARM_EXT_V4T, do_t_arit},
11256 {"neg", T_OPCODE_NEG, 2, ARM_EXT_V4T, do_t_arit},
11257 {"orr", 0x4300, 2, ARM_EXT_V4T, do_t_arit},
11258 {"pop", 0xbc00, 2, ARM_EXT_V4T, do_t_push_pop},
11259 {"push", 0xb400, 2, ARM_EXT_V4T, do_t_push_pop},
11260 {"ror", 0x41c0, 2, ARM_EXT_V4T, do_t_arit},
11261 {"sbc", 0x4180, 2, ARM_EXT_V4T, do_t_arit},
11262 {"stmia", 0xc000, 2, ARM_EXT_V4T, do_t_ldmstm},
11263 {"str", 0x0000, 2, ARM_EXT_V4T, do_t_str},
11264 {"strb", 0x0000, 2, ARM_EXT_V4T, do_t_strb},
11265 {"strh", 0x0000, 2, ARM_EXT_V4T, do_t_strh},
11266 {"swi", 0xdf00, 2, ARM_EXT_V4T, do_t_swi},
11267 {"sub", 0x0000, 2, ARM_EXT_V4T, do_t_sub},
11268 {"tst", T_OPCODE_TST, 2, ARM_EXT_V4T, do_t_arit},
11269 /* Pseudo ops: */
11270 {"adr", 0x0000, 2, ARM_EXT_V4T, do_t_adr},
11271 {"nop", 0x46C0, 2, ARM_EXT_V4T, do_t_nop}, /* mov r8,r8 */
11272 /* Thumb v2 (ARMv5T). */
11273 {"blx", 0, 0, ARM_EXT_V5T, do_t_blx},
11274 {"bkpt", 0xbe00, 2, ARM_EXT_V5T, do_t_bkpt},
11276 /* ARM V6. */
11277 {"cpsie", 0xb660, 2, ARM_EXT_V6, do_t_cps},
11278 {"cpsid", 0xb670, 2, ARM_EXT_V6, do_t_cps},
11279 {"cpy", 0x4600, 2, ARM_EXT_V6, do_t_cpy},
11280 {"rev", 0xba00, 2, ARM_EXT_V6, do_t_arit},
11281 {"rev16", 0xba40, 2, ARM_EXT_V6, do_t_arit},
11282 {"revsh", 0xbac0, 2, ARM_EXT_V6, do_t_arit},
11283 {"setend", 0xb650, 2, ARM_EXT_V6, do_t_setend},
11284 {"sxth", 0xb200, 2, ARM_EXT_V6, do_t_arit},
11285 {"sxtb", 0xb240, 2, ARM_EXT_V6, do_t_arit},
11286 {"uxth", 0xb280, 2, ARM_EXT_V6, do_t_arit},
11287 {"uxtb", 0xb2c0, 2, ARM_EXT_V6, do_t_arit},
11289 /* ARM V6K. */
11290 {"sev", 0xbf40, 2, ARM_EXT_V6K, do_empty},
11291 {"wfe", 0xbf20, 2, ARM_EXT_V6K, do_empty},
11292 {"wfi", 0xbf30, 2, ARM_EXT_V6K, do_empty},
11293 {"yield", 0xbf10, 2, ARM_EXT_V6K, do_empty},
11296 void
11297 md_begin (void)
11299 unsigned mach;
11300 unsigned int i;
11302 if ( (arm_ops_hsh = hash_new ()) == NULL
11303 || (arm_tops_hsh = hash_new ()) == NULL
11304 || (arm_cond_hsh = hash_new ()) == NULL
11305 || (arm_shift_hsh = hash_new ()) == NULL
11306 || (arm_psr_hsh = hash_new ()) == NULL)
11307 as_fatal (_("virtual memory exhausted"));
11309 build_arm_ops_hsh ();
11310 for (i = 0; i < sizeof (tinsns) / sizeof (struct thumb_opcode); i++)
11311 hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
11312 for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
11313 hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
11314 for (i = 0; i < sizeof (shift_names) / sizeof (struct asm_shift_name); i++)
11315 hash_insert (arm_shift_hsh, shift_names[i].name, (PTR) (shift_names + i));
11316 for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
11317 hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
11319 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
11320 build_reg_hsh (all_reg_maps + i);
11322 set_constant_flonums ();
11324 /* Set the cpu variant based on the command-line options. We prefer
11325 -mcpu= over -march= if both are set (as for GCC); and we prefer
11326 -mfpu= over any other way of setting the floating point unit.
11327 Use of legacy options with new options are faulted. */
11328 if (legacy_cpu != -1)
11330 if (mcpu_cpu_opt != -1 || march_cpu_opt != -1)
11331 as_bad (_("use of old and new-style options to set CPU type"));
11333 mcpu_cpu_opt = legacy_cpu;
11335 else if (mcpu_cpu_opt == -1)
11336 mcpu_cpu_opt = march_cpu_opt;
11338 if (legacy_fpu != -1)
11340 if (mfpu_opt != -1)
11341 as_bad (_("use of old and new-style options to set FPU type"));
11343 mfpu_opt = legacy_fpu;
11345 else if (mfpu_opt == -1)
11347 #if !(defined (TE_LINUX) || defined (TE_NetBSD) || defined (TE_VXWORKS))
11348 /* Some environments specify a default FPU. If they don't, infer it
11349 from the processor. */
11350 if (mcpu_fpu_opt != -1)
11351 mfpu_opt = mcpu_fpu_opt;
11352 else
11353 mfpu_opt = march_fpu_opt;
11354 #else
11355 mfpu_opt = FPU_DEFAULT;
11356 #endif
11359 if (mfpu_opt == -1)
11361 if (mcpu_cpu_opt == -1)
11362 mfpu_opt = FPU_DEFAULT;
11363 else if (mcpu_cpu_opt & ARM_EXT_V5)
11364 mfpu_opt = FPU_ARCH_VFP_V2;
11365 else
11366 mfpu_opt = FPU_ARCH_FPA;
11369 if (mcpu_cpu_opt == -1)
11370 mcpu_cpu_opt = CPU_DEFAULT;
11372 cpu_variant = mcpu_cpu_opt | mfpu_opt;
11374 #if defined OBJ_COFF || defined OBJ_ELF
11376 unsigned int flags = 0;
11378 #if defined OBJ_ELF
11379 flags = meabi_flags;
11381 switch (meabi_flags)
11383 case EF_ARM_EABI_UNKNOWN:
11384 #endif
11385 /* Set the flags in the private structure. */
11386 if (uses_apcs_26) flags |= F_APCS26;
11387 if (support_interwork) flags |= F_INTERWORK;
11388 if (uses_apcs_float) flags |= F_APCS_FLOAT;
11389 if (pic_code) flags |= F_PIC;
11390 if ((cpu_variant & FPU_ANY) == FPU_NONE
11391 || (cpu_variant & FPU_ANY) == FPU_ARCH_VFP) /* VFP layout only. */
11392 flags |= F_SOFT_FLOAT;
11394 switch (mfloat_abi_opt)
11396 case ARM_FLOAT_ABI_SOFT:
11397 case ARM_FLOAT_ABI_SOFTFP:
11398 flags |= F_SOFT_FLOAT;
11399 break;
11401 case ARM_FLOAT_ABI_HARD:
11402 if (flags & F_SOFT_FLOAT)
11403 as_bad (_("hard-float conflicts with specified fpu"));
11404 break;
11407 /* Using VFP conventions (even if soft-float). */
11408 if (cpu_variant & FPU_VFP_EXT_NONE)
11409 flags |= F_VFP_FLOAT;
11411 #if defined OBJ_ELF
11412 if (cpu_variant & FPU_ARCH_MAVERICK)
11413 flags |= EF_ARM_MAVERICK_FLOAT;
11414 break;
11416 case EF_ARM_EABI_VER4:
11417 /* No additional flags to set. */
11418 break;
11420 default:
11421 abort ();
11423 #endif
11424 bfd_set_private_flags (stdoutput, flags);
11426 /* We have run out flags in the COFF header to encode the
11427 status of ATPCS support, so instead we create a dummy,
11428 empty, debug section called .arm.atpcs. */
11429 if (atpcs)
11431 asection * sec;
11433 sec = bfd_make_section (stdoutput, ".arm.atpcs");
11435 if (sec != NULL)
11437 bfd_set_section_flags
11438 (stdoutput, sec, SEC_READONLY | SEC_DEBUGGING /* | SEC_HAS_CONTENTS */);
11439 bfd_set_section_size (stdoutput, sec, 0);
11440 bfd_set_section_contents (stdoutput, sec, NULL, 0, 0);
11444 #endif
11446 /* Record the CPU type as well. */
11447 switch (cpu_variant & ARM_CPU_MASK)
11449 case ARM_2:
11450 mach = bfd_mach_arm_2;
11451 break;
11453 case ARM_3: /* Also ARM_250. */
11454 mach = bfd_mach_arm_2a;
11455 break;
11457 case ARM_6: /* Also ARM_7. */
11458 mach = bfd_mach_arm_3;
11459 break;
11461 default:
11462 mach = bfd_mach_arm_unknown;
11463 break;
11466 /* Catch special cases. */
11467 if (cpu_variant & ARM_CEXT_IWMMXT)
11468 mach = bfd_mach_arm_iWMMXt;
11469 else if (cpu_variant & ARM_CEXT_XSCALE)
11470 mach = bfd_mach_arm_XScale;
11471 else if (cpu_variant & ARM_CEXT_MAVERICK)
11472 mach = bfd_mach_arm_ep9312;
11473 else if (cpu_variant & ARM_EXT_V5E)
11474 mach = bfd_mach_arm_5TE;
11475 else if (cpu_variant & ARM_EXT_V5)
11477 if (cpu_variant & ARM_EXT_V4T)
11478 mach = bfd_mach_arm_5T;
11479 else
11480 mach = bfd_mach_arm_5;
11482 else if (cpu_variant & ARM_EXT_V4)
11484 if (cpu_variant & ARM_EXT_V4T)
11485 mach = bfd_mach_arm_4T;
11486 else
11487 mach = bfd_mach_arm_4;
11489 else if (cpu_variant & ARM_EXT_V3M)
11490 mach = bfd_mach_arm_3M;
11492 bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
11495 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11496 for use in the a.out file, and stores them in the array pointed to by buf.
11497 This knows about the endian-ness of the target machine and does
11498 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11499 2 (short) and 4 (long) Floating numbers are put out as a series of
11500 LITTLENUMS (shorts, here at least). */
11502 void
11503 md_number_to_chars (char * buf, valueT val, int n)
11505 if (target_big_endian)
11506 number_to_chars_bigendian (buf, val, n);
11507 else
11508 number_to_chars_littleendian (buf, val, n);
11511 static valueT
11512 md_chars_to_number (char * buf, int n)
11514 valueT result = 0;
11515 unsigned char * where = (unsigned char *) buf;
11517 if (target_big_endian)
11519 while (n--)
11521 result <<= 8;
11522 result |= (*where++ & 255);
11525 else
11527 while (n--)
11529 result <<= 8;
11530 result |= (where[n] & 255);
11534 return result;
11537 /* Turn a string in input_line_pointer into a floating point constant
11538 of type TYPE, and store the appropriate bytes in *LITP. The number
11539 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11540 returned, or NULL on OK.
11542 Note that fp constants aren't represent in the normal way on the ARM.
11543 In big endian mode, things are as expected. However, in little endian
11544 mode fp constants are big-endian word-wise, and little-endian byte-wise
11545 within the words. For example, (double) 1.1 in big endian mode is
11546 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11547 the byte sequence 99 99 f1 3f 9a 99 99 99.
11549 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11551 char *
11552 md_atof (int type, char * litP, int * sizeP)
11554 int prec;
11555 LITTLENUM_TYPE words[MAX_LITTLENUMS];
11556 char *t;
11557 int i;
11559 switch (type)
11561 case 'f':
11562 case 'F':
11563 case 's':
11564 case 'S':
11565 prec = 2;
11566 break;
11568 case 'd':
11569 case 'D':
11570 case 'r':
11571 case 'R':
11572 prec = 4;
11573 break;
11575 case 'x':
11576 case 'X':
11577 prec = 6;
11578 break;
11580 case 'p':
11581 case 'P':
11582 prec = 6;
11583 break;
11585 default:
11586 *sizeP = 0;
11587 return _("bad call to MD_ATOF()");
11590 t = atof_ieee (input_line_pointer, type, words);
11591 if (t)
11592 input_line_pointer = t;
11593 *sizeP = prec * 2;
11595 if (target_big_endian)
11597 for (i = 0; i < prec; i++)
11599 md_number_to_chars (litP, (valueT) words[i], 2);
11600 litP += 2;
11603 else
11605 if (cpu_variant & FPU_ARCH_VFP)
11606 for (i = prec - 1; i >= 0; i--)
11608 md_number_to_chars (litP, (valueT) words[i], 2);
11609 litP += 2;
11611 else
11612 /* For a 4 byte float the order of elements in `words' is 1 0.
11613 For an 8 byte float the order is 1 0 3 2. */
11614 for (i = 0; i < prec; i += 2)
11616 md_number_to_chars (litP, (valueT) words[i + 1], 2);
11617 md_number_to_chars (litP + 2, (valueT) words[i], 2);
11618 litP += 4;
11622 return 0;
11625 /* The knowledge of the PC's pipeline offset is built into the insns
11626 themselves. */
11628 long
11629 md_pcrel_from (fixS * fixP)
11631 if (fixP->fx_addsy
11632 && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section
11633 && fixP->fx_subsy == NULL)
11634 return 0;
11636 if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD))
11638 /* PC relative addressing on the Thumb is slightly odd
11639 as the bottom two bits of the PC are forced to zero
11640 for the calculation. */
11641 return (fixP->fx_where + fixP->fx_frag->fr_address) & ~3;
11644 #ifdef TE_WINCE
11645 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
11646 so we un-adjust here to compensate for the accommodation. */
11647 return fixP->fx_where + fixP->fx_frag->fr_address + 8;
11648 #else
11649 return fixP->fx_where + fixP->fx_frag->fr_address;
11650 #endif
11653 /* Round up a section size to the appropriate boundary. */
11655 valueT
11656 md_section_align (segT segment ATTRIBUTE_UNUSED,
11657 valueT size)
11659 #ifdef OBJ_ELF
11660 return size;
11661 #else
11662 /* Round all sects to multiple of 4. */
11663 return (size + 3) & ~3;
11664 #endif
11667 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
11668 Otherwise we have no need to default values of symbols. */
11670 symbolS *
11671 md_undefined_symbol (char * name ATTRIBUTE_UNUSED)
11673 #ifdef OBJ_ELF
11674 if (name[0] == '_' && name[1] == 'G'
11675 && streq (name, GLOBAL_OFFSET_TABLE_NAME))
11677 if (!GOT_symbol)
11679 if (symbol_find (name))
11680 as_bad ("GOT already in the symbol table");
11682 GOT_symbol = symbol_new (name, undefined_section,
11683 (valueT) 0, & zero_address_frag);
11686 return GOT_symbol;
11688 #endif
11690 return 0;
11693 void
11694 md_apply_fix3 (fixS * fixP,
11695 valueT * valP,
11696 segT seg)
11698 offsetT value = * valP;
11699 offsetT newval;
11700 unsigned int newimm;
11701 unsigned long temp;
11702 int sign;
11703 char * buf = fixP->fx_where + fixP->fx_frag->fr_literal;
11704 arm_fix_data * arm_data = (arm_fix_data *) fixP->tc_fix_data;
11706 assert (fixP->fx_r_type <= BFD_RELOC_UNUSED);
11708 /* Note whether this will delete the relocation. */
11709 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
11710 fixP->fx_done = 1;
11712 /* If this symbol is in a different section then we need to leave it for
11713 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
11714 so we have to undo it's effects here. */
11715 if (fixP->fx_pcrel)
11717 if (fixP->fx_addsy != NULL
11718 && S_IS_DEFINED (fixP->fx_addsy)
11719 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
11720 value += md_pcrel_from (fixP);
11723 /* Remember value for emit_reloc. */
11724 fixP->fx_addnumber = value;
11726 switch (fixP->fx_r_type)
11728 case BFD_RELOC_NONE:
11729 /* This will need to go in the object file. */
11730 fixP->fx_done = 0;
11731 break;
11733 case BFD_RELOC_ARM_IMMEDIATE:
11734 /* We claim that this fixup has been processed here,
11735 even if in fact we generate an error because we do
11736 not have a reloc for it, so tc_gen_reloc will reject it. */
11737 fixP->fx_done = 1;
11739 if (fixP->fx_addsy
11740 && ! S_IS_DEFINED (fixP->fx_addsy))
11742 as_bad_where (fixP->fx_file, fixP->fx_line,
11743 _("undefined symbol %s used as an immediate value"),
11744 S_GET_NAME (fixP->fx_addsy));
11745 break;
11748 newimm = validate_immediate (value);
11749 temp = md_chars_to_number (buf, INSN_SIZE);
11751 /* If the instruction will fail, see if we can fix things up by
11752 changing the opcode. */
11753 if (newimm == (unsigned int) FAIL
11754 && (newimm = negate_data_op (&temp, value)) == (unsigned int) FAIL)
11756 as_bad_where (fixP->fx_file, fixP->fx_line,
11757 _("invalid constant (%lx) after fixup"),
11758 (unsigned long) value);
11759 break;
11762 newimm |= (temp & 0xfffff000);
11763 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
11764 break;
11766 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
11768 unsigned int highpart = 0;
11769 unsigned int newinsn = 0xe1a00000; /* nop. */
11771 newimm = validate_immediate (value);
11772 temp = md_chars_to_number (buf, INSN_SIZE);
11774 /* If the instruction will fail, see if we can fix things up by
11775 changing the opcode. */
11776 if (newimm == (unsigned int) FAIL
11777 && (newimm = negate_data_op (& temp, value)) == (unsigned int) FAIL)
11779 /* No ? OK - try using two ADD instructions to generate
11780 the value. */
11781 newimm = validate_immediate_twopart (value, & highpart);
11783 /* Yes - then make sure that the second instruction is
11784 also an add. */
11785 if (newimm != (unsigned int) FAIL)
11786 newinsn = temp;
11787 /* Still No ? Try using a negated value. */
11788 else if ((newimm = validate_immediate_twopart (- value, & highpart)) != (unsigned int) FAIL)
11789 temp = newinsn = (temp & OPCODE_MASK) | OPCODE_SUB << DATA_OP_SHIFT;
11790 /* Otherwise - give up. */
11791 else
11793 as_bad_where (fixP->fx_file, fixP->fx_line,
11794 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
11795 (long) value);
11796 break;
11799 /* Replace the first operand in the 2nd instruction (which
11800 is the PC) with the destination register. We have
11801 already added in the PC in the first instruction and we
11802 do not want to do it again. */
11803 newinsn &= ~ 0xf0000;
11804 newinsn |= ((newinsn & 0x0f000) << 4);
11807 newimm |= (temp & 0xfffff000);
11808 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
11810 highpart |= (newinsn & 0xfffff000);
11811 md_number_to_chars (buf + INSN_SIZE, (valueT) highpart, INSN_SIZE);
11813 break;
11815 case BFD_RELOC_ARM_OFFSET_IMM:
11816 sign = value >= 0;
11818 if (value < 0)
11819 value = - value;
11821 if (validate_offset_imm (value, 0) == FAIL)
11823 as_bad_where (fixP->fx_file, fixP->fx_line,
11824 _("bad immediate value for offset (%ld)"),
11825 (long) value);
11826 break;
11829 newval = md_chars_to_number (buf, INSN_SIZE);
11830 newval &= 0xff7ff000;
11831 newval |= value | (sign ? INDEX_UP : 0);
11832 md_number_to_chars (buf, newval, INSN_SIZE);
11833 break;
11835 case BFD_RELOC_ARM_OFFSET_IMM8:
11836 case BFD_RELOC_ARM_HWLITERAL:
11837 sign = value >= 0;
11839 if (value < 0)
11840 value = - value;
11842 if (validate_offset_imm (value, 1) == FAIL)
11844 if (fixP->fx_r_type == BFD_RELOC_ARM_HWLITERAL)
11845 as_bad_where (fixP->fx_file, fixP->fx_line,
11846 _("invalid literal constant: pool needs to be closer"));
11847 else
11848 as_bad (_("bad immediate value for half-word offset (%ld)"),
11849 (long) value);
11850 break;
11853 newval = md_chars_to_number (buf, INSN_SIZE);
11854 newval &= 0xff7ff0f0;
11855 newval |= ((value >> 4) << 8) | (value & 0xf) | (sign ? INDEX_UP : 0);
11856 md_number_to_chars (buf, newval, INSN_SIZE);
11857 break;
11859 case BFD_RELOC_ARM_LITERAL:
11860 sign = value >= 0;
11862 if (value < 0)
11863 value = - value;
11865 if (validate_offset_imm (value, 0) == FAIL)
11867 as_bad_where (fixP->fx_file, fixP->fx_line,
11868 _("invalid literal constant: pool needs to be closer"));
11869 break;
11872 newval = md_chars_to_number (buf, INSN_SIZE);
11873 newval &= 0xff7ff000;
11874 newval |= value | (sign ? INDEX_UP : 0);
11875 md_number_to_chars (buf, newval, INSN_SIZE);
11876 break;
11878 case BFD_RELOC_ARM_SHIFT_IMM:
11879 newval = md_chars_to_number (buf, INSN_SIZE);
11880 if (((unsigned long) value) > 32
11881 || (value == 32
11882 && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60)))
11884 as_bad_where (fixP->fx_file, fixP->fx_line,
11885 _("shift expression is too large"));
11886 break;
11889 if (value == 0)
11890 /* Shifts of zero must be done as lsl. */
11891 newval &= ~0x60;
11892 else if (value == 32)
11893 value = 0;
11894 newval &= 0xfffff07f;
11895 newval |= (value & 0x1f) << 7;
11896 md_number_to_chars (buf, newval, INSN_SIZE);
11897 break;
11899 case BFD_RELOC_ARM_SMI:
11900 if (((unsigned long) value) > 0xffff)
11901 as_bad_where (fixP->fx_file, fixP->fx_line,
11902 _("invalid smi expression"));
11903 newval = md_chars_to_number (buf, INSN_SIZE) & 0xfff000f0;
11904 newval |= (value & 0xf) | ((value & 0xfff0) << 4);
11905 md_number_to_chars (buf, newval, INSN_SIZE);
11906 break;
11908 case BFD_RELOC_ARM_SWI:
11909 if (arm_data->thumb_mode)
11911 if (((unsigned long) value) > 0xff)
11912 as_bad_where (fixP->fx_file, fixP->fx_line,
11913 _("invalid swi expression"));
11914 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xff00;
11915 newval |= value;
11916 md_number_to_chars (buf, newval, THUMB_SIZE);
11918 else
11920 if (((unsigned long) value) > 0x00ffffff)
11921 as_bad_where (fixP->fx_file, fixP->fx_line,
11922 _("invalid swi expression"));
11923 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
11924 newval |= value;
11925 md_number_to_chars (buf, newval, INSN_SIZE);
11927 break;
11929 case BFD_RELOC_ARM_MULTI:
11930 if (((unsigned long) value) > 0xffff)
11931 as_bad_where (fixP->fx_file, fixP->fx_line,
11932 _("invalid expression in load/store multiple"));
11933 newval = value | md_chars_to_number (buf, INSN_SIZE);
11934 md_number_to_chars (buf, newval, INSN_SIZE);
11935 break;
11937 case BFD_RELOC_ARM_PCREL_BRANCH:
11938 newval = md_chars_to_number (buf, INSN_SIZE);
11940 /* Sign-extend a 24-bit number. */
11941 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
11943 #ifdef OBJ_ELF
11944 value = fixP->fx_offset;
11945 #endif
11947 /* We are going to store value (shifted right by two) in the
11948 instruction, in a 24 bit, signed field. Thus we need to check
11949 that none of the top 8 bits of the shifted value (top 7 bits of
11950 the unshifted, unsigned value) are set, or that they are all set. */
11951 if ((value & ~ ((offsetT) 0x1ffffff)) != 0
11952 && ((value & ~ ((offsetT) 0x1ffffff)) != ~ ((offsetT) 0x1ffffff)))
11954 #ifdef OBJ_ELF
11955 /* Normally we would be stuck at this point, since we cannot store
11956 the absolute address that is the destination of the branch in the
11957 24 bits of the branch instruction. If however, we happen to know
11958 that the destination of the branch is in the same section as the
11959 branch instruction itself, then we can compute the relocation for
11960 ourselves and not have to bother the linker with it.
11962 FIXME: The test for OBJ_ELF is only here because I have not
11963 worked out how to do this for OBJ_COFF. */
11964 if (fixP->fx_addsy != NULL
11965 && S_IS_DEFINED (fixP->fx_addsy)
11966 && S_GET_SEGMENT (fixP->fx_addsy) == seg)
11968 /* Get pc relative value to go into the branch. */
11969 value = * valP;
11971 /* Permit a backward branch provided that enough bits
11972 are set. Allow a forwards branch, provided that
11973 enough bits are clear. */
11974 if ( (value & ~ ((offsetT) 0x1ffffff)) == ~ ((offsetT) 0x1ffffff)
11975 || (value & ~ ((offsetT) 0x1ffffff)) == 0)
11976 fixP->fx_done = 1;
11979 if (! fixP->fx_done)
11980 #endif
11981 as_bad_where (fixP->fx_file, fixP->fx_line,
11982 _("GAS can't handle same-section branch dest >= 0x04000000"));
11985 value >>= 2;
11986 value += SEXT24 (newval);
11988 if ( (value & ~ ((offsetT) 0xffffff)) != 0
11989 && ((value & ~ ((offsetT) 0xffffff)) != ~ ((offsetT) 0xffffff)))
11990 as_bad_where (fixP->fx_file, fixP->fx_line,
11991 _("out of range branch"));
11993 if (seg->use_rela_p && !fixP->fx_done)
11995 /* Must unshift the value before storing it in the addend. */
11996 value <<= 2;
11997 #ifdef OBJ_ELF
11998 fixP->fx_offset = value;
11999 #endif
12000 fixP->fx_addnumber = value;
12001 newval = newval & 0xff000000;
12003 else
12004 newval = (value & 0x00ffffff) | (newval & 0xff000000);
12005 md_number_to_chars (buf, newval, INSN_SIZE);
12006 break;
12008 case BFD_RELOC_ARM_PCREL_BLX:
12010 offsetT hbit;
12011 newval = md_chars_to_number (buf, INSN_SIZE);
12013 #ifdef OBJ_ELF
12014 value = fixP->fx_offset;
12015 #endif
12016 hbit = (value >> 1) & 1;
12017 value = (value >> 2) & 0x00ffffff;
12018 value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
12020 if (seg->use_rela_p && !fixP->fx_done)
12022 /* Must sign-extend and unshift the value before storing
12023 it in the addend. */
12024 value = SEXT24 (value);
12025 value = (value << 2) | hbit;
12026 #ifdef OBJ_ELF
12027 fixP->fx_offset = value;
12028 #endif
12029 fixP->fx_addnumber = value;
12030 newval = newval & 0xfe000000;
12032 else
12033 newval = value | (newval & 0xfe000000) | (hbit << 24);
12034 md_number_to_chars (buf, newval, INSN_SIZE);
12036 break;
12038 case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch. */
12039 newval = md_chars_to_number (buf, THUMB_SIZE);
12041 addressT diff = (newval & 0xff) << 1;
12042 if (diff & 0x100)
12043 diff |= ~0xff;
12045 value += diff;
12046 if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
12047 as_bad_where (fixP->fx_file, fixP->fx_line,
12048 _("branch out of range"));
12049 if (seg->use_rela_p && !fixP->fx_done)
12051 #ifdef OBJ_ELF
12052 fixP->fx_offset = value;
12053 #endif
12054 fixP->fx_addnumber = value;
12055 newval = newval & 0xff00;
12057 else
12058 newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
12060 md_number_to_chars (buf, newval, THUMB_SIZE);
12061 break;
12063 case BFD_RELOC_THUMB_PCREL_BRANCH12: /* Unconditional branch. */
12064 newval = md_chars_to_number (buf, THUMB_SIZE);
12066 addressT diff = (newval & 0x7ff) << 1;
12067 if (diff & 0x800)
12068 diff |= ~0x7ff;
12070 value += diff;
12071 if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
12072 as_bad_where (fixP->fx_file, fixP->fx_line,
12073 _("branch out of range"));
12074 if (seg->use_rela_p && !fixP->fx_done)
12076 #ifdef OBJ_ELF
12077 fixP->fx_offset = value;
12078 #endif
12079 fixP->fx_addnumber = value;
12080 newval = newval & 0xf800;
12082 else
12083 newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
12085 md_number_to_chars (buf, newval, THUMB_SIZE);
12086 break;
12088 case BFD_RELOC_THUMB_PCREL_BLX:
12089 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12091 offsetT newval2;
12092 addressT diff;
12094 newval = md_chars_to_number (buf, THUMB_SIZE);
12095 newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
12096 diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
12097 if (diff & 0x400000)
12098 diff |= ~0x3fffff;
12099 #ifdef OBJ_ELF
12100 value = fixP->fx_offset;
12101 #endif
12102 value += diff;
12104 if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
12105 as_bad_where (fixP->fx_file, fixP->fx_line,
12106 _("branch with link out of range"));
12108 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
12109 /* For a BLX instruction, make sure that the relocation is rounded up
12110 to a word boundary. This follows the semantics of the instruction
12111 which specifies that bit 1 of the target address will come from bit
12112 1 of the base address. */
12113 value = (value + 1) & ~ 1;
12115 if (seg->use_rela_p && !fixP->fx_done)
12117 #ifdef OBJ_ELF
12118 fixP->fx_offset = value;
12119 #endif
12120 fixP->fx_addnumber = value;
12121 newval = newval & 0xf800;
12122 newval2 = newval2 & 0xf800;
12124 else
12126 newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12);
12127 newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
12129 md_number_to_chars (buf, newval, THUMB_SIZE);
12130 md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
12132 break;
12134 case BFD_RELOC_8:
12135 if (seg->use_rela_p && !fixP->fx_done)
12136 break;
12137 if (fixP->fx_done || fixP->fx_pcrel)
12138 md_number_to_chars (buf, value, 1);
12139 #ifdef OBJ_ELF
12140 else
12142 value = fixP->fx_offset;
12143 md_number_to_chars (buf, value, 1);
12145 #endif
12146 break;
12148 case BFD_RELOC_16:
12149 if (seg->use_rela_p && !fixP->fx_done)
12150 break;
12151 if (fixP->fx_done || fixP->fx_pcrel)
12152 md_number_to_chars (buf, value, 2);
12153 #ifdef OBJ_ELF
12154 else
12156 value = fixP->fx_offset;
12157 md_number_to_chars (buf, value, 2);
12159 #endif
12160 break;
12162 #ifdef OBJ_ELF
12163 case BFD_RELOC_ARM_TLS_GD32:
12164 case BFD_RELOC_ARM_TLS_LE32:
12165 case BFD_RELOC_ARM_TLS_IE32:
12166 case BFD_RELOC_ARM_TLS_LDM32:
12167 case BFD_RELOC_ARM_TLS_LDO32:
12168 S_SET_THREAD_LOCAL (fixP->fx_addsy);
12169 /* fall through */
12171 case BFD_RELOC_ARM_GOT32:
12172 case BFD_RELOC_ARM_GOTOFF:
12173 case BFD_RELOC_ARM_TARGET2:
12174 if (seg->use_rela_p && !fixP->fx_done)
12175 break;
12176 md_number_to_chars (buf, 0, 4);
12177 break;
12178 #endif
12180 case BFD_RELOC_RVA:
12181 case BFD_RELOC_32:
12182 case BFD_RELOC_ARM_TARGET1:
12183 case BFD_RELOC_ARM_ROSEGREL32:
12184 case BFD_RELOC_ARM_SBREL32:
12185 case BFD_RELOC_32_PCREL:
12186 if (seg->use_rela_p && !fixP->fx_done)
12187 break;
12188 if (fixP->fx_done || fixP->fx_pcrel)
12189 md_number_to_chars (buf, value, 4);
12190 #ifdef OBJ_ELF
12191 else
12193 value = fixP->fx_offset;
12194 md_number_to_chars (buf, value, 4);
12196 #endif
12197 break;
12199 #ifdef OBJ_ELF
12200 case BFD_RELOC_ARM_PREL31:
12201 if (fixP->fx_done || fixP->fx_pcrel)
12203 newval = md_chars_to_number (buf, 4) & 0x80000000;
12204 if ((value ^ (value >> 1)) & 0x40000000)
12206 as_bad_where (fixP->fx_file, fixP->fx_line,
12207 _("rel31 relocation overflow"));
12209 newval |= value & 0x7fffffff;
12210 md_number_to_chars (buf, newval, 4);
12212 break;
12214 case BFD_RELOC_ARM_PLT32:
12215 /* It appears the instruction is fully prepared at this point. */
12216 break;
12217 #endif
12219 case BFD_RELOC_ARM_CP_OFF_IMM:
12220 sign = value >= 0;
12221 if (value < -1023 || value > 1023 || (value & 3))
12222 as_bad_where (fixP->fx_file, fixP->fx_line,
12223 _("illegal value for co-processor offset"));
12224 if (value < 0)
12225 value = -value;
12226 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
12227 newval |= (value >> 2) | (sign ? INDEX_UP : 0);
12228 md_number_to_chars (buf, newval, INSN_SIZE);
12229 break;
12231 case BFD_RELOC_ARM_CP_OFF_IMM_S2:
12232 sign = value >= 0;
12233 if (value < -255 || value > 255)
12234 as_bad_where (fixP->fx_file, fixP->fx_line,
12235 _("Illegal value for co-processor offset"));
12236 if (value < 0)
12237 value = -value;
12238 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
12239 newval |= value | (sign ? INDEX_UP : 0);
12240 md_number_to_chars (buf, newval , INSN_SIZE);
12241 break;
12243 case BFD_RELOC_ARM_THUMB_OFFSET:
12244 newval = md_chars_to_number (buf, THUMB_SIZE);
12245 /* Exactly what ranges, and where the offset is inserted depends
12246 on the type of instruction, we can establish this from the
12247 top 4 bits. */
12248 switch (newval >> 12)
12250 case 4: /* PC load. */
12251 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
12252 forced to zero for these loads, so we will need to round
12253 up the offset if the instruction address is not word
12254 aligned (since the final address produced must be, and
12255 we can only describe word-aligned immediate offsets). */
12257 if ((fixP->fx_frag->fr_address + fixP->fx_where + value) & 3)
12258 as_bad_where (fixP->fx_file, fixP->fx_line,
12259 _("invalid offset, target not word aligned (0x%08X)"),
12260 (unsigned int) (fixP->fx_frag->fr_address
12261 + fixP->fx_where + value));
12263 if ((value + 2) & ~0x3fe)
12264 as_bad_where (fixP->fx_file, fixP->fx_line,
12265 _("invalid offset, value too big (0x%08lX)"),
12266 (long) value);
12268 /* Round up, since pc will be rounded down. */
12269 newval |= (value + 2) >> 2;
12270 break;
12272 case 9: /* SP load/store. */
12273 if (value & ~0x3fc)
12274 as_bad_where (fixP->fx_file, fixP->fx_line,
12275 _("invalid offset, value too big (0x%08lX)"),
12276 (long) value);
12277 newval |= value >> 2;
12278 break;
12280 case 6: /* Word load/store. */
12281 if (value & ~0x7c)
12282 as_bad_where (fixP->fx_file, fixP->fx_line,
12283 _("invalid offset, value too big (0x%08lX)"),
12284 (long) value);
12285 newval |= value << 4; /* 6 - 2. */
12286 break;
12288 case 7: /* Byte load/store. */
12289 if (value & ~0x1f)
12290 as_bad_where (fixP->fx_file, fixP->fx_line,
12291 _("invalid offset, value too big (0x%08lX)"),
12292 (long) value);
12293 newval |= value << 6;
12294 break;
12296 case 8: /* Halfword load/store. */
12297 if (value & ~0x3e)
12298 as_bad_where (fixP->fx_file, fixP->fx_line,
12299 _("invalid offset, value too big (0x%08lX)"),
12300 (long) value);
12301 newval |= value << 5; /* 6 - 1. */
12302 break;
12304 default:
12305 as_bad_where (fixP->fx_file, fixP->fx_line,
12306 "Unable to process relocation for thumb opcode: %lx",
12307 (unsigned long) newval);
12308 break;
12310 md_number_to_chars (buf, newval, THUMB_SIZE);
12311 break;
12313 case BFD_RELOC_ARM_THUMB_ADD:
12314 /* This is a complicated relocation, since we use it for all of
12315 the following immediate relocations:
12317 3bit ADD/SUB
12318 8bit ADD/SUB
12319 9bit ADD/SUB SP word-aligned
12320 10bit ADD PC/SP word-aligned
12322 The type of instruction being processed is encoded in the
12323 instruction field:
12325 0x8000 SUB
12326 0x00F0 Rd
12327 0x000F Rs
12329 newval = md_chars_to_number (buf, THUMB_SIZE);
12331 int rd = (newval >> 4) & 0xf;
12332 int rs = newval & 0xf;
12333 int subtract = newval & 0x8000;
12335 if (rd == REG_SP)
12337 if (value & ~0x1fc)
12338 as_bad_where (fixP->fx_file, fixP->fx_line,
12339 _("invalid immediate for stack address calculation"));
12340 newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
12341 newval |= value >> 2;
12343 else if (rs == REG_PC || rs == REG_SP)
12345 if (subtract ||
12346 value & ~0x3fc)
12347 as_bad_where (fixP->fx_file, fixP->fx_line,
12348 _("invalid immediate for address calculation (value = 0x%08lX)"),
12349 (unsigned long) value);
12350 newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP);
12351 newval |= rd << 8;
12352 newval |= value >> 2;
12354 else if (rs == rd)
12356 if (value & ~0xff)
12357 as_bad_where (fixP->fx_file, fixP->fx_line,
12358 _("invalid 8bit immediate"));
12359 newval = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
12360 newval |= (rd << 8) | value;
12362 else
12364 if (value & ~0x7)
12365 as_bad_where (fixP->fx_file, fixP->fx_line,
12366 _("invalid 3bit immediate"));
12367 newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
12368 newval |= rd | (rs << 3) | (value << 6);
12371 md_number_to_chars (buf, newval, THUMB_SIZE);
12372 break;
12374 case BFD_RELOC_ARM_THUMB_IMM:
12375 newval = md_chars_to_number (buf, THUMB_SIZE);
12376 switch (newval >> 11)
12378 case 0x04: /* 8bit immediate MOV. */
12379 case 0x05: /* 8bit immediate CMP. */
12380 if (value < 0 || value > 255)
12381 as_bad_where (fixP->fx_file, fixP->fx_line,
12382 _("invalid immediate: %ld is too large"),
12383 (long) value);
12384 newval |= value;
12385 break;
12387 default:
12388 abort ();
12390 md_number_to_chars (buf, newval, THUMB_SIZE);
12391 break;
12393 case BFD_RELOC_ARM_THUMB_SHIFT:
12394 /* 5bit shift value (0..31). */
12395 if (value < 0 || value > 31)
12396 as_bad_where (fixP->fx_file, fixP->fx_line,
12397 _("illegal Thumb shift value: %ld"), (long) value);
12398 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xf03f;
12399 newval |= value << 6;
12400 md_number_to_chars (buf, newval, THUMB_SIZE);
12401 break;
12403 case BFD_RELOC_VTABLE_INHERIT:
12404 case BFD_RELOC_VTABLE_ENTRY:
12405 fixP->fx_done = 0;
12406 return;
12408 case BFD_RELOC_UNUSED:
12409 default:
12410 as_bad_where (fixP->fx_file, fixP->fx_line,
12411 _("bad relocation fixup type (%d)"), fixP->fx_r_type);
12415 /* Translate internal representation of relocation info to BFD target
12416 format. */
12418 arelent *
12419 tc_gen_reloc (asection * section ATTRIBUTE_UNUSED,
12420 fixS * fixp)
12422 arelent * reloc;
12423 bfd_reloc_code_real_type code;
12425 reloc = xmalloc (sizeof (arelent));
12427 reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
12428 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
12429 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
12431 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12432 #ifndef OBJ_ELF
12433 if (fixp->fx_pcrel == 0)
12434 reloc->addend = fixp->fx_offset;
12435 else
12436 reloc->addend = fixp->fx_offset = reloc->address;
12437 #else /* OBJ_ELF */
12438 reloc->addend = fixp->fx_offset;
12439 #endif
12441 switch (fixp->fx_r_type)
12443 case BFD_RELOC_8:
12444 if (fixp->fx_pcrel)
12446 code = BFD_RELOC_8_PCREL;
12447 break;
12450 case BFD_RELOC_16:
12451 if (fixp->fx_pcrel)
12453 code = BFD_RELOC_16_PCREL;
12454 break;
12457 case BFD_RELOC_32:
12458 if (fixp->fx_pcrel)
12460 code = BFD_RELOC_32_PCREL;
12461 break;
12464 case BFD_RELOC_NONE:
12465 case BFD_RELOC_ARM_PCREL_BRANCH:
12466 case BFD_RELOC_ARM_PCREL_BLX:
12467 case BFD_RELOC_RVA:
12468 case BFD_RELOC_THUMB_PCREL_BRANCH9:
12469 case BFD_RELOC_THUMB_PCREL_BRANCH12:
12470 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12471 case BFD_RELOC_THUMB_PCREL_BLX:
12472 case BFD_RELOC_VTABLE_ENTRY:
12473 case BFD_RELOC_VTABLE_INHERIT:
12474 code = fixp->fx_r_type;
12475 break;
12477 case BFD_RELOC_ARM_LITERAL:
12478 case BFD_RELOC_ARM_HWLITERAL:
12479 /* If this is called then the a literal has
12480 been referenced across a section boundary. */
12481 as_bad_where (fixp->fx_file, fixp->fx_line,
12482 _("literal referenced across section boundary"));
12483 return NULL;
12485 #ifdef OBJ_ELF
12486 case BFD_RELOC_ARM_GOT32:
12487 case BFD_RELOC_ARM_GOTOFF:
12488 case BFD_RELOC_ARM_PLT32:
12489 case BFD_RELOC_ARM_TARGET1:
12490 case BFD_RELOC_ARM_ROSEGREL32:
12491 case BFD_RELOC_ARM_SBREL32:
12492 case BFD_RELOC_ARM_PREL31:
12493 case BFD_RELOC_ARM_TARGET2:
12494 case BFD_RELOC_ARM_TLS_LE32:
12495 case BFD_RELOC_ARM_TLS_LDO32:
12496 code = fixp->fx_r_type;
12497 break;
12499 case BFD_RELOC_ARM_TLS_GD32:
12500 case BFD_RELOC_ARM_TLS_IE32:
12501 case BFD_RELOC_ARM_TLS_LDM32:
12502 /* BFD will include the symbol's address in the addend.
12503 But we don't want that, so subtract it out again here. */
12504 if (!S_IS_COMMON (fixp->fx_addsy))
12505 reloc->addend -= (*reloc->sym_ptr_ptr)->value;
12506 code = fixp->fx_r_type;
12507 break;
12508 #endif
12510 case BFD_RELOC_ARM_IMMEDIATE:
12511 as_bad_where (fixp->fx_file, fixp->fx_line,
12512 _("internal relocation (type: IMMEDIATE) not fixed up"));
12513 return NULL;
12515 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
12516 as_bad_where (fixp->fx_file, fixp->fx_line,
12517 _("ADRL used for a symbol not defined in the same file"));
12518 return NULL;
12520 case BFD_RELOC_ARM_OFFSET_IMM:
12521 if (fixp->fx_addsy != NULL
12522 && !S_IS_DEFINED (fixp->fx_addsy)
12523 && S_IS_LOCAL (fixp->fx_addsy))
12525 as_bad_where (fixp->fx_file, fixp->fx_line,
12526 _("undefined local label `%s'"),
12527 S_GET_NAME (fixp->fx_addsy));
12528 return NULL;
12531 as_bad_where (fixp->fx_file, fixp->fx_line,
12532 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
12533 return NULL;
12535 default:
12537 char * type;
12539 switch (fixp->fx_r_type)
12541 case BFD_RELOC_NONE: type = "NONE"; break;
12542 case BFD_RELOC_ARM_OFFSET_IMM8: type = "OFFSET_IMM8"; break;
12543 case BFD_RELOC_ARM_SHIFT_IMM: type = "SHIFT_IMM"; break;
12544 case BFD_RELOC_ARM_SMI: type = "SMI"; break;
12545 case BFD_RELOC_ARM_SWI: type = "SWI"; break;
12546 case BFD_RELOC_ARM_MULTI: type = "MULTI"; break;
12547 case BFD_RELOC_ARM_CP_OFF_IMM: type = "CP_OFF_IMM"; break;
12548 case BFD_RELOC_ARM_THUMB_ADD: type = "THUMB_ADD"; break;
12549 case BFD_RELOC_ARM_THUMB_SHIFT: type = "THUMB_SHIFT"; break;
12550 case BFD_RELOC_ARM_THUMB_IMM: type = "THUMB_IMM"; break;
12551 case BFD_RELOC_ARM_THUMB_OFFSET: type = "THUMB_OFFSET"; break;
12552 default: type = _("<unknown>"); break;
12554 as_bad_where (fixp->fx_file, fixp->fx_line,
12555 _("cannot represent %s relocation in this object file format"),
12556 type);
12557 return NULL;
12561 #ifdef OBJ_ELF
12562 if ((code == BFD_RELOC_32_PCREL || code == BFD_RELOC_32)
12563 && GOT_symbol
12564 && fixp->fx_addsy == GOT_symbol)
12566 code = BFD_RELOC_ARM_GOTPC;
12567 reloc->addend = fixp->fx_offset = reloc->address;
12569 #endif
12571 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
12573 if (reloc->howto == NULL)
12575 as_bad_where (fixp->fx_file, fixp->fx_line,
12576 _("cannot represent %s relocation in this object file format"),
12577 bfd_get_reloc_code_name (code));
12578 return NULL;
12581 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12582 vtable entry to be used in the relocation's section offset. */
12583 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
12584 reloc->address = fixp->fx_offset;
12586 return reloc;
12590 md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED,
12591 segT segtype ATTRIBUTE_UNUSED)
12593 as_fatal (_("md_estimate_size_before_relax\n"));
12594 return 1;
12597 /* We need to be able to fix up arbitrary expressions in some statements.
12598 This is so that we can handle symbols that are an arbitrary distance from
12599 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
12600 which returns part of an address in a form which will be valid for
12601 a data instruction. We do this by pushing the expression into a symbol
12602 in the expr_section, and creating a fix for that. */
12604 static void
12605 fix_new_arm (fragS * frag,
12606 int where,
12607 short int size,
12608 expressionS * exp,
12609 int pc_rel,
12610 int reloc)
12612 fixS * new_fix;
12613 arm_fix_data * arm_data;
12615 switch (exp->X_op)
12617 case O_constant:
12618 case O_symbol:
12619 case O_add:
12620 case O_subtract:
12621 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
12622 break;
12624 default:
12625 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0,
12626 pc_rel, reloc);
12627 break;
12630 /* Mark whether the fix is to a THUMB instruction, or an ARM
12631 instruction. */
12632 arm_data = obstack_alloc (& notes, sizeof (arm_fix_data));
12633 new_fix->tc_fix_data = (PTR) arm_data;
12634 arm_data->thumb_mode = thumb_mode;
12637 static void
12638 output_inst (const char * str)
12640 char * to = NULL;
12642 if (inst.error)
12644 as_bad ("%s -- `%s'", inst.error, str);
12645 return;
12648 to = frag_more (inst.size);
12650 if (thumb_mode && (inst.size > THUMB_SIZE))
12652 assert (inst.size == (2 * THUMB_SIZE));
12653 md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE);
12654 md_number_to_chars (to + THUMB_SIZE, inst.instruction, THUMB_SIZE);
12656 else if (inst.size > INSN_SIZE)
12658 assert (inst.size == (2 * INSN_SIZE));
12659 md_number_to_chars (to, inst.instruction, INSN_SIZE);
12660 md_number_to_chars (to + INSN_SIZE, inst.instruction, INSN_SIZE);
12662 else
12663 md_number_to_chars (to, inst.instruction, inst.size);
12665 if (inst.reloc.type != BFD_RELOC_UNUSED)
12666 fix_new_arm (frag_now, to - frag_now->fr_literal,
12667 inst.size, & inst.reloc.exp, inst.reloc.pc_rel,
12668 inst.reloc.type);
12670 #ifdef OBJ_ELF
12671 dwarf2_emit_insn (inst.size);
12672 #endif
12675 void
12676 md_assemble (char * str)
12678 char c;
12679 char *p;
12680 char *start;
12682 /* Align the previous label if needed. */
12683 if (last_label_seen != NULL)
12685 symbol_set_frag (last_label_seen, frag_now);
12686 S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ());
12687 S_SET_SEGMENT (last_label_seen, now_seg);
12690 memset (&inst, '\0', sizeof (inst));
12691 inst.reloc.type = BFD_RELOC_UNUSED;
12693 skip_whitespace (str);
12695 /* Scan up to the end of the op-code, which must end in white space or
12696 end of string. */
12697 for (start = p = str; *p != '\0'; p++)
12698 if (*p == ' ')
12699 break;
12701 if (p == str)
12703 as_bad (_("no operator -- statement `%s'\n"), str);
12704 return;
12707 if (thumb_mode)
12709 const struct thumb_opcode * opcode;
12711 c = *p;
12712 *p = '\0';
12713 opcode = (const struct thumb_opcode *) hash_find (arm_tops_hsh, str);
12714 *p = c;
12716 if (opcode)
12718 /* Check that this instruction is supported for this CPU. */
12719 if (thumb_mode == 1 && (opcode->variant & cpu_variant) == 0)
12721 as_bad (_("selected processor does not support `%s'"), str);
12722 return;
12725 mapping_state (MAP_THUMB);
12726 inst.instruction = opcode->value;
12727 inst.size = opcode->size;
12728 opcode->parms (p);
12729 output_inst (str);
12730 return;
12733 else
12735 const struct asm_opcode * opcode;
12737 c = *p;
12738 *p = '\0';
12739 opcode = (const struct asm_opcode *) hash_find (arm_ops_hsh, str);
12740 *p = c;
12742 if (opcode)
12744 /* Check that this instruction is supported for this CPU. */
12745 if ((opcode->variant & cpu_variant) == 0)
12747 as_bad (_("selected processor does not support `%s'"), str);
12748 return;
12751 mapping_state (MAP_ARM);
12752 inst.instruction = opcode->value;
12753 inst.size = INSN_SIZE;
12754 opcode->parms (p);
12755 output_inst (str);
12756 return;
12760 /* It wasn't an instruction, but it might be a register alias of the form
12761 alias .req reg. */
12762 if (create_register_alias (str, p))
12763 return;
12765 as_bad (_("bad instruction `%s'"), start);
12768 /* md_parse_option
12769 Invocation line includes a switch not recognized by the base assembler.
12770 See if it's a processor-specific option.
12772 This routine is somewhat complicated by the need for backwards
12773 compatibility (since older releases of gcc can't be changed).
12774 The new options try to make the interface as compatible as
12775 possible with GCC.
12777 New options (supported) are:
12779 -mcpu=<cpu name> Assemble for selected processor
12780 -march=<architecture name> Assemble for selected architecture
12781 -mfpu=<fpu architecture> Assemble for selected FPU.
12782 -EB/-mbig-endian Big-endian
12783 -EL/-mlittle-endian Little-endian
12784 -k Generate PIC code
12785 -mthumb Start in Thumb mode
12786 -mthumb-interwork Code supports ARM/Thumb interworking
12788 For now we will also provide support for:
12790 -mapcs-32 32-bit Program counter
12791 -mapcs-26 26-bit Program counter
12792 -macps-float Floats passed in FP registers
12793 -mapcs-reentrant Reentrant code
12794 -matpcs
12795 (sometime these will probably be replaced with -mapcs=<list of options>
12796 and -matpcs=<list of options>)
12798 The remaining options are only supported for back-wards compatibility.
12799 Cpu variants, the arm part is optional:
12800 -m[arm]1 Currently not supported.
12801 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
12802 -m[arm]3 Arm 3 processor
12803 -m[arm]6[xx], Arm 6 processors
12804 -m[arm]7[xx][t][[d]m] Arm 7 processors
12805 -m[arm]8[10] Arm 8 processors
12806 -m[arm]9[20][tdmi] Arm 9 processors
12807 -mstrongarm[110[0]] StrongARM processors
12808 -mxscale XScale processors
12809 -m[arm]v[2345[t[e]]] Arm architectures
12810 -mall All (except the ARM1)
12811 FP variants:
12812 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
12813 -mfpe-old (No float load/store multiples)
12814 -mvfpxd VFP Single precision
12815 -mvfp All VFP
12816 -mno-fpu Disable all floating point instructions
12818 The following CPU names are recognized:
12819 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
12820 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
12821 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
12822 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
12823 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
12824 arm10t arm10e, arm1020t, arm1020e, arm10200e,
12825 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
12829 const char * md_shortopts = "m:k";
12831 #ifdef ARM_BI_ENDIAN
12832 #define OPTION_EB (OPTION_MD_BASE + 0)
12833 #define OPTION_EL (OPTION_MD_BASE + 1)
12834 #else
12835 #if TARGET_BYTES_BIG_ENDIAN
12836 #define OPTION_EB (OPTION_MD_BASE + 0)
12837 #else
12838 #define OPTION_EL (OPTION_MD_BASE + 1)
12839 #endif
12840 #endif
12842 struct option md_longopts[] =
12844 #ifdef OPTION_EB
12845 {"EB", no_argument, NULL, OPTION_EB},
12846 #endif
12847 #ifdef OPTION_EL
12848 {"EL", no_argument, NULL, OPTION_EL},
12849 #endif
12850 {NULL, no_argument, NULL, 0}
12853 size_t md_longopts_size = sizeof (md_longopts);
12855 struct arm_option_table
12857 char *option; /* Option name to match. */
12858 char *help; /* Help information. */
12859 int *var; /* Variable to change. */
12860 int value; /* What to change it to. */
12861 char *deprecated; /* If non-null, print this message. */
12864 struct arm_option_table arm_opts[] =
12866 {"k", N_("generate PIC code"), &pic_code, 1, NULL},
12867 {"mthumb", N_("assemble Thumb code"), &thumb_mode, 1, NULL},
12868 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
12869 &support_interwork, 1, NULL},
12870 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26, 0, NULL},
12871 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26, 1, NULL},
12872 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float,
12873 1, NULL},
12874 {"mapcs-reentrant", N_("re-entrant code"), &pic_code, 1, NULL},
12875 {"matpcs", N_("code is ATPCS conformant"), &atpcs, 1, NULL},
12876 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian, 1, NULL},
12877 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian, 1,
12878 NULL},
12880 /* These are recognized by the assembler, but have no affect on code. */
12881 {"mapcs-frame", N_("use frame pointer"), NULL, 0, NULL},
12882 {"mapcs-stack-check", N_("use stack size checking"), NULL, 0, NULL},
12884 /* DON'T add any new processors to this list -- we want the whole list
12885 to go away... Add them to the processors table instead. */
12886 {"marm1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
12887 {"m1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
12888 {"marm2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
12889 {"m2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
12890 {"marm250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
12891 {"m250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
12892 {"marm3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
12893 {"m3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
12894 {"marm6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
12895 {"m6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
12896 {"marm600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
12897 {"m600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
12898 {"marm610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
12899 {"m610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
12900 {"marm620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
12901 {"m620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
12902 {"marm7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
12903 {"m7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
12904 {"marm70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
12905 {"m70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
12906 {"marm700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
12907 {"m700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
12908 {"marm700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
12909 {"m700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
12910 {"marm710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
12911 {"m710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
12912 {"marm710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
12913 {"m710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
12914 {"marm720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
12915 {"m720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
12916 {"marm7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
12917 {"m7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
12918 {"marm7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
12919 {"m7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
12920 {"marm7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
12921 {"m7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
12922 {"marm7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
12923 {"m7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
12924 {"marm7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
12925 {"m7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
12926 {"marm7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
12927 {"m7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
12928 {"marm7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
12929 {"m7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
12930 {"marm7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
12931 {"m7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
12932 {"marm7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12933 {"m7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12934 {"marm7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12935 {"m7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12936 {"marm710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
12937 {"m710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
12938 {"marm720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
12939 {"m720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
12940 {"marm740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
12941 {"m740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
12942 {"marm8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
12943 {"m8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
12944 {"marm810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
12945 {"m810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
12946 {"marm9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
12947 {"m9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
12948 {"marm9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
12949 {"m9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
12950 {"marm920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
12951 {"m920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
12952 {"marm940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
12953 {"m940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
12954 {"mstrongarm", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=strongarm")},
12955 {"mstrongarm110", NULL, &legacy_cpu, ARM_ARCH_V4,
12956 N_("use -mcpu=strongarm110")},
12957 {"mstrongarm1100", NULL, &legacy_cpu, ARM_ARCH_V4,
12958 N_("use -mcpu=strongarm1100")},
12959 {"mstrongarm1110", NULL, &legacy_cpu, ARM_ARCH_V4,
12960 N_("use -mcpu=strongarm1110")},
12961 {"mxscale", NULL, &legacy_cpu, ARM_ARCH_XSCALE, N_("use -mcpu=xscale")},
12962 {"miwmmxt", NULL, &legacy_cpu, ARM_ARCH_IWMMXT, N_("use -mcpu=iwmmxt")},
12963 {"mall", NULL, &legacy_cpu, ARM_ANY, N_("use -mcpu=all")},
12965 /* Architecture variants -- don't add any more to this list either. */
12966 {"mv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
12967 {"marmv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
12968 {"mv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
12969 {"marmv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
12970 {"mv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
12971 {"marmv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
12972 {"mv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
12973 {"marmv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
12974 {"mv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
12975 {"marmv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
12976 {"mv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
12977 {"marmv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
12978 {"mv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
12979 {"marmv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
12980 {"mv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
12981 {"marmv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
12982 {"mv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
12983 {"marmv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
12985 /* Floating point variants -- don't add any more to this list either. */
12986 {"mfpe-old", NULL, &legacy_fpu, FPU_ARCH_FPE, N_("use -mfpu=fpe")},
12987 {"mfpa10", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa10")},
12988 {"mfpa11", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa11")},
12989 {"mno-fpu", NULL, &legacy_fpu, 0,
12990 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
12992 {NULL, NULL, NULL, 0, NULL}
12995 struct arm_cpu_option_table
12997 char *name;
12998 int value;
12999 /* For some CPUs we assume an FPU unless the user explicitly sets
13000 -mfpu=... */
13001 int default_fpu;
13004 /* This list should, at a minimum, contain all the cpu names
13005 recognized by GCC. */
13006 static struct arm_cpu_option_table arm_cpus[] =
13008 {"all", ARM_ANY, FPU_ARCH_FPA},
13009 {"arm1", ARM_ARCH_V1, FPU_ARCH_FPA},
13010 {"arm2", ARM_ARCH_V2, FPU_ARCH_FPA},
13011 {"arm250", ARM_ARCH_V2S, FPU_ARCH_FPA},
13012 {"arm3", ARM_ARCH_V2S, FPU_ARCH_FPA},
13013 {"arm6", ARM_ARCH_V3, FPU_ARCH_FPA},
13014 {"arm60", ARM_ARCH_V3, FPU_ARCH_FPA},
13015 {"arm600", ARM_ARCH_V3, FPU_ARCH_FPA},
13016 {"arm610", ARM_ARCH_V3, FPU_ARCH_FPA},
13017 {"arm620", ARM_ARCH_V3, FPU_ARCH_FPA},
13018 {"arm7", ARM_ARCH_V3, FPU_ARCH_FPA},
13019 {"arm7m", ARM_ARCH_V3M, FPU_ARCH_FPA},
13020 {"arm7d", ARM_ARCH_V3, FPU_ARCH_FPA},
13021 {"arm7dm", ARM_ARCH_V3M, FPU_ARCH_FPA},
13022 {"arm7di", ARM_ARCH_V3, FPU_ARCH_FPA},
13023 {"arm7dmi", ARM_ARCH_V3M, FPU_ARCH_FPA},
13024 {"arm70", ARM_ARCH_V3, FPU_ARCH_FPA},
13025 {"arm700", ARM_ARCH_V3, FPU_ARCH_FPA},
13026 {"arm700i", ARM_ARCH_V3, FPU_ARCH_FPA},
13027 {"arm710", ARM_ARCH_V3, FPU_ARCH_FPA},
13028 {"arm710t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13029 {"arm720", ARM_ARCH_V3, FPU_ARCH_FPA},
13030 {"arm720t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13031 {"arm740t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13032 {"arm710c", ARM_ARCH_V3, FPU_ARCH_FPA},
13033 {"arm7100", ARM_ARCH_V3, FPU_ARCH_FPA},
13034 {"arm7500", ARM_ARCH_V3, FPU_ARCH_FPA},
13035 {"arm7500fe", ARM_ARCH_V3, FPU_ARCH_FPA},
13036 {"arm7t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13037 {"arm7tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
13038 {"arm7tdmi-s", ARM_ARCH_V4T, FPU_ARCH_FPA},
13039 {"arm8", ARM_ARCH_V4, FPU_ARCH_FPA},
13040 {"arm810", ARM_ARCH_V4, FPU_ARCH_FPA},
13041 {"strongarm", ARM_ARCH_V4, FPU_ARCH_FPA},
13042 {"strongarm1", ARM_ARCH_V4, FPU_ARCH_FPA},
13043 {"strongarm110", ARM_ARCH_V4, FPU_ARCH_FPA},
13044 {"strongarm1100", ARM_ARCH_V4, FPU_ARCH_FPA},
13045 {"strongarm1110", ARM_ARCH_V4, FPU_ARCH_FPA},
13046 {"arm9", ARM_ARCH_V4T, FPU_ARCH_FPA},
13047 {"arm920", ARM_ARCH_V4T, FPU_ARCH_FPA},
13048 {"arm920t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13049 {"arm922t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13050 {"arm940t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13051 {"arm9tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
13052 /* For V5 or later processors we default to using VFP; but the user
13053 should really set the FPU type explicitly. */
13054 {"arm9e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13055 {"arm9e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13056 {"arm926ej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
13057 {"arm926ejs", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
13058 {"arm926ej-s", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
13059 {"arm946e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13060 {"arm946e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13061 {"arm966e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13062 {"arm966e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13063 {"arm10t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
13064 {"arm10e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13065 {"arm1020", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13066 {"arm1020t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
13067 {"arm1020e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13068 {"arm1026ejs", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
13069 {"arm1026ej-s", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
13070 {"arm1136js", ARM_ARCH_V6, FPU_NONE},
13071 {"arm1136j-s", ARM_ARCH_V6, FPU_NONE},
13072 {"arm1136jfs", ARM_ARCH_V6, FPU_ARCH_VFP_V2},
13073 {"arm1136jf-s", ARM_ARCH_V6, FPU_ARCH_VFP_V2},
13074 {"mpcore", ARM_ARCH_V6K, FPU_ARCH_VFP_V2},
13075 {"mpcorenovfp", ARM_ARCH_V6K, FPU_NONE},
13076 {"arm1176jz-s", ARM_ARCH_V6ZK, FPU_NONE},
13077 {"arm1176jzf-s", ARM_ARCH_V6ZK, FPU_ARCH_VFP_V2},
13078 /* ??? XSCALE is really an architecture. */
13079 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
13080 /* ??? iwmmxt is not a processor. */
13081 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP_V2},
13082 {"i80200", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
13083 /* Maverick */
13084 {"ep9312", ARM_ARCH_V4T | ARM_CEXT_MAVERICK, FPU_ARCH_MAVERICK},
13085 {NULL, 0, 0}
13088 struct arm_arch_option_table
13090 char *name;
13091 int value;
13092 int default_fpu;
13095 /* This list should, at a minimum, contain all the architecture names
13096 recognized by GCC. */
13097 static struct arm_arch_option_table arm_archs[] =
13099 {"all", ARM_ANY, FPU_ARCH_FPA},
13100 {"armv1", ARM_ARCH_V1, FPU_ARCH_FPA},
13101 {"armv2", ARM_ARCH_V2, FPU_ARCH_FPA},
13102 {"armv2a", ARM_ARCH_V2S, FPU_ARCH_FPA},
13103 {"armv2s", ARM_ARCH_V2S, FPU_ARCH_FPA},
13104 {"armv3", ARM_ARCH_V3, FPU_ARCH_FPA},
13105 {"armv3m", ARM_ARCH_V3M, FPU_ARCH_FPA},
13106 {"armv4", ARM_ARCH_V4, FPU_ARCH_FPA},
13107 {"armv4xm", ARM_ARCH_V4xM, FPU_ARCH_FPA},
13108 {"armv4t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13109 {"armv4txm", ARM_ARCH_V4TxM, FPU_ARCH_FPA},
13110 {"armv5", ARM_ARCH_V5, FPU_ARCH_VFP},
13111 {"armv5t", ARM_ARCH_V5T, FPU_ARCH_VFP},
13112 {"armv5txm", ARM_ARCH_V5TxM, FPU_ARCH_VFP},
13113 {"armv5te", ARM_ARCH_V5TE, FPU_ARCH_VFP},
13114 {"armv5texp", ARM_ARCH_V5TExP, FPU_ARCH_VFP},
13115 {"armv5tej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP},
13116 {"armv6", ARM_ARCH_V6, FPU_ARCH_VFP},
13117 {"armv6j", ARM_ARCH_V6, FPU_ARCH_VFP},
13118 {"armv6k", ARM_ARCH_V6K, FPU_ARCH_VFP},
13119 {"armv6z", ARM_ARCH_V6Z, FPU_ARCH_VFP},
13120 {"armv6zk", ARM_ARCH_V6ZK, FPU_ARCH_VFP},
13121 {"armv6t2", ARM_ARCH_V6T2, FPU_ARCH_VFP},
13122 {"armv6kt2", ARM_ARCH_V6KT2, FPU_ARCH_VFP},
13123 {"armv6zt2", ARM_ARCH_V6ZT2, FPU_ARCH_VFP},
13124 {"armv6zkt2", ARM_ARCH_V6ZKT2, FPU_ARCH_VFP},
13125 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP},
13126 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP},
13127 {NULL, 0, 0}
13130 /* ISA extensions in the co-processor space. */
13131 struct arm_arch_extension_table
13133 char *name;
13134 int value;
13137 static struct arm_arch_extension_table arm_extensions[] =
13139 {"maverick", ARM_CEXT_MAVERICK},
13140 {"xscale", ARM_CEXT_XSCALE},
13141 {"iwmmxt", ARM_CEXT_IWMMXT},
13142 {NULL, 0}
13145 struct arm_fpu_option_table
13147 char *name;
13148 int value;
13151 /* This list should, at a minimum, contain all the fpu names
13152 recognized by GCC. */
13153 static struct arm_fpu_option_table arm_fpus[] =
13155 {"softfpa", FPU_NONE},
13156 {"fpe", FPU_ARCH_FPE},
13157 {"fpe2", FPU_ARCH_FPE},
13158 {"fpe3", FPU_ARCH_FPA}, /* Third release supports LFM/SFM. */
13159 {"fpa", FPU_ARCH_FPA},
13160 {"fpa10", FPU_ARCH_FPA},
13161 {"fpa11", FPU_ARCH_FPA},
13162 {"arm7500fe", FPU_ARCH_FPA},
13163 {"softvfp", FPU_ARCH_VFP},
13164 {"softvfp+vfp", FPU_ARCH_VFP_V2},
13165 {"vfp", FPU_ARCH_VFP_V2},
13166 {"vfp9", FPU_ARCH_VFP_V2},
13167 {"vfp10", FPU_ARCH_VFP_V2},
13168 {"vfp10-r0", FPU_ARCH_VFP_V1},
13169 {"vfpxd", FPU_ARCH_VFP_V1xD},
13170 {"arm1020t", FPU_ARCH_VFP_V1},
13171 {"arm1020e", FPU_ARCH_VFP_V2},
13172 {"arm1136jfs", FPU_ARCH_VFP_V2},
13173 {"arm1136jf-s", FPU_ARCH_VFP_V2},
13174 {"maverick", FPU_ARCH_MAVERICK},
13175 {NULL, 0}
13178 struct arm_float_abi_option_table
13180 char *name;
13181 int value;
13184 static struct arm_float_abi_option_table arm_float_abis[] =
13186 {"hard", ARM_FLOAT_ABI_HARD},
13187 {"softfp", ARM_FLOAT_ABI_SOFTFP},
13188 {"soft", ARM_FLOAT_ABI_SOFT},
13189 {NULL, 0}
13192 struct arm_eabi_option_table
13194 char *name;
13195 unsigned int value;
13198 #ifdef OBJ_ELF
13199 /* We only know how to output GNU and ver 4 (AAELF) formats. */
13200 static struct arm_eabi_option_table arm_eabis[] =
13202 {"gnu", EF_ARM_EABI_UNKNOWN},
13203 {"4", EF_ARM_EABI_VER4},
13204 {NULL, 0}
13206 #endif
13208 struct arm_long_option_table
13210 char * option; /* Substring to match. */
13211 char * help; /* Help information. */
13212 int (* func) (char * subopt); /* Function to decode sub-option. */
13213 char * deprecated; /* If non-null, print this message. */
13216 static int
13217 arm_parse_extension (char * str, int * opt_p)
13219 while (str != NULL && *str != 0)
13221 struct arm_arch_extension_table * opt;
13222 char * ext;
13223 int optlen;
13225 if (*str != '+')
13227 as_bad (_("invalid architectural extension"));
13228 return 0;
13231 str++;
13232 ext = strchr (str, '+');
13234 if (ext != NULL)
13235 optlen = ext - str;
13236 else
13237 optlen = strlen (str);
13239 if (optlen == 0)
13241 as_bad (_("missing architectural extension"));
13242 return 0;
13245 for (opt = arm_extensions; opt->name != NULL; opt++)
13246 if (strncmp (opt->name, str, optlen) == 0)
13248 *opt_p |= opt->value;
13249 break;
13252 if (opt->name == NULL)
13254 as_bad (_("unknown architectural extnsion `%s'"), str);
13255 return 0;
13258 str = ext;
13261 return 1;
13264 static int
13265 arm_parse_cpu (char * str)
13267 struct arm_cpu_option_table * opt;
13268 char * ext = strchr (str, '+');
13269 int optlen;
13271 if (ext != NULL)
13272 optlen = ext - str;
13273 else
13274 optlen = strlen (str);
13276 if (optlen == 0)
13278 as_bad (_("missing cpu name `%s'"), str);
13279 return 0;
13282 for (opt = arm_cpus; opt->name != NULL; opt++)
13283 if (strncmp (opt->name, str, optlen) == 0)
13285 mcpu_cpu_opt = opt->value;
13286 mcpu_fpu_opt = opt->default_fpu;
13288 if (ext != NULL)
13289 return arm_parse_extension (ext, &mcpu_cpu_opt);
13291 return 1;
13294 as_bad (_("unknown cpu `%s'"), str);
13295 return 0;
13298 static int
13299 arm_parse_arch (char * str)
13301 struct arm_arch_option_table *opt;
13302 char *ext = strchr (str, '+');
13303 int optlen;
13305 if (ext != NULL)
13306 optlen = ext - str;
13307 else
13308 optlen = strlen (str);
13310 if (optlen == 0)
13312 as_bad (_("missing architecture name `%s'"), str);
13313 return 0;
13317 for (opt = arm_archs; opt->name != NULL; opt++)
13318 if (streq (opt->name, str))
13320 march_cpu_opt = opt->value;
13321 march_fpu_opt = opt->default_fpu;
13323 if (ext != NULL)
13324 return arm_parse_extension (ext, &march_cpu_opt);
13326 return 1;
13329 as_bad (_("unknown architecture `%s'\n"), str);
13330 return 0;
13333 static int
13334 arm_parse_fpu (char * str)
13336 struct arm_fpu_option_table * opt;
13338 for (opt = arm_fpus; opt->name != NULL; opt++)
13339 if (streq (opt->name, str))
13341 mfpu_opt = opt->value;
13342 return 1;
13345 as_bad (_("unknown floating point format `%s'\n"), str);
13346 return 0;
13349 static int
13350 arm_parse_float_abi (char * str)
13352 struct arm_float_abi_option_table * opt;
13354 for (opt = arm_float_abis; opt->name != NULL; opt++)
13355 if (streq (opt->name, str))
13357 mfloat_abi_opt = opt->value;
13358 return 1;
13361 as_bad (_("unknown floating point abi `%s'\n"), str);
13362 return 0;
13365 #ifdef OBJ_ELF
13366 static int
13367 arm_parse_eabi (char * str)
13369 struct arm_eabi_option_table *opt;
13371 for (opt = arm_eabis; opt->name != NULL; opt++)
13372 if (streq (opt->name, str))
13374 meabi_flags = opt->value;
13375 return 1;
13377 as_bad (_("unknown EABI `%s'\n"), str);
13378 return 0;
13380 #endif
13382 struct arm_long_option_table arm_long_opts[] =
13384 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13385 arm_parse_cpu, NULL},
13386 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13387 arm_parse_arch, NULL},
13388 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13389 arm_parse_fpu, NULL},
13390 {"mfloat-abi=", N_("<abi>\t assemble for floating point ABI <abi>"),
13391 arm_parse_float_abi, NULL},
13392 #ifdef OBJ_ELF
13393 {"meabi=", N_("<ver>\t assemble for eabi version <ver>"),
13394 arm_parse_eabi, NULL},
13395 #endif
13396 {NULL, NULL, 0, NULL}
13400 md_parse_option (int c, char * arg)
13402 struct arm_option_table *opt;
13403 struct arm_long_option_table *lopt;
13405 switch (c)
13407 #ifdef OPTION_EB
13408 case OPTION_EB:
13409 target_big_endian = 1;
13410 break;
13411 #endif
13413 #ifdef OPTION_EL
13414 case OPTION_EL:
13415 target_big_endian = 0;
13416 break;
13417 #endif
13419 case 'a':
13420 /* Listing option. Just ignore these, we don't support additional
13421 ones. */
13422 return 0;
13424 default:
13425 for (opt = arm_opts; opt->option != NULL; opt++)
13427 if (c == opt->option[0]
13428 && ((arg == NULL && opt->option[1] == 0)
13429 || streq (arg, opt->option + 1)))
13431 #if WARN_DEPRECATED
13432 /* If the option is deprecated, tell the user. */
13433 if (opt->deprecated != NULL)
13434 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c,
13435 arg ? arg : "", _(opt->deprecated));
13436 #endif
13438 if (opt->var != NULL)
13439 *opt->var = opt->value;
13441 return 1;
13445 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13447 /* These options are expected to have an argument. */
13448 if (c == lopt->option[0]
13449 && arg != NULL
13450 && strncmp (arg, lopt->option + 1,
13451 strlen (lopt->option + 1)) == 0)
13453 #if WARN_DEPRECATED
13454 /* If the option is deprecated, tell the user. */
13455 if (lopt->deprecated != NULL)
13456 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c, arg,
13457 _(lopt->deprecated));
13458 #endif
13460 /* Call the sup-option parser. */
13461 return lopt->func (arg + strlen (lopt->option) - 1);
13465 return 0;
13468 return 1;
13471 void
13472 md_show_usage (FILE * fp)
13474 struct arm_option_table *opt;
13475 struct arm_long_option_table *lopt;
13477 fprintf (fp, _(" ARM-specific assembler options:\n"));
13479 for (opt = arm_opts; opt->option != NULL; opt++)
13480 if (opt->help != NULL)
13481 fprintf (fp, " -%-23s%s\n", opt->option, _(opt->help));
13483 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13484 if (lopt->help != NULL)
13485 fprintf (fp, " -%s%s\n", lopt->option, _(lopt->help));
13487 #ifdef OPTION_EB
13488 fprintf (fp, _("\
13489 -EB assemble code for a big-endian cpu\n"));
13490 #endif
13492 #ifdef OPTION_EL
13493 fprintf (fp, _("\
13494 -EL assemble code for a little-endian cpu\n"));
13495 #endif
13498 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13500 void
13501 cons_fix_new_arm (fragS * frag,
13502 int where,
13503 int size,
13504 expressionS * exp)
13506 bfd_reloc_code_real_type type;
13507 int pcrel = 0;
13509 /* Pick a reloc.
13510 FIXME: @@ Should look at CPU word size. */
13511 switch (size)
13513 case 1:
13514 type = BFD_RELOC_8;
13515 break;
13516 case 2:
13517 type = BFD_RELOC_16;
13518 break;
13519 case 4:
13520 default:
13521 type = BFD_RELOC_32;
13522 break;
13523 case 8:
13524 type = BFD_RELOC_64;
13525 break;
13528 fix_new_exp (frag, where, (int) size, exp, pcrel, type);
13531 /* A good place to do this, although this was probably not intended
13532 for this kind of use. We need to dump the literal pool before
13533 references are made to a null symbol pointer. */
13535 void
13536 arm_cleanup (void)
13538 literal_pool * pool;
13540 for (pool = list_of_pools; pool; pool = pool->next)
13542 /* Put it at the end of the relevent section. */
13543 subseg_set (pool->section, pool->sub_section);
13544 #ifdef OBJ_ELF
13545 arm_elf_change_section ();
13546 #endif
13547 s_ltorg (0);
13551 void
13552 arm_start_line_hook (void)
13554 last_label_seen = NULL;
13557 void
13558 arm_frob_label (symbolS * sym)
13560 last_label_seen = sym;
13562 ARM_SET_THUMB (sym, thumb_mode);
13564 #if defined OBJ_COFF || defined OBJ_ELF
13565 ARM_SET_INTERWORK (sym, support_interwork);
13566 #endif
13568 /* Note - do not allow local symbols (.Lxxx) to be labeled
13569 as Thumb functions. This is because these labels, whilst
13570 they exist inside Thumb code, are not the entry points for
13571 possible ARM->Thumb calls. Also, these labels can be used
13572 as part of a computed goto or switch statement. eg gcc
13573 can generate code that looks like this:
13575 ldr r2, [pc, .Laaa]
13576 lsl r3, r3, #2
13577 ldr r2, [r3, r2]
13578 mov pc, r2
13580 .Lbbb: .word .Lxxx
13581 .Lccc: .word .Lyyy
13582 ..etc...
13583 .Laaa: .word Lbbb
13585 The first instruction loads the address of the jump table.
13586 The second instruction converts a table index into a byte offset.
13587 The third instruction gets the jump address out of the table.
13588 The fourth instruction performs the jump.
13590 If the address stored at .Laaa is that of a symbol which has the
13591 Thumb_Func bit set, then the linker will arrange for this address
13592 to have the bottom bit set, which in turn would mean that the
13593 address computation performed by the third instruction would end
13594 up with the bottom bit set. Since the ARM is capable of unaligned
13595 word loads, the instruction would then load the incorrect address
13596 out of the jump table, and chaos would ensue. */
13597 if (label_is_thumb_function_name
13598 && (S_GET_NAME (sym)[0] != '.' || S_GET_NAME (sym)[1] != 'L')
13599 && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
13601 /* When the address of a Thumb function is taken the bottom
13602 bit of that address should be set. This will allow
13603 interworking between Arm and Thumb functions to work
13604 correctly. */
13606 THUMB_SET_FUNC (sym, 1);
13608 label_is_thumb_function_name = FALSE;
13612 /* Adjust the symbol table. This marks Thumb symbols as distinct from
13613 ARM ones. */
13615 void
13616 arm_adjust_symtab (void)
13618 #ifdef OBJ_COFF
13619 symbolS * sym;
13621 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13623 if (ARM_IS_THUMB (sym))
13625 if (THUMB_IS_FUNC (sym))
13627 /* Mark the symbol as a Thumb function. */
13628 if ( S_GET_STORAGE_CLASS (sym) == C_STAT
13629 || S_GET_STORAGE_CLASS (sym) == C_LABEL) /* This can happen! */
13630 S_SET_STORAGE_CLASS (sym, C_THUMBSTATFUNC);
13632 else if (S_GET_STORAGE_CLASS (sym) == C_EXT)
13633 S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC);
13634 else
13635 as_bad (_("%s: unexpected function type: %d"),
13636 S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym));
13638 else switch (S_GET_STORAGE_CLASS (sym))
13640 case C_EXT:
13641 S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
13642 break;
13643 case C_STAT:
13644 S_SET_STORAGE_CLASS (sym, C_THUMBSTAT);
13645 break;
13646 case C_LABEL:
13647 S_SET_STORAGE_CLASS (sym, C_THUMBLABEL);
13648 break;
13649 default:
13650 /* Do nothing. */
13651 break;
13655 if (ARM_IS_INTERWORK (sym))
13656 coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_flags = 0xFF;
13658 #endif
13659 #ifdef OBJ_ELF
13660 symbolS * sym;
13661 char bind;
13663 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13665 if (ARM_IS_THUMB (sym))
13667 elf_symbol_type * elf_sym;
13669 elf_sym = elf_symbol (symbol_get_bfdsym (sym));
13670 bind = ELF_ST_BIND (elf_sym->internal_elf_sym.st_info);
13672 if (! bfd_is_arm_mapping_symbol_name (elf_sym->symbol.name))
13674 /* If it's a .thumb_func, declare it as so,
13675 otherwise tag label as .code 16. */
13676 if (THUMB_IS_FUNC (sym))
13677 elf_sym->internal_elf_sym.st_info =
13678 ELF_ST_INFO (bind, STT_ARM_TFUNC);
13679 else
13680 elf_sym->internal_elf_sym.st_info =
13681 ELF_ST_INFO (bind, STT_ARM_16BIT);
13685 #endif
13689 arm_data_in_code (void)
13691 if (thumb_mode && ! strncmp (input_line_pointer + 1, "data:", 5))
13693 *input_line_pointer = '/';
13694 input_line_pointer += 5;
13695 *input_line_pointer = 0;
13696 return 1;
13699 return 0;
13702 char *
13703 arm_canonicalize_symbol_name (char * name)
13705 int len;
13707 if (thumb_mode && (len = strlen (name)) > 5
13708 && streq (name + len - 5, "/data"))
13709 *(name + len - 5) = 0;
13711 return name;
13714 #if defined OBJ_COFF || defined OBJ_ELF
13715 void
13716 arm_validate_fix (fixS * fixP)
13718 /* If the destination of the branch is a defined symbol which does not have
13719 the THUMB_FUNC attribute, then we must be calling a function which has
13720 the (interfacearm) attribute. We look for the Thumb entry point to that
13721 function and change the branch to refer to that function instead. */
13722 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23
13723 && fixP->fx_addsy != NULL
13724 && S_IS_DEFINED (fixP->fx_addsy)
13725 && ! THUMB_IS_FUNC (fixP->fx_addsy))
13727 fixP->fx_addsy = find_real_start (fixP->fx_addsy);
13730 #endif
13733 arm_force_relocation (struct fix * fixp)
13735 #if defined (OBJ_COFF) && defined (TE_PE)
13736 if (fixp->fx_r_type == BFD_RELOC_RVA)
13737 return 1;
13738 #endif
13739 #ifdef OBJ_ELF
13740 if (fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
13741 || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
13742 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX
13743 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23)
13744 return 1;
13745 #endif
13747 /* Resolve these relocations even if the symbol is extern or weak. */
13748 if (fixp->fx_r_type == BFD_RELOC_ARM_IMMEDIATE
13749 || fixp->fx_r_type == BFD_RELOC_ARM_OFFSET_IMM
13750 || fixp->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
13751 return 0;
13753 return generic_force_reloc (fixp);
13756 #ifdef OBJ_COFF
13757 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
13758 local labels from being added to the output symbol table when they
13759 are used with the ADRL pseudo op. The ADRL relocation should always
13760 be resolved before the binbary is emitted, so it is safe to say that
13761 it is adjustable. */
13763 bfd_boolean
13764 arm_fix_adjustable (fixS * fixP)
13766 if (fixP->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
13767 return 1;
13768 return 0;
13770 #endif
13772 #ifdef OBJ_ELF
13773 /* Relocations against Thumb function names must be left unadjusted,
13774 so that the linker can use this information to correctly set the
13775 bottom bit of their addresses. The MIPS version of this function
13776 also prevents relocations that are mips-16 specific, but I do not
13777 know why it does this.
13779 FIXME:
13780 There is one other problem that ought to be addressed here, but
13781 which currently is not: Taking the address of a label (rather
13782 than a function) and then later jumping to that address. Such
13783 addresses also ought to have their bottom bit set (assuming that
13784 they reside in Thumb code), but at the moment they will not. */
13786 bfd_boolean
13787 arm_fix_adjustable (fixS * fixP)
13789 if (fixP->fx_addsy == NULL)
13790 return 1;
13792 if (THUMB_IS_FUNC (fixP->fx_addsy)
13793 && fixP->fx_subsy == NULL)
13794 return 0;
13796 /* We need the symbol name for the VTABLE entries. */
13797 if ( fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
13798 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
13799 return 0;
13801 /* Don't allow symbols to be discarded on GOT related relocs. */
13802 if (fixP->fx_r_type == BFD_RELOC_ARM_PLT32
13803 || fixP->fx_r_type == BFD_RELOC_ARM_GOT32
13804 || fixP->fx_r_type == BFD_RELOC_ARM_GOTOFF
13805 || fixP->fx_r_type == BFD_RELOC_ARM_TLS_GD32
13806 || fixP->fx_r_type == BFD_RELOC_ARM_TLS_LE32
13807 || fixP->fx_r_type == BFD_RELOC_ARM_TLS_IE32
13808 || fixP->fx_r_type == BFD_RELOC_ARM_TLS_LDM32
13809 || fixP->fx_r_type == BFD_RELOC_ARM_TLS_LDO32
13810 || fixP->fx_r_type == BFD_RELOC_ARM_TARGET2)
13811 return 0;
13813 return 1;
13816 const char *
13817 elf32_arm_target_format (void)
13819 #ifdef TE_SYMBIAN
13820 return (target_big_endian
13821 ? "elf32-bigarm-symbian"
13822 : "elf32-littlearm-symbian");
13823 #elif defined (TE_VXWORKS)
13824 return (target_big_endian
13825 ? "elf32-bigarm-vxworks"
13826 : "elf32-littlearm-vxworks");
13827 #else
13828 if (target_big_endian)
13829 return "elf32-bigarm";
13830 else
13831 return "elf32-littlearm";
13832 #endif
13835 void
13836 armelf_frob_symbol (symbolS * symp,
13837 int * puntp)
13839 elf_frob_symbol (symp, puntp);
13842 static void
13843 s_arm_elf_cons (int nbytes)
13845 expressionS exp;
13847 #ifdef md_flush_pending_output
13848 md_flush_pending_output ();
13849 #endif
13851 if (is_it_end_of_statement ())
13853 demand_empty_rest_of_line ();
13854 return;
13857 #ifdef md_cons_align
13858 md_cons_align (nbytes);
13859 #endif
13861 mapping_state (MAP_DATA);
13864 bfd_reloc_code_real_type reloc;
13865 char *sym_start;
13866 int sym_len;
13868 sym_start = input_line_pointer;
13869 expression (& exp);
13870 sym_len = input_line_pointer - sym_start;
13872 if (exp.X_op == O_symbol
13873 && * input_line_pointer == '('
13874 && (reloc = arm_parse_reloc ()) != BFD_RELOC_UNUSED)
13876 reloc_howto_type *howto = bfd_reloc_type_lookup (stdoutput, reloc);
13877 int size = bfd_get_reloc_size (howto);
13879 if (size > nbytes)
13880 as_bad ("%s relocations do not fit in %d bytes",
13881 howto->name, nbytes);
13882 else
13884 char *p;
13885 int offset = nbytes - size;
13886 char *saved_buf = alloca (sym_len), *saved_input;
13888 /* We've parsed an expression stopping at O_symbol. But there
13889 may be more expression left now that we have parsed the
13890 relocation marker. Parse it again. */
13891 saved_input = input_line_pointer - sym_len;
13892 memcpy (saved_buf, saved_input, sym_len);
13893 memmove (saved_input, sym_start, sym_len);
13894 input_line_pointer = saved_input;
13895 expression (& exp);
13896 memcpy (saved_input, saved_buf, sym_len);
13897 assert (input_line_pointer >= saved_input + sym_len);
13899 p = frag_more ((int) nbytes);
13900 fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size,
13901 &exp, 0, reloc);
13904 else
13905 emit_expr (&exp, (unsigned int) nbytes);
13907 while (*input_line_pointer++ == ',');
13909 /* Put terminator back into stream. */
13910 input_line_pointer --;
13911 demand_empty_rest_of_line ();
13915 /* Parse a .rel31 directive. */
13917 static void
13918 s_arm_rel31 (int ignored ATTRIBUTE_UNUSED)
13920 expressionS exp;
13921 char *p;
13922 valueT highbit;
13924 SKIP_WHITESPACE ();
13926 highbit = 0;
13927 if (*input_line_pointer == '1')
13928 highbit = 0x80000000;
13929 else if (*input_line_pointer != '0')
13930 as_bad (_("expected 0 or 1"));
13932 input_line_pointer++;
13933 SKIP_WHITESPACE ();
13934 if (*input_line_pointer != ',')
13935 as_bad (_("missing comma"));
13936 input_line_pointer++;
13938 #ifdef md_flush_pending_output
13939 md_flush_pending_output ();
13940 #endif
13942 #ifdef md_cons_align
13943 md_cons_align (4);
13944 #endif
13946 mapping_state (MAP_DATA);
13948 expression (&exp);
13950 p = frag_more (4);
13951 md_number_to_chars (p, highbit, 4);
13952 fix_new_arm (frag_now, p - frag_now->fr_literal, 4, &exp, 1,
13953 BFD_RELOC_ARM_PREL31);
13955 demand_empty_rest_of_line ();
13958 /* Code to deal with unwinding tables. */
13960 static void add_unwind_adjustsp (offsetT);
13962 /* Switch to section NAME and create section if necessary. It's
13963 rather ugly that we have to manipulate input_line_pointer but I
13964 don't see any other way to accomplish the same thing without
13965 changing obj-elf.c (which may be the Right Thing, in the end).
13966 Copied from tc-ia64.c. */
13968 static void
13969 set_section (char *name)
13971 char *saved_input_line_pointer;
13973 saved_input_line_pointer = input_line_pointer;
13974 input_line_pointer = name;
13975 obj_elf_section (0);
13976 input_line_pointer = saved_input_line_pointer;
13979 /* Cenerate and deferred unwind frame offset. */
13981 static void
13982 flush_pending_unwind (void)
13984 offsetT offset;
13986 offset = unwind.pending_offset;
13987 unwind.pending_offset = 0;
13988 if (offset != 0)
13989 add_unwind_adjustsp (offset);
13992 /* Add an opcode to this list for this function. Two-byte opcodes should
13993 be passed as op[0] << 8 | op[1]. The list of opcodes is built in reverse
13994 order. */
13996 static void
13997 add_unwind_opcode (valueT op, int length)
13999 /* Add any deferred stack adjustment. */
14000 if (unwind.pending_offset)
14001 flush_pending_unwind ();
14003 unwind.sp_restored = 0;
14005 if (unwind.opcode_count + length > unwind.opcode_alloc)
14007 unwind.opcode_alloc += ARM_OPCODE_CHUNK_SIZE;
14008 if (unwind.opcodes)
14009 unwind.opcodes = xrealloc (unwind.opcodes,
14010 unwind.opcode_alloc);
14011 else
14012 unwind.opcodes = xmalloc (unwind.opcode_alloc);
14014 while (length > 0)
14016 length--;
14017 unwind.opcodes[unwind.opcode_count] = op & 0xff;
14018 op >>= 8;
14019 unwind.opcode_count++;
14023 /* Add unwind opcodes to adjust the stack pointer. */
14025 static void
14026 add_unwind_adjustsp (offsetT offset)
14028 valueT op;
14030 if (offset > 0x200)
14032 /* We need at most 5 bytes to hold a 32-bit value in a uleb128. */
14033 char bytes[5];
14034 int n;
14035 valueT o;
14037 /* Long form: 0xb2, uleb128. */
14038 /* This might not fit in a word so add the individual bytes,
14039 remembering the list is built in reverse order. */
14040 o = (valueT) ((offset - 0x204) >> 2);
14041 if (o == 0)
14042 add_unwind_opcode (0, 1);
14044 /* Calculate the uleb128 encoding of the offset. */
14045 n = 0;
14046 while (o)
14048 bytes[n] = o & 0x7f;
14049 o >>= 7;
14050 if (o)
14051 bytes[n] |= 0x80;
14052 n++;
14054 /* Add the insn. */
14055 for (; n; n--)
14056 add_unwind_opcode (bytes[n - 1], 1);
14057 add_unwind_opcode (0xb2, 1);
14059 else if (offset > 0x100)
14061 /* Two short opcodes. */
14062 add_unwind_opcode (0x3f, 1);
14063 op = (offset - 0x104) >> 2;
14064 add_unwind_opcode (op, 1);
14066 else if (offset > 0)
14068 /* Short opcode. */
14069 op = (offset - 4) >> 2;
14070 add_unwind_opcode (op, 1);
14072 else if (offset < 0)
14074 offset = -offset;
14075 while (offset > 0x100)
14077 add_unwind_opcode (0x7f, 1);
14078 offset -= 0x100;
14080 op = ((offset - 4) >> 2) | 0x40;
14081 add_unwind_opcode (op, 1);
14085 /* Finish the list of unwind opcodes for this function. */
14086 static void
14087 finish_unwind_opcodes (void)
14089 valueT op;
14091 if (unwind.fp_used)
14093 /* Adjust sp as neccessary. */
14094 unwind.pending_offset += unwind.fp_offset - unwind.frame_size;
14095 flush_pending_unwind ();
14097 /* After restoring sp from the frame pointer. */
14098 op = 0x90 | unwind.fp_reg;
14099 add_unwind_opcode (op, 1);
14101 else
14102 flush_pending_unwind ();
14106 /* Start an exception table entry. If idx is nonzero this is an index table
14107 entry. */
14109 static void
14110 start_unwind_section (const segT text_seg, int idx)
14112 const char * text_name;
14113 const char * prefix;
14114 const char * prefix_once;
14115 size_t prefix_len;
14116 size_t text_len;
14117 char * sec_name;
14118 size_t sec_name_len;
14120 if (idx)
14122 prefix = ELF_STRING_ARM_unwind;
14123 prefix_once = ELF_STRING_ARM_unwind_once;
14125 else
14127 prefix = ELF_STRING_ARM_unwind_info;
14128 prefix_once = ELF_STRING_ARM_unwind_info_once;
14131 text_name = segment_name (text_seg);
14132 if (streq (text_name, ".text"))
14133 text_name = "";
14135 if (strncmp (text_name, ".gnu.linkonce.t.",
14136 strlen (".gnu.linkonce.t.")) == 0)
14138 prefix = prefix_once;
14139 text_name += strlen (".gnu.linkonce.t.");
14142 prefix_len = strlen (prefix);
14143 text_len = strlen (text_name);
14144 sec_name_len = prefix_len + text_len;
14145 sec_name = alloca (sec_name_len + 1);
14146 memcpy (sec_name, prefix, prefix_len);
14147 memcpy (sec_name + prefix_len, text_name, text_len);
14148 sec_name[prefix_len + text_len] = '\0';
14150 /* Handle COMDAT group. */
14151 if (prefix != prefix_once && (text_seg->flags & SEC_LINK_ONCE) != 0)
14153 char *section;
14154 size_t len, group_name_len;
14155 const char *group_name = elf_group_name (text_seg);
14157 if (group_name == NULL)
14159 as_bad ("Group section `%s' has no group signature",
14160 segment_name (text_seg));
14161 ignore_rest_of_line ();
14162 return;
14164 /* We have to construct a fake section directive. */
14165 group_name_len = strlen (group_name);
14166 if (idx)
14167 prefix_len = 13;
14168 else
14169 prefix_len = 16;
14171 len = (sec_name_len
14172 + prefix_len /* ,"aG",%sectiontype, */
14173 + group_name_len /* ,group_name */
14174 + 7); /* ,comdat */
14176 section = alloca (len + 1);
14177 memcpy (section, sec_name, sec_name_len);
14178 if (idx)
14179 memcpy (section + sec_name_len, ",\"aG\",%exidx,", 13);
14180 else
14181 memcpy (section + sec_name_len, ",\"aG\",%progbits,", 16);
14182 memcpy (section + sec_name_len + prefix_len, group_name, group_name_len);
14183 memcpy (section + len - 7, ",comdat", 7);
14184 section [len] = '\0';
14185 set_section (section);
14187 else
14189 set_section (sec_name);
14190 bfd_set_section_flags (stdoutput, now_seg,
14191 SEC_LOAD | SEC_ALLOC | SEC_READONLY);
14194 /* Set the setion link for index tables. */
14195 if (idx)
14196 elf_linked_to_section (now_seg) = text_seg;
14200 /* Start an unwind table entry. HAVE_DATA is nonzero if we have additional
14201 personality routine data. Returns zero, or the index table value for
14202 and inline entry. */
14204 static valueT
14205 create_unwind_entry (int have_data)
14207 int size;
14208 addressT where;
14209 char *ptr;
14210 /* The current word of data. */
14211 valueT data;
14212 /* The number of bytes left in this word. */
14213 int n;
14215 finish_unwind_opcodes ();
14217 /* Remember the current text section. */
14218 unwind.saved_seg = now_seg;
14219 unwind.saved_subseg = now_subseg;
14221 start_unwind_section (now_seg, 0);
14223 if (unwind.personality_routine == NULL)
14225 if (unwind.personality_index == -2)
14227 if (have_data)
14228 as_bad (_("handerdata in cantunwind frame"));
14229 return 1; /* EXIDX_CANTUNWIND. */
14232 /* Use a default personality routine if none is specified. */
14233 if (unwind.personality_index == -1)
14235 if (unwind.opcode_count > 3)
14236 unwind.personality_index = 1;
14237 else
14238 unwind.personality_index = 0;
14241 /* Space for the personality routine entry. */
14242 if (unwind.personality_index == 0)
14244 if (unwind.opcode_count > 3)
14245 as_bad (_("too many unwind opcodes for personality routine 0"));
14247 if (!have_data)
14249 /* All the data is inline in the index table. */
14250 data = 0x80;
14251 n = 3;
14252 while (unwind.opcode_count > 0)
14254 unwind.opcode_count--;
14255 data = (data << 8) | unwind.opcodes[unwind.opcode_count];
14256 n--;
14259 /* Pad with "finish" opcodes. */
14260 while (n--)
14261 data = (data << 8) | 0xb0;
14263 return data;
14265 size = 0;
14267 else
14268 /* We get two opcodes "free" in the first word. */
14269 size = unwind.opcode_count - 2;
14271 else
14272 /* An extra byte is required for the opcode count. */
14273 size = unwind.opcode_count + 1;
14275 size = (size + 3) >> 2;
14276 if (size > 0xff)
14277 as_bad (_("too many unwind opcodes"));
14279 frag_align (2, 0, 0);
14280 record_alignment (now_seg, 2);
14281 unwind.table_entry = expr_build_dot ();
14283 /* Allocate the table entry. */
14284 ptr = frag_more ((size << 2) + 4);
14285 where = frag_now_fix () - ((size << 2) + 4);
14287 switch (unwind.personality_index)
14289 case -1:
14290 /* ??? Should this be a PLT generating relocation? */
14291 /* Custom personality routine. */
14292 fix_new (frag_now, where, 4, unwind.personality_routine, 0, 1,
14293 BFD_RELOC_ARM_PREL31);
14295 where += 4;
14296 ptr += 4;
14298 /* Set the first byte to the number of additional words. */
14299 data = size - 1;
14300 n = 3;
14301 break;
14303 /* ABI defined personality routines. */
14304 case 0:
14305 /* Three opcodes bytes are packed into the first word. */
14306 data = 0x80;
14307 n = 3;
14308 break;
14310 case 1:
14311 case 2:
14312 /* The size and first two opcode bytes go in the first word. */
14313 data = ((0x80 + unwind.personality_index) << 8) | size;
14314 n = 2;
14315 break;
14317 default:
14318 /* Should never happen. */
14319 abort ();
14322 /* Pack the opcodes into words (MSB first), reversing the list at the same
14323 time. */
14324 while (unwind.opcode_count > 0)
14326 if (n == 0)
14328 md_number_to_chars (ptr, data, 4);
14329 ptr += 4;
14330 n = 4;
14331 data = 0;
14333 unwind.opcode_count--;
14334 n--;
14335 data = (data << 8) | unwind.opcodes[unwind.opcode_count];
14338 /* Finish off the last word. */
14339 if (n < 4)
14341 /* Pad with "finish" opcodes. */
14342 while (n--)
14343 data = (data << 8) | 0xb0;
14345 md_number_to_chars (ptr, data, 4);
14348 if (!have_data)
14350 /* Add an empty descriptor if there is no user-specified data. */
14351 ptr = frag_more (4);
14352 md_number_to_chars (ptr, 0, 4);
14355 return 0;
14359 /* Parse an unwind_fnstart directive. Simply records the current location. */
14361 static void
14362 s_arm_unwind_fnstart (int ignored ATTRIBUTE_UNUSED)
14364 demand_empty_rest_of_line ();
14365 /* Mark the start of the function. */
14366 unwind.proc_start = expr_build_dot ();
14368 /* Reset the rest of the unwind info. */
14369 unwind.opcode_count = 0;
14370 unwind.table_entry = NULL;
14371 unwind.personality_routine = NULL;
14372 unwind.personality_index = -1;
14373 unwind.frame_size = 0;
14374 unwind.fp_offset = 0;
14375 unwind.fp_reg = 13;
14376 unwind.fp_used = 0;
14377 unwind.sp_restored = 0;
14381 /* Parse a handlerdata directive. Creates the exception handling table entry
14382 for the function. */
14384 static void
14385 s_arm_unwind_handlerdata (int ignored ATTRIBUTE_UNUSED)
14387 demand_empty_rest_of_line ();
14388 if (unwind.table_entry)
14389 as_bad (_("dupicate .handlerdata directive"));
14391 create_unwind_entry (1);
14394 /* Parse an unwind_fnend directive. Generates the index table entry. */
14396 static void
14397 s_arm_unwind_fnend (int ignored ATTRIBUTE_UNUSED)
14399 long where;
14400 char *ptr;
14401 valueT val;
14403 demand_empty_rest_of_line ();
14405 /* Add eh table entry. */
14406 if (unwind.table_entry == NULL)
14407 val = create_unwind_entry (0);
14408 else
14409 val = 0;
14411 /* Add index table entry. This is two words. */
14412 start_unwind_section (unwind.saved_seg, 1);
14413 frag_align (2, 0, 0);
14414 record_alignment (now_seg, 2);
14416 ptr = frag_more (8);
14417 where = frag_now_fix () - 8;
14419 /* Self relative offset of the function start. */
14420 fix_new (frag_now, where, 4, unwind.proc_start, 0, 1,
14421 BFD_RELOC_ARM_PREL31);
14423 /* Indicate dependency on EHABI-defined personality routines to the
14424 linker, if it hasn't been done already. */
14425 if (unwind.personality_index >= 0 && unwind.personality_index < 3)
14427 char *name[] = { "__aeabi_unwind_cpp_pr0",
14428 "__aeabi_unwind_cpp_pr1",
14429 "__aeabi_unwind_cpp_pr2" };
14430 if (!(marked_pr_dependency & (1 << unwind.personality_index)))
14432 symbolS *pr = symbol_find_or_make (name[unwind.personality_index]);
14433 fix_new (frag_now, where, 0, pr, 0, 1, BFD_RELOC_NONE);
14434 marked_pr_dependency |= 1 << unwind.personality_index;
14435 seg_info (now_seg)->tc_segment_info_data.marked_pr_dependency
14436 = marked_pr_dependency;
14440 if (val)
14441 /* Inline exception table entry. */
14442 md_number_to_chars (ptr + 4, val, 4);
14443 else
14444 /* Self relative offset of the table entry. */
14445 fix_new (frag_now, where + 4, 4, unwind.table_entry, 0, 1,
14446 BFD_RELOC_ARM_PREL31);
14448 /* Restore the original section. */
14449 subseg_set (unwind.saved_seg, unwind.saved_subseg);
14453 /* Parse an unwind_cantunwind directive. */
14455 static void
14456 s_arm_unwind_cantunwind (int ignored ATTRIBUTE_UNUSED)
14458 demand_empty_rest_of_line ();
14459 if (unwind.personality_routine || unwind.personality_index != -1)
14460 as_bad (_("personality routine specified for cantunwind frame"));
14462 unwind.personality_index = -2;
14466 /* Parse a personalityindex directive. */
14468 static void
14469 s_arm_unwind_personalityindex (int ignored ATTRIBUTE_UNUSED)
14471 expressionS exp;
14473 if (unwind.personality_routine || unwind.personality_index != -1)
14474 as_bad (_("duplicate .personalityindex directive"));
14476 SKIP_WHITESPACE ();
14478 expression (&exp);
14480 if (exp.X_op != O_constant
14481 || exp.X_add_number < 0 || exp.X_add_number > 15)
14483 as_bad (_("bad personality routine number"));
14484 ignore_rest_of_line ();
14485 return;
14488 unwind.personality_index = exp.X_add_number;
14490 demand_empty_rest_of_line ();
14494 /* Parse a personality directive. */
14496 static void
14497 s_arm_unwind_personality (int ignored ATTRIBUTE_UNUSED)
14499 char *name, *p, c;
14501 if (unwind.personality_routine || unwind.personality_index != -1)
14502 as_bad (_("duplicate .personality directive"));
14504 SKIP_WHITESPACE ();
14505 name = input_line_pointer;
14506 c = get_symbol_end ();
14507 p = input_line_pointer;
14508 unwind.personality_routine = symbol_find_or_make (name);
14509 *p = c;
14510 SKIP_WHITESPACE ();
14511 demand_empty_rest_of_line ();
14515 /* Parse a directive saving core registers. */
14517 static void
14518 s_arm_unwind_save_core (void)
14520 valueT op;
14521 long range;
14522 int n;
14524 SKIP_WHITESPACE ();
14525 range = reg_list (&input_line_pointer);
14526 if (range == FAIL)
14528 as_bad (_("expected register list"));
14529 ignore_rest_of_line ();
14530 return;
14533 demand_empty_rest_of_line ();
14535 /* Turn .unwind_movsp ip followed by .unwind_save {..., ip, ...}
14536 into .unwind_save {..., sp...}. We aren't bothered about the value of
14537 ip because it is clobbered by calls. */
14538 if (unwind.sp_restored && unwind.fp_reg == 12
14539 && (range & 0x3000) == 0x1000)
14541 unwind.opcode_count--;
14542 unwind.sp_restored = 0;
14543 range = (range | 0x2000) & ~0x1000;
14544 unwind.pending_offset = 0;
14547 /* See if we can use the short opcodes. These pop a block of upto 8
14548 registers starting with r4, plus maybe r14. */
14549 for (n = 0; n < 8; n++)
14551 /* Break at the first non-saved register. */
14552 if ((range & (1 << (n + 4))) == 0)
14553 break;
14555 /* See if there are any other bits set. */
14556 if (n == 0 || (range & (0xfff0 << n) & 0xbff0) != 0)
14558 /* Use the long form. */
14559 op = 0x8000 | ((range >> 4) & 0xfff);
14560 add_unwind_opcode (op, 2);
14562 else
14564 /* Use the short form. */
14565 if (range & 0x4000)
14566 op = 0xa8; /* Pop r14. */
14567 else
14568 op = 0xa0; /* Do not pop r14. */
14569 op |= (n - 1);
14570 add_unwind_opcode (op, 1);
14573 /* Pop r0-r3. */
14574 if (range & 0xf)
14576 op = 0xb100 | (range & 0xf);
14577 add_unwind_opcode (op, 2);
14580 /* Record the number of bytes pushed. */
14581 for (n = 0; n < 16; n++)
14583 if (range & (1 << n))
14584 unwind.frame_size += 4;
14589 /* Parse a directive saving FPA registers. */
14591 static void
14592 s_arm_unwind_save_fpa (int reg)
14594 expressionS exp;
14595 int num_regs;
14596 valueT op;
14598 /* Get Number of registers to transfer. */
14599 if (skip_past_comma (&input_line_pointer) != FAIL)
14600 expression (&exp);
14601 else
14602 exp.X_op = O_illegal;
14604 if (exp.X_op != O_constant)
14606 as_bad (_("expected , <constant>"));
14607 ignore_rest_of_line ();
14608 return;
14611 num_regs = exp.X_add_number;
14613 if (num_regs < 1 || num_regs > 4)
14615 as_bad (_("number of registers must be in the range [1:4]"));
14616 ignore_rest_of_line ();
14617 return;
14620 demand_empty_rest_of_line ();
14622 if (reg == 4)
14624 /* Short form. */
14625 op = 0xb4 | (num_regs - 1);
14626 add_unwind_opcode (op, 1);
14628 else
14630 /* Long form. */
14631 op = 0xc800 | (reg << 4) | (num_regs - 1);
14632 add_unwind_opcode (op, 2);
14634 unwind.frame_size += num_regs * 12;
14638 /* Parse a directive saving VFP registers. */
14640 static void
14641 s_arm_unwind_save_vfp (void)
14643 int count;
14644 int reg;
14645 valueT op;
14647 count = vfp_parse_reg_list (&input_line_pointer, &reg, 1);
14648 if (count == FAIL)
14650 as_bad (_("expected register list"));
14651 ignore_rest_of_line ();
14652 return;
14655 demand_empty_rest_of_line ();
14657 if (reg == 8)
14659 /* Short form. */
14660 op = 0xb8 | (count - 1);
14661 add_unwind_opcode (op, 1);
14663 else
14665 /* Long form. */
14666 op = 0xb300 | (reg << 4) | (count - 1);
14667 add_unwind_opcode (op, 2);
14669 unwind.frame_size += count * 8 + 4;
14673 /* Parse a directive saving iWMMXt registers. */
14675 static void
14676 s_arm_unwind_save_wmmx (void)
14678 int reg;
14679 int hi_reg;
14680 int i;
14681 unsigned wcg_mask;
14682 unsigned wr_mask;
14683 valueT op;
14685 if (*input_line_pointer == '{')
14686 input_line_pointer++;
14688 wcg_mask = 0;
14689 wr_mask = 0;
14692 reg = arm_reg_parse (&input_line_pointer,
14693 all_reg_maps[REG_TYPE_IWMMXT].htab);
14695 if (wr_register (reg))
14697 i = reg & ~WR_PREFIX;
14698 if (wr_mask >> i)
14699 as_tsktsk (_("register list not in ascending order"));
14700 wr_mask |= 1 << i;
14702 else if (wcg_register (reg))
14704 i = (reg & ~WC_PREFIX) - 8;
14705 if (wcg_mask >> i)
14706 as_tsktsk (_("register list not in ascending order"));
14707 wcg_mask |= 1 << i;
14709 else
14711 as_bad (_("expected wr or wcgr"));
14712 goto error;
14715 SKIP_WHITESPACE ();
14716 if (*input_line_pointer == '-')
14718 hi_reg = arm_reg_parse (&input_line_pointer,
14719 all_reg_maps[REG_TYPE_IWMMXT].htab);
14720 if (wr_register (reg) && wr_register (hi_reg))
14722 for (; reg < hi_reg; reg++)
14723 wr_mask |= 1 << (reg & ~WR_PREFIX);
14725 else if (wcg_register (reg) && wcg_register (hi_reg))
14727 for (; reg < hi_reg; reg++)
14728 wcg_mask |= 1 << ((reg & ~WC_PREFIX) - 8);
14730 else
14732 as_bad (_("bad register range"));
14733 goto error;
14737 while (skip_past_comma (&input_line_pointer) != FAIL);
14739 SKIP_WHITESPACE ();
14740 if (*input_line_pointer == '}')
14741 input_line_pointer++;
14743 demand_empty_rest_of_line ();
14745 if (wr_mask && wcg_mask)
14747 as_bad (_("inconsistent register types"));
14748 goto error;
14751 /* Generate any deferred opcodes becuuse we're going to be looking at
14752 the list. */
14753 flush_pending_unwind ();
14755 if (wcg_mask)
14757 for (i = 0; i < 16; i++)
14759 if (wcg_mask & (1 << i))
14760 unwind.frame_size += 4;
14762 op = 0xc700 | wcg_mask;
14763 add_unwind_opcode (op, 2);
14765 else
14767 for (i = 0; i < 16; i++)
14769 if (wr_mask & (1 << i))
14770 unwind.frame_size += 8;
14772 /* Attempt to combine with a previous opcode. We do this because gcc
14773 likes to output separate unwind directives for a single block of
14774 registers. */
14775 if (unwind.opcode_count > 0)
14777 i = unwind.opcodes[unwind.opcode_count - 1];
14778 if ((i & 0xf8) == 0xc0)
14780 i &= 7;
14781 /* Only merge if the blocks are contiguous. */
14782 if (i < 6)
14784 if ((wr_mask & 0xfe00) == (1 << 9))
14786 wr_mask |= ((1 << (i + 11)) - 1) & 0xfc00;
14787 unwind.opcode_count--;
14790 else if (i == 6 && unwind.opcode_count >= 2)
14792 i = unwind.opcodes[unwind.opcode_count - 2];
14793 reg = i >> 4;
14794 i &= 0xf;
14796 op = 0xffff << (reg - 1);
14797 if (reg > 0
14798 || ((wr_mask & op) == (1u << (reg - 1))))
14800 op = (1 << (reg + i + 1)) - 1;
14801 op &= ~((1 << reg) - 1);
14802 wr_mask |= op;
14803 unwind.opcode_count -= 2;
14809 hi_reg = 15;
14810 /* We want to generate opcodes in the order the registers have been
14811 saved, ie. descending order. */
14812 for (reg = 15; reg >= -1; reg--)
14814 /* Save registers in blocks. */
14815 if (reg < 0
14816 || !(wr_mask & (1 << reg)))
14818 /* We found an unsaved reg. Generate opcodes to save the
14819 preceeding block. */
14820 if (reg != hi_reg)
14822 if (reg == 9)
14824 /* Short form. */
14825 op = 0xc0 | (hi_reg - 10);
14826 add_unwind_opcode (op, 1);
14828 else
14830 /* Long form. */
14831 op = 0xc600 | ((reg + 1) << 4) | ((hi_reg - reg) - 1);
14832 add_unwind_opcode (op, 2);
14835 hi_reg = reg - 1;
14839 return;
14840 error:
14841 ignore_rest_of_line ();
14845 /* Parse an unwind_save directive. */
14847 static void
14848 s_arm_unwind_save (int ignored ATTRIBUTE_UNUSED)
14850 char *saved_ptr;
14851 int reg;
14853 /* Figure out what sort of save we have. */
14854 SKIP_WHITESPACE ();
14855 saved_ptr = input_line_pointer;
14857 reg = arm_reg_parse (&input_line_pointer, all_reg_maps[REG_TYPE_FN].htab);
14858 if (reg != FAIL)
14860 s_arm_unwind_save_fpa (reg);
14861 return;
14864 if (*input_line_pointer == '{')
14865 input_line_pointer++;
14867 SKIP_WHITESPACE ();
14869 reg = arm_reg_parse (&input_line_pointer, all_reg_maps[REG_TYPE_RN].htab);
14870 if (reg != FAIL)
14872 input_line_pointer = saved_ptr;
14873 s_arm_unwind_save_core ();
14874 return;
14877 reg = arm_reg_parse (&input_line_pointer, all_reg_maps[REG_TYPE_DN].htab);
14878 if (reg != FAIL)
14880 input_line_pointer = saved_ptr;
14881 s_arm_unwind_save_vfp ();
14882 return;
14885 reg = arm_reg_parse (&input_line_pointer,
14886 all_reg_maps[REG_TYPE_IWMMXT].htab);
14887 if (reg != FAIL)
14889 input_line_pointer = saved_ptr;
14890 s_arm_unwind_save_wmmx ();
14891 return;
14894 /* TODO: Maverick registers. */
14895 as_bad (_("unrecognised register"));
14899 /* Parse an unwind_movsp directive. */
14901 static void
14902 s_arm_unwind_movsp (int ignored ATTRIBUTE_UNUSED)
14904 int reg;
14905 valueT op;
14907 SKIP_WHITESPACE ();
14908 reg = reg_required_here (&input_line_pointer, -1);
14909 if (reg == FAIL)
14911 as_bad (_("ARM register expected"));
14912 ignore_rest_of_line ();
14913 return;
14916 if (reg == 13 || reg == 15)
14918 as_bad (_("r%d not permitted in .unwind_movsp directive"), reg);
14919 ignore_rest_of_line ();
14920 return;
14923 if (unwind.fp_reg != 13)
14924 as_bad (_("unexpected .unwind_movsp directive"));
14926 /* Generate opcode to restore the value. */
14927 op = 0x90 | reg;
14928 add_unwind_opcode (op, 1);
14930 /* Record the information for later. */
14931 unwind.fp_reg = reg;
14932 unwind.fp_offset = unwind.frame_size;
14933 unwind.sp_restored = 1;
14934 demand_empty_rest_of_line ();
14938 /* Parse #<number>. */
14940 static int
14941 require_hashconst (int * val)
14943 expressionS exp;
14945 SKIP_WHITESPACE ();
14946 if (*input_line_pointer == '#')
14948 input_line_pointer++;
14949 expression (&exp);
14951 else
14952 exp.X_op = O_illegal;
14954 if (exp.X_op != O_constant)
14956 as_bad (_("expected #constant"));
14957 ignore_rest_of_line ();
14958 return FAIL;
14960 *val = exp.X_add_number;
14961 return SUCCESS;
14964 /* Parse an unwind_pad directive. */
14966 static void
14967 s_arm_unwind_pad (int ignored ATTRIBUTE_UNUSED)
14969 int offset;
14971 if (require_hashconst (&offset) == FAIL)
14972 return;
14974 if (offset & 3)
14976 as_bad (_("stack increment must be multiple of 4"));
14977 ignore_rest_of_line ();
14978 return;
14981 /* Don't generate any opcodes, just record the details for later. */
14982 unwind.frame_size += offset;
14983 unwind.pending_offset += offset;
14985 demand_empty_rest_of_line ();
14988 /* Parse an unwind_setfp directive. */
14990 static void
14991 s_arm_unwind_setfp (int ignored ATTRIBUTE_UNUSED)
14993 int sp_reg;
14994 int fp_reg;
14995 int offset;
14997 fp_reg = reg_required_here (&input_line_pointer, -1);
14998 if (skip_past_comma (&input_line_pointer) == FAIL)
14999 sp_reg = FAIL;
15000 else
15001 sp_reg = reg_required_here (&input_line_pointer, -1);
15003 if (fp_reg == FAIL || sp_reg == FAIL)
15005 as_bad (_("expected <reg>, <reg>"));
15006 ignore_rest_of_line ();
15007 return;
15010 /* Optonal constant. */
15011 if (skip_past_comma (&input_line_pointer) != FAIL)
15013 if (require_hashconst (&offset) == FAIL)
15014 return;
15016 else
15017 offset = 0;
15019 demand_empty_rest_of_line ();
15021 if (sp_reg != 13 && sp_reg != unwind.fp_reg)
15023 as_bad (_("register must be either sp or set by a previous"
15024 "unwind_movsp directive"));
15025 return;
15028 /* Don't generate any opcodes, just record the information for later. */
15029 unwind.fp_reg = fp_reg;
15030 unwind.fp_used = 1;
15031 if (sp_reg == 13)
15032 unwind.fp_offset = unwind.frame_size - offset;
15033 else
15034 unwind.fp_offset -= offset;
15037 /* Parse an unwind_raw directive. */
15039 static void
15040 s_arm_unwind_raw (int ignored ATTRIBUTE_UNUSED)
15042 expressionS exp;
15043 /* This is an arbitary limit. */
15044 unsigned char op[16];
15045 int count;
15047 SKIP_WHITESPACE ();
15048 expression (&exp);
15049 if (exp.X_op == O_constant
15050 && skip_past_comma (&input_line_pointer) != FAIL)
15052 unwind.frame_size += exp.X_add_number;
15053 expression (&exp);
15055 else
15056 exp.X_op = O_illegal;
15058 if (exp.X_op != O_constant)
15060 as_bad (_("expected <offset>, <opcode>"));
15061 ignore_rest_of_line ();
15062 return;
15065 count = 0;
15067 /* Parse the opcode. */
15068 for (;;)
15070 if (count >= 16)
15072 as_bad (_("unwind opcode too long"));
15073 ignore_rest_of_line ();
15075 if (exp.X_op != O_constant || exp.X_add_number & ~0xff)
15077 as_bad (_("invalid unwind opcode"));
15078 ignore_rest_of_line ();
15079 return;
15081 op[count++] = exp.X_add_number;
15083 /* Parse the next byte. */
15084 if (skip_past_comma (&input_line_pointer) == FAIL)
15085 break;
15087 expression (&exp);
15090 /* Add the opcode bytes in reverse order. */
15091 while (count--)
15092 add_unwind_opcode (op[count], 1);
15094 demand_empty_rest_of_line ();
15097 #endif /* OBJ_ELF */
15099 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
15100 of an rs_align_code fragment. */
15102 void
15103 arm_handle_align (fragS * fragP)
15105 static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 };
15106 static char const thumb_noop[2] = { 0xc0, 0x46 };
15107 static char const arm_bigend_noop[4] = { 0xe1, 0xa0, 0x00, 0x00 };
15108 static char const thumb_bigend_noop[2] = { 0x46, 0xc0 };
15110 int bytes, fix, noop_size;
15111 char * p;
15112 const char * noop;
15114 if (fragP->fr_type != rs_align_code)
15115 return;
15117 bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
15118 p = fragP->fr_literal + fragP->fr_fix;
15119 fix = 0;
15121 if (bytes > MAX_MEM_FOR_RS_ALIGN_CODE)
15122 bytes &= MAX_MEM_FOR_RS_ALIGN_CODE;
15124 if (fragP->tc_frag_data)
15126 if (target_big_endian)
15127 noop = thumb_bigend_noop;
15128 else
15129 noop = thumb_noop;
15130 noop_size = sizeof (thumb_noop);
15132 else
15134 if (target_big_endian)
15135 noop = arm_bigend_noop;
15136 else
15137 noop = arm_noop;
15138 noop_size = sizeof (arm_noop);
15141 if (bytes & (noop_size - 1))
15143 fix = bytes & (noop_size - 1);
15144 memset (p, 0, fix);
15145 p += fix;
15146 bytes -= fix;
15149 while (bytes >= noop_size)
15151 memcpy (p, noop, noop_size);
15152 p += noop_size;
15153 bytes -= noop_size;
15154 fix += noop_size;
15157 fragP->fr_fix += fix;
15158 fragP->fr_var = noop_size;
15161 /* Called from md_do_align. Used to create an alignment
15162 frag in a code section. */
15164 void
15165 arm_frag_align_code (int n, int max)
15167 char * p;
15169 /* We assume that there will never be a requirement
15170 to support alignments greater than 32 bytes. */
15171 if (max > MAX_MEM_FOR_RS_ALIGN_CODE)
15172 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
15174 p = frag_var (rs_align_code,
15175 MAX_MEM_FOR_RS_ALIGN_CODE,
15177 (relax_substateT) max,
15178 (symbolS *) NULL,
15179 (offsetT) n,
15180 (char *) NULL);
15181 *p = 0;
15184 /* Perform target specific initialisation of a frag. */
15186 void
15187 arm_init_frag (fragS * fragP)
15189 /* Record whether this frag is in an ARM or a THUMB area. */
15190 fragP->tc_frag_data = thumb_mode;
15193 #ifdef OBJ_ELF
15195 /* Convert REGNAME to a DWARF-2 register number. */
15198 tc_arm_regname_to_dw2regnum (const char *regname)
15200 unsigned int i;
15202 for (i = 0; rn_table[i].name; i++)
15203 if (streq (regname, rn_table[i].name))
15204 return rn_table[i].number;
15206 return -1;
15209 /* Initialize the DWARF-2 unwind information for this procedure. */
15211 void
15212 tc_arm_frame_initial_instructions (void)
15214 cfi_add_CFA_def_cfa (REG_SP, 0);
15216 #endif
15218 /* This table describes all the machine specific pseudo-ops the assembler
15219 has to support. The fields are:
15220 pseudo-op name without dot
15221 function to call to execute this pseudo-op
15222 Integer arg to pass to the function. */
15224 const pseudo_typeS md_pseudo_table[] =
15226 /* Never called because '.req' does not start a line. */
15227 { "req", s_req, 0 },
15228 { "unreq", s_unreq, 0 },
15229 { "bss", s_bss, 0 },
15230 { "align", s_align, 0 },
15231 { "arm", s_arm, 0 },
15232 { "thumb", s_thumb, 0 },
15233 { "code", s_code, 0 },
15234 { "force_thumb", s_force_thumb, 0 },
15235 { "thumb_func", s_thumb_func, 0 },
15236 { "thumb_set", s_thumb_set, 0 },
15237 { "even", s_even, 0 },
15238 { "ltorg", s_ltorg, 0 },
15239 { "pool", s_ltorg, 0 },
15240 #ifdef OBJ_ELF
15241 { "word", s_arm_elf_cons, 4 },
15242 { "long", s_arm_elf_cons, 4 },
15243 { "rel31", s_arm_rel31, 0 },
15244 { "fnstart", s_arm_unwind_fnstart, 0 },
15245 { "fnend", s_arm_unwind_fnend, 0 },
15246 { "cantunwind", s_arm_unwind_cantunwind, 0 },
15247 { "personality", s_arm_unwind_personality, 0 },
15248 { "personalityindex", s_arm_unwind_personalityindex, 0 },
15249 { "handlerdata", s_arm_unwind_handlerdata, 0 },
15250 { "save", s_arm_unwind_save, 0 },
15251 { "movsp", s_arm_unwind_movsp, 0 },
15252 { "pad", s_arm_unwind_pad, 0 },
15253 { "setfp", s_arm_unwind_setfp, 0 },
15254 { "unwind_raw", s_arm_unwind_raw, 0 },
15255 #else
15256 { "word", cons, 4},
15257 #endif
15258 { "extend", float_cons, 'x' },
15259 { "ldouble", float_cons, 'x' },
15260 { "packed", float_cons, 'p' },
15261 { 0, 0, 0 }