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, 59 Temple Place - Suite 330, 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
);
1140 #ifdef STRIP_UNDERSCORE
1141 if (preserved_copy_of_name
[0] == '_')
1142 preserved_copy_of_name
++;
1145 #ifdef tc_canonicalize_symbol_name
1146 preserved_copy_of_name
=
1147 tc_canonicalize_symbol_name (preserved_copy_of_name
);
1150 S_SET_NAME (symbolP
, preserved_copy_of_name
);
1152 S_SET_SEGMENT (symbolP
, segment
);
1153 S_SET_VALUE (symbolP
, valu
);
1154 symbol_clear_list_pointers (symbolP
);
1156 symbol_set_frag (symbolP
, frag
);
1158 /* Link to end of symbol chain. */
1160 extern int symbol_table_frozen
;
1162 if (symbol_table_frozen
)
1166 symbol_append (symbolP
, symbol_lastP
, & symbol_rootP
, & symbol_lastP
);
1168 obj_symbol_new_hook (symbolP
);
1170 #ifdef tc_symbol_new_hook
1171 tc_symbol_new_hook (symbolP
);
1175 verify_symbol_chain (symbol_rootP
, symbol_lastP
);
1176 #endif /* DEBUG_SYMS */
1179 /* Check that an immediate is valid.
1180 If so, convert it to the right format. */
1183 validate_immediate (unsigned int val
)
1188 #define rotate_left(v, n) (v << n | v >> (32 - n))
1190 for (i
= 0; i
< 32; i
+= 2)
1191 if ((a
= rotate_left (val
, i
)) <= 0xff)
1192 return a
| (i
<< 7); /* 12-bit pack: [shift-cnt,const]. */
1197 /* Check to see if an immediate can be computed as two separate immediate
1198 values, added together. We already know that this value cannot be
1199 computed by just one ARM instruction. */
1202 validate_immediate_twopart (unsigned int val
,
1203 unsigned int * highpart
)
1208 for (i
= 0; i
< 32; i
+= 2)
1209 if (((a
= rotate_left (val
, i
)) & 0xff) != 0)
1215 * highpart
= (a
>> 8) | ((i
+ 24) << 7);
1217 else if (a
& 0xff0000)
1221 * highpart
= (a
>> 16) | ((i
+ 16) << 7);
1225 assert (a
& 0xff000000);
1226 * highpart
= (a
>> 24) | ((i
+ 8) << 7);
1229 return (a
& 0xff) | (i
<< 7);
1236 validate_offset_imm (unsigned int val
, int hwse
)
1238 if ((hwse
&& val
> 255) || val
> 4095)
1245 /* This code is to handle mapping symbols as defined in the ARM ELF spec.
1246 (See "Mapping symbols", section 4.5.5, ARM AAELF version 1.0).
1247 Note that previously, $a and $t has type STT_FUNC (BSF_OBJECT flag),
1248 and $d has type STT_OBJECT (BSF_OBJECT flag). Now all three are untyped. */
1250 static enum mstate mapstate
= MAP_UNDEFINED
;
1253 mapping_state (enum mstate state
)
1256 const char * symname
;
1259 if (mapstate
== state
)
1260 /* The mapping symbol has already been emitted.
1261 There is nothing else to do. */
1270 type
= BSF_NO_FLAGS
;
1274 type
= BSF_NO_FLAGS
;
1278 type
= BSF_NO_FLAGS
;
1286 seg_info (now_seg
)->tc_segment_info_data
.mapstate
= state
;
1288 symbolP
= symbol_new (symname
, now_seg
, (valueT
) frag_now_fix (), frag_now
);
1289 symbol_table_insert (symbolP
);
1290 symbol_get_bfdsym (symbolP
)->flags
|= type
| BSF_LOCAL
;
1295 THUMB_SET_FUNC (symbolP
, 0);
1296 ARM_SET_THUMB (symbolP
, 0);
1297 ARM_SET_INTERWORK (symbolP
, support_interwork
);
1301 THUMB_SET_FUNC (symbolP
, 1);
1302 ARM_SET_THUMB (symbolP
, 1);
1303 ARM_SET_INTERWORK (symbolP
, support_interwork
);
1312 /* When we change sections we need to issue a new mapping symbol. */
1315 arm_elf_change_section (void)
1318 segment_info_type
*seginfo
;
1320 /* Link an unlinked unwind index table section to the .text section. */
1321 if (elf_section_type (now_seg
) == SHT_ARM_EXIDX
1322 && elf_linked_to_section (now_seg
) == NULL
)
1323 elf_linked_to_section (now_seg
) = text_section
;
1325 if (!SEG_NORMAL (now_seg
))
1328 flags
= bfd_get_section_flags (stdoutput
, now_seg
);
1330 /* We can ignore sections that only contain debug info. */
1331 if ((flags
& SEC_ALLOC
) == 0)
1334 seginfo
= seg_info (now_seg
);
1335 mapstate
= seginfo
->tc_segment_info_data
.mapstate
;
1336 marked_pr_dependency
= seginfo
->tc_segment_info_data
.marked_pr_dependency
;
1340 arm_elf_section_type (const char * str
, size_t len
)
1342 if (len
== 5 && strncmp (str
, "exidx", 5) == 0)
1343 return SHT_ARM_EXIDX
;
1348 #define mapping_state(a)
1349 #endif /* OBJ_ELF */
1351 /* arm_reg_parse () := if it looks like a register, return its token and
1352 advance the pointer. */
1355 arm_reg_parse (char ** ccp
, struct hash_control
* htab
)
1357 char * start
= * ccp
;
1360 struct reg_entry
* reg
;
1362 #ifdef REGISTER_PREFIX
1363 if (*start
!= REGISTER_PREFIX
)
1368 #ifdef OPTIONAL_REGISTER_PREFIX
1369 if (*p
== OPTIONAL_REGISTER_PREFIX
)
1373 if (!ISALPHA (*p
) || !is_name_beginner (*p
))
1377 while (ISALPHA (c
) || ISDIGIT (c
) || c
== '_')
1381 reg
= (struct reg_entry
*) hash_find (htab
, start
);
1393 /* Search for the following register name in each of the possible reg name
1394 tables. Return the classification if found, or REG_TYPE_MAX if not
1397 static enum arm_reg_type
1398 arm_reg_parse_any (char *cp
)
1402 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
1403 if (arm_reg_parse (&cp
, all_reg_maps
[i
].htab
) != FAIL
)
1404 return (enum arm_reg_type
) i
;
1406 return REG_TYPE_MAX
;
1410 opcode_select (int width
)
1417 if (! (cpu_variant
& ARM_EXT_V4T
))
1418 as_bad (_("selected processor does not support THUMB opcodes"));
1421 /* No need to force the alignment, since we will have been
1422 coming from ARM mode, which is word-aligned. */
1423 record_alignment (now_seg
, 1);
1425 mapping_state (MAP_THUMB
);
1431 if ((cpu_variant
& ARM_ALL
) == ARM_EXT_V4T
)
1432 as_bad (_("selected processor does not support ARM opcodes"));
1437 frag_align (2, 0, 0);
1439 record_alignment (now_seg
, 1);
1441 mapping_state (MAP_ARM
);
1445 as_bad (_("invalid instruction size selected (%d)"), width
);
1450 s_req (int a ATTRIBUTE_UNUSED
)
1452 as_bad (_("invalid syntax for .req directive"));
1455 /* The .unreq directive deletes an alias which was previously defined
1456 by .req. For example:
1462 s_unreq (int a ATTRIBUTE_UNUSED
)
1467 skip_whitespace (input_line_pointer
);
1468 name
= input_line_pointer
;
1470 while (*input_line_pointer
!= 0
1471 && *input_line_pointer
!= ' '
1472 && *input_line_pointer
!= '\n')
1473 ++input_line_pointer
;
1475 saved_char
= *input_line_pointer
;
1476 *input_line_pointer
= 0;
1480 enum arm_reg_type req_type
= arm_reg_parse_any (name
);
1482 if (req_type
!= REG_TYPE_MAX
)
1484 char *temp_name
= name
;
1485 int req_no
= arm_reg_parse (&temp_name
, all_reg_maps
[req_type
].htab
);
1489 struct reg_entry
*req_entry
;
1491 /* Check to see if this alias is a builtin one. */
1492 req_entry
= hash_delete (all_reg_maps
[req_type
].htab
, name
);
1495 as_bad (_("unreq: missing hash entry for \"%s\""), name
);
1496 else if (req_entry
->builtin
)
1497 /* FIXME: We are deleting a built in register alias which
1498 points to a const data structure, so we only need to
1499 free up the memory used by the key in the hash table.
1500 Unfortunately we have not recorded this value, so this
1501 is a memory leak. */
1502 /* FIXME: Should we issue a warning message ? */
1506 /* Deleting a user defined alias. We need to free the
1507 key and the value, but fortunately the key is the same
1508 as the value->name field. */
1509 free ((char *) req_entry
->name
);
1514 as_bad (_(".unreq: unrecognized symbol \"%s\""), name
);
1517 as_bad (_(".unreq: unrecognized symbol \"%s\""), name
);
1520 as_bad (_("invalid syntax for .unreq directive"));
1522 *input_line_pointer
= saved_char
;
1523 demand_empty_rest_of_line ();
1527 s_bss (int ignore ATTRIBUTE_UNUSED
)
1529 /* We don't support putting frags in the BSS segment, we fake it by
1530 marking in_bss, then looking at s_skip for clues. */
1531 subseg_set (bss_section
, 0);
1532 demand_empty_rest_of_line ();
1533 mapping_state (MAP_DATA
);
1537 s_even (int ignore ATTRIBUTE_UNUSED
)
1539 /* Never make frag if expect extra pass. */
1541 frag_align (1, 0, 0);
1543 record_alignment (now_seg
, 1);
1545 demand_empty_rest_of_line ();
1549 s_ltorg (int ignored ATTRIBUTE_UNUSED
)
1552 literal_pool
* pool
;
1555 pool
= find_literal_pool ();
1557 || pool
->symbol
== NULL
1558 || pool
->next_free_entry
== 0)
1561 mapping_state (MAP_DATA
);
1563 /* Align pool as you have word accesses.
1564 Only make a frag if we have to. */
1566 frag_align (2, 0, 0);
1568 record_alignment (now_seg
, 2);
1570 sprintf (sym_name
, "$$lit_\002%x", pool
->id
);
1572 symbol_locate (pool
->symbol
, sym_name
, now_seg
,
1573 (valueT
) frag_now_fix (), frag_now
);
1574 symbol_table_insert (pool
->symbol
);
1576 ARM_SET_THUMB (pool
->symbol
, thumb_mode
);
1578 #if defined OBJ_COFF || defined OBJ_ELF
1579 ARM_SET_INTERWORK (pool
->symbol
, support_interwork
);
1582 for (entry
= 0; entry
< pool
->next_free_entry
; entry
++)
1583 /* First output the expression in the instruction to the pool. */
1584 emit_expr (&(pool
->literals
[entry
]), 4); /* .word */
1586 /* Mark the pool as empty. */
1587 pool
->next_free_entry
= 0;
1588 pool
->symbol
= NULL
;
1591 /* Same as s_align_ptwo but align 0 => align 2. */
1594 s_align (int unused ATTRIBUTE_UNUSED
)
1598 long max_alignment
= 15;
1600 temp
= get_absolute_expression ();
1601 if (temp
> max_alignment
)
1602 as_bad (_("alignment too large: %d assumed"), temp
= max_alignment
);
1605 as_bad (_("alignment negative. 0 assumed."));
1609 if (*input_line_pointer
== ',')
1611 input_line_pointer
++;
1612 temp_fill
= get_absolute_expression ();
1620 /* Only make a frag if we HAVE to. */
1621 if (temp
&& !need_pass_2
)
1622 frag_align (temp
, (int) temp_fill
, 0);
1623 demand_empty_rest_of_line ();
1625 record_alignment (now_seg
, temp
);
1629 s_force_thumb (int ignore ATTRIBUTE_UNUSED
)
1631 /* If we are not already in thumb mode go into it, EVEN if
1632 the target processor does not support thumb instructions.
1633 This is used by gcc/config/arm/lib1funcs.asm for example
1634 to compile interworking support functions even if the
1635 target processor should not support interworking. */
1640 record_alignment (now_seg
, 1);
1643 demand_empty_rest_of_line ();
1647 s_thumb_func (int ignore ATTRIBUTE_UNUSED
)
1652 /* The following label is the name/address of the start of a Thumb function.
1653 We need to know this for the interworking support. */
1654 label_is_thumb_function_name
= TRUE
;
1656 demand_empty_rest_of_line ();
1659 /* Perform a .set directive, but also mark the alias as
1660 being a thumb function. */
1663 s_thumb_set (int equiv
)
1665 /* XXX the following is a duplicate of the code for s_set() in read.c
1666 We cannot just call that code as we need to get at the symbol that
1673 /* Especial apologies for the random logic:
1674 This just grew, and could be parsed much more simply!
1676 name
= input_line_pointer
;
1677 delim
= get_symbol_end ();
1678 end_name
= input_line_pointer
;
1683 if (*input_line_pointer
!= ',')
1686 as_bad (_("expected comma after name \"%s\""), name
);
1688 ignore_rest_of_line ();
1692 input_line_pointer
++;
1695 if (name
[0] == '.' && name
[1] == '\0')
1697 /* XXX - this should not happen to .thumb_set. */
1701 if ((symbolP
= symbol_find (name
)) == NULL
1702 && (symbolP
= md_undefined_symbol (name
)) == NULL
)
1705 /* When doing symbol listings, play games with dummy fragments living
1706 outside the normal fragment chain to record the file and line info
1708 if (listing
& LISTING_SYMBOLS
)
1710 extern struct list_info_struct
* listing_tail
;
1711 fragS
* dummy_frag
= xmalloc (sizeof (fragS
));
1713 memset (dummy_frag
, 0, sizeof (fragS
));
1714 dummy_frag
->fr_type
= rs_fill
;
1715 dummy_frag
->line
= listing_tail
;
1716 symbolP
= symbol_new (name
, undefined_section
, 0, dummy_frag
);
1717 dummy_frag
->fr_symbol
= symbolP
;
1721 symbolP
= symbol_new (name
, undefined_section
, 0, &zero_address_frag
);
1724 /* "set" symbols are local unless otherwise specified. */
1725 SF_SET_LOCAL (symbolP
);
1726 #endif /* OBJ_COFF */
1727 } /* Make a new symbol. */
1729 symbol_table_insert (symbolP
);
1734 && S_IS_DEFINED (symbolP
)
1735 && S_GET_SEGMENT (symbolP
) != reg_section
)
1736 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP
));
1738 pseudo_set (symbolP
);
1740 demand_empty_rest_of_line ();
1742 /* XXX Now we come to the Thumb specific bit of code. */
1744 THUMB_SET_FUNC (symbolP
, 1);
1745 ARM_SET_THUMB (symbolP
, 1);
1746 #if defined OBJ_ELF || defined OBJ_COFF
1747 ARM_SET_INTERWORK (symbolP
, support_interwork
);
1752 s_arm (int ignore ATTRIBUTE_UNUSED
)
1755 demand_empty_rest_of_line ();
1759 s_thumb (int ignore ATTRIBUTE_UNUSED
)
1762 demand_empty_rest_of_line ();
1766 s_code (int unused ATTRIBUTE_UNUSED
)
1770 temp
= get_absolute_expression ();
1775 opcode_select (temp
);
1779 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp
);
1784 end_of_line (char * str
)
1786 skip_whitespace (str
);
1788 if (*str
!= '\0' && !inst
.error
)
1789 inst
.error
= _("garbage following instruction");
1793 skip_past_comma (char ** str
)
1795 char * p
= * str
, c
;
1798 while ((c
= *p
) == ' ' || c
== ',')
1801 if (c
== ',' && comma
++)
1809 return comma
? SUCCESS
: FAIL
;
1812 /* Return TRUE if anything in the expression is a bignum. */
1815 walk_no_bignums (symbolS
* sp
)
1817 if (symbol_get_value_expression (sp
)->X_op
== O_big
)
1820 if (symbol_get_value_expression (sp
)->X_add_symbol
)
1822 return (walk_no_bignums (symbol_get_value_expression (sp
)->X_add_symbol
)
1823 || (symbol_get_value_expression (sp
)->X_op_symbol
1824 && walk_no_bignums (symbol_get_value_expression (sp
)->X_op_symbol
)));
1830 static int in_my_get_expression
= 0;
1833 my_get_expression (expressionS
* ep
, char ** str
)
1838 save_in
= input_line_pointer
;
1839 input_line_pointer
= *str
;
1840 in_my_get_expression
= 1;
1841 seg
= expression (ep
);
1842 in_my_get_expression
= 0;
1844 if (ep
->X_op
== O_illegal
)
1846 /* We found a bad expression in md_operand(). */
1847 *str
= input_line_pointer
;
1848 input_line_pointer
= save_in
;
1853 if (seg
!= absolute_section
1854 && seg
!= text_section
1855 && seg
!= data_section
1856 && seg
!= bss_section
1857 && seg
!= undefined_section
)
1859 inst
.error
= _("bad_segment");
1860 *str
= input_line_pointer
;
1861 input_line_pointer
= save_in
;
1866 /* Get rid of any bignums now, so that we don't generate an error for which
1867 we can't establish a line number later on. Big numbers are never valid
1868 in instructions, which is where this routine is always called. */
1869 if (ep
->X_op
== O_big
1870 || (ep
->X_add_symbol
1871 && (walk_no_bignums (ep
->X_add_symbol
)
1873 && walk_no_bignums (ep
->X_op_symbol
)))))
1875 inst
.error
= _("invalid constant");
1876 *str
= input_line_pointer
;
1877 input_line_pointer
= save_in
;
1881 *str
= input_line_pointer
;
1882 input_line_pointer
= save_in
;
1886 /* A standard register must be given at this point.
1887 SHIFT is the place to put it in inst.instruction.
1888 Restores input start point on error.
1889 Returns the reg#, or FAIL. */
1892 reg_required_here (char ** str
, int shift
)
1894 static char buff
[128]; /* XXX */
1896 char * start
= * str
;
1898 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_RN
].htab
)) != FAIL
)
1901 inst
.instruction
|= reg
<< shift
;
1905 /* Restore the start point, we may have got a reg of the wrong class. */
1908 /* In the few cases where we might be able to accept something else
1909 this error can be overridden. */
1910 sprintf (buff
, _("register expected, not '%.100s'"), start
);
1916 /* A Intel Wireless MMX technology register
1917 must be given at this point.
1918 Shift is the place to put it in inst.instruction.
1919 Restores input start point on err.
1920 Returns the reg#, or FAIL. */
1923 wreg_required_here (char ** str
,
1925 enum wreg_type reg_type
)
1927 static char buff
[128];
1929 char * start
= *str
;
1931 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_IWMMXT
].htab
)) != FAIL
)
1933 if (wr_register (reg
)
1934 && (reg_type
== IWMMXT_REG_WR
|| reg_type
== IWMMXT_REG_WR_OR_WC
))
1937 inst
.instruction
|= (reg
^ WR_PREFIX
) << shift
;
1940 else if (wc_register (reg
)
1941 && (reg_type
== IWMMXT_REG_WC
|| reg_type
== IWMMXT_REG_WR_OR_WC
))
1944 inst
.instruction
|= (reg
^ WC_PREFIX
) << shift
;
1947 else if ((wcg_register (reg
) && reg_type
== IWMMXT_REG_WCG
))
1950 inst
.instruction
|= ((reg
^ WC_PREFIX
) - 8) << shift
;
1955 /* Restore the start point, we may have got a reg of the wrong class. */
1958 /* In the few cases where we might be able to accept
1959 something else this error can be overridden. */
1960 sprintf (buff
, _("Intel Wireless MMX technology register expected, not '%.100s'"), start
);
1966 static const struct asm_psr
*
1967 arm_psr_parse (char ** ccp
)
1969 char * start
= * ccp
;
1972 const struct asm_psr
* psr
;
1976 /* Skip to the end of the next word in the input stream. */
1981 while (ISALPHA (c
) || c
== '_');
1983 /* Terminate the word. */
1986 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
1987 feature for ease of use and backwards compatibility. */
1988 if (!strncmp (start
, "cpsr", 4))
1989 strncpy (start
, "CPSR", 4);
1990 else if (!strncmp (start
, "spsr", 4))
1991 strncpy (start
, "SPSR", 4);
1993 /* Now locate the word in the psr hash table. */
1994 psr
= (const struct asm_psr
*) hash_find (arm_psr_hsh
, start
);
1996 /* Restore the input stream. */
1999 /* If we found a valid match, advance the
2000 stream pointer past the end of the word. */
2006 /* Parse the input looking for a PSR flag. */
2009 psr_required_here (char ** str
)
2011 char * start
= * str
;
2012 const struct asm_psr
* psr
;
2014 psr
= arm_psr_parse (str
);
2018 /* If this is the SPSR that is being modified, set the R bit. */
2020 inst
.instruction
|= SPSR_BIT
;
2022 /* Set the psr flags in the MSR instruction. */
2023 inst
.instruction
|= psr
->field
<< PSR_SHIFT
;
2028 /* In the few cases where we might be able to accept
2029 something else this error can be overridden. */
2030 inst
.error
= _("flag for {c}psr instruction expected");
2032 /* Restore the start point. */
2038 co_proc_number (char ** str
)
2040 int processor
, pchar
;
2043 skip_whitespace (*str
);
2046 /* The data sheet seems to imply that just a number on its own is valid
2047 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
2049 if ((processor
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CP
].htab
))
2055 if (pchar
>= '0' && pchar
<= '9')
2057 processor
= pchar
- '0';
2058 if (**str
>= '0' && **str
<= '9')
2060 processor
= processor
* 10 + *(*str
)++ - '0';
2063 inst
.error
= _("illegal co-processor number");
2070 inst
.error
= all_reg_maps
[REG_TYPE_CP
].expected
;
2075 inst
.instruction
|= processor
<< 8;
2080 cp_opc_expr (char ** str
, int where
, int length
)
2084 skip_whitespace (* str
);
2086 memset (&expr
, '\0', sizeof (expr
));
2088 if (my_get_expression (&expr
, str
))
2090 if (expr
.X_op
!= O_constant
)
2092 inst
.error
= _("bad or missing expression");
2096 if ((expr
.X_add_number
& ((1 << length
) - 1)) != expr
.X_add_number
)
2098 inst
.error
= _("immediate co-processor expression too large");
2102 inst
.instruction
|= expr
.X_add_number
<< where
;
2107 cp_reg_required_here (char ** str
, int where
)
2110 char * start
= *str
;
2112 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CN
].htab
)) != FAIL
)
2114 inst
.instruction
|= reg
<< where
;
2118 /* In the few cases where we might be able to accept something else
2119 this error can be overridden. */
2120 inst
.error
= all_reg_maps
[REG_TYPE_CN
].expected
;
2122 /* Restore the start point. */
2128 fp_reg_required_here (char ** str
, int where
)
2131 char * start
= * str
;
2133 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_FN
].htab
)) != FAIL
)
2135 inst
.instruction
|= reg
<< where
;
2139 /* In the few cases where we might be able to accept something else
2140 this error can be overridden. */
2141 inst
.error
= all_reg_maps
[REG_TYPE_FN
].expected
;
2143 /* Restore the start point. */
2149 cp_address_offset (char ** str
)
2153 skip_whitespace (* str
);
2155 if (! is_immediate_prefix (**str
))
2157 inst
.error
= _("immediate expression expected");
2163 if (my_get_expression (& inst
.reloc
.exp
, str
))
2166 if (inst
.reloc
.exp
.X_op
== O_constant
)
2168 offset
= inst
.reloc
.exp
.X_add_number
;
2172 inst
.error
= _("co-processor address must be word aligned");
2176 if (offset
> 1023 || offset
< -1023)
2178 inst
.error
= _("offset too large");
2183 inst
.instruction
|= INDEX_UP
;
2187 inst
.instruction
|= offset
>> 2;
2190 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
2196 cp_address_required_here (char ** str
, int wb_ok
)
2207 skip_whitespace (p
);
2209 if ((reg
= reg_required_here (& p
, 16)) == FAIL
)
2212 skip_whitespace (p
);
2218 skip_whitespace (p
);
2222 /* As an extension to the official ARM syntax we allow:
2224 as a short hand for:
2226 inst
.instruction
|= PRE_INDEX
| INDEX_UP
;
2231 if (skip_past_comma (& p
) == FAIL
)
2233 inst
.error
= _("comma expected after closing square bracket");
2237 skip_whitespace (p
);
2244 write_back
= WRITE_BACK
;
2248 inst
.error
= _("pc may not be used in post-increment");
2252 if (cp_address_offset (& p
) == FAIL
)
2256 pre_inc
= PRE_INDEX
| INDEX_UP
;
2262 /* [Rn], {<expr>} */
2265 skip_whitespace (p
);
2267 if (my_get_expression (& inst
.reloc
.exp
, & p
))
2270 if (inst
.reloc
.exp
.X_op
== O_constant
)
2272 option
= inst
.reloc
.exp
.X_add_number
;
2274 if (option
> 255 || option
< 0)
2276 inst
.error
= _("'option' field too large");
2280 skip_whitespace (p
);
2284 inst
.error
= _("'}' expected at end of 'option' field");
2290 inst
.instruction
|= option
;
2291 inst
.instruction
|= INDEX_UP
;
2296 inst
.error
= _("non-constant expressions for 'option' field not supported");
2302 inst
.error
= _("# or { expected after comma");
2308 /* '['Rn, #expr']'[!] */
2310 if (skip_past_comma (& p
) == FAIL
)
2312 inst
.error
= _("pre-indexed expression expected");
2316 pre_inc
= PRE_INDEX
;
2318 if (cp_address_offset (& p
) == FAIL
)
2321 skip_whitespace (p
);
2325 inst
.error
= _("missing ]");
2329 skip_whitespace (p
);
2331 if (wb_ok
&& *p
== '!')
2335 inst
.error
= _("pc may not be used with write-back");
2340 write_back
= WRITE_BACK
;
2346 if (my_get_expression (&inst
.reloc
.exp
, &p
))
2349 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
2350 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
2351 inst
.reloc
.pc_rel
= 1;
2352 inst
.instruction
|= (REG_PC
<< 16);
2353 pre_inc
= PRE_INDEX
;
2356 inst
.instruction
|= write_back
| pre_inc
;
2362 cp_byte_address_offset (char ** str
)
2366 skip_whitespace (* str
);
2368 if (! is_immediate_prefix (**str
))
2370 inst
.error
= _("immediate expression expected");
2376 if (my_get_expression (& inst
.reloc
.exp
, str
))
2379 if (inst
.reloc
.exp
.X_op
== O_constant
)
2381 offset
= inst
.reloc
.exp
.X_add_number
;
2383 if (offset
> 255 || offset
< -255)
2385 inst
.error
= _("offset too large");
2390 inst
.instruction
|= INDEX_UP
;
2394 inst
.instruction
|= offset
;
2397 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM_S2
;
2403 cp_byte_address_required_here (char ** str
)
2414 skip_whitespace (p
);
2416 if ((reg
= reg_required_here (& p
, 16)) == FAIL
)
2419 skip_whitespace (p
);
2425 if (skip_past_comma (& p
) == SUCCESS
)
2428 write_back
= WRITE_BACK
;
2432 inst
.error
= _("pc may not be used in post-increment");
2436 if (cp_byte_address_offset (& p
) == FAIL
)
2440 pre_inc
= PRE_INDEX
| INDEX_UP
;
2444 /* '['Rn, #expr']'[!] */
2446 if (skip_past_comma (& p
) == FAIL
)
2448 inst
.error
= _("pre-indexed expression expected");
2452 pre_inc
= PRE_INDEX
;
2454 if (cp_byte_address_offset (& p
) == FAIL
)
2457 skip_whitespace (p
);
2461 inst
.error
= _("missing ]");
2465 skip_whitespace (p
);
2471 inst
.error
= _("pc may not be used with write-back");
2476 write_back
= WRITE_BACK
;
2482 if (my_get_expression (&inst
.reloc
.exp
, &p
))
2485 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM_S2
;
2486 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
2487 inst
.reloc
.pc_rel
= 1;
2488 inst
.instruction
|= (REG_PC
<< 16);
2489 pre_inc
= PRE_INDEX
;
2492 inst
.instruction
|= write_back
| pre_inc
;
2500 skip_whitespace (str
);
2505 if (my_get_expression (&inst
.reloc
.exp
, &str
))
2506 inst
.reloc
.exp
.X_op
= O_illegal
;
2509 skip_whitespace (str
);
2513 inst
.reloc
.exp
.X_op
= O_illegal
;
2516 if (inst
.reloc
.exp
.X_op
!= O_constant
2517 || inst
.reloc
.exp
.X_add_number
> 255
2518 || inst
.reloc
.exp
.X_add_number
< 0)
2520 inst
.error
= _("Invalid NOP hint");
2524 /* Arcitectural NOP hints are CPSR sets with no bits selected. */
2525 inst
.instruction
&= 0xf0000000;
2526 inst
.instruction
|= 0x0320f000 + inst
.reloc
.exp
.X_add_number
;
2533 do_empty (char * str
)
2535 /* Do nothing really. */
2544 /* Only one syntax. */
2545 skip_whitespace (str
);
2547 if (reg_required_here (&str
, 12) == FAIL
)
2549 inst
.error
= BAD_ARGS
;
2553 if (skip_past_comma (&str
) == FAIL
)
2555 inst
.error
= _("comma expected after register name");
2559 skip_whitespace (str
);
2561 if ( streq (str
, "CPSR")
2562 || streq (str
, "SPSR")
2563 /* Lower case versions for backwards compatibility. */
2564 || streq (str
, "cpsr")
2565 || streq (str
, "spsr"))
2568 /* This is for backwards compatibility with older toolchains. */
2569 else if ( streq (str
, "cpsr_all")
2570 || streq (str
, "spsr_all"))
2574 inst
.error
= _("CPSR or SPSR expected");
2578 if (* str
== 's' || * str
== 'S')
2579 inst
.instruction
|= SPSR_BIT
;
2585 /* Two possible forms:
2586 "{C|S}PSR_<field>, Rm",
2587 "{C|S}PSR_f, #expression". */
2592 skip_whitespace (str
);
2594 if (psr_required_here (& str
) == FAIL
)
2597 if (skip_past_comma (& str
) == FAIL
)
2599 inst
.error
= _("comma missing after psr flags");
2603 skip_whitespace (str
);
2605 if (reg_required_here (& str
, 0) != FAIL
)
2612 if (! is_immediate_prefix (* str
))
2615 _("only a register or immediate value can follow a psr flag");
2622 if (my_get_expression (& inst
.reloc
.exp
, & str
))
2625 _("only a register or immediate value can follow a psr flag");
2629 inst
.instruction
|= INST_IMMEDIATE
;
2631 if (inst
.reloc
.exp
.X_add_symbol
)
2633 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
2634 inst
.reloc
.pc_rel
= 0;
2638 unsigned value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
2640 if (value
== (unsigned) FAIL
)
2642 inst
.error
= _("invalid constant");
2646 inst
.instruction
|= value
;
2653 /* Long Multiply Parser
2654 UMULL RdLo, RdHi, Rm, Rs
2655 SMULL RdLo, RdHi, Rm, Rs
2656 UMLAL RdLo, RdHi, Rm, Rs
2657 SMLAL RdLo, RdHi, Rm, Rs. */
2660 do_mull (char * str
)
2662 int rdlo
, rdhi
, rm
, rs
;
2664 /* Only one format "rdlo, rdhi, rm, rs". */
2665 skip_whitespace (str
);
2667 if ((rdlo
= reg_required_here (&str
, 12)) == FAIL
)
2669 inst
.error
= BAD_ARGS
;
2673 if (skip_past_comma (&str
) == FAIL
2674 || (rdhi
= reg_required_here (&str
, 16)) == FAIL
)
2676 inst
.error
= BAD_ARGS
;
2680 if (skip_past_comma (&str
) == FAIL
2681 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
2683 inst
.error
= BAD_ARGS
;
2687 /* rdhi, rdlo and rm must all be different. */
2688 if (rdlo
== rdhi
|| rdlo
== rm
|| rdhi
== rm
)
2689 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
2691 if (skip_past_comma (&str
) == FAIL
2692 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
2694 inst
.error
= BAD_ARGS
;
2698 if (rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
)
2700 inst
.error
= BAD_PC
;
2712 /* Only one format "rd, rm, rs". */
2713 skip_whitespace (str
);
2715 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
2717 inst
.error
= BAD_ARGS
;
2723 inst
.error
= BAD_PC
;
2727 if (skip_past_comma (&str
) == FAIL
2728 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
2730 inst
.error
= BAD_ARGS
;
2736 inst
.error
= BAD_PC
;
2741 as_tsktsk (_("rd and rm should be different in mul"));
2743 if (skip_past_comma (&str
) == FAIL
2744 || (rm
= reg_required_here (&str
, 8)) == FAIL
)
2746 inst
.error
= BAD_ARGS
;
2752 inst
.error
= BAD_PC
;
2760 do_mlas (char * str
, bfd_boolean is_mls
)
2764 /* Only one format "rd, rm, rs, rn". */
2765 skip_whitespace (str
);
2767 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
2769 inst
.error
= BAD_ARGS
;
2775 inst
.error
= BAD_PC
;
2779 if (skip_past_comma (&str
) == FAIL
2780 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
2782 inst
.error
= BAD_ARGS
;
2788 inst
.error
= BAD_PC
;
2792 /* This restriction does not apply to mls (nor to mla in v6, but
2793 that's hard to detect at present). */
2794 if (rm
== rd
&& !is_mls
)
2795 as_tsktsk (_("rd and rm should be different in mla"));
2797 if (skip_past_comma (&str
) == FAIL
2798 || (rd
= reg_required_here (&str
, 8)) == FAIL
2799 || skip_past_comma (&str
) == FAIL
2800 || (rm
= reg_required_here (&str
, 12)) == FAIL
)
2802 inst
.error
= BAD_ARGS
;
2806 if (rd
== REG_PC
|| rm
== REG_PC
)
2808 inst
.error
= BAD_PC
;
2818 do_mlas (str
, FALSE
);
2824 do_mlas (str
, TRUE
);
2827 /* Expects *str -> the characters "acc0", possibly with leading blanks.
2828 Advances *str to the next non-alphanumeric.
2829 Returns 0, or else FAIL (in which case sets inst.error).
2831 (In a future XScale, there may be accumulators other than zero.
2832 At that time this routine and its callers can be upgraded to suit.) */
2835 accum0_required_here (char ** str
)
2837 static char buff
[128]; /* Note the address is taken. Hence, static. */
2840 int result
= 0; /* The accum number. */
2842 skip_whitespace (p
);
2844 *str
= p
; /* Advance caller's string pointer too. */
2849 *--p
= 0; /* Aap nul into input buffer at non-alnum. */
2851 if (! ( streq (*str
, "acc0") || streq (*str
, "ACC0")))
2853 sprintf (buff
, _("acc0 expected, not '%.100s'"), *str
);
2858 *p
= c
; /* Unzap. */
2859 *str
= p
; /* Caller's string pointer to after match. */
2864 ldst_extend_v4 (char ** str
)
2873 if (my_get_expression (& inst
.reloc
.exp
, str
))
2876 if (inst
.reloc
.exp
.X_op
== O_constant
)
2878 int value
= inst
.reloc
.exp
.X_add_number
;
2880 if (value
< -255 || value
> 255)
2882 inst
.error
= _("address offset too large");
2892 /* Halfword and signextension instructions have the
2893 immediate value split across bits 11..8 and bits 3..0. */
2894 inst
.instruction
|= (add
| HWOFFSET_IMM
2895 | ((value
>> 4) << 8) | (value
& 0xF));
2899 inst
.instruction
|= HWOFFSET_IMM
;
2900 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
2901 inst
.reloc
.pc_rel
= 0;
2914 if (reg_required_here (str
, 0) == FAIL
)
2917 inst
.instruction
|= add
;
2922 /* Expects **str -> after a comma. May be leading blanks.
2923 Advances *str, recognizing a load mode, and setting inst.instruction.
2924 Returns rn, or else FAIL (in which case may set inst.error
2925 and not advance str)
2927 Note: doesn't know Rd, so no err checks that require such knowledge. */
2930 ld_mode_required_here (char ** string
)
2932 char * str
= * string
;
2936 skip_whitespace (str
);
2942 skip_whitespace (str
);
2944 if ((rn
= reg_required_here (& str
, 16)) == FAIL
)
2947 skip_whitespace (str
);
2953 if (skip_past_comma (& str
) == SUCCESS
)
2955 /* [Rn],... (post inc) */
2956 if (ldst_extend_v4 (&str
) == FAIL
)
2961 skip_whitespace (str
);
2966 inst
.instruction
|= WRITE_BACK
;
2969 inst
.instruction
|= INDEX_UP
| HWOFFSET_IMM
;
2975 if (skip_past_comma (& str
) == FAIL
)
2977 inst
.error
= _("pre-indexed expression expected");
2983 if (ldst_extend_v4 (&str
) == FAIL
)
2986 skip_whitespace (str
);
2988 if (* str
++ != ']')
2990 inst
.error
= _("missing ]");
2994 skip_whitespace (str
);
2999 inst
.instruction
|= WRITE_BACK
;
3003 else if (* str
== '=') /* ldr's "r,=label" syntax */
3004 /* We should never reach here, because <text> = <expression> is
3005 caught gas/read.c read_a_source_file() as a .set operation. */
3007 else /* PC +- 8 bit immediate offset. */
3009 if (my_get_expression (& inst
.reloc
.exp
, & str
))
3012 inst
.instruction
|= HWOFFSET_IMM
; /* The I bit. */
3013 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
3014 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
3015 inst
.reloc
.pc_rel
= 1;
3016 inst
.instruction
|= (REG_PC
<< 16);
3022 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
3028 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
3029 SMLAxy{cond} Rd,Rm,Rs,Rn
3030 SMLAWy{cond} Rd,Rm,Rs,Rn
3031 Error if any register is R15. */
3034 do_smla (char * str
)
3038 skip_whitespace (str
);
3040 if ((rd
= reg_required_here (& str
, 16)) == FAIL
3041 || skip_past_comma (& str
) == FAIL
3042 || (rm
= reg_required_here (& str
, 0)) == FAIL
3043 || skip_past_comma (& str
) == FAIL
3044 || (rs
= reg_required_here (& str
, 8)) == FAIL
3045 || skip_past_comma (& str
) == FAIL
3046 || (rn
= reg_required_here (& str
, 12)) == FAIL
)
3047 inst
.error
= BAD_ARGS
;
3049 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
|| rn
== REG_PC
)
3050 inst
.error
= BAD_PC
;
3056 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
3057 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
3058 Error if any register is R15.
3059 Warning if Rdlo == Rdhi. */
3062 do_smlal (char * str
)
3064 int rdlo
, rdhi
, rm
, rs
;
3066 skip_whitespace (str
);
3068 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
3069 || skip_past_comma (& str
) == FAIL
3070 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
3071 || skip_past_comma (& str
) == FAIL
3072 || (rm
= reg_required_here (& str
, 0)) == FAIL
3073 || skip_past_comma (& str
) == FAIL
3074 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
3076 inst
.error
= BAD_ARGS
;
3080 if (rdlo
== REG_PC
|| rdhi
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
3082 inst
.error
= BAD_PC
;
3087 as_tsktsk (_("rdhi and rdlo must be different"));
3092 /* ARM V5E (El Segundo) signed-multiply (argument parse)
3093 SMULxy{cond} Rd,Rm,Rs
3094 Error if any register is R15. */
3097 do_smul (char * str
)
3101 skip_whitespace (str
);
3103 if ((rd
= reg_required_here (& str
, 16)) == FAIL
3104 || skip_past_comma (& str
) == FAIL
3105 || (rm
= reg_required_here (& str
, 0)) == FAIL
3106 || skip_past_comma (& str
) == FAIL
3107 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
3108 inst
.error
= BAD_ARGS
;
3110 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
3111 inst
.error
= BAD_PC
;
3117 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
3118 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
3119 Error if any register is R15. */
3122 do_qadd (char * str
)
3126 skip_whitespace (str
);
3128 if ((rd
= reg_required_here (& str
, 12)) == FAIL
3129 || skip_past_comma (& str
) == FAIL
3130 || (rm
= reg_required_here (& str
, 0)) == FAIL
3131 || skip_past_comma (& str
) == FAIL
3132 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
3133 inst
.error
= BAD_ARGS
;
3135 else if (rd
== REG_PC
|| rm
== REG_PC
|| rn
== REG_PC
)
3136 inst
.error
= BAD_PC
;
3142 /* ARM V5E (el Segundo)
3143 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3144 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3146 These are equivalent to the XScale instructions MAR and MRA,
3147 respectively, when coproc == 0, opcode == 0, and CRm == 0.
3149 Result unpredicatable if Rd or Rn is R15. */
3152 do_co_reg2c (char * str
)
3156 skip_whitespace (str
);
3158 if (co_proc_number (& str
) == FAIL
)
3161 inst
.error
= BAD_ARGS
;
3165 if (skip_past_comma (& str
) == FAIL
3166 || cp_opc_expr (& str
, 4, 4) == FAIL
)
3169 inst
.error
= BAD_ARGS
;
3173 if (skip_past_comma (& str
) == FAIL
3174 || (rd
= reg_required_here (& str
, 12)) == FAIL
)
3177 inst
.error
= BAD_ARGS
;
3181 if (skip_past_comma (& str
) == FAIL
3182 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
3185 inst
.error
= BAD_ARGS
;
3189 /* Unpredictable result if rd or rn is R15. */
3190 if (rd
== REG_PC
|| rn
== REG_PC
)
3192 (_("Warning: instruction unpredictable when using r15"));
3194 if (skip_past_comma (& str
) == FAIL
3195 || cp_reg_required_here (& str
, 0) == FAIL
)
3198 inst
.error
= BAD_ARGS
;
3205 /* ARM V5 count-leading-zeroes instruction (argument parse)
3206 CLZ{<cond>} <Rd>, <Rm>
3207 Condition defaults to COND_ALWAYS.
3208 Error if Rd or Rm are R15. */
3215 skip_whitespace (str
);
3217 if (((rd
= reg_required_here (& str
, 12)) == FAIL
)
3218 || (skip_past_comma (& str
) == FAIL
)
3219 || ((rm
= reg_required_here (& str
, 0)) == FAIL
))
3220 inst
.error
= BAD_ARGS
;
3222 else if (rd
== REG_PC
|| rm
== REG_PC
)
3223 inst
.error
= BAD_PC
;
3229 /* ARM V5 (argument parse)
3230 LDC2{L} <coproc>, <CRd>, <addressing mode>
3231 STC2{L} <coproc>, <CRd>, <addressing mode>
3232 Instruction is not conditional, and has 0xf in the condition field.
3233 Otherwise, it's the same as LDC/STC. */
3236 do_lstc2 (char * str
)
3238 skip_whitespace (str
);
3240 if (co_proc_number (& str
) == FAIL
)
3243 inst
.error
= BAD_ARGS
;
3245 else if (skip_past_comma (& str
) == FAIL
3246 || cp_reg_required_here (& str
, 12) == FAIL
)
3249 inst
.error
= BAD_ARGS
;
3251 else if (skip_past_comma (& str
) == FAIL
3252 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
3255 inst
.error
= BAD_ARGS
;
3261 /* ARM V5 (argument parse)
3262 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
3263 Instruction is not conditional, and has 0xf in the condition field.
3264 Otherwise, it's the same as CDP. */
3267 do_cdp2 (char * str
)
3269 skip_whitespace (str
);
3271 if (co_proc_number (& str
) == FAIL
)
3274 inst
.error
= BAD_ARGS
;
3278 if (skip_past_comma (& str
) == FAIL
3279 || cp_opc_expr (& str
, 20,4) == FAIL
)
3282 inst
.error
= BAD_ARGS
;
3286 if (skip_past_comma (& str
) == FAIL
3287 || cp_reg_required_here (& str
, 12) == FAIL
)
3290 inst
.error
= BAD_ARGS
;
3294 if (skip_past_comma (& str
) == FAIL
3295 || cp_reg_required_here (& str
, 16) == FAIL
)
3298 inst
.error
= BAD_ARGS
;
3302 if (skip_past_comma (& str
) == FAIL
3303 || cp_reg_required_here (& str
, 0) == FAIL
)
3306 inst
.error
= BAD_ARGS
;
3310 if (skip_past_comma (& str
) == SUCCESS
)
3312 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
3315 inst
.error
= BAD_ARGS
;
3323 /* ARM V5 (argument parse)
3324 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3325 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3326 Instruction is not conditional, and has 0xf in the condition field.
3327 Otherwise, it's the same as MCR/MRC. */
3330 do_co_reg2 (char * str
)
3332 skip_whitespace (str
);
3334 if (co_proc_number (& str
) == FAIL
)
3337 inst
.error
= BAD_ARGS
;
3341 if (skip_past_comma (& str
) == FAIL
3342 || cp_opc_expr (& str
, 21, 3) == FAIL
)
3345 inst
.error
= BAD_ARGS
;
3349 if (skip_past_comma (& str
) == FAIL
3350 || reg_required_here (& str
, 12) == FAIL
)
3353 inst
.error
= BAD_ARGS
;
3357 if (skip_past_comma (& str
) == FAIL
3358 || cp_reg_required_here (& str
, 16) == FAIL
)
3361 inst
.error
= BAD_ARGS
;
3365 if (skip_past_comma (& str
) == FAIL
3366 || cp_reg_required_here (& str
, 0) == FAIL
)
3369 inst
.error
= BAD_ARGS
;
3373 if (skip_past_comma (& str
) == SUCCESS
)
3375 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
3378 inst
.error
= BAD_ARGS
;
3391 skip_whitespace (str
);
3393 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
3395 inst
.error
= BAD_ARGS
;
3399 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
3401 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
3406 /* ARM v5TEJ. Jump to Jazelle code. */
3413 skip_whitespace (str
);
3415 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
3417 inst
.error
= BAD_ARGS
;
3421 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
3423 as_tsktsk (_("use of r15 in bxj is not really useful"));
3428 /* ARM V6 umaal (argument parse). */
3431 do_umaal (char * str
)
3433 int rdlo
, rdhi
, rm
, rs
;
3435 skip_whitespace (str
);
3436 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
3437 || skip_past_comma (& str
) == FAIL
3438 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
3439 || skip_past_comma (& str
) == FAIL
3440 || (rm
= reg_required_here (& str
, 0)) == FAIL
3441 || skip_past_comma (& str
) == FAIL
3442 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
3444 inst
.error
= BAD_ARGS
;
3448 if (rdlo
== REG_PC
|| rdhi
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
3450 inst
.error
= BAD_PC
;
3457 /* ARM V6 strex (argument parse). */
3460 do_strex (char * str
)
3464 /* Parse Rd, Rm,. */
3465 skip_whitespace (str
);
3466 if ((rd
= reg_required_here (& str
, 12)) == FAIL
3467 || skip_past_comma (& str
) == FAIL
3468 || (rm
= reg_required_here (& str
, 0)) == FAIL
3469 || skip_past_comma (& str
) == FAIL
)
3471 inst
.error
= BAD_ARGS
;
3474 if (rd
== REG_PC
|| rm
== REG_PC
)
3476 inst
.error
= BAD_PC
;
3481 inst
.error
= _("Rd equal to Rm or Rn yields unpredictable results");
3485 /* Skip past '['. */
3486 if ((strlen (str
) >= 1)
3487 && strncmp (str
, "[", 1) == 0)
3490 skip_whitespace (str
);
3493 if ((rn
= reg_required_here (& str
, 16)) == FAIL
)
3495 inst
.error
= BAD_ARGS
;
3498 else if (rn
== REG_PC
)
3500 inst
.error
= BAD_PC
;
3505 inst
.error
= _("Rd equal to Rm or Rn yields unpredictable results");
3508 skip_whitespace (str
);
3510 /* Skip past ']'. */
3511 if ((strlen (str
) >= 1)
3512 && strncmp (str
, "]", 1) == 0)
3518 /* KIND indicates what kind of shifts are accepted. */
3521 decode_shift (char ** str
, int kind
)
3523 const struct asm_shift_name
* shift
;
3527 skip_whitespace (* str
);
3529 for (p
= * str
; ISALPHA (* p
); p
++)
3534 inst
.error
= _("shift expression expected");
3540 shift
= (const struct asm_shift_name
*) hash_find (arm_shift_hsh
, * str
);
3545 inst
.error
= _("shift expression expected");
3549 assert (shift
->properties
->index
== shift_properties
[shift
->properties
->index
].index
);
3551 if (kind
== SHIFT_LSL_OR_ASR_IMMEDIATE
3552 && shift
->properties
->index
!= SHIFT_LSL
3553 && shift
->properties
->index
!= SHIFT_ASR
)
3555 inst
.error
= _("'LSL' or 'ASR' required");
3558 else if (kind
== SHIFT_LSL_IMMEDIATE
3559 && shift
->properties
->index
!= SHIFT_LSL
)
3561 inst
.error
= _("'LSL' required");
3564 else if (kind
== SHIFT_ASR_IMMEDIATE
3565 && shift
->properties
->index
!= SHIFT_ASR
)
3567 inst
.error
= _("'ASR' required");
3571 if (shift
->properties
->index
== SHIFT_RRX
)
3574 inst
.instruction
|= shift
->properties
->bit_field
;
3578 skip_whitespace (p
);
3580 if (kind
== NO_SHIFT_RESTRICT
&& reg_required_here (& p
, 8) != FAIL
)
3582 inst
.instruction
|= shift
->properties
->bit_field
| SHIFT_BY_REG
;
3586 else if (! is_immediate_prefix (* p
))
3588 inst
.error
= (NO_SHIFT_RESTRICT
3589 ? _("shift requires register or #expression")
3590 : _("shift requires #expression"));
3598 if (my_get_expression (& inst
.reloc
.exp
, & p
))
3601 /* Validate some simple #expressions. */
3602 if (inst
.reloc
.exp
.X_op
== O_constant
)
3604 unsigned num
= inst
.reloc
.exp
.X_add_number
;
3606 /* Reject operations greater than 32. */
3608 /* Reject a shift of 0 unless the mode allows it. */
3609 || (num
== 0 && shift
->properties
->allows_0
== 0)
3610 /* Reject a shift of 32 unless the mode allows it. */
3611 || (num
== 32 && shift
->properties
->allows_32
== 0)
3614 /* As a special case we allow a shift of zero for
3615 modes that do not support it to be recoded as an
3616 logical shift left of zero (ie nothing). We warn
3617 about this though. */
3620 as_warn (_("shift of 0 ignored."));
3621 shift
= & shift_names
[0];
3622 assert (shift
->properties
->index
== SHIFT_LSL
);
3626 inst
.error
= _("invalid immediate shift");
3631 /* Shifts of 32 are encoded as 0, for those shifts that
3636 inst
.instruction
|= (num
<< 7) | shift
->properties
->bit_field
;
3640 inst
.reloc
.type
= BFD_RELOC_ARM_SHIFT_IMM
;
3641 inst
.reloc
.pc_rel
= 0;
3642 inst
.instruction
|= shift
->properties
->bit_field
;
3650 do_sat (char ** str
, int bias
)
3655 skip_whitespace (*str
);
3657 /* Parse <Rd>, field. */
3658 if ((rd
= reg_required_here (str
, 12)) == FAIL
3659 || skip_past_comma (str
) == FAIL
)
3661 inst
.error
= BAD_ARGS
;
3666 inst
.error
= BAD_PC
;
3670 /* Parse #<immed>, field. */
3671 if (is_immediate_prefix (**str
))
3675 inst
.error
= _("immediate expression expected");
3678 if (my_get_expression (&expr
, str
))
3680 inst
.error
= _("bad expression");
3683 if (expr
.X_op
!= O_constant
)
3685 inst
.error
= _("constant expression expected");
3688 if (expr
.X_add_number
+ bias
< 0
3689 || expr
.X_add_number
+ bias
> 31)
3691 inst
.error
= _("immediate value out of range");
3694 inst
.instruction
|= (expr
.X_add_number
+ bias
) << 16;
3695 if (skip_past_comma (str
) == FAIL
)
3697 inst
.error
= BAD_ARGS
;
3701 /* Parse <Rm> field. */
3702 if ((rm
= reg_required_here (str
, 0)) == FAIL
)
3704 inst
.error
= BAD_ARGS
;
3709 inst
.error
= BAD_PC
;
3713 if (skip_past_comma (str
) == SUCCESS
)
3714 decode_shift (str
, SHIFT_LSL_OR_ASR_IMMEDIATE
);
3717 /* ARM V6 ssat (argument parse). */
3720 do_ssat (char * str
)
3722 do_sat (&str
, /*bias=*/-1);
3726 /* ARM V6 usat (argument parse). */
3729 do_usat (char * str
)
3731 do_sat (&str
, /*bias=*/0);
3736 do_sat16 (char ** str
, int bias
)
3741 skip_whitespace (*str
);
3743 /* Parse the <Rd> field. */
3744 if ((rd
= reg_required_here (str
, 12)) == FAIL
3745 || skip_past_comma (str
) == FAIL
)
3747 inst
.error
= BAD_ARGS
;
3752 inst
.error
= BAD_PC
;
3756 /* Parse #<immed>, field. */
3757 if (is_immediate_prefix (**str
))
3761 inst
.error
= _("immediate expression expected");
3764 if (my_get_expression (&expr
, str
))
3766 inst
.error
= _("bad expression");
3769 if (expr
.X_op
!= O_constant
)
3771 inst
.error
= _("constant expression expected");
3774 if (expr
.X_add_number
+ bias
< 0
3775 || expr
.X_add_number
+ bias
> 15)
3777 inst
.error
= _("immediate value out of range");
3780 inst
.instruction
|= (expr
.X_add_number
+ bias
) << 16;
3781 if (skip_past_comma (str
) == FAIL
)
3783 inst
.error
= BAD_ARGS
;
3787 /* Parse <Rm> field. */
3788 if ((rm
= reg_required_here (str
, 0)) == FAIL
)
3790 inst
.error
= BAD_ARGS
;
3795 inst
.error
= BAD_PC
;
3800 /* ARM V6 ssat16 (argument parse). */
3803 do_ssat16 (char * str
)
3805 do_sat16 (&str
, /*bias=*/-1);
3810 do_usat16 (char * str
)
3812 do_sat16 (&str
, /*bias=*/0);
3817 do_cps_mode (char ** str
)
3821 skip_whitespace (*str
);
3823 if (! is_immediate_prefix (**str
))
3825 inst
.error
= _("immediate expression expected");
3829 (*str
)++; /* Strip off the immediate signifier. */
3830 if (my_get_expression (&expr
, str
))
3832 inst
.error
= _("bad expression");
3836 if (expr
.X_op
!= O_constant
)
3838 inst
.error
= _("constant expression expected");
3842 /* The mode is a 5 bit field. Valid values are 0-31. */
3843 if (((unsigned) expr
.X_add_number
) > 31
3844 || (inst
.reloc
.exp
.X_add_number
) < 0)
3846 inst
.error
= _("invalid constant");
3850 inst
.instruction
|= expr
.X_add_number
;
3853 /* ARM V6 srs (argument parse). */
3859 skip_whitespace (str
);
3860 exclam
= strchr (str
, '!');
3868 inst
.instruction
|= WRITE_BACK
;
3874 /* ARM V6 SMMUL (argument parse). */
3877 do_smmul (char * str
)
3881 skip_whitespace (str
);
3882 if ((rd
= reg_required_here (&str
, 16)) == FAIL
3883 || skip_past_comma (&str
) == FAIL
3884 || (rm
= reg_required_here (&str
, 0)) == FAIL
3885 || skip_past_comma (&str
) == FAIL
3886 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
3888 inst
.error
= BAD_ARGS
;
3896 inst
.error
= BAD_PC
;
3903 /* ARM V6 SMLALD (argument parse). */
3906 do_smlald (char * str
)
3908 int rdlo
, rdhi
, rm
, rs
;
3910 skip_whitespace (str
);
3911 if ((rdlo
= reg_required_here (&str
, 12)) == FAIL
3912 || skip_past_comma (&str
) == FAIL
3913 || (rdhi
= reg_required_here (&str
, 16)) == FAIL
3914 || skip_past_comma (&str
) == FAIL
3915 || (rm
= reg_required_here (&str
, 0)) == FAIL
3916 || skip_past_comma (&str
) == FAIL
3917 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
3919 inst
.error
= BAD_ARGS
;
3928 inst
.error
= BAD_PC
;
3935 /* ARM V6 SMLAD (argument parse). Signed multiply accumulate dual.
3936 smlad{x}{<cond>} Rd, Rm, Rs, Rn */
3939 do_smlad (char * str
)
3943 skip_whitespace (str
);
3944 if ((rd
= reg_required_here (&str
, 16)) == FAIL
3945 || skip_past_comma (&str
) == FAIL
3946 || (rm
= reg_required_here (&str
, 0)) == FAIL
3947 || skip_past_comma (&str
) == FAIL
3948 || (rs
= reg_required_here (&str
, 8)) == FAIL
3949 || skip_past_comma (&str
) == FAIL
3950 || (rn
= reg_required_here (&str
, 12)) == FAIL
)
3952 inst
.error
= BAD_ARGS
;
3961 inst
.error
= BAD_PC
;
3968 /* Returns true if the endian-specifier indicates big-endianness. */
3971 do_endian_specifier (char * str
)
3975 skip_whitespace (str
);
3976 if (strlen (str
) < 2)
3977 inst
.error
= _("missing endian specifier");
3978 else if (strncasecmp (str
, "BE", 2) == 0)
3983 else if (strncasecmp (str
, "LE", 2) == 0)
3986 inst
.error
= _("valid endian specifiers are be or le");
3993 /* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
3994 preserving the other bits.
3996 setend <endian_specifier>, where <endian_specifier> is either
4000 do_setend (char * str
)
4002 if (do_endian_specifier (str
))
4003 inst
.instruction
|= 0x200;
4008 SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
4009 Condition defaults to COND_ALWAYS.
4010 Error if any register uses R15. */
4013 do_sxth (char * str
)
4017 int rotation_clear_mask
= 0xfffff3ff;
4018 int rotation_eight_mask
= 0x00000400;
4019 int rotation_sixteen_mask
= 0x00000800;
4020 int rotation_twenty_four_mask
= 0x00000c00;
4022 skip_whitespace (str
);
4023 if ((rd
= reg_required_here (&str
, 12)) == FAIL
4024 || skip_past_comma (&str
) == FAIL
4025 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4027 inst
.error
= BAD_ARGS
;
4031 else if (rd
== REG_PC
|| rm
== REG_PC
)
4033 inst
.error
= BAD_PC
;
4037 /* Zero out the rotation field. */
4038 inst
.instruction
&= rotation_clear_mask
;
4040 /* Check for lack of optional rotation field. */
4041 if (skip_past_comma (&str
) == FAIL
)
4047 /* Move past 'ROR'. */
4048 skip_whitespace (str
);
4049 if (strncasecmp (str
, "ROR", 3) == 0)
4053 inst
.error
= _("missing rotation field after comma");
4057 /* Get the immediate constant. */
4058 skip_whitespace (str
);
4059 if (is_immediate_prefix (* str
))
4063 inst
.error
= _("immediate expression expected");
4067 if (my_get_expression (&expr
, &str
))
4069 inst
.error
= _("bad expression");
4073 if (expr
.X_op
!= O_constant
)
4075 inst
.error
= _("constant expression expected");
4079 switch (expr
.X_add_number
)
4082 /* Rotation field has already been zeroed. */
4085 inst
.instruction
|= rotation_eight_mask
;
4089 inst
.instruction
|= rotation_sixteen_mask
;
4093 inst
.instruction
|= rotation_twenty_four_mask
;
4097 inst
.error
= _("rotation can be 8, 16, 24 or 0 when field is ommited");
4104 /* ARM V6 SXTAH extracts a 16-bit value from a register, sign
4105 extends it to 32-bits, and adds the result to a value in another
4106 register. You can specify a rotation by 0, 8, 16, or 24 bits
4107 before extracting the 16-bit value.
4108 SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
4109 Condition defaults to COND_ALWAYS.
4110 Error if any register uses R15. */
4113 do_sxtah (char * str
)
4117 int rotation_clear_mask
= 0xfffff3ff;
4118 int rotation_eight_mask
= 0x00000400;
4119 int rotation_sixteen_mask
= 0x00000800;
4120 int rotation_twenty_four_mask
= 0x00000c00;
4122 skip_whitespace (str
);
4123 if ((rd
= reg_required_here (&str
, 12)) == FAIL
4124 || skip_past_comma (&str
) == FAIL
4125 || (rn
= reg_required_here (&str
, 16)) == FAIL
4126 || skip_past_comma (&str
) == FAIL
4127 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4129 inst
.error
= BAD_ARGS
;
4133 else if (rd
== REG_PC
|| rn
== REG_PC
|| rm
== REG_PC
)
4135 inst
.error
= BAD_PC
;
4139 /* Zero out the rotation field. */
4140 inst
.instruction
&= rotation_clear_mask
;
4142 /* Check for lack of optional rotation field. */
4143 if (skip_past_comma (&str
) == FAIL
)
4149 /* Move past 'ROR'. */
4150 skip_whitespace (str
);
4151 if (strncasecmp (str
, "ROR", 3) == 0)
4155 inst
.error
= _("missing rotation field after comma");
4159 /* Get the immediate constant. */
4160 skip_whitespace (str
);
4161 if (is_immediate_prefix (* str
))
4165 inst
.error
= _("immediate expression expected");
4169 if (my_get_expression (&expr
, &str
))
4171 inst
.error
= _("bad expression");
4175 if (expr
.X_op
!= O_constant
)
4177 inst
.error
= _("constant expression expected");
4181 switch (expr
.X_add_number
)
4184 /* Rotation field has already been zeroed. */
4188 inst
.instruction
|= rotation_eight_mask
;
4192 inst
.instruction
|= rotation_sixteen_mask
;
4196 inst
.instruction
|= rotation_twenty_four_mask
;
4200 inst
.error
= _("rotation can be 8, 16, 24 or 0 when field is ommited");
4208 /* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
4209 word at the specified address and the following word
4211 Unconditionally executed.
4212 Error if Rn is R15. */
4219 skip_whitespace (str
);
4221 if ((rn
= reg_required_here (&str
, 16)) == FAIL
)
4226 inst
.error
= BAD_PC
;
4230 skip_whitespace (str
);
4234 inst
.instruction
|= WRITE_BACK
;
4240 /* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
4241 register (argument parse).
4243 Condition defaults to COND_ALWAYS.
4244 Error if Rd or Rm are R15. */
4251 skip_whitespace (str
);
4253 if ((rd
= reg_required_here (&str
, 12)) == FAIL
4254 || skip_past_comma (&str
) == FAIL
4255 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4256 inst
.error
= BAD_ARGS
;
4258 else if (rd
== REG_PC
|| rm
== REG_PC
)
4259 inst
.error
= BAD_PC
;
4265 /* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
4266 QADD16{<cond>} <Rd>, <Rn>, <Rm>
4267 Condition defaults to COND_ALWAYS.
4268 Error if Rd, Rn or Rm are R15. */
4271 do_qadd16 (char * str
)
4275 skip_whitespace (str
);
4277 if ((rd
= reg_required_here (&str
, 12)) == FAIL
4278 || skip_past_comma (&str
) == FAIL
4279 || (rn
= reg_required_here (&str
, 16)) == FAIL
4280 || skip_past_comma (&str
) == FAIL
4281 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4282 inst
.error
= BAD_ARGS
;
4284 else if (rd
== REG_PC
|| rm
== REG_PC
|| rn
== REG_PC
)
4285 inst
.error
= BAD_PC
;
4292 do_pkh_core (char * str
, int shift
)
4296 skip_whitespace (str
);
4297 if (((rd
= reg_required_here (&str
, 12)) == FAIL
)
4298 || (skip_past_comma (&str
) == FAIL
)
4299 || ((rn
= reg_required_here (&str
, 16)) == FAIL
)
4300 || (skip_past_comma (&str
) == FAIL
)
4301 || ((rm
= reg_required_here (&str
, 0)) == FAIL
))
4303 inst
.error
= BAD_ARGS
;
4307 else if (rd
== REG_PC
|| rn
== REG_PC
|| rm
== REG_PC
)
4309 inst
.error
= BAD_PC
;
4313 /* Check for optional shift immediate constant. */
4314 if (skip_past_comma (&str
) == FAIL
)
4316 if (shift
== SHIFT_ASR_IMMEDIATE
)
4318 /* If the shift specifier is ommited, turn the instruction
4319 into pkhbt rd, rm, rn. First, switch the instruction
4320 code, and clear the rn and rm fields. */
4321 inst
.instruction
&= 0xfff0f010;
4322 /* Now, re-encode the registers. */
4323 inst
.instruction
|= (rm
<< 16) | rn
;
4328 decode_shift (&str
, shift
);
4331 /* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
4332 PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
4333 Condition defaults to COND_ALWAYS.
4334 Error if Rd, Rn or Rm are R15. */
4337 do_pkhbt (char * str
)
4339 do_pkh_core (str
, SHIFT_LSL_IMMEDIATE
);
4342 /* ARM V6 PKHTB (Argument Parse). */
4345 do_pkhtb (char * str
)
4347 do_pkh_core (str
, SHIFT_ASR_IMMEDIATE
);
4350 /* ARM V6 Load Register Exclusive instruction (argument parse).
4351 LDREX{,B,D,H}{<cond>} <Rd, [<Rn>]
4352 Condition defaults to COND_ALWAYS.
4353 Error if Rd or Rn are R15.
4354 See ARMARMv6 A4.1.27: LDREX. */
4357 do_ldrex (char * str
)
4361 skip_whitespace (str
);
4364 if (((rd
= reg_required_here (&str
, 12)) == FAIL
)
4365 || (skip_past_comma (&str
) == FAIL
))
4367 inst
.error
= BAD_ARGS
;
4370 else if (rd
== REG_PC
)
4372 inst
.error
= BAD_PC
;
4375 skip_whitespace (str
);
4377 /* Skip past '['. */
4378 if ((strlen (str
) >= 1)
4379 &&strncmp (str
, "[", 1) == 0)
4381 skip_whitespace (str
);
4384 if ((rn
= reg_required_here (&str
, 16)) == FAIL
)
4386 inst
.error
= BAD_ARGS
;
4389 else if (rn
== REG_PC
)
4391 inst
.error
= BAD_PC
;
4394 skip_whitespace (str
);
4396 /* Skip past ']'. */
4397 if ((strlen (str
) >= 1)
4398 && strncmp (str
, "]", 1) == 0)
4404 /* ARM V6 change processor state instruction (argument parse)
4405 CPS, CPSIE, CSPID . */
4415 do_cps_flags (char ** str
, int thumb_p
)
4420 unsigned long arm_value
;
4421 unsigned long thumb_value
;
4423 static struct cps_flag flag_table
[] =
4432 skip_whitespace (*str
);
4434 /* Get the a, f and i flags. */
4435 while (**str
&& **str
!= ',')
4438 struct cps_flag
*q
= flag_table
+ sizeof (flag_table
)/sizeof (*p
);
4440 for (p
= flag_table
; p
< q
; ++p
)
4441 if (strncasecmp (*str
, &p
->character
, 1) == 0)
4443 inst
.instruction
|= (thumb_p
? p
->thumb_value
: p
->arm_value
);
4449 inst
.error
= _("unrecognized flag");
4456 inst
.error
= _("no 'a', 'i', or 'f' flags for 'cps'");
4460 do_cpsi (char * str
)
4462 do_cps_flags (&str
, /*thumb_p=*/0);
4464 if (skip_past_comma (&str
) == SUCCESS
)
4466 skip_whitespace (str
);
4472 /* ARM V6T2 bitfield manipulation instructions. */
4475 five_bit_unsigned_immediate (char **str
)
4479 skip_whitespace (*str
);
4480 if (!is_immediate_prefix (**str
))
4482 inst
.error
= _("immediate expression expected");
4486 if (my_get_expression (&expr
, str
))
4488 inst
.error
= _("bad expression");
4491 if (expr
.X_op
!= O_constant
)
4493 inst
.error
= _("constant expression expected");
4496 if (expr
.X_add_number
< 0 || expr
.X_add_number
> 32)
4498 inst
.error
= _("immediate value out of range");
4502 return expr
.X_add_number
;
4506 bfci_lsb_and_width (char *str
)
4510 if ((lsb
= five_bit_unsigned_immediate (&str
)) == -1)
4513 if (skip_past_comma (&str
) == FAIL
)
4515 inst
.error
= BAD_ARGS
;
4518 if ((width
= five_bit_unsigned_immediate (&str
)) == -1)
4523 if (width
== 0 || lsb
== 32)
4525 inst
.error
= _("immediate value out of range");
4528 else if (width
+ lsb
> 32)
4530 inst
.error
= _("bit-field extends past end of register");
4534 /* Convert to LSB/MSB and write to register. */
4535 inst
.instruction
|= lsb
<< 7;
4536 inst
.instruction
|= (width
+ lsb
- 1) << 16;
4545 skip_whitespace (str
);
4546 if (((rd
= reg_required_here (&str
, 12)) == FAIL
)
4547 || (skip_past_comma (&str
) == FAIL
))
4549 inst
.error
= BAD_ARGS
;
4552 else if (rd
== REG_PC
)
4554 inst
.error
= BAD_PC
;
4558 bfci_lsb_and_width (str
);
4567 skip_whitespace (str
);
4568 if (((rd
= reg_required_here (&str
, 12)) == FAIL
)
4569 || (skip_past_comma (&str
) == FAIL
))
4571 inst
.error
= BAD_ARGS
;
4574 else if (rd
== REG_PC
)
4576 inst
.error
= BAD_PC
;
4580 /* Rm. Accept #0 in this position as an alternative syntax for bfc. */
4581 skip_whitespace (str
);
4582 if (is_immediate_prefix (*str
))
4586 if (my_get_expression (&expr
, &str
))
4588 inst
.error
= _("bad expression");
4591 if (expr
.X_op
!= O_constant
)
4593 inst
.error
= _("constant expression expected");
4596 if (expr
.X_add_number
!= 0)
4598 inst
.error
= _("immediate value out of range");
4601 inst
.instruction
|= 0x0000000f; /* Rm = PC -> bfc, not bfi. */
4605 if ((rm
= reg_required_here (&str
, 0)) == FAIL
)
4607 inst
.error
= BAD_ARGS
;
4610 else if (rm
== REG_PC
)
4612 inst
.error
= BAD_PC
;
4616 if (skip_past_comma (&str
) == FAIL
)
4618 inst
.error
= BAD_ARGS
;
4622 bfci_lsb_and_width (str
);
4631 skip_whitespace (str
);
4632 if (reg_required_here (&str
, 12) == FAIL
4633 || skip_past_comma (&str
) == FAIL
)
4635 inst
.error
= BAD_ARGS
;
4640 skip_whitespace (str
);
4641 if (reg_required_here (&str
, 0) == FAIL
4642 || skip_past_comma (&str
) == FAIL
)
4644 inst
.error
= BAD_ARGS
;
4648 if ((lsb
= five_bit_unsigned_immediate (&str
)) == -1)
4651 if (skip_past_comma (&str
) == FAIL
)
4653 inst
.error
= BAD_ARGS
;
4656 if ((width
= five_bit_unsigned_immediate (&str
)) == -1)
4661 if (width
== 0 || lsb
== 32)
4663 inst
.error
= _("immediate value out of range");
4666 else if (width
+ lsb
> 32)
4668 inst
.error
= _("bit-field extends past end of register");
4672 inst
.instruction
|= lsb
<< 7;
4673 inst
.instruction
|= (width
- 1) << 16;
4680 skip_whitespace (str
);
4681 if (reg_required_here (&str
, 12) == FAIL
4682 || skip_past_comma (&str
) == FAIL
)
4684 inst
.error
= BAD_ARGS
;
4689 skip_whitespace (str
);
4690 if (reg_required_here (&str
, 0) == FAIL
)
4692 inst
.error
= BAD_ARGS
;
4699 /* ARM V6T2 16-bit immediate register load: MOV[WT]{cond} Rd, #<imm16>. */
4701 do_mov16 (char *str
)
4707 skip_whitespace (str
);
4708 if (((rd
= reg_required_here (&str
, 12)) == FAIL
)
4709 || (skip_past_comma (&str
) == FAIL
))
4711 inst
.error
= BAD_ARGS
;
4714 else if (rd
== REG_PC
)
4716 inst
.error
= BAD_PC
;
4721 skip_whitespace (str
);
4722 if (!is_immediate_prefix (*str
))
4724 inst
.error
= _("immediate expression expected");
4728 if (my_get_expression (&expr
, &str
))
4730 inst
.error
= _("bad expression");
4733 if (expr
.X_op
!= O_constant
)
4735 inst
.error
= _("constant expression expected");
4738 if (expr
.X_add_number
< 0 || expr
.X_add_number
> 65535)
4740 inst
.error
= _("immediate value out of range");
4746 /* The value is in two pieces: 0:11, 16:19. */
4747 inst
.instruction
|= (expr
.X_add_number
& 0x00000fff);
4748 inst
.instruction
|= (expr
.X_add_number
& 0x0000f000) << 4;
4752 /* THUMB V5 breakpoint instruction (argument parse)
4756 do_t_bkpt (char * str
)
4759 unsigned long number
;
4761 skip_whitespace (str
);
4763 /* Allow optional leading '#'. */
4764 if (is_immediate_prefix (*str
))
4767 memset (& expr
, '\0', sizeof (expr
));
4768 if (my_get_expression (& expr
, & str
)
4769 || (expr
.X_op
!= O_constant
4770 /* As a convenience we allow 'bkpt' without an operand. */
4771 && expr
.X_op
!= O_absent
))
4773 inst
.error
= _("bad expression");
4777 number
= expr
.X_add_number
;
4779 /* Check it fits an 8 bit unsigned. */
4780 if (number
!= (number
& 0xff))
4782 inst
.error
= _("immediate value out of range");
4786 inst
.instruction
|= number
;
4792 static bfd_reloc_code_real_type
4793 arm_parse_reloc (void)
4802 bfd_reloc_code_real_type reloc
;
4806 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
4807 MAP ("(got)", BFD_RELOC_ARM_GOT32
),
4808 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF
),
4809 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
4810 branch instructions generated by GCC for PLT relocs. */
4811 MAP ("(plt)", BFD_RELOC_ARM_PLT32
),
4812 MAP ("(target1)", BFD_RELOC_ARM_TARGET1
),
4813 MAP ("(sbrel)", BFD_RELOC_ARM_SBREL32
),
4814 MAP ("(target2)", BFD_RELOC_ARM_TARGET2
),
4815 MAP ("(tlsgd)", BFD_RELOC_ARM_TLS_GD32
),
4816 MAP ("(tlsldm)", BFD_RELOC_ARM_TLS_LDM32
),
4817 MAP ("(tlsldo)", BFD_RELOC_ARM_TLS_LDO32
),
4818 MAP ("(gottpoff)", BFD_RELOC_ARM_TLS_IE32
),
4819 MAP ("(tpoff)", BFD_RELOC_ARM_TLS_LE32
),
4820 { NULL
, 0, BFD_RELOC_UNUSED
}
4824 for (i
= 0, ip
= input_line_pointer
;
4825 i
< sizeof (id
) && (ISALNUM (*ip
) || ISPUNCT (*ip
));
4827 id
[i
] = TOLOWER (*ip
);
4829 for (i
= 0; reloc_map
[i
].str
; i
++)
4830 if (strncmp (id
, reloc_map
[i
].str
, reloc_map
[i
].len
) == 0)
4833 input_line_pointer
+= reloc_map
[i
].len
;
4835 return reloc_map
[i
].reloc
;
4839 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
4840 Expects inst.instruction is set for BLX(1).
4841 Note: this is cloned from do_branch, and the reloc changed to be a
4842 new one that can cope with setting one extra bit (the H bit). */
4845 do_branch25 (char * str
)
4847 if (my_get_expression (& inst
.reloc
.exp
, & str
))
4854 /* ScottB: February 5, 1998 */
4855 /* Check to see of PLT32 reloc required for the instruction. */
4857 /* arm_parse_reloc() works on input_line_pointer.
4858 We actually want to parse the operands to the branch instruction
4859 passed in 'str'. Save the input pointer and restore it later. */
4860 save_in
= input_line_pointer
;
4861 input_line_pointer
= str
;
4863 if (inst
.reloc
.exp
.X_op
== O_symbol
4865 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
4867 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
4868 inst
.reloc
.pc_rel
= 0;
4869 /* Modify str to point to after parsed operands, otherwise
4870 end_of_line() will complain about the (PLT) left in str. */
4871 str
= input_line_pointer
;
4875 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
4876 inst
.reloc
.pc_rel
= 1;
4879 input_line_pointer
= save_in
;
4882 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
4883 inst
.reloc
.pc_rel
= 1;
4884 #endif /* OBJ_ELF */
4889 /* ARM V5 branch-link-exchange instruction (argument parse)
4890 BLX <target_addr> ie BLX(1)
4891 BLX{<condition>} <Rm> ie BLX(2)
4892 Unfortunately, there are two different opcodes for this mnemonic.
4893 So, the insns[].value is not used, and the code here zaps values
4894 into inst.instruction.
4895 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
4903 skip_whitespace (mystr
);
4904 rm
= reg_required_here (& mystr
, 0);
4906 /* The above may set inst.error. Ignore his opinion. */
4911 /* Arg is a register.
4912 Use the condition code our caller put in inst.instruction.
4913 Pass ourselves off as a BX with a funny opcode. */
4914 inst
.instruction
|= 0x012fff30;
4919 /* This must be is BLX <target address>, no condition allowed. */
4920 if (inst
.instruction
!= COND_ALWAYS
)
4922 inst
.error
= BAD_COND
;
4926 inst
.instruction
= 0xfafffffe;
4928 /* Process like a B/BL, but with a different reloc.
4929 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
4934 /* ARM V5 Thumb BLX (argument parse)
4935 BLX <target_addr> which is BLX(1)
4936 BLX <Rm> which is BLX(2)
4937 Unfortunately, there are two different opcodes for this mnemonic.
4938 So, the tinsns[].value is not used, and the code here zaps values
4939 into inst.instruction. */
4942 do_t_blx (char * str
)
4947 skip_whitespace (mystr
);
4948 inst
.instruction
= 0x4780;
4950 /* Note that this call is to the ARM register recognizer. BLX(2)
4951 uses the ARM register space, not the Thumb one, so a call to
4952 thumb_reg() would be wrong. */
4953 rm
= reg_required_here (& mystr
, 3);
4958 /* It's BLX(2). The .instruction was zapped with rm & is final. */
4963 /* No ARM register. This must be BLX(1). Change the .instruction. */
4964 inst
.instruction
= 0xf7ffeffe;
4967 if (my_get_expression (& inst
.reloc
.exp
, & mystr
))
4970 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BLX
;
4971 inst
.reloc
.pc_rel
= 1;
4974 end_of_line (mystr
);
4977 /* ARM V5 breakpoint instruction (argument parse)
4978 BKPT <16 bit unsigned immediate>
4979 Instruction is not conditional.
4980 The bit pattern given in insns[] has the COND_ALWAYS condition,
4981 and it is an error if the caller tried to override that. */
4984 do_bkpt (char * str
)
4987 unsigned long number
;
4989 skip_whitespace (str
);
4991 /* Allow optional leading '#'. */
4992 if (is_immediate_prefix (* str
))
4995 memset (& expr
, '\0', sizeof (expr
));
4997 if (my_get_expression (& expr
, & str
)
4998 || (expr
.X_op
!= O_constant
4999 /* As a convenience we allow 'bkpt' without an operand. */
5000 && expr
.X_op
!= O_absent
))
5002 inst
.error
= _("bad expression");
5006 number
= expr
.X_add_number
;
5008 /* Check it fits a 16 bit unsigned. */
5009 if (number
!= (number
& 0xffff))
5011 inst
.error
= _("immediate value out of range");
5015 /* Top 12 of 16 bits to bits 19:8. */
5016 inst
.instruction
|= (number
& 0xfff0) << 4;
5018 /* Bottom 4 of 16 bits to bits 3:0. */
5019 inst
.instruction
|= number
& 0xf;
5024 /* THUMB CPS instruction (argument parse). */
5027 do_t_cps (char * str
)
5029 do_cps_flags (&str
, /*thumb_p=*/1);
5033 /* Parse and validate that a register is of the right form, this saves
5034 repeated checking of this information in many similar cases.
5035 Unlike the 32-bit case we do not insert the register into the opcode
5036 here, since the position is often unknown until the full instruction
5040 thumb_reg (char ** strp
, int hi_lo
)
5044 if ((reg
= reg_required_here (strp
, -1)) == FAIL
)
5052 inst
.error
= _("lo register required");
5060 inst
.error
= _("hi register required");
5073 thumb_mov_compare (char * str
, int move
)
5077 skip_whitespace (str
);
5079 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
5080 || skip_past_comma (&str
) == FAIL
)
5083 inst
.error
= BAD_ARGS
;
5087 if (move
!= THUMB_CPY
&& is_immediate_prefix (*str
))
5090 if (my_get_expression (&inst
.reloc
.exp
, &str
))
5093 else if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
5098 if (move
!= THUMB_CPY
&& Rs
< 8 && Rd
< 8)
5100 if (move
== THUMB_MOVE
)
5101 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
5102 since a MOV instruction produces unpredictable results. */
5103 inst
.instruction
= T_OPCODE_ADD_I3
;
5105 inst
.instruction
= T_OPCODE_CMP_LR
;
5106 inst
.instruction
|= Rd
| (Rs
<< 3);
5110 if (move
== THUMB_MOVE
)
5111 inst
.instruction
= T_OPCODE_MOV_HR
;
5112 else if (move
!= THUMB_CPY
)
5113 inst
.instruction
= T_OPCODE_CMP_HR
;
5116 inst
.instruction
|= THUMB_H1
;
5119 inst
.instruction
|= THUMB_H2
;
5121 inst
.instruction
|= (Rd
& 7) | ((Rs
& 7) << 3);
5128 inst
.error
= _("only lo regs allowed with immediate");
5132 if (move
== THUMB_MOVE
)
5133 inst
.instruction
= T_OPCODE_MOV_I8
;
5135 inst
.instruction
= T_OPCODE_CMP_I8
;
5137 inst
.instruction
|= Rd
<< 8;
5139 if (inst
.reloc
.exp
.X_op
!= O_constant
)
5140 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_IMM
;
5143 unsigned value
= inst
.reloc
.exp
.X_add_number
;
5147 inst
.error
= _("invalid immediate");
5151 inst
.instruction
|= value
;
5158 /* THUMB CPY instruction (argument parse). */
5161 do_t_cpy (char * str
)
5163 thumb_mov_compare (str
, THUMB_CPY
);
5166 /* THUMB SETEND instruction (argument parse). */
5169 do_t_setend (char * str
)
5171 if (do_endian_specifier (str
))
5172 inst
.instruction
|= 0x8;
5175 /* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
5177 static unsigned long
5178 check_iwmmxt_insn (char * str
,
5179 enum iwmmxt_insn_type insn_type
,
5183 const char * inst_error
;
5185 unsigned long number
;
5187 inst_error
= inst
.error
;
5189 inst
.error
= BAD_ARGS
;
5190 skip_whitespace (str
);
5195 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
5200 if ((wreg_required_here (&str
, 0, IWMMXT_REG_WR
)) == FAIL
)
5205 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
5206 || skip_past_comma (&str
) == FAIL
5207 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
))
5212 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
5213 || skip_past_comma (&str
) == FAIL
5214 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5215 || skip_past_comma (&str
) == FAIL
5216 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
))
5221 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
5222 || skip_past_comma (&str
) == FAIL
5223 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5224 || skip_past_comma (&str
) == FAIL
5225 || wreg_required_here (&str
, 0, IWMMXT_REG_WCG
) == FAIL
))
5230 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5231 || skip_past_comma (&str
) == FAIL
5232 || reg_required_here (&str
, 12) == FAIL
))
5237 if ((reg_required_here (&str
, 12) == FAIL
5238 || skip_past_comma (&str
) == FAIL
5239 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
))
5244 if ((wreg_required_here (&str
, 5, IWMMXT_REG_WR
) == FAIL
5245 || skip_past_comma (&str
) == FAIL
5246 || reg_required_here (&str
, 0) == FAIL
5247 || skip_past_comma (&str
) == FAIL
5248 || reg_required_here (&str
, 12) == FAIL
))
5253 if ((wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
5254 || skip_past_comma (&str
) == FAIL
5255 || reg_required_here (&str
, 12) == FAIL
5256 || skip_past_comma (&str
) == FAIL
5257 || reg_required_here (&str
, 16) == FAIL
))
5262 if ((reg_required_here (&str
, 12) == FAIL
5263 || skip_past_comma (&str
) == FAIL
5264 || reg_required_here (&str
, 16) == FAIL
5265 || skip_past_comma (&str
) == FAIL
5266 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
))
5271 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WC
) == FAIL
5272 || skip_past_comma (&str
) == FAIL
5273 || reg_required_here (&str
, 12) == FAIL
))
5278 if ((reg_required_here (&str
, 12) == FAIL
5279 || skip_past_comma (&str
) == FAIL
5280 || wreg_required_here (&str
, 16, IWMMXT_REG_WC
) == FAIL
))
5285 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5286 || skip_past_comma (&str
) == FAIL
5287 || reg_required_here (&str
, 12) == FAIL
5288 || skip_past_comma (&str
) == FAIL
))
5293 if ((reg_required_here (&str
, 12) == FAIL
5294 || skip_past_comma (&str
) == FAIL
))
5299 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
5300 || skip_past_comma (&str
) == FAIL
5301 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5302 || skip_past_comma (&str
) == FAIL
5303 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
5304 || skip_past_comma (&str
) == FAIL
))
5309 if ((reg_required_here (&str
, 12) == FAIL
5310 || skip_past_comma (&str
) == FAIL
5311 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5312 || skip_past_comma (&str
) == FAIL
))
5317 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
5318 || skip_past_comma (&str
) == FAIL
5319 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5320 || skip_past_comma (&str
) == FAIL
))
5325 if (immediate_size
== 0)
5328 inst
.error
= inst_error
;
5333 skip_whitespace (str
);
5335 /* Allow optional leading '#'. */
5336 if (is_immediate_prefix (* str
))
5339 memset (& expr
, '\0', sizeof (expr
));
5341 if (my_get_expression (& expr
, & str
) || (expr
.X_op
!= O_constant
))
5343 inst
.error
= _("bad or missing expression");
5347 number
= expr
.X_add_number
;
5349 if (number
!= (number
& immediate_size
))
5351 inst
.error
= _("immediate value out of range");
5355 inst
.error
= inst_error
;
5361 do_iwmmxt_byte_addr (char * str
)
5363 int op
= (inst
.instruction
& 0x300) >> 8;
5366 inst
.instruction
&= ~0x300;
5367 inst
.instruction
|= (op
& 1) << 22 | (op
& 2) << 7;
5369 skip_whitespace (str
);
5371 if ((reg
= wreg_required_here (&str
, 12, IWMMXT_REG_WR_OR_WC
)) == FAIL
5372 || skip_past_comma (& str
) == FAIL
5373 || cp_byte_address_required_here (&str
) == FAIL
)
5376 inst
.error
= BAD_ARGS
;
5381 if (wc_register (reg
))
5383 as_bad (_("non-word size not supported with control register"));
5384 inst
.instruction
|= 0xf0000100;
5385 inst
.instruction
&= ~0x00400000;
5390 do_iwmmxt_tandc (char * str
)
5394 reg
= check_iwmmxt_insn (str
, check_rd
, 0);
5396 if (reg
!= REG_PC
&& !inst
.error
)
5397 inst
.error
= _("only r15 allowed here");
5401 do_iwmmxt_tbcst (char * str
)
5403 check_iwmmxt_insn (str
, check_tbcst
, 0);
5407 do_iwmmxt_textrc (char * str
)
5409 unsigned long number
;
5411 if ((number
= check_iwmmxt_insn (str
, check_textrc
, 7)) == (unsigned long) FAIL
)
5414 inst
.instruction
|= number
& 0x7;
5418 do_iwmmxt_textrm (char * str
)
5420 unsigned long number
;
5422 if ((number
= check_iwmmxt_insn (str
, check_textrm
, 7)) == (unsigned long) FAIL
)
5425 inst
.instruction
|= number
& 0x7;
5429 do_iwmmxt_tinsr (char * str
)
5431 unsigned long number
;
5433 if ((number
= check_iwmmxt_insn (str
, check_tinsr
, 7)) == (unsigned long) FAIL
)
5436 inst
.instruction
|= number
& 0x7;
5440 do_iwmmxt_tmcr (char * str
)
5442 check_iwmmxt_insn (str
, check_tmcr
, 0);
5446 do_iwmmxt_tmcrr (char * str
)
5448 check_iwmmxt_insn (str
, check_tmcrr
, 0);
5452 do_iwmmxt_tmia (char * str
)
5454 check_iwmmxt_insn (str
, check_tmia
, 0);
5458 do_iwmmxt_tmovmsk (char * str
)
5460 check_iwmmxt_insn (str
, check_tmovmsk
, 0);
5464 do_iwmmxt_tmrc (char * str
)
5466 check_iwmmxt_insn (str
, check_tmrc
, 0);
5470 do_iwmmxt_tmrrc (char * str
)
5472 check_iwmmxt_insn (str
, check_tmrrc
, 0);
5476 do_iwmmxt_torc (char * str
)
5478 check_iwmmxt_insn (str
, check_rd
, 0);
5482 do_iwmmxt_waligni (char * str
)
5484 unsigned long number
;
5486 if ((number
= check_iwmmxt_insn (str
, check_waligni
, 7)) == (unsigned long) FAIL
)
5489 inst
.instruction
|= ((number
& 0x7) << 20);
5493 do_iwmmxt_wmov (char * str
)
5495 if (check_iwmmxt_insn (str
, check_wrwr
, 0) == (unsigned long) FAIL
)
5498 inst
.instruction
|= ((inst
.instruction
>> 16) & 0xf);
5502 do_iwmmxt_word_addr (char * str
)
5504 int op
= (inst
.instruction
& 0x300) >> 8;
5507 inst
.instruction
&= ~0x300;
5508 inst
.instruction
|= (op
& 1) << 22 | (op
& 2) << 7;
5510 skip_whitespace (str
);
5512 if ((reg
= wreg_required_here (&str
, 12, IWMMXT_REG_WR_OR_WC
)) == FAIL
5513 || skip_past_comma (& str
) == FAIL
5514 || cp_address_required_here (& str
, CP_WB_OK
) == FAIL
)
5517 inst
.error
= BAD_ARGS
;
5522 if (wc_register (reg
))
5524 if ((inst
.instruction
& COND_MASK
) != COND_ALWAYS
)
5525 as_bad (_("conditional execution not supported with control register"));
5527 as_bad (_("non-word size not supported with control register"));
5528 inst
.instruction
|= 0xf0000100;
5529 inst
.instruction
&= ~0x00400000;
5534 do_iwmmxt_wrwr (char * str
)
5536 check_iwmmxt_insn (str
, check_wrwr
, 0);
5540 do_iwmmxt_wrwrwcg (char * str
)
5542 check_iwmmxt_insn (str
, check_wrwrwcg
, 0);
5546 do_iwmmxt_wrwrwr (char * str
)
5548 check_iwmmxt_insn (str
, check_wrwrwr
, 0);
5552 do_iwmmxt_wshufh (char * str
)
5554 unsigned long number
;
5556 if ((number
= check_iwmmxt_insn (str
, check_wshufh
, 0xff)) == (unsigned long) FAIL
)
5559 inst
.instruction
|= ((number
& 0xf0) << 16) | (number
& 0xf);
5563 do_iwmmxt_wzero (char * str
)
5565 if (check_iwmmxt_insn (str
, check_wr
, 0) == (unsigned long) FAIL
)
5568 inst
.instruction
|= ((inst
.instruction
& 0xf) << 12) | ((inst
.instruction
& 0xf) << 16);
5571 /* Xscale multiply-accumulate (argument parse)
5574 MIAxycc acc0,Rm,Rs. */
5577 do_xsc_mia (char * str
)
5582 if (accum0_required_here (& str
) == FAIL
)
5583 inst
.error
= ERR_NO_ACCUM
;
5585 else if (skip_past_comma (& str
) == FAIL
5586 || (rm
= reg_required_here (& str
, 0)) == FAIL
)
5587 inst
.error
= BAD_ARGS
;
5589 else if (skip_past_comma (& str
) == FAIL
5590 || (rs
= reg_required_here (& str
, 12)) == FAIL
)
5591 inst
.error
= BAD_ARGS
;
5593 /* inst.instruction has now been zapped with both rm and rs. */
5594 else if (rm
== REG_PC
|| rs
== REG_PC
)
5595 inst
.error
= BAD_PC
; /* Undefined result if rm or rs is R15. */
5601 /* Xscale move-accumulator-register (argument parse)
5603 MARcc acc0,RdLo,RdHi. */
5606 do_xsc_mar (char * str
)
5610 if (accum0_required_here (& str
) == FAIL
)
5611 inst
.error
= ERR_NO_ACCUM
;
5613 else if (skip_past_comma (& str
) == FAIL
5614 || (rdlo
= reg_required_here (& str
, 12)) == FAIL
)
5615 inst
.error
= BAD_ARGS
;
5617 else if (skip_past_comma (& str
) == FAIL
5618 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
5619 inst
.error
= BAD_ARGS
;
5621 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5622 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
5623 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
5629 /* Xscale move-register-accumulator (argument parse)
5631 MRAcc RdLo,RdHi,acc0. */
5634 do_xsc_mra (char * str
)
5639 skip_whitespace (str
);
5641 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
)
5642 inst
.error
= BAD_ARGS
;
5644 else if (skip_past_comma (& str
) == FAIL
5645 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
5646 inst
.error
= BAD_ARGS
;
5648 else if (skip_past_comma (& str
) == FAIL
5649 || accum0_required_here (& str
) == FAIL
)
5650 inst
.error
= ERR_NO_ACCUM
;
5652 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5653 else if (rdlo
== rdhi
)
5654 inst
.error
= BAD_ARGS
; /* Undefined result if 2 writes to same reg. */
5656 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
5657 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
5663 ldst_extend (char ** str
)
5672 if (my_get_expression (& inst
.reloc
.exp
, str
))
5675 if (inst
.reloc
.exp
.X_op
== O_constant
)
5677 int value
= inst
.reloc
.exp
.X_add_number
;
5679 if (value
< -4095 || value
> 4095)
5681 inst
.error
= _("address offset too large");
5691 inst
.instruction
|= add
| value
;
5695 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
5696 inst
.reloc
.pc_rel
= 0;
5709 if (reg_required_here (str
, 0) == FAIL
)
5712 inst
.instruction
|= add
| OFFSET_REG
;
5713 if (skip_past_comma (str
) == SUCCESS
)
5714 return decode_shift (str
, SHIFT_IMMEDIATE
);
5720 /* ARMv5TE: Preload-Cache
5724 Syntactically, like LDR with B=1, W=0, L=1. */
5731 skip_whitespace (str
);
5735 inst
.error
= _("'[' expected after PLD mnemonic");
5740 skip_whitespace (str
);
5742 if ((rd
= reg_required_here (& str
, 16)) == FAIL
)
5745 skip_whitespace (str
);
5751 skip_whitespace (str
);
5753 /* Post-indexed addressing is not allowed with PLD. */
5754 if (skip_past_comma (&str
) == SUCCESS
)
5757 = _("post-indexed expression used in preload instruction");
5760 else if (*str
== '!') /* [Rn]! */
5762 inst
.error
= _("writeback used in preload instruction");
5766 inst
.instruction
|= INDEX_UP
| PRE_INDEX
;
5768 else /* [Rn, ...] */
5770 if (skip_past_comma (& str
) == FAIL
)
5772 inst
.error
= _("pre-indexed expression expected");
5776 if (ldst_extend (&str
) == FAIL
)
5779 skip_whitespace (str
);
5783 inst
.error
= _("missing ]");
5788 skip_whitespace (str
);
5790 if (* str
== '!') /* [Rn]! */
5792 inst
.error
= _("writeback used in preload instruction");
5796 inst
.instruction
|= PRE_INDEX
;
5802 /* ARMv5TE load-consecutive (argument parse)
5809 do_ldrd (char * str
)
5814 skip_whitespace (str
);
5816 if ((rd
= reg_required_here (& str
, 12)) == FAIL
)
5818 inst
.error
= BAD_ARGS
;
5822 if (skip_past_comma (& str
) == FAIL
5823 || (rn
= ld_mode_required_here (& str
)) == FAIL
)
5826 inst
.error
= BAD_ARGS
;
5830 /* inst.instruction has now been zapped with Rd and the addressing mode. */
5831 if (rd
& 1) /* Unpredictable result if Rd is odd. */
5833 inst
.error
= _("destination register must be even");
5839 inst
.error
= _("r14 not allowed here");
5843 if (((rd
== rn
) || (rd
+ 1 == rn
))
5844 && ((inst
.instruction
& WRITE_BACK
)
5845 || (!(inst
.instruction
& PRE_INDEX
))))
5846 as_warn (_("pre/post-indexing used when modified address register is destination"));
5848 /* For an index-register load, the index register must not overlap the
5849 destination (even if not write-back). */
5850 if ((inst
.instruction
& V4_STR_BIT
) == 0
5851 && (inst
.instruction
& HWOFFSET_IMM
) == 0)
5853 int rm
= inst
.instruction
& 0x0000000f;
5855 if (rm
== rd
|| (rm
== rd
+ 1))
5856 as_warn (_("ldrd destination registers must not overlap index register"));
5862 /* Returns the index into fp_values of a floating point number,
5863 or -1 if not in the table. */
5866 my_get_float_expression (char ** str
)
5868 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
5874 memset (words
, 0, MAX_LITTLENUMS
* sizeof (LITTLENUM_TYPE
));
5876 /* Look for a raw floating point number. */
5877 if ((save_in
= atof_ieee (*str
, 'x', words
)) != NULL
5878 && is_end_of_line
[(unsigned char) *save_in
])
5880 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
5882 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
5884 if (words
[j
] != fp_values
[i
][j
])
5888 if (j
== MAX_LITTLENUMS
)
5896 /* Try and parse a more complex expression, this will probably fail
5897 unless the code uses a floating point prefix (eg "0f"). */
5898 save_in
= input_line_pointer
;
5899 input_line_pointer
= *str
;
5900 if (expression (&exp
) == absolute_section
5901 && exp
.X_op
== O_big
5902 && exp
.X_add_number
< 0)
5904 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
5906 if (gen_to_words (words
, 5, (long) 15) == 0)
5908 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
5910 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
5912 if (words
[j
] != fp_values
[i
][j
])
5916 if (j
== MAX_LITTLENUMS
)
5918 *str
= input_line_pointer
;
5919 input_line_pointer
= save_in
;
5926 *str
= input_line_pointer
;
5927 input_line_pointer
= save_in
;
5931 /* We handle all bad expressions here, so that we can report the faulty
5932 instruction in the error message. */
5934 md_operand (expressionS
* expr
)
5936 if (in_my_get_expression
)
5938 expr
->X_op
= O_illegal
;
5939 if (inst
.error
== NULL
)
5940 inst
.error
= _("bad expression");
5944 /* Do those data_ops which can take a negative immediate constant
5945 by altering the instruction. A bit of a hack really.
5949 by inverting the second operand, and
5952 by negating the second operand. */
5955 negate_data_op (unsigned long * instruction
,
5956 unsigned long value
)
5959 unsigned long negated
, inverted
;
5961 negated
= validate_immediate (-value
);
5962 inverted
= validate_immediate (~value
);
5964 op
= (*instruction
>> DATA_OP_SHIFT
) & 0xf;
5967 /* First negates. */
5968 case OPCODE_SUB
: /* ADD <-> SUB */
5969 new_inst
= OPCODE_ADD
;
5974 new_inst
= OPCODE_SUB
;
5978 case OPCODE_CMP
: /* CMP <-> CMN */
5979 new_inst
= OPCODE_CMN
;
5984 new_inst
= OPCODE_CMP
;
5988 /* Now Inverted ops. */
5989 case OPCODE_MOV
: /* MOV <-> MVN */
5990 new_inst
= OPCODE_MVN
;
5995 new_inst
= OPCODE_MOV
;
5999 case OPCODE_AND
: /* AND <-> BIC */
6000 new_inst
= OPCODE_BIC
;
6005 new_inst
= OPCODE_AND
;
6009 case OPCODE_ADC
: /* ADC <-> SBC */
6010 new_inst
= OPCODE_SBC
;
6015 new_inst
= OPCODE_ADC
;
6019 /* We cannot do anything. */
6024 if (value
== (unsigned) FAIL
)
6027 *instruction
&= OPCODE_MASK
;
6028 *instruction
|= new_inst
<< DATA_OP_SHIFT
;
6033 data_op2 (char ** str
)
6038 skip_whitespace (* str
);
6040 if (reg_required_here (str
, 0) != FAIL
)
6042 if (skip_past_comma (str
) == SUCCESS
)
6043 /* Shift operation on register. */
6044 return decode_shift (str
, NO_SHIFT_RESTRICT
);
6050 /* Immediate expression. */
6051 if (is_immediate_prefix (**str
))
6056 if (my_get_expression (&inst
.reloc
.exp
, str
))
6059 if (inst
.reloc
.exp
.X_add_symbol
)
6061 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
6062 inst
.reloc
.pc_rel
= 0;
6066 if (skip_past_comma (str
) == SUCCESS
)
6068 /* #x, y -- ie explicit rotation by Y. */
6069 if (my_get_expression (&expr
, str
))
6072 if (expr
.X_op
!= O_constant
)
6074 inst
.error
= _("constant expression expected");
6078 /* Rotate must be a multiple of 2. */
6079 if (((unsigned) expr
.X_add_number
) > 30
6080 || (expr
.X_add_number
& 1) != 0
6081 || ((unsigned) inst
.reloc
.exp
.X_add_number
) > 255)
6083 inst
.error
= _("invalid constant");
6086 inst
.instruction
|= INST_IMMEDIATE
;
6087 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
6088 inst
.instruction
|= expr
.X_add_number
<< 7;
6092 /* Implicit rotation, select a suitable one. */
6093 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
6097 /* Can't be done. Perhaps the code reads something like
6098 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
6099 if ((value
= negate_data_op (&inst
.instruction
,
6100 inst
.reloc
.exp
.X_add_number
))
6103 inst
.error
= _("invalid constant");
6108 inst
.instruction
|= value
;
6111 inst
.instruction
|= INST_IMMEDIATE
;
6116 inst
.error
= _("register or shift expression expected");
6122 fp_op2 (char ** str
)
6124 skip_whitespace (* str
);
6126 if (fp_reg_required_here (str
, 0) != FAIL
)
6130 /* Immediate expression. */
6131 if (*((*str
)++) == '#')
6137 skip_whitespace (* str
);
6139 /* First try and match exact strings, this is to guarantee
6140 that some formats will work even for cross assembly. */
6142 for (i
= 0; fp_const
[i
]; i
++)
6144 if (strncmp (*str
, fp_const
[i
], strlen (fp_const
[i
])) == 0)
6148 *str
+= strlen (fp_const
[i
]);
6149 if (is_end_of_line
[(unsigned char) **str
])
6151 inst
.instruction
|= i
+ 8;
6158 /* Just because we didn't get a match doesn't mean that the
6159 constant isn't valid, just that it is in a format that we
6160 don't automatically recognize. Try parsing it with
6161 the standard expression routines. */
6162 if ((i
= my_get_float_expression (str
)) >= 0)
6164 inst
.instruction
|= i
+ 8;
6168 inst
.error
= _("invalid floating point immediate expression");
6172 _("floating point register or immediate expression expected");
6178 do_arit (char * str
)
6180 skip_whitespace (str
);
6182 if (reg_required_here (&str
, 12) == FAIL
6183 || skip_past_comma (&str
) == FAIL
6184 || reg_required_here (&str
, 16) == FAIL
6185 || skip_past_comma (&str
) == FAIL
6186 || data_op2 (&str
) == FAIL
)
6189 inst
.error
= BAD_ARGS
;
6199 /* This is a pseudo-op of the form "adr rd, label" to be converted
6200 into a relative address of the form "add rd, pc, #label-.-8". */
6201 skip_whitespace (str
);
6203 if (reg_required_here (&str
, 12) == FAIL
6204 || skip_past_comma (&str
) == FAIL
6205 || my_get_expression (&inst
.reloc
.exp
, &str
))
6208 inst
.error
= BAD_ARGS
;
6212 /* Frag hacking will turn this into a sub instruction if the offset turns
6213 out to be negative. */
6214 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
6216 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust. */
6218 inst
.reloc
.pc_rel
= 1;
6224 do_adrl (char * str
)
6226 /* This is a pseudo-op of the form "adrl rd, label" to be converted
6227 into a relative address of the form:
6228 add rd, pc, #low(label-.-8)"
6229 add rd, rd, #high(label-.-8)" */
6231 skip_whitespace (str
);
6233 if (reg_required_here (&str
, 12) == FAIL
6234 || skip_past_comma (&str
) == FAIL
6235 || my_get_expression (&inst
.reloc
.exp
, &str
))
6238 inst
.error
= BAD_ARGS
;
6244 /* Frag hacking will turn this into a sub instruction if the offset turns
6245 out to be negative. */
6246 inst
.reloc
.type
= BFD_RELOC_ARM_ADRL_IMMEDIATE
;
6248 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust */
6250 inst
.reloc
.pc_rel
= 1;
6251 inst
.size
= INSN_SIZE
* 2;
6257 skip_whitespace (str
);
6259 if (reg_required_here (&str
, 16) == FAIL
)
6262 inst
.error
= BAD_ARGS
;
6266 if (skip_past_comma (&str
) == FAIL
6267 || data_op2 (&str
) == FAIL
)
6270 inst
.error
= BAD_ARGS
;
6280 skip_whitespace (str
);
6282 if (reg_required_here (&str
, 12) == FAIL
)
6285 inst
.error
= BAD_ARGS
;
6289 if (skip_past_comma (&str
) == FAIL
6290 || data_op2 (&str
) == FAIL
)
6293 inst
.error
= BAD_ARGS
;
6301 do_ldst (char * str
)
6307 skip_whitespace (str
);
6309 if ((conflict_reg
= reg_required_here (&str
, 12)) == FAIL
)
6312 inst
.error
= BAD_ARGS
;
6316 if (skip_past_comma (&str
) == FAIL
)
6318 inst
.error
= _("address expected");
6328 skip_whitespace (str
);
6330 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6333 /* Conflicts can occur on stores as well as loads. */
6334 conflict_reg
= (conflict_reg
== reg
);
6336 skip_whitespace (str
);
6342 if (skip_past_comma (&str
) == SUCCESS
)
6344 /* [Rn],... (post inc) */
6345 if (ldst_extend (&str
) == FAIL
)
6348 as_warn (_("%s register same as write-back base"),
6349 ((inst
.instruction
& LOAD_BIT
)
6350 ? _("destination") : _("source")));
6355 skip_whitespace (str
);
6360 as_warn (_("%s register same as write-back base"),
6361 ((inst
.instruction
& LOAD_BIT
)
6362 ? _("destination") : _("source")));
6364 inst
.instruction
|= WRITE_BACK
;
6367 inst
.instruction
|= INDEX_UP
;
6374 if (skip_past_comma (&str
) == FAIL
)
6376 inst
.error
= _("pre-indexed expression expected");
6381 if (ldst_extend (&str
) == FAIL
)
6384 skip_whitespace (str
);
6388 inst
.error
= _("missing ]");
6392 skip_whitespace (str
);
6397 as_warn (_("%s register same as write-back base"),
6398 ((inst
.instruction
& LOAD_BIT
)
6399 ? _("destination") : _("source")));
6401 inst
.instruction
|= WRITE_BACK
;
6405 else if (*str
== '=')
6407 if ((inst
.instruction
& LOAD_BIT
) == 0)
6409 inst
.error
= _("invalid pseudo operation");
6413 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6416 skip_whitespace (str
);
6418 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6421 if (inst
.reloc
.exp
.X_op
!= O_constant
6422 && inst
.reloc
.exp
.X_op
!= O_symbol
)
6424 inst
.error
= _("constant expression expected");
6428 if (inst
.reloc
.exp
.X_op
== O_constant
)
6430 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
6434 /* This can be done with a mov instruction. */
6435 inst
.instruction
&= LITERAL_MASK
;
6436 inst
.instruction
|= (INST_IMMEDIATE
6437 | (OPCODE_MOV
<< DATA_OP_SHIFT
));
6438 inst
.instruction
|= value
& 0xfff;
6443 value
= validate_immediate (~inst
.reloc
.exp
.X_add_number
);
6447 /* This can be done with a mvn instruction. */
6448 inst
.instruction
&= LITERAL_MASK
;
6449 inst
.instruction
|= (INST_IMMEDIATE
6450 | (OPCODE_MVN
<< DATA_OP_SHIFT
));
6451 inst
.instruction
|= value
& 0xfff;
6457 /* Insert into literal pool. */
6458 if (add_to_lit_pool () == FAIL
)
6461 inst
.error
= _("literal pool insertion failed");
6465 /* Change the instruction exp to point to the pool. */
6466 inst
.reloc
.type
= BFD_RELOC_ARM_LITERAL
;
6467 inst
.reloc
.pc_rel
= 1;
6468 inst
.instruction
|= (REG_PC
<< 16);
6473 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6476 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
6478 /* PC rel adjust. */
6479 inst
.reloc
.exp
.X_add_number
-= 8;
6481 inst
.reloc
.pc_rel
= 1;
6482 inst
.instruction
|= (REG_PC
<< 16);
6486 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
6491 do_ldstt (char * str
)
6495 skip_whitespace (str
);
6497 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
6500 inst
.error
= BAD_ARGS
;
6504 if (skip_past_comma (& str
) == FAIL
)
6506 inst
.error
= _("address expected");
6516 skip_whitespace (str
);
6518 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6521 /* ldrt/strt always use post-indexed addressing, so if the base is
6522 the same as Rd, we warn. */
6523 if (conflict_reg
== reg
)
6524 as_warn (_("%s register same as write-back base"),
6525 ((inst
.instruction
& LOAD_BIT
)
6526 ? _("destination") : _("source")));
6528 skip_whitespace (str
);
6534 if (skip_past_comma (&str
) == SUCCESS
)
6536 /* [Rn],... (post inc) */
6537 if (ldst_extend (&str
) == FAIL
)
6543 skip_whitespace (str
);
6545 /* Skip a write-back '!'. */
6549 inst
.instruction
|= INDEX_UP
;
6554 inst
.error
= _("post-indexed expression expected");
6560 inst
.error
= _("post-indexed expression expected");
6567 /* Halfword and signed-byte load/store operations. */
6570 do_ldstv4 (char * str
)
6576 skip_whitespace (str
);
6578 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
6581 inst
.error
= BAD_ARGS
;
6585 if (skip_past_comma (& str
) == FAIL
)
6587 inst
.error
= _("address expected");
6597 skip_whitespace (str
);
6599 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6602 /* Conflicts can occur on stores as well as loads. */
6603 conflict_reg
= (conflict_reg
== reg
);
6605 skip_whitespace (str
);
6611 if (skip_past_comma (&str
) == SUCCESS
)
6613 /* [Rn],... (post inc) */
6614 if (ldst_extend_v4 (&str
) == FAIL
)
6617 as_warn (_("%s register same as write-back base"),
6618 ((inst
.instruction
& LOAD_BIT
)
6619 ? _("destination") : _("source")));
6624 inst
.instruction
|= HWOFFSET_IMM
;
6626 skip_whitespace (str
);
6631 as_warn (_("%s register same as write-back base"),
6632 ((inst
.instruction
& LOAD_BIT
)
6633 ? _("destination") : _("source")));
6635 inst
.instruction
|= WRITE_BACK
;
6638 inst
.instruction
|= INDEX_UP
;
6645 if (skip_past_comma (&str
) == FAIL
)
6647 inst
.error
= _("pre-indexed expression expected");
6652 if (ldst_extend_v4 (&str
) == FAIL
)
6655 skip_whitespace (str
);
6659 inst
.error
= _("missing ]");
6663 skip_whitespace (str
);
6668 as_warn (_("%s register same as write-back base"),
6669 ((inst
.instruction
& LOAD_BIT
)
6670 ? _("destination") : _("source")));
6672 inst
.instruction
|= WRITE_BACK
;
6676 else if (*str
== '=')
6678 if ((inst
.instruction
& LOAD_BIT
) == 0)
6680 inst
.error
= _("invalid pseudo operation");
6684 /* XXX Does this work correctly for half-word/byte ops? */
6685 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6688 skip_whitespace (str
);
6690 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6693 if (inst
.reloc
.exp
.X_op
!= O_constant
6694 && inst
.reloc
.exp
.X_op
!= O_symbol
)
6696 inst
.error
= _("constant expression expected");
6700 if (inst
.reloc
.exp
.X_op
== O_constant
)
6702 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
6706 /* This can be done with a mov instruction. */
6707 inst
.instruction
&= LITERAL_MASK
;
6708 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MOV
<< DATA_OP_SHIFT
);
6709 inst
.instruction
|= value
& 0xfff;
6714 value
= validate_immediate (~ inst
.reloc
.exp
.X_add_number
);
6718 /* This can be done with a mvn instruction. */
6719 inst
.instruction
&= LITERAL_MASK
;
6720 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MVN
<< DATA_OP_SHIFT
);
6721 inst
.instruction
|= value
& 0xfff;
6727 /* Insert into literal pool. */
6728 if (add_to_lit_pool () == FAIL
)
6731 inst
.error
= _("literal pool insertion failed");
6735 /* Change the instruction exp to point to the pool. */
6736 inst
.instruction
|= HWOFFSET_IMM
;
6737 inst
.reloc
.type
= BFD_RELOC_ARM_HWLITERAL
;
6738 inst
.reloc
.pc_rel
= 1;
6739 inst
.instruction
|= (REG_PC
<< 16);
6744 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6747 inst
.instruction
|= HWOFFSET_IMM
;
6748 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
6750 /* PC rel adjust. */
6751 inst
.reloc
.exp
.X_add_number
-= 8;
6753 inst
.reloc
.pc_rel
= 1;
6754 inst
.instruction
|= (REG_PC
<< 16);
6758 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
6763 do_ldsttv4 (char * str
)
6767 skip_whitespace (str
);
6769 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
6772 inst
.error
= BAD_ARGS
;
6776 if (skip_past_comma (& str
) == FAIL
)
6778 inst
.error
= _("address expected");
6788 skip_whitespace (str
);
6790 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6793 /* ldrt/strt always use post-indexed addressing, so if the base is
6794 the same as Rd, we warn. */
6795 if (conflict_reg
== reg
)
6796 as_warn (_("%s register same as write-back base"),
6797 ((inst
.instruction
& LOAD_BIT
)
6798 ? _("destination") : _("source")));
6800 skip_whitespace (str
);
6806 if (skip_past_comma (&str
) == SUCCESS
)
6808 /* [Rn],... (post inc) */
6809 if (ldst_extend_v4 (&str
) == FAIL
)
6815 skip_whitespace (str
);
6817 /* Skip a write-back '!'. */
6821 inst
.instruction
|= (INDEX_UP
|HWOFFSET_IMM
);
6826 inst
.error
= _("post-indexed expression expected");
6832 inst
.error
= _("post-indexed expression expected");
6841 reg_list (char ** strp
)
6843 char * str
= * strp
;
6847 /* We come back here if we get ranges concatenated by '+' or '|'. */
6862 skip_whitespace (str
);
6864 if ((reg
= reg_required_here (& str
, -1)) == FAIL
)
6873 inst
.error
= _("bad range in register list");
6877 for (i
= cur_reg
+ 1; i
< reg
; i
++)
6879 if (range
& (1 << i
))
6881 (_("Warning: duplicated register (r%d) in register list"),
6889 if (range
& (1 << reg
))
6890 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
6892 else if (reg
<= cur_reg
)
6893 as_tsktsk (_("Warning: register range not in ascending order"));
6898 while (skip_past_comma (&str
) != FAIL
6899 || (in_range
= 1, *str
++ == '-'));
6901 skip_whitespace (str
);
6905 inst
.error
= _("missing `}'");
6913 if (my_get_expression (&expr
, &str
))
6916 if (expr
.X_op
== O_constant
)
6918 if (expr
.X_add_number
6919 != (expr
.X_add_number
& 0x0000ffff))
6921 inst
.error
= _("invalid register mask");
6925 if ((range
& expr
.X_add_number
) != 0)
6927 int regno
= range
& expr
.X_add_number
;
6930 regno
= (1 << regno
) - 1;
6932 (_("Warning: duplicated register (r%d) in register list"),
6936 range
|= expr
.X_add_number
;
6940 if (inst
.reloc
.type
!= 0)
6942 inst
.error
= _("expression too complex");
6946 memcpy (&inst
.reloc
.exp
, &expr
, sizeof (expressionS
));
6947 inst
.reloc
.type
= BFD_RELOC_ARM_MULTI
;
6948 inst
.reloc
.pc_rel
= 0;
6952 skip_whitespace (str
);
6954 if (*str
== '|' || *str
== '+')
6960 while (another_range
);
6967 do_ldmstm (char * str
)
6972 skip_whitespace (str
);
6974 if ((base_reg
= reg_required_here (&str
, 16)) == FAIL
)
6977 if (base_reg
== REG_PC
)
6979 inst
.error
= _("r15 not allowed as base register");
6983 skip_whitespace (str
);
6987 inst
.instruction
|= WRITE_BACK
;
6991 if (skip_past_comma (&str
) == FAIL
6992 || (range
= reg_list (&str
)) == FAIL
)
6995 inst
.error
= BAD_ARGS
;
7002 inst
.instruction
|= LDM_TYPE_2_OR_3
;
7005 if (inst
.instruction
& WRITE_BACK
)
7007 /* Check for unpredictable uses of writeback. */
7008 if (inst
.instruction
& LOAD_BIT
)
7010 /* Not allowed in LDM type 2. */
7011 if ((inst
.instruction
& LDM_TYPE_2_OR_3
)
7012 && ((range
& (1 << REG_PC
)) == 0))
7013 as_warn (_("writeback of base register is UNPREDICTABLE"));
7014 /* Only allowed if base reg not in list for other types. */
7015 else if (range
& (1 << base_reg
))
7016 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
7020 /* Not allowed for type 2. */
7021 if (inst
.instruction
& LDM_TYPE_2_OR_3
)
7022 as_warn (_("writeback of base register is UNPREDICTABLE"));
7023 /* Only allowed if base reg not in list, or first in list. */
7024 else if ((range
& (1 << base_reg
))
7025 && (range
& ((1 << base_reg
) - 1)))
7026 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
7030 inst
.instruction
|= range
;
7037 skip_whitespace (str
);
7039 /* Allow optional leading '#'. */
7040 if (is_immediate_prefix (*str
))
7043 if (my_get_expression (& inst
.reloc
.exp
, & str
))
7046 inst
.reloc
.type
= BFD_RELOC_ARM_SMI
;
7047 inst
.reloc
.pc_rel
= 0;
7054 skip_whitespace (str
);
7056 /* Allow optional leading '#'. */
7057 if (is_immediate_prefix (*str
))
7060 if (my_get_expression (& inst
.reloc
.exp
, & str
))
7063 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
7064 inst
.reloc
.pc_rel
= 0;
7069 do_swap (char * str
)
7073 skip_whitespace (str
);
7075 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
7080 inst
.error
= _("r15 not allowed in swap");
7084 if (skip_past_comma (&str
) == FAIL
7085 || (reg
= reg_required_here (&str
, 0)) == FAIL
)
7088 inst
.error
= BAD_ARGS
;
7094 inst
.error
= _("r15 not allowed in swap");
7098 if (skip_past_comma (&str
) == FAIL
7101 inst
.error
= BAD_ARGS
;
7105 skip_whitespace (str
);
7107 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
7112 inst
.error
= BAD_PC
;
7116 skip_whitespace (str
);
7120 inst
.error
= _("missing ]");
7128 do_branch (char * str
)
7130 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7137 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
7138 required for the instruction. */
7140 /* arm_parse_reloc () works on input_line_pointer.
7141 We actually want to parse the operands to the branch instruction
7142 passed in 'str'. Save the input pointer and restore it later. */
7143 save_in
= input_line_pointer
;
7144 input_line_pointer
= str
;
7145 if (inst
.reloc
.exp
.X_op
== O_symbol
7147 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
7149 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
7150 inst
.reloc
.pc_rel
= 0;
7151 /* Modify str to point to after parsed operands, otherwise
7152 end_of_line() will complain about the (PLT) left in str. */
7153 str
= input_line_pointer
;
7157 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
7158 inst
.reloc
.pc_rel
= 1;
7160 input_line_pointer
= save_in
;
7163 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
7164 inst
.reloc
.pc_rel
= 1;
7165 #endif /* OBJ_ELF */
7173 /* Co-processor data operation.
7174 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
7175 skip_whitespace (str
);
7177 if (co_proc_number (&str
) == FAIL
)
7180 inst
.error
= BAD_ARGS
;
7184 if (skip_past_comma (&str
) == FAIL
7185 || cp_opc_expr (&str
, 20,4) == FAIL
)
7188 inst
.error
= BAD_ARGS
;
7192 if (skip_past_comma (&str
) == FAIL
7193 || cp_reg_required_here (&str
, 12) == FAIL
)
7196 inst
.error
= BAD_ARGS
;
7200 if (skip_past_comma (&str
) == FAIL
7201 || cp_reg_required_here (&str
, 16) == FAIL
)
7204 inst
.error
= BAD_ARGS
;
7208 if (skip_past_comma (&str
) == FAIL
7209 || cp_reg_required_here (&str
, 0) == FAIL
)
7212 inst
.error
= BAD_ARGS
;
7216 if (skip_past_comma (&str
) == SUCCESS
)
7218 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
7221 inst
.error
= BAD_ARGS
;
7230 do_lstc (char * str
)
7232 /* Co-processor register load/store.
7233 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
7235 skip_whitespace (str
);
7237 if (co_proc_number (&str
) == FAIL
)
7240 inst
.error
= BAD_ARGS
;
7244 if (skip_past_comma (&str
) == FAIL
7245 || cp_reg_required_here (&str
, 12) == FAIL
)
7248 inst
.error
= BAD_ARGS
;
7252 if (skip_past_comma (&str
) == FAIL
7253 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
7256 inst
.error
= BAD_ARGS
;
7264 do_co_reg (char * str
)
7266 /* Co-processor register transfer.
7267 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
7269 skip_whitespace (str
);
7271 if (co_proc_number (&str
) == FAIL
)
7274 inst
.error
= BAD_ARGS
;
7278 if (skip_past_comma (&str
) == FAIL
7279 || cp_opc_expr (&str
, 21, 3) == FAIL
)
7282 inst
.error
= BAD_ARGS
;
7286 if (skip_past_comma (&str
) == FAIL
7287 || reg_required_here (&str
, 12) == FAIL
)
7290 inst
.error
= BAD_ARGS
;
7294 if (skip_past_comma (&str
) == FAIL
7295 || cp_reg_required_here (&str
, 16) == FAIL
)
7298 inst
.error
= BAD_ARGS
;
7302 if (skip_past_comma (&str
) == FAIL
7303 || cp_reg_required_here (&str
, 0) == FAIL
)
7306 inst
.error
= BAD_ARGS
;
7310 if (skip_past_comma (&str
) == SUCCESS
)
7312 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
7315 inst
.error
= BAD_ARGS
;
7324 do_fpa_ctrl (char * str
)
7326 /* FP control registers.
7327 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
7329 skip_whitespace (str
);
7331 if (reg_required_here (&str
, 12) == FAIL
)
7334 inst
.error
= BAD_ARGS
;
7342 do_fpa_ldst (char * str
)
7344 skip_whitespace (str
);
7346 if (fp_reg_required_here (&str
, 12) == FAIL
)
7349 inst
.error
= BAD_ARGS
;
7353 if (skip_past_comma (&str
) == FAIL
7354 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
7357 inst
.error
= BAD_ARGS
;
7365 do_fpa_ldmstm (char * str
)
7369 skip_whitespace (str
);
7371 if (fp_reg_required_here (&str
, 12) == FAIL
)
7374 inst
.error
= BAD_ARGS
;
7378 /* Get Number of registers to transfer. */
7379 if (skip_past_comma (&str
) == FAIL
7380 || my_get_expression (&inst
.reloc
.exp
, &str
))
7383 inst
.error
= _("constant expression expected");
7387 if (inst
.reloc
.exp
.X_op
!= O_constant
)
7389 inst
.error
= _("constant value required for number of registers");
7393 num_regs
= inst
.reloc
.exp
.X_add_number
;
7395 if (num_regs
< 1 || num_regs
> 4)
7397 inst
.error
= _("number of registers must be in the range [1:4]");
7404 inst
.instruction
|= CP_T_X
;
7407 inst
.instruction
|= CP_T_Y
;
7410 inst
.instruction
|= CP_T_Y
| CP_T_X
;
7418 if (inst
.instruction
& (CP_T_Pre
| CP_T_UD
)) /* ea/fd format. */
7424 /* The instruction specified "ea" or "fd", so we can only accept
7425 [Rn]{!}. The instruction does not really support stacking or
7426 unstacking, so we have to emulate these by setting appropriate
7427 bits and offsets. */
7428 if (skip_past_comma (&str
) == FAIL
7432 inst
.error
= BAD_ARGS
;
7437 skip_whitespace (str
);
7439 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
7442 skip_whitespace (str
);
7446 inst
.error
= BAD_ARGS
;
7458 _("r15 not allowed as base register with write-back");
7465 if (inst
.instruction
& CP_T_Pre
)
7467 /* Pre-decrement. */
7468 offset
= 3 * num_regs
;
7470 inst
.instruction
|= CP_T_WB
;
7474 /* Post-increment. */
7477 inst
.instruction
|= CP_T_WB
;
7478 offset
= 3 * num_regs
;
7482 /* No write-back, so convert this into a standard pre-increment
7483 instruction -- aesthetically more pleasing. */
7484 inst
.instruction
|= CP_T_Pre
| CP_T_UD
;
7489 inst
.instruction
|= offset
;
7491 else if (skip_past_comma (&str
) == FAIL
7492 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
7495 inst
.error
= BAD_ARGS
;
7503 do_fpa_dyadic (char * str
)
7505 skip_whitespace (str
);
7507 if (fp_reg_required_here (&str
, 12) == FAIL
)
7510 inst
.error
= BAD_ARGS
;
7514 if (skip_past_comma (&str
) == FAIL
7515 || fp_reg_required_here (&str
, 16) == FAIL
)
7518 inst
.error
= BAD_ARGS
;
7522 if (skip_past_comma (&str
) == FAIL
7523 || fp_op2 (&str
) == FAIL
)
7526 inst
.error
= BAD_ARGS
;
7534 do_fpa_monadic (char * str
)
7536 skip_whitespace (str
);
7538 if (fp_reg_required_here (&str
, 12) == FAIL
)
7541 inst
.error
= BAD_ARGS
;
7545 if (skip_past_comma (&str
) == FAIL
7546 || fp_op2 (&str
) == FAIL
)
7549 inst
.error
= BAD_ARGS
;
7557 do_fpa_cmp (char * str
)
7559 skip_whitespace (str
);
7561 if (fp_reg_required_here (&str
, 16) == FAIL
)
7564 inst
.error
= BAD_ARGS
;
7568 if (skip_past_comma (&str
) == FAIL
7569 || fp_op2 (&str
) == FAIL
)
7572 inst
.error
= BAD_ARGS
;
7580 do_fpa_from_reg (char * str
)
7582 skip_whitespace (str
);
7584 if (fp_reg_required_here (&str
, 16) == FAIL
)
7587 inst
.error
= BAD_ARGS
;
7591 if (skip_past_comma (&str
) == FAIL
7592 || reg_required_here (&str
, 12) == FAIL
)
7595 inst
.error
= BAD_ARGS
;
7603 do_fpa_to_reg (char * str
)
7605 skip_whitespace (str
);
7607 if (reg_required_here (&str
, 12) == FAIL
)
7610 if (skip_past_comma (&str
) == FAIL
7611 || fp_reg_required_here (&str
, 0) == FAIL
)
7614 inst
.error
= BAD_ARGS
;
7621 /* Encode a VFP SP register number. */
7624 vfp_sp_encode_reg (int reg
, enum vfp_sp_reg_pos pos
)
7629 inst
.instruction
|= ((reg
>> 1) << 12) | ((reg
& 1) << 22);
7633 inst
.instruction
|= ((reg
>> 1) << 16) | ((reg
& 1) << 7);
7637 inst
.instruction
|= ((reg
>> 1) << 0) | ((reg
& 1) << 5);
7646 vfp_sp_reg_required_here (char ** str
,
7647 enum vfp_sp_reg_pos pos
)
7650 char * start
= *str
;
7652 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_SN
].htab
)) != FAIL
)
7654 vfp_sp_encode_reg (reg
, pos
);
7658 /* In the few cases where we might be able to accept something else
7659 this error can be overridden. */
7660 inst
.error
= _(all_reg_maps
[REG_TYPE_SN
].expected
);
7662 /* Restore the start point. */
7668 vfp_dp_reg_required_here (char ** str
,
7669 enum vfp_dp_reg_pos pos
)
7672 char * start
= *str
;
7674 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_DN
].htab
)) != FAIL
)
7679 inst
.instruction
|= reg
<< 12;
7683 inst
.instruction
|= reg
<< 16;
7687 inst
.instruction
|= reg
<< 0;
7696 /* In the few cases where we might be able to accept something else
7697 this error can be overridden. */
7698 inst
.error
= _(all_reg_maps
[REG_TYPE_DN
].expected
);
7700 /* Restore the start point. */
7706 do_vfp_sp_monadic (char * str
)
7708 skip_whitespace (str
);
7710 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7713 if (skip_past_comma (&str
) == FAIL
7714 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
7717 inst
.error
= BAD_ARGS
;
7725 do_vfp_dp_monadic (char * str
)
7727 skip_whitespace (str
);
7729 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7732 if (skip_past_comma (&str
) == FAIL
7733 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7736 inst
.error
= BAD_ARGS
;
7744 do_vfp_sp_dyadic (char * str
)
7746 skip_whitespace (str
);
7748 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7751 if (skip_past_comma (&str
) == FAIL
7752 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
7753 || skip_past_comma (&str
) == FAIL
7754 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
7757 inst
.error
= BAD_ARGS
;
7765 do_vfp_dp_dyadic (char * str
)
7767 skip_whitespace (str
);
7769 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7772 if (skip_past_comma (&str
) == FAIL
7773 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
7774 || skip_past_comma (&str
) == FAIL
7775 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7778 inst
.error
= BAD_ARGS
;
7786 do_vfp_reg_from_sp (char * str
)
7788 skip_whitespace (str
);
7790 if (reg_required_here (&str
, 12) == FAIL
)
7793 if (skip_past_comma (&str
) == FAIL
7794 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
7797 inst
.error
= BAD_ARGS
;
7804 /* Parse a VFP register list. If the string is invalid return FAIL.
7805 Otherwise return the number of registers, and set PBASE to the first
7806 register. Double precision registers are matched if DP is nonzero. */
7809 vfp_parse_reg_list (char **str
, int *pbase
, int dp
)
7817 unsigned long mask
= 0;
7824 skip_whitespace (*str
);
7828 regtype
= REG_TYPE_DN
;
7833 regtype
= REG_TYPE_SN
;
7837 base_reg
= max_regs
;
7841 new_base
= arm_reg_parse (str
, all_reg_maps
[regtype
].htab
);
7842 if (new_base
== FAIL
)
7844 inst
.error
= _(all_reg_maps
[regtype
].expected
);
7848 if (new_base
< base_reg
)
7849 base_reg
= new_base
;
7851 if (mask
& (1 << new_base
))
7853 inst
.error
= _("invalid register list");
7857 if ((mask
>> new_base
) != 0 && ! warned
)
7859 as_tsktsk (_("register list not in ascending order"));
7863 mask
|= 1 << new_base
;
7866 skip_whitespace (*str
);
7868 if (**str
== '-') /* We have the start of a range expression */
7875 = arm_reg_parse (str
, all_reg_maps
[regtype
].htab
))
7878 inst
.error
= _(all_reg_maps
[regtype
].expected
);
7882 if (high_range
<= new_base
)
7884 inst
.error
= _("register range not in ascending order");
7888 for (new_base
++; new_base
<= high_range
; new_base
++)
7890 if (mask
& (1 << new_base
))
7892 inst
.error
= _("invalid register list");
7896 mask
|= 1 << new_base
;
7901 while (skip_past_comma (str
) != FAIL
);
7905 /* Sanity check -- should have raised a parse error above. */
7906 if (count
== 0 || count
> max_regs
)
7911 /* Final test -- the registers must be consecutive. */
7913 for (i
= 0; i
< count
; i
++)
7915 if ((mask
& (1u << i
)) == 0)
7917 inst
.error
= _("non-contiguous register range");
7926 do_vfp_reg2_from_sp2 (char * str
)
7930 skip_whitespace (str
);
7932 if (reg_required_here (&str
, 12) == FAIL
7933 || skip_past_comma (&str
) == FAIL
7934 || reg_required_here (&str
, 16) == FAIL
7935 || skip_past_comma (&str
) == FAIL
)
7938 inst
.error
= BAD_ARGS
;
7942 /* We require exactly two consecutive SP registers. */
7943 if (vfp_parse_reg_list (&str
, ®
, 0) != 2)
7946 inst
.error
= _("only two consecutive VFP SP registers allowed here");
7948 vfp_sp_encode_reg (reg
, VFP_REG_Sm
);
7954 do_vfp_sp_from_reg (char * str
)
7956 skip_whitespace (str
);
7958 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
7961 if (skip_past_comma (&str
) == FAIL
7962 || reg_required_here (&str
, 12) == FAIL
)
7965 inst
.error
= BAD_ARGS
;
7973 do_vfp_sp2_from_reg2 (char * str
)
7977 skip_whitespace (str
);
7979 /* We require exactly two consecutive SP registers. */
7980 if (vfp_parse_reg_list (&str
, ®
, 0) != 2)
7983 inst
.error
= _("only two consecutive VFP SP registers allowed here");
7985 vfp_sp_encode_reg (reg
, VFP_REG_Sm
);
7987 if (skip_past_comma (&str
) == FAIL
7988 || reg_required_here (&str
, 12) == FAIL
7989 || skip_past_comma (&str
) == FAIL
7990 || reg_required_here (&str
, 16) == FAIL
)
7993 inst
.error
= BAD_ARGS
;
8001 do_vfp_reg_from_dp (char * str
)
8003 skip_whitespace (str
);
8005 if (reg_required_here (&str
, 12) == FAIL
)
8008 if (skip_past_comma (&str
) == FAIL
8009 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
8012 inst
.error
= BAD_ARGS
;
8020 do_vfp_reg2_from_dp (char * str
)
8022 skip_whitespace (str
);
8024 if (reg_required_here (&str
, 12) == FAIL
)
8027 if (skip_past_comma (&str
) == FAIL
8028 || reg_required_here (&str
, 16) == FAIL
8029 || skip_past_comma (&str
) == FAIL
8030 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
8033 inst
.error
= BAD_ARGS
;
8041 do_vfp_dp_from_reg (char * str
)
8043 skip_whitespace (str
);
8045 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
8048 if (skip_past_comma (&str
) == FAIL
8049 || reg_required_here (&str
, 12) == FAIL
)
8052 inst
.error
= BAD_ARGS
;
8060 do_vfp_dp_from_reg2 (char * str
)
8062 skip_whitespace (str
);
8064 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
8067 if (skip_past_comma (&str
) == FAIL
8068 || reg_required_here (&str
, 12) == FAIL
8069 || skip_past_comma (&str
) == FAIL
8070 || reg_required_here (&str
, 16) == FAIL
)
8073 inst
.error
= BAD_ARGS
;
8080 static const struct vfp_reg
*
8081 vfp_psr_parse (char ** str
)
8086 const struct vfp_reg
*vreg
;
8090 /* Find the end of the current token. */
8095 while (ISALPHA (c
));
8100 for (vreg
= vfp_regs
+ 0;
8101 vreg
< vfp_regs
+ sizeof (vfp_regs
) / sizeof (struct vfp_reg
);
8104 if (streq (start
, vreg
->name
))
8117 vfp_psr_required_here (char ** str
)
8120 const struct vfp_reg
*vreg
;
8122 vreg
= vfp_psr_parse (str
);
8126 inst
.instruction
|= vreg
->regno
;
8130 inst
.error
= _("VFP system register expected");
8137 do_vfp_reg_from_ctrl (char * str
)
8139 skip_whitespace (str
);
8141 if (reg_required_here (&str
, 12) == FAIL
)
8144 if (skip_past_comma (&str
) == FAIL
8145 || vfp_psr_required_here (&str
) == FAIL
)
8148 inst
.error
= BAD_ARGS
;
8156 do_vfp_ctrl_from_reg (char * str
)
8158 skip_whitespace (str
);
8160 if (vfp_psr_required_here (&str
) == FAIL
)
8163 if (skip_past_comma (&str
) == FAIL
8164 || reg_required_here (&str
, 12) == FAIL
)
8167 inst
.error
= BAD_ARGS
;
8175 do_vfp_sp_ldst (char * str
)
8177 skip_whitespace (str
);
8179 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8182 inst
.error
= BAD_ARGS
;
8186 if (skip_past_comma (&str
) == FAIL
8187 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
8190 inst
.error
= BAD_ARGS
;
8198 do_vfp_dp_ldst (char * str
)
8200 skip_whitespace (str
);
8202 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8205 inst
.error
= BAD_ARGS
;
8209 if (skip_past_comma (&str
) == FAIL
8210 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
8213 inst
.error
= BAD_ARGS
;
8222 vfp_sp_ldstm (char * str
, enum vfp_ldstm_type ldstm_type
)
8227 skip_whitespace (str
);
8229 if (reg_required_here (&str
, 16) == FAIL
)
8232 skip_whitespace (str
);
8236 inst
.instruction
|= WRITE_BACK
;
8239 else if (ldstm_type
!= VFP_LDSTMIA
)
8241 inst
.error
= _("this addressing mode requires base-register writeback");
8245 if (skip_past_comma (&str
) == FAIL
8246 || (count
= vfp_parse_reg_list (&str
, ®
, 0)) == FAIL
)
8249 inst
.error
= BAD_ARGS
;
8252 vfp_sp_encode_reg (reg
, VFP_REG_Sd
);
8254 inst
.instruction
|= count
;
8259 vfp_dp_ldstm (char * str
, enum vfp_ldstm_type ldstm_type
)
8264 skip_whitespace (str
);
8266 if (reg_required_here (&str
, 16) == FAIL
)
8269 skip_whitespace (str
);
8273 inst
.instruction
|= WRITE_BACK
;
8276 else if (ldstm_type
!= VFP_LDSTMIA
&& ldstm_type
!= VFP_LDSTMIAX
)
8278 inst
.error
= _("this addressing mode requires base-register writeback");
8282 if (skip_past_comma (&str
) == FAIL
8283 || (count
= vfp_parse_reg_list (&str
, ®
, 1)) == FAIL
)
8286 inst
.error
= BAD_ARGS
;
8291 if (ldstm_type
== VFP_LDSTMIAX
|| ldstm_type
== VFP_LDSTMDBX
)
8294 inst
.instruction
|= (reg
<< 12) | count
;
8299 do_vfp_sp_ldstmia (char * str
)
8301 vfp_sp_ldstm (str
, VFP_LDSTMIA
);
8305 do_vfp_sp_ldstmdb (char * str
)
8307 vfp_sp_ldstm (str
, VFP_LDSTMDB
);
8311 do_vfp_dp_ldstmia (char * str
)
8313 vfp_dp_ldstm (str
, VFP_LDSTMIA
);
8317 do_vfp_dp_ldstmdb (char * str
)
8319 vfp_dp_ldstm (str
, VFP_LDSTMDB
);
8323 do_vfp_xp_ldstmia (char *str
)
8325 vfp_dp_ldstm (str
, VFP_LDSTMIAX
);
8329 do_vfp_xp_ldstmdb (char * str
)
8331 vfp_dp_ldstm (str
, VFP_LDSTMDBX
);
8335 do_vfp_sp_compare_z (char * str
)
8337 skip_whitespace (str
);
8339 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8342 inst
.error
= BAD_ARGS
;
8350 do_vfp_dp_compare_z (char * str
)
8352 skip_whitespace (str
);
8354 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8357 inst
.error
= BAD_ARGS
;
8365 do_vfp_dp_sp_cvt (char * str
)
8367 skip_whitespace (str
);
8369 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8372 if (skip_past_comma (&str
) == FAIL
8373 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
8376 inst
.error
= BAD_ARGS
;
8384 do_vfp_sp_dp_cvt (char * str
)
8386 skip_whitespace (str
);
8388 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8391 if (skip_past_comma (&str
) == FAIL
8392 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
8395 inst
.error
= BAD_ARGS
;
8402 /* Thumb specific routines. */
8404 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
8408 thumb_add_sub (char * str
, int subtract
)
8410 int Rd
, Rs
, Rn
= FAIL
;
8412 skip_whitespace (str
);
8414 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
8415 || skip_past_comma (&str
) == FAIL
)
8418 inst
.error
= BAD_ARGS
;
8422 if (is_immediate_prefix (*str
))
8426 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8431 if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8434 if (skip_past_comma (&str
) == FAIL
)
8436 /* Two operand format, shuffle the registers
8437 and pretend there are 3. */
8441 else if (is_immediate_prefix (*str
))
8444 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8447 else if ((Rn
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8451 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8452 for the latter case, EXPR contains the immediate that was found. */
8455 /* All register format. */
8456 if (Rd
> 7 || Rs
> 7 || Rn
> 7)
8460 inst
.error
= _("dest and source1 must be the same register");
8464 /* Can't do this for SUB. */
8467 inst
.error
= _("subtract valid only on lo regs");
8471 inst
.instruction
= (T_OPCODE_ADD_HI
8472 | (Rd
> 7 ? THUMB_H1
: 0)
8473 | (Rn
> 7 ? THUMB_H2
: 0));
8474 inst
.instruction
|= (Rd
& 7) | ((Rn
& 7) << 3);
8478 inst
.instruction
= subtract
? T_OPCODE_SUB_R3
: T_OPCODE_ADD_R3
;
8479 inst
.instruction
|= Rd
| (Rs
<< 3) | (Rn
<< 6);
8484 /* Immediate expression, now things start to get nasty. */
8486 /* First deal with HI regs, only very restricted cases allowed:
8487 Adjusting SP, and using PC or SP to get an address. */
8488 if ((Rd
> 7 && (Rd
!= REG_SP
|| Rs
!= REG_SP
))
8489 || (Rs
> 7 && Rs
!= REG_SP
&& Rs
!= REG_PC
))
8491 inst
.error
= _("invalid Hi register with immediate");
8495 if (inst
.reloc
.exp
.X_op
!= O_constant
)
8497 /* Value isn't known yet, all we can do is store all the fragments
8498 we know about in the instruction and let the reloc hacking
8500 inst
.instruction
= (subtract
? 0x8000 : 0) | (Rd
<< 4) | Rs
;
8501 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
8505 int offset
= inst
.reloc
.exp
.X_add_number
;
8515 /* Quick check, in case offset is MIN_INT. */
8518 inst
.error
= _("immediate value out of range");
8522 /* Note - you cannot convert a subtract of 0 into an
8523 add of 0 because the carry flag is set differently. */
8524 else if (offset
> 0)
8529 if (offset
& ~0x1fc)
8531 inst
.error
= _("invalid immediate value for stack adjust");
8534 inst
.instruction
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
8535 inst
.instruction
|= offset
>> 2;
8537 else if (Rs
== REG_PC
|| Rs
== REG_SP
)
8540 || (offset
& ~0x3fc))
8542 inst
.error
= _("invalid immediate for address calculation");
8545 inst
.instruction
= (Rs
== REG_PC
? T_OPCODE_ADD_PC
8547 inst
.instruction
|= (Rd
<< 8) | (offset
>> 2);
8553 inst
.error
= _("immediate value out of range");
8556 inst
.instruction
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
8557 inst
.instruction
|= (Rd
<< 8) | offset
;
8563 inst
.error
= _("immediate value out of range");
8566 inst
.instruction
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
8567 inst
.instruction
|= Rd
| (Rs
<< 3) | (offset
<< 6);
8576 thumb_shift (char * str
, int shift
)
8578 int Rd
, Rs
, Rn
= FAIL
;
8580 skip_whitespace (str
);
8582 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
8583 || skip_past_comma (&str
) == FAIL
)
8586 inst
.error
= BAD_ARGS
;
8590 if (is_immediate_prefix (*str
))
8592 /* Two operand immediate format, set Rs to Rd. */
8595 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8600 if ((Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8603 if (skip_past_comma (&str
) == FAIL
)
8605 /* Two operand format, shuffle the registers
8606 and pretend there are 3. */
8610 else if (is_immediate_prefix (*str
))
8613 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8616 else if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8620 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8621 for the latter case, EXPR contains the immediate that was found. */
8627 inst
.error
= _("source1 and dest must be same register");
8633 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_R
; break;
8634 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_R
; break;
8635 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_R
; break;
8638 inst
.instruction
|= Rd
| (Rn
<< 3);
8644 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_I
; break;
8645 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_I
; break;
8646 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_I
; break;
8649 if (inst
.reloc
.exp
.X_op
!= O_constant
)
8651 /* Value isn't known yet, create a dummy reloc and let reloc
8652 hacking fix it up. */
8653 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_SHIFT
;
8657 unsigned shift_value
= inst
.reloc
.exp
.X_add_number
;
8659 if (shift_value
> 32 || (shift_value
== 32 && shift
== THUMB_LSL
))
8661 inst
.error
= _("invalid immediate for shift");
8665 /* Shifts of zero are handled by converting to LSL. */
8666 if (shift_value
== 0)
8667 inst
.instruction
= T_OPCODE_LSL_I
;
8669 /* Shifts of 32 are encoded as a shift of zero. */
8670 if (shift_value
== 32)
8673 inst
.instruction
|= shift_value
<< 6;
8676 inst
.instruction
|= Rd
| (Rs
<< 3);
8683 thumb_load_store (char * str
, int load_store
, int size
)
8685 int Rd
, Rb
, Ro
= FAIL
;
8687 skip_whitespace (str
);
8689 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
8690 || skip_past_comma (&str
) == FAIL
)
8693 inst
.error
= BAD_ARGS
;
8700 if ((Rb
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8703 if (skip_past_comma (&str
) != FAIL
)
8705 if (is_immediate_prefix (*str
))
8708 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8711 else if ((Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8716 inst
.reloc
.exp
.X_op
= O_constant
;
8717 inst
.reloc
.exp
.X_add_number
= 0;
8722 inst
.error
= _("expected ']'");
8727 else if (*str
== '=')
8729 if (load_store
!= THUMB_LOAD
)
8731 inst
.error
= _("invalid pseudo operation");
8735 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
8738 skip_whitespace (str
);
8740 if (my_get_expression (& inst
.reloc
.exp
, & str
))
8745 if ( inst
.reloc
.exp
.X_op
!= O_constant
8746 && inst
.reloc
.exp
.X_op
!= O_symbol
)
8748 inst
.error
= "Constant expression expected";
8752 if (inst
.reloc
.exp
.X_op
== O_constant
8753 && ((inst
.reloc
.exp
.X_add_number
& ~0xFF) == 0))
8755 /* This can be done with a mov instruction. */
8757 inst
.instruction
= T_OPCODE_MOV_I8
| (Rd
<< 8);
8758 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
8762 /* Insert into literal pool. */
8763 if (add_to_lit_pool () == FAIL
)
8766 inst
.error
= "literal pool insertion failed";
8770 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8771 inst
.reloc
.pc_rel
= 1;
8772 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
8773 /* Adjust ARM pipeline offset to Thumb. */
8774 inst
.reloc
.exp
.X_add_number
+= 4;
8780 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8783 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
8784 inst
.reloc
.pc_rel
= 1;
8785 inst
.reloc
.exp
.X_add_number
-= 4; /* Pipeline offset. */
8786 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8791 if (Rb
== REG_PC
|| Rb
== REG_SP
)
8793 if (size
!= THUMB_WORD
)
8795 inst
.error
= _("byte or halfword not valid for base register");
8798 else if (Rb
== REG_PC
&& load_store
!= THUMB_LOAD
)
8800 inst
.error
= _("r15 based store not allowed");
8803 else if (Ro
!= FAIL
)
8805 inst
.error
= _("invalid base register for register offset");
8810 inst
.instruction
= T_OPCODE_LDR_PC
;
8811 else if (load_store
== THUMB_LOAD
)
8812 inst
.instruction
= T_OPCODE_LDR_SP
;
8814 inst
.instruction
= T_OPCODE_STR_SP
;
8816 inst
.instruction
|= Rd
<< 8;
8817 if (inst
.reloc
.exp
.X_op
== O_constant
)
8819 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
8821 if (offset
& ~0x3fc)
8823 inst
.error
= _("invalid offset");
8827 inst
.instruction
|= offset
>> 2;
8830 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8834 inst
.error
= _("invalid base register in load/store");
8837 else if (Ro
== FAIL
)
8839 /* Immediate offset. */
8840 if (size
== THUMB_WORD
)
8841 inst
.instruction
= (load_store
== THUMB_LOAD
8842 ? T_OPCODE_LDR_IW
: T_OPCODE_STR_IW
);
8843 else if (size
== THUMB_HALFWORD
)
8844 inst
.instruction
= (load_store
== THUMB_LOAD
8845 ? T_OPCODE_LDR_IH
: T_OPCODE_STR_IH
);
8847 inst
.instruction
= (load_store
== THUMB_LOAD
8848 ? T_OPCODE_LDR_IB
: T_OPCODE_STR_IB
);
8850 inst
.instruction
|= Rd
| (Rb
<< 3);
8852 if (inst
.reloc
.exp
.X_op
== O_constant
)
8854 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
8856 if (offset
& ~(0x1f << size
))
8858 inst
.error
= _("invalid offset");
8861 inst
.instruction
|= (offset
>> size
) << 6;
8864 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8868 /* Register offset. */
8869 if (size
== THUMB_WORD
)
8870 inst
.instruction
= (load_store
== THUMB_LOAD
8871 ? T_OPCODE_LDR_RW
: T_OPCODE_STR_RW
);
8872 else if (size
== THUMB_HALFWORD
)
8873 inst
.instruction
= (load_store
== THUMB_LOAD
8874 ? T_OPCODE_LDR_RH
: T_OPCODE_STR_RH
);
8876 inst
.instruction
= (load_store
== THUMB_LOAD
8877 ? T_OPCODE_LDR_RB
: T_OPCODE_STR_RB
);
8879 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
8885 /* A register must be given at this point.
8887 Shift is the place to put it in inst.instruction.
8889 Restores input start point on err.
8890 Returns the reg#, or FAIL. */
8893 mav_reg_required_here (char ** str
, int shift
, enum arm_reg_type regtype
)
8898 if ((reg
= arm_reg_parse (str
, all_reg_maps
[regtype
].htab
)) != FAIL
)
8901 inst
.instruction
|= reg
<< shift
;
8906 /* Restore the start point. */
8909 /* Try generic coprocessor name if applicable. */
8910 if (regtype
== REG_TYPE_MVF
||
8911 regtype
== REG_TYPE_MVD
||
8912 regtype
== REG_TYPE_MVFX
||
8913 regtype
== REG_TYPE_MVDX
)
8915 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CN
].htab
)) != FAIL
)
8918 inst
.instruction
|= reg
<< shift
;
8923 /* Restore the start point. */
8927 /* In the few cases where we might be able to accept something else
8928 this error can be overridden. */
8929 inst
.error
= _(all_reg_maps
[regtype
].expected
);
8934 /* Cirrus Maverick Instructions. */
8936 /* Isnsn like "foo X,Y". */
8939 do_mav_binops (char * str
,
8941 enum arm_reg_type reg0
,
8942 enum arm_reg_type reg1
)
8946 shift0
= mode
& 0xff;
8947 shift1
= (mode
>> 8) & 0xff;
8949 skip_whitespace (str
);
8951 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
8952 || skip_past_comma (&str
) == FAIL
8953 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
)
8956 inst
.error
= BAD_ARGS
;
8962 /* Isnsn like "foo X,Y,Z". */
8965 do_mav_triple (char * str
,
8967 enum arm_reg_type reg0
,
8968 enum arm_reg_type reg1
,
8969 enum arm_reg_type reg2
)
8971 int shift0
, shift1
, shift2
;
8973 shift0
= mode
& 0xff;
8974 shift1
= (mode
>> 8) & 0xff;
8975 shift2
= (mode
>> 16) & 0xff;
8977 skip_whitespace (str
);
8979 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
8980 || skip_past_comma (&str
) == FAIL
8981 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
8982 || skip_past_comma (&str
) == FAIL
8983 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
)
8986 inst
.error
= BAD_ARGS
;
8992 /* Wrapper functions. */
8995 do_mav_binops_1a (char * str
)
8997 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVF
);
9001 do_mav_binops_1b (char * str
)
9003 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVD
);
9007 do_mav_binops_1c (char * str
)
9009 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVDX
);
9013 do_mav_binops_1d (char * str
)
9015 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVF
);
9019 do_mav_binops_1e (char * str
)
9021 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVD
);
9025 do_mav_binops_1f (char * str
)
9027 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVF
);
9031 do_mav_binops_1g (char * str
)
9033 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVD
);
9037 do_mav_binops_1h (char * str
)
9039 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVFX
);
9043 do_mav_binops_1i (char * str
)
9045 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVFX
);
9049 do_mav_binops_1j (char * str
)
9051 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVDX
);
9055 do_mav_binops_1k (char * str
)
9057 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVDX
);
9061 do_mav_binops_1l (char * str
)
9063 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVF
);
9067 do_mav_binops_1m (char * str
)
9069 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVD
);
9073 do_mav_binops_1n (char * str
)
9075 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
9079 do_mav_binops_1o (char * str
)
9081 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
9085 do_mav_binops_2a (char * str
)
9087 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVF
, REG_TYPE_RN
);
9091 do_mav_binops_2b (char * str
)
9093 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVD
, REG_TYPE_RN
);
9097 do_mav_binops_2c (char * str
)
9099 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVDX
, REG_TYPE_RN
);
9103 do_mav_binops_3a (char * str
)
9105 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVFX
);
9109 do_mav_binops_3b (char * str
)
9111 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVFX
, REG_TYPE_MVAX
);
9115 do_mav_binops_3c (char * str
)
9117 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVDX
);
9121 do_mav_binops_3d (char * str
)
9123 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVDX
, REG_TYPE_MVAX
);
9127 do_mav_triple_4a (char * str
)
9129 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_RN
);
9133 do_mav_triple_4b (char * str
)
9135 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_RN
);
9139 do_mav_triple_5a (char * str
)
9141 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVF
, REG_TYPE_MVF
);
9145 do_mav_triple_5b (char * str
)
9147 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVD
, REG_TYPE_MVD
);
9151 do_mav_triple_5c (char * str
)
9153 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
9157 do_mav_triple_5d (char * str
)
9159 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
9163 do_mav_triple_5e (char * str
)
9165 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVF
, REG_TYPE_MVF
, REG_TYPE_MVF
);
9169 do_mav_triple_5f (char * str
)
9171 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVD
, REG_TYPE_MVD
, REG_TYPE_MVD
);
9175 do_mav_triple_5g (char * str
)
9177 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
9181 do_mav_triple_5h (char * str
)
9183 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
9186 /* Isnsn like "foo W,X,Y,Z".
9187 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
9190 do_mav_quad (char * str
,
9192 enum arm_reg_type reg0
,
9193 enum arm_reg_type reg1
,
9194 enum arm_reg_type reg2
,
9195 enum arm_reg_type reg3
)
9197 int shift0
, shift1
, shift2
, shift3
;
9199 shift0
= mode
& 0xff;
9200 shift1
= (mode
>> 8) & 0xff;
9201 shift2
= (mode
>> 16) & 0xff;
9202 shift3
= (mode
>> 24) & 0xff;
9204 skip_whitespace (str
);
9206 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
9207 || skip_past_comma (&str
) == FAIL
9208 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
9209 || skip_past_comma (&str
) == FAIL
9210 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
9211 || skip_past_comma (&str
) == FAIL
9212 || mav_reg_required_here (&str
, shift3
, reg3
) == FAIL
)
9215 inst
.error
= BAD_ARGS
;
9222 do_mav_quad_6a (char * str
)
9224 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
,
9229 do_mav_quad_6b (char * str
)
9231 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVAX
, REG_TYPE_MVFX
,
9235 /* cfmvsc32<cond> DSPSC,MVDX[15:0]. */
9237 do_mav_dspsc_1 (char * str
)
9239 skip_whitespace (str
);
9242 if (mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
9243 || skip_past_comma (&str
) == FAIL
9244 || mav_reg_required_here (&str
, 12, REG_TYPE_MVDX
) == FAIL
)
9247 inst
.error
= BAD_ARGS
;
9255 /* cfmv32sc<cond> MVDX[15:0],DSPSC. */
9257 do_mav_dspsc_2 (char * str
)
9259 skip_whitespace (str
);
9262 if (mav_reg_required_here (&str
, 12, REG_TYPE_MVDX
) == FAIL
9263 || skip_past_comma (&str
) == FAIL
9264 || mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
)
9267 inst
.error
= BAD_ARGS
;
9275 /* Maverick shift immediate instructions.
9276 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
9277 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
9280 do_mav_shift (char * str
,
9281 enum arm_reg_type reg0
,
9282 enum arm_reg_type reg1
)
9287 skip_whitespace (str
);
9291 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
9292 || skip_past_comma (&str
) == FAIL
9293 || mav_reg_required_here (&str
, 16, reg1
) == FAIL
9294 || skip_past_comma (&str
) == FAIL
)
9297 inst
.error
= BAD_ARGS
;
9301 /* Calculate the immediate operand.
9302 The operand is a 7bit signed number. */
9303 skip_whitespace (str
);
9308 if (!ISDIGIT (*str
) && *str
!= '-')
9310 inst
.error
= _("expecting immediate, 7bit operand");
9320 for (imm
= 0; *str
&& ISDIGIT (*str
); ++str
)
9321 imm
= imm
* 10 + *str
- '0';
9325 inst
.error
= _("immediate out of range");
9329 /* Make negative imm's into 7bit signed numbers. */
9336 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
9337 Bits 5-7 of the insn should have bits 4-6 of the immediate.
9338 Bit 4 should be 0. */
9339 imm
= (imm
& 0xf) | ((imm
& 0x70) << 1);
9341 inst
.instruction
|= imm
;
9346 do_mav_shift_1 (char * str
)
9348 do_mav_shift (str
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
9352 do_mav_shift_2 (char * str
)
9354 do_mav_shift (str
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
9358 mav_parse_offset (char ** str
, int * negative
)
9365 skip_whitespace (p
);
9378 inst
.error
= _("offset expected");
9382 for (offset
= 0; *p
&& ISDIGIT (*p
); ++p
)
9383 offset
= offset
* 10 + *p
- '0';
9387 inst
.error
= _("offset out of range");
9392 inst
.error
= _("offset not a multiple of 4");
9398 return *negative
? -offset
: offset
;
9401 /* Maverick load/store instructions.
9402 <insn><cond> CRd,[Rn,<offset>]{!}.
9403 <insn><cond> CRd,[Rn],<offset>. */
9406 do_mav_ldst (char * str
, enum arm_reg_type reg0
)
9408 int offset
, negative
;
9410 skip_whitespace (str
);
9412 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
9413 || skip_past_comma (&str
) == FAIL
9415 || reg_required_here (&str
, 16) == FAIL
)
9418 if (skip_past_comma (&str
) == SUCCESS
)
9420 /* You are here: "<offset>]{!}". */
9421 inst
.instruction
|= PRE_INDEX
;
9423 offset
= mav_parse_offset (&str
, &negative
);
9430 inst
.error
= _("missing ]");
9436 inst
.instruction
|= WRITE_BACK
;
9442 /* You are here: "], <offset>". */
9445 inst
.error
= _("missing ]");
9449 if (skip_past_comma (&str
) == FAIL
9450 || (offset
= mav_parse_offset (&str
, &negative
), inst
.error
))
9453 inst
.instruction
|= CP_T_WB
; /* Post indexed, set bit W. */
9459 inst
.instruction
|= CP_T_UD
; /* Positive, so set bit U. */
9461 inst
.instruction
|= offset
>> 2;
9467 inst
.error
= BAD_ARGS
;
9471 do_mav_ldst_1 (char * str
)
9473 do_mav_ldst (str
, REG_TYPE_MVF
);
9477 do_mav_ldst_2 (char * str
)
9479 do_mav_ldst (str
, REG_TYPE_MVD
);
9483 do_mav_ldst_3 (char * str
)
9485 do_mav_ldst (str
, REG_TYPE_MVFX
);
9489 do_mav_ldst_4 (char * str
)
9491 do_mav_ldst (str
, REG_TYPE_MVDX
);
9495 do_t_nop (char * str
)
9501 /* Handle the Format 4 instructions that do not have equivalents in other
9502 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
9506 do_t_arit (char * str
)
9510 skip_whitespace (str
);
9512 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9513 || skip_past_comma (&str
) == FAIL
9514 || (Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9516 inst
.error
= BAD_ARGS
;
9520 if (skip_past_comma (&str
) != FAIL
)
9522 /* Three operand format not allowed for TST, CMN, NEG and MVN.
9523 (It isn't allowed for CMP either, but that isn't handled by this
9525 if (inst
.instruction
== T_OPCODE_TST
9526 || inst
.instruction
== T_OPCODE_CMN
9527 || inst
.instruction
== T_OPCODE_NEG
9528 || inst
.instruction
== T_OPCODE_MVN
)
9530 inst
.error
= BAD_ARGS
;
9534 if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9539 inst
.error
= _("dest and source1 must be the same register");
9545 if (inst
.instruction
== T_OPCODE_MUL
9547 as_tsktsk (_("Rs and Rd must be different in MUL"));
9549 inst
.instruction
|= Rd
| (Rs
<< 3);
9554 do_t_add (char * str
)
9556 thumb_add_sub (str
, 0);
9560 do_t_asr (char * str
)
9562 thumb_shift (str
, THUMB_ASR
);
9566 do_t_branch9 (char * str
)
9568 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9570 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH9
;
9571 inst
.reloc
.pc_rel
= 1;
9576 do_t_branch12 (char * str
)
9578 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9580 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH12
;
9581 inst
.reloc
.pc_rel
= 1;
9585 /* Find the real, Thumb encoded start of a Thumb function. */
9588 find_real_start (symbolS
* symbolP
)
9591 const char * name
= S_GET_NAME (symbolP
);
9592 symbolS
* new_target
;
9594 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
9595 #define STUB_NAME ".real_start_of"
9600 /* Names that start with '.' are local labels, not function entry points.
9601 The compiler may generate BL instructions to these labels because it
9602 needs to perform a branch to a far away location. */
9606 real_start
= malloc (strlen (name
) + strlen (STUB_NAME
) + 1);
9607 sprintf (real_start
, "%s%s", STUB_NAME
, name
);
9609 new_target
= symbol_find (real_start
);
9611 if (new_target
== NULL
)
9613 as_warn ("Failed to find real start of function: %s\n", name
);
9614 new_target
= symbolP
;
9623 do_t_branch23 (char * str
)
9625 if (my_get_expression (& inst
.reloc
.exp
, & str
))
9628 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH23
;
9629 inst
.reloc
.pc_rel
= 1;
9632 /* If the destination of the branch is a defined symbol which does not have
9633 the THUMB_FUNC attribute, then we must be calling a function which has
9634 the (interfacearm) attribute. We look for the Thumb entry point to that
9635 function and change the branch to refer to that function instead. */
9636 if ( inst
.reloc
.exp
.X_op
== O_symbol
9637 && inst
.reloc
.exp
.X_add_symbol
!= NULL
9638 && S_IS_DEFINED (inst
.reloc
.exp
.X_add_symbol
)
9639 && ! THUMB_IS_FUNC (inst
.reloc
.exp
.X_add_symbol
))
9640 inst
.reloc
.exp
.X_add_symbol
=
9641 find_real_start (inst
.reloc
.exp
.X_add_symbol
);
9645 do_t_bx (char * str
)
9649 skip_whitespace (str
);
9651 if ((reg
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
9654 /* This sets THUMB_H2 from the top bit of reg. */
9655 inst
.instruction
|= reg
<< 3;
9657 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
9658 should cause the alignment to be checked once it is known. This is
9659 because BX PC only works if the instruction is word aligned. */
9665 do_t_compare (char * str
)
9667 thumb_mov_compare (str
, THUMB_COMPARE
);
9671 do_t_ldmstm (char * str
)
9676 skip_whitespace (str
);
9678 if ((Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9682 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
9686 if (skip_past_comma (&str
) == FAIL
9687 || (range
= reg_list (&str
)) == FAIL
)
9690 inst
.error
= BAD_ARGS
;
9694 if (inst
.reloc
.type
!= BFD_RELOC_UNUSED
)
9696 /* This really doesn't seem worth it. */
9697 inst
.reloc
.type
= BFD_RELOC_UNUSED
;
9698 inst
.error
= _("expression too complex");
9704 inst
.error
= _("only lo-regs valid in load/store multiple");
9708 inst
.instruction
|= (Rb
<< 8) | range
;
9713 do_t_ldr (char * str
)
9715 thumb_load_store (str
, THUMB_LOAD
, THUMB_WORD
);
9719 do_t_ldrb (char * str
)
9721 thumb_load_store (str
, THUMB_LOAD
, THUMB_BYTE
);
9725 do_t_ldrh (char * str
)
9727 thumb_load_store (str
, THUMB_LOAD
, THUMB_HALFWORD
);
9731 do_t_lds (char * str
)
9735 skip_whitespace (str
);
9737 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9738 || skip_past_comma (&str
) == FAIL
9740 || (Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9741 || skip_past_comma (&str
) == FAIL
9742 || (Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9746 inst
.error
= _("syntax: ldrs[b] Rd, [Rb, Ro]");
9750 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
9755 do_t_lsl (char * str
)
9757 thumb_shift (str
, THUMB_LSL
);
9761 do_t_lsr (char * str
)
9763 thumb_shift (str
, THUMB_LSR
);
9767 do_t_mov (char * str
)
9769 thumb_mov_compare (str
, THUMB_MOVE
);
9773 do_t_push_pop (char * str
)
9777 skip_whitespace (str
);
9779 if ((range
= reg_list (&str
)) == FAIL
)
9782 inst
.error
= BAD_ARGS
;
9786 if (inst
.reloc
.type
!= BFD_RELOC_UNUSED
)
9788 /* This really doesn't seem worth it. */
9789 inst
.reloc
.type
= BFD_RELOC_UNUSED
;
9790 inst
.error
= _("expression too complex");
9796 if ((inst
.instruction
== T_OPCODE_PUSH
9797 && (range
& ~0xff) == 1 << REG_LR
)
9798 || (inst
.instruction
== T_OPCODE_POP
9799 && (range
& ~0xff) == 1 << REG_PC
))
9801 inst
.instruction
|= THUMB_PP_PC_LR
;
9806 inst
.error
= _("invalid register list to push/pop instruction");
9811 inst
.instruction
|= range
;
9816 do_t_str (char * str
)
9818 thumb_load_store (str
, THUMB_STORE
, THUMB_WORD
);
9822 do_t_strb (char * str
)
9824 thumb_load_store (str
, THUMB_STORE
, THUMB_BYTE
);
9828 do_t_strh (char * str
)
9830 thumb_load_store (str
, THUMB_STORE
, THUMB_HALFWORD
);
9834 do_t_sub (char * str
)
9836 thumb_add_sub (str
, 1);
9840 do_t_swi (char * str
)
9842 skip_whitespace (str
);
9844 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9847 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
9852 do_t_adr (char * str
)
9856 /* This is a pseudo-op of the form "adr rd, label" to be converted
9857 into a relative address of the form "add rd, pc, #label-.-4". */
9858 skip_whitespace (str
);
9860 /* Store Rd in temporary location inside instruction. */
9861 if ((reg
= reg_required_here (&str
, 4)) == FAIL
9862 || (reg
> 7) /* For Thumb reg must be r0..r7. */
9863 || skip_past_comma (&str
) == FAIL
9864 || my_get_expression (&inst
.reloc
.exp
, &str
))
9867 inst
.error
= BAD_ARGS
;
9871 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
9872 inst
.reloc
.exp
.X_add_number
-= 4; /* PC relative adjust. */
9873 inst
.reloc
.pc_rel
= 1;
9874 inst
.instruction
|= REG_PC
; /* Rd is already placed into the instruction. */
9880 insert_reg (const struct reg_entry
* r
,
9881 struct hash_control
* htab
)
9883 int len
= strlen (r
->name
) + 2;
9884 char * buf
= xmalloc (len
);
9885 char * buf2
= xmalloc (len
);
9888 #ifdef REGISTER_PREFIX
9889 buf
[i
++] = REGISTER_PREFIX
;
9892 strcpy (buf
+ i
, r
->name
);
9894 for (i
= 0; buf
[i
]; i
++)
9895 buf2
[i
] = TOUPPER (buf
[i
]);
9899 hash_insert (htab
, buf
, (PTR
) r
);
9900 hash_insert (htab
, buf2
, (PTR
) r
);
9904 build_reg_hsh (struct reg_map
* map
)
9906 const struct reg_entry
*r
;
9908 if ((map
->htab
= hash_new ()) == NULL
)
9909 as_fatal (_("virtual memory exhausted"));
9911 for (r
= map
->names
; r
->name
!= NULL
; r
++)
9912 insert_reg (r
, map
->htab
);
9916 insert_reg_alias (char * str
,
9918 struct hash_control
*htab
)
9921 struct reg_entry
* new = xmalloc (sizeof (struct reg_entry
));
9922 const char * name
= xmalloc (strlen (str
) + 1);
9924 strcpy ((char *) name
, str
);
9927 new->number
= regnum
;
9928 new->builtin
= FALSE
;
9930 error
= hash_insert (htab
, name
, (PTR
) new);
9933 as_bad (_("failed to create an alias for %s, reason: %s"),
9935 free ((char *) name
);
9940 /* Look for the .req directive. This is of the form:
9942 new_register_name .req existing_register_name
9944 If we find one, or if it looks sufficiently like one that we want to
9945 handle any error here, return non-zero. Otherwise return zero. */
9948 create_register_alias (char * newname
, char * p
)
9954 skip_whitespace (q
);
9959 if (*q
&& !strncmp (q
, ".req ", 5))
9964 #ifndef IGNORE_OPCODE_CASE
9965 newname
= original_case_string
;
9967 copy_of_str
= newname
;
9970 skip_whitespace (q
);
9972 for (r
= q
; *r
!= '\0'; r
++)
9978 enum arm_reg_type new_type
, old_type
;
9983 old_type
= arm_reg_parse_any (q
);
9986 new_type
= arm_reg_parse_any (newname
);
9988 if (new_type
== REG_TYPE_MAX
)
9990 if (old_type
!= REG_TYPE_MAX
)
9992 old_regno
= arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
);
9993 insert_reg_alias (newname
, old_regno
,
9994 all_reg_maps
[old_type
].htab
);
9997 as_warn (_("register '%s' does not exist\n"), q
);
9999 else if (old_type
== REG_TYPE_MAX
)
10001 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
10006 /* Do not warn about redefinitions to the same alias. */
10007 if (new_type
!= old_type
10008 || (arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
)
10009 != arm_reg_parse (&q
, all_reg_maps
[new_type
].htab
)))
10010 as_warn (_("ignoring redefinition of register alias '%s'"),
10016 as_warn (_("ignoring incomplete .req pseuso op"));
10027 set_constant_flonums (void)
10031 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
10032 if (atof_ieee ((char *) fp_const
[i
], 'x', fp_values
[i
]) == NULL
)
10037 static const struct asm_opcode insns
[] =
10039 /* Core ARM Instructions. */
10040 {"and", 0xe0000000, 3, ARM_EXT_V1
, do_arit
},
10041 {"ands", 0xe0100000, 3, ARM_EXT_V1
, do_arit
},
10042 {"eor", 0xe0200000, 3, ARM_EXT_V1
, do_arit
},
10043 {"eors", 0xe0300000, 3, ARM_EXT_V1
, do_arit
},
10044 {"sub", 0xe0400000, 3, ARM_EXT_V1
, do_arit
},
10045 {"subs", 0xe0500000, 3, ARM_EXT_V1
, do_arit
},
10046 {"rsb", 0xe0600000, 3, ARM_EXT_V1
, do_arit
},
10047 {"rsbs", 0xe0700000, 3, ARM_EXT_V1
, do_arit
},
10048 {"add", 0xe0800000, 3, ARM_EXT_V1
, do_arit
},
10049 {"adds", 0xe0900000, 3, ARM_EXT_V1
, do_arit
},
10050 {"adc", 0xe0a00000, 3, ARM_EXT_V1
, do_arit
},
10051 {"adcs", 0xe0b00000, 3, ARM_EXT_V1
, do_arit
},
10052 {"sbc", 0xe0c00000, 3, ARM_EXT_V1
, do_arit
},
10053 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1
, do_arit
},
10054 {"rsc", 0xe0e00000, 3, ARM_EXT_V1
, do_arit
},
10055 {"rscs", 0xe0f00000, 3, ARM_EXT_V1
, do_arit
},
10056 {"orr", 0xe1800000, 3, ARM_EXT_V1
, do_arit
},
10057 {"orrs", 0xe1900000, 3, ARM_EXT_V1
, do_arit
},
10058 {"bic", 0xe1c00000, 3, ARM_EXT_V1
, do_arit
},
10059 {"bics", 0xe1d00000, 3, ARM_EXT_V1
, do_arit
},
10061 {"tst", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
10062 {"tsts", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
10063 {"tstp", 0xe110f000, 3, ARM_EXT_V1
, do_cmp
},
10064 {"teq", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
10065 {"teqs", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
10066 {"teqp", 0xe130f000, 3, ARM_EXT_V1
, do_cmp
},
10067 {"cmp", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
10068 {"cmps", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
10069 {"cmpp", 0xe150f000, 3, ARM_EXT_V1
, do_cmp
},
10070 {"cmn", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
10071 {"cmns", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
10072 {"cmnp", 0xe170f000, 3, ARM_EXT_V1
, do_cmp
},
10074 {"mov", 0xe1a00000, 3, ARM_EXT_V1
, do_mov
},
10075 {"movs", 0xe1b00000, 3, ARM_EXT_V1
, do_mov
},
10076 {"mvn", 0xe1e00000, 3, ARM_EXT_V1
, do_mov
},
10077 {"mvns", 0xe1f00000, 3, ARM_EXT_V1
, do_mov
},
10079 {"ldr", 0xe4100000, 3, ARM_EXT_V1
, do_ldst
},
10080 {"ldrb", 0xe4500000, 3, ARM_EXT_V1
, do_ldst
},
10081 {"ldrt", 0xe4300000, 3, ARM_EXT_V1
, do_ldstt
},
10082 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1
, do_ldstt
},
10083 {"str", 0xe4000000, 3, ARM_EXT_V1
, do_ldst
},
10084 {"strb", 0xe4400000, 3, ARM_EXT_V1
, do_ldst
},
10085 {"strt", 0xe4200000, 3, ARM_EXT_V1
, do_ldstt
},
10086 {"strbt", 0xe4600000, 3, ARM_EXT_V1
, do_ldstt
},
10088 {"stmia", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
10089 {"stmib", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
10090 {"stmda", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
10091 {"stmdb", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
10092 {"stmfd", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
10093 {"stmfa", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
10094 {"stmea", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
10095 {"stmed", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
10097 {"ldmia", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
10098 {"ldmib", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
10099 {"ldmda", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
10100 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
10101 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
10102 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
10103 {"ldmea", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
10104 {"ldmed", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
10106 {"swi", 0xef000000, 3, ARM_EXT_V1
, do_swi
},
10108 /* XXX This is the wrong place to do this. Think multi-arch. */
10109 {"bl", 0xeb000000, 2, ARM_EXT_V1
, do_branch
},
10110 {"b", 0xea000000, 1, ARM_EXT_V1
, do_branch
},
10112 {"bl", 0xebfffffe, 2, ARM_EXT_V1
, do_branch
},
10113 {"b", 0xeafffffe, 1, ARM_EXT_V1
, do_branch
},
10117 {"adr", 0xe28f0000, 3, ARM_EXT_V1
, do_adr
},
10118 {"adrl", 0xe28f0000, 3, ARM_EXT_V1
, do_adrl
},
10119 {"nop", 0xe1a00000, 3, ARM_EXT_V1
, do_nop
},
10121 /* ARM 2 multiplies. */
10122 {"mul", 0xe0000090, 3, ARM_EXT_V2
, do_mul
},
10123 {"muls", 0xe0100090, 3, ARM_EXT_V2
, do_mul
},
10124 {"mla", 0xe0200090, 3, ARM_EXT_V2
, do_mla
},
10125 {"mlas", 0xe0300090, 3, ARM_EXT_V2
, do_mla
},
10127 /* Generic coprocessor instructions. */
10128 {"cdp", 0xee000000, 3, ARM_EXT_V2
, do_cdp
},
10129 {"ldc", 0xec100000, 3, ARM_EXT_V2
, do_lstc
},
10130 {"ldcl", 0xec500000, 3, ARM_EXT_V2
, do_lstc
},
10131 {"stc", 0xec000000, 3, ARM_EXT_V2
, do_lstc
},
10132 {"stcl", 0xec400000, 3, ARM_EXT_V2
, do_lstc
},
10133 {"mcr", 0xee000010, 3, ARM_EXT_V2
, do_co_reg
},
10134 {"mrc", 0xee100010, 3, ARM_EXT_V2
, do_co_reg
},
10136 /* ARM 3 - swp instructions. */
10137 {"swp", 0xe1000090, 3, ARM_EXT_V2S
, do_swap
},
10138 {"swpb", 0xe1400090, 3, ARM_EXT_V2S
, do_swap
},
10140 /* ARM 6 Status register instructions. */
10141 {"mrs", 0xe10f0000, 3, ARM_EXT_V3
, do_mrs
},
10142 {"msr", 0xe120f000, 3, ARM_EXT_V3
, do_msr
},
10143 /* ScottB: our code uses 0xe128f000 for msr.
10144 NickC: but this is wrong because the bits 16 through 19 are
10145 handled by the PSR_xxx defines above. */
10147 /* ARM 7M long multiplies. */
10148 {"smull", 0xe0c00090, 5, ARM_EXT_V3M
, do_mull
},
10149 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M
, do_mull
},
10150 {"umull", 0xe0800090, 5, ARM_EXT_V3M
, do_mull
},
10151 {"umulls", 0xe0900090, 5, ARM_EXT_V3M
, do_mull
},
10152 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M
, do_mull
},
10153 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M
, do_mull
},
10154 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M
, do_mull
},
10155 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M
, do_mull
},
10157 /* ARM Architecture 4. */
10158 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4
, do_ldstv4
},
10159 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4
, do_ldstv4
},
10160 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4
, do_ldstv4
},
10161 {"strh", 0xe00000b0, 3, ARM_EXT_V4
, do_ldstv4
},
10163 /* ARM Architecture 4T. */
10164 /* Note: bx (and blx) are required on V5, even if the processor does
10165 not support Thumb. */
10166 {"bx", 0xe12fff10, 2, ARM_EXT_V4T
| ARM_EXT_V5
, do_bx
},
10168 /* ARM Architecture 5T. */
10169 /* Note: blx has 2 variants, so the .value is set dynamically.
10170 Only one of the variants has conditional execution. */
10171 {"blx", 0xe0000000, 3, ARM_EXT_V5
, do_blx
},
10172 {"clz", 0xe16f0f10, 3, ARM_EXT_V5
, do_clz
},
10173 {"bkpt", 0xe1200070, 0, ARM_EXT_V5
, do_bkpt
},
10174 {"ldc2", 0xfc100000, 0, ARM_EXT_V5
, do_lstc2
},
10175 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5
, do_lstc2
},
10176 {"stc2", 0xfc000000, 0, ARM_EXT_V5
, do_lstc2
},
10177 {"stc2l", 0xfc400000, 0, ARM_EXT_V5
, do_lstc2
},
10178 {"cdp2", 0xfe000000, 0, ARM_EXT_V5
, do_cdp2
},
10179 {"mcr2", 0xfe000010, 0, ARM_EXT_V5
, do_co_reg2
},
10180 {"mrc2", 0xfe100010, 0, ARM_EXT_V5
, do_co_reg2
},
10182 /* ARM Architecture 5TExP. */
10183 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP
, do_smla
},
10184 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP
, do_smla
},
10185 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP
, do_smla
},
10186 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP
, do_smla
},
10188 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP
, do_smla
},
10189 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP
, do_smla
},
10191 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP
, do_smlal
},
10192 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP
, do_smlal
},
10193 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP
, do_smlal
},
10194 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP
, do_smlal
},
10196 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP
, do_smul
},
10197 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP
, do_smul
},
10198 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP
, do_smul
},
10199 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP
, do_smul
},
10201 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP
, do_smul
},
10202 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP
, do_smul
},
10204 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP
, do_qadd
},
10205 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP
, do_qadd
},
10206 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP
, do_qadd
},
10207 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP
, do_qadd
},
10209 /* ARM Architecture 5TE. */
10210 {"pld", 0xf450f000, 0, ARM_EXT_V5E
, do_pld
},
10211 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E
, do_ldrd
},
10212 {"strd", 0xe00000f0, 3, ARM_EXT_V5E
, do_ldrd
},
10214 {"mcrr", 0xec400000, 4, ARM_EXT_V5E
, do_co_reg2c
},
10215 {"mrrc", 0xec500000, 4, ARM_EXT_V5E
, do_co_reg2c
},
10217 /* ARM Architecture 5TEJ. */
10218 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J
, do_bxj
},
10221 { "cps", 0xf1020000, 0, ARM_EXT_V6
, do_cps
},
10222 { "cpsie", 0xf1080000, 0, ARM_EXT_V6
, do_cpsi
},
10223 { "cpsid", 0xf10C0000, 0, ARM_EXT_V6
, do_cpsi
},
10224 { "ldrex", 0xe1900f9f, 5, ARM_EXT_V6
, do_ldrex
},
10225 { "mcrr2", 0xfc400000, 0, ARM_EXT_V6
, do_co_reg2c
},
10226 { "mrrc2", 0xfc500000, 0, ARM_EXT_V6
, do_co_reg2c
},
10227 { "pkhbt", 0xe6800010, 5, ARM_EXT_V6
, do_pkhbt
},
10228 { "pkhtb", 0xe6800050, 5, ARM_EXT_V6
, do_pkhtb
},
10229 { "qadd16", 0xe6200f10, 6, ARM_EXT_V6
, do_qadd16
},
10230 { "qadd8", 0xe6200f90, 5, ARM_EXT_V6
, do_qadd16
},
10231 { "qaddsubx", 0xe6200f30, 8, ARM_EXT_V6
, do_qadd16
},
10232 { "qsub16", 0xe6200f70, 6, ARM_EXT_V6
, do_qadd16
},
10233 { "qsub8", 0xe6200ff0, 5, ARM_EXT_V6
, do_qadd16
},
10234 { "qsubaddx", 0xe6200f50, 8, ARM_EXT_V6
, do_qadd16
},
10235 { "sadd16", 0xe6100f10, 6, ARM_EXT_V6
, do_qadd16
},
10236 { "sadd8", 0xe6100f90, 5, ARM_EXT_V6
, do_qadd16
},
10237 { "saddsubx", 0xe6100f30, 8, ARM_EXT_V6
, do_qadd16
},
10238 { "shadd16", 0xe6300f10, 7, ARM_EXT_V6
, do_qadd16
},
10239 { "shadd8", 0xe6300f90, 6, ARM_EXT_V6
, do_qadd16
},
10240 { "shaddsubx", 0xe6300f30, 9, ARM_EXT_V6
, do_qadd16
},
10241 { "shsub16", 0xe6300f70, 7, ARM_EXT_V6
, do_qadd16
},
10242 { "shsub8", 0xe6300ff0, 6, ARM_EXT_V6
, do_qadd16
},
10243 { "shsubaddx", 0xe6300f50, 9, ARM_EXT_V6
, do_qadd16
},
10244 { "ssub16", 0xe6100f70, 6, ARM_EXT_V6
, do_qadd16
},
10245 { "ssub8", 0xe6100ff0, 5, ARM_EXT_V6
, do_qadd16
},
10246 { "ssubaddx", 0xe6100f50, 8, ARM_EXT_V6
, do_qadd16
},
10247 { "uadd16", 0xe6500f10, 6, ARM_EXT_V6
, do_qadd16
},
10248 { "uadd8", 0xe6500f90, 5, ARM_EXT_V6
, do_qadd16
},
10249 { "uaddsubx", 0xe6500f30, 8, ARM_EXT_V6
, do_qadd16
},
10250 { "uhadd16", 0xe6700f10, 7, ARM_EXT_V6
, do_qadd16
},
10251 { "uhadd8", 0xe6700f90, 6, ARM_EXT_V6
, do_qadd16
},
10252 { "uhaddsubx", 0xe6700f30, 9, ARM_EXT_V6
, do_qadd16
},
10253 { "uhsub16", 0xe6700f70, 7, ARM_EXT_V6
, do_qadd16
},
10254 { "uhsub8", 0xe6700ff0, 6, ARM_EXT_V6
, do_qadd16
},
10255 { "uhsubaddx", 0xe6700f50, 9, ARM_EXT_V6
, do_qadd16
},
10256 { "uqadd16", 0xe6600f10, 7, ARM_EXT_V6
, do_qadd16
},
10257 { "uqadd8", 0xe6600f90, 6, ARM_EXT_V6
, do_qadd16
},
10258 { "uqaddsubx", 0xe6600f30, 9, ARM_EXT_V6
, do_qadd16
},
10259 { "uqsub16", 0xe6600f70, 7, ARM_EXT_V6
, do_qadd16
},
10260 { "uqsub8", 0xe6600ff0, 6, ARM_EXT_V6
, do_qadd16
},
10261 { "uqsubaddx", 0xe6600f50, 9, ARM_EXT_V6
, do_qadd16
},
10262 { "usub16", 0xe6500f70, 6, ARM_EXT_V6
, do_qadd16
},
10263 { "usub8", 0xe6500ff0, 5, ARM_EXT_V6
, do_qadd16
},
10264 { "usubaddx", 0xe6500f50, 8, ARM_EXT_V6
, do_qadd16
},
10265 { "rev", 0xe6bf0f30, 3, ARM_EXT_V6
, do_rev
},
10266 { "rev16", 0xe6bf0fb0, 5, ARM_EXT_V6
, do_rev
},
10267 { "revsh", 0xe6ff0fb0, 5, ARM_EXT_V6
, do_rev
},
10268 { "rfeia", 0xf8900a00, 0, ARM_EXT_V6
, do_rfe
},
10269 { "rfeib", 0xf9900a00, 0, ARM_EXT_V6
, do_rfe
},
10270 { "rfeda", 0xf8100a00, 0, ARM_EXT_V6
, do_rfe
},
10271 { "rfedb", 0xf9100a00, 0, ARM_EXT_V6
, do_rfe
},
10272 { "rfefd", 0xf8900a00, 0, ARM_EXT_V6
, do_rfe
},
10273 { "rfefa", 0xf9900a00, 0, ARM_EXT_V6
, do_rfe
},
10274 { "rfeea", 0xf8100a00, 0, ARM_EXT_V6
, do_rfe
},
10275 { "rfeed", 0xf9100a00, 0, ARM_EXT_V6
, do_rfe
},
10276 { "sxtah", 0xe6b00070, 5, ARM_EXT_V6
, do_sxtah
},
10277 { "sxtab16", 0xe6800070, 7, ARM_EXT_V6
, do_sxtah
},
10278 { "sxtab", 0xe6a00070, 5, ARM_EXT_V6
, do_sxtah
},
10279 { "sxth", 0xe6bf0070, 4, ARM_EXT_V6
, do_sxth
},
10280 { "sxtb16", 0xe68f0070, 6, ARM_EXT_V6
, do_sxth
},
10281 { "sxtb", 0xe6af0070, 4, ARM_EXT_V6
, do_sxth
},
10282 { "uxtah", 0xe6f00070, 5, ARM_EXT_V6
, do_sxtah
},
10283 { "uxtab16", 0xe6c00070, 7, ARM_EXT_V6
, do_sxtah
},
10284 { "uxtab", 0xe6e00070, 5, ARM_EXT_V6
, do_sxtah
},
10285 { "uxth", 0xe6ff0070, 4, ARM_EXT_V6
, do_sxth
},
10286 { "uxtb16", 0xe6cf0070, 6, ARM_EXT_V6
, do_sxth
},
10287 { "uxtb", 0xe6ef0070, 4, ARM_EXT_V6
, do_sxth
},
10288 { "sel", 0xe68000b0, 3, ARM_EXT_V6
, do_qadd16
},
10289 { "setend", 0xf1010000, 0, ARM_EXT_V6
, do_setend
},
10290 { "smlad", 0xe7000010, 5, ARM_EXT_V6
, do_smlad
},
10291 { "smladx", 0xe7000030, 6, ARM_EXT_V6
, do_smlad
},
10292 { "smlald", 0xe7400010, 6, ARM_EXT_V6
, do_smlald
},
10293 { "smlaldx", 0xe7400030, 7, ARM_EXT_V6
, do_smlald
},
10294 { "smlsd", 0xe7000050, 5, ARM_EXT_V6
, do_smlad
},
10295 { "smlsdx", 0xe7000070, 6, ARM_EXT_V6
, do_smlad
},
10296 { "smlsld", 0xe7400050, 6, ARM_EXT_V6
, do_smlald
},
10297 { "smlsldx", 0xe7400070, 7, ARM_EXT_V6
, do_smlald
},
10298 { "smmla", 0xe7500010, 5, ARM_EXT_V6
, do_smlad
},
10299 { "smmlar", 0xe7500030, 6, ARM_EXT_V6
, do_smlad
},
10300 { "smmls", 0xe75000d0, 5, ARM_EXT_V6
, do_smlad
},
10301 { "smmlsr", 0xe75000f0, 6, ARM_EXT_V6
, do_smlad
},
10302 { "smmul", 0xe750f010, 5, ARM_EXT_V6
, do_smmul
},
10303 { "smmulr", 0xe750f030, 6, ARM_EXT_V6
, do_smmul
},
10304 { "smuad", 0xe700f010, 5, ARM_EXT_V6
, do_smmul
},
10305 { "smuadx", 0xe700f030, 6, ARM_EXT_V6
, do_smmul
},
10306 { "smusd", 0xe700f050, 5, ARM_EXT_V6
, do_smmul
},
10307 { "smusdx", 0xe700f070, 6, ARM_EXT_V6
, do_smmul
},
10308 { "srsia", 0xf8cd0500, 0, ARM_EXT_V6
, do_srs
},
10309 { "srsib", 0xf9cd0500, 0, ARM_EXT_V6
, do_srs
},
10310 { "srsda", 0xf84d0500, 0, ARM_EXT_V6
, do_srs
},
10311 { "srsdb", 0xf94d0500, 0, ARM_EXT_V6
, do_srs
},
10312 { "ssat", 0xe6a00010, 4, ARM_EXT_V6
, do_ssat
},
10313 { "ssat16", 0xe6a00f30, 6, ARM_EXT_V6
, do_ssat16
},
10314 { "strex", 0xe1800f90, 5, ARM_EXT_V6
, do_strex
},
10315 { "umaal", 0xe0400090, 5, ARM_EXT_V6
, do_umaal
},
10316 { "usad8", 0xe780f010, 5, ARM_EXT_V6
, do_smmul
},
10317 { "usada8", 0xe7800010, 6, ARM_EXT_V6
, do_smlad
},
10318 { "usat", 0xe6e00010, 4, ARM_EXT_V6
, do_usat
},
10319 { "usat16", 0xe6e00f30, 6, ARM_EXT_V6
, do_usat16
},
10322 { "clrex", 0xf57ff01f, 0, ARM_EXT_V6K
, do_empty
},
10323 { "ldrexb", 0xe1d00f9f, 6, ARM_EXT_V6K
, do_ldrex
},
10324 { "ldrexd", 0xe1b00f9f, 6, ARM_EXT_V6K
, do_ldrex
},
10325 { "ldrexh", 0xe1f00f9f, 6, ARM_EXT_V6K
, do_ldrex
},
10326 { "sev", 0xe320f004, 3, ARM_EXT_V6K
, do_empty
},
10327 { "strexb", 0xe1c00f90, 6, ARM_EXT_V6K
, do_strex
},
10328 { "strexd", 0xe1a00f90, 6, ARM_EXT_V6K
, do_strex
},
10329 { "strexh", 0xe1e00f90, 6, ARM_EXT_V6K
, do_strex
},
10330 { "wfe", 0xe320f002, 3, ARM_EXT_V6K
, do_empty
},
10331 { "wfi", 0xe320f003, 3, ARM_EXT_V6K
, do_empty
},
10332 { "yield", 0xe320f001, 5, ARM_EXT_V6K
, do_empty
},
10335 { "smi", 0xe1600070, 3, ARM_EXT_V6Z
, do_smi
},
10338 { "bfc", 0xe7c0001f, 3, ARM_EXT_V6T2
, do_bfc
},
10339 { "bfi", 0xe7c00010, 3, ARM_EXT_V6T2
, do_bfi
},
10340 { "mls", 0xe0600090, 3, ARM_EXT_V6T2
, do_mls
},
10341 { "movw", 0xe3000000, 4, ARM_EXT_V6T2
, do_mov16
},
10342 { "movt", 0xe3400000, 4, ARM_EXT_V6T2
, do_mov16
},
10343 { "rbit", 0xe3ff0f30, 4, ARM_EXT_V6T2
, do_rbit
},
10344 { "sbfx", 0xe7a00050, 4, ARM_EXT_V6T2
, do_bfx
},
10345 { "ubfx", 0xe7e00050, 4, ARM_EXT_V6T2
, do_bfx
},
10347 { "ldrht", 0xe03000b0, 3, ARM_EXT_V6T2
, do_ldsttv4
},
10348 { "ldrsht", 0xe03000f0, 3, ARM_EXT_V6T2
, do_ldsttv4
},
10349 { "ldrsbt", 0xe03000d0, 3, ARM_EXT_V6T2
, do_ldsttv4
},
10350 { "strht", 0xe02000b0, 3, ARM_EXT_V6T2
, do_ldsttv4
},
10352 /* Core FPA instruction set (V1). */
10353 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
10354 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
10355 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
10356 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
10358 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10359 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10360 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10361 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10363 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10364 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10365 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10366 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10368 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10369 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10370 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10371 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10372 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10373 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10374 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10375 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10376 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10377 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10378 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10379 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10381 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10382 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10383 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10384 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10385 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10386 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10387 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10388 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10389 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10390 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10391 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10392 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10394 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10395 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10396 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10397 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10398 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10399 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10400 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10401 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10402 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10403 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10404 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10405 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10407 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10408 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10409 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10410 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10411 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10412 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10413 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10414 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10415 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10416 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10417 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10418 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10420 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10421 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10422 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10423 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10424 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10425 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10426 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10427 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10428 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10429 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10430 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10431 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10433 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10434 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10435 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10436 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10437 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10438 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10439 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10440 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10441 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10442 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10443 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10444 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10446 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10447 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10448 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10449 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10450 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10451 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10452 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10453 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10454 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10455 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10456 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10457 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10459 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10460 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10461 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10462 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10463 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10464 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10465 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10466 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10467 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10468 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10469 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10470 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10472 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10473 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10474 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10475 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10476 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10477 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10478 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10479 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10480 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10481 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10482 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10483 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10485 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10486 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10487 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10488 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10489 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10490 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10491 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10492 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10493 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10494 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10495 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10496 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10498 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10499 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10500 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10501 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10502 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10503 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10504 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10505 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10506 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10507 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10508 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10509 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10511 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10512 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10513 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10514 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10515 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10516 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10517 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10518 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10519 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10520 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10521 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10522 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10524 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10525 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10526 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10527 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10528 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10529 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10530 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10531 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10532 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10533 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10534 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10535 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10537 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10538 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10539 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10540 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10541 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10542 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10543 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10544 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10545 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10546 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10547 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10548 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10550 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10551 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10552 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10553 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10554 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10555 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10556 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10557 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10558 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10559 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10560 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10561 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10563 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10564 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10565 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10566 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10567 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10568 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10569 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10570 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10571 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10572 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10573 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10574 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10576 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10577 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10578 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10579 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10580 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10581 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10582 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10583 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10584 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10585 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10586 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10587 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10589 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10590 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10591 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10592 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10593 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10594 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10595 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10596 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10597 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10598 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10599 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10600 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10602 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10603 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10604 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10605 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10606 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10607 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10608 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10609 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10610 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10611 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10612 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10613 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10615 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10616 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10617 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10618 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10619 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10620 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10621 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10622 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10623 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10624 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10625 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10626 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10628 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10629 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10630 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10631 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10632 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10633 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10634 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10635 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10636 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10637 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10638 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10639 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10641 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10642 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10643 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10644 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10645 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10646 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10647 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10648 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10649 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10650 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10651 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10652 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10654 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10655 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10656 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10657 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10658 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10659 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10660 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10661 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10662 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10663 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10664 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10665 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10667 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10668 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10669 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10670 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10671 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10672 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10673 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10674 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10675 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10676 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10677 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10678 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10680 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10681 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10682 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10683 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10684 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10685 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10686 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10687 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10688 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10689 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10690 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10691 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10693 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10694 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10695 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10696 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10697 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10698 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10699 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10700 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10701 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10702 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10703 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10704 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10706 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10707 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10708 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10709 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10710 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10711 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10712 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10713 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10714 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10715 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10716 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10717 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10719 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10720 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10721 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10722 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10723 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10724 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10725 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10726 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10727 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10728 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10729 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10730 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10732 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10733 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10734 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10735 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10736 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10737 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10738 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10739 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10740 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10741 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10742 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10743 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10745 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10746 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10747 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10748 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10749 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
10750 not be an optional suffix, but part of the instruction. To be
10751 compatible, we accept either. */
10752 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10753 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10755 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10756 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10757 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10758 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10759 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10760 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10761 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10762 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10763 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10764 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10765 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10766 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10768 /* The implementation of the FIX instruction is broken on some
10769 assemblers, in that it accepts a precision specifier as well as a
10770 rounding specifier, despite the fact that this is meaningless.
10771 To be more compatible, we accept it as well, though of course it
10772 does not set any bits. */
10773 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10774 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10775 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10776 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10777 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10778 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10779 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10780 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10781 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10782 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10783 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10784 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10785 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10787 /* Instructions that were new with the real FPA, call them V2. */
10788 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10789 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10790 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10791 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10792 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10793 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10795 /* VFP V1xD (single precision). */
10796 /* Moves and type conversions. */
10797 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10798 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_reg_from_sp
},
10799 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_from_reg
},
10800 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD
, do_empty
},
10801 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10802 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10803 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10804 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10805 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10806 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10807 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_reg_from_ctrl
},
10808 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_ctrl_from_reg
},
10810 /* Memory operations. */
10811 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldst
},
10812 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldst
},
10813 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
10814 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
10815 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
10816 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
10817 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
10818 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
10819 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
10820 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
10821 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
10822 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
10823 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
10824 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
10825 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
10826 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
10827 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
10828 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
10830 /* Monadic operations. */
10831 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10832 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10833 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10835 /* Dyadic operations. */
10836 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10837 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10838 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10839 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10840 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10841 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10842 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10843 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10844 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10847 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10848 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_compare_z
},
10849 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10850 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_compare_z
},
10852 /* VFP V1 (Double precision). */
10853 /* Moves and type conversions. */
10854 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10855 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
10856 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10857 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1
, do_vfp_dp_from_reg
},
10858 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1
, do_vfp_dp_from_reg
},
10859 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1
, do_vfp_reg_from_dp
},
10860 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1
, do_vfp_reg_from_dp
},
10861 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
10862 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
10863 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10864 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10865 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10866 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10868 /* Memory operations. */
10869 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1
, do_vfp_dp_ldst
},
10870 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1
, do_vfp_dp_ldst
},
10871 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
10872 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
10873 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
10874 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
10875 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
10876 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
10877 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
10878 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
10880 /* Monadic operations. */
10881 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10882 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10883 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10885 /* Dyadic operations. */
10886 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10887 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10888 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10889 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10890 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10891 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10892 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10893 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10894 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10897 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10898 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_compare_z
},
10899 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10900 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1
, do_vfp_dp_compare_z
},
10903 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2
, do_vfp_sp2_from_reg2
},
10904 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2
, do_vfp_reg2_from_sp2
},
10905 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2
, do_vfp_dp_from_reg2
},
10906 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2
, do_vfp_reg2_from_dp
},
10908 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
10909 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE
, do_xsc_mia
},
10910 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10911 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10912 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10913 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10914 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10915 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE
, do_xsc_mar
},
10916 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE
, do_xsc_mra
},
10918 /* Intel Wireless MMX technology instructions. */
10919 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
10920 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
10921 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
10922 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
10923 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
10924 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
10925 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
10926 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
10927 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
10928 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10929 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10930 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10931 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10932 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10933 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10934 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
10935 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
10936 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
10937 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmcr
},
10938 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_tmcrr
},
10939 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10940 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10941 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10942 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10943 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10944 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10945 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
10946 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
10947 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
10948 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmrc
},
10949 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_tmrrc
},
10950 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
10951 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
10952 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
10953 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10954 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10955 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10956 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10957 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10958 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10959 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10960 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10961 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10962 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10963 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10964 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10965 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_waligni
},
10966 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10967 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10968 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10969 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10970 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10971 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10972 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10973 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10974 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10975 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10976 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10977 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10978 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10979 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10980 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10981 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10982 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10983 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10984 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10985 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
10986 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
10987 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
10988 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
10989 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10990 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10991 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10992 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10993 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10994 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10995 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10996 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10997 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10998 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10999 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11000 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11001 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11002 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11003 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11004 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11005 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11006 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11007 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wmov
},
11008 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11009 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11010 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11011 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11012 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11013 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11014 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11015 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11016 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11017 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11018 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11019 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11020 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
11021 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11022 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
11023 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11024 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
11025 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11026 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11027 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11028 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11029 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wshufh
},
11030 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11031 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
11032 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11033 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
11034 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11035 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
11036 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11037 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
11038 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11039 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
11040 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11041 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
11042 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11043 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
11044 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11045 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
11046 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11047 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
11048 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
11049 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
11050 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
11051 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
11052 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11053 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11054 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11055 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11056 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11057 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11058 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11059 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11060 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11061 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11062 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11063 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11064 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11065 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11066 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11067 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11068 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11069 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11070 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11071 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11072 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11073 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11074 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11075 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11076 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11077 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11078 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11079 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11080 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wzero
},
11082 /* Cirrus Maverick instructions. */
11083 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_1
},
11084 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_2
},
11085 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_3
},
11086 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_4
},
11087 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_1
},
11088 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_2
},
11089 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_3
},
11090 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_4
},
11091 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK
, do_mav_binops_2a
},
11092 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1a
},
11093 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK
, do_mav_binops_2b
},
11094 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1b
},
11095 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK
, do_mav_binops_2b
},
11096 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1b
},
11097 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK
, do_mav_binops_2c
},
11098 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1c
},
11099 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK
, do_mav_binops_2c
},
11100 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1c
},
11101 {"cfmval32", 0xee200440, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
11102 {"cfmv32al", 0xee100440, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
11103 {"cfmvam32", 0xee200460, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
11104 {"cfmv32am", 0xee100460, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
11105 {"cfmvah32", 0xee200480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
11106 {"cfmv32ah", 0xee100480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
11107 {"cfmva32", 0xee2004a0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
11108 {"cfmv32a", 0xee1004a0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
11109 {"cfmva64", 0xee2004c0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3c
},
11110 {"cfmv64a", 0xee1004c0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3d
},
11111 {"cfmvsc32", 0xee2004e0, 8, ARM_CEXT_MAVERICK
, do_mav_dspsc_1
},
11112 {"cfmv32sc", 0xee1004e0, 8, ARM_CEXT_MAVERICK
, do_mav_dspsc_2
},
11113 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
11114 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
11115 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1f
},
11116 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1g
},
11117 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1h
},
11118 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1i
},
11119 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1j
},
11120 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1k
},
11121 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1l
},
11122 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1m
},
11123 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK
, do_mav_binops_1l
},
11124 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK
, do_mav_binops_1m
},
11125 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK
, do_mav_triple_4a
},
11126 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK
, do_mav_triple_4b
},
11127 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK
, do_mav_shift_1
},
11128 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK
, do_mav_shift_2
},
11129 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5a
},
11130 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5b
},
11131 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5c
},
11132 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5d
},
11133 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
11134 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
11135 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
11136 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
11137 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
11138 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
11139 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
11140 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
11141 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
11142 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
11143 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1n
},
11144 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1o
},
11145 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1n
},
11146 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1o
},
11147 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
11148 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
11149 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
11150 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
11151 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
11152 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
11153 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
11154 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
11155 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK
, do_mav_quad_6a
},
11156 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK
, do_mav_quad_6a
},
11157 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK
, do_mav_quad_6b
},
11158 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK
, do_mav_quad_6b
},
11161 /* Iterate over the base tables to create the instruction patterns. */
11164 build_arm_ops_hsh (void)
11168 static struct obstack insn_obstack
;
11170 obstack_begin (&insn_obstack
, 4000);
11172 for (i
= 0; i
< sizeof (insns
) / sizeof (struct asm_opcode
); i
++)
11174 const struct asm_opcode
*insn
= insns
+ i
;
11176 if (insn
->cond_offset
!= 0)
11178 /* Insn supports conditional execution. Build the varaints
11179 and insert them in the hash table. */
11180 for (j
= 0; j
< sizeof (conds
) / sizeof (struct asm_cond
); j
++)
11182 unsigned len
= strlen (insn
->template);
11183 struct asm_opcode
*new;
11186 new = obstack_alloc (&insn_obstack
, sizeof (struct asm_opcode
));
11187 /* All condition codes are two characters. */
11188 template = obstack_alloc (&insn_obstack
, len
+ 3);
11190 strncpy (template, insn
->template, insn
->cond_offset
);
11191 strcpy (template + insn
->cond_offset
, conds
[j
].template);
11192 if (len
> insn
->cond_offset
)
11193 strcpy (template + insn
->cond_offset
+ 2,
11194 insn
->template + insn
->cond_offset
);
11195 new->template = template;
11196 new->cond_offset
= 0;
11197 new->variant
= insn
->variant
;
11198 new->parms
= insn
->parms
;
11199 new->value
= (insn
->value
& ~COND_MASK
) | conds
[j
].value
;
11201 hash_insert (arm_ops_hsh
, new->template, (PTR
) new);
11204 /* Finally, insert the unconditional insn in the table directly;
11205 no need to build a copy. */
11206 hash_insert (arm_ops_hsh
, insn
->template, (PTR
) insn
);
11211 static const struct thumb_opcode tinsns
[] =
11213 /* Thumb v1 (ARMv4T). */
11214 {"adc", 0x4140, 2, ARM_EXT_V4T
, do_t_arit
},
11215 {"add", 0x0000, 2, ARM_EXT_V4T
, do_t_add
},
11216 {"and", 0x4000, 2, ARM_EXT_V4T
, do_t_arit
},
11217 {"asr", 0x0000, 2, ARM_EXT_V4T
, do_t_asr
},
11218 {"b", T_OPCODE_BRANCH
, 2, ARM_EXT_V4T
, do_t_branch12
},
11219 {"beq", 0xd0fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11220 {"bne", 0xd1fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11221 {"bcs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11222 {"bhs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11223 {"bcc", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11224 {"bul", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11225 {"blo", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11226 {"bmi", 0xd4fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11227 {"bpl", 0xd5fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11228 {"bvs", 0xd6fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11229 {"bvc", 0xd7fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11230 {"bhi", 0xd8fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11231 {"bls", 0xd9fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11232 {"bge", 0xdafe, 2, ARM_EXT_V4T
, do_t_branch9
},
11233 {"blt", 0xdbfe, 2, ARM_EXT_V4T
, do_t_branch9
},
11234 {"bgt", 0xdcfe, 2, ARM_EXT_V4T
, do_t_branch9
},
11235 {"ble", 0xddfe, 2, ARM_EXT_V4T
, do_t_branch9
},
11236 {"bal", 0xdefe, 2, ARM_EXT_V4T
, do_t_branch9
},
11237 {"bic", 0x4380, 2, ARM_EXT_V4T
, do_t_arit
},
11238 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T
, do_t_branch23
},
11239 {"bx", 0x4700, 2, ARM_EXT_V4T
, do_t_bx
},
11240 {"cmn", T_OPCODE_CMN
, 2, ARM_EXT_V4T
, do_t_arit
},
11241 {"cmp", 0x0000, 2, ARM_EXT_V4T
, do_t_compare
},
11242 {"eor", 0x4040, 2, ARM_EXT_V4T
, do_t_arit
},
11243 {"ldmia", 0xc800, 2, ARM_EXT_V4T
, do_t_ldmstm
},
11244 {"ldr", 0x0000, 2, ARM_EXT_V4T
, do_t_ldr
},
11245 {"ldrb", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrb
},
11246 {"ldrh", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrh
},
11247 {"ldrsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
11248 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
11249 {"ldsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
11250 {"ldsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
11251 {"lsl", 0x0000, 2, ARM_EXT_V4T
, do_t_lsl
},
11252 {"lsr", 0x0000, 2, ARM_EXT_V4T
, do_t_lsr
},
11253 {"mov", 0x0000, 2, ARM_EXT_V4T
, do_t_mov
},
11254 {"mul", T_OPCODE_MUL
, 2, ARM_EXT_V4T
, do_t_arit
},
11255 {"mvn", T_OPCODE_MVN
, 2, ARM_EXT_V4T
, do_t_arit
},
11256 {"neg", T_OPCODE_NEG
, 2, ARM_EXT_V4T
, do_t_arit
},
11257 {"orr", 0x4300, 2, ARM_EXT_V4T
, do_t_arit
},
11258 {"pop", 0xbc00, 2, ARM_EXT_V4T
, do_t_push_pop
},
11259 {"push", 0xb400, 2, ARM_EXT_V4T
, do_t_push_pop
},
11260 {"ror", 0x41c0, 2, ARM_EXT_V4T
, do_t_arit
},
11261 {"sbc", 0x4180, 2, ARM_EXT_V4T
, do_t_arit
},
11262 {"stmia", 0xc000, 2, ARM_EXT_V4T
, do_t_ldmstm
},
11263 {"str", 0x0000, 2, ARM_EXT_V4T
, do_t_str
},
11264 {"strb", 0x0000, 2, ARM_EXT_V4T
, do_t_strb
},
11265 {"strh", 0x0000, 2, ARM_EXT_V4T
, do_t_strh
},
11266 {"swi", 0xdf00, 2, ARM_EXT_V4T
, do_t_swi
},
11267 {"sub", 0x0000, 2, ARM_EXT_V4T
, do_t_sub
},
11268 {"tst", T_OPCODE_TST
, 2, ARM_EXT_V4T
, do_t_arit
},
11270 {"adr", 0x0000, 2, ARM_EXT_V4T
, do_t_adr
},
11271 {"nop", 0x46C0, 2, ARM_EXT_V4T
, do_t_nop
}, /* mov r8,r8 */
11272 /* Thumb v2 (ARMv5T). */
11273 {"blx", 0, 0, ARM_EXT_V5T
, do_t_blx
},
11274 {"bkpt", 0xbe00, 2, ARM_EXT_V5T
, do_t_bkpt
},
11277 {"cpsie", 0xb660, 2, ARM_EXT_V6
, do_t_cps
},
11278 {"cpsid", 0xb670, 2, ARM_EXT_V6
, do_t_cps
},
11279 {"cpy", 0x4600, 2, ARM_EXT_V6
, do_t_cpy
},
11280 {"rev", 0xba00, 2, ARM_EXT_V6
, do_t_arit
},
11281 {"rev16", 0xba40, 2, ARM_EXT_V6
, do_t_arit
},
11282 {"revsh", 0xbac0, 2, ARM_EXT_V6
, do_t_arit
},
11283 {"setend", 0xb650, 2, ARM_EXT_V6
, do_t_setend
},
11284 {"sxth", 0xb200, 2, ARM_EXT_V6
, do_t_arit
},
11285 {"sxtb", 0xb240, 2, ARM_EXT_V6
, do_t_arit
},
11286 {"uxth", 0xb280, 2, ARM_EXT_V6
, do_t_arit
},
11287 {"uxtb", 0xb2c0, 2, ARM_EXT_V6
, do_t_arit
},
11290 {"sev", 0xbf40, 2, ARM_EXT_V6K
, do_empty
},
11291 {"wfe", 0xbf20, 2, ARM_EXT_V6K
, do_empty
},
11292 {"wfi", 0xbf30, 2, ARM_EXT_V6K
, do_empty
},
11293 {"yield", 0xbf10, 2, ARM_EXT_V6K
, do_empty
},
11302 if ( (arm_ops_hsh
= hash_new ()) == NULL
11303 || (arm_tops_hsh
= hash_new ()) == NULL
11304 || (arm_cond_hsh
= hash_new ()) == NULL
11305 || (arm_shift_hsh
= hash_new ()) == NULL
11306 || (arm_psr_hsh
= hash_new ()) == NULL
)
11307 as_fatal (_("virtual memory exhausted"));
11309 build_arm_ops_hsh ();
11310 for (i
= 0; i
< sizeof (tinsns
) / sizeof (struct thumb_opcode
); i
++)
11311 hash_insert (arm_tops_hsh
, tinsns
[i
].template, (PTR
) (tinsns
+ i
));
11312 for (i
= 0; i
< sizeof (conds
) / sizeof (struct asm_cond
); i
++)
11313 hash_insert (arm_cond_hsh
, conds
[i
].template, (PTR
) (conds
+ i
));
11314 for (i
= 0; i
< sizeof (shift_names
) / sizeof (struct asm_shift_name
); i
++)
11315 hash_insert (arm_shift_hsh
, shift_names
[i
].name
, (PTR
) (shift_names
+ i
));
11316 for (i
= 0; i
< sizeof (psrs
) / sizeof (struct asm_psr
); i
++)
11317 hash_insert (arm_psr_hsh
, psrs
[i
].template, (PTR
) (psrs
+ i
));
11319 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
11320 build_reg_hsh (all_reg_maps
+ i
);
11322 set_constant_flonums ();
11324 /* Set the cpu variant based on the command-line options. We prefer
11325 -mcpu= over -march= if both are set (as for GCC); and we prefer
11326 -mfpu= over any other way of setting the floating point unit.
11327 Use of legacy options with new options are faulted. */
11328 if (legacy_cpu
!= -1)
11330 if (mcpu_cpu_opt
!= -1 || march_cpu_opt
!= -1)
11331 as_bad (_("use of old and new-style options to set CPU type"));
11333 mcpu_cpu_opt
= legacy_cpu
;
11335 else if (mcpu_cpu_opt
== -1)
11336 mcpu_cpu_opt
= march_cpu_opt
;
11338 if (legacy_fpu
!= -1)
11340 if (mfpu_opt
!= -1)
11341 as_bad (_("use of old and new-style options to set FPU type"));
11343 mfpu_opt
= legacy_fpu
;
11345 else if (mfpu_opt
== -1)
11347 #if !(defined (TE_LINUX) || defined (TE_NetBSD) || defined (TE_VXWORKS))
11348 /* Some environments specify a default FPU. If they don't, infer it
11349 from the processor. */
11350 if (mcpu_fpu_opt
!= -1)
11351 mfpu_opt
= mcpu_fpu_opt
;
11353 mfpu_opt
= march_fpu_opt
;
11355 mfpu_opt
= FPU_DEFAULT
;
11359 if (mfpu_opt
== -1)
11361 if (mcpu_cpu_opt
== -1)
11362 mfpu_opt
= FPU_DEFAULT
;
11363 else if (mcpu_cpu_opt
& ARM_EXT_V5
)
11364 mfpu_opt
= FPU_ARCH_VFP_V2
;
11366 mfpu_opt
= FPU_ARCH_FPA
;
11369 if (mcpu_cpu_opt
== -1)
11370 mcpu_cpu_opt
= CPU_DEFAULT
;
11372 cpu_variant
= mcpu_cpu_opt
| mfpu_opt
;
11374 #if defined OBJ_COFF || defined OBJ_ELF
11376 unsigned int flags
= 0;
11378 #if defined OBJ_ELF
11379 flags
= meabi_flags
;
11381 switch (meabi_flags
)
11383 case EF_ARM_EABI_UNKNOWN
:
11385 /* Set the flags in the private structure. */
11386 if (uses_apcs_26
) flags
|= F_APCS26
;
11387 if (support_interwork
) flags
|= F_INTERWORK
;
11388 if (uses_apcs_float
) flags
|= F_APCS_FLOAT
;
11389 if (pic_code
) flags
|= F_PIC
;
11390 if ((cpu_variant
& FPU_ANY
) == FPU_NONE
11391 || (cpu_variant
& FPU_ANY
) == FPU_ARCH_VFP
) /* VFP layout only. */
11392 flags
|= F_SOFT_FLOAT
;
11394 switch (mfloat_abi_opt
)
11396 case ARM_FLOAT_ABI_SOFT
:
11397 case ARM_FLOAT_ABI_SOFTFP
:
11398 flags
|= F_SOFT_FLOAT
;
11401 case ARM_FLOAT_ABI_HARD
:
11402 if (flags
& F_SOFT_FLOAT
)
11403 as_bad (_("hard-float conflicts with specified fpu"));
11407 /* Using VFP conventions (even if soft-float). */
11408 if (cpu_variant
& FPU_VFP_EXT_NONE
)
11409 flags
|= F_VFP_FLOAT
;
11411 #if defined OBJ_ELF
11412 if (cpu_variant
& FPU_ARCH_MAVERICK
)
11413 flags
|= EF_ARM_MAVERICK_FLOAT
;
11416 case EF_ARM_EABI_VER4
:
11417 /* No additional flags to set. */
11424 bfd_set_private_flags (stdoutput
, flags
);
11426 /* We have run out flags in the COFF header to encode the
11427 status of ATPCS support, so instead we create a dummy,
11428 empty, debug section called .arm.atpcs. */
11433 sec
= bfd_make_section (stdoutput
, ".arm.atpcs");
11437 bfd_set_section_flags
11438 (stdoutput
, sec
, SEC_READONLY
| SEC_DEBUGGING
/* | SEC_HAS_CONTENTS */);
11439 bfd_set_section_size (stdoutput
, sec
, 0);
11440 bfd_set_section_contents (stdoutput
, sec
, NULL
, 0, 0);
11446 /* Record the CPU type as well. */
11447 switch (cpu_variant
& ARM_CPU_MASK
)
11450 mach
= bfd_mach_arm_2
;
11453 case ARM_3
: /* Also ARM_250. */
11454 mach
= bfd_mach_arm_2a
;
11457 case ARM_6
: /* Also ARM_7. */
11458 mach
= bfd_mach_arm_3
;
11462 mach
= bfd_mach_arm_unknown
;
11466 /* Catch special cases. */
11467 if (cpu_variant
& ARM_CEXT_IWMMXT
)
11468 mach
= bfd_mach_arm_iWMMXt
;
11469 else if (cpu_variant
& ARM_CEXT_XSCALE
)
11470 mach
= bfd_mach_arm_XScale
;
11471 else if (cpu_variant
& ARM_CEXT_MAVERICK
)
11472 mach
= bfd_mach_arm_ep9312
;
11473 else if (cpu_variant
& ARM_EXT_V5E
)
11474 mach
= bfd_mach_arm_5TE
;
11475 else if (cpu_variant
& ARM_EXT_V5
)
11477 if (cpu_variant
& ARM_EXT_V4T
)
11478 mach
= bfd_mach_arm_5T
;
11480 mach
= bfd_mach_arm_5
;
11482 else if (cpu_variant
& ARM_EXT_V4
)
11484 if (cpu_variant
& ARM_EXT_V4T
)
11485 mach
= bfd_mach_arm_4T
;
11487 mach
= bfd_mach_arm_4
;
11489 else if (cpu_variant
& ARM_EXT_V3M
)
11490 mach
= bfd_mach_arm_3M
;
11492 bfd_set_arch_mach (stdoutput
, TARGET_ARCH
, mach
);
11495 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11496 for use in the a.out file, and stores them in the array pointed to by buf.
11497 This knows about the endian-ness of the target machine and does
11498 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11499 2 (short) and 4 (long) Floating numbers are put out as a series of
11500 LITTLENUMS (shorts, here at least). */
11503 md_number_to_chars (char * buf
, valueT val
, int n
)
11505 if (target_big_endian
)
11506 number_to_chars_bigendian (buf
, val
, n
);
11508 number_to_chars_littleendian (buf
, val
, n
);
11512 md_chars_to_number (char * buf
, int n
)
11515 unsigned char * where
= (unsigned char *) buf
;
11517 if (target_big_endian
)
11522 result
|= (*where
++ & 255);
11530 result
|= (where
[n
] & 255);
11537 /* Turn a string in input_line_pointer into a floating point constant
11538 of type TYPE, and store the appropriate bytes in *LITP. The number
11539 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11540 returned, or NULL on OK.
11542 Note that fp constants aren't represent in the normal way on the ARM.
11543 In big endian mode, things are as expected. However, in little endian
11544 mode fp constants are big-endian word-wise, and little-endian byte-wise
11545 within the words. For example, (double) 1.1 in big endian mode is
11546 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11547 the byte sequence 99 99 f1 3f 9a 99 99 99.
11549 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11552 md_atof (int type
, char * litP
, int * sizeP
)
11555 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
11587 return _("bad call to MD_ATOF()");
11590 t
= atof_ieee (input_line_pointer
, type
, words
);
11592 input_line_pointer
= t
;
11595 if (target_big_endian
)
11597 for (i
= 0; i
< prec
; i
++)
11599 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
11605 if (cpu_variant
& FPU_ARCH_VFP
)
11606 for (i
= prec
- 1; i
>= 0; i
--)
11608 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
11612 /* For a 4 byte float the order of elements in `words' is 1 0.
11613 For an 8 byte float the order is 1 0 3 2. */
11614 for (i
= 0; i
< prec
; i
+= 2)
11616 md_number_to_chars (litP
, (valueT
) words
[i
+ 1], 2);
11617 md_number_to_chars (litP
+ 2, (valueT
) words
[i
], 2);
11625 /* The knowledge of the PC's pipeline offset is built into the insns
11629 md_pcrel_from (fixS
* fixP
)
11632 && S_GET_SEGMENT (fixP
->fx_addsy
) == undefined_section
11633 && fixP
->fx_subsy
== NULL
)
11636 if (fixP
->fx_pcrel
&& (fixP
->fx_r_type
== BFD_RELOC_ARM_THUMB_ADD
))
11638 /* PC relative addressing on the Thumb is slightly odd
11639 as the bottom two bits of the PC are forced to zero
11640 for the calculation. */
11641 return (fixP
->fx_where
+ fixP
->fx_frag
->fr_address
) & ~3;
11645 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
11646 so we un-adjust here to compensate for the accommodation. */
11647 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
+ 8;
11649 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
11653 /* Round up a section size to the appropriate boundary. */
11656 md_section_align (segT segment ATTRIBUTE_UNUSED
,
11662 /* Round all sects to multiple of 4. */
11663 return (size
+ 3) & ~3;
11667 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
11668 Otherwise we have no need to default values of symbols. */
11671 md_undefined_symbol (char * name ATTRIBUTE_UNUSED
)
11674 if (name
[0] == '_' && name
[1] == 'G'
11675 && streq (name
, GLOBAL_OFFSET_TABLE_NAME
))
11679 if (symbol_find (name
))
11680 as_bad ("GOT already in the symbol table");
11682 GOT_symbol
= symbol_new (name
, undefined_section
,
11683 (valueT
) 0, & zero_address_frag
);
11694 md_apply_fix3 (fixS
* fixP
,
11698 offsetT value
= * valP
;
11700 unsigned int newimm
;
11701 unsigned long temp
;
11703 char * buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
11704 arm_fix_data
* arm_data
= (arm_fix_data
*) fixP
->tc_fix_data
;
11706 assert (fixP
->fx_r_type
<= BFD_RELOC_UNUSED
);
11708 /* Note whether this will delete the relocation. */
11709 if (fixP
->fx_addsy
== 0 && !fixP
->fx_pcrel
)
11712 /* If this symbol is in a different section then we need to leave it for
11713 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
11714 so we have to undo it's effects here. */
11715 if (fixP
->fx_pcrel
)
11717 if (fixP
->fx_addsy
!= NULL
11718 && S_IS_DEFINED (fixP
->fx_addsy
)
11719 && S_GET_SEGMENT (fixP
->fx_addsy
) != seg
)
11720 value
+= md_pcrel_from (fixP
);
11723 /* Remember value for emit_reloc. */
11724 fixP
->fx_addnumber
= value
;
11726 switch (fixP
->fx_r_type
)
11728 case BFD_RELOC_NONE
:
11729 /* This will need to go in the object file. */
11733 case BFD_RELOC_ARM_IMMEDIATE
:
11734 /* We claim that this fixup has been processed here,
11735 even if in fact we generate an error because we do
11736 not have a reloc for it, so tc_gen_reloc will reject it. */
11740 && ! S_IS_DEFINED (fixP
->fx_addsy
))
11742 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11743 _("undefined symbol %s used as an immediate value"),
11744 S_GET_NAME (fixP
->fx_addsy
));
11748 newimm
= validate_immediate (value
);
11749 temp
= md_chars_to_number (buf
, INSN_SIZE
);
11751 /* If the instruction will fail, see if we can fix things up by
11752 changing the opcode. */
11753 if (newimm
== (unsigned int) FAIL
11754 && (newimm
= negate_data_op (&temp
, value
)) == (unsigned int) FAIL
)
11756 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11757 _("invalid constant (%lx) after fixup"),
11758 (unsigned long) value
);
11762 newimm
|= (temp
& 0xfffff000);
11763 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
11766 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
11768 unsigned int highpart
= 0;
11769 unsigned int newinsn
= 0xe1a00000; /* nop. */
11771 newimm
= validate_immediate (value
);
11772 temp
= md_chars_to_number (buf
, INSN_SIZE
);
11774 /* If the instruction will fail, see if we can fix things up by
11775 changing the opcode. */
11776 if (newimm
== (unsigned int) FAIL
11777 && (newimm
= negate_data_op (& temp
, value
)) == (unsigned int) FAIL
)
11779 /* No ? OK - try using two ADD instructions to generate
11781 newimm
= validate_immediate_twopart (value
, & highpart
);
11783 /* Yes - then make sure that the second instruction is
11785 if (newimm
!= (unsigned int) FAIL
)
11787 /* Still No ? Try using a negated value. */
11788 else if ((newimm
= validate_immediate_twopart (- value
, & highpart
)) != (unsigned int) FAIL
)
11789 temp
= newinsn
= (temp
& OPCODE_MASK
) | OPCODE_SUB
<< DATA_OP_SHIFT
;
11790 /* Otherwise - give up. */
11793 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11794 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
11799 /* Replace the first operand in the 2nd instruction (which
11800 is the PC) with the destination register. We have
11801 already added in the PC in the first instruction and we
11802 do not want to do it again. */
11803 newinsn
&= ~ 0xf0000;
11804 newinsn
|= ((newinsn
& 0x0f000) << 4);
11807 newimm
|= (temp
& 0xfffff000);
11808 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
11810 highpart
|= (newinsn
& 0xfffff000);
11811 md_number_to_chars (buf
+ INSN_SIZE
, (valueT
) highpart
, INSN_SIZE
);
11815 case BFD_RELOC_ARM_OFFSET_IMM
:
11821 if (validate_offset_imm (value
, 0) == FAIL
)
11823 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11824 _("bad immediate value for offset (%ld)"),
11829 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11830 newval
&= 0xff7ff000;
11831 newval
|= value
| (sign
? INDEX_UP
: 0);
11832 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11835 case BFD_RELOC_ARM_OFFSET_IMM8
:
11836 case BFD_RELOC_ARM_HWLITERAL
:
11842 if (validate_offset_imm (value
, 1) == FAIL
)
11844 if (fixP
->fx_r_type
== BFD_RELOC_ARM_HWLITERAL
)
11845 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11846 _("invalid literal constant: pool needs to be closer"));
11848 as_bad (_("bad immediate value for half-word offset (%ld)"),
11853 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11854 newval
&= 0xff7ff0f0;
11855 newval
|= ((value
>> 4) << 8) | (value
& 0xf) | (sign
? INDEX_UP
: 0);
11856 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11859 case BFD_RELOC_ARM_LITERAL
:
11865 if (validate_offset_imm (value
, 0) == FAIL
)
11867 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11868 _("invalid literal constant: pool needs to be closer"));
11872 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11873 newval
&= 0xff7ff000;
11874 newval
|= value
| (sign
? INDEX_UP
: 0);
11875 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11878 case BFD_RELOC_ARM_SHIFT_IMM
:
11879 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11880 if (((unsigned long) value
) > 32
11882 && (((newval
& 0x60) == 0) || (newval
& 0x60) == 0x60)))
11884 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11885 _("shift expression is too large"));
11890 /* Shifts of zero must be done as lsl. */
11892 else if (value
== 32)
11894 newval
&= 0xfffff07f;
11895 newval
|= (value
& 0x1f) << 7;
11896 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11899 case BFD_RELOC_ARM_SMI
:
11900 if (((unsigned long) value
) > 0xffff)
11901 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11902 _("invalid smi expression"));
11903 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xfff000f0;
11904 newval
|= (value
& 0xf) | ((value
& 0xfff0) << 4);
11905 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11908 case BFD_RELOC_ARM_SWI
:
11909 if (arm_data
->thumb_mode
)
11911 if (((unsigned long) value
) > 0xff)
11912 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11913 _("invalid swi expression"));
11914 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xff00;
11916 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11920 if (((unsigned long) value
) > 0x00ffffff)
11921 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11922 _("invalid swi expression"));
11923 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff000000;
11925 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11929 case BFD_RELOC_ARM_MULTI
:
11930 if (((unsigned long) value
) > 0xffff)
11931 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11932 _("invalid expression in load/store multiple"));
11933 newval
= value
| md_chars_to_number (buf
, INSN_SIZE
);
11934 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11937 case BFD_RELOC_ARM_PCREL_BRANCH
:
11938 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11940 /* Sign-extend a 24-bit number. */
11941 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
11944 value
= fixP
->fx_offset
;
11947 /* We are going to store value (shifted right by two) in the
11948 instruction, in a 24 bit, signed field. Thus we need to check
11949 that none of the top 8 bits of the shifted value (top 7 bits of
11950 the unshifted, unsigned value) are set, or that they are all set. */
11951 if ((value
& ~ ((offsetT
) 0x1ffffff)) != 0
11952 && ((value
& ~ ((offsetT
) 0x1ffffff)) != ~ ((offsetT
) 0x1ffffff)))
11955 /* Normally we would be stuck at this point, since we cannot store
11956 the absolute address that is the destination of the branch in the
11957 24 bits of the branch instruction. If however, we happen to know
11958 that the destination of the branch is in the same section as the
11959 branch instruction itself, then we can compute the relocation for
11960 ourselves and not have to bother the linker with it.
11962 FIXME: The test for OBJ_ELF is only here because I have not
11963 worked out how to do this for OBJ_COFF. */
11964 if (fixP
->fx_addsy
!= NULL
11965 && S_IS_DEFINED (fixP
->fx_addsy
)
11966 && S_GET_SEGMENT (fixP
->fx_addsy
) == seg
)
11968 /* Get pc relative value to go into the branch. */
11971 /* Permit a backward branch provided that enough bits
11972 are set. Allow a forwards branch, provided that
11973 enough bits are clear. */
11974 if ( (value
& ~ ((offsetT
) 0x1ffffff)) == ~ ((offsetT
) 0x1ffffff)
11975 || (value
& ~ ((offsetT
) 0x1ffffff)) == 0)
11979 if (! fixP
->fx_done
)
11981 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11982 _("GAS can't handle same-section branch dest >= 0x04000000"));
11986 value
+= SEXT24 (newval
);
11988 if ( (value
& ~ ((offsetT
) 0xffffff)) != 0
11989 && ((value
& ~ ((offsetT
) 0xffffff)) != ~ ((offsetT
) 0xffffff)))
11990 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11991 _("out of range branch"));
11993 if (seg
->use_rela_p
&& !fixP
->fx_done
)
11995 /* Must unshift the value before storing it in the addend. */
11998 fixP
->fx_offset
= value
;
12000 fixP
->fx_addnumber
= value
;
12001 newval
= newval
& 0xff000000;
12004 newval
= (value
& 0x00ffffff) | (newval
& 0xff000000);
12005 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12008 case BFD_RELOC_ARM_PCREL_BLX
:
12011 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12014 value
= fixP
->fx_offset
;
12016 hbit
= (value
>> 1) & 1;
12017 value
= (value
>> 2) & 0x00ffffff;
12018 value
= (value
+ (newval
& 0x00ffffff)) & 0x00ffffff;
12020 if (seg
->use_rela_p
&& !fixP
->fx_done
)
12022 /* Must sign-extend and unshift the value before storing
12023 it in the addend. */
12024 value
= SEXT24 (value
);
12025 value
= (value
<< 2) | hbit
;
12027 fixP
->fx_offset
= value
;
12029 fixP
->fx_addnumber
= value
;
12030 newval
= newval
& 0xfe000000;
12033 newval
= value
| (newval
& 0xfe000000) | (hbit
<< 24);
12034 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12038 case BFD_RELOC_THUMB_PCREL_BRANCH9
: /* Conditional branch. */
12039 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12041 addressT diff
= (newval
& 0xff) << 1;
12046 if ((value
& ~0xff) && ((value
& ~0xff) != ~0xff))
12047 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12048 _("branch out of range"));
12049 if (seg
->use_rela_p
&& !fixP
->fx_done
)
12052 fixP
->fx_offset
= value
;
12054 fixP
->fx_addnumber
= value
;
12055 newval
= newval
& 0xff00;
12058 newval
= (newval
& 0xff00) | ((value
& 0x1ff) >> 1);
12060 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12063 case BFD_RELOC_THUMB_PCREL_BRANCH12
: /* Unconditional branch. */
12064 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12066 addressT diff
= (newval
& 0x7ff) << 1;
12071 if ((value
& ~0x7ff) && ((value
& ~0x7ff) != ~0x7ff))
12072 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12073 _("branch out of range"));
12074 if (seg
->use_rela_p
&& !fixP
->fx_done
)
12077 fixP
->fx_offset
= value
;
12079 fixP
->fx_addnumber
= value
;
12080 newval
= newval
& 0xf800;
12083 newval
= (newval
& 0xf800) | ((value
& 0xfff) >> 1);
12085 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12088 case BFD_RELOC_THUMB_PCREL_BLX
:
12089 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
12094 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12095 newval2
= md_chars_to_number (buf
+ THUMB_SIZE
, THUMB_SIZE
);
12096 diff
= ((newval
& 0x7ff) << 12) | ((newval2
& 0x7ff) << 1);
12097 if (diff
& 0x400000)
12100 value
= fixP
->fx_offset
;
12104 if ((value
& ~0x3fffff) && ((value
& ~0x3fffff) != ~0x3fffff))
12105 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12106 _("branch with link out of range"));
12108 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
)
12109 /* For a BLX instruction, make sure that the relocation is rounded up
12110 to a word boundary. This follows the semantics of the instruction
12111 which specifies that bit 1 of the target address will come from bit
12112 1 of the base address. */
12113 value
= (value
+ 1) & ~ 1;
12115 if (seg
->use_rela_p
&& !fixP
->fx_done
)
12118 fixP
->fx_offset
= value
;
12120 fixP
->fx_addnumber
= value
;
12121 newval
= newval
& 0xf800;
12122 newval2
= newval2
& 0xf800;
12126 newval
= (newval
& 0xf800) | ((value
& 0x7fffff) >> 12);
12127 newval2
= (newval2
& 0xf800) | ((value
& 0xfff) >> 1);
12129 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12130 md_number_to_chars (buf
+ THUMB_SIZE
, newval2
, THUMB_SIZE
);
12135 if (seg
->use_rela_p
&& !fixP
->fx_done
)
12137 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
12138 md_number_to_chars (buf
, value
, 1);
12142 value
= fixP
->fx_offset
;
12143 md_number_to_chars (buf
, value
, 1);
12149 if (seg
->use_rela_p
&& !fixP
->fx_done
)
12151 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
12152 md_number_to_chars (buf
, value
, 2);
12156 value
= fixP
->fx_offset
;
12157 md_number_to_chars (buf
, value
, 2);
12163 case BFD_RELOC_ARM_TLS_GD32
:
12164 case BFD_RELOC_ARM_TLS_LE32
:
12165 case BFD_RELOC_ARM_TLS_IE32
:
12166 case BFD_RELOC_ARM_TLS_LDM32
:
12167 case BFD_RELOC_ARM_TLS_LDO32
:
12168 S_SET_THREAD_LOCAL (fixP
->fx_addsy
);
12171 case BFD_RELOC_ARM_GOT32
:
12172 case BFD_RELOC_ARM_GOTOFF
:
12173 case BFD_RELOC_ARM_TARGET2
:
12174 if (seg
->use_rela_p
&& !fixP
->fx_done
)
12176 md_number_to_chars (buf
, 0, 4);
12180 case BFD_RELOC_RVA
:
12182 case BFD_RELOC_ARM_TARGET1
:
12183 case BFD_RELOC_ARM_ROSEGREL32
:
12184 case BFD_RELOC_ARM_SBREL32
:
12185 case BFD_RELOC_32_PCREL
:
12186 if (seg
->use_rela_p
&& !fixP
->fx_done
)
12188 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
12189 md_number_to_chars (buf
, value
, 4);
12193 value
= fixP
->fx_offset
;
12194 md_number_to_chars (buf
, value
, 4);
12200 case BFD_RELOC_ARM_PREL31
:
12201 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
12203 newval
= md_chars_to_number (buf
, 4) & 0x80000000;
12204 if ((value
^ (value
>> 1)) & 0x40000000)
12206 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12207 _("rel31 relocation overflow"));
12209 newval
|= value
& 0x7fffffff;
12210 md_number_to_chars (buf
, newval
, 4);
12214 case BFD_RELOC_ARM_PLT32
:
12215 /* It appears the instruction is fully prepared at this point. */
12219 case BFD_RELOC_ARM_CP_OFF_IMM
:
12221 if (value
< -1023 || value
> 1023 || (value
& 3))
12222 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12223 _("illegal value for co-processor offset"));
12226 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
12227 newval
|= (value
>> 2) | (sign
? INDEX_UP
: 0);
12228 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12231 case BFD_RELOC_ARM_CP_OFF_IMM_S2
:
12233 if (value
< -255 || value
> 255)
12234 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12235 _("Illegal value for co-processor offset"));
12238 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
12239 newval
|= value
| (sign
? INDEX_UP
: 0);
12240 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12243 case BFD_RELOC_ARM_THUMB_OFFSET
:
12244 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12245 /* Exactly what ranges, and where the offset is inserted depends
12246 on the type of instruction, we can establish this from the
12248 switch (newval
>> 12)
12250 case 4: /* PC load. */
12251 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
12252 forced to zero for these loads, so we will need to round
12253 up the offset if the instruction address is not word
12254 aligned (since the final address produced must be, and
12255 we can only describe word-aligned immediate offsets). */
12257 if ((fixP
->fx_frag
->fr_address
+ fixP
->fx_where
+ value
) & 3)
12258 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12259 _("invalid offset, target not word aligned (0x%08X)"),
12260 (unsigned int) (fixP
->fx_frag
->fr_address
12261 + fixP
->fx_where
+ value
));
12263 if ((value
+ 2) & ~0x3fe)
12264 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12265 _("invalid offset, value too big (0x%08lX)"),
12268 /* Round up, since pc will be rounded down. */
12269 newval
|= (value
+ 2) >> 2;
12272 case 9: /* SP load/store. */
12273 if (value
& ~0x3fc)
12274 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12275 _("invalid offset, value too big (0x%08lX)"),
12277 newval
|= value
>> 2;
12280 case 6: /* Word load/store. */
12282 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12283 _("invalid offset, value too big (0x%08lX)"),
12285 newval
|= value
<< 4; /* 6 - 2. */
12288 case 7: /* Byte load/store. */
12290 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12291 _("invalid offset, value too big (0x%08lX)"),
12293 newval
|= value
<< 6;
12296 case 8: /* Halfword load/store. */
12298 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12299 _("invalid offset, value too big (0x%08lX)"),
12301 newval
|= value
<< 5; /* 6 - 1. */
12305 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12306 "Unable to process relocation for thumb opcode: %lx",
12307 (unsigned long) newval
);
12310 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12313 case BFD_RELOC_ARM_THUMB_ADD
:
12314 /* This is a complicated relocation, since we use it for all of
12315 the following immediate relocations:
12319 9bit ADD/SUB SP word-aligned
12320 10bit ADD PC/SP word-aligned
12322 The type of instruction being processed is encoded in the
12329 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12331 int rd
= (newval
>> 4) & 0xf;
12332 int rs
= newval
& 0xf;
12333 int subtract
= newval
& 0x8000;
12337 if (value
& ~0x1fc)
12338 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12339 _("invalid immediate for stack address calculation"));
12340 newval
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
12341 newval
|= value
>> 2;
12343 else if (rs
== REG_PC
|| rs
== REG_SP
)
12347 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12348 _("invalid immediate for address calculation (value = 0x%08lX)"),
12349 (unsigned long) value
);
12350 newval
= (rs
== REG_PC
? T_OPCODE_ADD_PC
: T_OPCODE_ADD_SP
);
12352 newval
|= value
>> 2;
12357 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12358 _("invalid 8bit immediate"));
12359 newval
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
12360 newval
|= (rd
<< 8) | value
;
12365 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12366 _("invalid 3bit immediate"));
12367 newval
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
12368 newval
|= rd
| (rs
<< 3) | (value
<< 6);
12371 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12374 case BFD_RELOC_ARM_THUMB_IMM
:
12375 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12376 switch (newval
>> 11)
12378 case 0x04: /* 8bit immediate MOV. */
12379 case 0x05: /* 8bit immediate CMP. */
12380 if (value
< 0 || value
> 255)
12381 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12382 _("invalid immediate: %ld is too large"),
12390 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12393 case BFD_RELOC_ARM_THUMB_SHIFT
:
12394 /* 5bit shift value (0..31). */
12395 if (value
< 0 || value
> 31)
12396 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12397 _("illegal Thumb shift value: %ld"), (long) value
);
12398 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xf03f;
12399 newval
|= value
<< 6;
12400 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12403 case BFD_RELOC_VTABLE_INHERIT
:
12404 case BFD_RELOC_VTABLE_ENTRY
:
12408 case BFD_RELOC_UNUSED
:
12410 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12411 _("bad relocation fixup type (%d)"), fixP
->fx_r_type
);
12415 /* Translate internal representation of relocation info to BFD target
12419 tc_gen_reloc (asection
* section ATTRIBUTE_UNUSED
,
12423 bfd_reloc_code_real_type code
;
12425 reloc
= xmalloc (sizeof (arelent
));
12427 reloc
->sym_ptr_ptr
= xmalloc (sizeof (asymbol
*));
12428 *reloc
->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
12429 reloc
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
12431 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12433 if (fixp
->fx_pcrel
== 0)
12434 reloc
->addend
= fixp
->fx_offset
;
12436 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
12437 #else /* OBJ_ELF */
12438 reloc
->addend
= fixp
->fx_offset
;
12441 switch (fixp
->fx_r_type
)
12444 if (fixp
->fx_pcrel
)
12446 code
= BFD_RELOC_8_PCREL
;
12451 if (fixp
->fx_pcrel
)
12453 code
= BFD_RELOC_16_PCREL
;
12458 if (fixp
->fx_pcrel
)
12460 code
= BFD_RELOC_32_PCREL
;
12464 case BFD_RELOC_NONE
:
12465 case BFD_RELOC_ARM_PCREL_BRANCH
:
12466 case BFD_RELOC_ARM_PCREL_BLX
:
12467 case BFD_RELOC_RVA
:
12468 case BFD_RELOC_THUMB_PCREL_BRANCH9
:
12469 case BFD_RELOC_THUMB_PCREL_BRANCH12
:
12470 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
12471 case BFD_RELOC_THUMB_PCREL_BLX
:
12472 case BFD_RELOC_VTABLE_ENTRY
:
12473 case BFD_RELOC_VTABLE_INHERIT
:
12474 code
= fixp
->fx_r_type
;
12477 case BFD_RELOC_ARM_LITERAL
:
12478 case BFD_RELOC_ARM_HWLITERAL
:
12479 /* If this is called then the a literal has
12480 been referenced across a section boundary. */
12481 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12482 _("literal referenced across section boundary"));
12486 case BFD_RELOC_ARM_GOT32
:
12487 case BFD_RELOC_ARM_GOTOFF
:
12488 case BFD_RELOC_ARM_PLT32
:
12489 case BFD_RELOC_ARM_TARGET1
:
12490 case BFD_RELOC_ARM_ROSEGREL32
:
12491 case BFD_RELOC_ARM_SBREL32
:
12492 case BFD_RELOC_ARM_PREL31
:
12493 case BFD_RELOC_ARM_TARGET2
:
12494 case BFD_RELOC_ARM_TLS_LE32
:
12495 case BFD_RELOC_ARM_TLS_LDO32
:
12496 code
= fixp
->fx_r_type
;
12499 case BFD_RELOC_ARM_TLS_GD32
:
12500 case BFD_RELOC_ARM_TLS_IE32
:
12501 case BFD_RELOC_ARM_TLS_LDM32
:
12502 /* BFD will include the symbol's address in the addend.
12503 But we don't want that, so subtract it out again here. */
12504 if (!S_IS_COMMON (fixp
->fx_addsy
))
12505 reloc
->addend
-= (*reloc
->sym_ptr_ptr
)->value
;
12506 code
= fixp
->fx_r_type
;
12510 case BFD_RELOC_ARM_IMMEDIATE
:
12511 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12512 _("internal relocation (type: IMMEDIATE) not fixed up"));
12515 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
12516 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12517 _("ADRL used for a symbol not defined in the same file"));
12520 case BFD_RELOC_ARM_OFFSET_IMM
:
12521 if (fixp
->fx_addsy
!= NULL
12522 && !S_IS_DEFINED (fixp
->fx_addsy
)
12523 && S_IS_LOCAL (fixp
->fx_addsy
))
12525 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12526 _("undefined local label `%s'"),
12527 S_GET_NAME (fixp
->fx_addsy
));
12531 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12532 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
12539 switch (fixp
->fx_r_type
)
12541 case BFD_RELOC_NONE
: type
= "NONE"; break;
12542 case BFD_RELOC_ARM_OFFSET_IMM8
: type
= "OFFSET_IMM8"; break;
12543 case BFD_RELOC_ARM_SHIFT_IMM
: type
= "SHIFT_IMM"; break;
12544 case BFD_RELOC_ARM_SMI
: type
= "SMI"; break;
12545 case BFD_RELOC_ARM_SWI
: type
= "SWI"; break;
12546 case BFD_RELOC_ARM_MULTI
: type
= "MULTI"; break;
12547 case BFD_RELOC_ARM_CP_OFF_IMM
: type
= "CP_OFF_IMM"; break;
12548 case BFD_RELOC_ARM_THUMB_ADD
: type
= "THUMB_ADD"; break;
12549 case BFD_RELOC_ARM_THUMB_SHIFT
: type
= "THUMB_SHIFT"; break;
12550 case BFD_RELOC_ARM_THUMB_IMM
: type
= "THUMB_IMM"; break;
12551 case BFD_RELOC_ARM_THUMB_OFFSET
: type
= "THUMB_OFFSET"; break;
12552 default: type
= _("<unknown>"); break;
12554 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12555 _("cannot represent %s relocation in this object file format"),
12562 if ((code
== BFD_RELOC_32_PCREL
|| code
== BFD_RELOC_32
)
12564 && fixp
->fx_addsy
== GOT_symbol
)
12566 code
= BFD_RELOC_ARM_GOTPC
;
12567 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
12571 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, code
);
12573 if (reloc
->howto
== NULL
)
12575 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12576 _("cannot represent %s relocation in this object file format"),
12577 bfd_get_reloc_code_name (code
));
12581 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12582 vtable entry to be used in the relocation's section offset. */
12583 if (fixp
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
12584 reloc
->address
= fixp
->fx_offset
;
12590 md_estimate_size_before_relax (fragS
* fragP ATTRIBUTE_UNUSED
,
12591 segT segtype ATTRIBUTE_UNUSED
)
12593 as_fatal (_("md_estimate_size_before_relax\n"));
12597 /* We need to be able to fix up arbitrary expressions in some statements.
12598 This is so that we can handle symbols that are an arbitrary distance from
12599 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
12600 which returns part of an address in a form which will be valid for
12601 a data instruction. We do this by pushing the expression into a symbol
12602 in the expr_section, and creating a fix for that. */
12605 fix_new_arm (fragS
* frag
,
12613 arm_fix_data
* arm_data
;
12621 new_fix
= fix_new_exp (frag
, where
, size
, exp
, pc_rel
, reloc
);
12625 new_fix
= fix_new (frag
, where
, size
, make_expr_symbol (exp
), 0,
12630 /* Mark whether the fix is to a THUMB instruction, or an ARM
12632 arm_data
= obstack_alloc (& notes
, sizeof (arm_fix_data
));
12633 new_fix
->tc_fix_data
= (PTR
) arm_data
;
12634 arm_data
->thumb_mode
= thumb_mode
;
12638 output_inst (const char * str
)
12644 as_bad ("%s -- `%s'", inst
.error
, str
);
12648 to
= frag_more (inst
.size
);
12650 if (thumb_mode
&& (inst
.size
> THUMB_SIZE
))
12652 assert (inst
.size
== (2 * THUMB_SIZE
));
12653 md_number_to_chars (to
, inst
.instruction
>> 16, THUMB_SIZE
);
12654 md_number_to_chars (to
+ THUMB_SIZE
, inst
.instruction
, THUMB_SIZE
);
12656 else if (inst
.size
> INSN_SIZE
)
12658 assert (inst
.size
== (2 * INSN_SIZE
));
12659 md_number_to_chars (to
, inst
.instruction
, INSN_SIZE
);
12660 md_number_to_chars (to
+ INSN_SIZE
, inst
.instruction
, INSN_SIZE
);
12663 md_number_to_chars (to
, inst
.instruction
, inst
.size
);
12665 if (inst
.reloc
.type
!= BFD_RELOC_UNUSED
)
12666 fix_new_arm (frag_now
, to
- frag_now
->fr_literal
,
12667 inst
.size
, & inst
.reloc
.exp
, inst
.reloc
.pc_rel
,
12671 dwarf2_emit_insn (inst
.size
);
12676 md_assemble (char * str
)
12682 /* Align the previous label if needed. */
12683 if (last_label_seen
!= NULL
)
12685 symbol_set_frag (last_label_seen
, frag_now
);
12686 S_SET_VALUE (last_label_seen
, (valueT
) frag_now_fix ());
12687 S_SET_SEGMENT (last_label_seen
, now_seg
);
12690 memset (&inst
, '\0', sizeof (inst
));
12691 inst
.reloc
.type
= BFD_RELOC_UNUSED
;
12693 skip_whitespace (str
);
12695 /* Scan up to the end of the op-code, which must end in white space or
12697 for (start
= p
= str
; *p
!= '\0'; p
++)
12703 as_bad (_("no operator -- statement `%s'\n"), str
);
12709 const struct thumb_opcode
* opcode
;
12713 opcode
= (const struct thumb_opcode
*) hash_find (arm_tops_hsh
, str
);
12718 /* Check that this instruction is supported for this CPU. */
12719 if (thumb_mode
== 1 && (opcode
->variant
& cpu_variant
) == 0)
12721 as_bad (_("selected processor does not support `%s'"), str
);
12725 mapping_state (MAP_THUMB
);
12726 inst
.instruction
= opcode
->value
;
12727 inst
.size
= opcode
->size
;
12735 const struct asm_opcode
* opcode
;
12739 opcode
= (const struct asm_opcode
*) hash_find (arm_ops_hsh
, str
);
12744 /* Check that this instruction is supported for this CPU. */
12745 if ((opcode
->variant
& cpu_variant
) == 0)
12747 as_bad (_("selected processor does not support `%s'"), str
);
12751 mapping_state (MAP_ARM
);
12752 inst
.instruction
= opcode
->value
;
12753 inst
.size
= INSN_SIZE
;
12760 /* It wasn't an instruction, but it might be a register alias of the form
12762 if (create_register_alias (str
, p
))
12765 as_bad (_("bad instruction `%s'"), start
);
12769 Invocation line includes a switch not recognized by the base assembler.
12770 See if it's a processor-specific option.
12772 This routine is somewhat complicated by the need for backwards
12773 compatibility (since older releases of gcc can't be changed).
12774 The new options try to make the interface as compatible as
12777 New options (supported) are:
12779 -mcpu=<cpu name> Assemble for selected processor
12780 -march=<architecture name> Assemble for selected architecture
12781 -mfpu=<fpu architecture> Assemble for selected FPU.
12782 -EB/-mbig-endian Big-endian
12783 -EL/-mlittle-endian Little-endian
12784 -k Generate PIC code
12785 -mthumb Start in Thumb mode
12786 -mthumb-interwork Code supports ARM/Thumb interworking
12788 For now we will also provide support for:
12790 -mapcs-32 32-bit Program counter
12791 -mapcs-26 26-bit Program counter
12792 -macps-float Floats passed in FP registers
12793 -mapcs-reentrant Reentrant code
12795 (sometime these will probably be replaced with -mapcs=<list of options>
12796 and -matpcs=<list of options>)
12798 The remaining options are only supported for back-wards compatibility.
12799 Cpu variants, the arm part is optional:
12800 -m[arm]1 Currently not supported.
12801 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
12802 -m[arm]3 Arm 3 processor
12803 -m[arm]6[xx], Arm 6 processors
12804 -m[arm]7[xx][t][[d]m] Arm 7 processors
12805 -m[arm]8[10] Arm 8 processors
12806 -m[arm]9[20][tdmi] Arm 9 processors
12807 -mstrongarm[110[0]] StrongARM processors
12808 -mxscale XScale processors
12809 -m[arm]v[2345[t[e]]] Arm architectures
12810 -mall All (except the ARM1)
12812 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
12813 -mfpe-old (No float load/store multiples)
12814 -mvfpxd VFP Single precision
12816 -mno-fpu Disable all floating point instructions
12818 The following CPU names are recognized:
12819 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
12820 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
12821 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
12822 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
12823 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
12824 arm10t arm10e, arm1020t, arm1020e, arm10200e,
12825 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
12829 const char * md_shortopts
= "m:k";
12831 #ifdef ARM_BI_ENDIAN
12832 #define OPTION_EB (OPTION_MD_BASE + 0)
12833 #define OPTION_EL (OPTION_MD_BASE + 1)
12835 #if TARGET_BYTES_BIG_ENDIAN
12836 #define OPTION_EB (OPTION_MD_BASE + 0)
12838 #define OPTION_EL (OPTION_MD_BASE + 1)
12842 struct option md_longopts
[] =
12845 {"EB", no_argument
, NULL
, OPTION_EB
},
12848 {"EL", no_argument
, NULL
, OPTION_EL
},
12850 {NULL
, no_argument
, NULL
, 0}
12853 size_t md_longopts_size
= sizeof (md_longopts
);
12855 struct arm_option_table
12857 char *option
; /* Option name to match. */
12858 char *help
; /* Help information. */
12859 int *var
; /* Variable to change. */
12860 int value
; /* What to change it to. */
12861 char *deprecated
; /* If non-null, print this message. */
12864 struct arm_option_table arm_opts
[] =
12866 {"k", N_("generate PIC code"), &pic_code
, 1, NULL
},
12867 {"mthumb", N_("assemble Thumb code"), &thumb_mode
, 1, NULL
},
12868 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
12869 &support_interwork
, 1, NULL
},
12870 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26
, 0, NULL
},
12871 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26
, 1, NULL
},
12872 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float
,
12874 {"mapcs-reentrant", N_("re-entrant code"), &pic_code
, 1, NULL
},
12875 {"matpcs", N_("code is ATPCS conformant"), &atpcs
, 1, NULL
},
12876 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian
, 1, NULL
},
12877 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian
, 1,
12880 /* These are recognized by the assembler, but have no affect on code. */
12881 {"mapcs-frame", N_("use frame pointer"), NULL
, 0, NULL
},
12882 {"mapcs-stack-check", N_("use stack size checking"), NULL
, 0, NULL
},
12884 /* DON'T add any new processors to this list -- we want the whole list
12885 to go away... Add them to the processors table instead. */
12886 {"marm1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
12887 {"m1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
12888 {"marm2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
12889 {"m2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
12890 {"marm250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
12891 {"m250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
12892 {"marm3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
12893 {"m3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
12894 {"marm6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
12895 {"m6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
12896 {"marm600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
12897 {"m600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
12898 {"marm610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
12899 {"m610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
12900 {"marm620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
12901 {"m620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
12902 {"marm7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
12903 {"m7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
12904 {"marm70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
12905 {"m70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
12906 {"marm700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
12907 {"m700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
12908 {"marm700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
12909 {"m700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
12910 {"marm710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
12911 {"m710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
12912 {"marm710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
12913 {"m710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
12914 {"marm720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
12915 {"m720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
12916 {"marm7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
12917 {"m7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
12918 {"marm7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
12919 {"m7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
12920 {"marm7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
12921 {"m7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
12922 {"marm7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
12923 {"m7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
12924 {"marm7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
12925 {"m7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
12926 {"marm7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
12927 {"m7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
12928 {"marm7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
12929 {"m7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
12930 {"marm7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
12931 {"m7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
12932 {"marm7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12933 {"m7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12934 {"marm7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12935 {"m7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12936 {"marm710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
12937 {"m710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
12938 {"marm720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
12939 {"m720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
12940 {"marm740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
12941 {"m740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
12942 {"marm8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
12943 {"m8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
12944 {"marm810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
12945 {"m810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
12946 {"marm9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
12947 {"m9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
12948 {"marm9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
12949 {"m9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
12950 {"marm920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
12951 {"m920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
12952 {"marm940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
12953 {"m940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
12954 {"mstrongarm", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=strongarm")},
12955 {"mstrongarm110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
12956 N_("use -mcpu=strongarm110")},
12957 {"mstrongarm1100", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
12958 N_("use -mcpu=strongarm1100")},
12959 {"mstrongarm1110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
12960 N_("use -mcpu=strongarm1110")},
12961 {"mxscale", NULL
, &legacy_cpu
, ARM_ARCH_XSCALE
, N_("use -mcpu=xscale")},
12962 {"miwmmxt", NULL
, &legacy_cpu
, ARM_ARCH_IWMMXT
, N_("use -mcpu=iwmmxt")},
12963 {"mall", NULL
, &legacy_cpu
, ARM_ANY
, N_("use -mcpu=all")},
12965 /* Architecture variants -- don't add any more to this list either. */
12966 {"mv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
12967 {"marmv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
12968 {"mv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
12969 {"marmv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
12970 {"mv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
12971 {"marmv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
12972 {"mv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
12973 {"marmv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
12974 {"mv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
12975 {"marmv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
12976 {"mv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
12977 {"marmv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
12978 {"mv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
12979 {"marmv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
12980 {"mv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
12981 {"marmv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
12982 {"mv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
12983 {"marmv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
12985 /* Floating point variants -- don't add any more to this list either. */
12986 {"mfpe-old", NULL
, &legacy_fpu
, FPU_ARCH_FPE
, N_("use -mfpu=fpe")},
12987 {"mfpa10", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa10")},
12988 {"mfpa11", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa11")},
12989 {"mno-fpu", NULL
, &legacy_fpu
, 0,
12990 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
12992 {NULL
, NULL
, NULL
, 0, NULL
}
12995 struct arm_cpu_option_table
12999 /* For some CPUs we assume an FPU unless the user explicitly sets
13004 /* This list should, at a minimum, contain all the cpu names
13005 recognized by GCC. */
13006 static struct arm_cpu_option_table arm_cpus
[] =
13008 {"all", ARM_ANY
, FPU_ARCH_FPA
},
13009 {"arm1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
13010 {"arm2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
13011 {"arm250", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
13012 {"arm3", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
13013 {"arm6", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13014 {"arm60", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13015 {"arm600", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13016 {"arm610", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13017 {"arm620", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13018 {"arm7", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13019 {"arm7m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
13020 {"arm7d", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13021 {"arm7dm", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
13022 {"arm7di", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13023 {"arm7dmi", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
13024 {"arm70", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13025 {"arm700", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13026 {"arm700i", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13027 {"arm710", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13028 {"arm710t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13029 {"arm720", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13030 {"arm720t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13031 {"arm740t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13032 {"arm710c", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13033 {"arm7100", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13034 {"arm7500", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13035 {"arm7500fe", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13036 {"arm7t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13037 {"arm7tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13038 {"arm7tdmi-s", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13039 {"arm8", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13040 {"arm810", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13041 {"strongarm", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13042 {"strongarm1", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13043 {"strongarm110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13044 {"strongarm1100", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13045 {"strongarm1110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13046 {"arm9", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13047 {"arm920", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13048 {"arm920t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13049 {"arm922t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13050 {"arm940t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13051 {"arm9tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13052 /* For V5 or later processors we default to using VFP; but the user
13053 should really set the FPU type explicitly. */
13054 {"arm9e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
13055 {"arm9e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13056 {"arm926ej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
13057 {"arm926ejs", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
13058 {"arm926ej-s", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
13059 {"arm946e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
13060 {"arm946e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13061 {"arm966e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
13062 {"arm966e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13063 {"arm10t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
13064 {"arm10e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13065 {"arm1020", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13066 {"arm1020t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
13067 {"arm1020e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13068 {"arm1026ejs", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
13069 {"arm1026ej-s", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
13070 {"arm1136js", ARM_ARCH_V6
, FPU_NONE
},
13071 {"arm1136j-s", ARM_ARCH_V6
, FPU_NONE
},
13072 {"arm1136jfs", ARM_ARCH_V6
, FPU_ARCH_VFP_V2
},
13073 {"arm1136jf-s", ARM_ARCH_V6
, FPU_ARCH_VFP_V2
},
13074 {"mpcore", ARM_ARCH_V6K
, FPU_ARCH_VFP_V2
},
13075 {"mpcorenovfp", ARM_ARCH_V6K
, FPU_NONE
},
13076 {"arm1176jz-s", ARM_ARCH_V6ZK
, FPU_NONE
},
13077 {"arm1176jzf-s", ARM_ARCH_V6ZK
, FPU_ARCH_VFP_V2
},
13078 /* ??? XSCALE is really an architecture. */
13079 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
13080 /* ??? iwmmxt is not a processor. */
13081 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP_V2
},
13082 {"i80200", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
13084 {"ep9312", ARM_ARCH_V4T
| ARM_CEXT_MAVERICK
, FPU_ARCH_MAVERICK
},
13088 struct arm_arch_option_table
13095 /* This list should, at a minimum, contain all the architecture names
13096 recognized by GCC. */
13097 static struct arm_arch_option_table arm_archs
[] =
13099 {"all", ARM_ANY
, FPU_ARCH_FPA
},
13100 {"armv1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
13101 {"armv2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
13102 {"armv2a", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
13103 {"armv2s", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
13104 {"armv3", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13105 {"armv3m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
13106 {"armv4", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13107 {"armv4xm", ARM_ARCH_V4xM
, FPU_ARCH_FPA
},
13108 {"armv4t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13109 {"armv4txm", ARM_ARCH_V4TxM
, FPU_ARCH_FPA
},
13110 {"armv5", ARM_ARCH_V5
, FPU_ARCH_VFP
},
13111 {"armv5t", ARM_ARCH_V5T
, FPU_ARCH_VFP
},
13112 {"armv5txm", ARM_ARCH_V5TxM
, FPU_ARCH_VFP
},
13113 {"armv5te", ARM_ARCH_V5TE
, FPU_ARCH_VFP
},
13114 {"armv5texp", ARM_ARCH_V5TExP
, FPU_ARCH_VFP
},
13115 {"armv5tej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP
},
13116 {"armv6", ARM_ARCH_V6
, FPU_ARCH_VFP
},
13117 {"armv6j", ARM_ARCH_V6
, FPU_ARCH_VFP
},
13118 {"armv6k", ARM_ARCH_V6K
, FPU_ARCH_VFP
},
13119 {"armv6z", ARM_ARCH_V6Z
, FPU_ARCH_VFP
},
13120 {"armv6zk", ARM_ARCH_V6ZK
, FPU_ARCH_VFP
},
13121 {"armv6t2", ARM_ARCH_V6T2
, FPU_ARCH_VFP
},
13122 {"armv6kt2", ARM_ARCH_V6KT2
, FPU_ARCH_VFP
},
13123 {"armv6zt2", ARM_ARCH_V6ZT2
, FPU_ARCH_VFP
},
13124 {"armv6zkt2", ARM_ARCH_V6ZKT2
, FPU_ARCH_VFP
},
13125 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP
},
13126 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP
},
13130 /* ISA extensions in the co-processor space. */
13131 struct arm_arch_extension_table
13137 static struct arm_arch_extension_table arm_extensions
[] =
13139 {"maverick", ARM_CEXT_MAVERICK
},
13140 {"xscale", ARM_CEXT_XSCALE
},
13141 {"iwmmxt", ARM_CEXT_IWMMXT
},
13145 struct arm_fpu_option_table
13151 /* This list should, at a minimum, contain all the fpu names
13152 recognized by GCC. */
13153 static struct arm_fpu_option_table arm_fpus
[] =
13155 {"softfpa", FPU_NONE
},
13156 {"fpe", FPU_ARCH_FPE
},
13157 {"fpe2", FPU_ARCH_FPE
},
13158 {"fpe3", FPU_ARCH_FPA
}, /* Third release supports LFM/SFM. */
13159 {"fpa", FPU_ARCH_FPA
},
13160 {"fpa10", FPU_ARCH_FPA
},
13161 {"fpa11", FPU_ARCH_FPA
},
13162 {"arm7500fe", FPU_ARCH_FPA
},
13163 {"softvfp", FPU_ARCH_VFP
},
13164 {"softvfp+vfp", FPU_ARCH_VFP_V2
},
13165 {"vfp", FPU_ARCH_VFP_V2
},
13166 {"vfp9", FPU_ARCH_VFP_V2
},
13167 {"vfp10", FPU_ARCH_VFP_V2
},
13168 {"vfp10-r0", FPU_ARCH_VFP_V1
},
13169 {"vfpxd", FPU_ARCH_VFP_V1xD
},
13170 {"arm1020t", FPU_ARCH_VFP_V1
},
13171 {"arm1020e", FPU_ARCH_VFP_V2
},
13172 {"arm1136jfs", FPU_ARCH_VFP_V2
},
13173 {"arm1136jf-s", FPU_ARCH_VFP_V2
},
13174 {"maverick", FPU_ARCH_MAVERICK
},
13178 struct arm_float_abi_option_table
13184 static struct arm_float_abi_option_table arm_float_abis
[] =
13186 {"hard", ARM_FLOAT_ABI_HARD
},
13187 {"softfp", ARM_FLOAT_ABI_SOFTFP
},
13188 {"soft", ARM_FLOAT_ABI_SOFT
},
13192 struct arm_eabi_option_table
13195 unsigned int value
;
13199 /* We only know how to output GNU and ver 4 (AAELF) formats. */
13200 static struct arm_eabi_option_table arm_eabis
[] =
13202 {"gnu", EF_ARM_EABI_UNKNOWN
},
13203 {"4", EF_ARM_EABI_VER4
},
13208 struct arm_long_option_table
13210 char * option
; /* Substring to match. */
13211 char * help
; /* Help information. */
13212 int (* func
) (char * subopt
); /* Function to decode sub-option. */
13213 char * deprecated
; /* If non-null, print this message. */
13217 arm_parse_extension (char * str
, int * opt_p
)
13219 while (str
!= NULL
&& *str
!= 0)
13221 struct arm_arch_extension_table
* opt
;
13227 as_bad (_("invalid architectural extension"));
13232 ext
= strchr (str
, '+');
13235 optlen
= ext
- str
;
13237 optlen
= strlen (str
);
13241 as_bad (_("missing architectural extension"));
13245 for (opt
= arm_extensions
; opt
->name
!= NULL
; opt
++)
13246 if (strncmp (opt
->name
, str
, optlen
) == 0)
13248 *opt_p
|= opt
->value
;
13252 if (opt
->name
== NULL
)
13254 as_bad (_("unknown architectural extnsion `%s'"), str
);
13265 arm_parse_cpu (char * str
)
13267 struct arm_cpu_option_table
* opt
;
13268 char * ext
= strchr (str
, '+');
13272 optlen
= ext
- str
;
13274 optlen
= strlen (str
);
13278 as_bad (_("missing cpu name `%s'"), str
);
13282 for (opt
= arm_cpus
; opt
->name
!= NULL
; opt
++)
13283 if (strncmp (opt
->name
, str
, optlen
) == 0)
13285 mcpu_cpu_opt
= opt
->value
;
13286 mcpu_fpu_opt
= opt
->default_fpu
;
13289 return arm_parse_extension (ext
, &mcpu_cpu_opt
);
13294 as_bad (_("unknown cpu `%s'"), str
);
13299 arm_parse_arch (char * str
)
13301 struct arm_arch_option_table
*opt
;
13302 char *ext
= strchr (str
, '+');
13306 optlen
= ext
- str
;
13308 optlen
= strlen (str
);
13312 as_bad (_("missing architecture name `%s'"), str
);
13317 for (opt
= arm_archs
; opt
->name
!= NULL
; opt
++)
13318 if (streq (opt
->name
, str
))
13320 march_cpu_opt
= opt
->value
;
13321 march_fpu_opt
= opt
->default_fpu
;
13324 return arm_parse_extension (ext
, &march_cpu_opt
);
13329 as_bad (_("unknown architecture `%s'\n"), str
);
13334 arm_parse_fpu (char * str
)
13336 struct arm_fpu_option_table
* opt
;
13338 for (opt
= arm_fpus
; opt
->name
!= NULL
; opt
++)
13339 if (streq (opt
->name
, str
))
13341 mfpu_opt
= opt
->value
;
13345 as_bad (_("unknown floating point format `%s'\n"), str
);
13350 arm_parse_float_abi (char * str
)
13352 struct arm_float_abi_option_table
* opt
;
13354 for (opt
= arm_float_abis
; opt
->name
!= NULL
; opt
++)
13355 if (streq (opt
->name
, str
))
13357 mfloat_abi_opt
= opt
->value
;
13361 as_bad (_("unknown floating point abi `%s'\n"), str
);
13367 arm_parse_eabi (char * str
)
13369 struct arm_eabi_option_table
*opt
;
13371 for (opt
= arm_eabis
; opt
->name
!= NULL
; opt
++)
13372 if (streq (opt
->name
, str
))
13374 meabi_flags
= opt
->value
;
13377 as_bad (_("unknown EABI `%s'\n"), str
);
13382 struct arm_long_option_table arm_long_opts
[] =
13384 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13385 arm_parse_cpu
, NULL
},
13386 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13387 arm_parse_arch
, NULL
},
13388 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13389 arm_parse_fpu
, NULL
},
13390 {"mfloat-abi=", N_("<abi>\t assemble for floating point ABI <abi>"),
13391 arm_parse_float_abi
, NULL
},
13393 {"meabi=", N_("<ver>\t assemble for eabi version <ver>"),
13394 arm_parse_eabi
, NULL
},
13396 {NULL
, NULL
, 0, NULL
}
13400 md_parse_option (int c
, char * arg
)
13402 struct arm_option_table
*opt
;
13403 struct arm_long_option_table
*lopt
;
13409 target_big_endian
= 1;
13415 target_big_endian
= 0;
13420 /* Listing option. Just ignore these, we don't support additional
13425 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
13427 if (c
== opt
->option
[0]
13428 && ((arg
== NULL
&& opt
->option
[1] == 0)
13429 || streq (arg
, opt
->option
+ 1)))
13431 #if WARN_DEPRECATED
13432 /* If the option is deprecated, tell the user. */
13433 if (opt
->deprecated
!= NULL
)
13434 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
,
13435 arg
? arg
: "", _(opt
->deprecated
));
13438 if (opt
->var
!= NULL
)
13439 *opt
->var
= opt
->value
;
13445 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
13447 /* These options are expected to have an argument. */
13448 if (c
== lopt
->option
[0]
13450 && strncmp (arg
, lopt
->option
+ 1,
13451 strlen (lopt
->option
+ 1)) == 0)
13453 #if WARN_DEPRECATED
13454 /* If the option is deprecated, tell the user. */
13455 if (lopt
->deprecated
!= NULL
)
13456 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
, arg
,
13457 _(lopt
->deprecated
));
13460 /* Call the sup-option parser. */
13461 return lopt
->func (arg
+ strlen (lopt
->option
) - 1);
13472 md_show_usage (FILE * fp
)
13474 struct arm_option_table
*opt
;
13475 struct arm_long_option_table
*lopt
;
13477 fprintf (fp
, _(" ARM-specific assembler options:\n"));
13479 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
13480 if (opt
->help
!= NULL
)
13481 fprintf (fp
, " -%-23s%s\n", opt
->option
, _(opt
->help
));
13483 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
13484 if (lopt
->help
!= NULL
)
13485 fprintf (fp
, " -%s%s\n", lopt
->option
, _(lopt
->help
));
13489 -EB assemble code for a big-endian cpu\n"));
13494 -EL assemble code for a little-endian cpu\n"));
13498 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13501 cons_fix_new_arm (fragS
* frag
,
13506 bfd_reloc_code_real_type type
;
13510 FIXME: @@ Should look at CPU word size. */
13514 type
= BFD_RELOC_8
;
13517 type
= BFD_RELOC_16
;
13521 type
= BFD_RELOC_32
;
13524 type
= BFD_RELOC_64
;
13528 fix_new_exp (frag
, where
, (int) size
, exp
, pcrel
, type
);
13531 /* A good place to do this, although this was probably not intended
13532 for this kind of use. We need to dump the literal pool before
13533 references are made to a null symbol pointer. */
13538 literal_pool
* pool
;
13540 for (pool
= list_of_pools
; pool
; pool
= pool
->next
)
13542 /* Put it at the end of the relevent section. */
13543 subseg_set (pool
->section
, pool
->sub_section
);
13545 arm_elf_change_section ();
13552 arm_start_line_hook (void)
13554 last_label_seen
= NULL
;
13558 arm_frob_label (symbolS
* sym
)
13560 last_label_seen
= sym
;
13562 ARM_SET_THUMB (sym
, thumb_mode
);
13564 #if defined OBJ_COFF || defined OBJ_ELF
13565 ARM_SET_INTERWORK (sym
, support_interwork
);
13568 /* Note - do not allow local symbols (.Lxxx) to be labeled
13569 as Thumb functions. This is because these labels, whilst
13570 they exist inside Thumb code, are not the entry points for
13571 possible ARM->Thumb calls. Also, these labels can be used
13572 as part of a computed goto or switch statement. eg gcc
13573 can generate code that looks like this:
13575 ldr r2, [pc, .Laaa]
13585 The first instruction loads the address of the jump table.
13586 The second instruction converts a table index into a byte offset.
13587 The third instruction gets the jump address out of the table.
13588 The fourth instruction performs the jump.
13590 If the address stored at .Laaa is that of a symbol which has the
13591 Thumb_Func bit set, then the linker will arrange for this address
13592 to have the bottom bit set, which in turn would mean that the
13593 address computation performed by the third instruction would end
13594 up with the bottom bit set. Since the ARM is capable of unaligned
13595 word loads, the instruction would then load the incorrect address
13596 out of the jump table, and chaos would ensue. */
13597 if (label_is_thumb_function_name
13598 && (S_GET_NAME (sym
)[0] != '.' || S_GET_NAME (sym
)[1] != 'L')
13599 && (bfd_get_section_flags (stdoutput
, now_seg
) & SEC_CODE
) != 0)
13601 /* When the address of a Thumb function is taken the bottom
13602 bit of that address should be set. This will allow
13603 interworking between Arm and Thumb functions to work
13606 THUMB_SET_FUNC (sym
, 1);
13608 label_is_thumb_function_name
= FALSE
;
13612 /* Adjust the symbol table. This marks Thumb symbols as distinct from
13616 arm_adjust_symtab (void)
13621 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
13623 if (ARM_IS_THUMB (sym
))
13625 if (THUMB_IS_FUNC (sym
))
13627 /* Mark the symbol as a Thumb function. */
13628 if ( S_GET_STORAGE_CLASS (sym
) == C_STAT
13629 || S_GET_STORAGE_CLASS (sym
) == C_LABEL
) /* This can happen! */
13630 S_SET_STORAGE_CLASS (sym
, C_THUMBSTATFUNC
);
13632 else if (S_GET_STORAGE_CLASS (sym
) == C_EXT
)
13633 S_SET_STORAGE_CLASS (sym
, C_THUMBEXTFUNC
);
13635 as_bad (_("%s: unexpected function type: %d"),
13636 S_GET_NAME (sym
), S_GET_STORAGE_CLASS (sym
));
13638 else switch (S_GET_STORAGE_CLASS (sym
))
13641 S_SET_STORAGE_CLASS (sym
, C_THUMBEXT
);
13644 S_SET_STORAGE_CLASS (sym
, C_THUMBSTAT
);
13647 S_SET_STORAGE_CLASS (sym
, C_THUMBLABEL
);
13655 if (ARM_IS_INTERWORK (sym
))
13656 coffsymbol (symbol_get_bfdsym (sym
))->native
->u
.syment
.n_flags
= 0xFF;
13663 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
13665 if (ARM_IS_THUMB (sym
))
13667 elf_symbol_type
* elf_sym
;
13669 elf_sym
= elf_symbol (symbol_get_bfdsym (sym
));
13670 bind
= ELF_ST_BIND (elf_sym
->internal_elf_sym
.st_info
);
13672 if (! bfd_is_arm_mapping_symbol_name (elf_sym
->symbol
.name
))
13674 /* If it's a .thumb_func, declare it as so,
13675 otherwise tag label as .code 16. */
13676 if (THUMB_IS_FUNC (sym
))
13677 elf_sym
->internal_elf_sym
.st_info
=
13678 ELF_ST_INFO (bind
, STT_ARM_TFUNC
);
13680 elf_sym
->internal_elf_sym
.st_info
=
13681 ELF_ST_INFO (bind
, STT_ARM_16BIT
);
13689 arm_data_in_code (void)
13691 if (thumb_mode
&& ! strncmp (input_line_pointer
+ 1, "data:", 5))
13693 *input_line_pointer
= '/';
13694 input_line_pointer
+= 5;
13695 *input_line_pointer
= 0;
13703 arm_canonicalize_symbol_name (char * name
)
13707 if (thumb_mode
&& (len
= strlen (name
)) > 5
13708 && streq (name
+ len
- 5, "/data"))
13709 *(name
+ len
- 5) = 0;
13714 #if defined OBJ_COFF || defined OBJ_ELF
13716 arm_validate_fix (fixS
* fixP
)
13718 /* If the destination of the branch is a defined symbol which does not have
13719 the THUMB_FUNC attribute, then we must be calling a function which has
13720 the (interfacearm) attribute. We look for the Thumb entry point to that
13721 function and change the branch to refer to that function instead. */
13722 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
13723 && fixP
->fx_addsy
!= NULL
13724 && S_IS_DEFINED (fixP
->fx_addsy
)
13725 && ! THUMB_IS_FUNC (fixP
->fx_addsy
))
13727 fixP
->fx_addsy
= find_real_start (fixP
->fx_addsy
);
13733 arm_force_relocation (struct fix
* fixp
)
13735 #if defined (OBJ_COFF) && defined (TE_PE)
13736 if (fixp
->fx_r_type
== BFD_RELOC_RVA
)
13740 if (fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
13741 || fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
13742 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
13743 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
)
13747 /* Resolve these relocations even if the symbol is extern or weak. */
13748 if (fixp
->fx_r_type
== BFD_RELOC_ARM_IMMEDIATE
13749 || fixp
->fx_r_type
== BFD_RELOC_ARM_OFFSET_IMM
13750 || fixp
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
13753 return generic_force_reloc (fixp
);
13757 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
13758 local labels from being added to the output symbol table when they
13759 are used with the ADRL pseudo op. The ADRL relocation should always
13760 be resolved before the binbary is emitted, so it is safe to say that
13761 it is adjustable. */
13764 arm_fix_adjustable (fixS
* fixP
)
13766 if (fixP
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
13773 /* Relocations against Thumb function names must be left unadjusted,
13774 so that the linker can use this information to correctly set the
13775 bottom bit of their addresses. The MIPS version of this function
13776 also prevents relocations that are mips-16 specific, but I do not
13777 know why it does this.
13780 There is one other problem that ought to be addressed here, but
13781 which currently is not: Taking the address of a label (rather
13782 than a function) and then later jumping to that address. Such
13783 addresses also ought to have their bottom bit set (assuming that
13784 they reside in Thumb code), but at the moment they will not. */
13787 arm_fix_adjustable (fixS
* fixP
)
13789 if (fixP
->fx_addsy
== NULL
)
13792 if (THUMB_IS_FUNC (fixP
->fx_addsy
)
13793 && fixP
->fx_subsy
== NULL
)
13796 /* We need the symbol name for the VTABLE entries. */
13797 if ( fixP
->fx_r_type
== BFD_RELOC_VTABLE_INHERIT
13798 || fixP
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
13801 /* Don't allow symbols to be discarded on GOT related relocs. */
13802 if (fixP
->fx_r_type
== BFD_RELOC_ARM_PLT32
13803 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOT32
13804 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOTOFF
13805 || fixP
->fx_r_type
== BFD_RELOC_ARM_TLS_GD32
13806 || fixP
->fx_r_type
== BFD_RELOC_ARM_TLS_LE32
13807 || fixP
->fx_r_type
== BFD_RELOC_ARM_TLS_IE32
13808 || fixP
->fx_r_type
== BFD_RELOC_ARM_TLS_LDM32
13809 || fixP
->fx_r_type
== BFD_RELOC_ARM_TLS_LDO32
13810 || fixP
->fx_r_type
== BFD_RELOC_ARM_TARGET2
)
13817 elf32_arm_target_format (void)
13820 return (target_big_endian
13821 ? "elf32-bigarm-symbian"
13822 : "elf32-littlearm-symbian");
13823 #elif defined (TE_VXWORKS)
13824 return (target_big_endian
13825 ? "elf32-bigarm-vxworks"
13826 : "elf32-littlearm-vxworks");
13828 if (target_big_endian
)
13829 return "elf32-bigarm";
13831 return "elf32-littlearm";
13836 armelf_frob_symbol (symbolS
* symp
,
13839 elf_frob_symbol (symp
, puntp
);
13843 s_arm_elf_cons (int nbytes
)
13847 #ifdef md_flush_pending_output
13848 md_flush_pending_output ();
13851 if (is_it_end_of_statement ())
13853 demand_empty_rest_of_line ();
13857 #ifdef md_cons_align
13858 md_cons_align (nbytes
);
13861 mapping_state (MAP_DATA
);
13864 bfd_reloc_code_real_type reloc
;
13868 sym_start
= input_line_pointer
;
13869 expression (& exp
);
13870 sym_len
= input_line_pointer
- sym_start
;
13872 if (exp
.X_op
== O_symbol
13873 && * input_line_pointer
== '('
13874 && (reloc
= arm_parse_reloc ()) != BFD_RELOC_UNUSED
)
13876 reloc_howto_type
*howto
= bfd_reloc_type_lookup (stdoutput
, reloc
);
13877 int size
= bfd_get_reloc_size (howto
);
13880 as_bad ("%s relocations do not fit in %d bytes",
13881 howto
->name
, nbytes
);
13885 int offset
= nbytes
- size
;
13886 char *saved_buf
= alloca (sym_len
), *saved_input
;
13888 /* We've parsed an expression stopping at O_symbol. But there
13889 may be more expression left now that we have parsed the
13890 relocation marker. Parse it again. */
13891 saved_input
= input_line_pointer
- sym_len
;
13892 memcpy (saved_buf
, saved_input
, sym_len
);
13893 memmove (saved_input
, sym_start
, sym_len
);
13894 input_line_pointer
= saved_input
;
13895 expression (& exp
);
13896 memcpy (saved_input
, saved_buf
, sym_len
);
13897 assert (input_line_pointer
>= saved_input
+ sym_len
);
13899 p
= frag_more ((int) nbytes
);
13900 fix_new_exp (frag_now
, p
- frag_now
->fr_literal
+ offset
, size
,
13905 emit_expr (&exp
, (unsigned int) nbytes
);
13907 while (*input_line_pointer
++ == ',');
13909 /* Put terminator back into stream. */
13910 input_line_pointer
--;
13911 demand_empty_rest_of_line ();
13915 /* Parse a .rel31 directive. */
13918 s_arm_rel31 (int ignored ATTRIBUTE_UNUSED
)
13924 SKIP_WHITESPACE ();
13927 if (*input_line_pointer
== '1')
13928 highbit
= 0x80000000;
13929 else if (*input_line_pointer
!= '0')
13930 as_bad (_("expected 0 or 1"));
13932 input_line_pointer
++;
13933 SKIP_WHITESPACE ();
13934 if (*input_line_pointer
!= ',')
13935 as_bad (_("missing comma"));
13936 input_line_pointer
++;
13938 #ifdef md_flush_pending_output
13939 md_flush_pending_output ();
13942 #ifdef md_cons_align
13946 mapping_state (MAP_DATA
);
13951 md_number_to_chars (p
, highbit
, 4);
13952 fix_new_arm (frag_now
, p
- frag_now
->fr_literal
, 4, &exp
, 1,
13953 BFD_RELOC_ARM_PREL31
);
13955 demand_empty_rest_of_line ();
13958 /* Code to deal with unwinding tables. */
13960 static void add_unwind_adjustsp (offsetT
);
13962 /* Switch to section NAME and create section if necessary. It's
13963 rather ugly that we have to manipulate input_line_pointer but I
13964 don't see any other way to accomplish the same thing without
13965 changing obj-elf.c (which may be the Right Thing, in the end).
13966 Copied from tc-ia64.c. */
13969 set_section (char *name
)
13971 char *saved_input_line_pointer
;
13973 saved_input_line_pointer
= input_line_pointer
;
13974 input_line_pointer
= name
;
13975 obj_elf_section (0);
13976 input_line_pointer
= saved_input_line_pointer
;
13979 /* Cenerate and deferred unwind frame offset. */
13982 flush_pending_unwind (void)
13986 offset
= unwind
.pending_offset
;
13987 unwind
.pending_offset
= 0;
13989 add_unwind_adjustsp (offset
);
13992 /* Add an opcode to this list for this function. Two-byte opcodes should
13993 be passed as op[0] << 8 | op[1]. The list of opcodes is built in reverse
13997 add_unwind_opcode (valueT op
, int length
)
13999 /* Add any deferred stack adjustment. */
14000 if (unwind
.pending_offset
)
14001 flush_pending_unwind ();
14003 unwind
.sp_restored
= 0;
14005 if (unwind
.opcode_count
+ length
> unwind
.opcode_alloc
)
14007 unwind
.opcode_alloc
+= ARM_OPCODE_CHUNK_SIZE
;
14008 if (unwind
.opcodes
)
14009 unwind
.opcodes
= xrealloc (unwind
.opcodes
,
14010 unwind
.opcode_alloc
);
14012 unwind
.opcodes
= xmalloc (unwind
.opcode_alloc
);
14017 unwind
.opcodes
[unwind
.opcode_count
] = op
& 0xff;
14019 unwind
.opcode_count
++;
14023 /* Add unwind opcodes to adjust the stack pointer. */
14026 add_unwind_adjustsp (offsetT offset
)
14030 if (offset
> 0x200)
14032 /* We need at most 5 bytes to hold a 32-bit value in a uleb128. */
14037 /* Long form: 0xb2, uleb128. */
14038 /* This might not fit in a word so add the individual bytes,
14039 remembering the list is built in reverse order. */
14040 o
= (valueT
) ((offset
- 0x204) >> 2);
14042 add_unwind_opcode (0, 1);
14044 /* Calculate the uleb128 encoding of the offset. */
14048 bytes
[n
] = o
& 0x7f;
14054 /* Add the insn. */
14056 add_unwind_opcode (bytes
[n
- 1], 1);
14057 add_unwind_opcode (0xb2, 1);
14059 else if (offset
> 0x100)
14061 /* Two short opcodes. */
14062 add_unwind_opcode (0x3f, 1);
14063 op
= (offset
- 0x104) >> 2;
14064 add_unwind_opcode (op
, 1);
14066 else if (offset
> 0)
14068 /* Short opcode. */
14069 op
= (offset
- 4) >> 2;
14070 add_unwind_opcode (op
, 1);
14072 else if (offset
< 0)
14075 while (offset
> 0x100)
14077 add_unwind_opcode (0x7f, 1);
14080 op
= ((offset
- 4) >> 2) | 0x40;
14081 add_unwind_opcode (op
, 1);
14085 /* Finish the list of unwind opcodes for this function. */
14087 finish_unwind_opcodes (void)
14091 if (unwind
.fp_used
)
14093 /* Adjust sp as neccessary. */
14094 unwind
.pending_offset
+= unwind
.fp_offset
- unwind
.frame_size
;
14095 flush_pending_unwind ();
14097 /* After restoring sp from the frame pointer. */
14098 op
= 0x90 | unwind
.fp_reg
;
14099 add_unwind_opcode (op
, 1);
14102 flush_pending_unwind ();
14106 /* Start an exception table entry. If idx is nonzero this is an index table
14110 start_unwind_section (const segT text_seg
, int idx
)
14112 const char * text_name
;
14113 const char * prefix
;
14114 const char * prefix_once
;
14118 size_t sec_name_len
;
14122 prefix
= ELF_STRING_ARM_unwind
;
14123 prefix_once
= ELF_STRING_ARM_unwind_once
;
14127 prefix
= ELF_STRING_ARM_unwind_info
;
14128 prefix_once
= ELF_STRING_ARM_unwind_info_once
;
14131 text_name
= segment_name (text_seg
);
14132 if (streq (text_name
, ".text"))
14135 if (strncmp (text_name
, ".gnu.linkonce.t.",
14136 strlen (".gnu.linkonce.t.")) == 0)
14138 prefix
= prefix_once
;
14139 text_name
+= strlen (".gnu.linkonce.t.");
14142 prefix_len
= strlen (prefix
);
14143 text_len
= strlen (text_name
);
14144 sec_name_len
= prefix_len
+ text_len
;
14145 sec_name
= alloca (sec_name_len
+ 1);
14146 memcpy (sec_name
, prefix
, prefix_len
);
14147 memcpy (sec_name
+ prefix_len
, text_name
, text_len
);
14148 sec_name
[prefix_len
+ text_len
] = '\0';
14150 /* Handle COMDAT group. */
14151 if (prefix
!= prefix_once
&& (text_seg
->flags
& SEC_LINK_ONCE
) != 0)
14154 size_t len
, group_name_len
;
14155 const char *group_name
= elf_group_name (text_seg
);
14157 if (group_name
== NULL
)
14159 as_bad ("Group section `%s' has no group signature",
14160 segment_name (text_seg
));
14161 ignore_rest_of_line ();
14164 /* We have to construct a fake section directive. */
14165 group_name_len
= strlen (group_name
);
14171 len
= (sec_name_len
14172 + prefix_len
/* ,"aG",%sectiontype, */
14173 + group_name_len
/* ,group_name */
14174 + 7); /* ,comdat */
14176 section
= alloca (len
+ 1);
14177 memcpy (section
, sec_name
, sec_name_len
);
14179 memcpy (section
+ sec_name_len
, ",\"aG\",%exidx,", 13);
14181 memcpy (section
+ sec_name_len
, ",\"aG\",%progbits,", 16);
14182 memcpy (section
+ sec_name_len
+ prefix_len
, group_name
, group_name_len
);
14183 memcpy (section
+ len
- 7, ",comdat", 7);
14184 section
[len
] = '\0';
14185 set_section (section
);
14189 set_section (sec_name
);
14190 bfd_set_section_flags (stdoutput
, now_seg
,
14191 SEC_LOAD
| SEC_ALLOC
| SEC_READONLY
);
14194 /* Set the setion link for index tables. */
14196 elf_linked_to_section (now_seg
) = text_seg
;
14200 /* Start an unwind table entry. HAVE_DATA is nonzero if we have additional
14201 personality routine data. Returns zero, or the index table value for
14202 and inline entry. */
14205 create_unwind_entry (int have_data
)
14210 /* The current word of data. */
14212 /* The number of bytes left in this word. */
14215 finish_unwind_opcodes ();
14217 /* Remember the current text section. */
14218 unwind
.saved_seg
= now_seg
;
14219 unwind
.saved_subseg
= now_subseg
;
14221 start_unwind_section (now_seg
, 0);
14223 if (unwind
.personality_routine
== NULL
)
14225 if (unwind
.personality_index
== -2)
14228 as_bad (_("handerdata in cantunwind frame"));
14229 return 1; /* EXIDX_CANTUNWIND. */
14232 /* Use a default personality routine if none is specified. */
14233 if (unwind
.personality_index
== -1)
14235 if (unwind
.opcode_count
> 3)
14236 unwind
.personality_index
= 1;
14238 unwind
.personality_index
= 0;
14241 /* Space for the personality routine entry. */
14242 if (unwind
.personality_index
== 0)
14244 if (unwind
.opcode_count
> 3)
14245 as_bad (_("too many unwind opcodes for personality routine 0"));
14249 /* All the data is inline in the index table. */
14252 while (unwind
.opcode_count
> 0)
14254 unwind
.opcode_count
--;
14255 data
= (data
<< 8) | unwind
.opcodes
[unwind
.opcode_count
];
14259 /* Pad with "finish" opcodes. */
14261 data
= (data
<< 8) | 0xb0;
14268 /* We get two opcodes "free" in the first word. */
14269 size
= unwind
.opcode_count
- 2;
14272 /* An extra byte is required for the opcode count. */
14273 size
= unwind
.opcode_count
+ 1;
14275 size
= (size
+ 3) >> 2;
14277 as_bad (_("too many unwind opcodes"));
14279 frag_align (2, 0, 0);
14280 record_alignment (now_seg
, 2);
14281 unwind
.table_entry
= expr_build_dot ();
14283 /* Allocate the table entry. */
14284 ptr
= frag_more ((size
<< 2) + 4);
14285 where
= frag_now_fix () - ((size
<< 2) + 4);
14287 switch (unwind
.personality_index
)
14290 /* ??? Should this be a PLT generating relocation? */
14291 /* Custom personality routine. */
14292 fix_new (frag_now
, where
, 4, unwind
.personality_routine
, 0, 1,
14293 BFD_RELOC_ARM_PREL31
);
14298 /* Set the first byte to the number of additional words. */
14303 /* ABI defined personality routines. */
14305 /* Three opcodes bytes are packed into the first word. */
14312 /* The size and first two opcode bytes go in the first word. */
14313 data
= ((0x80 + unwind
.personality_index
) << 8) | size
;
14318 /* Should never happen. */
14322 /* Pack the opcodes into words (MSB first), reversing the list at the same
14324 while (unwind
.opcode_count
> 0)
14328 md_number_to_chars (ptr
, data
, 4);
14333 unwind
.opcode_count
--;
14335 data
= (data
<< 8) | unwind
.opcodes
[unwind
.opcode_count
];
14338 /* Finish off the last word. */
14341 /* Pad with "finish" opcodes. */
14343 data
= (data
<< 8) | 0xb0;
14345 md_number_to_chars (ptr
, data
, 4);
14350 /* Add an empty descriptor if there is no user-specified data. */
14351 ptr
= frag_more (4);
14352 md_number_to_chars (ptr
, 0, 4);
14359 /* Parse an unwind_fnstart directive. Simply records the current location. */
14362 s_arm_unwind_fnstart (int ignored ATTRIBUTE_UNUSED
)
14364 demand_empty_rest_of_line ();
14365 /* Mark the start of the function. */
14366 unwind
.proc_start
= expr_build_dot ();
14368 /* Reset the rest of the unwind info. */
14369 unwind
.opcode_count
= 0;
14370 unwind
.table_entry
= NULL
;
14371 unwind
.personality_routine
= NULL
;
14372 unwind
.personality_index
= -1;
14373 unwind
.frame_size
= 0;
14374 unwind
.fp_offset
= 0;
14375 unwind
.fp_reg
= 13;
14376 unwind
.fp_used
= 0;
14377 unwind
.sp_restored
= 0;
14381 /* Parse a handlerdata directive. Creates the exception handling table entry
14382 for the function. */
14385 s_arm_unwind_handlerdata (int ignored ATTRIBUTE_UNUSED
)
14387 demand_empty_rest_of_line ();
14388 if (unwind
.table_entry
)
14389 as_bad (_("dupicate .handlerdata directive"));
14391 create_unwind_entry (1);
14394 /* Parse an unwind_fnend directive. Generates the index table entry. */
14397 s_arm_unwind_fnend (int ignored ATTRIBUTE_UNUSED
)
14403 demand_empty_rest_of_line ();
14405 /* Add eh table entry. */
14406 if (unwind
.table_entry
== NULL
)
14407 val
= create_unwind_entry (0);
14411 /* Add index table entry. This is two words. */
14412 start_unwind_section (unwind
.saved_seg
, 1);
14413 frag_align (2, 0, 0);
14414 record_alignment (now_seg
, 2);
14416 ptr
= frag_more (8);
14417 where
= frag_now_fix () - 8;
14419 /* Self relative offset of the function start. */
14420 fix_new (frag_now
, where
, 4, unwind
.proc_start
, 0, 1,
14421 BFD_RELOC_ARM_PREL31
);
14423 /* Indicate dependency on EHABI-defined personality routines to the
14424 linker, if it hasn't been done already. */
14425 if (unwind
.personality_index
>= 0 && unwind
.personality_index
< 3)
14427 char *name
[] = { "__aeabi_unwind_cpp_pr0",
14428 "__aeabi_unwind_cpp_pr1",
14429 "__aeabi_unwind_cpp_pr2" };
14430 if (!(marked_pr_dependency
& (1 << unwind
.personality_index
)))
14432 symbolS
*pr
= symbol_find_or_make (name
[unwind
.personality_index
]);
14433 fix_new (frag_now
, where
, 0, pr
, 0, 1, BFD_RELOC_NONE
);
14434 marked_pr_dependency
|= 1 << unwind
.personality_index
;
14435 seg_info (now_seg
)->tc_segment_info_data
.marked_pr_dependency
14436 = marked_pr_dependency
;
14441 /* Inline exception table entry. */
14442 md_number_to_chars (ptr
+ 4, val
, 4);
14444 /* Self relative offset of the table entry. */
14445 fix_new (frag_now
, where
+ 4, 4, unwind
.table_entry
, 0, 1,
14446 BFD_RELOC_ARM_PREL31
);
14448 /* Restore the original section. */
14449 subseg_set (unwind
.saved_seg
, unwind
.saved_subseg
);
14453 /* Parse an unwind_cantunwind directive. */
14456 s_arm_unwind_cantunwind (int ignored ATTRIBUTE_UNUSED
)
14458 demand_empty_rest_of_line ();
14459 if (unwind
.personality_routine
|| unwind
.personality_index
!= -1)
14460 as_bad (_("personality routine specified for cantunwind frame"));
14462 unwind
.personality_index
= -2;
14466 /* Parse a personalityindex directive. */
14469 s_arm_unwind_personalityindex (int ignored ATTRIBUTE_UNUSED
)
14473 if (unwind
.personality_routine
|| unwind
.personality_index
!= -1)
14474 as_bad (_("duplicate .personalityindex directive"));
14476 SKIP_WHITESPACE ();
14480 if (exp
.X_op
!= O_constant
14481 || exp
.X_add_number
< 0 || exp
.X_add_number
> 15)
14483 as_bad (_("bad personality routine number"));
14484 ignore_rest_of_line ();
14488 unwind
.personality_index
= exp
.X_add_number
;
14490 demand_empty_rest_of_line ();
14494 /* Parse a personality directive. */
14497 s_arm_unwind_personality (int ignored ATTRIBUTE_UNUSED
)
14501 if (unwind
.personality_routine
|| unwind
.personality_index
!= -1)
14502 as_bad (_("duplicate .personality directive"));
14504 SKIP_WHITESPACE ();
14505 name
= input_line_pointer
;
14506 c
= get_symbol_end ();
14507 p
= input_line_pointer
;
14508 unwind
.personality_routine
= symbol_find_or_make (name
);
14510 SKIP_WHITESPACE ();
14511 demand_empty_rest_of_line ();
14515 /* Parse a directive saving core registers. */
14518 s_arm_unwind_save_core (void)
14524 SKIP_WHITESPACE ();
14525 range
= reg_list (&input_line_pointer
);
14528 as_bad (_("expected register list"));
14529 ignore_rest_of_line ();
14533 demand_empty_rest_of_line ();
14535 /* Turn .unwind_movsp ip followed by .unwind_save {..., ip, ...}
14536 into .unwind_save {..., sp...}. We aren't bothered about the value of
14537 ip because it is clobbered by calls. */
14538 if (unwind
.sp_restored
&& unwind
.fp_reg
== 12
14539 && (range
& 0x3000) == 0x1000)
14541 unwind
.opcode_count
--;
14542 unwind
.sp_restored
= 0;
14543 range
= (range
| 0x2000) & ~0x1000;
14544 unwind
.pending_offset
= 0;
14547 /* See if we can use the short opcodes. These pop a block of upto 8
14548 registers starting with r4, plus maybe r14. */
14549 for (n
= 0; n
< 8; n
++)
14551 /* Break at the first non-saved register. */
14552 if ((range
& (1 << (n
+ 4))) == 0)
14555 /* See if there are any other bits set. */
14556 if (n
== 0 || (range
& (0xfff0 << n
) & 0xbff0) != 0)
14558 /* Use the long form. */
14559 op
= 0x8000 | ((range
>> 4) & 0xfff);
14560 add_unwind_opcode (op
, 2);
14564 /* Use the short form. */
14565 if (range
& 0x4000)
14566 op
= 0xa8; /* Pop r14. */
14568 op
= 0xa0; /* Do not pop r14. */
14570 add_unwind_opcode (op
, 1);
14576 op
= 0xb100 | (range
& 0xf);
14577 add_unwind_opcode (op
, 2);
14580 /* Record the number of bytes pushed. */
14581 for (n
= 0; n
< 16; n
++)
14583 if (range
& (1 << n
))
14584 unwind
.frame_size
+= 4;
14589 /* Parse a directive saving FPA registers. */
14592 s_arm_unwind_save_fpa (int reg
)
14598 /* Get Number of registers to transfer. */
14599 if (skip_past_comma (&input_line_pointer
) != FAIL
)
14602 exp
.X_op
= O_illegal
;
14604 if (exp
.X_op
!= O_constant
)
14606 as_bad (_("expected , <constant>"));
14607 ignore_rest_of_line ();
14611 num_regs
= exp
.X_add_number
;
14613 if (num_regs
< 1 || num_regs
> 4)
14615 as_bad (_("number of registers must be in the range [1:4]"));
14616 ignore_rest_of_line ();
14620 demand_empty_rest_of_line ();
14625 op
= 0xb4 | (num_regs
- 1);
14626 add_unwind_opcode (op
, 1);
14631 op
= 0xc800 | (reg
<< 4) | (num_regs
- 1);
14632 add_unwind_opcode (op
, 2);
14634 unwind
.frame_size
+= num_regs
* 12;
14638 /* Parse a directive saving VFP registers. */
14641 s_arm_unwind_save_vfp (void)
14647 count
= vfp_parse_reg_list (&input_line_pointer
, ®
, 1);
14650 as_bad (_("expected register list"));
14651 ignore_rest_of_line ();
14655 demand_empty_rest_of_line ();
14660 op
= 0xb8 | (count
- 1);
14661 add_unwind_opcode (op
, 1);
14666 op
= 0xb300 | (reg
<< 4) | (count
- 1);
14667 add_unwind_opcode (op
, 2);
14669 unwind
.frame_size
+= count
* 8 + 4;
14673 /* Parse a directive saving iWMMXt registers. */
14676 s_arm_unwind_save_wmmx (void)
14685 if (*input_line_pointer
== '{')
14686 input_line_pointer
++;
14692 reg
= arm_reg_parse (&input_line_pointer
,
14693 all_reg_maps
[REG_TYPE_IWMMXT
].htab
);
14695 if (wr_register (reg
))
14697 i
= reg
& ~WR_PREFIX
;
14699 as_tsktsk (_("register list not in ascending order"));
14702 else if (wcg_register (reg
))
14704 i
= (reg
& ~WC_PREFIX
) - 8;
14706 as_tsktsk (_("register list not in ascending order"));
14707 wcg_mask
|= 1 << i
;
14711 as_bad (_("expected wr or wcgr"));
14715 SKIP_WHITESPACE ();
14716 if (*input_line_pointer
== '-')
14718 hi_reg
= arm_reg_parse (&input_line_pointer
,
14719 all_reg_maps
[REG_TYPE_IWMMXT
].htab
);
14720 if (wr_register (reg
) && wr_register (hi_reg
))
14722 for (; reg
< hi_reg
; reg
++)
14723 wr_mask
|= 1 << (reg
& ~WR_PREFIX
);
14725 else if (wcg_register (reg
) && wcg_register (hi_reg
))
14727 for (; reg
< hi_reg
; reg
++)
14728 wcg_mask
|= 1 << ((reg
& ~WC_PREFIX
) - 8);
14732 as_bad (_("bad register range"));
14737 while (skip_past_comma (&input_line_pointer
) != FAIL
);
14739 SKIP_WHITESPACE ();
14740 if (*input_line_pointer
== '}')
14741 input_line_pointer
++;
14743 demand_empty_rest_of_line ();
14745 if (wr_mask
&& wcg_mask
)
14747 as_bad (_("inconsistent register types"));
14751 /* Generate any deferred opcodes becuuse we're going to be looking at
14753 flush_pending_unwind ();
14757 for (i
= 0; i
< 16; i
++)
14759 if (wcg_mask
& (1 << i
))
14760 unwind
.frame_size
+= 4;
14762 op
= 0xc700 | wcg_mask
;
14763 add_unwind_opcode (op
, 2);
14767 for (i
= 0; i
< 16; i
++)
14769 if (wr_mask
& (1 << i
))
14770 unwind
.frame_size
+= 8;
14772 /* Attempt to combine with a previous opcode. We do this because gcc
14773 likes to output separate unwind directives for a single block of
14775 if (unwind
.opcode_count
> 0)
14777 i
= unwind
.opcodes
[unwind
.opcode_count
- 1];
14778 if ((i
& 0xf8) == 0xc0)
14781 /* Only merge if the blocks are contiguous. */
14784 if ((wr_mask
& 0xfe00) == (1 << 9))
14786 wr_mask
|= ((1 << (i
+ 11)) - 1) & 0xfc00;
14787 unwind
.opcode_count
--;
14790 else if (i
== 6 && unwind
.opcode_count
>= 2)
14792 i
= unwind
.opcodes
[unwind
.opcode_count
- 2];
14796 op
= 0xffff << (reg
- 1);
14798 || ((wr_mask
& op
) == (1u << (reg
- 1))))
14800 op
= (1 << (reg
+ i
+ 1)) - 1;
14801 op
&= ~((1 << reg
) - 1);
14803 unwind
.opcode_count
-= 2;
14810 /* We want to generate opcodes in the order the registers have been
14811 saved, ie. descending order. */
14812 for (reg
= 15; reg
>= -1; reg
--)
14814 /* Save registers in blocks. */
14816 || !(wr_mask
& (1 << reg
)))
14818 /* We found an unsaved reg. Generate opcodes to save the
14819 preceeding block. */
14825 op
= 0xc0 | (hi_reg
- 10);
14826 add_unwind_opcode (op
, 1);
14831 op
= 0xc600 | ((reg
+ 1) << 4) | ((hi_reg
- reg
) - 1);
14832 add_unwind_opcode (op
, 2);
14841 ignore_rest_of_line ();
14845 /* Parse an unwind_save directive. */
14848 s_arm_unwind_save (int ignored ATTRIBUTE_UNUSED
)
14853 /* Figure out what sort of save we have. */
14854 SKIP_WHITESPACE ();
14855 saved_ptr
= input_line_pointer
;
14857 reg
= arm_reg_parse (&input_line_pointer
, all_reg_maps
[REG_TYPE_FN
].htab
);
14860 s_arm_unwind_save_fpa (reg
);
14864 if (*input_line_pointer
== '{')
14865 input_line_pointer
++;
14867 SKIP_WHITESPACE ();
14869 reg
= arm_reg_parse (&input_line_pointer
, all_reg_maps
[REG_TYPE_RN
].htab
);
14872 input_line_pointer
= saved_ptr
;
14873 s_arm_unwind_save_core ();
14877 reg
= arm_reg_parse (&input_line_pointer
, all_reg_maps
[REG_TYPE_DN
].htab
);
14880 input_line_pointer
= saved_ptr
;
14881 s_arm_unwind_save_vfp ();
14885 reg
= arm_reg_parse (&input_line_pointer
,
14886 all_reg_maps
[REG_TYPE_IWMMXT
].htab
);
14889 input_line_pointer
= saved_ptr
;
14890 s_arm_unwind_save_wmmx ();
14894 /* TODO: Maverick registers. */
14895 as_bad (_("unrecognised register"));
14899 /* Parse an unwind_movsp directive. */
14902 s_arm_unwind_movsp (int ignored ATTRIBUTE_UNUSED
)
14907 SKIP_WHITESPACE ();
14908 reg
= reg_required_here (&input_line_pointer
, -1);
14911 as_bad (_("ARM register expected"));
14912 ignore_rest_of_line ();
14916 if (reg
== 13 || reg
== 15)
14918 as_bad (_("r%d not permitted in .unwind_movsp directive"), reg
);
14919 ignore_rest_of_line ();
14923 if (unwind
.fp_reg
!= 13)
14924 as_bad (_("unexpected .unwind_movsp directive"));
14926 /* Generate opcode to restore the value. */
14928 add_unwind_opcode (op
, 1);
14930 /* Record the information for later. */
14931 unwind
.fp_reg
= reg
;
14932 unwind
.fp_offset
= unwind
.frame_size
;
14933 unwind
.sp_restored
= 1;
14934 demand_empty_rest_of_line ();
14938 /* Parse #<number>. */
14941 require_hashconst (int * val
)
14945 SKIP_WHITESPACE ();
14946 if (*input_line_pointer
== '#')
14948 input_line_pointer
++;
14952 exp
.X_op
= O_illegal
;
14954 if (exp
.X_op
!= O_constant
)
14956 as_bad (_("expected #constant"));
14957 ignore_rest_of_line ();
14960 *val
= exp
.X_add_number
;
14964 /* Parse an unwind_pad directive. */
14967 s_arm_unwind_pad (int ignored ATTRIBUTE_UNUSED
)
14971 if (require_hashconst (&offset
) == FAIL
)
14976 as_bad (_("stack increment must be multiple of 4"));
14977 ignore_rest_of_line ();
14981 /* Don't generate any opcodes, just record the details for later. */
14982 unwind
.frame_size
+= offset
;
14983 unwind
.pending_offset
+= offset
;
14985 demand_empty_rest_of_line ();
14988 /* Parse an unwind_setfp directive. */
14991 s_arm_unwind_setfp (int ignored ATTRIBUTE_UNUSED
)
14997 fp_reg
= reg_required_here (&input_line_pointer
, -1);
14998 if (skip_past_comma (&input_line_pointer
) == FAIL
)
15001 sp_reg
= reg_required_here (&input_line_pointer
, -1);
15003 if (fp_reg
== FAIL
|| sp_reg
== FAIL
)
15005 as_bad (_("expected <reg>, <reg>"));
15006 ignore_rest_of_line ();
15010 /* Optonal constant. */
15011 if (skip_past_comma (&input_line_pointer
) != FAIL
)
15013 if (require_hashconst (&offset
) == FAIL
)
15019 demand_empty_rest_of_line ();
15021 if (sp_reg
!= 13 && sp_reg
!= unwind
.fp_reg
)
15023 as_bad (_("register must be either sp or set by a previous"
15024 "unwind_movsp directive"));
15028 /* Don't generate any opcodes, just record the information for later. */
15029 unwind
.fp_reg
= fp_reg
;
15030 unwind
.fp_used
= 1;
15032 unwind
.fp_offset
= unwind
.frame_size
- offset
;
15034 unwind
.fp_offset
-= offset
;
15037 /* Parse an unwind_raw directive. */
15040 s_arm_unwind_raw (int ignored ATTRIBUTE_UNUSED
)
15043 /* This is an arbitary limit. */
15044 unsigned char op
[16];
15047 SKIP_WHITESPACE ();
15049 if (exp
.X_op
== O_constant
15050 && skip_past_comma (&input_line_pointer
) != FAIL
)
15052 unwind
.frame_size
+= exp
.X_add_number
;
15056 exp
.X_op
= O_illegal
;
15058 if (exp
.X_op
!= O_constant
)
15060 as_bad (_("expected <offset>, <opcode>"));
15061 ignore_rest_of_line ();
15067 /* Parse the opcode. */
15072 as_bad (_("unwind opcode too long"));
15073 ignore_rest_of_line ();
15075 if (exp
.X_op
!= O_constant
|| exp
.X_add_number
& ~0xff)
15077 as_bad (_("invalid unwind opcode"));
15078 ignore_rest_of_line ();
15081 op
[count
++] = exp
.X_add_number
;
15083 /* Parse the next byte. */
15084 if (skip_past_comma (&input_line_pointer
) == FAIL
)
15090 /* Add the opcode bytes in reverse order. */
15092 add_unwind_opcode (op
[count
], 1);
15094 demand_empty_rest_of_line ();
15097 #endif /* OBJ_ELF */
15099 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
15100 of an rs_align_code fragment. */
15103 arm_handle_align (fragS
* fragP
)
15105 static char const arm_noop
[4] = { 0x00, 0x00, 0xa0, 0xe1 };
15106 static char const thumb_noop
[2] = { 0xc0, 0x46 };
15107 static char const arm_bigend_noop
[4] = { 0xe1, 0xa0, 0x00, 0x00 };
15108 static char const thumb_bigend_noop
[2] = { 0x46, 0xc0 };
15110 int bytes
, fix
, noop_size
;
15114 if (fragP
->fr_type
!= rs_align_code
)
15117 bytes
= fragP
->fr_next
->fr_address
- fragP
->fr_address
- fragP
->fr_fix
;
15118 p
= fragP
->fr_literal
+ fragP
->fr_fix
;
15121 if (bytes
> MAX_MEM_FOR_RS_ALIGN_CODE
)
15122 bytes
&= MAX_MEM_FOR_RS_ALIGN_CODE
;
15124 if (fragP
->tc_frag_data
)
15126 if (target_big_endian
)
15127 noop
= thumb_bigend_noop
;
15130 noop_size
= sizeof (thumb_noop
);
15134 if (target_big_endian
)
15135 noop
= arm_bigend_noop
;
15138 noop_size
= sizeof (arm_noop
);
15141 if (bytes
& (noop_size
- 1))
15143 fix
= bytes
& (noop_size
- 1);
15144 memset (p
, 0, fix
);
15149 while (bytes
>= noop_size
)
15151 memcpy (p
, noop
, noop_size
);
15153 bytes
-= noop_size
;
15157 fragP
->fr_fix
+= fix
;
15158 fragP
->fr_var
= noop_size
;
15161 /* Called from md_do_align. Used to create an alignment
15162 frag in a code section. */
15165 arm_frag_align_code (int n
, int max
)
15169 /* We assume that there will never be a requirement
15170 to support alignments greater than 32 bytes. */
15171 if (max
> MAX_MEM_FOR_RS_ALIGN_CODE
)
15172 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
15174 p
= frag_var (rs_align_code
,
15175 MAX_MEM_FOR_RS_ALIGN_CODE
,
15177 (relax_substateT
) max
,
15184 /* Perform target specific initialisation of a frag. */
15187 arm_init_frag (fragS
* fragP
)
15189 /* Record whether this frag is in an ARM or a THUMB area. */
15190 fragP
->tc_frag_data
= thumb_mode
;
15195 /* Convert REGNAME to a DWARF-2 register number. */
15198 tc_arm_regname_to_dw2regnum (const char *regname
)
15202 for (i
= 0; rn_table
[i
].name
; i
++)
15203 if (streq (regname
, rn_table
[i
].name
))
15204 return rn_table
[i
].number
;
15209 /* Initialize the DWARF-2 unwind information for this procedure. */
15212 tc_arm_frame_initial_instructions (void)
15214 cfi_add_CFA_def_cfa (REG_SP
, 0);
15218 /* This table describes all the machine specific pseudo-ops the assembler
15219 has to support. The fields are:
15220 pseudo-op name without dot
15221 function to call to execute this pseudo-op
15222 Integer arg to pass to the function. */
15224 const pseudo_typeS md_pseudo_table
[] =
15226 /* Never called because '.req' does not start a line. */
15227 { "req", s_req
, 0 },
15228 { "unreq", s_unreq
, 0 },
15229 { "bss", s_bss
, 0 },
15230 { "align", s_align
, 0 },
15231 { "arm", s_arm
, 0 },
15232 { "thumb", s_thumb
, 0 },
15233 { "code", s_code
, 0 },
15234 { "force_thumb", s_force_thumb
, 0 },
15235 { "thumb_func", s_thumb_func
, 0 },
15236 { "thumb_set", s_thumb_set
, 0 },
15237 { "even", s_even
, 0 },
15238 { "ltorg", s_ltorg
, 0 },
15239 { "pool", s_ltorg
, 0 },
15241 { "word", s_arm_elf_cons
, 4 },
15242 { "long", s_arm_elf_cons
, 4 },
15243 { "rel31", s_arm_rel31
, 0 },
15244 { "fnstart", s_arm_unwind_fnstart
, 0 },
15245 { "fnend", s_arm_unwind_fnend
, 0 },
15246 { "cantunwind", s_arm_unwind_cantunwind
, 0 },
15247 { "personality", s_arm_unwind_personality
, 0 },
15248 { "personalityindex", s_arm_unwind_personalityindex
, 0 },
15249 { "handlerdata", s_arm_unwind_handlerdata
, 0 },
15250 { "save", s_arm_unwind_save
, 0 },
15251 { "movsp", s_arm_unwind_movsp
, 0 },
15252 { "pad", s_arm_unwind_pad
, 0 },
15253 { "setfp", s_arm_unwind_setfp
, 0 },
15254 { "unwind_raw", s_arm_unwind_raw
, 0 },
15256 { "word", cons
, 4},
15258 { "extend", float_cons
, 'x' },
15259 { "ldouble", float_cons
, 'x' },
15260 { "packed", float_cons
, 'p' },