1 /* tc-arm.c -- Assemble for the ARM
2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
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)
18 GAS is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with GAS; see the file COPYING. If not, write to the Free
25 Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
31 #include "safe-ctype.h"
33 /* Need TARGET_CPU. */
40 #include "opcode/arm.h"
44 #include "dwarf2dbg.h"
45 #include "dw2gencfi.h"
48 /* XXX Set this to 1 after the next binutils release. */
49 #define WARN_DEPRECATED 0
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. */
60 symbolS * table_entry;
61 symbolS * personality_routine;
62 int personality_index;
63 /* The segment containing the function. */
66 /* Opcodes generated from this function. */
67 unsigned char * opcodes;
70 /* The number of bytes pushed to the stack. */
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. */
80 /* Nonzero if an unwind_setfp directive has been seen. */
82 /* Nonzero if the last opcode restores sp from fp_reg. */
83 unsigned sp_restored:1;
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;
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? */
113 #if defined __XSCALE__
114 #define CPU_DEFAULT (ARM_ARCH_XSCALE)
116 #if defined __thumb__
117 #define CPU_DEFAULT (ARM_ARCH_V5T)
119 #define CPU_DEFAULT ARM_ANY
126 # define FPU_DEFAULT FPU_ARCH_FPA
127 # elif defined (TE_NetBSD)
129 # define FPU_DEFAULT FPU_ARCH_VFP /* Soft-float, but VFP order. */
131 /* Legacy a.out format. */
132 # define FPU_DEFAULT FPU_ARCH_FPA /* Soft-float, but FPA order. */
134 # elif defined (TE_VXWORKS)
135 # define FPU_DEFAULT FPU_ARCH_VFP /* Soft-float, VFP order. */
137 /* For backwards compatibility, default to FPA. */
138 # define FPU_DEFAULT FPU_ARCH_FPA
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
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;
168 static int meabi_flags = EABI_DEFAULT;
170 static int meabi_flags = EF_ARM_EABI_UNKNOWN;
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. */
197 const char FLT_CHARS[] = "rRsSfFdDxXeEpP";
199 /* Prefix characters that indicate the start of an immediate
201 #define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
204 /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
205 symbolS * GOT_symbol;
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
215 static int thumb_mode = 0;
217 typedef struct arm_fix
225 unsigned long instruction;
229 bfd_reloc_code_real_type type;
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
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];
311 /* Whether a Co-processor load/store operation accepts write-back forms. */
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
333 const char * template;
337 #define COND_ALWAYS 0xe0000000
338 #define COND_MASK 0xf0000000
340 static const struct asm_cond conds[] =
344 {"cs", 0x20000000}, {"hs", 0x20000000},
345 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
362 const char *template;
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. */
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},
523 IWMMXT_REG_WR_OR_WC = 2,
527 enum iwmmxt_insn_type
550 VFP_REG_Dd, VFP_REG_Dm, VFP_REG_Dn
555 VFP_REG_Sd, VFP_REG_Sm, VFP_REG_Sn
560 VFP_LDSTMIA, VFP_LDSTMDB, VFP_LDSTMIAX, VFP_LDSTMDBX
563 /* VFP system registers. */
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. */
588 /* Some well known registers that we refer to directly elsewhere. */
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},
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},
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},
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},
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},
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},
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},
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},
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},
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},
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},
745 static const struct reg_entry mav_mvax_table[] =
747 {"mvax0", 0, TRUE}, {"mvax1", 1, TRUE}, {"mvax2", 2, TRUE}, {"mvax3", 3, TRUE},
751 static const struct reg_entry mav_dspsc_table[] =
759 const struct reg_entry * names;
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. */
786 #define REG_TYPE_FIRST REG_TYPE_RN
798 REG_TYPE_IWMMXT = 12,
803 /* ARM instructions take 4bytes in the object file, Thumb instructions
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
827 /* Basic string to match. */
828 const char * template;
830 /* Basic instruction code. */
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. */
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
943 #define THUMB_COMPARE 1
947 #define THUMB_STORE 1
949 #define THUMB_PP_PC_LR 0x0100
951 /* These three are used for immediate shifts, do not alter. */
953 #define THUMB_HALFWORD 1
958 /* Basic string to match. */
959 const char * template;
961 /* Basic instruction code. */
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
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;
1011 subsegT sub_section;
1012 struct literal_pool * next;
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)
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 ();
1044 /* Create a new pool. */
1045 pool = xmalloc (sizeof (* pool));
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 ++;
1071 /* Add the literal in the global 'inst'
1072 structure to the relevent literal pool. */
1075 add_to_lit_pool (void)
1077 literal_pool * pool;
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))
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))
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");
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;
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. */
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 (¬es, name, name_length);
1139 preserved_copy_of_name = obstack_finish (¬es);
1141 #ifdef tc_canonicalize_symbol_name
1142 preserved_copy_of_name =
1143 tc_canonicalize_symbol_name (preserved_copy_of_name);
1146 S_SET_NAME (symbolP, preserved_copy_of_name);
1148 S_SET_SEGMENT (symbolP, segment);
1149 S_SET_VALUE (symbolP, valu);
1150 symbol_clear_list_pointers (symbolP);
1152 symbol_set_frag (symbolP, frag);
1154 /* Link to end of symbol chain. */
1156 extern int symbol_table_frozen;
1158 if (symbol_table_frozen)
1162 symbol_append (symbolP, symbol_lastP, & symbol_rootP, & symbol_lastP);
1164 obj_symbol_new_hook (symbolP);
1166 #ifdef tc_symbol_new_hook
1167 tc_symbol_new_hook (symbolP);
1171 verify_symbol_chain (symbol_rootP, symbol_lastP);
1172 #endif /* DEBUG_SYMS */
1175 /* Check that an immediate is valid.
1176 If so, convert it to the right format. */
1179 validate_immediate (unsigned int val)
1184 #define rotate_left(v, n) (v << n | v >> (32 - n))
1186 for (i = 0; i < 32; i += 2)
1187 if ((a = rotate_left (val, i)) <= 0xff)
1188 return a | (i << 7); /* 12-bit pack: [shift-cnt,const]. */
1193 /* Check to see if an immediate can be computed as two separate immediate
1194 values, added together. We already know that this value cannot be
1195 computed by just one ARM instruction. */
1198 validate_immediate_twopart (unsigned int val,
1199 unsigned int * highpart)
1204 for (i = 0; i < 32; i += 2)
1205 if (((a = rotate_left (val, i)) & 0xff) != 0)
1211 * highpart = (a >> 8) | ((i + 24) << 7);
1213 else if (a & 0xff0000)
1217 * highpart = (a >> 16) | ((i + 16) << 7);
1221 assert (a & 0xff000000);
1222 * highpart = (a >> 24) | ((i + 8) << 7);
1225 return (a & 0xff) | (i << 7);
1232 validate_offset_imm (unsigned int val, int hwse)
1234 if ((hwse && val > 255) || val > 4095)
1241 /* This code is to handle mapping symbols as defined in the ARM ELF spec.
1242 (See "Mapping symbols", section 4.5.5, ARM AAELF version 1.0).
1243 Note that previously, $a and $t has type STT_FUNC (BSF_OBJECT flag),
1244 and $d has type STT_OBJECT (BSF_OBJECT flag). Now all three are untyped. */
1246 static enum mstate mapstate = MAP_UNDEFINED;
1249 mapping_state (enum mstate state)
1252 const char * symname;
1255 if (mapstate == state)
1256 /* The mapping symbol has already been emitted.
1257 There is nothing else to do. */
1266 type = BSF_NO_FLAGS;
1270 type = BSF_NO_FLAGS;
1274 type = BSF_NO_FLAGS;
1282 seg_info (now_seg)->tc_segment_info_data.mapstate = state;
1284 symbolP = symbol_new (symname, now_seg, (valueT) frag_now_fix (), frag_now);
1285 symbol_table_insert (symbolP);
1286 symbol_get_bfdsym (symbolP)->flags |= type | BSF_LOCAL;
1291 THUMB_SET_FUNC (symbolP, 0);
1292 ARM_SET_THUMB (symbolP, 0);
1293 ARM_SET_INTERWORK (symbolP, support_interwork);
1297 THUMB_SET_FUNC (symbolP, 1);
1298 ARM_SET_THUMB (symbolP, 1);
1299 ARM_SET_INTERWORK (symbolP, support_interwork);
1308 /* When we change sections we need to issue a new mapping symbol. */
1311 arm_elf_change_section (void)
1314 segment_info_type *seginfo;
1316 /* Link an unlinked unwind index table section to the .text section. */
1317 if (elf_section_type (now_seg) == SHT_ARM_EXIDX
1318 && elf_linked_to_section (now_seg) == NULL)
1319 elf_linked_to_section (now_seg) = text_section;
1321 if (!SEG_NORMAL (now_seg))
1324 flags = bfd_get_section_flags (stdoutput, now_seg);
1326 /* We can ignore sections that only contain debug info. */
1327 if ((flags & SEC_ALLOC) == 0)
1330 seginfo = seg_info (now_seg);
1331 mapstate = seginfo->tc_segment_info_data.mapstate;
1332 marked_pr_dependency = seginfo->tc_segment_info_data.marked_pr_dependency;
1336 arm_elf_section_type (const char * str, size_t len)
1338 if (len == 5 && strncmp (str, "exidx", 5) == 0)
1339 return SHT_ARM_EXIDX;
1344 #define mapping_state(a)
1345 #endif /* OBJ_ELF */
1347 /* arm_reg_parse () := if it looks like a register, return its token and
1348 advance the pointer. */
1351 arm_reg_parse (char ** ccp, struct hash_control * htab)
1353 char * start = * ccp;
1356 struct reg_entry * reg;
1358 #ifdef REGISTER_PREFIX
1359 if (*start != REGISTER_PREFIX)
1364 #ifdef OPTIONAL_REGISTER_PREFIX
1365 if (*p == OPTIONAL_REGISTER_PREFIX)
1369 if (!ISALPHA (*p) || !is_name_beginner (*p))
1373 while (ISALPHA (c) || ISDIGIT (c) || c == '_')
1377 reg = (struct reg_entry *) hash_find (htab, start);
1389 /* Search for the following register name in each of the possible reg name
1390 tables. Return the classification if found, or REG_TYPE_MAX if not
1393 static enum arm_reg_type
1394 arm_reg_parse_any (char *cp)
1398 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
1399 if (arm_reg_parse (&cp, all_reg_maps[i].htab) != FAIL)
1400 return (enum arm_reg_type) i;
1402 return REG_TYPE_MAX;
1406 opcode_select (int width)
1413 if (! (cpu_variant & ARM_EXT_V4T))
1414 as_bad (_("selected processor does not support THUMB opcodes"));
1417 /* No need to force the alignment, since we will have been
1418 coming from ARM mode, which is word-aligned. */
1419 record_alignment (now_seg, 1);
1421 mapping_state (MAP_THUMB);
1427 if ((cpu_variant & ARM_ALL) == ARM_EXT_V4T)
1428 as_bad (_("selected processor does not support ARM opcodes"));
1433 frag_align (2, 0, 0);
1435 record_alignment (now_seg, 1);
1437 mapping_state (MAP_ARM);
1441 as_bad (_("invalid instruction size selected (%d)"), width);
1446 s_req (int a ATTRIBUTE_UNUSED)
1448 as_bad (_("invalid syntax for .req directive"));
1451 /* The .unreq directive deletes an alias which was previously defined
1452 by .req. For example:
1458 s_unreq (int a ATTRIBUTE_UNUSED)
1463 skip_whitespace (input_line_pointer);
1464 name = input_line_pointer;
1466 while (*input_line_pointer != 0
1467 && *input_line_pointer != ' '
1468 && *input_line_pointer != '\n')
1469 ++input_line_pointer;
1471 saved_char = *input_line_pointer;
1472 *input_line_pointer = 0;
1476 enum arm_reg_type req_type = arm_reg_parse_any (name);
1478 if (req_type != REG_TYPE_MAX)
1480 char *temp_name = name;
1481 int req_no = arm_reg_parse (&temp_name, all_reg_maps[req_type].htab);
1485 struct reg_entry *req_entry;
1487 /* Check to see if this alias is a builtin one. */
1488 req_entry = hash_delete (all_reg_maps[req_type].htab, name);
1491 as_bad (_("unreq: missing hash entry for \"%s\""), name);
1492 else if (req_entry->builtin)
1493 /* FIXME: We are deleting a built in register alias which
1494 points to a const data structure, so we only need to
1495 free up the memory used by the key in the hash table.
1496 Unfortunately we have not recorded this value, so this
1497 is a memory leak. */
1498 /* FIXME: Should we issue a warning message ? */
1502 /* Deleting a user defined alias. We need to free the
1503 key and the value, but fortunately the key is the same
1504 as the value->name field. */
1505 free ((char *) req_entry->name);
1510 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
1513 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
1516 as_bad (_("invalid syntax for .unreq directive"));
1518 *input_line_pointer = saved_char;
1519 demand_empty_rest_of_line ();
1523 s_bss (int ignore ATTRIBUTE_UNUSED)
1525 /* We don't support putting frags in the BSS segment, we fake it by
1526 marking in_bss, then looking at s_skip for clues. */
1527 subseg_set (bss_section, 0);
1528 demand_empty_rest_of_line ();
1529 mapping_state (MAP_DATA);
1533 s_even (int ignore ATTRIBUTE_UNUSED)
1535 /* Never make frag if expect extra pass. */
1537 frag_align (1, 0, 0);
1539 record_alignment (now_seg, 1);
1541 demand_empty_rest_of_line ();
1545 s_ltorg (int ignored ATTRIBUTE_UNUSED)
1548 literal_pool * pool;
1551 pool = find_literal_pool ();
1553 || pool->symbol == NULL
1554 || pool->next_free_entry == 0)
1557 mapping_state (MAP_DATA);
1559 /* Align pool as you have word accesses.
1560 Only make a frag if we have to. */
1562 frag_align (2, 0, 0);
1564 record_alignment (now_seg, 2);
1566 sprintf (sym_name, "$$lit_\002%x", pool->id);
1568 symbol_locate (pool->symbol, sym_name, now_seg,
1569 (valueT) frag_now_fix (), frag_now);
1570 symbol_table_insert (pool->symbol);
1572 ARM_SET_THUMB (pool->symbol, thumb_mode);
1574 #if defined OBJ_COFF || defined OBJ_ELF
1575 ARM_SET_INTERWORK (pool->symbol, support_interwork);
1578 for (entry = 0; entry < pool->next_free_entry; entry ++)
1579 /* First output the expression in the instruction to the pool. */
1580 emit_expr (&(pool->literals[entry]), 4); /* .word */
1582 /* Mark the pool as empty. */
1583 pool->next_free_entry = 0;
1584 pool->symbol = NULL;
1587 /* Same as s_align_ptwo but align 0 => align 2. */
1590 s_align (int unused ATTRIBUTE_UNUSED)
1594 long max_alignment = 15;
1596 temp = get_absolute_expression ();
1597 if (temp > max_alignment)
1598 as_bad (_("alignment too large: %d assumed"), temp = max_alignment);
1601 as_bad (_("alignment negative. 0 assumed."));
1605 if (*input_line_pointer == ',')
1607 input_line_pointer++;
1608 temp_fill = get_absolute_expression ();
1616 /* Only make a frag if we HAVE to. */
1617 if (temp && !need_pass_2)
1618 frag_align (temp, (int) temp_fill, 0);
1619 demand_empty_rest_of_line ();
1621 record_alignment (now_seg, temp);
1625 s_force_thumb (int ignore ATTRIBUTE_UNUSED)
1627 /* If we are not already in thumb mode go into it, EVEN if
1628 the target processor does not support thumb instructions.
1629 This is used by gcc/config/arm/lib1funcs.asm for example
1630 to compile interworking support functions even if the
1631 target processor should not support interworking. */
1636 record_alignment (now_seg, 1);
1639 demand_empty_rest_of_line ();
1643 s_thumb_func (int ignore ATTRIBUTE_UNUSED)
1648 /* The following label is the name/address of the start of a Thumb function.
1649 We need to know this for the interworking support. */
1650 label_is_thumb_function_name = TRUE;
1652 demand_empty_rest_of_line ();
1655 /* Perform a .set directive, but also mark the alias as
1656 being a thumb function. */
1659 s_thumb_set (int equiv)
1661 /* XXX the following is a duplicate of the code for s_set() in read.c
1662 We cannot just call that code as we need to get at the symbol that
1669 /* Especial apologies for the random logic:
1670 This just grew, and could be parsed much more simply!
1672 name = input_line_pointer;
1673 delim = get_symbol_end ();
1674 end_name = input_line_pointer;
1679 if (*input_line_pointer != ',')
1682 as_bad (_("expected comma after name \"%s\""), name);
1684 ignore_rest_of_line ();
1688 input_line_pointer++;
1691 if (name[0] == '.' && name[1] == '\0')
1693 /* XXX - this should not happen to .thumb_set. */
1697 if ((symbolP = symbol_find (name)) == NULL
1698 && (symbolP = md_undefined_symbol (name)) == NULL)
1701 /* When doing symbol listings, play games with dummy fragments living
1702 outside the normal fragment chain to record the file and line info
1704 if (listing & LISTING_SYMBOLS)
1706 extern struct list_info_struct * listing_tail;
1707 fragS * dummy_frag = xmalloc (sizeof (fragS));
1709 memset (dummy_frag, 0, sizeof (fragS));
1710 dummy_frag->fr_type = rs_fill;
1711 dummy_frag->line = listing_tail;
1712 symbolP = symbol_new (name, undefined_section, 0, dummy_frag);
1713 dummy_frag->fr_symbol = symbolP;
1717 symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
1720 /* "set" symbols are local unless otherwise specified. */
1721 SF_SET_LOCAL (symbolP);
1722 #endif /* OBJ_COFF */
1723 } /* Make a new symbol. */
1725 symbol_table_insert (symbolP);
1730 && S_IS_DEFINED (symbolP)
1731 && S_GET_SEGMENT (symbolP) != reg_section)
1732 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP));
1734 pseudo_set (symbolP);
1736 demand_empty_rest_of_line ();
1738 /* XXX Now we come to the Thumb specific bit of code. */
1740 THUMB_SET_FUNC (symbolP, 1);
1741 ARM_SET_THUMB (symbolP, 1);
1742 #if defined OBJ_ELF || defined OBJ_COFF
1743 ARM_SET_INTERWORK (symbolP, support_interwork);
1748 s_arm (int ignore ATTRIBUTE_UNUSED)
1751 demand_empty_rest_of_line ();
1755 s_thumb (int ignore ATTRIBUTE_UNUSED)
1758 demand_empty_rest_of_line ();
1762 s_code (int unused ATTRIBUTE_UNUSED)
1766 temp = get_absolute_expression ();
1771 opcode_select (temp);
1775 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp);
1780 end_of_line (char * str)
1782 skip_whitespace (str);
1784 if (*str != '\0' && !inst.error)
1785 inst.error = _("garbage following instruction");
1789 skip_past_comma (char ** str)
1791 char * p = * str, c;
1794 while ((c = *p) == ' ' || c == ',')
1797 if (c == ',' && comma++)
1805 return comma ? SUCCESS : FAIL;
1808 /* Return TRUE if anything in the expression is a bignum. */
1811 walk_no_bignums (symbolS * sp)
1813 if (symbol_get_value_expression (sp)->X_op == O_big)
1816 if (symbol_get_value_expression (sp)->X_add_symbol)
1818 return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
1819 || (symbol_get_value_expression (sp)->X_op_symbol
1820 && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
1826 static int in_my_get_expression = 0;
1829 my_get_expression (expressionS * ep, char ** str)
1834 save_in = input_line_pointer;
1835 input_line_pointer = *str;
1836 in_my_get_expression = 1;
1837 seg = expression (ep);
1838 in_my_get_expression = 0;
1840 if (ep->X_op == O_illegal)
1842 /* We found a bad expression in md_operand(). */
1843 *str = input_line_pointer;
1844 input_line_pointer = save_in;
1849 if (seg != absolute_section
1850 && seg != text_section
1851 && seg != data_section
1852 && seg != bss_section
1853 && seg != undefined_section)
1855 inst.error = _("bad_segment");
1856 *str = input_line_pointer;
1857 input_line_pointer = save_in;
1862 /* Get rid of any bignums now, so that we don't generate an error for which
1863 we can't establish a line number later on. Big numbers are never valid
1864 in instructions, which is where this routine is always called. */
1865 if (ep->X_op == O_big
1866 || (ep->X_add_symbol
1867 && (walk_no_bignums (ep->X_add_symbol)
1869 && walk_no_bignums (ep->X_op_symbol)))))
1871 inst.error = _("invalid constant");
1872 *str = input_line_pointer;
1873 input_line_pointer = save_in;
1877 *str = input_line_pointer;
1878 input_line_pointer = save_in;
1882 /* A standard register must be given at this point.
1883 SHIFT is the place to put it in inst.instruction.
1884 Restores input start point on error.
1885 Returns the reg#, or FAIL. */
1888 reg_required_here (char ** str, int shift)
1890 static char buff [128]; /* XXX */
1892 char * start = * str;
1894 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_RN].htab)) != FAIL)
1897 inst.instruction |= reg << shift;
1901 /* Restore the start point, we may have got a reg of the wrong class. */
1904 /* In the few cases where we might be able to accept something else
1905 this error can be overridden. */
1906 sprintf (buff, _("register expected, not '%.100s'"), start);
1912 /* A Intel Wireless MMX technology register
1913 must be given at this point.
1914 Shift is the place to put it in inst.instruction.
1915 Restores input start point on err.
1916 Returns the reg#, or FAIL. */
1919 wreg_required_here (char ** str,
1921 enum wreg_type reg_type)
1923 static char buff [128];
1925 char * start = *str;
1927 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_IWMMXT].htab)) != FAIL)
1929 if (wr_register (reg)
1930 && (reg_type == IWMMXT_REG_WR || reg_type == IWMMXT_REG_WR_OR_WC))
1933 inst.instruction |= (reg ^ WR_PREFIX) << shift;
1936 else if (wc_register (reg)
1937 && (reg_type == IWMMXT_REG_WC || reg_type == IWMMXT_REG_WR_OR_WC))
1940 inst.instruction |= (reg ^ WC_PREFIX) << shift;
1943 else if ((wcg_register (reg) && reg_type == IWMMXT_REG_WCG))
1946 inst.instruction |= ((reg ^ WC_PREFIX) - 8) << shift;
1951 /* Restore the start point, we may have got a reg of the wrong class. */
1954 /* In the few cases where we might be able to accept
1955 something else this error can be overridden. */
1956 sprintf (buff, _("Intel Wireless MMX technology register expected, not '%.100s'"), start);
1962 static const struct asm_psr *
1963 arm_psr_parse (char ** ccp)
1965 char * start = * ccp;
1968 const struct asm_psr * psr;
1972 /* Skip to the end of the next word in the input stream. */
1977 while (ISALPHA (c) || c == '_');
1979 /* Terminate the word. */
1982 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
1983 feature for ease of use and backwards compatibility. */
1984 if (!strncmp (start, "cpsr", 4))
1985 strncpy (start, "CPSR", 4);
1986 else if (!strncmp (start, "spsr", 4))
1987 strncpy (start, "SPSR", 4);
1989 /* Now locate the word in the psr hash table. */
1990 psr = (const struct asm_psr *) hash_find (arm_psr_hsh, start);
1992 /* Restore the input stream. */
1995 /* If we found a valid match, advance the
1996 stream pointer past the end of the word. */
2002 /* Parse the input looking for a PSR flag. */
2005 psr_required_here (char ** str)
2007 char * start = * str;
2008 const struct asm_psr * psr;
2010 psr = arm_psr_parse (str);
2014 /* If this is the SPSR that is being modified, set the R bit. */
2016 inst.instruction |= SPSR_BIT;
2018 /* Set the psr flags in the MSR instruction. */
2019 inst.instruction |= psr->field << PSR_SHIFT;
2024 /* In the few cases where we might be able to accept
2025 something else this error can be overridden. */
2026 inst.error = _("flag for {c}psr instruction expected");
2028 /* Restore the start point. */
2034 co_proc_number (char ** str)
2036 int processor, pchar;
2039 skip_whitespace (*str);
2042 /* The data sheet seems to imply that just a number on its own is valid
2043 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
2045 if ((processor = arm_reg_parse (str, all_reg_maps[REG_TYPE_CP].htab))
2051 if (pchar >= '0' && pchar <= '9')
2053 processor = pchar - '0';
2054 if (**str >= '0' && **str <= '9')
2056 processor = processor * 10 + *(*str)++ - '0';
2059 inst.error = _("illegal co-processor number");
2066 inst.error = all_reg_maps[REG_TYPE_CP].expected;
2071 inst.instruction |= processor << 8;
2076 cp_opc_expr (char ** str, int where, int length)
2080 skip_whitespace (* str);
2082 memset (&expr, '\0', sizeof (expr));
2084 if (my_get_expression (&expr, str))
2086 if (expr.X_op != O_constant)
2088 inst.error = _("bad or missing expression");
2092 if ((expr.X_add_number & ((1 << length) - 1)) != expr.X_add_number)
2094 inst.error = _("immediate co-processor expression too large");
2098 inst.instruction |= expr.X_add_number << where;
2103 cp_reg_required_here (char ** str, int where)
2106 char * start = *str;
2108 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
2110 inst.instruction |= reg << where;
2114 /* In the few cases where we might be able to accept something else
2115 this error can be overridden. */
2116 inst.error = all_reg_maps[REG_TYPE_CN].expected;
2118 /* Restore the start point. */
2124 fp_reg_required_here (char ** str, int where)
2127 char * start = * str;
2129 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_FN].htab)) != FAIL)
2131 inst.instruction |= reg << where;
2135 /* In the few cases where we might be able to accept something else
2136 this error can be overridden. */
2137 inst.error = all_reg_maps[REG_TYPE_FN].expected;
2139 /* Restore the start point. */
2145 cp_address_offset (char ** str)
2149 skip_whitespace (* str);
2151 if (! is_immediate_prefix (**str))
2153 inst.error = _("immediate expression expected");
2159 if (my_get_expression (& inst.reloc.exp, str))
2162 if (inst.reloc.exp.X_op == O_constant)
2164 offset = inst.reloc.exp.X_add_number;
2168 inst.error = _("co-processor address must be word aligned");
2172 if (offset > 1023 || offset < -1023)
2174 inst.error = _("offset too large");
2179 inst.instruction |= INDEX_UP;
2183 inst.instruction |= offset >> 2;
2186 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
2192 cp_address_required_here (char ** str, int wb_ok)
2203 skip_whitespace (p);
2205 if ((reg = reg_required_here (& p, 16)) == FAIL)
2208 skip_whitespace (p);
2214 skip_whitespace (p);
2218 /* As an extension to the official ARM syntax we allow:
2220 as a short hand for:
2222 inst.instruction |= PRE_INDEX | INDEX_UP;
2227 if (skip_past_comma (& p) == FAIL)
2229 inst.error = _("comma expected after closing square bracket");
2233 skip_whitespace (p);
2240 write_back = WRITE_BACK;
2244 inst.error = _("pc may not be used in post-increment");
2248 if (cp_address_offset (& p) == FAIL)
2252 pre_inc = PRE_INDEX | INDEX_UP;
2258 /* [Rn], {<expr>} */
2261 skip_whitespace (p);
2263 if (my_get_expression (& inst.reloc.exp, & p))
2266 if (inst.reloc.exp.X_op == O_constant)
2268 option = inst.reloc.exp.X_add_number;
2270 if (option > 255 || option < 0)
2272 inst.error = _("'option' field too large");
2276 skip_whitespace (p);
2280 inst.error = _("'}' expected at end of 'option' field");
2286 inst.instruction |= option;
2287 inst.instruction |= INDEX_UP;
2292 inst.error = _("non-constant expressions for 'option' field not supported");
2298 inst.error = _("# or { expected after comma");
2304 /* '['Rn, #expr']'[!] */
2306 if (skip_past_comma (& p) == FAIL)
2308 inst.error = _("pre-indexed expression expected");
2312 pre_inc = PRE_INDEX;
2314 if (cp_address_offset (& p) == FAIL)
2317 skip_whitespace (p);
2321 inst.error = _("missing ]");
2325 skip_whitespace (p);
2327 if (wb_ok && *p == '!')
2331 inst.error = _("pc may not be used with write-back");
2336 write_back = WRITE_BACK;
2342 if (my_get_expression (&inst.reloc.exp, &p))
2345 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
2346 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
2347 inst.reloc.pc_rel = 1;
2348 inst.instruction |= (REG_PC << 16);
2349 pre_inc = PRE_INDEX;
2352 inst.instruction |= write_back | pre_inc;
2358 cp_byte_address_offset (char ** str)
2362 skip_whitespace (* str);
2364 if (! is_immediate_prefix (**str))
2366 inst.error = _("immediate expression expected");
2372 if (my_get_expression (& inst.reloc.exp, str))
2375 if (inst.reloc.exp.X_op == O_constant)
2377 offset = inst.reloc.exp.X_add_number;
2379 if (offset > 255 || offset < -255)
2381 inst.error = _("offset too large");
2386 inst.instruction |= INDEX_UP;
2390 inst.instruction |= offset;
2393 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
2399 cp_byte_address_required_here (char ** str)
2410 skip_whitespace (p);
2412 if ((reg = reg_required_here (& p, 16)) == FAIL)
2415 skip_whitespace (p);
2421 if (skip_past_comma (& p) == SUCCESS)
2424 write_back = WRITE_BACK;
2428 inst.error = _("pc may not be used in post-increment");
2432 if (cp_byte_address_offset (& p) == FAIL)
2436 pre_inc = PRE_INDEX | INDEX_UP;
2440 /* '['Rn, #expr']'[!] */
2442 if (skip_past_comma (& p) == FAIL)
2444 inst.error = _("pre-indexed expression expected");
2448 pre_inc = PRE_INDEX;
2450 if (cp_byte_address_offset (& p) == FAIL)
2453 skip_whitespace (p);
2457 inst.error = _("missing ]");
2461 skip_whitespace (p);
2467 inst.error = _("pc may not be used with write-back");
2472 write_back = WRITE_BACK;
2478 if (my_get_expression (&inst.reloc.exp, &p))
2481 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
2482 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
2483 inst.reloc.pc_rel = 1;
2484 inst.instruction |= (REG_PC << 16);
2485 pre_inc = PRE_INDEX;
2488 inst.instruction |= write_back | pre_inc;
2496 skip_whitespace (str);
2501 if (my_get_expression (&inst.reloc.exp, &str))
2502 inst.reloc.exp.X_op = O_illegal;
2505 skip_whitespace (str);
2509 inst.reloc.exp.X_op = O_illegal;
2512 if (inst.reloc.exp.X_op != O_constant
2513 || inst.reloc.exp.X_add_number > 255
2514 || inst.reloc.exp.X_add_number < 0)
2516 inst.error = _("Invalid NOP hint");
2520 /* Arcitectural NOP hints are CPSR sets with no bits selected. */
2521 inst.instruction &= 0xf0000000;
2522 inst.instruction |= 0x0320f000 + inst.reloc.exp.X_add_number;
2529 do_empty (char * str)
2531 /* Do nothing really. */
2540 /* Only one syntax. */
2541 skip_whitespace (str);
2543 if (reg_required_here (&str, 12) == FAIL)
2545 inst.error = BAD_ARGS;
2549 if (skip_past_comma (&str) == FAIL)
2551 inst.error = _("comma expected after register name");
2555 skip_whitespace (str);
2557 if ( streq (str, "CPSR")
2558 || streq (str, "SPSR")
2559 /* Lower case versions for backwards compatibility. */
2560 || streq (str, "cpsr")
2561 || streq (str, "spsr"))
2564 /* This is for backwards compatibility with older toolchains. */
2565 else if ( streq (str, "cpsr_all")
2566 || streq (str, "spsr_all"))
2570 inst.error = _("CPSR or SPSR expected");
2574 if (* str == 's' || * str == 'S')
2575 inst.instruction |= SPSR_BIT;
2581 /* Two possible forms:
2582 "{C|S}PSR_<field>, Rm",
2583 "{C|S}PSR_f, #expression". */
2588 skip_whitespace (str);
2590 if (psr_required_here (& str) == FAIL)
2593 if (skip_past_comma (& str) == FAIL)
2595 inst.error = _("comma missing after psr flags");
2599 skip_whitespace (str);
2601 if (reg_required_here (& str, 0) != FAIL)
2608 if (! is_immediate_prefix (* str))
2611 _("only a register or immediate value can follow a psr flag");
2618 if (my_get_expression (& inst.reloc.exp, & str))
2621 _("only a register or immediate value can follow a psr flag");
2625 inst.instruction |= INST_IMMEDIATE;
2627 if (inst.reloc.exp.X_add_symbol)
2629 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
2630 inst.reloc.pc_rel = 0;
2634 unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
2636 if (value == (unsigned) FAIL)
2638 inst.error = _("invalid constant");
2642 inst.instruction |= value;
2649 /* Long Multiply Parser
2650 UMULL RdLo, RdHi, Rm, Rs
2651 SMULL RdLo, RdHi, Rm, Rs
2652 UMLAL RdLo, RdHi, Rm, Rs
2653 SMLAL RdLo, RdHi, Rm, Rs. */
2656 do_mull (char * str)
2658 int rdlo, rdhi, rm, rs;
2660 /* Only one format "rdlo, rdhi, rm, rs". */
2661 skip_whitespace (str);
2663 if ((rdlo = reg_required_here (&str, 12)) == FAIL)
2665 inst.error = BAD_ARGS;
2669 if (skip_past_comma (&str) == FAIL
2670 || (rdhi = reg_required_here (&str, 16)) == FAIL)
2672 inst.error = BAD_ARGS;
2676 if (skip_past_comma (&str) == FAIL
2677 || (rm = reg_required_here (&str, 0)) == FAIL)
2679 inst.error = BAD_ARGS;
2683 /* rdhi, rdlo and rm must all be different. */
2684 if (rdlo == rdhi || rdlo == rm || rdhi == rm)
2685 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
2687 if (skip_past_comma (&str) == FAIL
2688 || (rs = reg_required_here (&str, 8)) == FAIL)
2690 inst.error = BAD_ARGS;
2694 if (rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC)
2696 inst.error = BAD_PC;
2708 /* Only one format "rd, rm, rs". */
2709 skip_whitespace (str);
2711 if ((rd = reg_required_here (&str, 16)) == FAIL)
2713 inst.error = BAD_ARGS;
2719 inst.error = BAD_PC;
2723 if (skip_past_comma (&str) == FAIL
2724 || (rm = reg_required_here (&str, 0)) == FAIL)
2726 inst.error = BAD_ARGS;
2732 inst.error = BAD_PC;
2737 as_tsktsk (_("rd and rm should be different in mul"));
2739 if (skip_past_comma (&str) == FAIL
2740 || (rm = reg_required_here (&str, 8)) == FAIL)
2742 inst.error = BAD_ARGS;
2748 inst.error = BAD_PC;
2756 do_mlas (char * str, bfd_boolean is_mls)
2760 /* Only one format "rd, rm, rs, rn". */
2761 skip_whitespace (str);
2763 if ((rd = reg_required_here (&str, 16)) == FAIL)
2765 inst.error = BAD_ARGS;
2771 inst.error = BAD_PC;
2775 if (skip_past_comma (&str) == FAIL
2776 || (rm = reg_required_here (&str, 0)) == FAIL)
2778 inst.error = BAD_ARGS;
2784 inst.error = BAD_PC;
2788 /* This restriction does not apply to mls (nor to mla in v6, but
2789 that's hard to detect at present). */
2790 if (rm == rd && !is_mls)
2791 as_tsktsk (_("rd and rm should be different in mla"));
2793 if (skip_past_comma (&str) == FAIL
2794 || (rd = reg_required_here (&str, 8)) == FAIL
2795 || skip_past_comma (&str) == FAIL
2796 || (rm = reg_required_here (&str, 12)) == FAIL)
2798 inst.error = BAD_ARGS;
2802 if (rd == REG_PC || rm == REG_PC)
2804 inst.error = BAD_PC;
2814 do_mlas (str, FALSE);
2820 do_mlas (str, TRUE);
2823 /* Expects *str -> the characters "acc0", possibly with leading blanks.
2824 Advances *str to the next non-alphanumeric.
2825 Returns 0, or else FAIL (in which case sets inst.error).
2827 (In a future XScale, there may be accumulators other than zero.
2828 At that time this routine and its callers can be upgraded to suit.) */
2831 accum0_required_here (char ** str)
2833 static char buff [128]; /* Note the address is taken. Hence, static. */
2836 int result = 0; /* The accum number. */
2838 skip_whitespace (p);
2840 *str = p; /* Advance caller's string pointer too. */
2845 *--p = 0; /* Aap nul into input buffer at non-alnum. */
2847 if (! ( streq (*str, "acc0") || streq (*str, "ACC0")))
2849 sprintf (buff, _("acc0 expected, not '%.100s'"), *str);
2854 *p = c; /* Unzap. */
2855 *str = p; /* Caller's string pointer to after match. */
2860 ldst_extend_v4 (char ** str)
2869 if (my_get_expression (& inst.reloc.exp, str))
2872 if (inst.reloc.exp.X_op == O_constant)
2874 int value = inst.reloc.exp.X_add_number;
2876 if (value < -255 || value > 255)
2878 inst.error = _("address offset too large");
2888 /* Halfword and signextension instructions have the
2889 immediate value split across bits 11..8 and bits 3..0. */
2890 inst.instruction |= (add | HWOFFSET_IMM
2891 | ((value >> 4) << 8) | (value & 0xF));
2895 inst.instruction |= HWOFFSET_IMM;
2896 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
2897 inst.reloc.pc_rel = 0;
2910 if (reg_required_here (str, 0) == FAIL)
2913 inst.instruction |= add;
2918 /* Expects **str -> after a comma. May be leading blanks.
2919 Advances *str, recognizing a load mode, and setting inst.instruction.
2920 Returns rn, or else FAIL (in which case may set inst.error
2921 and not advance str)
2923 Note: doesn't know Rd, so no err checks that require such knowledge. */
2926 ld_mode_required_here (char ** string)
2928 char * str = * string;
2932 skip_whitespace (str);
2938 skip_whitespace (str);
2940 if ((rn = reg_required_here (& str, 16)) == FAIL)
2943 skip_whitespace (str);
2949 if (skip_past_comma (& str) == SUCCESS)
2951 /* [Rn],... (post inc) */
2952 if (ldst_extend_v4 (&str) == FAIL)
2957 skip_whitespace (str);
2962 inst.instruction |= WRITE_BACK;
2965 inst.instruction |= INDEX_UP | HWOFFSET_IMM;
2971 if (skip_past_comma (& str) == FAIL)
2973 inst.error = _("pre-indexed expression expected");
2979 if (ldst_extend_v4 (&str) == FAIL)
2982 skip_whitespace (str);
2984 if (* str ++ != ']')
2986 inst.error = _("missing ]");
2990 skip_whitespace (str);
2995 inst.instruction |= WRITE_BACK;
2999 else if (* str == '=') /* ldr's "r,=label" syntax */
3000 /* We should never reach here, because <text> = <expression> is
3001 caught gas/read.c read_a_source_file() as a .set operation. */
3003 else /* PC +- 8 bit immediate offset. */
3005 if (my_get_expression (& inst.reloc.exp, & str))
3008 inst.instruction |= HWOFFSET_IMM; /* The I bit. */
3009 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
3010 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
3011 inst.reloc.pc_rel = 1;
3012 inst.instruction |= (REG_PC << 16);
3018 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
3024 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
3025 SMLAxy{cond} Rd,Rm,Rs,Rn
3026 SMLAWy{cond} Rd,Rm,Rs,Rn
3027 Error if any register is R15. */
3030 do_smla (char * str)
3034 skip_whitespace (str);
3036 if ((rd = reg_required_here (& str, 16)) == FAIL
3037 || skip_past_comma (& str) == FAIL
3038 || (rm = reg_required_here (& str, 0)) == FAIL
3039 || skip_past_comma (& str) == FAIL
3040 || (rs = reg_required_here (& str, 8)) == FAIL
3041 || skip_past_comma (& str) == FAIL
3042 || (rn = reg_required_here (& str, 12)) == FAIL)
3043 inst.error = BAD_ARGS;
3045 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC || rn == REG_PC)
3046 inst.error = BAD_PC;
3052 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
3053 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
3054 Error if any register is R15.
3055 Warning if Rdlo == Rdhi. */
3058 do_smlal (char * str)
3060 int rdlo, rdhi, rm, rs;
3062 skip_whitespace (str);
3064 if ((rdlo = reg_required_here (& str, 12)) == FAIL
3065 || skip_past_comma (& str) == FAIL
3066 || (rdhi = reg_required_here (& str, 16)) == FAIL
3067 || skip_past_comma (& str) == FAIL
3068 || (rm = reg_required_here (& str, 0)) == FAIL
3069 || skip_past_comma (& str) == FAIL
3070 || (rs = reg_required_here (& str, 8)) == FAIL)
3072 inst.error = BAD_ARGS;
3076 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
3078 inst.error = BAD_PC;
3083 as_tsktsk (_("rdhi and rdlo must be different"));
3088 /* ARM V5E (El Segundo) signed-multiply (argument parse)
3089 SMULxy{cond} Rd,Rm,Rs
3090 Error if any register is R15. */
3093 do_smul (char * str)
3097 skip_whitespace (str);
3099 if ((rd = reg_required_here (& str, 16)) == FAIL
3100 || skip_past_comma (& str) == FAIL
3101 || (rm = reg_required_here (& str, 0)) == FAIL
3102 || skip_past_comma (& str) == FAIL
3103 || (rs = reg_required_here (& str, 8)) == FAIL)
3104 inst.error = BAD_ARGS;
3106 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC)
3107 inst.error = BAD_PC;
3113 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
3114 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
3115 Error if any register is R15. */
3118 do_qadd (char * str)
3122 skip_whitespace (str);
3124 if ((rd = reg_required_here (& str, 12)) == FAIL
3125 || skip_past_comma (& str) == FAIL
3126 || (rm = reg_required_here (& str, 0)) == FAIL
3127 || skip_past_comma (& str) == FAIL
3128 || (rn = reg_required_here (& str, 16)) == FAIL)
3129 inst.error = BAD_ARGS;
3131 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
3132 inst.error = BAD_PC;
3138 /* ARM V5E (el Segundo)
3139 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3140 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3142 These are equivalent to the XScale instructions MAR and MRA,
3143 respectively, when coproc == 0, opcode == 0, and CRm == 0.
3145 Result unpredicatable if Rd or Rn is R15. */
3148 do_co_reg2c (char * str)
3152 skip_whitespace (str);
3154 if (co_proc_number (& str) == FAIL)
3157 inst.error = BAD_ARGS;
3161 if (skip_past_comma (& str) == FAIL
3162 || cp_opc_expr (& str, 4, 4) == FAIL)
3165 inst.error = BAD_ARGS;
3169 if (skip_past_comma (& str) == FAIL
3170 || (rd = reg_required_here (& str, 12)) == FAIL)
3173 inst.error = BAD_ARGS;
3177 if (skip_past_comma (& str) == FAIL
3178 || (rn = reg_required_here (& str, 16)) == FAIL)
3181 inst.error = BAD_ARGS;
3185 /* Unpredictable result if rd or rn is R15. */
3186 if (rd == REG_PC || rn == REG_PC)
3188 (_("Warning: instruction unpredictable when using r15"));
3190 if (skip_past_comma (& str) == FAIL
3191 || cp_reg_required_here (& str, 0) == FAIL)
3194 inst.error = BAD_ARGS;
3201 /* ARM V5 count-leading-zeroes instruction (argument parse)
3202 CLZ{<cond>} <Rd>, <Rm>
3203 Condition defaults to COND_ALWAYS.
3204 Error if Rd or Rm are R15. */
3211 skip_whitespace (str);
3213 if (((rd = reg_required_here (& str, 12)) == FAIL)
3214 || (skip_past_comma (& str) == FAIL)
3215 || ((rm = reg_required_here (& str, 0)) == FAIL))
3216 inst.error = BAD_ARGS;
3218 else if (rd == REG_PC || rm == REG_PC )
3219 inst.error = BAD_PC;
3225 /* ARM V5 (argument parse)
3226 LDC2{L} <coproc>, <CRd>, <addressing mode>
3227 STC2{L} <coproc>, <CRd>, <addressing mode>
3228 Instruction is not conditional, and has 0xf in the condition field.
3229 Otherwise, it's the same as LDC/STC. */
3232 do_lstc2 (char * str)
3234 skip_whitespace (str);
3236 if (co_proc_number (& str) == FAIL)
3239 inst.error = BAD_ARGS;
3241 else if (skip_past_comma (& str) == FAIL
3242 || cp_reg_required_here (& str, 12) == FAIL)
3245 inst.error = BAD_ARGS;
3247 else if (skip_past_comma (& str) == FAIL
3248 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
3251 inst.error = BAD_ARGS;
3257 /* ARM V5 (argument parse)
3258 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
3259 Instruction is not conditional, and has 0xf in the condition field.
3260 Otherwise, it's the same as CDP. */
3263 do_cdp2 (char * str)
3265 skip_whitespace (str);
3267 if (co_proc_number (& str) == FAIL)
3270 inst.error = BAD_ARGS;
3274 if (skip_past_comma (& str) == FAIL
3275 || cp_opc_expr (& str, 20,4) == FAIL)
3278 inst.error = BAD_ARGS;
3282 if (skip_past_comma (& str) == FAIL
3283 || cp_reg_required_here (& str, 12) == FAIL)
3286 inst.error = BAD_ARGS;
3290 if (skip_past_comma (& str) == FAIL
3291 || cp_reg_required_here (& str, 16) == FAIL)
3294 inst.error = BAD_ARGS;
3298 if (skip_past_comma (& str) == FAIL
3299 || cp_reg_required_here (& str, 0) == FAIL)
3302 inst.error = BAD_ARGS;
3306 if (skip_past_comma (& str) == SUCCESS)
3308 if (cp_opc_expr (& str, 5, 3) == FAIL)
3311 inst.error = BAD_ARGS;
3319 /* ARM V5 (argument parse)
3320 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3321 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3322 Instruction is not conditional, and has 0xf in the condition field.
3323 Otherwise, it's the same as MCR/MRC. */
3326 do_co_reg2 (char * str)
3328 skip_whitespace (str);
3330 if (co_proc_number (& str) == FAIL)
3333 inst.error = BAD_ARGS;
3337 if (skip_past_comma (& str) == FAIL
3338 || cp_opc_expr (& str, 21, 3) == FAIL)
3341 inst.error = BAD_ARGS;
3345 if (skip_past_comma (& str) == FAIL
3346 || reg_required_here (& str, 12) == FAIL)
3349 inst.error = BAD_ARGS;
3353 if (skip_past_comma (& str) == FAIL
3354 || cp_reg_required_here (& str, 16) == FAIL)
3357 inst.error = BAD_ARGS;
3361 if (skip_past_comma (& str) == FAIL
3362 || cp_reg_required_here (& str, 0) == FAIL)
3365 inst.error = BAD_ARGS;
3369 if (skip_past_comma (& str) == SUCCESS)
3371 if (cp_opc_expr (& str, 5, 3) == FAIL)
3374 inst.error = BAD_ARGS;
3387 skip_whitespace (str);
3389 if ((reg = reg_required_here (&str, 0)) == FAIL)
3391 inst.error = BAD_ARGS;
3395 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
3397 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
3402 /* ARM v5TEJ. Jump to Jazelle code. */
3409 skip_whitespace (str);
3411 if ((reg = reg_required_here (&str, 0)) == FAIL)
3413 inst.error = BAD_ARGS;
3417 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
3419 as_tsktsk (_("use of r15 in bxj is not really useful"));
3424 /* ARM V6 umaal (argument parse). */
3427 do_umaal (char * str)
3429 int rdlo, rdhi, rm, rs;
3431 skip_whitespace (str);
3432 if ((rdlo = reg_required_here (& str, 12)) == FAIL
3433 || skip_past_comma (& str) == FAIL
3434 || (rdhi = reg_required_here (& str, 16)) == FAIL
3435 || skip_past_comma (& str) == FAIL
3436 || (rm = reg_required_here (& str, 0)) == FAIL
3437 || skip_past_comma (& str) == FAIL
3438 || (rs = reg_required_here (& str, 8)) == FAIL)
3440 inst.error = BAD_ARGS;
3444 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
3446 inst.error = BAD_PC;
3453 /* ARM V6 strex (argument parse). */
3456 do_strex (char * str)
3460 /* Parse Rd, Rm,. */
3461 skip_whitespace (str);
3462 if ((rd = reg_required_here (& str, 12)) == FAIL
3463 || skip_past_comma (& str) == FAIL
3464 || (rm = reg_required_here (& str, 0)) == FAIL
3465 || skip_past_comma (& str) == FAIL)
3467 inst.error = BAD_ARGS;
3470 if (rd == REG_PC || rm == REG_PC)
3472 inst.error = BAD_PC;
3477 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
3481 /* Skip past '['. */
3482 if ((strlen (str) >= 1)
3483 && strncmp (str, "[", 1) == 0)
3486 skip_whitespace (str);
3489 if ((rn = reg_required_here (& str, 16)) == FAIL)
3491 inst.error = BAD_ARGS;
3494 else if (rn == REG_PC)
3496 inst.error = BAD_PC;
3501 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
3504 skip_whitespace (str);
3506 /* Skip past ']'. */
3507 if ((strlen (str) >= 1)
3508 && strncmp (str, "]", 1) == 0)
3514 /* KIND indicates what kind of shifts are accepted. */
3517 decode_shift (char ** str, int kind)
3519 const struct asm_shift_name * shift;
3523 skip_whitespace (* str);
3525 for (p = * str; ISALPHA (* p); p ++)
3530 inst.error = _("shift expression expected");
3536 shift = (const struct asm_shift_name *) hash_find (arm_shift_hsh, * str);
3541 inst.error = _("shift expression expected");
3545 assert (shift->properties->index == shift_properties[shift->properties->index].index);
3547 if (kind == SHIFT_LSL_OR_ASR_IMMEDIATE
3548 && shift->properties->index != SHIFT_LSL
3549 && shift->properties->index != SHIFT_ASR)
3551 inst.error = _("'LSL' or 'ASR' required");
3554 else if (kind == SHIFT_LSL_IMMEDIATE
3555 && shift->properties->index != SHIFT_LSL)
3557 inst.error = _("'LSL' required");
3560 else if (kind == SHIFT_ASR_IMMEDIATE
3561 && shift->properties->index != SHIFT_ASR)
3563 inst.error = _("'ASR' required");
3567 if (shift->properties->index == SHIFT_RRX)
3570 inst.instruction |= shift->properties->bit_field;
3574 skip_whitespace (p);
3576 if (kind == NO_SHIFT_RESTRICT && reg_required_here (& p, 8) != FAIL)
3578 inst.instruction |= shift->properties->bit_field | SHIFT_BY_REG;
3582 else if (! is_immediate_prefix (* p))
3584 inst.error = (NO_SHIFT_RESTRICT
3585 ? _("shift requires register or #expression")
3586 : _("shift requires #expression"));
3594 if (my_get_expression (& inst.reloc.exp, & p))
3597 /* Validate some simple #expressions. */
3598 if (inst.reloc.exp.X_op == O_constant)
3600 unsigned num = inst.reloc.exp.X_add_number;
3602 /* Reject operations greater than 32. */
3604 /* Reject a shift of 0 unless the mode allows it. */
3605 || (num == 0 && shift->properties->allows_0 == 0)
3606 /* Reject a shift of 32 unless the mode allows it. */
3607 || (num == 32 && shift->properties->allows_32 == 0)
3610 /* As a special case we allow a shift of zero for
3611 modes that do not support it to be recoded as an
3612 logical shift left of zero (ie nothing). We warn
3613 about this though. */
3616 as_warn (_("shift of 0 ignored."));
3617 shift = & shift_names[0];
3618 assert (shift->properties->index == SHIFT_LSL);
3622 inst.error = _("invalid immediate shift");
3627 /* Shifts of 32 are encoded as 0, for those shifts that
3632 inst.instruction |= (num << 7) | shift->properties->bit_field;
3636 inst.reloc.type = BFD_RELOC_ARM_SHIFT_IMM;
3637 inst.reloc.pc_rel = 0;
3638 inst.instruction |= shift->properties->bit_field;
3646 do_sat (char ** str, int bias)
3651 skip_whitespace (*str);
3653 /* Parse <Rd>, field. */
3654 if ((rd = reg_required_here (str, 12)) == FAIL
3655 || skip_past_comma (str) == FAIL)
3657 inst.error = BAD_ARGS;
3662 inst.error = BAD_PC;
3666 /* Parse #<immed>, field. */
3667 if (is_immediate_prefix (**str))
3671 inst.error = _("immediate expression expected");
3674 if (my_get_expression (&expr, str))
3676 inst.error = _("bad expression");
3679 if (expr.X_op != O_constant)
3681 inst.error = _("constant expression expected");
3684 if (expr.X_add_number + bias < 0
3685 || expr.X_add_number + bias > 31)
3687 inst.error = _("immediate value out of range");
3690 inst.instruction |= (expr.X_add_number + bias) << 16;
3691 if (skip_past_comma (str) == FAIL)
3693 inst.error = BAD_ARGS;
3697 /* Parse <Rm> field. */
3698 if ((rm = reg_required_here (str, 0)) == FAIL)
3700 inst.error = BAD_ARGS;
3705 inst.error = BAD_PC;
3709 if (skip_past_comma (str) == SUCCESS)
3710 decode_shift (str, SHIFT_LSL_OR_ASR_IMMEDIATE);
3713 /* ARM V6 ssat (argument parse). */
3716 do_ssat (char * str)
3718 do_sat (&str, /*bias=*/-1);
3722 /* ARM V6 usat (argument parse). */
3725 do_usat (char * str)
3727 do_sat (&str, /*bias=*/0);
3732 do_sat16 (char ** str, int bias)
3737 skip_whitespace (*str);
3739 /* Parse the <Rd> field. */
3740 if ((rd = reg_required_here (str, 12)) == FAIL
3741 || skip_past_comma (str) == FAIL)
3743 inst.error = BAD_ARGS;
3748 inst.error = BAD_PC;
3752 /* Parse #<immed>, field. */
3753 if (is_immediate_prefix (**str))
3757 inst.error = _("immediate expression expected");
3760 if (my_get_expression (&expr, str))
3762 inst.error = _("bad expression");
3765 if (expr.X_op != O_constant)
3767 inst.error = _("constant expression expected");
3770 if (expr.X_add_number + bias < 0
3771 || expr.X_add_number + bias > 15)
3773 inst.error = _("immediate value out of range");
3776 inst.instruction |= (expr.X_add_number + bias) << 16;
3777 if (skip_past_comma (str) == FAIL)
3779 inst.error = BAD_ARGS;
3783 /* Parse <Rm> field. */
3784 if ((rm = reg_required_here (str, 0)) == FAIL)
3786 inst.error = BAD_ARGS;
3791 inst.error = BAD_PC;
3796 /* ARM V6 ssat16 (argument parse). */
3799 do_ssat16 (char * str)
3801 do_sat16 (&str, /*bias=*/-1);
3806 do_usat16 (char * str)
3808 do_sat16 (&str, /*bias=*/0);
3813 do_cps_mode (char ** str)
3817 skip_whitespace (*str);
3819 if (! is_immediate_prefix (**str))
3821 inst.error = _("immediate expression expected");
3825 (*str)++; /* Strip off the immediate signifier. */
3826 if (my_get_expression (&expr, str))
3828 inst.error = _("bad expression");
3832 if (expr.X_op != O_constant)
3834 inst.error = _("constant expression expected");
3838 /* The mode is a 5 bit field. Valid values are 0-31. */
3839 if (((unsigned) expr.X_add_number) > 31
3840 || (inst.reloc.exp.X_add_number) < 0)
3842 inst.error = _("invalid constant");
3846 inst.instruction |= expr.X_add_number;
3849 /* ARM V6 srs (argument parse). */
3855 skip_whitespace (str);
3856 exclam = strchr (str, '!');
3864 inst.instruction |= WRITE_BACK;
3870 /* ARM V6 SMMUL (argument parse). */
3873 do_smmul (char * str)
3877 skip_whitespace (str);
3878 if ((rd = reg_required_here (&str, 16)) == FAIL
3879 || skip_past_comma (&str) == FAIL
3880 || (rm = reg_required_here (&str, 0)) == FAIL
3881 || skip_past_comma (&str) == FAIL
3882 || (rs = reg_required_here (&str, 8)) == FAIL)
3884 inst.error = BAD_ARGS;
3892 inst.error = BAD_PC;
3899 /* ARM V6 SMLALD (argument parse). */
3902 do_smlald (char * str)
3904 int rdlo, rdhi, rm, rs;
3906 skip_whitespace (str);
3907 if ((rdlo = reg_required_here (&str, 12)) == FAIL
3908 || skip_past_comma (&str) == FAIL
3909 || (rdhi = reg_required_here (&str, 16)) == FAIL
3910 || skip_past_comma (&str) == FAIL
3911 || (rm = reg_required_here (&str, 0)) == FAIL
3912 || skip_past_comma (&str) == FAIL
3913 || (rs = reg_required_here (&str, 8)) == FAIL)
3915 inst.error = BAD_ARGS;
3924 inst.error = BAD_PC;
3931 /* ARM V6 SMLAD (argument parse). Signed multiply accumulate dual.
3932 smlad{x}{<cond>} Rd, Rm, Rs, Rn */
3935 do_smlad (char * str)
3939 skip_whitespace (str);
3940 if ((rd = reg_required_here (&str, 16)) == FAIL
3941 || skip_past_comma (&str) == FAIL
3942 || (rm = reg_required_here (&str, 0)) == FAIL
3943 || skip_past_comma (&str) == FAIL
3944 || (rs = reg_required_here (&str, 8)) == FAIL
3945 || skip_past_comma (&str) == FAIL
3946 || (rn = reg_required_here (&str, 12)) == FAIL)
3948 inst.error = BAD_ARGS;
3957 inst.error = BAD_PC;
3964 /* Returns true if the endian-specifier indicates big-endianness. */
3967 do_endian_specifier (char * str)
3971 skip_whitespace (str);
3972 if (strlen (str) < 2)
3973 inst.error = _("missing endian specifier");
3974 else if (strncasecmp (str, "BE", 2) == 0)
3979 else if (strncasecmp (str, "LE", 2) == 0)
3982 inst.error = _("valid endian specifiers are be or le");
3989 /* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
3990 preserving the other bits.
3992 setend <endian_specifier>, where <endian_specifier> is either
3996 do_setend (char * str)
3998 if (do_endian_specifier (str))
3999 inst.instruction |= 0x200;
4004 SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
4005 Condition defaults to COND_ALWAYS.
4006 Error if any register uses R15. */
4009 do_sxth (char * str)
4013 int rotation_clear_mask = 0xfffff3ff;
4014 int rotation_eight_mask = 0x00000400;
4015 int rotation_sixteen_mask = 0x00000800;
4016 int rotation_twenty_four_mask = 0x00000c00;
4018 skip_whitespace (str);
4019 if ((rd = reg_required_here (&str, 12)) == FAIL
4020 || skip_past_comma (&str) == FAIL
4021 || (rm = reg_required_here (&str, 0)) == FAIL)
4023 inst.error = BAD_ARGS;
4027 else if (rd == REG_PC || rm == REG_PC)
4029 inst.error = BAD_PC;
4033 /* Zero out the rotation field. */
4034 inst.instruction &= rotation_clear_mask;
4036 /* Check for lack of optional rotation field. */
4037 if (skip_past_comma (&str) == FAIL)
4043 /* Move past 'ROR'. */
4044 skip_whitespace (str);
4045 if (strncasecmp (str, "ROR", 3) == 0)
4049 inst.error = _("missing rotation field after comma");
4053 /* Get the immediate constant. */
4054 skip_whitespace (str);
4055 if (is_immediate_prefix (* str))
4059 inst.error = _("immediate expression expected");
4063 if (my_get_expression (&expr, &str))
4065 inst.error = _("bad expression");
4069 if (expr.X_op != O_constant)
4071 inst.error = _("constant expression expected");
4075 switch (expr.X_add_number)
4078 /* Rotation field has already been zeroed. */
4081 inst.instruction |= rotation_eight_mask;
4085 inst.instruction |= rotation_sixteen_mask;
4089 inst.instruction |= rotation_twenty_four_mask;
4093 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
4100 /* ARM V6 SXTAH extracts a 16-bit value from a register, sign
4101 extends it to 32-bits, and adds the result to a value in another
4102 register. You can specify a rotation by 0, 8, 16, or 24 bits
4103 before extracting the 16-bit value.
4104 SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
4105 Condition defaults to COND_ALWAYS.
4106 Error if any register uses R15. */
4109 do_sxtah (char * str)
4113 int rotation_clear_mask = 0xfffff3ff;
4114 int rotation_eight_mask = 0x00000400;
4115 int rotation_sixteen_mask = 0x00000800;
4116 int rotation_twenty_four_mask = 0x00000c00;
4118 skip_whitespace (str);
4119 if ((rd = reg_required_here (&str, 12)) == FAIL
4120 || skip_past_comma (&str) == FAIL
4121 || (rn = reg_required_here (&str, 16)) == FAIL
4122 || skip_past_comma (&str) == FAIL
4123 || (rm = reg_required_here (&str, 0)) == FAIL)
4125 inst.error = BAD_ARGS;
4129 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
4131 inst.error = BAD_PC;
4135 /* Zero out the rotation field. */
4136 inst.instruction &= rotation_clear_mask;
4138 /* Check for lack of optional rotation field. */
4139 if (skip_past_comma (&str) == FAIL)
4145 /* Move past 'ROR'. */
4146 skip_whitespace (str);
4147 if (strncasecmp (str, "ROR", 3) == 0)
4151 inst.error = _("missing rotation field after comma");
4155 /* Get the immediate constant. */
4156 skip_whitespace (str);
4157 if (is_immediate_prefix (* str))
4161 inst.error = _("immediate expression expected");
4165 if (my_get_expression (&expr, &str))
4167 inst.error = _("bad expression");
4171 if (expr.X_op != O_constant)
4173 inst.error = _("constant expression expected");
4177 switch (expr.X_add_number)
4180 /* Rotation field has already been zeroed. */
4184 inst.instruction |= rotation_eight_mask;
4188 inst.instruction |= rotation_sixteen_mask;
4192 inst.instruction |= rotation_twenty_four_mask;
4196 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
4204 /* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
4205 word at the specified address and the following word
4207 Unconditionally executed.
4208 Error if Rn is R15. */
4215 skip_whitespace (str);
4217 if ((rn = reg_required_here (&str, 16)) == FAIL)
4222 inst.error = BAD_PC;
4226 skip_whitespace (str);
4230 inst.instruction |= WRITE_BACK;
4236 /* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
4237 register (argument parse).
4239 Condition defaults to COND_ALWAYS.
4240 Error if Rd or Rm are R15. */
4247 skip_whitespace (str);
4249 if ((rd = reg_required_here (&str, 12)) == FAIL
4250 || skip_past_comma (&str) == FAIL
4251 || (rm = reg_required_here (&str, 0)) == FAIL)
4252 inst.error = BAD_ARGS;
4254 else if (rd == REG_PC || rm == REG_PC)
4255 inst.error = BAD_PC;
4261 /* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
4262 QADD16{<cond>} <Rd>, <Rn>, <Rm>
4263 Condition defaults to COND_ALWAYS.
4264 Error if Rd, Rn or Rm are R15. */
4267 do_qadd16 (char * str)
4271 skip_whitespace (str);
4273 if ((rd = reg_required_here (&str, 12)) == FAIL
4274 || skip_past_comma (&str) == FAIL
4275 || (rn = reg_required_here (&str, 16)) == FAIL
4276 || skip_past_comma (&str) == FAIL
4277 || (rm = reg_required_here (&str, 0)) == FAIL)
4278 inst.error = BAD_ARGS;
4280 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
4281 inst.error = BAD_PC;
4288 do_pkh_core (char * str, int shift)
4292 skip_whitespace (str);
4293 if (((rd = reg_required_here (&str, 12)) == FAIL)
4294 || (skip_past_comma (&str) == FAIL)
4295 || ((rn = reg_required_here (&str, 16)) == FAIL)
4296 || (skip_past_comma (&str) == FAIL)
4297 || ((rm = reg_required_here (&str, 0)) == FAIL))
4299 inst.error = BAD_ARGS;
4303 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
4305 inst.error = BAD_PC;
4309 /* Check for optional shift immediate constant. */
4310 if (skip_past_comma (&str) == FAIL)
4312 if (shift == SHIFT_ASR_IMMEDIATE)
4314 /* If the shift specifier is ommited, turn the instruction
4315 into pkhbt rd, rm, rn. First, switch the instruction
4316 code, and clear the rn and rm fields. */
4317 inst.instruction &= 0xfff0f010;
4318 /* Now, re-encode the registers. */
4319 inst.instruction |= (rm << 16) | rn;
4324 decode_shift (&str, shift);
4327 /* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
4328 PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
4329 Condition defaults to COND_ALWAYS.
4330 Error if Rd, Rn or Rm are R15. */
4333 do_pkhbt (char * str)
4335 do_pkh_core (str, SHIFT_LSL_IMMEDIATE);
4338 /* ARM V6 PKHTB (Argument Parse). */
4341 do_pkhtb (char * str)
4343 do_pkh_core (str, SHIFT_ASR_IMMEDIATE);
4346 /* ARM V6 Load Register Exclusive instruction (argument parse).
4347 LDREX{,B,D,H}{<cond>} <Rd, [<Rn>]
4348 Condition defaults to COND_ALWAYS.
4349 Error if Rd or Rn are R15.
4350 See ARMARMv6 A4.1.27: LDREX. */
4353 do_ldrex (char * str)
4357 skip_whitespace (str);
4360 if (((rd = reg_required_here (&str, 12)) == FAIL)
4361 || (skip_past_comma (&str) == FAIL))
4363 inst.error = BAD_ARGS;
4366 else if (rd == REG_PC)
4368 inst.error = BAD_PC;
4371 skip_whitespace (str);
4373 /* Skip past '['. */
4374 if ((strlen (str) >= 1)
4375 &&strncmp (str, "[", 1) == 0)
4377 skip_whitespace (str);
4380 if ((rn = reg_required_here (&str, 16)) == FAIL)
4382 inst.error = BAD_ARGS;
4385 else if (rn == REG_PC)
4387 inst.error = BAD_PC;
4390 skip_whitespace (str);
4392 /* Skip past ']'. */
4393 if ((strlen (str) >= 1)
4394 && strncmp (str, "]", 1) == 0)
4400 /* ARM V6 change processor state instruction (argument parse)
4401 CPS, CPSIE, CSPID . */
4411 do_cps_flags (char ** str, int thumb_p)
4416 unsigned long arm_value;
4417 unsigned long thumb_value;
4419 static struct cps_flag flag_table[] =
4428 skip_whitespace (*str);
4430 /* Get the a, f and i flags. */
4431 while (**str && **str != ',')
4434 struct cps_flag *q = flag_table + sizeof (flag_table)/sizeof (*p);
4436 for (p = flag_table; p < q; ++p)
4437 if (strncasecmp (*str, &p->character, 1) == 0)
4439 inst.instruction |= (thumb_p ? p->thumb_value : p->arm_value);
4445 inst.error = _("unrecognized flag");
4452 inst.error = _("no 'a', 'i', or 'f' flags for 'cps'");
4456 do_cpsi (char * str)
4458 do_cps_flags (&str, /*thumb_p=*/0);
4460 if (skip_past_comma (&str) == SUCCESS)
4462 skip_whitespace (str);
4468 /* ARM V6T2 bitfield manipulation instructions. */
4471 five_bit_unsigned_immediate (char **str)
4475 skip_whitespace (*str);
4476 if (!is_immediate_prefix (**str))
4478 inst.error = _("immediate expression expected");
4482 if (my_get_expression (&expr, str))
4484 inst.error = _("bad expression");
4487 if (expr.X_op != O_constant)
4489 inst.error = _("constant expression expected");
4492 if (expr.X_add_number < 0 || expr.X_add_number > 32)
4494 inst.error = _("immediate value out of range");
4498 return expr.X_add_number;
4502 bfci_lsb_and_width (char *str)
4506 if ((lsb = five_bit_unsigned_immediate (&str)) == -1)
4509 if (skip_past_comma (&str) == FAIL)
4511 inst.error = BAD_ARGS;
4514 if ((width = five_bit_unsigned_immediate (&str)) == -1)
4519 if (width == 0 || lsb == 32)
4521 inst.error = _("immediate value out of range");
4524 else if (width + lsb > 32)
4526 inst.error = _("bit-field extends past end of register");
4530 /* Convert to LSB/MSB and write to register. */
4531 inst.instruction |= lsb << 7;
4532 inst.instruction |= (width + lsb - 1) << 16;
4541 skip_whitespace (str);
4542 if (((rd = reg_required_here (&str, 12)) == FAIL)
4543 || (skip_past_comma (&str) == FAIL))
4545 inst.error = BAD_ARGS;
4548 else if (rd == REG_PC)
4550 inst.error = BAD_PC;
4554 bfci_lsb_and_width (str);
4563 skip_whitespace (str);
4564 if (((rd = reg_required_here (&str, 12)) == FAIL)
4565 || (skip_past_comma (&str) == FAIL))
4567 inst.error = BAD_ARGS;
4570 else if (rd == REG_PC)
4572 inst.error = BAD_PC;
4576 /* Rm. Accept #0 in this position as an alternative syntax for bfc. */
4577 skip_whitespace (str);
4578 if (is_immediate_prefix (*str))
4582 if (my_get_expression (&expr, &str))
4584 inst.error = _("bad expression");
4587 if (expr.X_op != O_constant)
4589 inst.error = _("constant expression expected");
4592 if (expr.X_add_number != 0)
4594 inst.error = _("immediate value out of range");
4597 inst.instruction |= 0x0000000f; /* Rm = PC -> bfc, not bfi. */
4601 if ((rm = reg_required_here (&str, 0)) == FAIL)
4603 inst.error = BAD_ARGS;
4606 else if (rm == REG_PC)
4608 inst.error = BAD_PC;
4612 if (skip_past_comma (&str) == FAIL)
4614 inst.error = BAD_ARGS;
4618 bfci_lsb_and_width (str);
4627 skip_whitespace (str);
4628 if (reg_required_here (&str, 12) == FAIL
4629 || skip_past_comma (&str) == FAIL)
4631 inst.error = BAD_ARGS;
4636 skip_whitespace (str);
4637 if (reg_required_here (&str, 0) == FAIL
4638 || skip_past_comma (&str) == FAIL)
4640 inst.error = BAD_ARGS;
4644 if ((lsb = five_bit_unsigned_immediate (&str)) == -1)
4647 if (skip_past_comma (&str) == FAIL)
4649 inst.error = BAD_ARGS;
4652 if ((width = five_bit_unsigned_immediate (&str)) == -1)
4657 if (width == 0 || lsb == 32)
4659 inst.error = _("immediate value out of range");
4662 else if (width + lsb > 32)
4664 inst.error = _("bit-field extends past end of register");
4668 inst.instruction |= lsb << 7;
4669 inst.instruction |= (width - 1) << 16;
4676 skip_whitespace (str);
4677 if (reg_required_here (&str, 12) == FAIL
4678 || skip_past_comma (&str) == FAIL)
4680 inst.error = BAD_ARGS;
4685 skip_whitespace (str);
4686 if (reg_required_here (&str, 0) == FAIL)
4688 inst.error = BAD_ARGS;
4695 /* ARM V6T2 16-bit immediate register load: MOV[WT]{cond} Rd, #<imm16>. */
4697 do_mov16 (char *str)
4703 skip_whitespace (str);
4704 if (((rd = reg_required_here (&str, 12)) == FAIL)
4705 || (skip_past_comma (&str) == FAIL))
4707 inst.error = BAD_ARGS;
4710 else if (rd == REG_PC)
4712 inst.error = BAD_PC;
4717 skip_whitespace (str);
4718 if (!is_immediate_prefix (*str))
4720 inst.error = _("immediate expression expected");
4724 if (my_get_expression (&expr, &str))
4726 inst.error = _("bad expression");
4729 if (expr.X_op != O_constant)
4731 inst.error = _("constant expression expected");
4734 if (expr.X_add_number < 0 || expr.X_add_number > 65535)
4736 inst.error = _("immediate value out of range");
4742 /* The value is in two pieces: 0:11, 16:19. */
4743 inst.instruction |= (expr.X_add_number & 0x00000fff);
4744 inst.instruction |= (expr.X_add_number & 0x0000f000) << 4;
4748 /* THUMB V5 breakpoint instruction (argument parse)
4752 do_t_bkpt (char * str)
4755 unsigned long number;
4757 skip_whitespace (str);
4759 /* Allow optional leading '#'. */
4760 if (is_immediate_prefix (*str))
4763 memset (& expr, '\0', sizeof (expr));
4764 if (my_get_expression (& expr, & str)
4765 || (expr.X_op != O_constant
4766 /* As a convenience we allow 'bkpt' without an operand. */
4767 && expr.X_op != O_absent))
4769 inst.error = _("bad expression");
4773 number = expr.X_add_number;
4775 /* Check it fits an 8 bit unsigned. */
4776 if (number != (number & 0xff))
4778 inst.error = _("immediate value out of range");
4782 inst.instruction |= number;
4788 static bfd_reloc_code_real_type
4789 arm_parse_reloc (void)
4798 bfd_reloc_code_real_type reloc;
4802 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
4803 MAP ("(got)", BFD_RELOC_ARM_GOT32),
4804 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF),
4805 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
4806 branch instructions generated by GCC for PLT relocs. */
4807 MAP ("(plt)", BFD_RELOC_ARM_PLT32),
4808 MAP ("(target1)", BFD_RELOC_ARM_TARGET1),
4809 MAP ("(sbrel)", BFD_RELOC_ARM_SBREL32),
4810 MAP ("(target2)", BFD_RELOC_ARM_TARGET2),
4811 MAP ("(tlsgd)", BFD_RELOC_ARM_TLS_GD32),
4812 MAP ("(tlsldm)", BFD_RELOC_ARM_TLS_LDM32),
4813 MAP ("(tlsldo)", BFD_RELOC_ARM_TLS_LDO32),
4814 MAP ("(gottpoff)", BFD_RELOC_ARM_TLS_IE32),
4815 MAP ("(tpoff)", BFD_RELOC_ARM_TLS_LE32),
4816 { NULL, 0, BFD_RELOC_UNUSED }
4820 for (i = 0, ip = input_line_pointer;
4821 i < sizeof (id) && (ISALNUM (*ip) || ISPUNCT (*ip));
4823 id[i] = TOLOWER (*ip);
4825 for (i = 0; reloc_map[i].str; i++)
4826 if (strncmp (id, reloc_map[i].str, reloc_map[i].len) == 0)
4829 input_line_pointer += reloc_map[i].len;
4831 return reloc_map[i].reloc;
4835 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
4836 Expects inst.instruction is set for BLX(1).
4837 Note: this is cloned from do_branch, and the reloc changed to be a
4838 new one that can cope with setting one extra bit (the H bit). */
4841 do_branch25 (char * str)
4843 if (my_get_expression (& inst.reloc.exp, & str))
4850 /* ScottB: February 5, 1998 */
4851 /* Check to see of PLT32 reloc required for the instruction. */
4853 /* arm_parse_reloc() works on input_line_pointer.
4854 We actually want to parse the operands to the branch instruction
4855 passed in 'str'. Save the input pointer and restore it later. */
4856 save_in = input_line_pointer;
4857 input_line_pointer = str;
4859 if (inst.reloc.exp.X_op == O_symbol
4861 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
4863 inst.reloc.type = BFD_RELOC_ARM_PLT32;
4864 inst.reloc.pc_rel = 0;
4865 /* Modify str to point to after parsed operands, otherwise
4866 end_of_line() will complain about the (PLT) left in str. */
4867 str = input_line_pointer;
4871 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
4872 inst.reloc.pc_rel = 1;
4875 input_line_pointer = save_in;
4878 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
4879 inst.reloc.pc_rel = 1;
4880 #endif /* OBJ_ELF */
4885 /* ARM V5 branch-link-exchange instruction (argument parse)
4886 BLX <target_addr> ie BLX(1)
4887 BLX{<condition>} <Rm> ie BLX(2)
4888 Unfortunately, there are two different opcodes for this mnemonic.
4889 So, the insns[].value is not used, and the code here zaps values
4890 into inst.instruction.
4891 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
4899 skip_whitespace (mystr);
4900 rm = reg_required_here (& mystr, 0);
4902 /* The above may set inst.error. Ignore his opinion. */
4907 /* Arg is a register.
4908 Use the condition code our caller put in inst.instruction.
4909 Pass ourselves off as a BX with a funny opcode. */
4910 inst.instruction |= 0x012fff30;
4915 /* This must be is BLX <target address>, no condition allowed. */
4916 if (inst.instruction != COND_ALWAYS)
4918 inst.error = BAD_COND;
4922 inst.instruction = 0xfafffffe;
4924 /* Process like a B/BL, but with a different reloc.
4925 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
4930 /* ARM V5 Thumb BLX (argument parse)
4931 BLX <target_addr> which is BLX(1)
4932 BLX <Rm> which is BLX(2)
4933 Unfortunately, there are two different opcodes for this mnemonic.
4934 So, the tinsns[].value is not used, and the code here zaps values
4935 into inst.instruction. */
4938 do_t_blx (char * str)
4943 skip_whitespace (mystr);
4944 inst.instruction = 0x4780;
4946 /* Note that this call is to the ARM register recognizer. BLX(2)
4947 uses the ARM register space, not the Thumb one, so a call to
4948 thumb_reg() would be wrong. */
4949 rm = reg_required_here (& mystr, 3);
4954 /* It's BLX(2). The .instruction was zapped with rm & is final. */
4959 /* No ARM register. This must be BLX(1). Change the .instruction. */
4960 inst.instruction = 0xf7ffeffe;
4963 if (my_get_expression (& inst.reloc.exp, & mystr))
4966 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BLX;
4967 inst.reloc.pc_rel = 1;
4970 end_of_line (mystr);
4973 /* ARM V5 breakpoint instruction (argument parse)
4974 BKPT <16 bit unsigned immediate>
4975 Instruction is not conditional.
4976 The bit pattern given in insns[] has the COND_ALWAYS condition,
4977 and it is an error if the caller tried to override that. */
4980 do_bkpt (char * str)
4983 unsigned long number;
4985 skip_whitespace (str);
4987 /* Allow optional leading '#'. */
4988 if (is_immediate_prefix (* str))
4991 memset (& expr, '\0', sizeof (expr));
4993 if (my_get_expression (& expr, & str)
4994 || (expr.X_op != O_constant
4995 /* As a convenience we allow 'bkpt' without an operand. */
4996 && expr.X_op != O_absent))
4998 inst.error = _("bad expression");
5002 number = expr.X_add_number;
5004 /* Check it fits a 16 bit unsigned. */
5005 if (number != (number & 0xffff))
5007 inst.error = _("immediate value out of range");
5011 /* Top 12 of 16 bits to bits 19:8. */
5012 inst.instruction |= (number & 0xfff0) << 4;
5014 /* Bottom 4 of 16 bits to bits 3:0. */
5015 inst.instruction |= number & 0xf;
5020 /* THUMB CPS instruction (argument parse). */
5023 do_t_cps (char * str)
5025 do_cps_flags (&str, /*thumb_p=*/1);
5029 /* Parse and validate that a register is of the right form, this saves
5030 repeated checking of this information in many similar cases.
5031 Unlike the 32-bit case we do not insert the register into the opcode
5032 here, since the position is often unknown until the full instruction
5036 thumb_reg (char ** strp, int hi_lo)
5040 if ((reg = reg_required_here (strp, -1)) == FAIL)
5048 inst.error = _("lo register required");
5056 inst.error = _("hi register required");
5069 thumb_mov_compare (char * str, int move)
5073 skip_whitespace (str);
5075 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
5076 || skip_past_comma (&str) == FAIL)
5079 inst.error = BAD_ARGS;
5083 if (move != THUMB_CPY && is_immediate_prefix (*str))
5086 if (my_get_expression (&inst.reloc.exp, &str))
5089 else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
5094 if (move != THUMB_CPY && Rs < 8 && Rd < 8)
5096 if (move == THUMB_MOVE)
5097 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
5098 since a MOV instruction produces unpredictable results. */
5099 inst.instruction = T_OPCODE_ADD_I3;
5101 inst.instruction = T_OPCODE_CMP_LR;
5102 inst.instruction |= Rd | (Rs << 3);
5106 if (move == THUMB_MOVE)
5107 inst.instruction = T_OPCODE_MOV_HR;
5108 else if (move != THUMB_CPY)
5109 inst.instruction = T_OPCODE_CMP_HR;
5112 inst.instruction |= THUMB_H1;
5115 inst.instruction |= THUMB_H2;
5117 inst.instruction |= (Rd & 7) | ((Rs & 7) << 3);
5124 inst.error = _("only lo regs allowed with immediate");
5128 if (move == THUMB_MOVE)
5129 inst.instruction = T_OPCODE_MOV_I8;
5131 inst.instruction = T_OPCODE_CMP_I8;
5133 inst.instruction |= Rd << 8;
5135 if (inst.reloc.exp.X_op != O_constant)
5136 inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
5139 unsigned value = inst.reloc.exp.X_add_number;
5143 inst.error = _("invalid immediate");
5147 inst.instruction |= value;
5154 /* THUMB CPY instruction (argument parse). */
5157 do_t_cpy (char * str)
5159 thumb_mov_compare (str, THUMB_CPY);
5162 /* THUMB SETEND instruction (argument parse). */
5165 do_t_setend (char * str)
5167 if (do_endian_specifier (str))
5168 inst.instruction |= 0x8;
5171 /* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
5173 static unsigned long
5174 check_iwmmxt_insn (char * str,
5175 enum iwmmxt_insn_type insn_type,
5179 const char * inst_error;
5181 unsigned long number;
5183 inst_error = inst.error;
5185 inst.error = BAD_ARGS;
5186 skip_whitespace (str);
5191 if ((reg = reg_required_here (&str, 12)) == FAIL)
5196 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR)) == FAIL)
5201 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5202 || skip_past_comma (&str) == FAIL
5203 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
5208 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5209 || skip_past_comma (&str) == FAIL
5210 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5211 || skip_past_comma (&str) == FAIL
5212 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
5217 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5218 || skip_past_comma (&str) == FAIL
5219 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5220 || skip_past_comma (&str) == FAIL
5221 || wreg_required_here (&str, 0, IWMMXT_REG_WCG) == FAIL))
5226 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5227 || skip_past_comma (&str) == FAIL
5228 || reg_required_here (&str, 12) == FAIL))
5233 if ((reg_required_here (&str, 12) == FAIL
5234 || skip_past_comma (&str) == FAIL
5235 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
5240 if ((wreg_required_here (&str, 5, IWMMXT_REG_WR) == FAIL
5241 || skip_past_comma (&str) == FAIL
5242 || reg_required_here (&str, 0) == FAIL
5243 || skip_past_comma (&str) == FAIL
5244 || reg_required_here (&str, 12) == FAIL))
5249 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
5250 || skip_past_comma (&str) == FAIL
5251 || reg_required_here (&str, 12) == FAIL
5252 || skip_past_comma (&str) == FAIL
5253 || reg_required_here (&str, 16) == FAIL))
5258 if ((reg_required_here (&str, 12) == FAIL
5259 || skip_past_comma (&str) == FAIL
5260 || reg_required_here (&str, 16) == FAIL
5261 || skip_past_comma (&str) == FAIL
5262 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
5267 if ((wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL
5268 || skip_past_comma (&str) == FAIL
5269 || reg_required_here (&str, 12) == FAIL))
5274 if ((reg_required_here (&str, 12) == FAIL
5275 || skip_past_comma (&str) == FAIL
5276 || wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL))
5281 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5282 || skip_past_comma (&str) == FAIL
5283 || reg_required_here (&str, 12) == FAIL
5284 || skip_past_comma (&str) == FAIL))
5289 if ((reg_required_here (&str, 12) == FAIL
5290 || skip_past_comma (&str) == FAIL))
5295 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5296 || skip_past_comma (&str) == FAIL
5297 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5298 || skip_past_comma (&str) == FAIL
5299 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
5300 || skip_past_comma (&str) == FAIL))
5305 if ((reg_required_here (&str, 12) == FAIL
5306 || skip_past_comma (&str) == FAIL
5307 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5308 || skip_past_comma (&str) == FAIL))
5313 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5314 || skip_past_comma (&str) == FAIL
5315 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5316 || skip_past_comma (&str) == FAIL))
5321 if (immediate_size == 0)
5324 inst.error = inst_error;
5329 skip_whitespace (str);
5331 /* Allow optional leading '#'. */
5332 if (is_immediate_prefix (* str))
5335 memset (& expr, '\0', sizeof (expr));
5337 if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
5339 inst.error = _("bad or missing expression");
5343 number = expr.X_add_number;
5345 if (number != (number & immediate_size))
5347 inst.error = _("immediate value out of range");
5351 inst.error = inst_error;
5357 do_iwmmxt_byte_addr (char * str)
5359 int op = (inst.instruction & 0x300) >> 8;
5362 inst.instruction &= ~0x300;
5363 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
5365 skip_whitespace (str);
5367 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
5368 || skip_past_comma (& str) == FAIL
5369 || cp_byte_address_required_here (&str) == FAIL)
5372 inst.error = BAD_ARGS;
5377 if (wc_register (reg))
5379 as_bad (_("non-word size not supported with control register"));
5380 inst.instruction |= 0xf0000100;
5381 inst.instruction &= ~0x00400000;
5386 do_iwmmxt_tandc (char * str)
5390 reg = check_iwmmxt_insn (str, check_rd, 0);
5392 if (reg != REG_PC && !inst.error)
5393 inst.error = _("only r15 allowed here");
5397 do_iwmmxt_tbcst (char * str)
5399 check_iwmmxt_insn (str, check_tbcst, 0);
5403 do_iwmmxt_textrc (char * str)
5405 unsigned long number;
5407 if ((number = check_iwmmxt_insn (str, check_textrc, 7)) == (unsigned long) FAIL)
5410 inst.instruction |= number & 0x7;
5414 do_iwmmxt_textrm (char * str)
5416 unsigned long number;
5418 if ((number = check_iwmmxt_insn (str, check_textrm, 7)) == (unsigned long) FAIL)
5421 inst.instruction |= number & 0x7;
5425 do_iwmmxt_tinsr (char * str)
5427 unsigned long number;
5429 if ((number = check_iwmmxt_insn (str, check_tinsr, 7)) == (unsigned long) FAIL)
5432 inst.instruction |= number & 0x7;
5436 do_iwmmxt_tmcr (char * str)
5438 check_iwmmxt_insn (str, check_tmcr, 0);
5442 do_iwmmxt_tmcrr (char * str)
5444 check_iwmmxt_insn (str, check_tmcrr, 0);
5448 do_iwmmxt_tmia (char * str)
5450 check_iwmmxt_insn (str, check_tmia, 0);
5454 do_iwmmxt_tmovmsk (char * str)
5456 check_iwmmxt_insn (str, check_tmovmsk, 0);
5460 do_iwmmxt_tmrc (char * str)
5462 check_iwmmxt_insn (str, check_tmrc, 0);
5466 do_iwmmxt_tmrrc (char * str)
5468 check_iwmmxt_insn (str, check_tmrrc, 0);
5472 do_iwmmxt_torc (char * str)
5474 check_iwmmxt_insn (str, check_rd, 0);
5478 do_iwmmxt_waligni (char * str)
5480 unsigned long number;
5482 if ((number = check_iwmmxt_insn (str, check_waligni, 7)) == (unsigned long) FAIL)
5485 inst.instruction |= ((number & 0x7) << 20);
5489 do_iwmmxt_wmov (char * str)
5491 if (check_iwmmxt_insn (str, check_wrwr, 0) == (unsigned long) FAIL)
5494 inst.instruction |= ((inst.instruction >> 16) & 0xf);
5498 do_iwmmxt_word_addr (char * str)
5500 int op = (inst.instruction & 0x300) >> 8;
5503 inst.instruction &= ~0x300;
5504 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
5506 skip_whitespace (str);
5508 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
5509 || skip_past_comma (& str) == FAIL
5510 || cp_address_required_here (& str, CP_WB_OK) == FAIL)
5513 inst.error = BAD_ARGS;
5518 if (wc_register (reg))
5520 if ((inst.instruction & COND_MASK) != COND_ALWAYS)
5521 as_bad (_("conditional execution not supported with control register"));
5523 as_bad (_("non-word size not supported with control register"));
5524 inst.instruction |= 0xf0000100;
5525 inst.instruction &= ~0x00400000;
5530 do_iwmmxt_wrwr (char * str)
5532 check_iwmmxt_insn (str, check_wrwr, 0);
5536 do_iwmmxt_wrwrwcg (char * str)
5538 check_iwmmxt_insn (str, check_wrwrwcg, 0);
5542 do_iwmmxt_wrwrwr (char * str)
5544 check_iwmmxt_insn (str, check_wrwrwr, 0);
5548 do_iwmmxt_wshufh (char * str)
5550 unsigned long number;
5552 if ((number = check_iwmmxt_insn (str, check_wshufh, 0xff)) == (unsigned long) FAIL)
5555 inst.instruction |= ((number & 0xf0) << 16) | (number & 0xf);
5559 do_iwmmxt_wzero (char * str)
5561 if (check_iwmmxt_insn (str, check_wr, 0) == (unsigned long) FAIL)
5564 inst.instruction |= ((inst.instruction & 0xf) << 12) | ((inst.instruction & 0xf) << 16);
5567 /* Xscale multiply-accumulate (argument parse)
5570 MIAxycc acc0,Rm,Rs. */
5573 do_xsc_mia (char * str)
5578 if (accum0_required_here (& str) == FAIL)
5579 inst.error = ERR_NO_ACCUM;
5581 else if (skip_past_comma (& str) == FAIL
5582 || (rm = reg_required_here (& str, 0)) == FAIL)
5583 inst.error = BAD_ARGS;
5585 else if (skip_past_comma (& str) == FAIL
5586 || (rs = reg_required_here (& str, 12)) == FAIL)
5587 inst.error = BAD_ARGS;
5589 /* inst.instruction has now been zapped with both rm and rs. */
5590 else if (rm == REG_PC || rs == REG_PC)
5591 inst.error = BAD_PC; /* Undefined result if rm or rs is R15. */
5597 /* Xscale move-accumulator-register (argument parse)
5599 MARcc acc0,RdLo,RdHi. */
5602 do_xsc_mar (char * str)
5606 if (accum0_required_here (& str) == FAIL)
5607 inst.error = ERR_NO_ACCUM;
5609 else if (skip_past_comma (& str) == FAIL
5610 || (rdlo = reg_required_here (& str, 12)) == FAIL)
5611 inst.error = BAD_ARGS;
5613 else if (skip_past_comma (& str) == FAIL
5614 || (rdhi = reg_required_here (& str, 16)) == FAIL)
5615 inst.error = BAD_ARGS;
5617 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5618 else if (rdlo == REG_PC || rdhi == REG_PC)
5619 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
5625 /* Xscale move-register-accumulator (argument parse)
5627 MRAcc RdLo,RdHi,acc0. */
5630 do_xsc_mra (char * str)
5635 skip_whitespace (str);
5637 if ((rdlo = reg_required_here (& str, 12)) == FAIL)
5638 inst.error = BAD_ARGS;
5640 else if (skip_past_comma (& str) == FAIL
5641 || (rdhi = reg_required_here (& str, 16)) == FAIL)
5642 inst.error = BAD_ARGS;
5644 else if (skip_past_comma (& str) == FAIL
5645 || accum0_required_here (& str) == FAIL)
5646 inst.error = ERR_NO_ACCUM;
5648 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5649 else if (rdlo == rdhi)
5650 inst.error = BAD_ARGS; /* Undefined result if 2 writes to same reg. */
5652 else if (rdlo == REG_PC || rdhi == REG_PC)
5653 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
5659 ldst_extend (char ** str)
5668 if (my_get_expression (& inst.reloc.exp, str))
5671 if (inst.reloc.exp.X_op == O_constant)
5673 int value = inst.reloc.exp.X_add_number;
5675 if (value < -4095 || value > 4095)
5677 inst.error = _("address offset too large");
5687 inst.instruction |= add | value;
5691 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
5692 inst.reloc.pc_rel = 0;
5705 if (reg_required_here (str, 0) == FAIL)
5708 inst.instruction |= add | OFFSET_REG;
5709 if (skip_past_comma (str) == SUCCESS)
5710 return decode_shift (str, SHIFT_IMMEDIATE);
5716 /* ARMv5TE: Preload-Cache
5720 Syntactically, like LDR with B=1, W=0, L=1. */
5727 skip_whitespace (str);
5731 inst.error = _("'[' expected after PLD mnemonic");
5736 skip_whitespace (str);
5738 if ((rd = reg_required_here (& str, 16)) == FAIL)
5741 skip_whitespace (str);
5747 skip_whitespace (str);
5749 /* Post-indexed addressing is not allowed with PLD. */
5750 if (skip_past_comma (&str) == SUCCESS)
5753 = _("post-indexed expression used in preload instruction");
5756 else if (*str == '!') /* [Rn]! */
5758 inst.error = _("writeback used in preload instruction");
5762 inst.instruction |= INDEX_UP | PRE_INDEX;
5764 else /* [Rn, ...] */
5766 if (skip_past_comma (& str) == FAIL)
5768 inst.error = _("pre-indexed expression expected");
5772 if (ldst_extend (&str) == FAIL)
5775 skip_whitespace (str);
5779 inst.error = _("missing ]");
5784 skip_whitespace (str);
5786 if (* str == '!') /* [Rn]! */
5788 inst.error = _("writeback used in preload instruction");
5792 inst.instruction |= PRE_INDEX;
5798 /* ARMv5TE load-consecutive (argument parse)
5805 do_ldrd (char * str)
5810 skip_whitespace (str);
5812 if ((rd = reg_required_here (& str, 12)) == FAIL)
5814 inst.error = BAD_ARGS;
5818 if (skip_past_comma (& str) == FAIL
5819 || (rn = ld_mode_required_here (& str)) == FAIL)
5822 inst.error = BAD_ARGS;
5826 /* inst.instruction has now been zapped with Rd and the addressing mode. */
5827 if (rd & 1) /* Unpredictable result if Rd is odd. */
5829 inst.error = _("destination register must be even");
5835 inst.error = _("r14 not allowed here");
5839 if (((rd == rn) || (rd + 1 == rn))
5840 && ((inst.instruction & WRITE_BACK)
5841 || (!(inst.instruction & PRE_INDEX))))
5842 as_warn (_("pre/post-indexing used when modified address register is destination"));
5844 /* For an index-register load, the index register must not overlap the
5845 destination (even if not write-back). */
5846 if ((inst.instruction & V4_STR_BIT) == 0
5847 && (inst.instruction & HWOFFSET_IMM) == 0)
5849 int rm = inst.instruction & 0x0000000f;
5851 if (rm == rd || (rm == rd + 1))
5852 as_warn (_("ldrd destination registers must not overlap index register"));
5858 /* Returns the index into fp_values of a floating point number,
5859 or -1 if not in the table. */
5862 my_get_float_expression (char ** str)
5864 LITTLENUM_TYPE words[MAX_LITTLENUMS];
5870 memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE));
5872 /* Look for a raw floating point number. */
5873 if ((save_in = atof_ieee (*str, 'x', words)) != NULL
5874 && is_end_of_line[(unsigned char) *save_in])
5876 for (i = 0; i < NUM_FLOAT_VALS; i++)
5878 for (j = 0; j < MAX_LITTLENUMS; j++)
5880 if (words[j] != fp_values[i][j])
5884 if (j == MAX_LITTLENUMS)
5892 /* Try and parse a more complex expression, this will probably fail
5893 unless the code uses a floating point prefix (eg "0f"). */
5894 save_in = input_line_pointer;
5895 input_line_pointer = *str;
5896 if (expression (&exp) == absolute_section
5897 && exp.X_op == O_big
5898 && exp.X_add_number < 0)
5900 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
5902 if (gen_to_words (words, 5, (long) 15) == 0)
5904 for (i = 0; i < NUM_FLOAT_VALS; i++)
5906 for (j = 0; j < MAX_LITTLENUMS; j++)
5908 if (words[j] != fp_values[i][j])
5912 if (j == MAX_LITTLENUMS)
5914 *str = input_line_pointer;
5915 input_line_pointer = save_in;
5922 *str = input_line_pointer;
5923 input_line_pointer = save_in;
5927 /* We handle all bad expressions here, so that we can report the faulty
5928 instruction in the error message. */
5930 md_operand (expressionS * expr)
5932 if (in_my_get_expression)
5934 expr->X_op = O_illegal;
5935 if (inst.error == NULL)
5936 inst.error = _("bad expression");
5940 /* Do those data_ops which can take a negative immediate constant
5941 by altering the instruction. A bit of a hack really.
5945 by inverting the second operand, and
5948 by negating the second operand. */
5951 negate_data_op (unsigned long * instruction,
5952 unsigned long value)
5955 unsigned long negated, inverted;
5957 negated = validate_immediate (-value);
5958 inverted = validate_immediate (~value);
5960 op = (*instruction >> DATA_OP_SHIFT) & 0xf;
5963 /* First negates. */
5964 case OPCODE_SUB: /* ADD <-> SUB */
5965 new_inst = OPCODE_ADD;
5970 new_inst = OPCODE_SUB;
5974 case OPCODE_CMP: /* CMP <-> CMN */
5975 new_inst = OPCODE_CMN;
5980 new_inst = OPCODE_CMP;
5984 /* Now Inverted ops. */
5985 case OPCODE_MOV: /* MOV <-> MVN */
5986 new_inst = OPCODE_MVN;
5991 new_inst = OPCODE_MOV;
5995 case OPCODE_AND: /* AND <-> BIC */
5996 new_inst = OPCODE_BIC;
6001 new_inst = OPCODE_AND;
6005 case OPCODE_ADC: /* ADC <-> SBC */
6006 new_inst = OPCODE_SBC;
6011 new_inst = OPCODE_ADC;
6015 /* We cannot do anything. */
6020 if (value == (unsigned) FAIL)
6023 *instruction &= OPCODE_MASK;
6024 *instruction |= new_inst << DATA_OP_SHIFT;
6029 data_op2 (char ** str)
6034 skip_whitespace (* str);
6036 if (reg_required_here (str, 0) != FAIL)
6038 if (skip_past_comma (str) == SUCCESS)
6039 /* Shift operation on register. */
6040 return decode_shift (str, NO_SHIFT_RESTRICT);
6046 /* Immediate expression. */
6047 if (is_immediate_prefix (**str))
6052 if (my_get_expression (&inst.reloc.exp, str))
6055 if (inst.reloc.exp.X_add_symbol)
6057 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
6058 inst.reloc.pc_rel = 0;
6062 if (skip_past_comma (str) == SUCCESS)
6064 /* #x, y -- ie explicit rotation by Y. */
6065 if (my_get_expression (&expr, str))
6068 if (expr.X_op != O_constant)
6070 inst.error = _("constant expression expected");
6074 /* Rotate must be a multiple of 2. */
6075 if (((unsigned) expr.X_add_number) > 30
6076 || (expr.X_add_number & 1) != 0
6077 || ((unsigned) inst.reloc.exp.X_add_number) > 255)
6079 inst.error = _("invalid constant");
6082 inst.instruction |= INST_IMMEDIATE;
6083 inst.instruction |= inst.reloc.exp.X_add_number;
6084 inst.instruction |= expr.X_add_number << 7;
6088 /* Implicit rotation, select a suitable one. */
6089 value = validate_immediate (inst.reloc.exp.X_add_number);
6093 /* Can't be done. Perhaps the code reads something like
6094 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
6095 if ((value = negate_data_op (&inst.instruction,
6096 inst.reloc.exp.X_add_number))
6099 inst.error = _("invalid constant");
6104 inst.instruction |= value;
6107 inst.instruction |= INST_IMMEDIATE;
6112 inst.error = _("register or shift expression expected");
6118 fp_op2 (char ** str)
6120 skip_whitespace (* str);
6122 if (fp_reg_required_here (str, 0) != FAIL)
6126 /* Immediate expression. */
6127 if (*((*str)++) == '#')
6133 skip_whitespace (* str);
6135 /* First try and match exact strings, this is to guarantee
6136 that some formats will work even for cross assembly. */
6138 for (i = 0; fp_const[i]; i++)
6140 if (strncmp (*str, fp_const[i], strlen (fp_const[i])) == 0)
6144 *str += strlen (fp_const[i]);
6145 if (is_end_of_line[(unsigned char) **str])
6147 inst.instruction |= i + 8;
6154 /* Just because we didn't get a match doesn't mean that the
6155 constant isn't valid, just that it is in a format that we
6156 don't automatically recognize. Try parsing it with
6157 the standard expression routines. */
6158 if ((i = my_get_float_expression (str)) >= 0)
6160 inst.instruction |= i + 8;
6164 inst.error = _("invalid floating point immediate expression");
6168 _("floating point register or immediate expression expected");
6174 do_arit (char * str)
6176 skip_whitespace (str);
6178 if (reg_required_here (&str, 12) == FAIL
6179 || skip_past_comma (&str) == FAIL
6180 || reg_required_here (&str, 16) == FAIL
6181 || skip_past_comma (&str) == FAIL
6182 || data_op2 (&str) == FAIL)
6185 inst.error = BAD_ARGS;
6195 /* This is a pseudo-op of the form "adr rd, label" to be converted
6196 into a relative address of the form "add rd, pc, #label-.-8". */
6197 skip_whitespace (str);
6199 if (reg_required_here (&str, 12) == FAIL
6200 || skip_past_comma (&str) == FAIL
6201 || my_get_expression (&inst.reloc.exp, &str))
6204 inst.error = BAD_ARGS;
6208 /* Frag hacking will turn this into a sub instruction if the offset turns
6209 out to be negative. */
6210 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
6212 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust. */
6214 inst.reloc.pc_rel = 1;
6220 do_adrl (char * str)
6222 /* This is a pseudo-op of the form "adrl rd, label" to be converted
6223 into a relative address of the form:
6224 add rd, pc, #low(label-.-8)"
6225 add rd, rd, #high(label-.-8)" */
6227 skip_whitespace (str);
6229 if (reg_required_here (&str, 12) == FAIL
6230 || skip_past_comma (&str) == FAIL
6231 || my_get_expression (&inst.reloc.exp, &str))
6234 inst.error = BAD_ARGS;
6240 /* Frag hacking will turn this into a sub instruction if the offset turns
6241 out to be negative. */
6242 inst.reloc.type = BFD_RELOC_ARM_ADRL_IMMEDIATE;
6244 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust */
6246 inst.reloc.pc_rel = 1;
6247 inst.size = INSN_SIZE * 2;
6253 skip_whitespace (str);
6255 if (reg_required_here (&str, 16) == FAIL)
6258 inst.error = BAD_ARGS;
6262 if (skip_past_comma (&str) == FAIL
6263 || data_op2 (&str) == FAIL)
6266 inst.error = BAD_ARGS;
6276 skip_whitespace (str);
6278 if (reg_required_here (&str, 12) == FAIL)
6281 inst.error = BAD_ARGS;
6285 if (skip_past_comma (&str) == FAIL
6286 || data_op2 (&str) == FAIL)
6289 inst.error = BAD_ARGS;
6297 do_ldst (char * str)
6303 skip_whitespace (str);
6305 if ((conflict_reg = reg_required_here (&str, 12)) == FAIL)
6308 inst.error = BAD_ARGS;
6312 if (skip_past_comma (&str) == FAIL)
6314 inst.error = _("address expected");
6324 skip_whitespace (str);
6326 if ((reg = reg_required_here (&str, 16)) == FAIL)
6329 /* Conflicts can occur on stores as well as loads. */
6330 conflict_reg = (conflict_reg == reg);
6332 skip_whitespace (str);
6338 if (skip_past_comma (&str) == SUCCESS)
6340 /* [Rn],... (post inc) */
6341 if (ldst_extend (&str) == FAIL)
6344 as_warn (_("%s register same as write-back base"),
6345 ((inst.instruction & LOAD_BIT)
6346 ? _("destination") : _("source")));
6351 skip_whitespace (str);
6356 as_warn (_("%s register same as write-back base"),
6357 ((inst.instruction & LOAD_BIT)
6358 ? _("destination") : _("source")));
6360 inst.instruction |= WRITE_BACK;
6363 inst.instruction |= INDEX_UP;
6370 if (skip_past_comma (&str) == FAIL)
6372 inst.error = _("pre-indexed expression expected");
6377 if (ldst_extend (&str) == FAIL)
6380 skip_whitespace (str);
6384 inst.error = _("missing ]");
6388 skip_whitespace (str);
6393 as_warn (_("%s register same as write-back base"),
6394 ((inst.instruction & LOAD_BIT)
6395 ? _("destination") : _("source")));
6397 inst.instruction |= WRITE_BACK;
6401 else if (*str == '=')
6403 if ((inst.instruction & LOAD_BIT) == 0)
6405 inst.error = _("invalid pseudo operation");
6409 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6412 skip_whitespace (str);
6414 if (my_get_expression (&inst.reloc.exp, &str))
6417 if (inst.reloc.exp.X_op != O_constant
6418 && inst.reloc.exp.X_op != O_symbol)
6420 inst.error = _("constant expression expected");
6424 if (inst.reloc.exp.X_op == O_constant)
6426 value = validate_immediate (inst.reloc.exp.X_add_number);
6430 /* This can be done with a mov instruction. */
6431 inst.instruction &= LITERAL_MASK;
6432 inst.instruction |= (INST_IMMEDIATE
6433 | (OPCODE_MOV << DATA_OP_SHIFT));
6434 inst.instruction |= value & 0xfff;
6439 value = validate_immediate (~inst.reloc.exp.X_add_number);
6443 /* This can be done with a mvn instruction. */
6444 inst.instruction &= LITERAL_MASK;
6445 inst.instruction |= (INST_IMMEDIATE
6446 | (OPCODE_MVN << DATA_OP_SHIFT));
6447 inst.instruction |= value & 0xfff;
6453 /* Insert into literal pool. */
6454 if (add_to_lit_pool () == FAIL)
6457 inst.error = _("literal pool insertion failed");
6461 /* Change the instruction exp to point to the pool. */
6462 inst.reloc.type = BFD_RELOC_ARM_LITERAL;
6463 inst.reloc.pc_rel = 1;
6464 inst.instruction |= (REG_PC << 16);
6469 if (my_get_expression (&inst.reloc.exp, &str))
6472 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
6474 /* PC rel adjust. */
6475 inst.reloc.exp.X_add_number -= 8;
6477 inst.reloc.pc_rel = 1;
6478 inst.instruction |= (REG_PC << 16);
6482 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
6487 do_ldstt (char * str)
6491 skip_whitespace (str);
6493 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
6496 inst.error = BAD_ARGS;
6500 if (skip_past_comma (& str) == FAIL)
6502 inst.error = _("address expected");
6512 skip_whitespace (str);
6514 if ((reg = reg_required_here (&str, 16)) == FAIL)
6517 /* ldrt/strt always use post-indexed addressing, so if the base is
6518 the same as Rd, we warn. */
6519 if (conflict_reg == reg)
6520 as_warn (_("%s register same as write-back base"),
6521 ((inst.instruction & LOAD_BIT)
6522 ? _("destination") : _("source")));
6524 skip_whitespace (str);
6530 if (skip_past_comma (&str) == SUCCESS)
6532 /* [Rn],... (post inc) */
6533 if (ldst_extend (&str) == FAIL)
6539 skip_whitespace (str);
6541 /* Skip a write-back '!'. */
6545 inst.instruction |= INDEX_UP;
6550 inst.error = _("post-indexed expression expected");
6556 inst.error = _("post-indexed expression expected");
6563 /* Halfword and signed-byte load/store operations. */
6566 do_ldstv4 (char * str)
6572 skip_whitespace (str);
6574 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
6577 inst.error = BAD_ARGS;
6581 if (skip_past_comma (& str) == FAIL)
6583 inst.error = _("address expected");
6593 skip_whitespace (str);
6595 if ((reg = reg_required_here (&str, 16)) == FAIL)
6598 /* Conflicts can occur on stores as well as loads. */
6599 conflict_reg = (conflict_reg == reg);
6601 skip_whitespace (str);
6607 if (skip_past_comma (&str) == SUCCESS)
6609 /* [Rn],... (post inc) */
6610 if (ldst_extend_v4 (&str) == FAIL)
6613 as_warn (_("%s register same as write-back base"),
6614 ((inst.instruction & LOAD_BIT)
6615 ? _("destination") : _("source")));
6620 inst.instruction |= HWOFFSET_IMM;
6622 skip_whitespace (str);
6627 as_warn (_("%s register same as write-back base"),
6628 ((inst.instruction & LOAD_BIT)
6629 ? _("destination") : _("source")));
6631 inst.instruction |= WRITE_BACK;
6634 inst.instruction |= INDEX_UP;
6641 if (skip_past_comma (&str) == FAIL)
6643 inst.error = _("pre-indexed expression expected");
6648 if (ldst_extend_v4 (&str) == FAIL)
6651 skip_whitespace (str);
6655 inst.error = _("missing ]");
6659 skip_whitespace (str);
6664 as_warn (_("%s register same as write-back base"),
6665 ((inst.instruction & LOAD_BIT)
6666 ? _("destination") : _("source")));
6668 inst.instruction |= WRITE_BACK;
6672 else if (*str == '=')
6674 if ((inst.instruction & LOAD_BIT) == 0)
6676 inst.error = _("invalid pseudo operation");
6680 /* XXX Does this work correctly for half-word/byte ops? */
6681 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6684 skip_whitespace (str);
6686 if (my_get_expression (&inst.reloc.exp, &str))
6689 if (inst.reloc.exp.X_op != O_constant
6690 && inst.reloc.exp.X_op != O_symbol)
6692 inst.error = _("constant expression expected");
6696 if (inst.reloc.exp.X_op == O_constant)
6698 value = validate_immediate (inst.reloc.exp.X_add_number);
6702 /* This can be done with a mov instruction. */
6703 inst.instruction &= LITERAL_MASK;
6704 inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
6705 inst.instruction |= value & 0xfff;
6710 value = validate_immediate (~ inst.reloc.exp.X_add_number);
6714 /* This can be done with a mvn instruction. */
6715 inst.instruction &= LITERAL_MASK;
6716 inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT);
6717 inst.instruction |= value & 0xfff;
6723 /* Insert into literal pool. */
6724 if (add_to_lit_pool () == FAIL)
6727 inst.error = _("literal pool insertion failed");
6731 /* Change the instruction exp to point to the pool. */
6732 inst.instruction |= HWOFFSET_IMM;
6733 inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
6734 inst.reloc.pc_rel = 1;
6735 inst.instruction |= (REG_PC << 16);
6740 if (my_get_expression (&inst.reloc.exp, &str))
6743 inst.instruction |= HWOFFSET_IMM;
6744 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
6746 /* PC rel adjust. */
6747 inst.reloc.exp.X_add_number -= 8;
6749 inst.reloc.pc_rel = 1;
6750 inst.instruction |= (REG_PC << 16);
6754 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
6759 do_ldsttv4 (char * str)
6763 skip_whitespace (str);
6765 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
6768 inst.error = BAD_ARGS;
6772 if (skip_past_comma (& str) == FAIL)
6774 inst.error = _("address expected");
6784 skip_whitespace (str);
6786 if ((reg = reg_required_here (&str, 16)) == FAIL)
6789 /* ldrt/strt always use post-indexed addressing, so if the base is
6790 the same as Rd, we warn. */
6791 if (conflict_reg == reg)
6792 as_warn (_("%s register same as write-back base"),
6793 ((inst.instruction & LOAD_BIT)
6794 ? _("destination") : _("source")));
6796 skip_whitespace (str);
6802 if (skip_past_comma (&str) == SUCCESS)
6804 /* [Rn],... (post inc) */
6805 if (ldst_extend_v4 (&str) == FAIL)
6811 skip_whitespace (str);
6813 /* Skip a write-back '!'. */
6817 inst.instruction |= (INDEX_UP|HWOFFSET_IMM);
6822 inst.error = _("post-indexed expression expected");
6828 inst.error = _("post-indexed expression expected");
6837 reg_list (char ** strp)
6839 char * str = * strp;
6843 /* We come back here if we get ranges concatenated by '+' or '|'. */
6858 skip_whitespace (str);
6860 if ((reg = reg_required_here (& str, -1)) == FAIL)
6869 inst.error = _("bad range in register list");
6873 for (i = cur_reg + 1; i < reg; i++)
6875 if (range & (1 << i))
6877 (_("Warning: duplicated register (r%d) in register list"),
6885 if (range & (1 << reg))
6886 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
6888 else if (reg <= cur_reg)
6889 as_tsktsk (_("Warning: register range not in ascending order"));
6894 while (skip_past_comma (&str) != FAIL
6895 || (in_range = 1, *str++ == '-'));
6897 skip_whitespace (str);
6901 inst.error = _("missing `}'");
6909 if (my_get_expression (&expr, &str))
6912 if (expr.X_op == O_constant)
6914 if (expr.X_add_number
6915 != (expr.X_add_number & 0x0000ffff))
6917 inst.error = _("invalid register mask");
6921 if ((range & expr.X_add_number) != 0)
6923 int regno = range & expr.X_add_number;
6926 regno = (1 << regno) - 1;
6928 (_("Warning: duplicated register (r%d) in register list"),
6932 range |= expr.X_add_number;
6936 if (inst.reloc.type != 0)
6938 inst.error = _("expression too complex");
6942 memcpy (&inst.reloc.exp, &expr, sizeof (expressionS));
6943 inst.reloc.type = BFD_RELOC_ARM_MULTI;
6944 inst.reloc.pc_rel = 0;
6948 skip_whitespace (str);
6950 if (*str == '|' || *str == '+')
6956 while (another_range);
6963 do_ldmstm (char * str)
6968 skip_whitespace (str);
6970 if ((base_reg = reg_required_here (&str, 16)) == FAIL)
6973 if (base_reg == REG_PC)
6975 inst.error = _("r15 not allowed as base register");
6979 skip_whitespace (str);
6983 inst.instruction |= WRITE_BACK;
6987 if (skip_past_comma (&str) == FAIL
6988 || (range = reg_list (&str)) == FAIL)
6991 inst.error = BAD_ARGS;
6998 inst.instruction |= LDM_TYPE_2_OR_3;
7001 if (inst.instruction & WRITE_BACK)
7003 /* Check for unpredictable uses of writeback. */
7004 if (inst.instruction & LOAD_BIT)
7006 /* Not allowed in LDM type 2. */
7007 if ((inst.instruction & LDM_TYPE_2_OR_3)
7008 && ((range & (1 << REG_PC)) == 0))
7009 as_warn (_("writeback of base register is UNPREDICTABLE"));
7010 /* Only allowed if base reg not in list for other types. */
7011 else if (range & (1 << base_reg))
7012 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
7016 /* Not allowed for type 2. */
7017 if (inst.instruction & LDM_TYPE_2_OR_3)
7018 as_warn (_("writeback of base register is UNPREDICTABLE"));
7019 /* Only allowed if base reg not in list, or first in list. */
7020 else if ((range & (1 << base_reg))
7021 && (range & ((1 << base_reg) - 1)))
7022 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
7026 inst.instruction |= range;
7033 skip_whitespace (str);
7035 /* Allow optional leading '#'. */
7036 if (is_immediate_prefix (*str))
7039 if (my_get_expression (& inst.reloc.exp, & str))
7042 inst.reloc.type = BFD_RELOC_ARM_SMI;
7043 inst.reloc.pc_rel = 0;
7050 skip_whitespace (str);
7052 /* Allow optional leading '#'. */
7053 if (is_immediate_prefix (*str))
7056 if (my_get_expression (& inst.reloc.exp, & str))
7059 inst.reloc.type = BFD_RELOC_ARM_SWI;
7060 inst.reloc.pc_rel = 0;
7065 do_swap (char * str)
7069 skip_whitespace (str);
7071 if ((reg = reg_required_here (&str, 12)) == FAIL)
7076 inst.error = _("r15 not allowed in swap");
7080 if (skip_past_comma (&str) == FAIL
7081 || (reg = reg_required_here (&str, 0)) == FAIL)
7084 inst.error = BAD_ARGS;
7090 inst.error = _("r15 not allowed in swap");
7094 if (skip_past_comma (&str) == FAIL
7097 inst.error = BAD_ARGS;
7101 skip_whitespace (str);
7103 if ((reg = reg_required_here (&str, 16)) == FAIL)
7108 inst.error = BAD_PC;
7112 skip_whitespace (str);
7116 inst.error = _("missing ]");
7124 do_branch (char * str)
7126 if (my_get_expression (&inst.reloc.exp, &str))
7133 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
7134 required for the instruction. */
7136 /* arm_parse_reloc () works on input_line_pointer.
7137 We actually want to parse the operands to the branch instruction
7138 passed in 'str'. Save the input pointer and restore it later. */
7139 save_in = input_line_pointer;
7140 input_line_pointer = str;
7141 if (inst.reloc.exp.X_op == O_symbol
7143 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
7145 inst.reloc.type = BFD_RELOC_ARM_PLT32;
7146 inst.reloc.pc_rel = 0;
7147 /* Modify str to point to after parsed operands, otherwise
7148 end_of_line() will complain about the (PLT) left in str. */
7149 str = input_line_pointer;
7153 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
7154 inst.reloc.pc_rel = 1;
7156 input_line_pointer = save_in;
7159 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
7160 inst.reloc.pc_rel = 1;
7161 #endif /* OBJ_ELF */
7169 /* Co-processor data operation.
7170 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
7171 skip_whitespace (str);
7173 if (co_proc_number (&str) == FAIL)
7176 inst.error = BAD_ARGS;
7180 if (skip_past_comma (&str) == FAIL
7181 || cp_opc_expr (&str, 20,4) == FAIL)
7184 inst.error = BAD_ARGS;
7188 if (skip_past_comma (&str) == FAIL
7189 || cp_reg_required_here (&str, 12) == FAIL)
7192 inst.error = BAD_ARGS;
7196 if (skip_past_comma (&str) == FAIL
7197 || cp_reg_required_here (&str, 16) == FAIL)
7200 inst.error = BAD_ARGS;
7204 if (skip_past_comma (&str) == FAIL
7205 || cp_reg_required_here (&str, 0) == FAIL)
7208 inst.error = BAD_ARGS;
7212 if (skip_past_comma (&str) == SUCCESS)
7214 if (cp_opc_expr (&str, 5, 3) == FAIL)
7217 inst.error = BAD_ARGS;
7226 do_lstc (char * str)
7228 /* Co-processor register load/store.
7229 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
7231 skip_whitespace (str);
7233 if (co_proc_number (&str) == FAIL)
7236 inst.error = BAD_ARGS;
7240 if (skip_past_comma (&str) == FAIL
7241 || cp_reg_required_here (&str, 12) == FAIL)
7244 inst.error = BAD_ARGS;
7248 if (skip_past_comma (&str) == FAIL
7249 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
7252 inst.error = BAD_ARGS;
7260 do_co_reg (char * str)
7262 /* Co-processor register transfer.
7263 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
7265 skip_whitespace (str);
7267 if (co_proc_number (&str) == FAIL)
7270 inst.error = BAD_ARGS;
7274 if (skip_past_comma (&str) == FAIL
7275 || cp_opc_expr (&str, 21, 3) == FAIL)
7278 inst.error = BAD_ARGS;
7282 if (skip_past_comma (&str) == FAIL
7283 || reg_required_here (&str, 12) == FAIL)
7286 inst.error = BAD_ARGS;
7290 if (skip_past_comma (&str) == FAIL
7291 || cp_reg_required_here (&str, 16) == FAIL)
7294 inst.error = BAD_ARGS;
7298 if (skip_past_comma (&str) == FAIL
7299 || cp_reg_required_here (&str, 0) == FAIL)
7302 inst.error = BAD_ARGS;
7306 if (skip_past_comma (&str) == SUCCESS)
7308 if (cp_opc_expr (&str, 5, 3) == FAIL)
7311 inst.error = BAD_ARGS;
7320 do_fpa_ctrl (char * str)
7322 /* FP control registers.
7323 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
7325 skip_whitespace (str);
7327 if (reg_required_here (&str, 12) == FAIL)
7330 inst.error = BAD_ARGS;
7338 do_fpa_ldst (char * str)
7340 skip_whitespace (str);
7342 if (fp_reg_required_here (&str, 12) == FAIL)
7345 inst.error = BAD_ARGS;
7349 if (skip_past_comma (&str) == FAIL
7350 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
7353 inst.error = BAD_ARGS;
7361 do_fpa_ldmstm (char * str)
7365 skip_whitespace (str);
7367 if (fp_reg_required_here (&str, 12) == FAIL)
7370 inst.error = BAD_ARGS;
7374 /* Get Number of registers to transfer. */
7375 if (skip_past_comma (&str) == FAIL
7376 || my_get_expression (&inst.reloc.exp, &str))
7379 inst.error = _("constant expression expected");
7383 if (inst.reloc.exp.X_op != O_constant)
7385 inst.error = _("constant value required for number of registers");
7389 num_regs = inst.reloc.exp.X_add_number;
7391 if (num_regs < 1 || num_regs > 4)
7393 inst.error = _("number of registers must be in the range [1:4]");
7400 inst.instruction |= CP_T_X;
7403 inst.instruction |= CP_T_Y;
7406 inst.instruction |= CP_T_Y | CP_T_X;
7414 if (inst.instruction & (CP_T_Pre | CP_T_UD)) /* ea/fd format. */
7420 /* The instruction specified "ea" or "fd", so we can only accept
7421 [Rn]{!}. The instruction does not really support stacking or
7422 unstacking, so we have to emulate these by setting appropriate
7423 bits and offsets. */
7424 if (skip_past_comma (&str) == FAIL
7428 inst.error = BAD_ARGS;
7433 skip_whitespace (str);
7435 if ((reg = reg_required_here (&str, 16)) == FAIL)
7438 skip_whitespace (str);
7442 inst.error = BAD_ARGS;
7454 _("r15 not allowed as base register with write-back");
7461 if (inst.instruction & CP_T_Pre)
7463 /* Pre-decrement. */
7464 offset = 3 * num_regs;
7466 inst.instruction |= CP_T_WB;
7470 /* Post-increment. */
7473 inst.instruction |= CP_T_WB;
7474 offset = 3 * num_regs;
7478 /* No write-back, so convert this into a standard pre-increment
7479 instruction -- aesthetically more pleasing. */
7480 inst.instruction |= CP_T_Pre | CP_T_UD;
7485 inst.instruction |= offset;
7487 else if (skip_past_comma (&str) == FAIL
7488 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
7491 inst.error = BAD_ARGS;
7499 do_fpa_dyadic (char * str)
7501 skip_whitespace (str);
7503 if (fp_reg_required_here (&str, 12) == FAIL)
7506 inst.error = BAD_ARGS;
7510 if (skip_past_comma (&str) == FAIL
7511 || fp_reg_required_here (&str, 16) == FAIL)
7514 inst.error = BAD_ARGS;
7518 if (skip_past_comma (&str) == FAIL
7519 || fp_op2 (&str) == FAIL)
7522 inst.error = BAD_ARGS;
7530 do_fpa_monadic (char * str)
7532 skip_whitespace (str);
7534 if (fp_reg_required_here (&str, 12) == FAIL)
7537 inst.error = BAD_ARGS;
7541 if (skip_past_comma (&str) == FAIL
7542 || fp_op2 (&str) == FAIL)
7545 inst.error = BAD_ARGS;
7553 do_fpa_cmp (char * str)
7555 skip_whitespace (str);
7557 if (fp_reg_required_here (&str, 16) == FAIL)
7560 inst.error = BAD_ARGS;
7564 if (skip_past_comma (&str) == FAIL
7565 || fp_op2 (&str) == FAIL)
7568 inst.error = BAD_ARGS;
7576 do_fpa_from_reg (char * str)
7578 skip_whitespace (str);
7580 if (fp_reg_required_here (&str, 16) == FAIL)
7583 inst.error = BAD_ARGS;
7587 if (skip_past_comma (&str) == FAIL
7588 || reg_required_here (&str, 12) == FAIL)
7591 inst.error = BAD_ARGS;
7599 do_fpa_to_reg (char * str)
7601 skip_whitespace (str);
7603 if (reg_required_here (&str, 12) == FAIL)
7606 if (skip_past_comma (&str) == FAIL
7607 || fp_reg_required_here (&str, 0) == FAIL)
7610 inst.error = BAD_ARGS;
7617 /* Encode a VFP SP register number. */
7620 vfp_sp_encode_reg (int reg, enum vfp_sp_reg_pos pos)
7625 inst.instruction |= ((reg >> 1) << 12) | ((reg & 1) << 22);
7629 inst.instruction |= ((reg >> 1) << 16) | ((reg & 1) << 7);
7633 inst.instruction |= ((reg >> 1) << 0) | ((reg & 1) << 5);
7642 vfp_sp_reg_required_here (char ** str,
7643 enum vfp_sp_reg_pos pos)
7646 char * start = *str;
7648 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab)) != FAIL)
7650 vfp_sp_encode_reg (reg, pos);
7654 /* In the few cases where we might be able to accept something else
7655 this error can be overridden. */
7656 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
7658 /* Restore the start point. */
7664 vfp_dp_reg_required_here (char ** str,
7665 enum vfp_dp_reg_pos pos)
7668 char * start = *str;
7670 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab)) != FAIL)
7675 inst.instruction |= reg << 12;
7679 inst.instruction |= reg << 16;
7683 inst.instruction |= reg << 0;
7692 /* In the few cases where we might be able to accept something else
7693 this error can be overridden. */
7694 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
7696 /* Restore the start point. */
7702 do_vfp_sp_monadic (char * str)
7704 skip_whitespace (str);
7706 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7709 if (skip_past_comma (&str) == FAIL
7710 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
7713 inst.error = BAD_ARGS;
7721 do_vfp_dp_monadic (char * str)
7723 skip_whitespace (str);
7725 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7728 if (skip_past_comma (&str) == FAIL
7729 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7732 inst.error = BAD_ARGS;
7740 do_vfp_sp_dyadic (char * str)
7742 skip_whitespace (str);
7744 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7747 if (skip_past_comma (&str) == FAIL
7748 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL
7749 || skip_past_comma (&str) == FAIL
7750 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
7753 inst.error = BAD_ARGS;
7761 do_vfp_dp_dyadic (char * str)
7763 skip_whitespace (str);
7765 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7768 if (skip_past_comma (&str) == FAIL
7769 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL
7770 || skip_past_comma (&str) == FAIL
7771 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7774 inst.error = BAD_ARGS;
7782 do_vfp_reg_from_sp (char * str)
7784 skip_whitespace (str);
7786 if (reg_required_here (&str, 12) == FAIL)
7789 if (skip_past_comma (&str) == FAIL
7790 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
7793 inst.error = BAD_ARGS;
7800 /* Parse a VFP register list. If the string is invalid return FAIL.
7801 Otherwise return the number of registers, and set PBASE to the first
7802 register. Double precision registers are matched if DP is nonzero. */
7805 vfp_parse_reg_list (char **str, int *pbase, int dp)
7813 unsigned long mask = 0;
7820 skip_whitespace (*str);
7824 regtype = REG_TYPE_DN;
7829 regtype = REG_TYPE_SN;
7833 base_reg = max_regs;
7837 new_base = arm_reg_parse (str, all_reg_maps[regtype].htab);
7838 if (new_base == FAIL)
7840 inst.error = _(all_reg_maps[regtype].expected);
7844 if (new_base < base_reg)
7845 base_reg = new_base;
7847 if (mask & (1 << new_base))
7849 inst.error = _("invalid register list");
7853 if ((mask >> new_base) != 0 && ! warned)
7855 as_tsktsk (_("register list not in ascending order"));
7859 mask |= 1 << new_base;
7862 skip_whitespace (*str);
7864 if (**str == '-') /* We have the start of a range expression */
7871 = arm_reg_parse (str, all_reg_maps[regtype].htab))
7874 inst.error = _(all_reg_maps[regtype].expected);
7878 if (high_range <= new_base)
7880 inst.error = _("register range not in ascending order");
7884 for (new_base++; new_base <= high_range; new_base++)
7886 if (mask & (1 << new_base))
7888 inst.error = _("invalid register list");
7892 mask |= 1 << new_base;
7897 while (skip_past_comma (str) != FAIL);
7901 /* Sanity check -- should have raised a parse error above. */
7902 if (count == 0 || count > max_regs)
7907 /* Final test -- the registers must be consecutive. */
7909 for (i = 0; i < count; i++)
7911 if ((mask & (1u << i)) == 0)
7913 inst.error = _("non-contiguous register range");
7922 do_vfp_reg2_from_sp2 (char * str)
7926 skip_whitespace (str);
7928 if (reg_required_here (&str, 12) == FAIL
7929 || skip_past_comma (&str) == FAIL
7930 || reg_required_here (&str, 16) == FAIL
7931 || skip_past_comma (&str) == FAIL)
7934 inst.error = BAD_ARGS;
7938 /* We require exactly two consecutive SP registers. */
7939 if (vfp_parse_reg_list (&str, ®, 0) != 2)
7942 inst.error = _("only two consecutive VFP SP registers allowed here");
7944 vfp_sp_encode_reg (reg, VFP_REG_Sm);
7950 do_vfp_sp_from_reg (char * str)
7952 skip_whitespace (str);
7954 if (vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
7957 if (skip_past_comma (&str) == FAIL
7958 || reg_required_here (&str, 12) == FAIL)
7961 inst.error = BAD_ARGS;
7969 do_vfp_sp2_from_reg2 (char * str)
7973 skip_whitespace (str);
7975 /* We require exactly two consecutive SP registers. */
7976 if (vfp_parse_reg_list (&str, ®, 0) != 2)
7979 inst.error = _("only two consecutive VFP SP registers allowed here");
7981 vfp_sp_encode_reg (reg, VFP_REG_Sm);
7983 if (skip_past_comma (&str) == FAIL
7984 || reg_required_here (&str, 12) == FAIL
7985 || skip_past_comma (&str) == FAIL
7986 || reg_required_here (&str, 16) == FAIL)
7989 inst.error = BAD_ARGS;
7997 do_vfp_reg_from_dp (char * str)
7999 skip_whitespace (str);
8001 if (reg_required_here (&str, 12) == FAIL)
8004 if (skip_past_comma (&str) == FAIL
8005 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
8008 inst.error = BAD_ARGS;
8016 do_vfp_reg2_from_dp (char * str)
8018 skip_whitespace (str);
8020 if (reg_required_here (&str, 12) == FAIL)
8023 if (skip_past_comma (&str) == FAIL
8024 || reg_required_here (&str, 16) == FAIL
8025 || skip_past_comma (&str) == FAIL
8026 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8029 inst.error = BAD_ARGS;
8037 do_vfp_dp_from_reg (char * str)
8039 skip_whitespace (str);
8041 if (vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
8044 if (skip_past_comma (&str) == FAIL
8045 || reg_required_here (&str, 12) == FAIL)
8048 inst.error = BAD_ARGS;
8056 do_vfp_dp_from_reg2 (char * str)
8058 skip_whitespace (str);
8060 if (vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8063 if (skip_past_comma (&str) == FAIL
8064 || reg_required_here (&str, 12) == FAIL
8065 || skip_past_comma (&str) == FAIL
8066 || reg_required_here (&str, 16) == FAIL)
8069 inst.error = BAD_ARGS;
8076 static const struct vfp_reg *
8077 vfp_psr_parse (char ** str)
8082 const struct vfp_reg *vreg;
8086 /* Find the end of the current token. */
8091 while (ISALPHA (c));
8096 for (vreg = vfp_regs + 0;
8097 vreg < vfp_regs + sizeof (vfp_regs) / sizeof (struct vfp_reg);
8100 if (streq (start, vreg->name))
8113 vfp_psr_required_here (char ** str)
8116 const struct vfp_reg *vreg;
8118 vreg = vfp_psr_parse (str);
8122 inst.instruction |= vreg->regno;
8126 inst.error = _("VFP system register expected");
8133 do_vfp_reg_from_ctrl (char * str)
8135 skip_whitespace (str);
8137 if (reg_required_here (&str, 12) == FAIL)
8140 if (skip_past_comma (&str) == FAIL
8141 || vfp_psr_required_here (&str) == FAIL)
8144 inst.error = BAD_ARGS;
8152 do_vfp_ctrl_from_reg (char * str)
8154 skip_whitespace (str);
8156 if (vfp_psr_required_here (&str) == FAIL)
8159 if (skip_past_comma (&str) == FAIL
8160 || reg_required_here (&str, 12) == FAIL)
8163 inst.error = BAD_ARGS;
8171 do_vfp_sp_ldst (char * str)
8173 skip_whitespace (str);
8175 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8178 inst.error = BAD_ARGS;
8182 if (skip_past_comma (&str) == FAIL
8183 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
8186 inst.error = BAD_ARGS;
8194 do_vfp_dp_ldst (char * str)
8196 skip_whitespace (str);
8198 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8201 inst.error = BAD_ARGS;
8205 if (skip_past_comma (&str) == FAIL
8206 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
8209 inst.error = BAD_ARGS;
8218 vfp_sp_ldstm (char * str, enum vfp_ldstm_type ldstm_type)
8223 skip_whitespace (str);
8225 if (reg_required_here (&str, 16) == FAIL)
8228 skip_whitespace (str);
8232 inst.instruction |= WRITE_BACK;
8235 else if (ldstm_type != VFP_LDSTMIA)
8237 inst.error = _("this addressing mode requires base-register writeback");
8241 if (skip_past_comma (&str) == FAIL
8242 || (count = vfp_parse_reg_list (&str, ®, 0)) == FAIL)
8245 inst.error = BAD_ARGS;
8248 vfp_sp_encode_reg (reg, VFP_REG_Sd);
8250 inst.instruction |= count;
8255 vfp_dp_ldstm (char * str, enum vfp_ldstm_type ldstm_type)
8260 skip_whitespace (str);
8262 if (reg_required_here (&str, 16) == FAIL)
8265 skip_whitespace (str);
8269 inst.instruction |= WRITE_BACK;
8272 else if (ldstm_type != VFP_LDSTMIA && ldstm_type != VFP_LDSTMIAX)
8274 inst.error = _("this addressing mode requires base-register writeback");
8278 if (skip_past_comma (&str) == FAIL
8279 || (count = vfp_parse_reg_list (&str, ®, 1)) == FAIL)
8282 inst.error = BAD_ARGS;
8287 if (ldstm_type == VFP_LDSTMIAX || ldstm_type == VFP_LDSTMDBX)
8290 inst.instruction |= (reg << 12) | count;
8295 do_vfp_sp_ldstmia (char * str)
8297 vfp_sp_ldstm (str, VFP_LDSTMIA);
8301 do_vfp_sp_ldstmdb (char * str)
8303 vfp_sp_ldstm (str, VFP_LDSTMDB);
8307 do_vfp_dp_ldstmia (char * str)
8309 vfp_dp_ldstm (str, VFP_LDSTMIA);
8313 do_vfp_dp_ldstmdb (char * str)
8315 vfp_dp_ldstm (str, VFP_LDSTMDB);
8319 do_vfp_xp_ldstmia (char *str)
8321 vfp_dp_ldstm (str, VFP_LDSTMIAX);
8325 do_vfp_xp_ldstmdb (char * str)
8327 vfp_dp_ldstm (str, VFP_LDSTMDBX);
8331 do_vfp_sp_compare_z (char * str)
8333 skip_whitespace (str);
8335 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8338 inst.error = BAD_ARGS;
8346 do_vfp_dp_compare_z (char * str)
8348 skip_whitespace (str);
8350 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8353 inst.error = BAD_ARGS;
8361 do_vfp_dp_sp_cvt (char * str)
8363 skip_whitespace (str);
8365 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8368 if (skip_past_comma (&str) == FAIL
8369 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
8372 inst.error = BAD_ARGS;
8380 do_vfp_sp_dp_cvt (char * str)
8382 skip_whitespace (str);
8384 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8387 if (skip_past_comma (&str) == FAIL
8388 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8391 inst.error = BAD_ARGS;
8398 /* Thumb specific routines. */
8400 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
8404 thumb_add_sub (char * str, int subtract)
8406 int Rd, Rs, Rn = FAIL;
8408 skip_whitespace (str);
8410 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
8411 || skip_past_comma (&str) == FAIL)
8414 inst.error = BAD_ARGS;
8418 if (is_immediate_prefix (*str))
8422 if (my_get_expression (&inst.reloc.exp, &str))
8427 if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8430 if (skip_past_comma (&str) == FAIL)
8432 /* Two operand format, shuffle the registers
8433 and pretend there are 3. */
8437 else if (is_immediate_prefix (*str))
8440 if (my_get_expression (&inst.reloc.exp, &str))
8443 else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8447 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8448 for the latter case, EXPR contains the immediate that was found. */
8451 /* All register format. */
8452 if (Rd > 7 || Rs > 7 || Rn > 7)
8456 inst.error = _("dest and source1 must be the same register");
8460 /* Can't do this for SUB. */
8463 inst.error = _("subtract valid only on lo regs");
8467 inst.instruction = (T_OPCODE_ADD_HI
8468 | (Rd > 7 ? THUMB_H1 : 0)
8469 | (Rn > 7 ? THUMB_H2 : 0));
8470 inst.instruction |= (Rd & 7) | ((Rn & 7) << 3);
8474 inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3;
8475 inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
8480 /* Immediate expression, now things start to get nasty. */
8482 /* First deal with HI regs, only very restricted cases allowed:
8483 Adjusting SP, and using PC or SP to get an address. */
8484 if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP))
8485 || (Rs > 7 && Rs != REG_SP && Rs != REG_PC))
8487 inst.error = _("invalid Hi register with immediate");
8491 if (inst.reloc.exp.X_op != O_constant)
8493 /* Value isn't known yet, all we can do is store all the fragments
8494 we know about in the instruction and let the reloc hacking
8496 inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs;
8497 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
8501 int offset = inst.reloc.exp.X_add_number;
8511 /* Quick check, in case offset is MIN_INT. */
8514 inst.error = _("immediate value out of range");
8518 /* Note - you cannot convert a subtract of 0 into an
8519 add of 0 because the carry flag is set differently. */
8520 else if (offset > 0)
8525 if (offset & ~0x1fc)
8527 inst.error = _("invalid immediate value for stack adjust");
8530 inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
8531 inst.instruction |= offset >> 2;
8533 else if (Rs == REG_PC || Rs == REG_SP)
8536 || (offset & ~0x3fc))
8538 inst.error = _("invalid immediate for address calculation");
8541 inst.instruction = (Rs == REG_PC ? T_OPCODE_ADD_PC
8543 inst.instruction |= (Rd << 8) | (offset >> 2);
8549 inst.error = _("immediate value out of range");
8552 inst.instruction = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
8553 inst.instruction |= (Rd << 8) | offset;
8559 inst.error = _("immediate value out of range");
8562 inst.instruction = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
8563 inst.instruction |= Rd | (Rs << 3) | (offset << 6);
8572 thumb_shift (char * str, int shift)
8574 int Rd, Rs, Rn = FAIL;
8576 skip_whitespace (str);
8578 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8579 || skip_past_comma (&str) == FAIL)
8582 inst.error = BAD_ARGS;
8586 if (is_immediate_prefix (*str))
8588 /* Two operand immediate format, set Rs to Rd. */
8591 if (my_get_expression (&inst.reloc.exp, &str))
8596 if ((Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8599 if (skip_past_comma (&str) == FAIL)
8601 /* Two operand format, shuffle the registers
8602 and pretend there are 3. */
8606 else if (is_immediate_prefix (*str))
8609 if (my_get_expression (&inst.reloc.exp, &str))
8612 else if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8616 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8617 for the latter case, EXPR contains the immediate that was found. */
8623 inst.error = _("source1 and dest must be same register");
8629 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_R; break;
8630 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_R; break;
8631 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_R; break;
8634 inst.instruction |= Rd | (Rn << 3);
8640 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_I; break;
8641 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_I; break;
8642 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_I; break;
8645 if (inst.reloc.exp.X_op != O_constant)
8647 /* Value isn't known yet, create a dummy reloc and let reloc
8648 hacking fix it up. */
8649 inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
8653 unsigned shift_value = inst.reloc.exp.X_add_number;
8655 if (shift_value > 32 || (shift_value == 32 && shift == THUMB_LSL))
8657 inst.error = _("invalid immediate for shift");
8661 /* Shifts of zero are handled by converting to LSL. */
8662 if (shift_value == 0)
8663 inst.instruction = T_OPCODE_LSL_I;
8665 /* Shifts of 32 are encoded as a shift of zero. */
8666 if (shift_value == 32)
8669 inst.instruction |= shift_value << 6;
8672 inst.instruction |= Rd | (Rs << 3);
8679 thumb_load_store (char * str, int load_store, int size)
8681 int Rd, Rb, Ro = FAIL;
8683 skip_whitespace (str);
8685 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8686 || skip_past_comma (&str) == FAIL)
8689 inst.error = BAD_ARGS;
8696 if ((Rb = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8699 if (skip_past_comma (&str) != FAIL)
8701 if (is_immediate_prefix (*str))
8704 if (my_get_expression (&inst.reloc.exp, &str))
8707 else if ((Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8712 inst.reloc.exp.X_op = O_constant;
8713 inst.reloc.exp.X_add_number = 0;
8718 inst.error = _("expected ']'");
8723 else if (*str == '=')
8725 if (load_store != THUMB_LOAD)
8727 inst.error = _("invalid pseudo operation");
8731 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
8734 skip_whitespace (str);
8736 if (my_get_expression (& inst.reloc.exp, & str))
8741 if ( inst.reloc.exp.X_op != O_constant
8742 && inst.reloc.exp.X_op != O_symbol)
8744 inst.error = "Constant expression expected";
8748 if (inst.reloc.exp.X_op == O_constant
8749 && ((inst.reloc.exp.X_add_number & ~0xFF) == 0))
8751 /* This can be done with a mov instruction. */
8753 inst.instruction = T_OPCODE_MOV_I8 | (Rd << 8);
8754 inst.instruction |= inst.reloc.exp.X_add_number;
8758 /* Insert into literal pool. */
8759 if (add_to_lit_pool () == FAIL)
8762 inst.error = "literal pool insertion failed";
8766 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8767 inst.reloc.pc_rel = 1;
8768 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
8769 /* Adjust ARM pipeline offset to Thumb. */
8770 inst.reloc.exp.X_add_number += 4;
8776 if (my_get_expression (&inst.reloc.exp, &str))
8779 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
8780 inst.reloc.pc_rel = 1;
8781 inst.reloc.exp.X_add_number -= 4; /* Pipeline offset. */
8782 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8787 if (Rb == REG_PC || Rb == REG_SP)
8789 if (size != THUMB_WORD)
8791 inst.error = _("byte or halfword not valid for base register");
8794 else if (Rb == REG_PC && load_store != THUMB_LOAD)
8796 inst.error = _("r15 based store not allowed");
8799 else if (Ro != FAIL)
8801 inst.error = _("invalid base register for register offset");
8806 inst.instruction = T_OPCODE_LDR_PC;
8807 else if (load_store == THUMB_LOAD)
8808 inst.instruction = T_OPCODE_LDR_SP;
8810 inst.instruction = T_OPCODE_STR_SP;
8812 inst.instruction |= Rd << 8;
8813 if (inst.reloc.exp.X_op == O_constant)
8815 unsigned offset = inst.reloc.exp.X_add_number;
8817 if (offset & ~0x3fc)
8819 inst.error = _("invalid offset");
8823 inst.instruction |= offset >> 2;
8826 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8830 inst.error = _("invalid base register in load/store");
8833 else if (Ro == FAIL)
8835 /* Immediate offset. */
8836 if (size == THUMB_WORD)
8837 inst.instruction = (load_store == THUMB_LOAD
8838 ? T_OPCODE_LDR_IW : T_OPCODE_STR_IW);
8839 else if (size == THUMB_HALFWORD)
8840 inst.instruction = (load_store == THUMB_LOAD
8841 ? T_OPCODE_LDR_IH : T_OPCODE_STR_IH);
8843 inst.instruction = (load_store == THUMB_LOAD
8844 ? T_OPCODE_LDR_IB : T_OPCODE_STR_IB);
8846 inst.instruction |= Rd | (Rb << 3);
8848 if (inst.reloc.exp.X_op == O_constant)
8850 unsigned offset = inst.reloc.exp.X_add_number;
8852 if (offset & ~(0x1f << size))
8854 inst.error = _("invalid offset");
8857 inst.instruction |= (offset >> size) << 6;
8860 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8864 /* Register offset. */
8865 if (size == THUMB_WORD)
8866 inst.instruction = (load_store == THUMB_LOAD
8867 ? T_OPCODE_LDR_RW : T_OPCODE_STR_RW);
8868 else if (size == THUMB_HALFWORD)
8869 inst.instruction = (load_store == THUMB_LOAD
8870 ? T_OPCODE_LDR_RH : T_OPCODE_STR_RH);
8872 inst.instruction = (load_store == THUMB_LOAD
8873 ? T_OPCODE_LDR_RB : T_OPCODE_STR_RB);
8875 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
8881 /* A register must be given at this point.
8883 Shift is the place to put it in inst.instruction.
8885 Restores input start point on err.
8886 Returns the reg#, or FAIL. */
8889 mav_reg_required_here (char ** str, int shift, enum arm_reg_type regtype)
8894 if ((reg = arm_reg_parse (str, all_reg_maps[regtype].htab)) != FAIL)
8897 inst.instruction |= reg << shift;
8902 /* Restore the start point. */
8905 /* Try generic coprocessor name if applicable. */
8906 if (regtype == REG_TYPE_MVF ||
8907 regtype == REG_TYPE_MVD ||
8908 regtype == REG_TYPE_MVFX ||
8909 regtype == REG_TYPE_MVDX)
8911 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
8914 inst.instruction |= reg << shift;
8919 /* Restore the start point. */
8923 /* In the few cases where we might be able to accept something else
8924 this error can be overridden. */
8925 inst.error = _(all_reg_maps[regtype].expected);
8930 /* Cirrus Maverick Instructions. */
8932 /* Isnsn like "foo X,Y". */
8935 do_mav_binops (char * str,
8937 enum arm_reg_type reg0,
8938 enum arm_reg_type reg1)
8942 shift0 = mode & 0xff;
8943 shift1 = (mode >> 8) & 0xff;
8945 skip_whitespace (str);
8947 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
8948 || skip_past_comma (&str) == FAIL
8949 || mav_reg_required_here (&str, shift1, reg1) == FAIL)
8952 inst.error = BAD_ARGS;
8958 /* Isnsn like "foo X,Y,Z". */
8961 do_mav_triple (char * str,
8963 enum arm_reg_type reg0,
8964 enum arm_reg_type reg1,
8965 enum arm_reg_type reg2)
8967 int shift0, shift1, shift2;
8969 shift0 = mode & 0xff;
8970 shift1 = (mode >> 8) & 0xff;
8971 shift2 = (mode >> 16) & 0xff;
8973 skip_whitespace (str);
8975 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
8976 || skip_past_comma (&str) == FAIL
8977 || mav_reg_required_here (&str, shift1, reg1) == FAIL
8978 || skip_past_comma (&str) == FAIL
8979 || mav_reg_required_here (&str, shift2, reg2) == FAIL)
8982 inst.error = BAD_ARGS;
8988 /* Wrapper functions. */
8991 do_mav_binops_1a (char * str)
8993 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVF);
8997 do_mav_binops_1b (char * str)
8999 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVD);
9003 do_mav_binops_1c (char * str)
9005 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVDX);
9009 do_mav_binops_1d (char * str)
9011 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVF);
9015 do_mav_binops_1e (char * str)
9017 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVD);
9021 do_mav_binops_1f (char * str)
9023 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVF);
9027 do_mav_binops_1g (char * str)
9029 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVD);
9033 do_mav_binops_1h (char * str)
9035 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVFX);
9039 do_mav_binops_1i (char * str)
9041 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVFX);
9045 do_mav_binops_1j (char * str)
9047 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVDX);
9051 do_mav_binops_1k (char * str)
9053 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVDX);
9057 do_mav_binops_1l (char * str)
9059 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVF);
9063 do_mav_binops_1m (char * str)
9065 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVD);
9069 do_mav_binops_1n (char * str)
9071 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVFX);
9075 do_mav_binops_1o (char * str)
9077 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVDX, REG_TYPE_MVDX);
9081 do_mav_binops_2a (char * str)
9083 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVF, REG_TYPE_RN);
9087 do_mav_binops_2b (char * str)
9089 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVD, REG_TYPE_RN);
9093 do_mav_binops_2c (char * str)
9095 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVDX, REG_TYPE_RN);
9099 do_mav_binops_3a (char * str)
9101 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVFX);
9105 do_mav_binops_3b (char * str)
9107 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVFX, REG_TYPE_MVAX);
9111 do_mav_binops_3c (char * str)
9113 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVDX);
9117 do_mav_binops_3d (char * str)
9119 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVDX, REG_TYPE_MVAX);
9123 do_mav_triple_4a (char * str)
9125 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_RN);
9129 do_mav_triple_4b (char * str)
9131 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_RN);
9135 do_mav_triple_5a (char * str)
9137 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVF, REG_TYPE_MVF);
9141 do_mav_triple_5b (char * str)
9143 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVD, REG_TYPE_MVD);
9147 do_mav_triple_5c (char * str)
9149 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVFX, REG_TYPE_MVFX);
9153 do_mav_triple_5d (char * str)
9155 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVDX, REG_TYPE_MVDX);
9159 do_mav_triple_5e (char * str)
9161 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVF, REG_TYPE_MVF, REG_TYPE_MVF);
9165 do_mav_triple_5f (char * str)
9167 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVD, REG_TYPE_MVD, REG_TYPE_MVD);
9171 do_mav_triple_5g (char * str)
9173 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_MVFX);
9177 do_mav_triple_5h (char * str)
9179 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_MVDX);
9182 /* Isnsn like "foo W,X,Y,Z".
9183 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
9186 do_mav_quad (char * str,
9188 enum arm_reg_type reg0,
9189 enum arm_reg_type reg1,
9190 enum arm_reg_type reg2,
9191 enum arm_reg_type reg3)
9193 int shift0, shift1, shift2, shift3;
9195 shift0= mode & 0xff;
9196 shift1 = (mode >> 8) & 0xff;
9197 shift2 = (mode >> 16) & 0xff;
9198 shift3 = (mode >> 24) & 0xff;
9200 skip_whitespace (str);
9202 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
9203 || skip_past_comma (&str) == FAIL
9204 || mav_reg_required_here (&str, shift1, reg1) == FAIL
9205 || skip_past_comma (&str) == FAIL
9206 || mav_reg_required_here (&str, shift2, reg2) == FAIL
9207 || skip_past_comma (&str) == FAIL
9208 || mav_reg_required_here (&str, shift3, reg3) == FAIL)
9211 inst.error = BAD_ARGS;
9218 do_mav_quad_6a (char * str)
9220 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVFX, REG_TYPE_MVFX,
9225 do_mav_quad_6b (char * str)
9227 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVAX, REG_TYPE_MVFX,
9231 /* cfmvsc32<cond> DSPSC,MVDX[15:0]. */
9233 do_mav_dspsc_1 (char * str)
9235 skip_whitespace (str);
9238 if (mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL
9239 || skip_past_comma (&str) == FAIL
9240 || mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL)
9243 inst.error = BAD_ARGS;
9251 /* cfmv32sc<cond> MVDX[15:0],DSPSC. */
9253 do_mav_dspsc_2 (char * str)
9255 skip_whitespace (str);
9258 if (mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL
9259 || skip_past_comma (&str) == FAIL
9260 || mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL)
9263 inst.error = BAD_ARGS;
9271 /* Maverick shift immediate instructions.
9272 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
9273 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
9276 do_mav_shift (char * str,
9277 enum arm_reg_type reg0,
9278 enum arm_reg_type reg1)
9283 skip_whitespace (str);
9287 if (mav_reg_required_here (&str, 12, reg0) == FAIL
9288 || skip_past_comma (&str) == FAIL
9289 || mav_reg_required_here (&str, 16, reg1) == FAIL
9290 || skip_past_comma (&str) == FAIL)
9293 inst.error = BAD_ARGS;
9297 /* Calculate the immediate operand.
9298 The operand is a 7bit signed number. */
9299 skip_whitespace (str);
9304 if (!ISDIGIT (*str) && *str != '-')
9306 inst.error = _("expecting immediate, 7bit operand");
9316 for (imm = 0; *str && ISDIGIT (*str); ++str)
9317 imm = imm * 10 + *str - '0';
9321 inst.error = _("immediate out of range");
9325 /* Make negative imm's into 7bit signed numbers. */
9332 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
9333 Bits 5-7 of the insn should have bits 4-6 of the immediate.
9334 Bit 4 should be 0. */
9335 imm = (imm & 0xf) | ((imm & 0x70) << 1);
9337 inst.instruction |= imm;
9342 do_mav_shift_1 (char * str)
9344 do_mav_shift (str, REG_TYPE_MVFX, REG_TYPE_MVFX);
9348 do_mav_shift_2 (char * str)
9350 do_mav_shift (str, REG_TYPE_MVDX, REG_TYPE_MVDX);
9354 mav_parse_offset (char ** str, int * negative)
9361 skip_whitespace (p);
9374 inst.error = _("offset expected");
9378 for (offset = 0; *p && ISDIGIT (*p); ++p)
9379 offset = offset * 10 + *p - '0';
9383 inst.error = _("offset out of range");
9388 inst.error = _("offset not a multiple of 4");
9394 return *negative ? -offset : offset;
9397 /* Maverick load/store instructions.
9398 <insn><cond> CRd,[Rn,<offset>]{!}.
9399 <insn><cond> CRd,[Rn],<offset>. */
9402 do_mav_ldst (char * str, enum arm_reg_type reg0)
9404 int offset, negative;
9406 skip_whitespace (str);
9408 if (mav_reg_required_here (&str, 12, reg0) == FAIL
9409 || skip_past_comma (&str) == FAIL
9411 || reg_required_here (&str, 16) == FAIL)
9414 if (skip_past_comma (&str) == SUCCESS)
9416 /* You are here: "<offset>]{!}". */
9417 inst.instruction |= PRE_INDEX;
9419 offset = mav_parse_offset (&str, &negative);
9426 inst.error = _("missing ]");
9432 inst.instruction |= WRITE_BACK;
9438 /* You are here: "], <offset>". */
9441 inst.error = _("missing ]");
9445 if (skip_past_comma (&str) == FAIL
9446 || (offset = mav_parse_offset (&str, &negative), inst.error))
9449 inst.instruction |= CP_T_WB; /* Post indexed, set bit W. */
9455 inst.instruction |= CP_T_UD; /* Positive, so set bit U. */
9457 inst.instruction |= offset >> 2;
9463 inst.error = BAD_ARGS;
9467 do_mav_ldst_1 (char * str)
9469 do_mav_ldst (str, REG_TYPE_MVF);
9473 do_mav_ldst_2 (char * str)
9475 do_mav_ldst (str, REG_TYPE_MVD);
9479 do_mav_ldst_3 (char * str)
9481 do_mav_ldst (str, REG_TYPE_MVFX);
9485 do_mav_ldst_4 (char * str)
9487 do_mav_ldst (str, REG_TYPE_MVDX);
9491 do_t_nop (char * str)
9497 /* Handle the Format 4 instructions that do not have equivalents in other
9498 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
9502 do_t_arit (char * str)
9506 skip_whitespace (str);
9508 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9509 || skip_past_comma (&str) == FAIL
9510 || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9512 inst.error = BAD_ARGS;
9516 if (skip_past_comma (&str) != FAIL)
9518 /* Three operand format not allowed for TST, CMN, NEG and MVN.
9519 (It isn't allowed for CMP either, but that isn't handled by this
9521 if (inst.instruction == T_OPCODE_TST
9522 || inst.instruction == T_OPCODE_CMN
9523 || inst.instruction == T_OPCODE_NEG
9524 || inst.instruction == T_OPCODE_MVN)
9526 inst.error = BAD_ARGS;
9530 if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9535 inst.error = _("dest and source1 must be the same register");
9541 if (inst.instruction == T_OPCODE_MUL
9543 as_tsktsk (_("Rs and Rd must be different in MUL"));
9545 inst.instruction |= Rd | (Rs << 3);
9550 do_t_add (char * str)
9552 thumb_add_sub (str, 0);
9556 do_t_asr (char * str)
9558 thumb_shift (str, THUMB_ASR);
9562 do_t_branch9 (char * str)
9564 if (my_get_expression (&inst.reloc.exp, &str))
9566 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
9567 inst.reloc.pc_rel = 1;
9572 do_t_branch12 (char * str)
9574 if (my_get_expression (&inst.reloc.exp, &str))
9576 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
9577 inst.reloc.pc_rel = 1;
9581 /* Find the real, Thumb encoded start of a Thumb function. */
9584 find_real_start (symbolS * symbolP)
9587 const char * name = S_GET_NAME (symbolP);
9588 symbolS * new_target;
9590 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
9591 #define STUB_NAME ".real_start_of"
9596 /* Names that start with '.' are local labels, not function entry points.
9597 The compiler may generate BL instructions to these labels because it
9598 needs to perform a branch to a far away location. */
9602 real_start = malloc (strlen (name) + strlen (STUB_NAME) + 1);
9603 sprintf (real_start, "%s%s", STUB_NAME, name);
9605 new_target = symbol_find (real_start);
9607 if (new_target == NULL)
9609 as_warn ("Failed to find real start of function: %s\n", name);
9610 new_target = symbolP;
9619 do_t_branch23 (char * str)
9621 if (my_get_expression (& inst.reloc.exp, & str))
9624 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH23;
9625 inst.reloc.pc_rel = 1;
9628 /* If the destination of the branch is a defined symbol which does not have
9629 the THUMB_FUNC attribute, then we must be calling a function which has
9630 the (interfacearm) attribute. We look for the Thumb entry point to that
9631 function and change the branch to refer to that function instead. */
9632 if ( inst.reloc.exp.X_op == O_symbol
9633 && inst.reloc.exp.X_add_symbol != NULL
9634 && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
9635 && ! THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
9636 inst.reloc.exp.X_add_symbol =
9637 find_real_start (inst.reloc.exp.X_add_symbol);
9641 do_t_bx (char * str)
9645 skip_whitespace (str);
9647 if ((reg = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9650 /* This sets THUMB_H2 from the top bit of reg. */
9651 inst.instruction |= reg << 3;
9653 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
9654 should cause the alignment to be checked once it is known. This is
9655 because BX PC only works if the instruction is word aligned. */
9661 do_t_compare (char * str)
9663 thumb_mov_compare (str, THUMB_COMPARE);
9667 do_t_ldmstm (char * str)
9672 skip_whitespace (str);
9674 if ((Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9678 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
9682 if (skip_past_comma (&str) == FAIL
9683 || (range = reg_list (&str)) == FAIL)
9686 inst.error = BAD_ARGS;
9690 if (inst.reloc.type != BFD_RELOC_UNUSED)
9692 /* This really doesn't seem worth it. */
9693 inst.reloc.type = BFD_RELOC_UNUSED;
9694 inst.error = _("expression too complex");
9700 inst.error = _("only lo-regs valid in load/store multiple");
9704 inst.instruction |= (Rb << 8) | range;
9709 do_t_ldr (char * str)
9711 thumb_load_store (str, THUMB_LOAD, THUMB_WORD);
9715 do_t_ldrb (char * str)
9717 thumb_load_store (str, THUMB_LOAD, THUMB_BYTE);
9721 do_t_ldrh (char * str)
9723 thumb_load_store (str, THUMB_LOAD, THUMB_HALFWORD);
9727 do_t_lds (char * str)
9731 skip_whitespace (str);
9733 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9734 || skip_past_comma (&str) == FAIL
9736 || (Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9737 || skip_past_comma (&str) == FAIL
9738 || (Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9742 inst.error = _("syntax: ldrs[b] Rd, [Rb, Ro]");
9746 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
9751 do_t_lsl (char * str)
9753 thumb_shift (str, THUMB_LSL);
9757 do_t_lsr (char * str)
9759 thumb_shift (str, THUMB_LSR);
9763 do_t_mov (char * str)
9765 thumb_mov_compare (str, THUMB_MOVE);
9769 do_t_push_pop (char * str)
9773 skip_whitespace (str);
9775 if ((range = reg_list (&str)) == FAIL)
9778 inst.error = BAD_ARGS;
9782 if (inst.reloc.type != BFD_RELOC_UNUSED)
9784 /* This really doesn't seem worth it. */
9785 inst.reloc.type = BFD_RELOC_UNUSED;
9786 inst.error = _("expression too complex");
9792 if ((inst.instruction == T_OPCODE_PUSH
9793 && (range & ~0xff) == 1 << REG_LR)
9794 || (inst.instruction == T_OPCODE_POP
9795 && (range & ~0xff) == 1 << REG_PC))
9797 inst.instruction |= THUMB_PP_PC_LR;
9802 inst.error = _("invalid register list to push/pop instruction");
9807 inst.instruction |= range;
9812 do_t_str (char * str)
9814 thumb_load_store (str, THUMB_STORE, THUMB_WORD);
9818 do_t_strb (char * str)
9820 thumb_load_store (str, THUMB_STORE, THUMB_BYTE);
9824 do_t_strh (char * str)
9826 thumb_load_store (str, THUMB_STORE, THUMB_HALFWORD);
9830 do_t_sub (char * str)
9832 thumb_add_sub (str, 1);
9836 do_t_swi (char * str)
9838 skip_whitespace (str);
9840 if (my_get_expression (&inst.reloc.exp, &str))
9843 inst.reloc.type = BFD_RELOC_ARM_SWI;
9848 do_t_adr (char * str)
9852 /* This is a pseudo-op of the form "adr rd, label" to be converted
9853 into a relative address of the form "add rd, pc, #label-.-4". */
9854 skip_whitespace (str);
9856 /* Store Rd in temporary location inside instruction. */
9857 if ((reg = reg_required_here (&str, 4)) == FAIL
9858 || (reg > 7) /* For Thumb reg must be r0..r7. */
9859 || skip_past_comma (&str) == FAIL
9860 || my_get_expression (&inst.reloc.exp, &str))
9863 inst.error = BAD_ARGS;
9867 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
9868 inst.reloc.exp.X_add_number -= 4; /* PC relative adjust. */
9869 inst.reloc.pc_rel = 1;
9870 inst.instruction |= REG_PC; /* Rd is already placed into the instruction. */
9876 insert_reg (const struct reg_entry * r,
9877 struct hash_control * htab)
9879 int len = strlen (r->name) + 2;
9880 char * buf = xmalloc (len);
9881 char * buf2 = xmalloc (len);
9884 #ifdef REGISTER_PREFIX
9885 buf[i++] = REGISTER_PREFIX;
9888 strcpy (buf + i, r->name);
9890 for (i = 0; buf[i]; i++)
9891 buf2[i] = TOUPPER (buf[i]);
9895 hash_insert (htab, buf, (PTR) r);
9896 hash_insert (htab, buf2, (PTR) r);
9900 build_reg_hsh (struct reg_map * map)
9902 const struct reg_entry *r;
9904 if ((map->htab = hash_new ()) == NULL)
9905 as_fatal (_("virtual memory exhausted"));
9907 for (r = map->names; r->name != NULL; r++)
9908 insert_reg (r, map->htab);
9912 insert_reg_alias (char * str,
9914 struct hash_control *htab)
9917 struct reg_entry * new = xmalloc (sizeof (struct reg_entry));
9918 const char * name = xmalloc (strlen (str) + 1);
9920 strcpy ((char *) name, str);
9923 new->number = regnum;
9924 new->builtin = FALSE;
9926 error = hash_insert (htab, name, (PTR) new);
9929 as_bad (_("failed to create an alias for %s, reason: %s"),
9931 free ((char *) name);
9936 /* Look for the .req directive. This is of the form:
9938 new_register_name .req existing_register_name
9940 If we find one, or if it looks sufficiently like one that we want to
9941 handle any error here, return non-zero. Otherwise return zero. */
9944 create_register_alias (char * newname, char * p)
9950 skip_whitespace (q);
9955 if (*q && !strncmp (q, ".req ", 5))
9960 #ifndef IGNORE_OPCODE_CASE
9961 newname = original_case_string;
9963 copy_of_str = newname;
9966 skip_whitespace (q);
9968 for (r = q; *r != '\0'; r++)
9974 enum arm_reg_type new_type, old_type;
9979 old_type = arm_reg_parse_any (q);
9982 new_type = arm_reg_parse_any (newname);
9984 if (new_type == REG_TYPE_MAX)
9986 if (old_type != REG_TYPE_MAX)
9988 old_regno = arm_reg_parse (&q, all_reg_maps[old_type].htab);
9989 insert_reg_alias (newname, old_regno,
9990 all_reg_maps[old_type].htab);
9993 as_warn (_("register '%s' does not exist\n"), q);
9995 else if (old_type == REG_TYPE_MAX)
9997 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
10002 /* Do not warn about redefinitions to the same alias. */
10003 if (new_type != old_type
10004 || (arm_reg_parse (&q, all_reg_maps[old_type].htab)
10005 != arm_reg_parse (&q, all_reg_maps[new_type].htab)))
10006 as_warn (_("ignoring redefinition of register alias '%s'"),
10012 as_warn (_("ignoring incomplete .req pseuso op"));
10023 set_constant_flonums (void)
10027 for (i = 0; i < NUM_FLOAT_VALS; i++)
10028 if (atof_ieee ((char *) fp_const[i], 'x', fp_values[i]) == NULL)
10033 static const struct asm_opcode insns[] =
10035 /* Core ARM Instructions. */
10036 {"and", 0xe0000000, 3, ARM_EXT_V1, do_arit},
10037 {"ands", 0xe0100000, 3, ARM_EXT_V1, do_arit},
10038 {"eor", 0xe0200000, 3, ARM_EXT_V1, do_arit},
10039 {"eors", 0xe0300000, 3, ARM_EXT_V1, do_arit},
10040 {"sub", 0xe0400000, 3, ARM_EXT_V1, do_arit},
10041 {"subs", 0xe0500000, 3, ARM_EXT_V1, do_arit},
10042 {"rsb", 0xe0600000, 3, ARM_EXT_V1, do_arit},
10043 {"rsbs", 0xe0700000, 3, ARM_EXT_V1, do_arit},
10044 {"add", 0xe0800000, 3, ARM_EXT_V1, do_arit},
10045 {"adds", 0xe0900000, 3, ARM_EXT_V1, do_arit},
10046 {"adc", 0xe0a00000, 3, ARM_EXT_V1, do_arit},
10047 {"adcs", 0xe0b00000, 3, ARM_EXT_V1, do_arit},
10048 {"sbc", 0xe0c00000, 3, ARM_EXT_V1, do_arit},
10049 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1, do_arit},
10050 {"rsc", 0xe0e00000, 3, ARM_EXT_V1, do_arit},
10051 {"rscs", 0xe0f00000, 3, ARM_EXT_V1, do_arit},
10052 {"orr", 0xe1800000, 3, ARM_EXT_V1, do_arit},
10053 {"orrs", 0xe1900000, 3, ARM_EXT_V1, do_arit},
10054 {"bic", 0xe1c00000, 3, ARM_EXT_V1, do_arit},
10055 {"bics", 0xe1d00000, 3, ARM_EXT_V1, do_arit},
10057 {"tst", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
10058 {"tsts", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
10059 {"tstp", 0xe110f000, 3, ARM_EXT_V1, do_cmp},
10060 {"teq", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
10061 {"teqs", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
10062 {"teqp", 0xe130f000, 3, ARM_EXT_V1, do_cmp},
10063 {"cmp", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
10064 {"cmps", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
10065 {"cmpp", 0xe150f000, 3, ARM_EXT_V1, do_cmp},
10066 {"cmn", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
10067 {"cmns", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
10068 {"cmnp", 0xe170f000, 3, ARM_EXT_V1, do_cmp},
10070 {"mov", 0xe1a00000, 3, ARM_EXT_V1, do_mov},
10071 {"movs", 0xe1b00000, 3, ARM_EXT_V1, do_mov},
10072 {"mvn", 0xe1e00000, 3, ARM_EXT_V1, do_mov},
10073 {"mvns", 0xe1f00000, 3, ARM_EXT_V1, do_mov},
10075 {"ldr", 0xe4100000, 3, ARM_EXT_V1, do_ldst},
10076 {"ldrb", 0xe4500000, 3, ARM_EXT_V1, do_ldst},
10077 {"ldrt", 0xe4300000, 3, ARM_EXT_V1, do_ldstt},
10078 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1, do_ldstt},
10079 {"str", 0xe4000000, 3, ARM_EXT_V1, do_ldst},
10080 {"strb", 0xe4400000, 3, ARM_EXT_V1, do_ldst},
10081 {"strt", 0xe4200000, 3, ARM_EXT_V1, do_ldstt},
10082 {"strbt", 0xe4600000, 3, ARM_EXT_V1, do_ldstt},
10084 {"stmia", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
10085 {"stmib", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
10086 {"stmda", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
10087 {"stmdb", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
10088 {"stmfd", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
10089 {"stmfa", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
10090 {"stmea", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
10091 {"stmed", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
10093 {"ldmia", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
10094 {"ldmib", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
10095 {"ldmda", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
10096 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
10097 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
10098 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
10099 {"ldmea", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
10100 {"ldmed", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
10102 {"swi", 0xef000000, 3, ARM_EXT_V1, do_swi},
10104 /* XXX This is the wrong place to do this. Think multi-arch. */
10105 {"bl", 0xeb000000, 2, ARM_EXT_V1, do_branch},
10106 {"b", 0xea000000, 1, ARM_EXT_V1, do_branch},
10108 {"bl", 0xebfffffe, 2, ARM_EXT_V1, do_branch},
10109 {"b", 0xeafffffe, 1, ARM_EXT_V1, do_branch},
10113 {"adr", 0xe28f0000, 3, ARM_EXT_V1, do_adr},
10114 {"adrl", 0xe28f0000, 3, ARM_EXT_V1, do_adrl},
10115 {"nop", 0xe1a00000, 3, ARM_EXT_V1, do_nop},
10117 /* ARM 2 multiplies. */
10118 {"mul", 0xe0000090, 3, ARM_EXT_V2, do_mul},
10119 {"muls", 0xe0100090, 3, ARM_EXT_V2, do_mul},
10120 {"mla", 0xe0200090, 3, ARM_EXT_V2, do_mla},
10121 {"mlas", 0xe0300090, 3, ARM_EXT_V2, do_mla},
10123 /* Generic coprocessor instructions. */
10124 {"cdp", 0xee000000, 3, ARM_EXT_V2, do_cdp},
10125 {"ldc", 0xec100000, 3, ARM_EXT_V2, do_lstc},
10126 {"ldcl", 0xec500000, 3, ARM_EXT_V2, do_lstc},
10127 {"stc", 0xec000000, 3, ARM_EXT_V2, do_lstc},
10128 {"stcl", 0xec400000, 3, ARM_EXT_V2, do_lstc},
10129 {"mcr", 0xee000010, 3, ARM_EXT_V2, do_co_reg},
10130 {"mrc", 0xee100010, 3, ARM_EXT_V2, do_co_reg},
10132 /* ARM 3 - swp instructions. */
10133 {"swp", 0xe1000090, 3, ARM_EXT_V2S, do_swap},
10134 {"swpb", 0xe1400090, 3, ARM_EXT_V2S, do_swap},
10136 /* ARM 6 Status register instructions. */
10137 {"mrs", 0xe10f0000, 3, ARM_EXT_V3, do_mrs},
10138 {"msr", 0xe120f000, 3, ARM_EXT_V3, do_msr},
10139 /* ScottB: our code uses 0xe128f000 for msr.
10140 NickC: but this is wrong because the bits 16 through 19 are
10141 handled by the PSR_xxx defines above. */
10143 /* ARM 7M long multiplies. */
10144 {"smull", 0xe0c00090, 5, ARM_EXT_V3M, do_mull},
10145 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M, do_mull},
10146 {"umull", 0xe0800090, 5, ARM_EXT_V3M, do_mull},
10147 {"umulls", 0xe0900090, 5, ARM_EXT_V3M, do_mull},
10148 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M, do_mull},
10149 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M, do_mull},
10150 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M, do_mull},
10151 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M, do_mull},
10153 /* ARM Architecture 4. */
10154 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4, do_ldstv4},
10155 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4, do_ldstv4},
10156 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4, do_ldstv4},
10157 {"strh", 0xe00000b0, 3, ARM_EXT_V4, do_ldstv4},
10159 /* ARM Architecture 4T. */
10160 /* Note: bx (and blx) are required on V5, even if the processor does
10161 not support Thumb. */
10162 {"bx", 0xe12fff10, 2, ARM_EXT_V4T | ARM_EXT_V5, do_bx},
10164 /* ARM Architecture 5T. */
10165 /* Note: blx has 2 variants, so the .value is set dynamically.
10166 Only one of the variants has conditional execution. */
10167 {"blx", 0xe0000000, 3, ARM_EXT_V5, do_blx},
10168 {"clz", 0xe16f0f10, 3, ARM_EXT_V5, do_clz},
10169 {"bkpt", 0xe1200070, 0, ARM_EXT_V5, do_bkpt},
10170 {"ldc2", 0xfc100000, 0, ARM_EXT_V5, do_lstc2},
10171 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5, do_lstc2},
10172 {"stc2", 0xfc000000, 0, ARM_EXT_V5, do_lstc2},
10173 {"stc2l", 0xfc400000, 0, ARM_EXT_V5, do_lstc2},
10174 {"cdp2", 0xfe000000, 0, ARM_EXT_V5, do_cdp2},
10175 {"mcr2", 0xfe000010, 0, ARM_EXT_V5, do_co_reg2},
10176 {"mrc2", 0xfe100010, 0, ARM_EXT_V5, do_co_reg2},
10178 /* ARM Architecture 5TExP. */
10179 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP, do_smla},
10180 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP, do_smla},
10181 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP, do_smla},
10182 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP, do_smla},
10184 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP, do_smla},
10185 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP, do_smla},
10187 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP, do_smlal},
10188 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP, do_smlal},
10189 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP, do_smlal},
10190 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP, do_smlal},
10192 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP, do_smul},
10193 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP, do_smul},
10194 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP, do_smul},
10195 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP, do_smul},
10197 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP, do_smul},
10198 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP, do_smul},
10200 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP, do_qadd},
10201 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP, do_qadd},
10202 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP, do_qadd},
10203 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP, do_qadd},
10205 /* ARM Architecture 5TE. */
10206 {"pld", 0xf450f000, 0, ARM_EXT_V5E, do_pld},
10207 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E, do_ldrd},
10208 {"strd", 0xe00000f0, 3, ARM_EXT_V5E, do_ldrd},
10210 {"mcrr", 0xec400000, 4, ARM_EXT_V5E, do_co_reg2c},
10211 {"mrrc", 0xec500000, 4, ARM_EXT_V5E, do_co_reg2c},
10213 /* ARM Architecture 5TEJ. */
10214 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J, do_bxj},
10217 { "cps", 0xf1020000, 0, ARM_EXT_V6, do_cps},
10218 { "cpsie", 0xf1080000, 0, ARM_EXT_V6, do_cpsi},
10219 { "cpsid", 0xf10C0000, 0, ARM_EXT_V6, do_cpsi},
10220 { "ldrex", 0xe1900f9f, 5, ARM_EXT_V6, do_ldrex},
10221 { "mcrr2", 0xfc400000, 0, ARM_EXT_V6, do_co_reg2c},
10222 { "mrrc2", 0xfc500000, 0, ARM_EXT_V6, do_co_reg2c},
10223 { "pkhbt", 0xe6800010, 5, ARM_EXT_V6, do_pkhbt},
10224 { "pkhtb", 0xe6800050, 5, ARM_EXT_V6, do_pkhtb},
10225 { "qadd16", 0xe6200f10, 6, ARM_EXT_V6, do_qadd16},
10226 { "qadd8", 0xe6200f90, 5, ARM_EXT_V6, do_qadd16},
10227 { "qaddsubx", 0xe6200f30, 8, ARM_EXT_V6, do_qadd16},
10228 { "qsub16", 0xe6200f70, 6, ARM_EXT_V6, do_qadd16},
10229 { "qsub8", 0xe6200ff0, 5, ARM_EXT_V6, do_qadd16},
10230 { "qsubaddx", 0xe6200f50, 8, ARM_EXT_V6, do_qadd16},
10231 { "sadd16", 0xe6100f10, 6, ARM_EXT_V6, do_qadd16},
10232 { "sadd8", 0xe6100f90, 5, ARM_EXT_V6, do_qadd16},
10233 { "saddsubx", 0xe6100f30, 8, ARM_EXT_V6, do_qadd16},
10234 { "shadd16", 0xe6300f10, 7, ARM_EXT_V6, do_qadd16},
10235 { "shadd8", 0xe6300f90, 6, ARM_EXT_V6, do_qadd16},
10236 { "shaddsubx", 0xe6300f30, 9, ARM_EXT_V6, do_qadd16},
10237 { "shsub16", 0xe6300f70, 7, ARM_EXT_V6, do_qadd16},
10238 { "shsub8", 0xe6300ff0, 6, ARM_EXT_V6, do_qadd16},
10239 { "shsubaddx", 0xe6300f50, 9, ARM_EXT_V6, do_qadd16},
10240 { "ssub16", 0xe6100f70, 6, ARM_EXT_V6, do_qadd16},
10241 { "ssub8", 0xe6100ff0, 5, ARM_EXT_V6, do_qadd16},
10242 { "ssubaddx", 0xe6100f50, 8, ARM_EXT_V6, do_qadd16},
10243 { "uadd16", 0xe6500f10, 6, ARM_EXT_V6, do_qadd16},
10244 { "uadd8", 0xe6500f90, 5, ARM_EXT_V6, do_qadd16},
10245 { "uaddsubx", 0xe6500f30, 8, ARM_EXT_V6, do_qadd16},
10246 { "uhadd16", 0xe6700f10, 7, ARM_EXT_V6, do_qadd16},
10247 { "uhadd8", 0xe6700f90, 6, ARM_EXT_V6, do_qadd16},
10248 { "uhaddsubx", 0xe6700f30, 9, ARM_EXT_V6, do_qadd16},
10249 { "uhsub16", 0xe6700f70, 7, ARM_EXT_V6, do_qadd16},
10250 { "uhsub8", 0xe6700ff0, 6, ARM_EXT_V6, do_qadd16},
10251 { "uhsubaddx", 0xe6700f50, 9, ARM_EXT_V6, do_qadd16},
10252 { "uqadd16", 0xe6600f10, 7, ARM_EXT_V6, do_qadd16},
10253 { "uqadd8", 0xe6600f90, 6, ARM_EXT_V6, do_qadd16},
10254 { "uqaddsubx", 0xe6600f30, 9, ARM_EXT_V6, do_qadd16},
10255 { "uqsub16", 0xe6600f70, 7, ARM_EXT_V6, do_qadd16},
10256 { "uqsub8", 0xe6600ff0, 6, ARM_EXT_V6, do_qadd16},
10257 { "uqsubaddx", 0xe6600f50, 9, ARM_EXT_V6, do_qadd16},
10258 { "usub16", 0xe6500f70, 6, ARM_EXT_V6, do_qadd16},
10259 { "usub8", 0xe6500ff0, 5, ARM_EXT_V6, do_qadd16},
10260 { "usubaddx", 0xe6500f50, 8, ARM_EXT_V6, do_qadd16},
10261 { "rev", 0xe6bf0f30, 3, ARM_EXT_V6, do_rev},
10262 { "rev16", 0xe6bf0fb0, 5, ARM_EXT_V6, do_rev},
10263 { "revsh", 0xe6ff0fb0, 5, ARM_EXT_V6, do_rev},
10264 { "rfeia", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
10265 { "rfeib", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
10266 { "rfeda", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
10267 { "rfedb", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
10268 { "rfefd", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
10269 { "rfefa", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
10270 { "rfeea", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
10271 { "rfeed", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
10272 { "sxtah", 0xe6b00070, 5, ARM_EXT_V6, do_sxtah},
10273 { "sxtab16", 0xe6800070, 7, ARM_EXT_V6, do_sxtah},
10274 { "sxtab", 0xe6a00070, 5, ARM_EXT_V6, do_sxtah},
10275 { "sxth", 0xe6bf0070, 4, ARM_EXT_V6, do_sxth},
10276 { "sxtb16", 0xe68f0070, 6, ARM_EXT_V6, do_sxth},
10277 { "sxtb", 0xe6af0070, 4, ARM_EXT_V6, do_sxth},
10278 { "uxtah", 0xe6f00070, 5, ARM_EXT_V6, do_sxtah},
10279 { "uxtab16", 0xe6c00070, 7, ARM_EXT_V6, do_sxtah},
10280 { "uxtab", 0xe6e00070, 5, ARM_EXT_V6, do_sxtah},
10281 { "uxth", 0xe6ff0070, 4, ARM_EXT_V6, do_sxth},
10282 { "uxtb16", 0xe6cf0070, 6, ARM_EXT_V6, do_sxth},
10283 { "uxtb", 0xe6ef0070, 4, ARM_EXT_V6, do_sxth},
10284 { "sel", 0xe68000b0, 3, ARM_EXT_V6, do_qadd16},
10285 { "setend", 0xf1010000, 0, ARM_EXT_V6, do_setend},
10286 { "smlad", 0xe7000010, 5, ARM_EXT_V6, do_smlad},
10287 { "smladx", 0xe7000030, 6, ARM_EXT_V6, do_smlad},
10288 { "smlald", 0xe7400010, 6, ARM_EXT_V6, do_smlald},
10289 { "smlaldx", 0xe7400030, 7, ARM_EXT_V6, do_smlald},
10290 { "smlsd", 0xe7000050, 5, ARM_EXT_V6, do_smlad},
10291 { "smlsdx", 0xe7000070, 6, ARM_EXT_V6, do_smlad},
10292 { "smlsld", 0xe7400050, 6, ARM_EXT_V6, do_smlald},
10293 { "smlsldx", 0xe7400070, 7, ARM_EXT_V6, do_smlald},
10294 { "smmla", 0xe7500010, 5, ARM_EXT_V6, do_smlad},
10295 { "smmlar", 0xe7500030, 6, ARM_EXT_V6, do_smlad},
10296 { "smmls", 0xe75000d0, 5, ARM_EXT_V6, do_smlad},
10297 { "smmlsr", 0xe75000f0, 6, ARM_EXT_V6, do_smlad},
10298 { "smmul", 0xe750f010, 5, ARM_EXT_V6, do_smmul},
10299 { "smmulr", 0xe750f030, 6, ARM_EXT_V6, do_smmul},
10300 { "smuad", 0xe700f010, 5, ARM_EXT_V6, do_smmul},
10301 { "smuadx", 0xe700f030, 6, ARM_EXT_V6, do_smmul},
10302 { "smusd", 0xe700f050, 5, ARM_EXT_V6, do_smmul},
10303 { "smusdx", 0xe700f070, 6, ARM_EXT_V6, do_smmul},
10304 { "srsia", 0xf8cd0500, 0, ARM_EXT_V6, do_srs},
10305 { "srsib", 0xf9cd0500, 0, ARM_EXT_V6, do_srs},
10306 { "srsda", 0xf84d0500, 0, ARM_EXT_V6, do_srs},
10307 { "srsdb", 0xf94d0500, 0, ARM_EXT_V6, do_srs},
10308 { "ssat", 0xe6a00010, 4, ARM_EXT_V6, do_ssat},
10309 { "ssat16", 0xe6a00f30, 6, ARM_EXT_V6, do_ssat16},
10310 { "strex", 0xe1800f90, 5, ARM_EXT_V6, do_strex},
10311 { "umaal", 0xe0400090, 5, ARM_EXT_V6, do_umaal},
10312 { "usad8", 0xe780f010, 5, ARM_EXT_V6, do_smmul},
10313 { "usada8", 0xe7800010, 6, ARM_EXT_V6, do_smlad},
10314 { "usat", 0xe6e00010, 4, ARM_EXT_V6, do_usat},
10315 { "usat16", 0xe6e00f30, 6, ARM_EXT_V6, do_usat16},
10318 { "clrex", 0xf57ff01f, 0, ARM_EXT_V6K, do_empty},
10319 { "ldrexb", 0xe1d00f9f, 6, ARM_EXT_V6K, do_ldrex},
10320 { "ldrexd", 0xe1b00f9f, 6, ARM_EXT_V6K, do_ldrex},
10321 { "ldrexh", 0xe1f00f9f, 6, ARM_EXT_V6K, do_ldrex},
10322 { "sev", 0xe320f004, 3, ARM_EXT_V6K, do_empty},
10323 { "strexb", 0xe1c00f90, 6, ARM_EXT_V6K, do_strex},
10324 { "strexd", 0xe1a00f90, 6, ARM_EXT_V6K, do_strex},
10325 { "strexh", 0xe1e00f90, 6, ARM_EXT_V6K, do_strex},
10326 { "wfe", 0xe320f002, 3, ARM_EXT_V6K, do_empty},
10327 { "wfi", 0xe320f003, 3, ARM_EXT_V6K, do_empty},
10328 { "yield", 0xe320f001, 5, ARM_EXT_V6K, do_empty},
10331 { "smi", 0xe1600070, 3, ARM_EXT_V6Z, do_smi},
10334 { "bfc", 0xe7c0001f, 3, ARM_EXT_V6T2, do_bfc},
10335 { "bfi", 0xe7c00010, 3, ARM_EXT_V6T2, do_bfi},
10336 { "mls", 0xe0600090, 3, ARM_EXT_V6T2, do_mls},
10337 { "movw", 0xe3000000, 4, ARM_EXT_V6T2, do_mov16},
10338 { "movt", 0xe3400000, 4, ARM_EXT_V6T2, do_mov16},
10339 { "rbit", 0xe3ff0f30, 4, ARM_EXT_V6T2, do_rbit},
10340 { "sbfx", 0xe7a00050, 4, ARM_EXT_V6T2, do_bfx},
10341 { "ubfx", 0xe7e00050, 4, ARM_EXT_V6T2, do_bfx},
10343 { "ldrht", 0xe03000b0, 3, ARM_EXT_V6T2, do_ldsttv4},
10344 { "ldrsht", 0xe03000f0, 3, ARM_EXT_V6T2, do_ldsttv4},
10345 { "ldrsbt", 0xe03000d0, 3, ARM_EXT_V6T2, do_ldsttv4},
10346 { "strht", 0xe02000b0, 3, ARM_EXT_V6T2, do_ldsttv4},
10348 /* Core FPA instruction set (V1). */
10349 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10350 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10351 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10352 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10354 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10355 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10356 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10357 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10359 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10360 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10361 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10362 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10364 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10365 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10366 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10367 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10368 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10369 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10370 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10371 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10372 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10373 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10374 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10375 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10377 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10378 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10379 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10380 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10381 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10382 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10383 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10384 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10385 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10386 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10387 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10388 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10390 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10391 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10392 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10393 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10394 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10395 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10396 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10397 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10398 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10399 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10400 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10401 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10403 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10404 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10405 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10406 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10407 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10408 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10409 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10410 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10411 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10412 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10413 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10414 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10416 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10417 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10418 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10419 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10420 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10421 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10422 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10423 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10424 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10425 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10426 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10427 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10429 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10430 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10431 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10432 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10433 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10434 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10435 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10436 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10437 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10438 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10439 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10440 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10442 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10443 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10444 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10445 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10446 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10447 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10448 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10449 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10450 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10451 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10452 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10453 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10455 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10456 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10457 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10458 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10459 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10460 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10461 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10462 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10463 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10464 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10465 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10466 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10468 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10469 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10470 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10471 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10472 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10473 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10474 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10475 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10476 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10477 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10478 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10479 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10481 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10482 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10483 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10484 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10485 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10486 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10487 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10488 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10489 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10490 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10491 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10492 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10494 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10495 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10496 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10497 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10498 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10499 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10500 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10501 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10502 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10503 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10504 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10505 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10507 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10508 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10509 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10510 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10511 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10512 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10513 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10514 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10515 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10516 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10517 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10518 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10520 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10521 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10522 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10523 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10524 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10525 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10526 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10527 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10528 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10529 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10530 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10531 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10533 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10534 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10535 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10536 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10537 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10538 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10539 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10540 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10541 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10542 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10543 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10544 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10546 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10547 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10548 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10549 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10550 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10551 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10552 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10553 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10554 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10555 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10556 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10557 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10559 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10560 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10561 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10562 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10563 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10564 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10565 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10566 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10567 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10568 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10569 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10570 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10572 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10573 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10574 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10575 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10576 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10577 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10578 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10579 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10580 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10581 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10582 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10583 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10585 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10586 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10587 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10588 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10589 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10590 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10591 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10592 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10593 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10594 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10595 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10596 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10598 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10599 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10600 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10601 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10602 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10603 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10604 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10605 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10606 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10607 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10608 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10609 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10611 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10612 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10613 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10614 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10615 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10616 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10617 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10618 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10619 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10620 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10621 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10622 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10624 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10625 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10626 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10627 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10628 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10629 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10630 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10631 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10632 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10633 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10634 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10635 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10637 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10638 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10639 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10640 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10641 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10642 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10643 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10644 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10645 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10646 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10647 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10648 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10650 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10651 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10652 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10653 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10654 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10655 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10656 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10657 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10658 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10659 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10660 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10661 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10663 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10664 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10665 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10666 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10667 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10668 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10669 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10670 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10671 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10672 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10673 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10674 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10676 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10677 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10678 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10679 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10680 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10681 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10682 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10683 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10684 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10685 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10686 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10687 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10689 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10690 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10691 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10692 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10693 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10694 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10695 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10696 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10697 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10698 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10699 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10700 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10702 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10703 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10704 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10705 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10706 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10707 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10708 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10709 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10710 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10711 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10712 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10713 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10715 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10716 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10717 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10718 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10719 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10720 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10721 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10722 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10723 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10724 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10725 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10726 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10728 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10729 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10730 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10731 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10732 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10733 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10734 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10735 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10736 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10737 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10738 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10739 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10741 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10742 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10743 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10744 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10745 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
10746 not be an optional suffix, but part of the instruction. To be
10747 compatible, we accept either. */
10748 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
10749 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
10751 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10752 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10753 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10754 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10755 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10756 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10757 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10758 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10759 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10760 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10761 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10762 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10764 /* The implementation of the FIX instruction is broken on some
10765 assemblers, in that it accepts a precision specifier as well as a
10766 rounding specifier, despite the fact that this is meaningless.
10767 To be more compatible, we accept it as well, though of course it
10768 does not set any bits. */
10769 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10770 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10771 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10772 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10773 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10774 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10775 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10776 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10777 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10778 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10779 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10780 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10781 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10783 /* Instructions that were new with the real FPA, call them V2. */
10784 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10785 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10786 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10787 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10788 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10789 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10791 /* VFP V1xD (single precision). */
10792 /* Moves and type conversions. */
10793 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10794 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_sp},
10795 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_from_reg},
10796 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD, do_empty},
10797 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10798 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10799 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10800 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10801 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10802 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10803 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_ctrl},
10804 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_ctrl_from_reg},
10806 /* Memory operations. */
10807 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
10808 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
10809 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10810 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10811 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10812 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10813 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10814 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10815 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10816 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10817 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10818 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10819 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10820 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10821 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10822 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10823 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10824 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10826 /* Monadic operations. */
10827 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10828 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10829 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10831 /* Dyadic operations. */
10832 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10833 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10834 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10835 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10836 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10837 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10838 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10839 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10840 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10843 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10844 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
10845 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10846 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
10848 /* VFP V1 (Double precision). */
10849 /* Moves and type conversions. */
10850 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10851 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
10852 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10853 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
10854 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
10855 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
10856 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
10857 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
10858 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
10859 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10860 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10861 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10862 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10864 /* Memory operations. */
10865 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
10866 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
10867 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10868 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10869 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10870 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10871 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10872 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10873 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10874 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10876 /* Monadic operations. */
10877 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10878 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10879 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10881 /* Dyadic operations. */
10882 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10883 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10884 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10885 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10886 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10887 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10888 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10889 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10890 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10893 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10894 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
10895 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10896 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
10899 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2, do_vfp_sp2_from_reg2},
10900 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_sp2},
10901 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2, do_vfp_dp_from_reg2},
10902 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_dp},
10904 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
10905 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE, do_xsc_mia},
10906 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10907 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10908 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10909 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10910 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10911 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE, do_xsc_mar},
10912 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE, do_xsc_mra},
10914 /* Intel Wireless MMX technology instructions. */
10915 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
10916 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
10917 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
10918 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
10919 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
10920 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
10921 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
10922 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
10923 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
10924 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10925 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10926 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10927 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10928 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10929 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10930 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
10931 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
10932 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
10933 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmcr},
10934 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmcrr},
10935 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10936 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10937 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10938 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10939 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10940 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10941 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
10942 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
10943 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
10944 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmrc},
10945 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmrrc},
10946 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
10947 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
10948 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
10949 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10950 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10951 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10952 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10953 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10954 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10955 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10956 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10957 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10958 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10959 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10960 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10961 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT, do_iwmmxt_waligni},
10962 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10963 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10964 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10965 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10966 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10967 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10968 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10969 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10970 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10971 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10972 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10973 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10974 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10975 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10976 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10977 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10978 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10979 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10980 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10981 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
10982 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
10983 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
10984 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
10985 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10986 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10987 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10988 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10989 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10990 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10991 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10992 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10993 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10994 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10995 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10996 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10997 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10998 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10999 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11000 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11001 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11002 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11003 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wmov},
11004 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11005 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11006 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11007 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11008 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11009 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11010 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11011 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11012 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11013 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11014 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11015 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11016 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11017 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11018 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11019 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11020 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11021 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11022 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11023 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11024 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11025 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wshufh},
11026 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11027 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11028 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11029 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11030 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11031 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11032 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11033 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11034 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11035 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11036 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11037 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11038 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11039 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11040 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11041 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11042 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11043 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11044 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
11045 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
11046 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
11047 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
11048 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11049 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11050 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11051 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11052 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11053 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11054 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11055 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11056 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11057 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11058 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11059 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11060 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11061 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11062 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11063 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11064 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11065 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11066 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11067 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11068 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11069 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11070 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11071 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11072 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11073 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11074 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11075 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11076 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wzero},
11078 /* Cirrus Maverick instructions. */
11079 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
11080 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
11081 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
11082 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
11083 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
11084 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
11085 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
11086 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
11087 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK, do_mav_binops_2a},
11088 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK, do_mav_binops_1a},
11089 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
11090 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
11091 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
11092 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
11093 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
11094 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
11095 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
11096 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
11097 {"cfmval32", 0xee200440, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
11098 {"cfmv32al", 0xee100440, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
11099 {"cfmvam32", 0xee200460, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
11100 {"cfmv32am", 0xee100460, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
11101 {"cfmvah32", 0xee200480, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
11102 {"cfmv32ah", 0xee100480, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
11103 {"cfmva32", 0xee2004a0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3a},
11104 {"cfmv32a", 0xee1004a0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3b},
11105 {"cfmva64", 0xee2004c0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3c},
11106 {"cfmv64a", 0xee1004c0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3d},
11107 {"cfmvsc32", 0xee2004e0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_1},
11108 {"cfmv32sc", 0xee1004e0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_2},
11109 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
11110 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
11111 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK, do_mav_binops_1f},
11112 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK, do_mav_binops_1g},
11113 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK, do_mav_binops_1h},
11114 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1i},
11115 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1j},
11116 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1k},
11117 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK, do_mav_binops_1l},
11118 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1m},
11119 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1l},
11120 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1m},
11121 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK, do_mav_triple_4a},
11122 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK, do_mav_triple_4b},
11123 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK, do_mav_shift_1},
11124 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK, do_mav_shift_2},
11125 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK, do_mav_triple_5a},
11126 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5b},
11127 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK, do_mav_triple_5c},
11128 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5d},
11129 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
11130 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
11131 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
11132 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
11133 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
11134 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
11135 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
11136 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
11137 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
11138 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
11139 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
11140 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
11141 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
11142 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
11143 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
11144 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
11145 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
11146 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
11147 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
11148 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
11149 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
11150 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
11151 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
11152 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
11153 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
11154 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
11157 /* Iterate over the base tables to create the instruction patterns. */
11160 build_arm_ops_hsh (void)
11164 static struct obstack insn_obstack;
11166 obstack_begin (&insn_obstack, 4000);
11168 for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
11170 const struct asm_opcode *insn = insns + i;
11172 if (insn->cond_offset != 0)
11174 /* Insn supports conditional execution. Build the varaints
11175 and insert them in the hash table. */
11176 for (j = 0; j < sizeof (conds) / sizeof (struct asm_cond); j++)
11178 unsigned len = strlen (insn->template);
11179 struct asm_opcode *new;
11182 new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
11183 /* All condition codes are two characters. */
11184 template = obstack_alloc (&insn_obstack, len + 3);
11186 strncpy (template, insn->template, insn->cond_offset);
11187 strcpy (template + insn->cond_offset, conds[j].template);
11188 if (len > insn->cond_offset)
11189 strcpy (template + insn->cond_offset + 2,
11190 insn->template + insn->cond_offset);
11191 new->template = template;
11192 new->cond_offset = 0;
11193 new->variant = insn->variant;
11194 new->parms = insn->parms;
11195 new->value = (insn->value & ~COND_MASK) | conds[j].value;
11197 hash_insert (arm_ops_hsh, new->template, (PTR) new);
11200 /* Finally, insert the unconditional insn in the table directly;
11201 no need to build a copy. */
11202 hash_insert (arm_ops_hsh, insn->template, (PTR) insn);
11207 static const struct thumb_opcode tinsns[] =
11209 /* Thumb v1 (ARMv4T). */
11210 {"adc", 0x4140, 2, ARM_EXT_V4T, do_t_arit},
11211 {"add", 0x0000, 2, ARM_EXT_V4T, do_t_add},
11212 {"and", 0x4000, 2, ARM_EXT_V4T, do_t_arit},
11213 {"asr", 0x0000, 2, ARM_EXT_V4T, do_t_asr},
11214 {"b", T_OPCODE_BRANCH, 2, ARM_EXT_V4T, do_t_branch12},
11215 {"beq", 0xd0fe, 2, ARM_EXT_V4T, do_t_branch9},
11216 {"bne", 0xd1fe, 2, ARM_EXT_V4T, do_t_branch9},
11217 {"bcs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
11218 {"bhs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
11219 {"bcc", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
11220 {"bul", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
11221 {"blo", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
11222 {"bmi", 0xd4fe, 2, ARM_EXT_V4T, do_t_branch9},
11223 {"bpl", 0xd5fe, 2, ARM_EXT_V4T, do_t_branch9},
11224 {"bvs", 0xd6fe, 2, ARM_EXT_V4T, do_t_branch9},
11225 {"bvc", 0xd7fe, 2, ARM_EXT_V4T, do_t_branch9},
11226 {"bhi", 0xd8fe, 2, ARM_EXT_V4T, do_t_branch9},
11227 {"bls", 0xd9fe, 2, ARM_EXT_V4T, do_t_branch9},
11228 {"bge", 0xdafe, 2, ARM_EXT_V4T, do_t_branch9},
11229 {"blt", 0xdbfe, 2, ARM_EXT_V4T, do_t_branch9},
11230 {"bgt", 0xdcfe, 2, ARM_EXT_V4T, do_t_branch9},
11231 {"ble", 0xddfe, 2, ARM_EXT_V4T, do_t_branch9},
11232 {"bal", 0xdefe, 2, ARM_EXT_V4T, do_t_branch9},
11233 {"bic", 0x4380, 2, ARM_EXT_V4T, do_t_arit},
11234 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T, do_t_branch23},
11235 {"bx", 0x4700, 2, ARM_EXT_V4T, do_t_bx},
11236 {"cmn", T_OPCODE_CMN, 2, ARM_EXT_V4T, do_t_arit},
11237 {"cmp", 0x0000, 2, ARM_EXT_V4T, do_t_compare},
11238 {"eor", 0x4040, 2, ARM_EXT_V4T, do_t_arit},
11239 {"ldmia", 0xc800, 2, ARM_EXT_V4T, do_t_ldmstm},
11240 {"ldr", 0x0000, 2, ARM_EXT_V4T, do_t_ldr},
11241 {"ldrb", 0x0000, 2, ARM_EXT_V4T, do_t_ldrb},
11242 {"ldrh", 0x0000, 2, ARM_EXT_V4T, do_t_ldrh},
11243 {"ldrsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
11244 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
11245 {"ldsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
11246 {"ldsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
11247 {"lsl", 0x0000, 2, ARM_EXT_V4T, do_t_lsl},
11248 {"lsr", 0x0000, 2, ARM_EXT_V4T, do_t_lsr},
11249 {"mov", 0x0000, 2, ARM_EXT_V4T, do_t_mov},
11250 {"mul", T_OPCODE_MUL, 2, ARM_EXT_V4T, do_t_arit},
11251 {"mvn", T_OPCODE_MVN, 2, ARM_EXT_V4T, do_t_arit},
11252 {"neg", T_OPCODE_NEG, 2, ARM_EXT_V4T, do_t_arit},
11253 {"orr", 0x4300, 2, ARM_EXT_V4T, do_t_arit},
11254 {"pop", 0xbc00, 2, ARM_EXT_V4T, do_t_push_pop},
11255 {"push", 0xb400, 2, ARM_EXT_V4T, do_t_push_pop},
11256 {"ror", 0x41c0, 2, ARM_EXT_V4T, do_t_arit},
11257 {"sbc", 0x4180, 2, ARM_EXT_V4T, do_t_arit},
11258 {"stmia", 0xc000, 2, ARM_EXT_V4T, do_t_ldmstm},
11259 {"str", 0x0000, 2, ARM_EXT_V4T, do_t_str},
11260 {"strb", 0x0000, 2, ARM_EXT_V4T, do_t_strb},
11261 {"strh", 0x0000, 2, ARM_EXT_V4T, do_t_strh},
11262 {"swi", 0xdf00, 2, ARM_EXT_V4T, do_t_swi},
11263 {"sub", 0x0000, 2, ARM_EXT_V4T, do_t_sub},
11264 {"tst", T_OPCODE_TST, 2, ARM_EXT_V4T, do_t_arit},
11266 {"adr", 0x0000, 2, ARM_EXT_V4T, do_t_adr},
11267 {"nop", 0x46C0, 2, ARM_EXT_V4T, do_t_nop}, /* mov r8,r8 */
11268 /* Thumb v2 (ARMv5T). */
11269 {"blx", 0, 0, ARM_EXT_V5T, do_t_blx},
11270 {"bkpt", 0xbe00, 2, ARM_EXT_V5T, do_t_bkpt},
11273 {"cpsie", 0xb660, 2, ARM_EXT_V6, do_t_cps},
11274 {"cpsid", 0xb670, 2, ARM_EXT_V6, do_t_cps},
11275 {"cpy", 0x4600, 2, ARM_EXT_V6, do_t_cpy},
11276 {"rev", 0xba00, 2, ARM_EXT_V6, do_t_arit},
11277 {"rev16", 0xba40, 2, ARM_EXT_V6, do_t_arit},
11278 {"revsh", 0xbac0, 2, ARM_EXT_V6, do_t_arit},
11279 {"setend", 0xb650, 2, ARM_EXT_V6, do_t_setend},
11280 {"sxth", 0xb200, 2, ARM_EXT_V6, do_t_arit},
11281 {"sxtb", 0xb240, 2, ARM_EXT_V6, do_t_arit},
11282 {"uxth", 0xb280, 2, ARM_EXT_V6, do_t_arit},
11283 {"uxtb", 0xb2c0, 2, ARM_EXT_V6, do_t_arit},
11286 {"sev", 0xbf40, 2, ARM_EXT_V6K, do_empty},
11287 {"wfe", 0xbf20, 2, ARM_EXT_V6K, do_empty},
11288 {"wfi", 0xbf30, 2, ARM_EXT_V6K, do_empty},
11289 {"yield", 0xbf10, 2, ARM_EXT_V6K, do_empty},
11298 if ( (arm_ops_hsh = hash_new ()) == NULL
11299 || (arm_tops_hsh = hash_new ()) == NULL
11300 || (arm_cond_hsh = hash_new ()) == NULL
11301 || (arm_shift_hsh = hash_new ()) == NULL
11302 || (arm_psr_hsh = hash_new ()) == NULL)
11303 as_fatal (_("virtual memory exhausted"));
11305 build_arm_ops_hsh ();
11306 for (i = 0; i < sizeof (tinsns) / sizeof (struct thumb_opcode); i++)
11307 hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
11308 for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
11309 hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
11310 for (i = 0; i < sizeof (shift_names) / sizeof (struct asm_shift_name); i++)
11311 hash_insert (arm_shift_hsh, shift_names[i].name, (PTR) (shift_names + i));
11312 for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
11313 hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
11315 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
11316 build_reg_hsh (all_reg_maps + i);
11318 set_constant_flonums ();
11320 /* Set the cpu variant based on the command-line options. We prefer
11321 -mcpu= over -march= if both are set (as for GCC); and we prefer
11322 -mfpu= over any other way of setting the floating point unit.
11323 Use of legacy options with new options are faulted. */
11324 if (legacy_cpu != -1)
11326 if (mcpu_cpu_opt != -1 || march_cpu_opt != -1)
11327 as_bad (_("use of old and new-style options to set CPU type"));
11329 mcpu_cpu_opt = legacy_cpu;
11331 else if (mcpu_cpu_opt == -1)
11332 mcpu_cpu_opt = march_cpu_opt;
11334 if (legacy_fpu != -1)
11336 if (mfpu_opt != -1)
11337 as_bad (_("use of old and new-style options to set FPU type"));
11339 mfpu_opt = legacy_fpu;
11341 else if (mfpu_opt == -1)
11343 #if !(defined (TE_LINUX) || defined (TE_NetBSD) || defined (TE_VXWORKS))
11344 /* Some environments specify a default FPU. If they don't, infer it
11345 from the processor. */
11346 if (mcpu_fpu_opt != -1)
11347 mfpu_opt = mcpu_fpu_opt;
11349 mfpu_opt = march_fpu_opt;
11351 mfpu_opt = FPU_DEFAULT;
11355 if (mfpu_opt == -1)
11357 if (mcpu_cpu_opt == -1)
11358 mfpu_opt = FPU_DEFAULT;
11359 else if (mcpu_cpu_opt & ARM_EXT_V5)
11360 mfpu_opt = FPU_ARCH_VFP_V2;
11362 mfpu_opt = FPU_ARCH_FPA;
11365 if (mcpu_cpu_opt == -1)
11366 mcpu_cpu_opt = CPU_DEFAULT;
11368 cpu_variant = mcpu_cpu_opt | mfpu_opt;
11370 #if defined OBJ_COFF || defined OBJ_ELF
11372 unsigned int flags = 0;
11374 #if defined OBJ_ELF
11375 flags = meabi_flags;
11377 switch (meabi_flags)
11379 case EF_ARM_EABI_UNKNOWN:
11381 /* Set the flags in the private structure. */
11382 if (uses_apcs_26) flags |= F_APCS26;
11383 if (support_interwork) flags |= F_INTERWORK;
11384 if (uses_apcs_float) flags |= F_APCS_FLOAT;
11385 if (pic_code) flags |= F_PIC;
11386 if ((cpu_variant & FPU_ANY) == FPU_NONE
11387 || (cpu_variant & FPU_ANY) == FPU_ARCH_VFP) /* VFP layout only. */
11388 flags |= F_SOFT_FLOAT;
11390 switch (mfloat_abi_opt)
11392 case ARM_FLOAT_ABI_SOFT:
11393 case ARM_FLOAT_ABI_SOFTFP:
11394 flags |= F_SOFT_FLOAT;
11397 case ARM_FLOAT_ABI_HARD:
11398 if (flags & F_SOFT_FLOAT)
11399 as_bad (_("hard-float conflicts with specified fpu"));
11403 /* Using VFP conventions (even if soft-float). */
11404 if (cpu_variant & FPU_VFP_EXT_NONE)
11405 flags |= F_VFP_FLOAT;
11407 #if defined OBJ_ELF
11408 if (cpu_variant & FPU_ARCH_MAVERICK)
11409 flags |= EF_ARM_MAVERICK_FLOAT;
11412 case EF_ARM_EABI_VER4:
11413 /* No additional flags to set. */
11420 bfd_set_private_flags (stdoutput, flags);
11422 /* We have run out flags in the COFF header to encode the
11423 status of ATPCS support, so instead we create a dummy,
11424 empty, debug section called .arm.atpcs. */
11429 sec = bfd_make_section (stdoutput, ".arm.atpcs");
11433 bfd_set_section_flags
11434 (stdoutput, sec, SEC_READONLY | SEC_DEBUGGING /* | SEC_HAS_CONTENTS */);
11435 bfd_set_section_size (stdoutput, sec, 0);
11436 bfd_set_section_contents (stdoutput, sec, NULL, 0, 0);
11442 /* Record the CPU type as well. */
11443 switch (cpu_variant & ARM_CPU_MASK)
11446 mach = bfd_mach_arm_2;
11449 case ARM_3: /* Also ARM_250. */
11450 mach = bfd_mach_arm_2a;
11453 case ARM_6: /* Also ARM_7. */
11454 mach = bfd_mach_arm_3;
11458 mach = bfd_mach_arm_unknown;
11462 /* Catch special cases. */
11463 if (cpu_variant & ARM_CEXT_IWMMXT)
11464 mach = bfd_mach_arm_iWMMXt;
11465 else if (cpu_variant & ARM_CEXT_XSCALE)
11466 mach = bfd_mach_arm_XScale;
11467 else if (cpu_variant & ARM_CEXT_MAVERICK)
11468 mach = bfd_mach_arm_ep9312;
11469 else if (cpu_variant & ARM_EXT_V5E)
11470 mach = bfd_mach_arm_5TE;
11471 else if (cpu_variant & ARM_EXT_V5)
11473 if (cpu_variant & ARM_EXT_V4T)
11474 mach = bfd_mach_arm_5T;
11476 mach = bfd_mach_arm_5;
11478 else if (cpu_variant & ARM_EXT_V4)
11480 if (cpu_variant & ARM_EXT_V4T)
11481 mach = bfd_mach_arm_4T;
11483 mach = bfd_mach_arm_4;
11485 else if (cpu_variant & ARM_EXT_V3M)
11486 mach = bfd_mach_arm_3M;
11488 bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
11491 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11492 for use in the a.out file, and stores them in the array pointed to by buf.
11493 This knows about the endian-ness of the target machine and does
11494 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11495 2 (short) and 4 (long) Floating numbers are put out as a series of
11496 LITTLENUMS (shorts, here at least). */
11499 md_number_to_chars (char * buf, valueT val, int n)
11501 if (target_big_endian)
11502 number_to_chars_bigendian (buf, val, n);
11504 number_to_chars_littleendian (buf, val, n);
11508 md_chars_to_number (char * buf, int n)
11511 unsigned char * where = (unsigned char *) buf;
11513 if (target_big_endian)
11518 result |= (*where++ & 255);
11526 result |= (where[n] & 255);
11533 /* Turn a string in input_line_pointer into a floating point constant
11534 of type TYPE, and store the appropriate bytes in *LITP. The number
11535 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11536 returned, or NULL on OK.
11538 Note that fp constants aren't represent in the normal way on the ARM.
11539 In big endian mode, things are as expected. However, in little endian
11540 mode fp constants are big-endian word-wise, and little-endian byte-wise
11541 within the words. For example, (double) 1.1 in big endian mode is
11542 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11543 the byte sequence 99 99 f1 3f 9a 99 99 99.
11545 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11548 md_atof (int type, char * litP, int * sizeP)
11551 LITTLENUM_TYPE words[MAX_LITTLENUMS];
11583 return _("bad call to MD_ATOF()");
11586 t = atof_ieee (input_line_pointer, type, words);
11588 input_line_pointer = t;
11591 if (target_big_endian)
11593 for (i = 0; i < prec; i++)
11595 md_number_to_chars (litP, (valueT) words[i], 2);
11601 if (cpu_variant & FPU_ARCH_VFP)
11602 for (i = prec - 1; i >= 0; i--)
11604 md_number_to_chars (litP, (valueT) words[i], 2);
11608 /* For a 4 byte float the order of elements in `words' is 1 0.
11609 For an 8 byte float the order is 1 0 3 2. */
11610 for (i = 0; i < prec; i += 2)
11612 md_number_to_chars (litP, (valueT) words[i + 1], 2);
11613 md_number_to_chars (litP + 2, (valueT) words[i], 2);
11621 /* The knowledge of the PC's pipeline offset is built into the insns
11625 md_pcrel_from (fixS * fixP)
11628 && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section
11629 && fixP->fx_subsy == NULL)
11632 if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD))
11634 /* PC relative addressing on the Thumb is slightly odd
11635 as the bottom two bits of the PC are forced to zero
11636 for the calculation. */
11637 return (fixP->fx_where + fixP->fx_frag->fr_address) & ~3;
11641 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
11642 so we un-adjust here to compensate for the accommodation. */
11643 return fixP->fx_where + fixP->fx_frag->fr_address + 8;
11645 return fixP->fx_where + fixP->fx_frag->fr_address;
11649 /* Round up a section size to the appropriate boundary. */
11652 md_section_align (segT segment ATTRIBUTE_UNUSED,
11658 /* Round all sects to multiple of 4. */
11659 return (size + 3) & ~3;
11663 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
11664 Otherwise we have no need to default values of symbols. */
11667 md_undefined_symbol (char * name ATTRIBUTE_UNUSED)
11670 if (name[0] == '_' && name[1] == 'G'
11671 && streq (name, GLOBAL_OFFSET_TABLE_NAME))
11675 if (symbol_find (name))
11676 as_bad ("GOT already in the symbol table");
11678 GOT_symbol = symbol_new (name, undefined_section,
11679 (valueT) 0, & zero_address_frag);
11690 md_apply_fix3 (fixS * fixP,
11694 offsetT value = * valP;
11696 unsigned int newimm;
11697 unsigned long temp;
11699 char * buf = fixP->fx_where + fixP->fx_frag->fr_literal;
11700 arm_fix_data * arm_data = (arm_fix_data *) fixP->tc_fix_data;
11702 assert (fixP->fx_r_type <= BFD_RELOC_UNUSED);
11704 /* Note whether this will delete the relocation. */
11705 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
11708 /* If this symbol is in a different section then we need to leave it for
11709 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
11710 so we have to undo it's effects here. */
11711 if (fixP->fx_pcrel)
11713 if (fixP->fx_addsy != NULL
11714 && S_IS_DEFINED (fixP->fx_addsy)
11715 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
11716 value += md_pcrel_from (fixP);
11719 /* Remember value for emit_reloc. */
11720 fixP->fx_addnumber = value;
11722 switch (fixP->fx_r_type)
11724 case BFD_RELOC_NONE:
11725 /* This will need to go in the object file. */
11729 case BFD_RELOC_ARM_IMMEDIATE:
11730 /* We claim that this fixup has been processed here,
11731 even if in fact we generate an error because we do
11732 not have a reloc for it, so tc_gen_reloc will reject it. */
11736 && ! S_IS_DEFINED (fixP->fx_addsy))
11738 as_bad_where (fixP->fx_file, fixP->fx_line,
11739 _("undefined symbol %s used as an immediate value"),
11740 S_GET_NAME (fixP->fx_addsy));
11744 newimm = validate_immediate (value);
11745 temp = md_chars_to_number (buf, INSN_SIZE);
11747 /* If the instruction will fail, see if we can fix things up by
11748 changing the opcode. */
11749 if (newimm == (unsigned int) FAIL
11750 && (newimm = negate_data_op (&temp, value)) == (unsigned int) FAIL)
11752 as_bad_where (fixP->fx_file, fixP->fx_line,
11753 _("invalid constant (%lx) after fixup"),
11754 (unsigned long) value);
11758 newimm |= (temp & 0xfffff000);
11759 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
11762 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
11764 unsigned int highpart = 0;
11765 unsigned int newinsn = 0xe1a00000; /* nop. */
11767 newimm = validate_immediate (value);
11768 temp = md_chars_to_number (buf, INSN_SIZE);
11770 /* If the instruction will fail, see if we can fix things up by
11771 changing the opcode. */
11772 if (newimm == (unsigned int) FAIL
11773 && (newimm = negate_data_op (& temp, value)) == (unsigned int) FAIL)
11775 /* No ? OK - try using two ADD instructions to generate
11777 newimm = validate_immediate_twopart (value, & highpart);
11779 /* Yes - then make sure that the second instruction is
11781 if (newimm != (unsigned int) FAIL)
11783 /* Still No ? Try using a negated value. */
11784 else if ((newimm = validate_immediate_twopart (- value, & highpart)) != (unsigned int) FAIL)
11785 temp = newinsn = (temp & OPCODE_MASK) | OPCODE_SUB << DATA_OP_SHIFT;
11786 /* Otherwise - give up. */
11789 as_bad_where (fixP->fx_file, fixP->fx_line,
11790 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
11795 /* Replace the first operand in the 2nd instruction (which
11796 is the PC) with the destination register. We have
11797 already added in the PC in the first instruction and we
11798 do not want to do it again. */
11799 newinsn &= ~ 0xf0000;
11800 newinsn |= ((newinsn & 0x0f000) << 4);
11803 newimm |= (temp & 0xfffff000);
11804 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
11806 highpart |= (newinsn & 0xfffff000);
11807 md_number_to_chars (buf + INSN_SIZE, (valueT) highpart, INSN_SIZE);
11811 case BFD_RELOC_ARM_OFFSET_IMM:
11817 if (validate_offset_imm (value, 0) == FAIL)
11819 as_bad_where (fixP->fx_file, fixP->fx_line,
11820 _("bad immediate value for offset (%ld)"),
11825 newval = md_chars_to_number (buf, INSN_SIZE);
11826 newval &= 0xff7ff000;
11827 newval |= value | (sign ? INDEX_UP : 0);
11828 md_number_to_chars (buf, newval, INSN_SIZE);
11831 case BFD_RELOC_ARM_OFFSET_IMM8:
11832 case BFD_RELOC_ARM_HWLITERAL:
11838 if (validate_offset_imm (value, 1) == FAIL)
11840 if (fixP->fx_r_type == BFD_RELOC_ARM_HWLITERAL)
11841 as_bad_where (fixP->fx_file, fixP->fx_line,
11842 _("invalid literal constant: pool needs to be closer"));
11844 as_bad (_("bad immediate value for half-word offset (%ld)"),
11849 newval = md_chars_to_number (buf, INSN_SIZE);
11850 newval &= 0xff7ff0f0;
11851 newval |= ((value >> 4) << 8) | (value & 0xf) | (sign ? INDEX_UP : 0);
11852 md_number_to_chars (buf, newval, INSN_SIZE);
11855 case BFD_RELOC_ARM_LITERAL:
11861 if (validate_offset_imm (value, 0) == FAIL)
11863 as_bad_where (fixP->fx_file, fixP->fx_line,
11864 _("invalid literal constant: pool needs to be closer"));
11868 newval = md_chars_to_number (buf, INSN_SIZE);
11869 newval &= 0xff7ff000;
11870 newval |= value | (sign ? INDEX_UP : 0);
11871 md_number_to_chars (buf, newval, INSN_SIZE);
11874 case BFD_RELOC_ARM_SHIFT_IMM:
11875 newval = md_chars_to_number (buf, INSN_SIZE);
11876 if (((unsigned long) value) > 32
11878 && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60)))
11880 as_bad_where (fixP->fx_file, fixP->fx_line,
11881 _("shift expression is too large"));
11886 /* Shifts of zero must be done as lsl. */
11888 else if (value == 32)
11890 newval &= 0xfffff07f;
11891 newval |= (value & 0x1f) << 7;
11892 md_number_to_chars (buf, newval, INSN_SIZE);
11895 case BFD_RELOC_ARM_SMI:
11896 if (((unsigned long) value) > 0xffff)
11897 as_bad_where (fixP->fx_file, fixP->fx_line,
11898 _("invalid smi expression"));
11899 newval = md_chars_to_number (buf, INSN_SIZE) & 0xfff000f0;
11900 newval |= (value & 0xf) | ((value & 0xfff0) << 4);
11901 md_number_to_chars (buf, newval, INSN_SIZE);
11904 case BFD_RELOC_ARM_SWI:
11905 if (arm_data->thumb_mode)
11907 if (((unsigned long) value) > 0xff)
11908 as_bad_where (fixP->fx_file, fixP->fx_line,
11909 _("invalid swi expression"));
11910 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xff00;
11912 md_number_to_chars (buf, newval, THUMB_SIZE);
11916 if (((unsigned long) value) > 0x00ffffff)
11917 as_bad_where (fixP->fx_file, fixP->fx_line,
11918 _("invalid swi expression"));
11919 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
11921 md_number_to_chars (buf, newval, INSN_SIZE);
11925 case BFD_RELOC_ARM_MULTI:
11926 if (((unsigned long) value) > 0xffff)
11927 as_bad_where (fixP->fx_file, fixP->fx_line,
11928 _("invalid expression in load/store multiple"));
11929 newval = value | md_chars_to_number (buf, INSN_SIZE);
11930 md_number_to_chars (buf, newval, INSN_SIZE);
11933 case BFD_RELOC_ARM_PCREL_BRANCH:
11934 newval = md_chars_to_number (buf, INSN_SIZE);
11936 /* Sign-extend a 24-bit number. */
11937 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
11940 value = fixP->fx_offset;
11943 /* We are going to store value (shifted right by two) in the
11944 instruction, in a 24 bit, signed field. Thus we need to check
11945 that none of the top 8 bits of the shifted value (top 7 bits of
11946 the unshifted, unsigned value) are set, or that they are all set. */
11947 if ((value & ~ ((offsetT) 0x1ffffff)) != 0
11948 && ((value & ~ ((offsetT) 0x1ffffff)) != ~ ((offsetT) 0x1ffffff)))
11951 /* Normally we would be stuck at this point, since we cannot store
11952 the absolute address that is the destination of the branch in the
11953 24 bits of the branch instruction. If however, we happen to know
11954 that the destination of the branch is in the same section as the
11955 branch instruction itself, then we can compute the relocation for
11956 ourselves and not have to bother the linker with it.
11958 FIXME: The test for OBJ_ELF is only here because I have not
11959 worked out how to do this for OBJ_COFF. */
11960 if (fixP->fx_addsy != NULL
11961 && S_IS_DEFINED (fixP->fx_addsy)
11962 && S_GET_SEGMENT (fixP->fx_addsy) == seg)
11964 /* Get pc relative value to go into the branch. */
11967 /* Permit a backward branch provided that enough bits
11968 are set. Allow a forwards branch, provided that
11969 enough bits are clear. */
11970 if ( (value & ~ ((offsetT) 0x1ffffff)) == ~ ((offsetT) 0x1ffffff)
11971 || (value & ~ ((offsetT) 0x1ffffff)) == 0)
11975 if (! fixP->fx_done)
11977 as_bad_where (fixP->fx_file, fixP->fx_line,
11978 _("GAS can't handle same-section branch dest >= 0x04000000"));
11982 value += SEXT24 (newval);
11984 if ( (value & ~ ((offsetT) 0xffffff)) != 0
11985 && ((value & ~ ((offsetT) 0xffffff)) != ~ ((offsetT) 0xffffff)))
11986 as_bad_where (fixP->fx_file, fixP->fx_line,
11987 _("out of range branch"));
11989 if (seg->use_rela_p && !fixP->fx_done)
11991 /* Must unshift the value before storing it in the addend. */
11994 fixP->fx_offset = value;
11996 fixP->fx_addnumber = value;
11997 newval = newval & 0xff000000;
12000 newval = (value & 0x00ffffff) | (newval & 0xff000000);
12001 md_number_to_chars (buf, newval, INSN_SIZE);
12004 case BFD_RELOC_ARM_PCREL_BLX:
12007 newval = md_chars_to_number (buf, INSN_SIZE);
12010 value = fixP->fx_offset;
12012 hbit = (value >> 1) & 1;
12013 value = (value >> 2) & 0x00ffffff;
12014 value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
12016 if (seg->use_rela_p && !fixP->fx_done)
12018 /* Must sign-extend and unshift the value before storing
12019 it in the addend. */
12020 value = SEXT24 (value);
12021 value = (value << 2) | hbit;
12023 fixP->fx_offset = value;
12025 fixP->fx_addnumber = value;
12026 newval = newval & 0xfe000000;
12029 newval = value | (newval & 0xfe000000) | (hbit << 24);
12030 md_number_to_chars (buf, newval, INSN_SIZE);
12034 case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch. */
12035 newval = md_chars_to_number (buf, THUMB_SIZE);
12037 addressT diff = (newval & 0xff) << 1;
12042 if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
12043 as_bad_where (fixP->fx_file, fixP->fx_line,
12044 _("branch out of range"));
12045 if (seg->use_rela_p && !fixP->fx_done)
12048 fixP->fx_offset = value;
12050 fixP->fx_addnumber = value;
12051 newval = newval & 0xff00;
12054 newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
12056 md_number_to_chars (buf, newval, THUMB_SIZE);
12059 case BFD_RELOC_THUMB_PCREL_BRANCH12: /* Unconditional branch. */
12060 newval = md_chars_to_number (buf, THUMB_SIZE);
12062 addressT diff = (newval & 0x7ff) << 1;
12067 if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
12068 as_bad_where (fixP->fx_file, fixP->fx_line,
12069 _("branch out of range"));
12070 if (seg->use_rela_p && !fixP->fx_done)
12073 fixP->fx_offset = value;
12075 fixP->fx_addnumber = value;
12076 newval = newval & 0xf800;
12079 newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
12081 md_number_to_chars (buf, newval, THUMB_SIZE);
12084 case BFD_RELOC_THUMB_PCREL_BLX:
12085 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12090 newval = md_chars_to_number (buf, THUMB_SIZE);
12091 newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
12092 diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
12093 if (diff & 0x400000)
12096 value = fixP->fx_offset;
12100 if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
12101 as_bad_where (fixP->fx_file, fixP->fx_line,
12102 _("branch with link out of range"));
12104 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
12105 /* For a BLX instruction, make sure that the relocation is rounded up
12106 to a word boundary. This follows the semantics of the instruction
12107 which specifies that bit 1 of the target address will come from bit
12108 1 of the base address. */
12109 value = (value + 1) & ~ 1;
12111 if (seg->use_rela_p && !fixP->fx_done)
12114 fixP->fx_offset = value;
12116 fixP->fx_addnumber = value;
12117 newval = newval & 0xf800;
12118 newval2 = newval2 & 0xf800;
12122 newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12);
12123 newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
12125 md_number_to_chars (buf, newval, THUMB_SIZE);
12126 md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
12131 if (seg->use_rela_p && !fixP->fx_done)
12133 if (fixP->fx_done || fixP->fx_pcrel)
12134 md_number_to_chars (buf, value, 1);
12138 value = fixP->fx_offset;
12139 md_number_to_chars (buf, value, 1);
12145 if (seg->use_rela_p && !fixP->fx_done)
12147 if (fixP->fx_done || fixP->fx_pcrel)
12148 md_number_to_chars (buf, value, 2);
12152 value = fixP->fx_offset;
12153 md_number_to_chars (buf, value, 2);
12159 case BFD_RELOC_ARM_TLS_GD32:
12160 case BFD_RELOC_ARM_TLS_LE32:
12161 case BFD_RELOC_ARM_TLS_IE32:
12162 case BFD_RELOC_ARM_TLS_LDM32:
12163 case BFD_RELOC_ARM_TLS_LDO32:
12164 S_SET_THREAD_LOCAL (fixP->fx_addsy);
12167 case BFD_RELOC_ARM_GOT32:
12168 case BFD_RELOC_ARM_GOTOFF:
12169 case BFD_RELOC_ARM_TARGET2:
12170 if (seg->use_rela_p && !fixP->fx_done)
12172 md_number_to_chars (buf, 0, 4);
12176 case BFD_RELOC_RVA:
12178 case BFD_RELOC_ARM_TARGET1:
12179 case BFD_RELOC_ARM_ROSEGREL32:
12180 case BFD_RELOC_ARM_SBREL32:
12181 case BFD_RELOC_32_PCREL:
12182 if (seg->use_rela_p && !fixP->fx_done)
12184 if (fixP->fx_done || fixP->fx_pcrel)
12185 md_number_to_chars (buf, value, 4);
12189 value = fixP->fx_offset;
12190 md_number_to_chars (buf, value, 4);
12196 case BFD_RELOC_ARM_PREL31:
12197 if (fixP->fx_done || fixP->fx_pcrel)
12199 newval = md_chars_to_number (buf, 4) & 0x80000000;
12200 if ((value ^ (value >> 1)) & 0x40000000)
12202 as_bad_where (fixP->fx_file, fixP->fx_line,
12203 _("rel31 relocation overflow"));
12205 newval |= value & 0x7fffffff;
12206 md_number_to_chars (buf, newval, 4);
12210 case BFD_RELOC_ARM_PLT32:
12211 /* It appears the instruction is fully prepared at this point. */
12215 case BFD_RELOC_ARM_CP_OFF_IMM:
12217 if (value < -1023 || value > 1023 || (value & 3))
12218 as_bad_where (fixP->fx_file, fixP->fx_line,
12219 _("illegal value for co-processor offset"));
12222 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
12223 newval |= (value >> 2) | (sign ? INDEX_UP : 0);
12224 md_number_to_chars (buf, newval, INSN_SIZE);
12227 case BFD_RELOC_ARM_CP_OFF_IMM_S2:
12229 if (value < -255 || value > 255)
12230 as_bad_where (fixP->fx_file, fixP->fx_line,
12231 _("Illegal value for co-processor offset"));
12234 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
12235 newval |= value | (sign ? INDEX_UP : 0);
12236 md_number_to_chars (buf, newval , INSN_SIZE);
12239 case BFD_RELOC_ARM_THUMB_OFFSET:
12240 newval = md_chars_to_number (buf, THUMB_SIZE);
12241 /* Exactly what ranges, and where the offset is inserted depends
12242 on the type of instruction, we can establish this from the
12244 switch (newval >> 12)
12246 case 4: /* PC load. */
12247 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
12248 forced to zero for these loads, so we will need to round
12249 up the offset if the instruction address is not word
12250 aligned (since the final address produced must be, and
12251 we can only describe word-aligned immediate offsets). */
12253 if ((fixP->fx_frag->fr_address + fixP->fx_where + value) & 3)
12254 as_bad_where (fixP->fx_file, fixP->fx_line,
12255 _("invalid offset, target not word aligned (0x%08X)"),
12256 (unsigned int) (fixP->fx_frag->fr_address
12257 + fixP->fx_where + value));
12259 if ((value + 2) & ~0x3fe)
12260 as_bad_where (fixP->fx_file, fixP->fx_line,
12261 _("invalid offset, value too big (0x%08lX)"),
12264 /* Round up, since pc will be rounded down. */
12265 newval |= (value + 2) >> 2;
12268 case 9: /* SP load/store. */
12269 if (value & ~0x3fc)
12270 as_bad_where (fixP->fx_file, fixP->fx_line,
12271 _("invalid offset, value too big (0x%08lX)"),
12273 newval |= value >> 2;
12276 case 6: /* Word load/store. */
12278 as_bad_where (fixP->fx_file, fixP->fx_line,
12279 _("invalid offset, value too big (0x%08lX)"),
12281 newval |= value << 4; /* 6 - 2. */
12284 case 7: /* Byte load/store. */
12286 as_bad_where (fixP->fx_file, fixP->fx_line,
12287 _("invalid offset, value too big (0x%08lX)"),
12289 newval |= value << 6;
12292 case 8: /* Halfword load/store. */
12294 as_bad_where (fixP->fx_file, fixP->fx_line,
12295 _("invalid offset, value too big (0x%08lX)"),
12297 newval |= value << 5; /* 6 - 1. */
12301 as_bad_where (fixP->fx_file, fixP->fx_line,
12302 "Unable to process relocation for thumb opcode: %lx",
12303 (unsigned long) newval);
12306 md_number_to_chars (buf, newval, THUMB_SIZE);
12309 case BFD_RELOC_ARM_THUMB_ADD:
12310 /* This is a complicated relocation, since we use it for all of
12311 the following immediate relocations:
12315 9bit ADD/SUB SP word-aligned
12316 10bit ADD PC/SP word-aligned
12318 The type of instruction being processed is encoded in the
12325 newval = md_chars_to_number (buf, THUMB_SIZE);
12327 int rd = (newval >> 4) & 0xf;
12328 int rs = newval & 0xf;
12329 int subtract = newval & 0x8000;
12333 if (value & ~0x1fc)
12334 as_bad_where (fixP->fx_file, fixP->fx_line,
12335 _("invalid immediate for stack address calculation"));
12336 newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
12337 newval |= value >> 2;
12339 else if (rs == REG_PC || rs == REG_SP)
12343 as_bad_where (fixP->fx_file, fixP->fx_line,
12344 _("invalid immediate for address calculation (value = 0x%08lX)"),
12345 (unsigned long) value);
12346 newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP);
12348 newval |= value >> 2;
12353 as_bad_where (fixP->fx_file, fixP->fx_line,
12354 _("invalid 8bit immediate"));
12355 newval = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
12356 newval |= (rd << 8) | value;
12361 as_bad_where (fixP->fx_file, fixP->fx_line,
12362 _("invalid 3bit immediate"));
12363 newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
12364 newval |= rd | (rs << 3) | (value << 6);
12367 md_number_to_chars (buf, newval, THUMB_SIZE);
12370 case BFD_RELOC_ARM_THUMB_IMM:
12371 newval = md_chars_to_number (buf, THUMB_SIZE);
12372 switch (newval >> 11)
12374 case 0x04: /* 8bit immediate MOV. */
12375 case 0x05: /* 8bit immediate CMP. */
12376 if (value < 0 || value > 255)
12377 as_bad_where (fixP->fx_file, fixP->fx_line,
12378 _("invalid immediate: %ld is too large"),
12386 md_number_to_chars (buf, newval, THUMB_SIZE);
12389 case BFD_RELOC_ARM_THUMB_SHIFT:
12390 /* 5bit shift value (0..31). */
12391 if (value < 0 || value > 31)
12392 as_bad_where (fixP->fx_file, fixP->fx_line,
12393 _("illegal Thumb shift value: %ld"), (long) value);
12394 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xf03f;
12395 newval |= value << 6;
12396 md_number_to_chars (buf, newval, THUMB_SIZE);
12399 case BFD_RELOC_VTABLE_INHERIT:
12400 case BFD_RELOC_VTABLE_ENTRY:
12404 case BFD_RELOC_UNUSED:
12406 as_bad_where (fixP->fx_file, fixP->fx_line,
12407 _("bad relocation fixup type (%d)"), fixP->fx_r_type);
12411 /* Translate internal representation of relocation info to BFD target
12415 tc_gen_reloc (asection * section ATTRIBUTE_UNUSED,
12419 bfd_reloc_code_real_type code;
12421 reloc = xmalloc (sizeof (arelent));
12423 reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
12424 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
12425 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
12427 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12429 if (fixp->fx_pcrel == 0)
12430 reloc->addend = fixp->fx_offset;
12432 reloc->addend = fixp->fx_offset = reloc->address;
12433 #else /* OBJ_ELF */
12434 reloc->addend = fixp->fx_offset;
12437 switch (fixp->fx_r_type)
12440 if (fixp->fx_pcrel)
12442 code = BFD_RELOC_8_PCREL;
12447 if (fixp->fx_pcrel)
12449 code = BFD_RELOC_16_PCREL;
12454 if (fixp->fx_pcrel)
12456 code = BFD_RELOC_32_PCREL;
12460 case BFD_RELOC_NONE:
12461 case BFD_RELOC_ARM_PCREL_BRANCH:
12462 case BFD_RELOC_ARM_PCREL_BLX:
12463 case BFD_RELOC_RVA:
12464 case BFD_RELOC_THUMB_PCREL_BRANCH9:
12465 case BFD_RELOC_THUMB_PCREL_BRANCH12:
12466 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12467 case BFD_RELOC_THUMB_PCREL_BLX:
12468 case BFD_RELOC_VTABLE_ENTRY:
12469 case BFD_RELOC_VTABLE_INHERIT:
12470 code = fixp->fx_r_type;
12473 case BFD_RELOC_ARM_LITERAL:
12474 case BFD_RELOC_ARM_HWLITERAL:
12475 /* If this is called then the a literal has
12476 been referenced across a section boundary. */
12477 as_bad_where (fixp->fx_file, fixp->fx_line,
12478 _("literal referenced across section boundary"));
12482 case BFD_RELOC_ARM_GOT32:
12483 case BFD_RELOC_ARM_GOTOFF:
12484 case BFD_RELOC_ARM_PLT32:
12485 case BFD_RELOC_ARM_TARGET1:
12486 case BFD_RELOC_ARM_ROSEGREL32:
12487 case BFD_RELOC_ARM_SBREL32:
12488 case BFD_RELOC_ARM_PREL31:
12489 case BFD_RELOC_ARM_TARGET2:
12490 case BFD_RELOC_ARM_TLS_LE32:
12491 case BFD_RELOC_ARM_TLS_LDO32:
12492 code = fixp->fx_r_type;
12495 case BFD_RELOC_ARM_TLS_GD32:
12496 case BFD_RELOC_ARM_TLS_IE32:
12497 case BFD_RELOC_ARM_TLS_LDM32:
12498 /* BFD will include the symbol's address in the addend.
12499 But we don't want that, so subtract it out again here. */
12500 if (!S_IS_COMMON (fixp->fx_addsy))
12501 reloc->addend -= (*reloc->sym_ptr_ptr)->value;
12502 code = fixp->fx_r_type;
12506 case BFD_RELOC_ARM_IMMEDIATE:
12507 as_bad_where (fixp->fx_file, fixp->fx_line,
12508 _("internal relocation (type: IMMEDIATE) not fixed up"));
12511 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
12512 as_bad_where (fixp->fx_file, fixp->fx_line,
12513 _("ADRL used for a symbol not defined in the same file"));
12516 case BFD_RELOC_ARM_OFFSET_IMM:
12517 if (fixp->fx_addsy != NULL
12518 && !S_IS_DEFINED (fixp->fx_addsy)
12519 && S_IS_LOCAL (fixp->fx_addsy))
12521 as_bad_where (fixp->fx_file, fixp->fx_line,
12522 _("undefined local label `%s'"),
12523 S_GET_NAME (fixp->fx_addsy));
12527 as_bad_where (fixp->fx_file, fixp->fx_line,
12528 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
12535 switch (fixp->fx_r_type)
12537 case BFD_RELOC_NONE: type = "NONE"; break;
12538 case BFD_RELOC_ARM_OFFSET_IMM8: type = "OFFSET_IMM8"; break;
12539 case BFD_RELOC_ARM_SHIFT_IMM: type = "SHIFT_IMM"; break;
12540 case BFD_RELOC_ARM_SMI: type = "SMI"; break;
12541 case BFD_RELOC_ARM_SWI: type = "SWI"; break;
12542 case BFD_RELOC_ARM_MULTI: type = "MULTI"; break;
12543 case BFD_RELOC_ARM_CP_OFF_IMM: type = "CP_OFF_IMM"; break;
12544 case BFD_RELOC_ARM_THUMB_ADD: type = "THUMB_ADD"; break;
12545 case BFD_RELOC_ARM_THUMB_SHIFT: type = "THUMB_SHIFT"; break;
12546 case BFD_RELOC_ARM_THUMB_IMM: type = "THUMB_IMM"; break;
12547 case BFD_RELOC_ARM_THUMB_OFFSET: type = "THUMB_OFFSET"; break;
12548 default: type = _("<unknown>"); break;
12550 as_bad_where (fixp->fx_file, fixp->fx_line,
12551 _("cannot represent %s relocation in this object file format"),
12558 if ((code == BFD_RELOC_32_PCREL || code == BFD_RELOC_32)
12560 && fixp->fx_addsy == GOT_symbol)
12562 code = BFD_RELOC_ARM_GOTPC;
12563 reloc->addend = fixp->fx_offset = reloc->address;
12567 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
12569 if (reloc->howto == NULL)
12571 as_bad_where (fixp->fx_file, fixp->fx_line,
12572 _("cannot represent %s relocation in this object file format"),
12573 bfd_get_reloc_code_name (code));
12577 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12578 vtable entry to be used in the relocation's section offset. */
12579 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
12580 reloc->address = fixp->fx_offset;
12586 md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED,
12587 segT segtype ATTRIBUTE_UNUSED)
12589 as_fatal (_("md_estimate_size_before_relax\n"));
12593 /* We need to be able to fix up arbitrary expressions in some statements.
12594 This is so that we can handle symbols that are an arbitrary distance from
12595 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
12596 which returns part of an address in a form which will be valid for
12597 a data instruction. We do this by pushing the expression into a symbol
12598 in the expr_section, and creating a fix for that. */
12601 fix_new_arm (fragS * frag,
12609 arm_fix_data * arm_data;
12617 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
12621 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0,
12626 /* Mark whether the fix is to a THUMB instruction, or an ARM
12628 arm_data = obstack_alloc (& notes, sizeof (arm_fix_data));
12629 new_fix->tc_fix_data = (PTR) arm_data;
12630 arm_data->thumb_mode = thumb_mode;
12634 output_inst (const char * str)
12640 as_bad ("%s -- `%s'", inst.error, str);
12644 to = frag_more (inst.size);
12646 if (thumb_mode && (inst.size > THUMB_SIZE))
12648 assert (inst.size == (2 * THUMB_SIZE));
12649 md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE);
12650 md_number_to_chars (to + THUMB_SIZE, inst.instruction, THUMB_SIZE);
12652 else if (inst.size > INSN_SIZE)
12654 assert (inst.size == (2 * INSN_SIZE));
12655 md_number_to_chars (to, inst.instruction, INSN_SIZE);
12656 md_number_to_chars (to + INSN_SIZE, inst.instruction, INSN_SIZE);
12659 md_number_to_chars (to, inst.instruction, inst.size);
12661 if (inst.reloc.type != BFD_RELOC_UNUSED)
12662 fix_new_arm (frag_now, to - frag_now->fr_literal,
12663 inst.size, & inst.reloc.exp, inst.reloc.pc_rel,
12667 dwarf2_emit_insn (inst.size);
12672 md_assemble (char * str)
12678 /* Align the previous label if needed. */
12679 if (last_label_seen != NULL)
12681 symbol_set_frag (last_label_seen, frag_now);
12682 S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ());
12683 S_SET_SEGMENT (last_label_seen, now_seg);
12686 memset (&inst, '\0', sizeof (inst));
12687 inst.reloc.type = BFD_RELOC_UNUSED;
12689 skip_whitespace (str);
12691 /* Scan up to the end of the op-code, which must end in white space or
12693 for (start = p = str; *p != '\0'; p++)
12699 as_bad (_("no operator -- statement `%s'\n"), str);
12705 const struct thumb_opcode * opcode;
12709 opcode = (const struct thumb_opcode *) hash_find (arm_tops_hsh, str);
12714 /* Check that this instruction is supported for this CPU. */
12715 if (thumb_mode == 1 && (opcode->variant & cpu_variant) == 0)
12717 as_bad (_("selected processor does not support `%s'"), str);
12721 mapping_state (MAP_THUMB);
12722 inst.instruction = opcode->value;
12723 inst.size = opcode->size;
12731 const struct asm_opcode * opcode;
12735 opcode = (const struct asm_opcode *) hash_find (arm_ops_hsh, str);
12740 /* Check that this instruction is supported for this CPU. */
12741 if ((opcode->variant & cpu_variant) == 0)
12743 as_bad (_("selected processor does not support `%s'"), str);
12747 mapping_state (MAP_ARM);
12748 inst.instruction = opcode->value;
12749 inst.size = INSN_SIZE;
12756 /* It wasn't an instruction, but it might be a register alias of the form
12758 if (create_register_alias (str, p))
12761 as_bad (_("bad instruction `%s'"), start);
12765 Invocation line includes a switch not recognized by the base assembler.
12766 See if it's a processor-specific option.
12768 This routine is somewhat complicated by the need for backwards
12769 compatibility (since older releases of gcc can't be changed).
12770 The new options try to make the interface as compatible as
12773 New options (supported) are:
12775 -mcpu=<cpu name> Assemble for selected processor
12776 -march=<architecture name> Assemble for selected architecture
12777 -mfpu=<fpu architecture> Assemble for selected FPU.
12778 -EB/-mbig-endian Big-endian
12779 -EL/-mlittle-endian Little-endian
12780 -k Generate PIC code
12781 -mthumb Start in Thumb mode
12782 -mthumb-interwork Code supports ARM/Thumb interworking
12784 For now we will also provide support for:
12786 -mapcs-32 32-bit Program counter
12787 -mapcs-26 26-bit Program counter
12788 -macps-float Floats passed in FP registers
12789 -mapcs-reentrant Reentrant code
12791 (sometime these will probably be replaced with -mapcs=<list of options>
12792 and -matpcs=<list of options>)
12794 The remaining options are only supported for back-wards compatibility.
12795 Cpu variants, the arm part is optional:
12796 -m[arm]1 Currently not supported.
12797 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
12798 -m[arm]3 Arm 3 processor
12799 -m[arm]6[xx], Arm 6 processors
12800 -m[arm]7[xx][t][[d]m] Arm 7 processors
12801 -m[arm]8[10] Arm 8 processors
12802 -m[arm]9[20][tdmi] Arm 9 processors
12803 -mstrongarm[110[0]] StrongARM processors
12804 -mxscale XScale processors
12805 -m[arm]v[2345[t[e]]] Arm architectures
12806 -mall All (except the ARM1)
12808 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
12809 -mfpe-old (No float load/store multiples)
12810 -mvfpxd VFP Single precision
12812 -mno-fpu Disable all floating point instructions
12814 The following CPU names are recognized:
12815 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
12816 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
12817 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
12818 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
12819 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
12820 arm10t arm10e, arm1020t, arm1020e, arm10200e,
12821 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
12825 const char * md_shortopts = "m:k";
12827 #ifdef ARM_BI_ENDIAN
12828 #define OPTION_EB (OPTION_MD_BASE + 0)
12829 #define OPTION_EL (OPTION_MD_BASE + 1)
12831 #if TARGET_BYTES_BIG_ENDIAN
12832 #define OPTION_EB (OPTION_MD_BASE + 0)
12834 #define OPTION_EL (OPTION_MD_BASE + 1)
12838 struct option md_longopts[] =
12841 {"EB", no_argument, NULL, OPTION_EB},
12844 {"EL", no_argument, NULL, OPTION_EL},
12846 {NULL, no_argument, NULL, 0}
12849 size_t md_longopts_size = sizeof (md_longopts);
12851 struct arm_option_table
12853 char *option; /* Option name to match. */
12854 char *help; /* Help information. */
12855 int *var; /* Variable to change. */
12856 int value; /* What to change it to. */
12857 char *deprecated; /* If non-null, print this message. */
12860 struct arm_option_table arm_opts[] =
12862 {"k", N_("generate PIC code"), &pic_code, 1, NULL},
12863 {"mthumb", N_("assemble Thumb code"), &thumb_mode, 1, NULL},
12864 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
12865 &support_interwork, 1, NULL},
12866 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26, 0, NULL},
12867 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26, 1, NULL},
12868 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float,
12870 {"mapcs-reentrant", N_("re-entrant code"), &pic_code, 1, NULL},
12871 {"matpcs", N_("code is ATPCS conformant"), &atpcs, 1, NULL},
12872 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian, 1, NULL},
12873 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian, 0,
12876 /* These are recognized by the assembler, but have no affect on code. */
12877 {"mapcs-frame", N_("use frame pointer"), NULL, 0, NULL},
12878 {"mapcs-stack-check", N_("use stack size checking"), NULL, 0, NULL},
12880 /* DON'T add any new processors to this list -- we want the whole list
12881 to go away... Add them to the processors table instead. */
12882 {"marm1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
12883 {"m1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
12884 {"marm2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
12885 {"m2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
12886 {"marm250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
12887 {"m250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
12888 {"marm3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
12889 {"m3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
12890 {"marm6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
12891 {"m6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
12892 {"marm600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
12893 {"m600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
12894 {"marm610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
12895 {"m610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
12896 {"marm620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
12897 {"m620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
12898 {"marm7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
12899 {"m7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
12900 {"marm70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
12901 {"m70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
12902 {"marm700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
12903 {"m700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
12904 {"marm700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
12905 {"m700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
12906 {"marm710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
12907 {"m710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
12908 {"marm710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
12909 {"m710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
12910 {"marm720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
12911 {"m720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
12912 {"marm7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
12913 {"m7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
12914 {"marm7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
12915 {"m7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
12916 {"marm7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
12917 {"m7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
12918 {"marm7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
12919 {"m7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
12920 {"marm7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
12921 {"m7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
12922 {"marm7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
12923 {"m7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
12924 {"marm7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
12925 {"m7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
12926 {"marm7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
12927 {"m7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
12928 {"marm7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12929 {"m7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12930 {"marm7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12931 {"m7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12932 {"marm710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
12933 {"m710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
12934 {"marm720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
12935 {"m720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
12936 {"marm740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
12937 {"m740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
12938 {"marm8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
12939 {"m8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
12940 {"marm810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
12941 {"m810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
12942 {"marm9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
12943 {"m9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
12944 {"marm9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
12945 {"m9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
12946 {"marm920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
12947 {"m920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
12948 {"marm940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
12949 {"m940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
12950 {"mstrongarm", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=strongarm")},
12951 {"mstrongarm110", NULL, &legacy_cpu, ARM_ARCH_V4,
12952 N_("use -mcpu=strongarm110")},
12953 {"mstrongarm1100", NULL, &legacy_cpu, ARM_ARCH_V4,
12954 N_("use -mcpu=strongarm1100")},
12955 {"mstrongarm1110", NULL, &legacy_cpu, ARM_ARCH_V4,
12956 N_("use -mcpu=strongarm1110")},
12957 {"mxscale", NULL, &legacy_cpu, ARM_ARCH_XSCALE, N_("use -mcpu=xscale")},
12958 {"miwmmxt", NULL, &legacy_cpu, ARM_ARCH_IWMMXT, N_("use -mcpu=iwmmxt")},
12959 {"mall", NULL, &legacy_cpu, ARM_ANY, N_("use -mcpu=all")},
12961 /* Architecture variants -- don't add any more to this list either. */
12962 {"mv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
12963 {"marmv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
12964 {"mv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
12965 {"marmv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
12966 {"mv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
12967 {"marmv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
12968 {"mv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
12969 {"marmv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
12970 {"mv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
12971 {"marmv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
12972 {"mv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
12973 {"marmv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
12974 {"mv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
12975 {"marmv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
12976 {"mv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
12977 {"marmv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
12978 {"mv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
12979 {"marmv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
12981 /* Floating point variants -- don't add any more to this list either. */
12982 {"mfpe-old", NULL, &legacy_fpu, FPU_ARCH_FPE, N_("use -mfpu=fpe")},
12983 {"mfpa10", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa10")},
12984 {"mfpa11", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa11")},
12985 {"mno-fpu", NULL, &legacy_fpu, 0,
12986 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
12988 {NULL, NULL, NULL, 0, NULL}
12991 struct arm_cpu_option_table
12995 /* For some CPUs we assume an FPU unless the user explicitly sets
13000 /* This list should, at a minimum, contain all the cpu names
13001 recognized by GCC. */
13002 static struct arm_cpu_option_table arm_cpus[] =
13004 {"all", ARM_ANY, FPU_ARCH_FPA},
13005 {"arm1", ARM_ARCH_V1, FPU_ARCH_FPA},
13006 {"arm2", ARM_ARCH_V2, FPU_ARCH_FPA},
13007 {"arm250", ARM_ARCH_V2S, FPU_ARCH_FPA},
13008 {"arm3", ARM_ARCH_V2S, FPU_ARCH_FPA},
13009 {"arm6", ARM_ARCH_V3, FPU_ARCH_FPA},
13010 {"arm60", ARM_ARCH_V3, FPU_ARCH_FPA},
13011 {"arm600", ARM_ARCH_V3, FPU_ARCH_FPA},
13012 {"arm610", ARM_ARCH_V3, FPU_ARCH_FPA},
13013 {"arm620", ARM_ARCH_V3, FPU_ARCH_FPA},
13014 {"arm7", ARM_ARCH_V3, FPU_ARCH_FPA},
13015 {"arm7m", ARM_ARCH_V3M, FPU_ARCH_FPA},
13016 {"arm7d", ARM_ARCH_V3, FPU_ARCH_FPA},
13017 {"arm7dm", ARM_ARCH_V3M, FPU_ARCH_FPA},
13018 {"arm7di", ARM_ARCH_V3, FPU_ARCH_FPA},
13019 {"arm7dmi", ARM_ARCH_V3M, FPU_ARCH_FPA},
13020 {"arm70", ARM_ARCH_V3, FPU_ARCH_FPA},
13021 {"arm700", ARM_ARCH_V3, FPU_ARCH_FPA},
13022 {"arm700i", ARM_ARCH_V3, FPU_ARCH_FPA},
13023 {"arm710", ARM_ARCH_V3, FPU_ARCH_FPA},
13024 {"arm710t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13025 {"arm720", ARM_ARCH_V3, FPU_ARCH_FPA},
13026 {"arm720t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13027 {"arm740t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13028 {"arm710c", ARM_ARCH_V3, FPU_ARCH_FPA},
13029 {"arm7100", ARM_ARCH_V3, FPU_ARCH_FPA},
13030 {"arm7500", ARM_ARCH_V3, FPU_ARCH_FPA},
13031 {"arm7500fe", ARM_ARCH_V3, FPU_ARCH_FPA},
13032 {"arm7t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13033 {"arm7tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
13034 {"arm7tdmi-s", ARM_ARCH_V4T, FPU_ARCH_FPA},
13035 {"arm8", ARM_ARCH_V4, FPU_ARCH_FPA},
13036 {"arm810", ARM_ARCH_V4, FPU_ARCH_FPA},
13037 {"strongarm", ARM_ARCH_V4, FPU_ARCH_FPA},
13038 {"strongarm1", ARM_ARCH_V4, FPU_ARCH_FPA},
13039 {"strongarm110", ARM_ARCH_V4, FPU_ARCH_FPA},
13040 {"strongarm1100", ARM_ARCH_V4, FPU_ARCH_FPA},
13041 {"strongarm1110", ARM_ARCH_V4, FPU_ARCH_FPA},
13042 {"arm9", ARM_ARCH_V4T, FPU_ARCH_FPA},
13043 {"arm920", ARM_ARCH_V4T, FPU_ARCH_FPA},
13044 {"arm920t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13045 {"arm922t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13046 {"arm940t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13047 {"arm9tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
13048 /* For V5 or later processors we default to using VFP; but the user
13049 should really set the FPU type explicitly. */
13050 {"arm9e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13051 {"arm9e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13052 {"arm926ej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
13053 {"arm926ejs", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
13054 {"arm926ej-s", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
13055 {"arm946e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13056 {"arm946e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13057 {"arm966e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13058 {"arm966e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13059 {"arm10t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
13060 {"arm10e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13061 {"arm1020", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13062 {"arm1020t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
13063 {"arm1020e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13064 {"arm1026ejs", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
13065 {"arm1026ej-s", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
13066 {"arm1136js", ARM_ARCH_V6, FPU_NONE},
13067 {"arm1136j-s", ARM_ARCH_V6, FPU_NONE},
13068 {"arm1136jfs", ARM_ARCH_V6, FPU_ARCH_VFP_V2},
13069 {"arm1136jf-s", ARM_ARCH_V6, FPU_ARCH_VFP_V2},
13070 {"mpcore", ARM_ARCH_V6K, FPU_ARCH_VFP_V2},
13071 {"mpcorenovfp", ARM_ARCH_V6K, FPU_NONE},
13072 {"arm1176jz-s", ARM_ARCH_V6ZK, FPU_NONE},
13073 {"arm1176jzf-s", ARM_ARCH_V6ZK, FPU_ARCH_VFP_V2},
13074 /* ??? XSCALE is really an architecture. */
13075 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
13076 /* ??? iwmmxt is not a processor. */
13077 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP_V2},
13078 {"i80200", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
13080 {"ep9312", ARM_ARCH_V4T | ARM_CEXT_MAVERICK, FPU_ARCH_MAVERICK},
13084 struct arm_arch_option_table
13091 /* This list should, at a minimum, contain all the architecture names
13092 recognized by GCC. */
13093 static struct arm_arch_option_table arm_archs[] =
13095 {"all", ARM_ANY, FPU_ARCH_FPA},
13096 {"armv1", ARM_ARCH_V1, FPU_ARCH_FPA},
13097 {"armv2", ARM_ARCH_V2, FPU_ARCH_FPA},
13098 {"armv2a", ARM_ARCH_V2S, FPU_ARCH_FPA},
13099 {"armv2s", ARM_ARCH_V2S, FPU_ARCH_FPA},
13100 {"armv3", ARM_ARCH_V3, FPU_ARCH_FPA},
13101 {"armv3m", ARM_ARCH_V3M, FPU_ARCH_FPA},
13102 {"armv4", ARM_ARCH_V4, FPU_ARCH_FPA},
13103 {"armv4xm", ARM_ARCH_V4xM, FPU_ARCH_FPA},
13104 {"armv4t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13105 {"armv4txm", ARM_ARCH_V4TxM, FPU_ARCH_FPA},
13106 {"armv5", ARM_ARCH_V5, FPU_ARCH_VFP},
13107 {"armv5t", ARM_ARCH_V5T, FPU_ARCH_VFP},
13108 {"armv5txm", ARM_ARCH_V5TxM, FPU_ARCH_VFP},
13109 {"armv5te", ARM_ARCH_V5TE, FPU_ARCH_VFP},
13110 {"armv5texp", ARM_ARCH_V5TExP, FPU_ARCH_VFP},
13111 {"armv5tej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP},
13112 {"armv6", ARM_ARCH_V6, FPU_ARCH_VFP},
13113 {"armv6j", ARM_ARCH_V6, FPU_ARCH_VFP},
13114 {"armv6k", ARM_ARCH_V6K, FPU_ARCH_VFP},
13115 {"armv6z", ARM_ARCH_V6Z, FPU_ARCH_VFP},
13116 {"armv6zk", ARM_ARCH_V6ZK, FPU_ARCH_VFP},
13117 {"armv6t2", ARM_ARCH_V6T2, FPU_ARCH_VFP},
13118 {"armv6kt2", ARM_ARCH_V6KT2, FPU_ARCH_VFP},
13119 {"armv6zt2", ARM_ARCH_V6ZT2, FPU_ARCH_VFP},
13120 {"armv6zkt2", ARM_ARCH_V6ZKT2, FPU_ARCH_VFP},
13121 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP},
13122 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP},
13126 /* ISA extensions in the co-processor space. */
13127 struct arm_arch_extension_table
13133 static struct arm_arch_extension_table arm_extensions[] =
13135 {"maverick", ARM_CEXT_MAVERICK},
13136 {"xscale", ARM_CEXT_XSCALE},
13137 {"iwmmxt", ARM_CEXT_IWMMXT},
13141 struct arm_fpu_option_table
13147 /* This list should, at a minimum, contain all the fpu names
13148 recognized by GCC. */
13149 static struct arm_fpu_option_table arm_fpus[] =
13151 {"softfpa", FPU_NONE},
13152 {"fpe", FPU_ARCH_FPE},
13153 {"fpe2", FPU_ARCH_FPE},
13154 {"fpe3", FPU_ARCH_FPA}, /* Third release supports LFM/SFM. */
13155 {"fpa", FPU_ARCH_FPA},
13156 {"fpa10", FPU_ARCH_FPA},
13157 {"fpa11", FPU_ARCH_FPA},
13158 {"arm7500fe", FPU_ARCH_FPA},
13159 {"softvfp", FPU_ARCH_VFP},
13160 {"softvfp+vfp", FPU_ARCH_VFP_V2},
13161 {"vfp", FPU_ARCH_VFP_V2},
13162 {"vfp9", FPU_ARCH_VFP_V2},
13163 {"vfp10", FPU_ARCH_VFP_V2},
13164 {"vfp10-r0", FPU_ARCH_VFP_V1},
13165 {"vfpxd", FPU_ARCH_VFP_V1xD},
13166 {"arm1020t", FPU_ARCH_VFP_V1},
13167 {"arm1020e", FPU_ARCH_VFP_V2},
13168 {"arm1136jfs", FPU_ARCH_VFP_V2},
13169 {"arm1136jf-s", FPU_ARCH_VFP_V2},
13170 {"maverick", FPU_ARCH_MAVERICK},
13174 struct arm_float_abi_option_table
13180 static struct arm_float_abi_option_table arm_float_abis[] =
13182 {"hard", ARM_FLOAT_ABI_HARD},
13183 {"softfp", ARM_FLOAT_ABI_SOFTFP},
13184 {"soft", ARM_FLOAT_ABI_SOFT},
13188 struct arm_eabi_option_table
13191 unsigned int value;
13195 /* We only know how to output GNU and ver 4 (AAELF) formats. */
13196 static struct arm_eabi_option_table arm_eabis[] =
13198 {"gnu", EF_ARM_EABI_UNKNOWN},
13199 {"4", EF_ARM_EABI_VER4},
13204 struct arm_long_option_table
13206 char * option; /* Substring to match. */
13207 char * help; /* Help information. */
13208 int (* func) (char * subopt); /* Function to decode sub-option. */
13209 char * deprecated; /* If non-null, print this message. */
13213 arm_parse_extension (char * str, int * opt_p)
13215 while (str != NULL && *str != 0)
13217 struct arm_arch_extension_table * opt;
13223 as_bad (_("invalid architectural extension"));
13228 ext = strchr (str, '+');
13231 optlen = ext - str;
13233 optlen = strlen (str);
13237 as_bad (_("missing architectural extension"));
13241 for (opt = arm_extensions; opt->name != NULL; opt++)
13242 if (strncmp (opt->name, str, optlen) == 0)
13244 *opt_p |= opt->value;
13248 if (opt->name == NULL)
13250 as_bad (_("unknown architectural extnsion `%s'"), str);
13261 arm_parse_cpu (char * str)
13263 struct arm_cpu_option_table * opt;
13264 char * ext = strchr (str, '+');
13268 optlen = ext - str;
13270 optlen = strlen (str);
13274 as_bad (_("missing cpu name `%s'"), str);
13278 for (opt = arm_cpus; opt->name != NULL; opt++)
13279 if (strncmp (opt->name, str, optlen) == 0)
13281 mcpu_cpu_opt = opt->value;
13282 mcpu_fpu_opt = opt->default_fpu;
13285 return arm_parse_extension (ext, &mcpu_cpu_opt);
13290 as_bad (_("unknown cpu `%s'"), str);
13295 arm_parse_arch (char * str)
13297 struct arm_arch_option_table *opt;
13298 char *ext = strchr (str, '+');
13302 optlen = ext - str;
13304 optlen = strlen (str);
13308 as_bad (_("missing architecture name `%s'"), str);
13313 for (opt = arm_archs; opt->name != NULL; opt++)
13314 if (streq (opt->name, str))
13316 march_cpu_opt = opt->value;
13317 march_fpu_opt = opt->default_fpu;
13320 return arm_parse_extension (ext, &march_cpu_opt);
13325 as_bad (_("unknown architecture `%s'\n"), str);
13330 arm_parse_fpu (char * str)
13332 struct arm_fpu_option_table * opt;
13334 for (opt = arm_fpus; opt->name != NULL; opt++)
13335 if (streq (opt->name, str))
13337 mfpu_opt = opt->value;
13341 as_bad (_("unknown floating point format `%s'\n"), str);
13346 arm_parse_float_abi (char * str)
13348 struct arm_float_abi_option_table * opt;
13350 for (opt = arm_float_abis; opt->name != NULL; opt++)
13351 if (streq (opt->name, str))
13353 mfloat_abi_opt = opt->value;
13357 as_bad (_("unknown floating point abi `%s'\n"), str);
13363 arm_parse_eabi (char * str)
13365 struct arm_eabi_option_table *opt;
13367 for (opt = arm_eabis; opt->name != NULL; opt++)
13368 if (streq (opt->name, str))
13370 meabi_flags = opt->value;
13373 as_bad (_("unknown EABI `%s'\n"), str);
13378 struct arm_long_option_table arm_long_opts[] =
13380 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13381 arm_parse_cpu, NULL},
13382 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13383 arm_parse_arch, NULL},
13384 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13385 arm_parse_fpu, NULL},
13386 {"mfloat-abi=", N_("<abi>\t assemble for floating point ABI <abi>"),
13387 arm_parse_float_abi, NULL},
13389 {"meabi=", N_("<ver>\t assemble for eabi version <ver>"),
13390 arm_parse_eabi, NULL},
13392 {NULL, NULL, 0, NULL}
13396 md_parse_option (int c, char * arg)
13398 struct arm_option_table *opt;
13399 struct arm_long_option_table *lopt;
13405 target_big_endian = 1;
13411 target_big_endian = 0;
13416 /* Listing option. Just ignore these, we don't support additional
13421 for (opt = arm_opts; opt->option != NULL; opt++)
13423 if (c == opt->option[0]
13424 && ((arg == NULL && opt->option[1] == 0)
13425 || streq (arg, opt->option + 1)))
13427 #if WARN_DEPRECATED
13428 /* If the option is deprecated, tell the user. */
13429 if (opt->deprecated != NULL)
13430 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c,
13431 arg ? arg : "", _(opt->deprecated));
13434 if (opt->var != NULL)
13435 *opt->var = opt->value;
13441 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13443 /* These options are expected to have an argument. */
13444 if (c == lopt->option[0]
13446 && strncmp (arg, lopt->option + 1,
13447 strlen (lopt->option + 1)) == 0)
13449 #if WARN_DEPRECATED
13450 /* If the option is deprecated, tell the user. */
13451 if (lopt->deprecated != NULL)
13452 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c, arg,
13453 _(lopt->deprecated));
13456 /* Call the sup-option parser. */
13457 return lopt->func (arg + strlen (lopt->option) - 1);
13468 md_show_usage (FILE * fp)
13470 struct arm_option_table *opt;
13471 struct arm_long_option_table *lopt;
13473 fprintf (fp, _(" ARM-specific assembler options:\n"));
13475 for (opt = arm_opts; opt->option != NULL; opt++)
13476 if (opt->help != NULL)
13477 fprintf (fp, " -%-23s%s\n", opt->option, _(opt->help));
13479 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13480 if (lopt->help != NULL)
13481 fprintf (fp, " -%s%s\n", lopt->option, _(lopt->help));
13485 -EB assemble code for a big-endian cpu\n"));
13490 -EL assemble code for a little-endian cpu\n"));
13494 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13497 cons_fix_new_arm (fragS * frag,
13502 bfd_reloc_code_real_type type;
13506 FIXME: @@ Should look at CPU word size. */
13510 type = BFD_RELOC_8;
13513 type = BFD_RELOC_16;
13517 type = BFD_RELOC_32;
13520 type = BFD_RELOC_64;
13524 fix_new_exp (frag, where, (int) size, exp, pcrel, type);
13527 /* A good place to do this, although this was probably not intended
13528 for this kind of use. We need to dump the literal pool before
13529 references are made to a null symbol pointer. */
13534 literal_pool * pool;
13536 for (pool = list_of_pools; pool; pool = pool->next)
13538 /* Put it at the end of the relevent section. */
13539 subseg_set (pool->section, pool->sub_section);
13541 arm_elf_change_section ();
13548 arm_start_line_hook (void)
13550 last_label_seen = NULL;
13554 arm_frob_label (symbolS * sym)
13556 last_label_seen = sym;
13558 ARM_SET_THUMB (sym, thumb_mode);
13560 #if defined OBJ_COFF || defined OBJ_ELF
13561 ARM_SET_INTERWORK (sym, support_interwork);
13564 /* Note - do not allow local symbols (.Lxxx) to be labeled
13565 as Thumb functions. This is because these labels, whilst
13566 they exist inside Thumb code, are not the entry points for
13567 possible ARM->Thumb calls. Also, these labels can be used
13568 as part of a computed goto or switch statement. eg gcc
13569 can generate code that looks like this:
13571 ldr r2, [pc, .Laaa]
13581 The first instruction loads the address of the jump table.
13582 The second instruction converts a table index into a byte offset.
13583 The third instruction gets the jump address out of the table.
13584 The fourth instruction performs the jump.
13586 If the address stored at .Laaa is that of a symbol which has the
13587 Thumb_Func bit set, then the linker will arrange for this address
13588 to have the bottom bit set, which in turn would mean that the
13589 address computation performed by the third instruction would end
13590 up with the bottom bit set. Since the ARM is capable of unaligned
13591 word loads, the instruction would then load the incorrect address
13592 out of the jump table, and chaos would ensue. */
13593 if (label_is_thumb_function_name
13594 && (S_GET_NAME (sym)[0] != '.' || S_GET_NAME (sym)[1] != 'L')
13595 && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
13597 /* When the address of a Thumb function is taken the bottom
13598 bit of that address should be set. This will allow
13599 interworking between Arm and Thumb functions to work
13602 THUMB_SET_FUNC (sym, 1);
13604 label_is_thumb_function_name = FALSE;
13608 /* Adjust the symbol table. This marks Thumb symbols as distinct from
13612 arm_adjust_symtab (void)
13617 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13619 if (ARM_IS_THUMB (sym))
13621 if (THUMB_IS_FUNC (sym))
13623 /* Mark the symbol as a Thumb function. */
13624 if ( S_GET_STORAGE_CLASS (sym) == C_STAT
13625 || S_GET_STORAGE_CLASS (sym) == C_LABEL) /* This can happen! */
13626 S_SET_STORAGE_CLASS (sym, C_THUMBSTATFUNC);
13628 else if (S_GET_STORAGE_CLASS (sym) == C_EXT)
13629 S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC);
13631 as_bad (_("%s: unexpected function type: %d"),
13632 S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym));
13634 else switch (S_GET_STORAGE_CLASS (sym))
13637 S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
13640 S_SET_STORAGE_CLASS (sym, C_THUMBSTAT);
13643 S_SET_STORAGE_CLASS (sym, C_THUMBLABEL);
13651 if (ARM_IS_INTERWORK (sym))
13652 coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_flags = 0xFF;
13659 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13661 if (ARM_IS_THUMB (sym))
13663 elf_symbol_type * elf_sym;
13665 elf_sym = elf_symbol (symbol_get_bfdsym (sym));
13666 bind = ELF_ST_BIND (elf_sym->internal_elf_sym.st_info);
13668 if (! bfd_is_arm_mapping_symbol_name (elf_sym->symbol.name))
13670 /* If it's a .thumb_func, declare it as so,
13671 otherwise tag label as .code 16. */
13672 if (THUMB_IS_FUNC (sym))
13673 elf_sym->internal_elf_sym.st_info =
13674 ELF_ST_INFO (bind, STT_ARM_TFUNC);
13676 elf_sym->internal_elf_sym.st_info =
13677 ELF_ST_INFO (bind, STT_ARM_16BIT);
13685 arm_data_in_code (void)
13687 if (thumb_mode && ! strncmp (input_line_pointer + 1, "data:", 5))
13689 *input_line_pointer = '/';
13690 input_line_pointer += 5;
13691 *input_line_pointer = 0;
13699 arm_canonicalize_symbol_name (char * name)
13703 if (thumb_mode && (len = strlen (name)) > 5
13704 && streq (name + len - 5, "/data"))
13705 *(name + len - 5) = 0;
13710 #if defined OBJ_COFF || defined OBJ_ELF
13712 arm_validate_fix (fixS * fixP)
13714 /* If the destination of the branch is a defined symbol which does not have
13715 the THUMB_FUNC attribute, then we must be calling a function which has
13716 the (interfacearm) attribute. We look for the Thumb entry point to that
13717 function and change the branch to refer to that function instead. */
13718 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23
13719 && fixP->fx_addsy != NULL
13720 && S_IS_DEFINED (fixP->fx_addsy)
13721 && ! THUMB_IS_FUNC (fixP->fx_addsy))
13723 fixP->fx_addsy = find_real_start (fixP->fx_addsy);
13729 arm_force_relocation (struct fix * fixp)
13731 #if defined (OBJ_COFF) && defined (TE_PE)
13732 if (fixp->fx_r_type == BFD_RELOC_RVA)
13736 if (fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
13737 || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
13738 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX
13739 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23)
13743 /* Resolve these relocations even if the symbol is extern or weak. */
13744 if (fixp->fx_r_type == BFD_RELOC_ARM_IMMEDIATE
13745 || fixp->fx_r_type == BFD_RELOC_ARM_OFFSET_IMM
13746 || fixp->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
13749 return generic_force_reloc (fixp);
13753 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
13754 local labels from being added to the output symbol table when they
13755 are used with the ADRL pseudo op. The ADRL relocation should always
13756 be resolved before the binbary is emitted, so it is safe to say that
13757 it is adjustable. */
13760 arm_fix_adjustable (fixS * fixP)
13762 if (fixP->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
13769 /* Relocations against Thumb function names must be left unadjusted,
13770 so that the linker can use this information to correctly set the
13771 bottom bit of their addresses. The MIPS version of this function
13772 also prevents relocations that are mips-16 specific, but I do not
13773 know why it does this.
13776 There is one other problem that ought to be addressed here, but
13777 which currently is not: Taking the address of a label (rather
13778 than a function) and then later jumping to that address. Such
13779 addresses also ought to have their bottom bit set (assuming that
13780 they reside in Thumb code), but at the moment they will not. */
13783 arm_fix_adjustable (fixS * fixP)
13785 if (fixP->fx_addsy == NULL)
13788 if (THUMB_IS_FUNC (fixP->fx_addsy)
13789 && fixP->fx_subsy == NULL)
13792 /* We need the symbol name for the VTABLE entries. */
13793 if ( fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
13794 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
13797 /* Don't allow symbols to be discarded on GOT related relocs. */
13798 if (fixP->fx_r_type == BFD_RELOC_ARM_PLT32
13799 || fixP->fx_r_type == BFD_RELOC_ARM_GOT32
13800 || fixP->fx_r_type == BFD_RELOC_ARM_GOTOFF
13801 || fixP->fx_r_type == BFD_RELOC_ARM_TLS_GD32
13802 || fixP->fx_r_type == BFD_RELOC_ARM_TLS_LE32
13803 || fixP->fx_r_type == BFD_RELOC_ARM_TLS_IE32
13804 || fixP->fx_r_type == BFD_RELOC_ARM_TLS_LDM32
13805 || fixP->fx_r_type == BFD_RELOC_ARM_TLS_LDO32
13806 || fixP->fx_r_type == BFD_RELOC_ARM_TARGET2)
13813 elf32_arm_target_format (void)
13816 return (target_big_endian
13817 ? "elf32-bigarm-symbian"
13818 : "elf32-littlearm-symbian");
13819 #elif defined (TE_VXWORKS)
13820 return (target_big_endian
13821 ? "elf32-bigarm-vxworks"
13822 : "elf32-littlearm-vxworks");
13824 if (target_big_endian)
13825 return "elf32-bigarm";
13827 return "elf32-littlearm";
13832 armelf_frob_symbol (symbolS * symp,
13835 elf_frob_symbol (symp, puntp);
13839 s_arm_elf_cons (int nbytes)
13843 #ifdef md_flush_pending_output
13844 md_flush_pending_output ();
13847 if (is_it_end_of_statement ())
13849 demand_empty_rest_of_line ();
13853 #ifdef md_cons_align
13854 md_cons_align (nbytes);
13857 mapping_state (MAP_DATA);
13860 bfd_reloc_code_real_type reloc;
13864 sym_start = input_line_pointer;
13865 expression (& exp);
13866 sym_len = input_line_pointer - sym_start;
13868 if (exp.X_op == O_symbol
13869 && * input_line_pointer == '('
13870 && (reloc = arm_parse_reloc ()) != BFD_RELOC_UNUSED)
13872 reloc_howto_type *howto = bfd_reloc_type_lookup (stdoutput, reloc);
13873 int size = bfd_get_reloc_size (howto);
13876 as_bad ("%s relocations do not fit in %d bytes",
13877 howto->name, nbytes);
13881 int offset = nbytes - size;
13882 char *saved_buf = alloca (sym_len), *saved_input;
13884 /* We've parsed an expression stopping at O_symbol. But there
13885 may be more expression left now that we have parsed the
13886 relocation marker. Parse it again. */
13887 saved_input = input_line_pointer - sym_len;
13888 memcpy (saved_buf, saved_input, sym_len);
13889 memmove (saved_input, sym_start, sym_len);
13890 input_line_pointer = saved_input;
13891 expression (& exp);
13892 memcpy (saved_input, saved_buf, sym_len);
13893 assert (input_line_pointer >= saved_input + sym_len);
13895 p = frag_more ((int) nbytes);
13896 fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size,
13901 emit_expr (&exp, (unsigned int) nbytes);
13903 while (*input_line_pointer++ == ',');
13905 /* Put terminator back into stream. */
13906 input_line_pointer --;
13907 demand_empty_rest_of_line ();
13911 /* Parse a .rel31 directive. */
13914 s_arm_rel31 (int ignored ATTRIBUTE_UNUSED)
13920 SKIP_WHITESPACE ();
13923 if (*input_line_pointer == '1')
13924 highbit = 0x80000000;
13925 else if (*input_line_pointer != '0')
13926 as_bad (_("expected 0 or 1"));
13928 input_line_pointer++;
13929 SKIP_WHITESPACE ();
13930 if (*input_line_pointer != ',')
13931 as_bad (_("missing comma"));
13932 input_line_pointer++;
13934 #ifdef md_flush_pending_output
13935 md_flush_pending_output ();
13938 #ifdef md_cons_align
13942 mapping_state (MAP_DATA);
13947 md_number_to_chars (p, highbit, 4);
13948 fix_new_arm (frag_now, p - frag_now->fr_literal, 4, &exp, 1,
13949 BFD_RELOC_ARM_PREL31);
13951 demand_empty_rest_of_line ();
13954 /* Code to deal with unwinding tables. */
13956 static void add_unwind_adjustsp (offsetT);
13958 /* Switch to section NAME and create section if necessary. It's
13959 rather ugly that we have to manipulate input_line_pointer but I
13960 don't see any other way to accomplish the same thing without
13961 changing obj-elf.c (which may be the Right Thing, in the end).
13962 Copied from tc-ia64.c. */
13965 set_section (char *name)
13967 char *saved_input_line_pointer;
13969 saved_input_line_pointer = input_line_pointer;
13970 input_line_pointer = name;
13971 obj_elf_section (0);
13972 input_line_pointer = saved_input_line_pointer;
13975 /* Cenerate and deferred unwind frame offset. */
13978 flush_pending_unwind (void)
13982 offset = unwind.pending_offset;
13983 unwind.pending_offset = 0;
13985 add_unwind_adjustsp (offset);
13988 /* Add an opcode to this list for this function. Two-byte opcodes should
13989 be passed as op[0] << 8 | op[1]. The list of opcodes is built in reverse
13993 add_unwind_opcode (valueT op, int length)
13995 /* Add any deferred stack adjustment. */
13996 if (unwind.pending_offset)
13997 flush_pending_unwind ();
13999 unwind.sp_restored = 0;
14001 if (unwind.opcode_count + length > unwind.opcode_alloc)
14003 unwind.opcode_alloc += ARM_OPCODE_CHUNK_SIZE;
14004 if (unwind.opcodes)
14005 unwind.opcodes = xrealloc (unwind.opcodes,
14006 unwind.opcode_alloc);
14008 unwind.opcodes = xmalloc (unwind.opcode_alloc);
14013 unwind.opcodes[unwind.opcode_count] = op & 0xff;
14015 unwind.opcode_count++;
14019 /* Add unwind opcodes to adjust the stack pointer. */
14022 add_unwind_adjustsp (offsetT offset)
14026 if (offset > 0x200)
14028 /* We need at most 5 bytes to hold a 32-bit value in a uleb128. */
14033 /* Long form: 0xb2, uleb128. */
14034 /* This might not fit in a word so add the individual bytes,
14035 remembering the list is built in reverse order. */
14036 o = (valueT) ((offset - 0x204) >> 2);
14038 add_unwind_opcode (0, 1);
14040 /* Calculate the uleb128 encoding of the offset. */
14044 bytes[n] = o & 0x7f;
14050 /* Add the insn. */
14052 add_unwind_opcode (bytes[n - 1], 1);
14053 add_unwind_opcode (0xb2, 1);
14055 else if (offset > 0x100)
14057 /* Two short opcodes. */
14058 add_unwind_opcode (0x3f, 1);
14059 op = (offset - 0x104) >> 2;
14060 add_unwind_opcode (op, 1);
14062 else if (offset > 0)
14064 /* Short opcode. */
14065 op = (offset - 4) >> 2;
14066 add_unwind_opcode (op, 1);
14068 else if (offset < 0)
14071 while (offset > 0x100)
14073 add_unwind_opcode (0x7f, 1);
14076 op = ((offset - 4) >> 2) | 0x40;
14077 add_unwind_opcode (op, 1);
14081 /* Finish the list of unwind opcodes for this function. */
14083 finish_unwind_opcodes (void)
14087 if (unwind.fp_used)
14089 /* Adjust sp as neccessary. */
14090 unwind.pending_offset += unwind.fp_offset - unwind.frame_size;
14091 flush_pending_unwind ();
14093 /* After restoring sp from the frame pointer. */
14094 op = 0x90 | unwind.fp_reg;
14095 add_unwind_opcode (op, 1);
14098 flush_pending_unwind ();
14102 /* Start an exception table entry. If idx is nonzero this is an index table
14106 start_unwind_section (const segT text_seg, int idx)
14108 const char * text_name;
14109 const char * prefix;
14110 const char * prefix_once;
14114 size_t sec_name_len;
14118 prefix = ELF_STRING_ARM_unwind;
14119 prefix_once = ELF_STRING_ARM_unwind_once;
14123 prefix = ELF_STRING_ARM_unwind_info;
14124 prefix_once = ELF_STRING_ARM_unwind_info_once;
14127 text_name = segment_name (text_seg);
14128 if (streq (text_name, ".text"))
14131 if (strncmp (text_name, ".gnu.linkonce.t.",
14132 strlen (".gnu.linkonce.t.")) == 0)
14134 prefix = prefix_once;
14135 text_name += strlen (".gnu.linkonce.t.");
14138 prefix_len = strlen (prefix);
14139 text_len = strlen (text_name);
14140 sec_name_len = prefix_len + text_len;
14141 sec_name = alloca (sec_name_len + 1);
14142 memcpy (sec_name, prefix, prefix_len);
14143 memcpy (sec_name + prefix_len, text_name, text_len);
14144 sec_name[prefix_len + text_len] = '\0';
14146 /* Handle COMDAT group. */
14147 if (prefix != prefix_once && (text_seg->flags & SEC_LINK_ONCE) != 0)
14150 size_t len, group_name_len;
14151 const char *group_name = elf_group_name (text_seg);
14153 if (group_name == NULL)
14155 as_bad ("Group section `%s' has no group signature",
14156 segment_name (text_seg));
14157 ignore_rest_of_line ();
14160 /* We have to construct a fake section directive. */
14161 group_name_len = strlen (group_name);
14167 len = (sec_name_len
14168 + prefix_len /* ,"aG",%sectiontype, */
14169 + group_name_len /* ,group_name */
14170 + 7); /* ,comdat */
14172 section = alloca (len + 1);
14173 memcpy (section, sec_name, sec_name_len);
14175 memcpy (section + sec_name_len, ",\"aG\",%exidx,", 13);
14177 memcpy (section + sec_name_len, ",\"aG\",%progbits,", 16);
14178 memcpy (section + sec_name_len + prefix_len, group_name, group_name_len);
14179 memcpy (section + len - 7, ",comdat", 7);
14180 section [len] = '\0';
14181 set_section (section);
14185 set_section (sec_name);
14186 bfd_set_section_flags (stdoutput, now_seg,
14187 SEC_LOAD | SEC_ALLOC | SEC_READONLY);
14190 /* Set the setion link for index tables. */
14192 elf_linked_to_section (now_seg) = text_seg;
14196 /* Start an unwind table entry. HAVE_DATA is nonzero if we have additional
14197 personality routine data. Returns zero, or the index table value for
14198 and inline entry. */
14201 create_unwind_entry (int have_data)
14206 /* The current word of data. */
14208 /* The number of bytes left in this word. */
14211 finish_unwind_opcodes ();
14213 /* Remember the current text section. */
14214 unwind.saved_seg = now_seg;
14215 unwind.saved_subseg = now_subseg;
14217 start_unwind_section (now_seg, 0);
14219 if (unwind.personality_routine == NULL)
14221 if (unwind.personality_index == -2)
14224 as_bad (_("handerdata in cantunwind frame"));
14225 return 1; /* EXIDX_CANTUNWIND. */
14228 /* Use a default personality routine if none is specified. */
14229 if (unwind.personality_index == -1)
14231 if (unwind.opcode_count > 3)
14232 unwind.personality_index = 1;
14234 unwind.personality_index = 0;
14237 /* Space for the personality routine entry. */
14238 if (unwind.personality_index == 0)
14240 if (unwind.opcode_count > 3)
14241 as_bad (_("too many unwind opcodes for personality routine 0"));
14245 /* All the data is inline in the index table. */
14248 while (unwind.opcode_count > 0)
14250 unwind.opcode_count--;
14251 data = (data << 8) | unwind.opcodes[unwind.opcode_count];
14255 /* Pad with "finish" opcodes. */
14257 data = (data << 8) | 0xb0;
14264 /* We get two opcodes "free" in the first word. */
14265 size = unwind.opcode_count - 2;
14268 /* An extra byte is required for the opcode count. */
14269 size = unwind.opcode_count + 1;
14271 size = (size + 3) >> 2;
14273 as_bad (_("too many unwind opcodes"));
14275 frag_align (2, 0, 0);
14276 record_alignment (now_seg, 2);
14277 unwind.table_entry = expr_build_dot ();
14279 /* Allocate the table entry. */
14280 ptr = frag_more ((size << 2) + 4);
14281 where = frag_now_fix () - ((size << 2) + 4);
14283 switch (unwind.personality_index)
14286 /* ??? Should this be a PLT generating relocation? */
14287 /* Custom personality routine. */
14288 fix_new (frag_now, where, 4, unwind.personality_routine, 0, 1,
14289 BFD_RELOC_ARM_PREL31);
14294 /* Set the first byte to the number of additional words. */
14299 /* ABI defined personality routines. */
14301 /* Three opcodes bytes are packed into the first word. */
14308 /* The size and first two opcode bytes go in the first word. */
14309 data = ((0x80 + unwind.personality_index) << 8) | size;
14314 /* Should never happen. */
14318 /* Pack the opcodes into words (MSB first), reversing the list at the same
14320 while (unwind.opcode_count > 0)
14324 md_number_to_chars (ptr, data, 4);
14329 unwind.opcode_count--;
14331 data = (data << 8) | unwind.opcodes[unwind.opcode_count];
14334 /* Finish off the last word. */
14337 /* Pad with "finish" opcodes. */
14339 data = (data << 8) | 0xb0;
14341 md_number_to_chars (ptr, data, 4);
14346 /* Add an empty descriptor if there is no user-specified data. */
14347 ptr = frag_more (4);
14348 md_number_to_chars (ptr, 0, 4);
14355 /* Parse an unwind_fnstart directive. Simply records the current location. */
14358 s_arm_unwind_fnstart (int ignored ATTRIBUTE_UNUSED)
14360 demand_empty_rest_of_line ();
14361 /* Mark the start of the function. */
14362 unwind.proc_start = expr_build_dot ();
14364 /* Reset the rest of the unwind info. */
14365 unwind.opcode_count = 0;
14366 unwind.table_entry = NULL;
14367 unwind.personality_routine = NULL;
14368 unwind.personality_index = -1;
14369 unwind.frame_size = 0;
14370 unwind.fp_offset = 0;
14371 unwind.fp_reg = 13;
14372 unwind.fp_used = 0;
14373 unwind.sp_restored = 0;
14377 /* Parse a handlerdata directive. Creates the exception handling table entry
14378 for the function. */
14381 s_arm_unwind_handlerdata (int ignored ATTRIBUTE_UNUSED)
14383 demand_empty_rest_of_line ();
14384 if (unwind.table_entry)
14385 as_bad (_("dupicate .handlerdata directive"));
14387 create_unwind_entry (1);
14390 /* Parse an unwind_fnend directive. Generates the index table entry. */
14393 s_arm_unwind_fnend (int ignored ATTRIBUTE_UNUSED)
14399 demand_empty_rest_of_line ();
14401 /* Add eh table entry. */
14402 if (unwind.table_entry == NULL)
14403 val = create_unwind_entry (0);
14407 /* Add index table entry. This is two words. */
14408 start_unwind_section (unwind.saved_seg, 1);
14409 frag_align (2, 0, 0);
14410 record_alignment (now_seg, 2);
14412 ptr = frag_more (8);
14413 where = frag_now_fix () - 8;
14415 /* Self relative offset of the function start. */
14416 fix_new (frag_now, where, 4, unwind.proc_start, 0, 1,
14417 BFD_RELOC_ARM_PREL31);
14419 /* Indicate dependency on EHABI-defined personality routines to the
14420 linker, if it hasn't been done already. */
14421 if (unwind.personality_index >= 0 && unwind.personality_index < 3)
14423 char *name[] = { "__aeabi_unwind_cpp_pr0",
14424 "__aeabi_unwind_cpp_pr1",
14425 "__aeabi_unwind_cpp_pr2" };
14426 if (!(marked_pr_dependency & (1 << unwind.personality_index)))
14428 symbolS *pr = symbol_find_or_make (name[unwind.personality_index]);
14429 fix_new (frag_now, where, 0, pr, 0, 1, BFD_RELOC_NONE);
14430 marked_pr_dependency |= 1 << unwind.personality_index;
14431 seg_info (now_seg)->tc_segment_info_data.marked_pr_dependency
14432 = marked_pr_dependency;
14437 /* Inline exception table entry. */
14438 md_number_to_chars (ptr + 4, val, 4);
14440 /* Self relative offset of the table entry. */
14441 fix_new (frag_now, where + 4, 4, unwind.table_entry, 0, 1,
14442 BFD_RELOC_ARM_PREL31);
14444 /* Restore the original section. */
14445 subseg_set (unwind.saved_seg, unwind.saved_subseg);
14449 /* Parse an unwind_cantunwind directive. */
14452 s_arm_unwind_cantunwind (int ignored ATTRIBUTE_UNUSED)
14454 demand_empty_rest_of_line ();
14455 if (unwind.personality_routine || unwind.personality_index != -1)
14456 as_bad (_("personality routine specified for cantunwind frame"));
14458 unwind.personality_index = -2;
14462 /* Parse a personalityindex directive. */
14465 s_arm_unwind_personalityindex (int ignored ATTRIBUTE_UNUSED)
14469 if (unwind.personality_routine || unwind.personality_index != -1)
14470 as_bad (_("duplicate .personalityindex directive"));
14472 SKIP_WHITESPACE ();
14476 if (exp.X_op != O_constant
14477 || exp.X_add_number < 0 || exp.X_add_number > 15)
14479 as_bad (_("bad personality routine number"));
14480 ignore_rest_of_line ();
14484 unwind.personality_index = exp.X_add_number;
14486 demand_empty_rest_of_line ();
14490 /* Parse a personality directive. */
14493 s_arm_unwind_personality (int ignored ATTRIBUTE_UNUSED)
14497 if (unwind.personality_routine || unwind.personality_index != -1)
14498 as_bad (_("duplicate .personality directive"));
14500 SKIP_WHITESPACE ();
14501 name = input_line_pointer;
14502 c = get_symbol_end ();
14503 p = input_line_pointer;
14504 unwind.personality_routine = symbol_find_or_make (name);
14506 SKIP_WHITESPACE ();
14507 demand_empty_rest_of_line ();
14511 /* Parse a directive saving core registers. */
14514 s_arm_unwind_save_core (void)
14520 SKIP_WHITESPACE ();
14521 range = reg_list (&input_line_pointer);
14524 as_bad (_("expected register list"));
14525 ignore_rest_of_line ();
14529 demand_empty_rest_of_line ();
14531 /* Turn .unwind_movsp ip followed by .unwind_save {..., ip, ...}
14532 into .unwind_save {..., sp...}. We aren't bothered about the value of
14533 ip because it is clobbered by calls. */
14534 if (unwind.sp_restored && unwind.fp_reg == 12
14535 && (range & 0x3000) == 0x1000)
14537 unwind.opcode_count--;
14538 unwind.sp_restored = 0;
14539 range = (range | 0x2000) & ~0x1000;
14540 unwind.pending_offset = 0;
14543 /* See if we can use the short opcodes. These pop a block of upto 8
14544 registers starting with r4, plus maybe r14. */
14545 for (n = 0; n < 8; n++)
14547 /* Break at the first non-saved register. */
14548 if ((range & (1 << (n + 4))) == 0)
14551 /* See if there are any other bits set. */
14552 if (n == 0 || (range & (0xfff0 << n) & 0xbff0) != 0)
14554 /* Use the long form. */
14555 op = 0x8000 | ((range >> 4) & 0xfff);
14556 add_unwind_opcode (op, 2);
14560 /* Use the short form. */
14561 if (range & 0x4000)
14562 op = 0xa8; /* Pop r14. */
14564 op = 0xa0; /* Do not pop r14. */
14566 add_unwind_opcode (op, 1);
14572 op = 0xb100 | (range & 0xf);
14573 add_unwind_opcode (op, 2);
14576 /* Record the number of bytes pushed. */
14577 for (n = 0; n < 16; n++)
14579 if (range & (1 << n))
14580 unwind.frame_size += 4;
14585 /* Parse a directive saving FPA registers. */
14588 s_arm_unwind_save_fpa (int reg)
14594 /* Get Number of registers to transfer. */
14595 if (skip_past_comma (&input_line_pointer) != FAIL)
14598 exp.X_op = O_illegal;
14600 if (exp.X_op != O_constant)
14602 as_bad (_("expected , <constant>"));
14603 ignore_rest_of_line ();
14607 num_regs = exp.X_add_number;
14609 if (num_regs < 1 || num_regs > 4)
14611 as_bad (_("number of registers must be in the range [1:4]"));
14612 ignore_rest_of_line ();
14616 demand_empty_rest_of_line ();
14621 op = 0xb4 | (num_regs - 1);
14622 add_unwind_opcode (op, 1);
14627 op = 0xc800 | (reg << 4) | (num_regs - 1);
14628 add_unwind_opcode (op, 2);
14630 unwind.frame_size += num_regs * 12;
14634 /* Parse a directive saving VFP registers. */
14637 s_arm_unwind_save_vfp (void)
14643 count = vfp_parse_reg_list (&input_line_pointer, ®, 1);
14646 as_bad (_("expected register list"));
14647 ignore_rest_of_line ();
14651 demand_empty_rest_of_line ();
14656 op = 0xb8 | (count - 1);
14657 add_unwind_opcode (op, 1);
14662 op = 0xb300 | (reg << 4) | (count - 1);
14663 add_unwind_opcode (op, 2);
14665 unwind.frame_size += count * 8 + 4;
14669 /* Parse a directive saving iWMMXt registers. */
14672 s_arm_unwind_save_wmmx (void)
14681 if (*input_line_pointer == '{')
14682 input_line_pointer++;
14688 reg = arm_reg_parse (&input_line_pointer,
14689 all_reg_maps[REG_TYPE_IWMMXT].htab);
14691 if (wr_register (reg))
14693 i = reg & ~WR_PREFIX;
14695 as_tsktsk (_("register list not in ascending order"));
14698 else if (wcg_register (reg))
14700 i = (reg & ~WC_PREFIX) - 8;
14702 as_tsktsk (_("register list not in ascending order"));
14703 wcg_mask |= 1 << i;
14707 as_bad (_("expected wr or wcgr"));
14711 SKIP_WHITESPACE ();
14712 if (*input_line_pointer == '-')
14714 hi_reg = arm_reg_parse (&input_line_pointer,
14715 all_reg_maps[REG_TYPE_IWMMXT].htab);
14716 if (wr_register (reg) && wr_register (hi_reg))
14718 for (; reg < hi_reg; reg++)
14719 wr_mask |= 1 << (reg & ~WR_PREFIX);
14721 else if (wcg_register (reg) && wcg_register (hi_reg))
14723 for (; reg < hi_reg; reg++)
14724 wcg_mask |= 1 << ((reg & ~WC_PREFIX) - 8);
14728 as_bad (_("bad register range"));
14733 while (skip_past_comma (&input_line_pointer) != FAIL);
14735 SKIP_WHITESPACE ();
14736 if (*input_line_pointer == '}')
14737 input_line_pointer++;
14739 demand_empty_rest_of_line ();
14741 if (wr_mask && wcg_mask)
14743 as_bad (_("inconsistent register types"));
14747 /* Generate any deferred opcodes becuuse we're going to be looking at
14749 flush_pending_unwind ();
14753 for (i = 0; i < 16; i++)
14755 if (wcg_mask & (1 << i))
14756 unwind.frame_size += 4;
14758 op = 0xc700 | wcg_mask;
14759 add_unwind_opcode (op, 2);
14763 for (i = 0; i < 16; i++)
14765 if (wr_mask & (1 << i))
14766 unwind.frame_size += 8;
14768 /* Attempt to combine with a previous opcode. We do this because gcc
14769 likes to output separate unwind directives for a single block of
14771 if (unwind.opcode_count > 0)
14773 i = unwind.opcodes[unwind.opcode_count - 1];
14774 if ((i & 0xf8) == 0xc0)
14777 /* Only merge if the blocks are contiguous. */
14780 if ((wr_mask & 0xfe00) == (1 << 9))
14782 wr_mask |= ((1 << (i + 11)) - 1) & 0xfc00;
14783 unwind.opcode_count--;
14786 else if (i == 6 && unwind.opcode_count >= 2)
14788 i = unwind.opcodes[unwind.opcode_count - 2];
14792 op = 0xffff << (reg - 1);
14794 || ((wr_mask & op) == (1u << (reg - 1))))
14796 op = (1 << (reg + i + 1)) - 1;
14797 op &= ~((1 << reg) - 1);
14799 unwind.opcode_count -= 2;
14806 /* We want to generate opcodes in the order the registers have been
14807 saved, ie. descending order. */
14808 for (reg = 15; reg >= -1; reg--)
14810 /* Save registers in blocks. */
14812 || !(wr_mask & (1 << reg)))
14814 /* We found an unsaved reg. Generate opcodes to save the
14815 preceeding block. */
14821 op = 0xc0 | (hi_reg - 10);
14822 add_unwind_opcode (op, 1);
14827 op = 0xc600 | ((reg + 1) << 4) | ((hi_reg - reg) - 1);
14828 add_unwind_opcode (op, 2);
14837 ignore_rest_of_line ();
14841 /* Parse an unwind_save directive. */
14844 s_arm_unwind_save (int ignored ATTRIBUTE_UNUSED)
14849 /* Figure out what sort of save we have. */
14850 SKIP_WHITESPACE ();
14851 saved_ptr = input_line_pointer;
14853 reg = arm_reg_parse (&input_line_pointer, all_reg_maps[REG_TYPE_FN].htab);
14856 s_arm_unwind_save_fpa (reg);
14860 if (*input_line_pointer == '{')
14861 input_line_pointer++;
14863 SKIP_WHITESPACE ();
14865 reg = arm_reg_parse (&input_line_pointer, all_reg_maps[REG_TYPE_RN].htab);
14868 input_line_pointer = saved_ptr;
14869 s_arm_unwind_save_core ();
14873 reg = arm_reg_parse (&input_line_pointer, all_reg_maps[REG_TYPE_DN].htab);
14876 input_line_pointer = saved_ptr;
14877 s_arm_unwind_save_vfp ();
14881 reg = arm_reg_parse (&input_line_pointer,
14882 all_reg_maps[REG_TYPE_IWMMXT].htab);
14885 input_line_pointer = saved_ptr;
14886 s_arm_unwind_save_wmmx ();
14890 /* TODO: Maverick registers. */
14891 as_bad (_("unrecognised register"));
14895 /* Parse an unwind_movsp directive. */
14898 s_arm_unwind_movsp (int ignored ATTRIBUTE_UNUSED)
14903 SKIP_WHITESPACE ();
14904 reg = reg_required_here (&input_line_pointer, -1);
14907 as_bad (_("ARM register expected"));
14908 ignore_rest_of_line ();
14912 if (reg == 13 || reg == 15)
14914 as_bad (_("r%d not permitted in .unwind_movsp directive"), reg);
14915 ignore_rest_of_line ();
14919 if (unwind.fp_reg != 13)
14920 as_bad (_("unexpected .unwind_movsp directive"));
14922 /* Generate opcode to restore the value. */
14924 add_unwind_opcode (op, 1);
14926 /* Record the information for later. */
14927 unwind.fp_reg = reg;
14928 unwind.fp_offset = unwind.frame_size;
14929 unwind.sp_restored = 1;
14930 demand_empty_rest_of_line ();
14934 /* Parse #<number>. */
14937 require_hashconst (int * val)
14941 SKIP_WHITESPACE ();
14942 if (*input_line_pointer == '#')
14944 input_line_pointer++;
14948 exp.X_op = O_illegal;
14950 if (exp.X_op != O_constant)
14952 as_bad (_("expected #constant"));
14953 ignore_rest_of_line ();
14956 *val = exp.X_add_number;
14960 /* Parse an unwind_pad directive. */
14963 s_arm_unwind_pad (int ignored ATTRIBUTE_UNUSED)
14967 if (require_hashconst (&offset) == FAIL)
14972 as_bad (_("stack increment must be multiple of 4"));
14973 ignore_rest_of_line ();
14977 /* Don't generate any opcodes, just record the details for later. */
14978 unwind.frame_size += offset;
14979 unwind.pending_offset += offset;
14981 demand_empty_rest_of_line ();
14984 /* Parse an unwind_setfp directive. */
14987 s_arm_unwind_setfp (int ignored ATTRIBUTE_UNUSED)
14993 fp_reg = reg_required_here (&input_line_pointer, -1);
14994 if (skip_past_comma (&input_line_pointer) == FAIL)
14997 sp_reg = reg_required_here (&input_line_pointer, -1);
14999 if (fp_reg == FAIL || sp_reg == FAIL)
15001 as_bad (_("expected <reg>, <reg>"));
15002 ignore_rest_of_line ();
15006 /* Optonal constant. */
15007 if (skip_past_comma (&input_line_pointer) != FAIL)
15009 if (require_hashconst (&offset) == FAIL)
15015 demand_empty_rest_of_line ();
15017 if (sp_reg != 13 && sp_reg != unwind.fp_reg)
15019 as_bad (_("register must be either sp or set by a previous"
15020 "unwind_movsp directive"));
15024 /* Don't generate any opcodes, just record the information for later. */
15025 unwind.fp_reg = fp_reg;
15026 unwind.fp_used = 1;
15028 unwind.fp_offset = unwind.frame_size - offset;
15030 unwind.fp_offset -= offset;
15033 /* Parse an unwind_raw directive. */
15036 s_arm_unwind_raw (int ignored ATTRIBUTE_UNUSED)
15039 /* This is an arbitary limit. */
15040 unsigned char op[16];
15043 SKIP_WHITESPACE ();
15045 if (exp.X_op == O_constant
15046 && skip_past_comma (&input_line_pointer) != FAIL)
15048 unwind.frame_size += exp.X_add_number;
15052 exp.X_op = O_illegal;
15054 if (exp.X_op != O_constant)
15056 as_bad (_("expected <offset>, <opcode>"));
15057 ignore_rest_of_line ();
15063 /* Parse the opcode. */
15068 as_bad (_("unwind opcode too long"));
15069 ignore_rest_of_line ();
15071 if (exp.X_op != O_constant || exp.X_add_number & ~0xff)
15073 as_bad (_("invalid unwind opcode"));
15074 ignore_rest_of_line ();
15077 op[count++] = exp.X_add_number;
15079 /* Parse the next byte. */
15080 if (skip_past_comma (&input_line_pointer) == FAIL)
15086 /* Add the opcode bytes in reverse order. */
15088 add_unwind_opcode (op[count], 1);
15090 demand_empty_rest_of_line ();
15093 #endif /* OBJ_ELF */
15095 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
15096 of an rs_align_code fragment. */
15099 arm_handle_align (fragS * fragP)
15101 static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 };
15102 static char const thumb_noop[2] = { 0xc0, 0x46 };
15103 static char const arm_bigend_noop[4] = { 0xe1, 0xa0, 0x00, 0x00 };
15104 static char const thumb_bigend_noop[2] = { 0x46, 0xc0 };
15106 int bytes, fix, noop_size;
15110 if (fragP->fr_type != rs_align_code)
15113 bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
15114 p = fragP->fr_literal + fragP->fr_fix;
15117 if (bytes > MAX_MEM_FOR_RS_ALIGN_CODE)
15118 bytes &= MAX_MEM_FOR_RS_ALIGN_CODE;
15120 if (fragP->tc_frag_data)
15122 if (target_big_endian)
15123 noop = thumb_bigend_noop;
15126 noop_size = sizeof (thumb_noop);
15130 if (target_big_endian)
15131 noop = arm_bigend_noop;
15134 noop_size = sizeof (arm_noop);
15137 if (bytes & (noop_size - 1))
15139 fix = bytes & (noop_size - 1);
15140 memset (p, 0, fix);
15145 while (bytes >= noop_size)
15147 memcpy (p, noop, noop_size);
15149 bytes -= noop_size;
15153 fragP->fr_fix += fix;
15154 fragP->fr_var = noop_size;
15157 /* Called from md_do_align. Used to create an alignment
15158 frag in a code section. */
15161 arm_frag_align_code (int n, int max)
15165 /* We assume that there will never be a requirement
15166 to support alignments greater than 32 bytes. */
15167 if (max > MAX_MEM_FOR_RS_ALIGN_CODE)
15168 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
15170 p = frag_var (rs_align_code,
15171 MAX_MEM_FOR_RS_ALIGN_CODE,
15173 (relax_substateT) max,
15180 /* Perform target specific initialisation of a frag. */
15183 arm_init_frag (fragS * fragP)
15185 /* Record whether this frag is in an ARM or a THUMB area. */
15186 fragP->tc_frag_data = thumb_mode;
15191 /* Convert REGNAME to a DWARF-2 register number. */
15194 tc_arm_regname_to_dw2regnum (const char *regname)
15198 for (i = 0; rn_table[i].name; i++)
15199 if (streq (regname, rn_table[i].name))
15200 return rn_table[i].number;
15205 /* Initialize the DWARF-2 unwind information for this procedure. */
15208 tc_arm_frame_initial_instructions (void)
15210 cfi_add_CFA_def_cfa (REG_SP, 0);
15214 /* This table describes all the machine specific pseudo-ops the assembler
15215 has to support. The fields are:
15216 pseudo-op name without dot
15217 function to call to execute this pseudo-op
15218 Integer arg to pass to the function. */
15220 const pseudo_typeS md_pseudo_table[] =
15222 /* Never called because '.req' does not start a line. */
15223 { "req", s_req, 0 },
15224 { "unreq", s_unreq, 0 },
15225 { "bss", s_bss, 0 },
15226 { "align", s_align, 0 },
15227 { "arm", s_arm, 0 },
15228 { "thumb", s_thumb, 0 },
15229 { "code", s_code, 0 },
15230 { "force_thumb", s_force_thumb, 0 },
15231 { "thumb_func", s_thumb_func, 0 },
15232 { "thumb_set", s_thumb_set, 0 },
15233 { "even", s_even, 0 },
15234 { "ltorg", s_ltorg, 0 },
15235 { "pool", s_ltorg, 0 },
15237 { "word", s_arm_elf_cons, 4 },
15238 { "long", s_arm_elf_cons, 4 },
15239 { "rel31", s_arm_rel31, 0 },
15240 { "fnstart", s_arm_unwind_fnstart, 0 },
15241 { "fnend", s_arm_unwind_fnend, 0 },
15242 { "cantunwind", s_arm_unwind_cantunwind, 0 },
15243 { "personality", s_arm_unwind_personality, 0 },
15244 { "personalityindex", s_arm_unwind_personalityindex, 0 },
15245 { "handlerdata", s_arm_unwind_handlerdata, 0 },
15246 { "save", s_arm_unwind_save, 0 },
15247 { "movsp", s_arm_unwind_movsp, 0 },
15248 { "pad", s_arm_unwind_pad, 0 },
15249 { "setfp", s_arm_unwind_setfp, 0 },
15250 { "unwind_raw", s_arm_unwind_raw, 0 },
15252 { "word", cons, 4},
15254 { "extend", float_cons, 'x' },
15255 { "ldouble", float_cons, 'x' },
15256 { "packed", float_cons, 'p' },