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 (This text is taken from version B-02 of the spec):
1248 4.4.7 Mapping and tagging symbols
1250 A section of an ARM ELF file can contain a mixture of ARM code,
1251 Thumb code, and data. There are inline transitions between code
1252 and data at literal pool boundaries. There can also be inline
1253 transitions between ARM code and Thumb code, for example in
1254 ARM-Thumb inter-working veneers. Linkers, machine-level
1255 debuggers, profiling tools, and disassembly tools need to map
1256 images accurately. For example, setting an ARM breakpoint on a
1257 Thumb location, or in a literal pool, can crash the program
1258 being debugged, ruining the debugging session.
1260 ARM ELF entities are mapped (see section 4.4.7.1 below) and
1261 tagged (see section 4.4.7.2 below) using local symbols (with
1262 binding STB_LOCAL). To assist consumers, mapping and tagging
1263 symbols should be collated first in the symbol table, before
1264 other symbols with binding STB_LOCAL.
1266 To allow properly collated mapping and tagging symbols to be
1267 skipped by consumers that have no interest in them, the first
1268 such symbol should have the name $m and its st_value field equal
1269 to the total number of mapping and tagging symbols (including
1270 the $m) in the symbol table.
1272 4.4.7.1 Mapping symbols
1274 $a Labels the first byte of a sequence of ARM instructions.
1275 Its type is STT_FUNC.
1277 $d Labels the first byte of a sequence of data items.
1278 Its type is STT_OBJECT.
1280 $t Labels the first byte of a sequence of Thumb instructions.
1281 Its type is STT_FUNC.
1283 This list of mapping symbols may be extended in the future.
1285 Section-relative mapping symbols
1287 Mapping symbols defined in a section define a sequence of
1288 half-open address intervals that cover the address range of the
1289 section. Each interval starts at the address defined by a
1290 mapping symbol, and continues up to, but not including, the
1291 address defined by the next (in address order) mapping symbol or
1292 the end of the section. A corollary is that there must be a
1293 mapping symbol defined at the beginning of each section.
1294 Consumers can ignore the size of a section-relative mapping
1295 symbol. Producers can set it to 0.
1297 Absolute mapping symbols
1299 Because of the need to crystallize a Thumb address with the
1300 Thumb-bit set, absolute symbol of type STT_FUNC (symbols of type
1301 STT_FUNC defined in section SHN_ABS) need to be mapped with $a
1304 The extent of a mapping symbol defined in SHN_ABS is [st_value,
1305 st_value + st_size), or [st_value, st_value + 1) if st_size = 0,
1306 where [x, y) denotes the half-open address range from x,
1307 inclusive, to y, exclusive.
1309 In the absence of a mapping symbol, a consumer can interpret a
1310 function symbol with an odd value as the Thumb code address
1311 obtained by clearing the least significant bit of the
1312 value. This interpretation is deprecated, and it may not work in
1315 Note - the Tagging symbols ($b, $f, $p $m) have been dropped from
1316 the EABI (which is still under development), so they are not
1317 implemented here. */
1319 static enum mstate mapstate
= MAP_UNDEFINED
;
1322 mapping_state (enum mstate state
)
1325 const char * symname
;
1328 if (mapstate
== state
)
1329 /* The mapping symbol has already been emitted.
1330 There is nothing else to do. */
1343 type
= BSF_FUNCTION
;
1347 type
= BSF_FUNCTION
;
1355 seg_info (now_seg
)->tc_segment_info_data
.mapstate
= state
;
1357 symbolP
= symbol_new (symname
, now_seg
, (valueT
) frag_now_fix (), frag_now
);
1358 symbol_table_insert (symbolP
);
1359 symbol_get_bfdsym (symbolP
)->flags
|= type
| BSF_LOCAL
;
1364 THUMB_SET_FUNC (symbolP
, 0);
1365 ARM_SET_THUMB (symbolP
, 0);
1366 ARM_SET_INTERWORK (symbolP
, support_interwork
);
1370 THUMB_SET_FUNC (symbolP
, 1);
1371 ARM_SET_THUMB (symbolP
, 1);
1372 ARM_SET_INTERWORK (symbolP
, support_interwork
);
1381 /* When we change sections we need to issue a new mapping symbol. */
1384 arm_elf_change_section (void)
1387 segment_info_type
*seginfo
;
1389 /* Link an unlinked unwind index table section to the .text section. */
1390 if (elf_section_type (now_seg
) == SHT_ARM_EXIDX
1391 && elf_linked_to_section (now_seg
) == NULL
)
1392 elf_linked_to_section (now_seg
) = text_section
;
1394 if (!SEG_NORMAL (now_seg
))
1397 flags
= bfd_get_section_flags (stdoutput
, now_seg
);
1399 /* We can ignore sections that only contain debug info. */
1400 if ((flags
& SEC_ALLOC
) == 0)
1403 seginfo
= seg_info (now_seg
);
1404 mapstate
= seginfo
->tc_segment_info_data
.mapstate
;
1405 marked_pr_dependency
= seginfo
->tc_segment_info_data
.marked_pr_dependency
;
1409 arm_elf_section_type (const char * str
, size_t len
)
1411 if (len
== 5 && strncmp (str
, "exidx", 5) == 0)
1412 return SHT_ARM_EXIDX
;
1417 #define mapping_state(a)
1418 #endif /* OBJ_ELF */
1420 /* arm_reg_parse () := if it looks like a register, return its token and
1421 advance the pointer. */
1424 arm_reg_parse (char ** ccp
, struct hash_control
* htab
)
1426 char * start
= * ccp
;
1429 struct reg_entry
* reg
;
1431 #ifdef REGISTER_PREFIX
1432 if (*start
!= REGISTER_PREFIX
)
1437 #ifdef OPTIONAL_REGISTER_PREFIX
1438 if (*p
== OPTIONAL_REGISTER_PREFIX
)
1442 if (!ISALPHA (*p
) || !is_name_beginner (*p
))
1446 while (ISALPHA (c
) || ISDIGIT (c
) || c
== '_')
1450 reg
= (struct reg_entry
*) hash_find (htab
, start
);
1462 /* Search for the following register name in each of the possible reg name
1463 tables. Return the classification if found, or REG_TYPE_MAX if not
1466 static enum arm_reg_type
1467 arm_reg_parse_any (char *cp
)
1471 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
1472 if (arm_reg_parse (&cp
, all_reg_maps
[i
].htab
) != FAIL
)
1473 return (enum arm_reg_type
) i
;
1475 return REG_TYPE_MAX
;
1479 opcode_select (int width
)
1486 if (! (cpu_variant
& ARM_EXT_V4T
))
1487 as_bad (_("selected processor does not support THUMB opcodes"));
1490 /* No need to force the alignment, since we will have been
1491 coming from ARM mode, which is word-aligned. */
1492 record_alignment (now_seg
, 1);
1494 mapping_state (MAP_THUMB
);
1500 if ((cpu_variant
& ARM_ALL
) == ARM_EXT_V4T
)
1501 as_bad (_("selected processor does not support ARM opcodes"));
1506 frag_align (2, 0, 0);
1508 record_alignment (now_seg
, 1);
1510 mapping_state (MAP_ARM
);
1514 as_bad (_("invalid instruction size selected (%d)"), width
);
1519 s_req (int a ATTRIBUTE_UNUSED
)
1521 as_bad (_("invalid syntax for .req directive"));
1524 /* The .unreq directive deletes an alias which was previously defined
1525 by .req. For example:
1531 s_unreq (int a ATTRIBUTE_UNUSED
)
1536 skip_whitespace (input_line_pointer
);
1537 name
= input_line_pointer
;
1539 while (*input_line_pointer
!= 0
1540 && *input_line_pointer
!= ' '
1541 && *input_line_pointer
!= '\n')
1542 ++input_line_pointer
;
1544 saved_char
= *input_line_pointer
;
1545 *input_line_pointer
= 0;
1549 enum arm_reg_type req_type
= arm_reg_parse_any (name
);
1551 if (req_type
!= REG_TYPE_MAX
)
1553 char *temp_name
= name
;
1554 int req_no
= arm_reg_parse (&temp_name
, all_reg_maps
[req_type
].htab
);
1558 struct reg_entry
*req_entry
;
1560 /* Check to see if this alias is a builtin one. */
1561 req_entry
= hash_delete (all_reg_maps
[req_type
].htab
, name
);
1564 as_bad (_("unreq: missing hash entry for \"%s\""), name
);
1565 else if (req_entry
->builtin
)
1566 /* FIXME: We are deleting a built in register alias which
1567 points to a const data structure, so we only need to
1568 free up the memory used by the key in the hash table.
1569 Unfortunately we have not recorded this value, so this
1570 is a memory leak. */
1571 /* FIXME: Should we issue a warning message ? */
1575 /* Deleting a user defined alias. We need to free the
1576 key and the value, but fortunately the key is the same
1577 as the value->name field. */
1578 free ((char *) req_entry
->name
);
1583 as_bad (_(".unreq: unrecognized symbol \"%s\""), name
);
1586 as_bad (_(".unreq: unrecognized symbol \"%s\""), name
);
1589 as_bad (_("invalid syntax for .unreq directive"));
1591 *input_line_pointer
= saved_char
;
1592 demand_empty_rest_of_line ();
1596 s_bss (int ignore ATTRIBUTE_UNUSED
)
1598 /* We don't support putting frags in the BSS segment, we fake it by
1599 marking in_bss, then looking at s_skip for clues. */
1600 subseg_set (bss_section
, 0);
1601 demand_empty_rest_of_line ();
1602 mapping_state (MAP_DATA
);
1606 s_even (int ignore ATTRIBUTE_UNUSED
)
1608 /* Never make frag if expect extra pass. */
1610 frag_align (1, 0, 0);
1612 record_alignment (now_seg
, 1);
1614 demand_empty_rest_of_line ();
1618 s_ltorg (int ignored ATTRIBUTE_UNUSED
)
1621 literal_pool
* pool
;
1624 pool
= find_literal_pool ();
1626 || pool
->symbol
== NULL
1627 || pool
->next_free_entry
== 0)
1630 mapping_state (MAP_DATA
);
1632 /* Align pool as you have word accesses.
1633 Only make a frag if we have to. */
1635 frag_align (2, 0, 0);
1637 record_alignment (now_seg
, 2);
1639 sprintf (sym_name
, "$$lit_\002%x", pool
->id
);
1641 symbol_locate (pool
->symbol
, sym_name
, now_seg
,
1642 (valueT
) frag_now_fix (), frag_now
);
1643 symbol_table_insert (pool
->symbol
);
1645 ARM_SET_THUMB (pool
->symbol
, thumb_mode
);
1647 #if defined OBJ_COFF || defined OBJ_ELF
1648 ARM_SET_INTERWORK (pool
->symbol
, support_interwork
);
1651 for (entry
= 0; entry
< pool
->next_free_entry
; entry
++)
1652 /* First output the expression in the instruction to the pool. */
1653 emit_expr (&(pool
->literals
[entry
]), 4); /* .word */
1655 /* Mark the pool as empty. */
1656 pool
->next_free_entry
= 0;
1657 pool
->symbol
= NULL
;
1660 /* Same as s_align_ptwo but align 0 => align 2. */
1663 s_align (int unused ATTRIBUTE_UNUSED
)
1667 long max_alignment
= 15;
1669 temp
= get_absolute_expression ();
1670 if (temp
> max_alignment
)
1671 as_bad (_("alignment too large: %d assumed"), temp
= max_alignment
);
1674 as_bad (_("alignment negative. 0 assumed."));
1678 if (*input_line_pointer
== ',')
1680 input_line_pointer
++;
1681 temp_fill
= get_absolute_expression ();
1689 /* Only make a frag if we HAVE to. */
1690 if (temp
&& !need_pass_2
)
1691 frag_align (temp
, (int) temp_fill
, 0);
1692 demand_empty_rest_of_line ();
1694 record_alignment (now_seg
, temp
);
1698 s_force_thumb (int ignore ATTRIBUTE_UNUSED
)
1700 /* If we are not already in thumb mode go into it, EVEN if
1701 the target processor does not support thumb instructions.
1702 This is used by gcc/config/arm/lib1funcs.asm for example
1703 to compile interworking support functions even if the
1704 target processor should not support interworking. */
1709 record_alignment (now_seg
, 1);
1712 demand_empty_rest_of_line ();
1716 s_thumb_func (int ignore ATTRIBUTE_UNUSED
)
1721 /* The following label is the name/address of the start of a Thumb function.
1722 We need to know this for the interworking support. */
1723 label_is_thumb_function_name
= TRUE
;
1725 demand_empty_rest_of_line ();
1728 /* Perform a .set directive, but also mark the alias as
1729 being a thumb function. */
1732 s_thumb_set (int equiv
)
1734 /* XXX the following is a duplicate of the code for s_set() in read.c
1735 We cannot just call that code as we need to get at the symbol that
1742 /* Especial apologies for the random logic:
1743 This just grew, and could be parsed much more simply!
1745 name
= input_line_pointer
;
1746 delim
= get_symbol_end ();
1747 end_name
= input_line_pointer
;
1752 if (*input_line_pointer
!= ',')
1755 as_bad (_("expected comma after name \"%s\""), name
);
1757 ignore_rest_of_line ();
1761 input_line_pointer
++;
1764 if (name
[0] == '.' && name
[1] == '\0')
1766 /* XXX - this should not happen to .thumb_set. */
1770 if ((symbolP
= symbol_find (name
)) == NULL
1771 && (symbolP
= md_undefined_symbol (name
)) == NULL
)
1774 /* When doing symbol listings, play games with dummy fragments living
1775 outside the normal fragment chain to record the file and line info
1777 if (listing
& LISTING_SYMBOLS
)
1779 extern struct list_info_struct
* listing_tail
;
1780 fragS
* dummy_frag
= xmalloc (sizeof (fragS
));
1782 memset (dummy_frag
, 0, sizeof (fragS
));
1783 dummy_frag
->fr_type
= rs_fill
;
1784 dummy_frag
->line
= listing_tail
;
1785 symbolP
= symbol_new (name
, undefined_section
, 0, dummy_frag
);
1786 dummy_frag
->fr_symbol
= symbolP
;
1790 symbolP
= symbol_new (name
, undefined_section
, 0, &zero_address_frag
);
1793 /* "set" symbols are local unless otherwise specified. */
1794 SF_SET_LOCAL (symbolP
);
1795 #endif /* OBJ_COFF */
1796 } /* Make a new symbol. */
1798 symbol_table_insert (symbolP
);
1803 && S_IS_DEFINED (symbolP
)
1804 && S_GET_SEGMENT (symbolP
) != reg_section
)
1805 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP
));
1807 pseudo_set (symbolP
);
1809 demand_empty_rest_of_line ();
1811 /* XXX Now we come to the Thumb specific bit of code. */
1813 THUMB_SET_FUNC (symbolP
, 1);
1814 ARM_SET_THUMB (symbolP
, 1);
1815 #if defined OBJ_ELF || defined OBJ_COFF
1816 ARM_SET_INTERWORK (symbolP
, support_interwork
);
1821 s_arm (int ignore ATTRIBUTE_UNUSED
)
1824 demand_empty_rest_of_line ();
1828 s_thumb (int ignore ATTRIBUTE_UNUSED
)
1831 demand_empty_rest_of_line ();
1835 s_code (int unused ATTRIBUTE_UNUSED
)
1839 temp
= get_absolute_expression ();
1844 opcode_select (temp
);
1848 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp
);
1853 end_of_line (char * str
)
1855 skip_whitespace (str
);
1857 if (*str
!= '\0' && !inst
.error
)
1858 inst
.error
= _("garbage following instruction");
1862 skip_past_comma (char ** str
)
1864 char * p
= * str
, c
;
1867 while ((c
= *p
) == ' ' || c
== ',')
1870 if (c
== ',' && comma
++)
1878 return comma
? SUCCESS
: FAIL
;
1881 /* Return TRUE if anything in the expression is a bignum. */
1884 walk_no_bignums (symbolS
* sp
)
1886 if (symbol_get_value_expression (sp
)->X_op
== O_big
)
1889 if (symbol_get_value_expression (sp
)->X_add_symbol
)
1891 return (walk_no_bignums (symbol_get_value_expression (sp
)->X_add_symbol
)
1892 || (symbol_get_value_expression (sp
)->X_op_symbol
1893 && walk_no_bignums (symbol_get_value_expression (sp
)->X_op_symbol
)));
1899 static int in_my_get_expression
= 0;
1902 my_get_expression (expressionS
* ep
, char ** str
)
1907 save_in
= input_line_pointer
;
1908 input_line_pointer
= *str
;
1909 in_my_get_expression
= 1;
1910 seg
= expression (ep
);
1911 in_my_get_expression
= 0;
1913 if (ep
->X_op
== O_illegal
)
1915 /* We found a bad expression in md_operand(). */
1916 *str
= input_line_pointer
;
1917 input_line_pointer
= save_in
;
1922 if (seg
!= absolute_section
1923 && seg
!= text_section
1924 && seg
!= data_section
1925 && seg
!= bss_section
1926 && seg
!= undefined_section
)
1928 inst
.error
= _("bad_segment");
1929 *str
= input_line_pointer
;
1930 input_line_pointer
= save_in
;
1935 /* Get rid of any bignums now, so that we don't generate an error for which
1936 we can't establish a line number later on. Big numbers are never valid
1937 in instructions, which is where this routine is always called. */
1938 if (ep
->X_op
== O_big
1939 || (ep
->X_add_symbol
1940 && (walk_no_bignums (ep
->X_add_symbol
)
1942 && walk_no_bignums (ep
->X_op_symbol
)))))
1944 inst
.error
= _("invalid constant");
1945 *str
= input_line_pointer
;
1946 input_line_pointer
= save_in
;
1950 *str
= input_line_pointer
;
1951 input_line_pointer
= save_in
;
1955 /* A standard register must be given at this point.
1956 SHIFT is the place to put it in inst.instruction.
1957 Restores input start point on error.
1958 Returns the reg#, or FAIL. */
1961 reg_required_here (char ** str
, int shift
)
1963 static char buff
[128]; /* XXX */
1965 char * start
= * str
;
1967 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_RN
].htab
)) != FAIL
)
1970 inst
.instruction
|= reg
<< shift
;
1974 /* Restore the start point, we may have got a reg of the wrong class. */
1977 /* In the few cases where we might be able to accept something else
1978 this error can be overridden. */
1979 sprintf (buff
, _("register expected, not '%.100s'"), start
);
1985 /* A Intel Wireless MMX technology register
1986 must be given at this point.
1987 Shift is the place to put it in inst.instruction.
1988 Restores input start point on err.
1989 Returns the reg#, or FAIL. */
1992 wreg_required_here (char ** str
,
1994 enum wreg_type reg_type
)
1996 static char buff
[128];
1998 char * start
= *str
;
2000 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_IWMMXT
].htab
)) != FAIL
)
2002 if (wr_register (reg
)
2003 && (reg_type
== IWMMXT_REG_WR
|| reg_type
== IWMMXT_REG_WR_OR_WC
))
2006 inst
.instruction
|= (reg
^ WR_PREFIX
) << shift
;
2009 else if (wc_register (reg
)
2010 && (reg_type
== IWMMXT_REG_WC
|| reg_type
== IWMMXT_REG_WR_OR_WC
))
2013 inst
.instruction
|= (reg
^ WC_PREFIX
) << shift
;
2016 else if ((wcg_register (reg
) && reg_type
== IWMMXT_REG_WCG
))
2019 inst
.instruction
|= ((reg
^ WC_PREFIX
) - 8) << shift
;
2024 /* Restore the start point, we may have got a reg of the wrong class. */
2027 /* In the few cases where we might be able to accept
2028 something else this error can be overridden. */
2029 sprintf (buff
, _("Intel Wireless MMX technology register expected, not '%.100s'"), start
);
2035 static const struct asm_psr
*
2036 arm_psr_parse (char ** ccp
)
2038 char * start
= * ccp
;
2041 const struct asm_psr
* psr
;
2045 /* Skip to the end of the next word in the input stream. */
2050 while (ISALPHA (c
) || c
== '_');
2052 /* Terminate the word. */
2055 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
2056 feature for ease of use and backwards compatibility. */
2057 if (!strncmp (start
, "cpsr", 4))
2058 strncpy (start
, "CPSR", 4);
2059 else if (!strncmp (start
, "spsr", 4))
2060 strncpy (start
, "SPSR", 4);
2062 /* Now locate the word in the psr hash table. */
2063 psr
= (const struct asm_psr
*) hash_find (arm_psr_hsh
, start
);
2065 /* Restore the input stream. */
2068 /* If we found a valid match, advance the
2069 stream pointer past the end of the word. */
2075 /* Parse the input looking for a PSR flag. */
2078 psr_required_here (char ** str
)
2080 char * start
= * str
;
2081 const struct asm_psr
* psr
;
2083 psr
= arm_psr_parse (str
);
2087 /* If this is the SPSR that is being modified, set the R bit. */
2089 inst
.instruction
|= SPSR_BIT
;
2091 /* Set the psr flags in the MSR instruction. */
2092 inst
.instruction
|= psr
->field
<< PSR_SHIFT
;
2097 /* In the few cases where we might be able to accept
2098 something else this error can be overridden. */
2099 inst
.error
= _("flag for {c}psr instruction expected");
2101 /* Restore the start point. */
2107 co_proc_number (char ** str
)
2109 int processor
, pchar
;
2112 skip_whitespace (*str
);
2115 /* The data sheet seems to imply that just a number on its own is valid
2116 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
2118 if ((processor
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CP
].htab
))
2124 if (pchar
>= '0' && pchar
<= '9')
2126 processor
= pchar
- '0';
2127 if (**str
>= '0' && **str
<= '9')
2129 processor
= processor
* 10 + *(*str
)++ - '0';
2132 inst
.error
= _("illegal co-processor number");
2139 inst
.error
= all_reg_maps
[REG_TYPE_CP
].expected
;
2144 inst
.instruction
|= processor
<< 8;
2149 cp_opc_expr (char ** str
, int where
, int length
)
2153 skip_whitespace (* str
);
2155 memset (&expr
, '\0', sizeof (expr
));
2157 if (my_get_expression (&expr
, str
))
2159 if (expr
.X_op
!= O_constant
)
2161 inst
.error
= _("bad or missing expression");
2165 if ((expr
.X_add_number
& ((1 << length
) - 1)) != expr
.X_add_number
)
2167 inst
.error
= _("immediate co-processor expression too large");
2171 inst
.instruction
|= expr
.X_add_number
<< where
;
2176 cp_reg_required_here (char ** str
, int where
)
2179 char * start
= *str
;
2181 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CN
].htab
)) != FAIL
)
2183 inst
.instruction
|= reg
<< where
;
2187 /* In the few cases where we might be able to accept something else
2188 this error can be overridden. */
2189 inst
.error
= all_reg_maps
[REG_TYPE_CN
].expected
;
2191 /* Restore the start point. */
2197 fp_reg_required_here (char ** str
, int where
)
2200 char * start
= * str
;
2202 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_FN
].htab
)) != FAIL
)
2204 inst
.instruction
|= reg
<< where
;
2208 /* In the few cases where we might be able to accept something else
2209 this error can be overridden. */
2210 inst
.error
= all_reg_maps
[REG_TYPE_FN
].expected
;
2212 /* Restore the start point. */
2218 cp_address_offset (char ** str
)
2222 skip_whitespace (* str
);
2224 if (! is_immediate_prefix (**str
))
2226 inst
.error
= _("immediate expression expected");
2232 if (my_get_expression (& inst
.reloc
.exp
, str
))
2235 if (inst
.reloc
.exp
.X_op
== O_constant
)
2237 offset
= inst
.reloc
.exp
.X_add_number
;
2241 inst
.error
= _("co-processor address must be word aligned");
2245 if (offset
> 1023 || offset
< -1023)
2247 inst
.error
= _("offset too large");
2252 inst
.instruction
|= INDEX_UP
;
2256 inst
.instruction
|= offset
>> 2;
2259 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
2265 cp_address_required_here (char ** str
, int wb_ok
)
2276 skip_whitespace (p
);
2278 if ((reg
= reg_required_here (& p
, 16)) == FAIL
)
2281 skip_whitespace (p
);
2287 skip_whitespace (p
);
2291 /* As an extension to the official ARM syntax we allow:
2293 as a short hand for:
2295 inst
.instruction
|= PRE_INDEX
| INDEX_UP
;
2300 if (skip_past_comma (& p
) == FAIL
)
2302 inst
.error
= _("comma expected after closing square bracket");
2306 skip_whitespace (p
);
2313 write_back
= WRITE_BACK
;
2317 inst
.error
= _("pc may not be used in post-increment");
2321 if (cp_address_offset (& p
) == FAIL
)
2325 pre_inc
= PRE_INDEX
| INDEX_UP
;
2331 /* [Rn], {<expr>} */
2334 skip_whitespace (p
);
2336 if (my_get_expression (& inst
.reloc
.exp
, & p
))
2339 if (inst
.reloc
.exp
.X_op
== O_constant
)
2341 option
= inst
.reloc
.exp
.X_add_number
;
2343 if (option
> 255 || option
< 0)
2345 inst
.error
= _("'option' field too large");
2349 skip_whitespace (p
);
2353 inst
.error
= _("'}' expected at end of 'option' field");
2359 inst
.instruction
|= option
;
2360 inst
.instruction
|= INDEX_UP
;
2365 inst
.error
= _("non-constant expressions for 'option' field not supported");
2371 inst
.error
= _("# or { expected after comma");
2377 /* '['Rn, #expr']'[!] */
2379 if (skip_past_comma (& p
) == FAIL
)
2381 inst
.error
= _("pre-indexed expression expected");
2385 pre_inc
= PRE_INDEX
;
2387 if (cp_address_offset (& p
) == FAIL
)
2390 skip_whitespace (p
);
2394 inst
.error
= _("missing ]");
2398 skip_whitespace (p
);
2400 if (wb_ok
&& *p
== '!')
2404 inst
.error
= _("pc may not be used with write-back");
2409 write_back
= WRITE_BACK
;
2415 if (my_get_expression (&inst
.reloc
.exp
, &p
))
2418 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
2419 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
2420 inst
.reloc
.pc_rel
= 1;
2421 inst
.instruction
|= (REG_PC
<< 16);
2422 pre_inc
= PRE_INDEX
;
2425 inst
.instruction
|= write_back
| pre_inc
;
2431 cp_byte_address_offset (char ** str
)
2435 skip_whitespace (* str
);
2437 if (! is_immediate_prefix (**str
))
2439 inst
.error
= _("immediate expression expected");
2445 if (my_get_expression (& inst
.reloc
.exp
, str
))
2448 if (inst
.reloc
.exp
.X_op
== O_constant
)
2450 offset
= inst
.reloc
.exp
.X_add_number
;
2452 if (offset
> 255 || offset
< -255)
2454 inst
.error
= _("offset too large");
2459 inst
.instruction
|= INDEX_UP
;
2463 inst
.instruction
|= offset
;
2466 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM_S2
;
2472 cp_byte_address_required_here (char ** str
)
2483 skip_whitespace (p
);
2485 if ((reg
= reg_required_here (& p
, 16)) == FAIL
)
2488 skip_whitespace (p
);
2494 if (skip_past_comma (& p
) == SUCCESS
)
2497 write_back
= WRITE_BACK
;
2501 inst
.error
= _("pc may not be used in post-increment");
2505 if (cp_byte_address_offset (& p
) == FAIL
)
2509 pre_inc
= PRE_INDEX
| INDEX_UP
;
2513 /* '['Rn, #expr']'[!] */
2515 if (skip_past_comma (& p
) == FAIL
)
2517 inst
.error
= _("pre-indexed expression expected");
2521 pre_inc
= PRE_INDEX
;
2523 if (cp_byte_address_offset (& p
) == FAIL
)
2526 skip_whitespace (p
);
2530 inst
.error
= _("missing ]");
2534 skip_whitespace (p
);
2540 inst
.error
= _("pc may not be used with write-back");
2545 write_back
= WRITE_BACK
;
2551 if (my_get_expression (&inst
.reloc
.exp
, &p
))
2554 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM_S2
;
2555 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
2556 inst
.reloc
.pc_rel
= 1;
2557 inst
.instruction
|= (REG_PC
<< 16);
2558 pre_inc
= PRE_INDEX
;
2561 inst
.instruction
|= write_back
| pre_inc
;
2569 skip_whitespace (str
);
2574 if (my_get_expression (&inst
.reloc
.exp
, &str
))
2575 inst
.reloc
.exp
.X_op
= O_illegal
;
2578 skip_whitespace (str
);
2582 inst
.reloc
.exp
.X_op
= O_illegal
;
2585 if (inst
.reloc
.exp
.X_op
!= O_constant
2586 || inst
.reloc
.exp
.X_add_number
> 255
2587 || inst
.reloc
.exp
.X_add_number
< 0)
2589 inst
.error
= _("Invalid NOP hint");
2593 /* Arcitectural NOP hints are CPSR sets with no bits selected. */
2594 inst
.instruction
&= 0xf0000000;
2595 inst
.instruction
|= 0x0320f000 + inst
.reloc
.exp
.X_add_number
;
2602 do_empty (char * str
)
2604 /* Do nothing really. */
2613 /* Only one syntax. */
2614 skip_whitespace (str
);
2616 if (reg_required_here (&str
, 12) == FAIL
)
2618 inst
.error
= BAD_ARGS
;
2622 if (skip_past_comma (&str
) == FAIL
)
2624 inst
.error
= _("comma expected after register name");
2628 skip_whitespace (str
);
2630 if ( streq (str
, "CPSR")
2631 || streq (str
, "SPSR")
2632 /* Lower case versions for backwards compatibility. */
2633 || streq (str
, "cpsr")
2634 || streq (str
, "spsr"))
2637 /* This is for backwards compatibility with older toolchains. */
2638 else if ( streq (str
, "cpsr_all")
2639 || streq (str
, "spsr_all"))
2643 inst
.error
= _("CPSR or SPSR expected");
2647 if (* str
== 's' || * str
== 'S')
2648 inst
.instruction
|= SPSR_BIT
;
2654 /* Two possible forms:
2655 "{C|S}PSR_<field>, Rm",
2656 "{C|S}PSR_f, #expression". */
2661 skip_whitespace (str
);
2663 if (psr_required_here (& str
) == FAIL
)
2666 if (skip_past_comma (& str
) == FAIL
)
2668 inst
.error
= _("comma missing after psr flags");
2672 skip_whitespace (str
);
2674 if (reg_required_here (& str
, 0) != FAIL
)
2681 if (! is_immediate_prefix (* str
))
2684 _("only a register or immediate value can follow a psr flag");
2691 if (my_get_expression (& inst
.reloc
.exp
, & str
))
2694 _("only a register or immediate value can follow a psr flag");
2698 inst
.instruction
|= INST_IMMEDIATE
;
2700 if (inst
.reloc
.exp
.X_add_symbol
)
2702 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
2703 inst
.reloc
.pc_rel
= 0;
2707 unsigned value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
2709 if (value
== (unsigned) FAIL
)
2711 inst
.error
= _("invalid constant");
2715 inst
.instruction
|= value
;
2722 /* Long Multiply Parser
2723 UMULL RdLo, RdHi, Rm, Rs
2724 SMULL RdLo, RdHi, Rm, Rs
2725 UMLAL RdLo, RdHi, Rm, Rs
2726 SMLAL RdLo, RdHi, Rm, Rs. */
2729 do_mull (char * str
)
2731 int rdlo
, rdhi
, rm
, rs
;
2733 /* Only one format "rdlo, rdhi, rm, rs". */
2734 skip_whitespace (str
);
2736 if ((rdlo
= reg_required_here (&str
, 12)) == FAIL
)
2738 inst
.error
= BAD_ARGS
;
2742 if (skip_past_comma (&str
) == FAIL
2743 || (rdhi
= reg_required_here (&str
, 16)) == FAIL
)
2745 inst
.error
= BAD_ARGS
;
2749 if (skip_past_comma (&str
) == FAIL
2750 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
2752 inst
.error
= BAD_ARGS
;
2756 /* rdhi, rdlo and rm must all be different. */
2757 if (rdlo
== rdhi
|| rdlo
== rm
|| rdhi
== rm
)
2758 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
2760 if (skip_past_comma (&str
) == FAIL
2761 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
2763 inst
.error
= BAD_ARGS
;
2767 if (rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
)
2769 inst
.error
= BAD_PC
;
2781 /* Only one format "rd, rm, rs". */
2782 skip_whitespace (str
);
2784 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
2786 inst
.error
= BAD_ARGS
;
2792 inst
.error
= BAD_PC
;
2796 if (skip_past_comma (&str
) == FAIL
2797 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
2799 inst
.error
= BAD_ARGS
;
2805 inst
.error
= BAD_PC
;
2810 as_tsktsk (_("rd and rm should be different in mul"));
2812 if (skip_past_comma (&str
) == FAIL
2813 || (rm
= reg_required_here (&str
, 8)) == FAIL
)
2815 inst
.error
= BAD_ARGS
;
2821 inst
.error
= BAD_PC
;
2829 do_mlas (char * str
, bfd_boolean is_mls
)
2833 /* Only one format "rd, rm, rs, rn". */
2834 skip_whitespace (str
);
2836 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
2838 inst
.error
= BAD_ARGS
;
2844 inst
.error
= BAD_PC
;
2848 if (skip_past_comma (&str
) == FAIL
2849 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
2851 inst
.error
= BAD_ARGS
;
2857 inst
.error
= BAD_PC
;
2861 /* This restriction does not apply to mls (nor to mla in v6, but
2862 that's hard to detect at present). */
2863 if (rm
== rd
&& !is_mls
)
2864 as_tsktsk (_("rd and rm should be different in mla"));
2866 if (skip_past_comma (&str
) == FAIL
2867 || (rd
= reg_required_here (&str
, 8)) == FAIL
2868 || skip_past_comma (&str
) == FAIL
2869 || (rm
= reg_required_here (&str
, 12)) == FAIL
)
2871 inst
.error
= BAD_ARGS
;
2875 if (rd
== REG_PC
|| rm
== REG_PC
)
2877 inst
.error
= BAD_PC
;
2887 do_mlas (str
, FALSE
);
2893 do_mlas (str
, TRUE
);
2896 /* Expects *str -> the characters "acc0", possibly with leading blanks.
2897 Advances *str to the next non-alphanumeric.
2898 Returns 0, or else FAIL (in which case sets inst.error).
2900 (In a future XScale, there may be accumulators other than zero.
2901 At that time this routine and its callers can be upgraded to suit.) */
2904 accum0_required_here (char ** str
)
2906 static char buff
[128]; /* Note the address is taken. Hence, static. */
2909 int result
= 0; /* The accum number. */
2911 skip_whitespace (p
);
2913 *str
= p
; /* Advance caller's string pointer too. */
2918 *--p
= 0; /* Aap nul into input buffer at non-alnum. */
2920 if (! ( streq (*str
, "acc0") || streq (*str
, "ACC0")))
2922 sprintf (buff
, _("acc0 expected, not '%.100s'"), *str
);
2927 *p
= c
; /* Unzap. */
2928 *str
= p
; /* Caller's string pointer to after match. */
2933 ldst_extend_v4 (char ** str
)
2942 if (my_get_expression (& inst
.reloc
.exp
, str
))
2945 if (inst
.reloc
.exp
.X_op
== O_constant
)
2947 int value
= inst
.reloc
.exp
.X_add_number
;
2949 if (value
< -255 || value
> 255)
2951 inst
.error
= _("address offset too large");
2961 /* Halfword and signextension instructions have the
2962 immediate value split across bits 11..8 and bits 3..0. */
2963 inst
.instruction
|= (add
| HWOFFSET_IMM
2964 | ((value
>> 4) << 8) | (value
& 0xF));
2968 inst
.instruction
|= HWOFFSET_IMM
;
2969 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
2970 inst
.reloc
.pc_rel
= 0;
2983 if (reg_required_here (str
, 0) == FAIL
)
2986 inst
.instruction
|= add
;
2991 /* Expects **str -> after a comma. May be leading blanks.
2992 Advances *str, recognizing a load mode, and setting inst.instruction.
2993 Returns rn, or else FAIL (in which case may set inst.error
2994 and not advance str)
2996 Note: doesn't know Rd, so no err checks that require such knowledge. */
2999 ld_mode_required_here (char ** string
)
3001 char * str
= * string
;
3005 skip_whitespace (str
);
3011 skip_whitespace (str
);
3013 if ((rn
= reg_required_here (& str
, 16)) == FAIL
)
3016 skip_whitespace (str
);
3022 if (skip_past_comma (& str
) == SUCCESS
)
3024 /* [Rn],... (post inc) */
3025 if (ldst_extend_v4 (&str
) == FAIL
)
3030 skip_whitespace (str
);
3035 inst
.instruction
|= WRITE_BACK
;
3038 inst
.instruction
|= INDEX_UP
| HWOFFSET_IMM
;
3044 if (skip_past_comma (& str
) == FAIL
)
3046 inst
.error
= _("pre-indexed expression expected");
3052 if (ldst_extend_v4 (&str
) == FAIL
)
3055 skip_whitespace (str
);
3057 if (* str
++ != ']')
3059 inst
.error
= _("missing ]");
3063 skip_whitespace (str
);
3068 inst
.instruction
|= WRITE_BACK
;
3072 else if (* str
== '=') /* ldr's "r,=label" syntax */
3073 /* We should never reach here, because <text> = <expression> is
3074 caught gas/read.c read_a_source_file() as a .set operation. */
3076 else /* PC +- 8 bit immediate offset. */
3078 if (my_get_expression (& inst
.reloc
.exp
, & str
))
3081 inst
.instruction
|= HWOFFSET_IMM
; /* The I bit. */
3082 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
3083 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
3084 inst
.reloc
.pc_rel
= 1;
3085 inst
.instruction
|= (REG_PC
<< 16);
3091 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
3097 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
3098 SMLAxy{cond} Rd,Rm,Rs,Rn
3099 SMLAWy{cond} Rd,Rm,Rs,Rn
3100 Error if any register is R15. */
3103 do_smla (char * str
)
3107 skip_whitespace (str
);
3109 if ((rd
= reg_required_here (& str
, 16)) == FAIL
3110 || skip_past_comma (& str
) == FAIL
3111 || (rm
= reg_required_here (& str
, 0)) == FAIL
3112 || skip_past_comma (& str
) == FAIL
3113 || (rs
= reg_required_here (& str
, 8)) == FAIL
3114 || skip_past_comma (& str
) == FAIL
3115 || (rn
= reg_required_here (& str
, 12)) == FAIL
)
3116 inst
.error
= BAD_ARGS
;
3118 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
|| rn
== REG_PC
)
3119 inst
.error
= BAD_PC
;
3125 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
3126 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
3127 Error if any register is R15.
3128 Warning if Rdlo == Rdhi. */
3131 do_smlal (char * str
)
3133 int rdlo
, rdhi
, rm
, rs
;
3135 skip_whitespace (str
);
3137 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
3138 || skip_past_comma (& str
) == FAIL
3139 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
3140 || skip_past_comma (& str
) == FAIL
3141 || (rm
= reg_required_here (& str
, 0)) == FAIL
3142 || skip_past_comma (& str
) == FAIL
3143 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
3145 inst
.error
= BAD_ARGS
;
3149 if (rdlo
== REG_PC
|| rdhi
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
3151 inst
.error
= BAD_PC
;
3156 as_tsktsk (_("rdhi and rdlo must be different"));
3161 /* ARM V5E (El Segundo) signed-multiply (argument parse)
3162 SMULxy{cond} Rd,Rm,Rs
3163 Error if any register is R15. */
3166 do_smul (char * str
)
3170 skip_whitespace (str
);
3172 if ((rd
= reg_required_here (& str
, 16)) == FAIL
3173 || skip_past_comma (& str
) == FAIL
3174 || (rm
= reg_required_here (& str
, 0)) == FAIL
3175 || skip_past_comma (& str
) == FAIL
3176 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
3177 inst
.error
= BAD_ARGS
;
3179 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
3180 inst
.error
= BAD_PC
;
3186 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
3187 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
3188 Error if any register is R15. */
3191 do_qadd (char * str
)
3195 skip_whitespace (str
);
3197 if ((rd
= reg_required_here (& str
, 12)) == FAIL
3198 || skip_past_comma (& str
) == FAIL
3199 || (rm
= reg_required_here (& str
, 0)) == FAIL
3200 || skip_past_comma (& str
) == FAIL
3201 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
3202 inst
.error
= BAD_ARGS
;
3204 else if (rd
== REG_PC
|| rm
== REG_PC
|| rn
== REG_PC
)
3205 inst
.error
= BAD_PC
;
3211 /* ARM V5E (el Segundo)
3212 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3213 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3215 These are equivalent to the XScale instructions MAR and MRA,
3216 respectively, when coproc == 0, opcode == 0, and CRm == 0.
3218 Result unpredicatable if Rd or Rn is R15. */
3221 do_co_reg2c (char * str
)
3225 skip_whitespace (str
);
3227 if (co_proc_number (& str
) == FAIL
)
3230 inst
.error
= BAD_ARGS
;
3234 if (skip_past_comma (& str
) == FAIL
3235 || cp_opc_expr (& str
, 4, 4) == FAIL
)
3238 inst
.error
= BAD_ARGS
;
3242 if (skip_past_comma (& str
) == FAIL
3243 || (rd
= reg_required_here (& str
, 12)) == FAIL
)
3246 inst
.error
= BAD_ARGS
;
3250 if (skip_past_comma (& str
) == FAIL
3251 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
3254 inst
.error
= BAD_ARGS
;
3258 /* Unpredictable result if rd or rn is R15. */
3259 if (rd
== REG_PC
|| rn
== REG_PC
)
3261 (_("Warning: instruction unpredictable when using r15"));
3263 if (skip_past_comma (& str
) == FAIL
3264 || cp_reg_required_here (& str
, 0) == FAIL
)
3267 inst
.error
= BAD_ARGS
;
3274 /* ARM V5 count-leading-zeroes instruction (argument parse)
3275 CLZ{<cond>} <Rd>, <Rm>
3276 Condition defaults to COND_ALWAYS.
3277 Error if Rd or Rm are R15. */
3284 skip_whitespace (str
);
3286 if (((rd
= reg_required_here (& str
, 12)) == FAIL
)
3287 || (skip_past_comma (& str
) == FAIL
)
3288 || ((rm
= reg_required_here (& str
, 0)) == FAIL
))
3289 inst
.error
= BAD_ARGS
;
3291 else if (rd
== REG_PC
|| rm
== REG_PC
)
3292 inst
.error
= BAD_PC
;
3298 /* ARM V5 (argument parse)
3299 LDC2{L} <coproc>, <CRd>, <addressing mode>
3300 STC2{L} <coproc>, <CRd>, <addressing mode>
3301 Instruction is not conditional, and has 0xf in the condition field.
3302 Otherwise, it's the same as LDC/STC. */
3305 do_lstc2 (char * str
)
3307 skip_whitespace (str
);
3309 if (co_proc_number (& str
) == FAIL
)
3312 inst
.error
= BAD_ARGS
;
3314 else if (skip_past_comma (& str
) == FAIL
3315 || cp_reg_required_here (& str
, 12) == FAIL
)
3318 inst
.error
= BAD_ARGS
;
3320 else if (skip_past_comma (& str
) == FAIL
3321 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
3324 inst
.error
= BAD_ARGS
;
3330 /* ARM V5 (argument parse)
3331 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
3332 Instruction is not conditional, and has 0xf in the condition field.
3333 Otherwise, it's the same as CDP. */
3336 do_cdp2 (char * str
)
3338 skip_whitespace (str
);
3340 if (co_proc_number (& str
) == FAIL
)
3343 inst
.error
= BAD_ARGS
;
3347 if (skip_past_comma (& str
) == FAIL
3348 || cp_opc_expr (& str
, 20,4) == FAIL
)
3351 inst
.error
= BAD_ARGS
;
3355 if (skip_past_comma (& str
) == FAIL
3356 || cp_reg_required_here (& str
, 12) == FAIL
)
3359 inst
.error
= BAD_ARGS
;
3363 if (skip_past_comma (& str
) == FAIL
3364 || cp_reg_required_here (& str
, 16) == FAIL
)
3367 inst
.error
= BAD_ARGS
;
3371 if (skip_past_comma (& str
) == FAIL
3372 || cp_reg_required_here (& str
, 0) == FAIL
)
3375 inst
.error
= BAD_ARGS
;
3379 if (skip_past_comma (& str
) == SUCCESS
)
3381 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
3384 inst
.error
= BAD_ARGS
;
3392 /* ARM V5 (argument parse)
3393 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3394 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3395 Instruction is not conditional, and has 0xf in the condition field.
3396 Otherwise, it's the same as MCR/MRC. */
3399 do_co_reg2 (char * str
)
3401 skip_whitespace (str
);
3403 if (co_proc_number (& str
) == FAIL
)
3406 inst
.error
= BAD_ARGS
;
3410 if (skip_past_comma (& str
) == FAIL
3411 || cp_opc_expr (& str
, 21, 3) == FAIL
)
3414 inst
.error
= BAD_ARGS
;
3418 if (skip_past_comma (& str
) == FAIL
3419 || reg_required_here (& str
, 12) == FAIL
)
3422 inst
.error
= BAD_ARGS
;
3426 if (skip_past_comma (& str
) == FAIL
3427 || cp_reg_required_here (& str
, 16) == FAIL
)
3430 inst
.error
= BAD_ARGS
;
3434 if (skip_past_comma (& str
) == FAIL
3435 || cp_reg_required_here (& str
, 0) == FAIL
)
3438 inst
.error
= BAD_ARGS
;
3442 if (skip_past_comma (& str
) == SUCCESS
)
3444 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
3447 inst
.error
= BAD_ARGS
;
3460 skip_whitespace (str
);
3462 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
3464 inst
.error
= BAD_ARGS
;
3468 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
3470 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
3475 /* ARM v5TEJ. Jump to Jazelle code. */
3482 skip_whitespace (str
);
3484 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
3486 inst
.error
= BAD_ARGS
;
3490 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
3492 as_tsktsk (_("use of r15 in bxj is not really useful"));
3497 /* ARM V6 umaal (argument parse). */
3500 do_umaal (char * str
)
3502 int rdlo
, rdhi
, rm
, rs
;
3504 skip_whitespace (str
);
3505 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
3506 || skip_past_comma (& str
) == FAIL
3507 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
3508 || skip_past_comma (& str
) == FAIL
3509 || (rm
= reg_required_here (& str
, 0)) == FAIL
3510 || skip_past_comma (& str
) == FAIL
3511 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
3513 inst
.error
= BAD_ARGS
;
3517 if (rdlo
== REG_PC
|| rdhi
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
3519 inst
.error
= BAD_PC
;
3526 /* ARM V6 strex (argument parse). */
3529 do_strex (char * str
)
3533 /* Parse Rd, Rm,. */
3534 skip_whitespace (str
);
3535 if ((rd
= reg_required_here (& str
, 12)) == FAIL
3536 || skip_past_comma (& str
) == FAIL
3537 || (rm
= reg_required_here (& str
, 0)) == FAIL
3538 || skip_past_comma (& str
) == FAIL
)
3540 inst
.error
= BAD_ARGS
;
3543 if (rd
== REG_PC
|| rm
== REG_PC
)
3545 inst
.error
= BAD_PC
;
3550 inst
.error
= _("Rd equal to Rm or Rn yields unpredictable results");
3554 /* Skip past '['. */
3555 if ((strlen (str
) >= 1)
3556 && strncmp (str
, "[", 1) == 0)
3559 skip_whitespace (str
);
3562 if ((rn
= reg_required_here (& str
, 16)) == FAIL
)
3564 inst
.error
= BAD_ARGS
;
3567 else if (rn
== REG_PC
)
3569 inst
.error
= BAD_PC
;
3574 inst
.error
= _("Rd equal to Rm or Rn yields unpredictable results");
3577 skip_whitespace (str
);
3579 /* Skip past ']'. */
3580 if ((strlen (str
) >= 1)
3581 && strncmp (str
, "]", 1) == 0)
3587 /* KIND indicates what kind of shifts are accepted. */
3590 decode_shift (char ** str
, int kind
)
3592 const struct asm_shift_name
* shift
;
3596 skip_whitespace (* str
);
3598 for (p
= * str
; ISALPHA (* p
); p
++)
3603 inst
.error
= _("shift expression expected");
3609 shift
= (const struct asm_shift_name
*) hash_find (arm_shift_hsh
, * str
);
3614 inst
.error
= _("shift expression expected");
3618 assert (shift
->properties
->index
== shift_properties
[shift
->properties
->index
].index
);
3620 if (kind
== SHIFT_LSL_OR_ASR_IMMEDIATE
3621 && shift
->properties
->index
!= SHIFT_LSL
3622 && shift
->properties
->index
!= SHIFT_ASR
)
3624 inst
.error
= _("'LSL' or 'ASR' required");
3627 else if (kind
== SHIFT_LSL_IMMEDIATE
3628 && shift
->properties
->index
!= SHIFT_LSL
)
3630 inst
.error
= _("'LSL' required");
3633 else if (kind
== SHIFT_ASR_IMMEDIATE
3634 && shift
->properties
->index
!= SHIFT_ASR
)
3636 inst
.error
= _("'ASR' required");
3640 if (shift
->properties
->index
== SHIFT_RRX
)
3643 inst
.instruction
|= shift
->properties
->bit_field
;
3647 skip_whitespace (p
);
3649 if (kind
== NO_SHIFT_RESTRICT
&& reg_required_here (& p
, 8) != FAIL
)
3651 inst
.instruction
|= shift
->properties
->bit_field
| SHIFT_BY_REG
;
3655 else if (! is_immediate_prefix (* p
))
3657 inst
.error
= (NO_SHIFT_RESTRICT
3658 ? _("shift requires register or #expression")
3659 : _("shift requires #expression"));
3667 if (my_get_expression (& inst
.reloc
.exp
, & p
))
3670 /* Validate some simple #expressions. */
3671 if (inst
.reloc
.exp
.X_op
== O_constant
)
3673 unsigned num
= inst
.reloc
.exp
.X_add_number
;
3675 /* Reject operations greater than 32. */
3677 /* Reject a shift of 0 unless the mode allows it. */
3678 || (num
== 0 && shift
->properties
->allows_0
== 0)
3679 /* Reject a shift of 32 unless the mode allows it. */
3680 || (num
== 32 && shift
->properties
->allows_32
== 0)
3683 /* As a special case we allow a shift of zero for
3684 modes that do not support it to be recoded as an
3685 logical shift left of zero (ie nothing). We warn
3686 about this though. */
3689 as_warn (_("shift of 0 ignored."));
3690 shift
= & shift_names
[0];
3691 assert (shift
->properties
->index
== SHIFT_LSL
);
3695 inst
.error
= _("invalid immediate shift");
3700 /* Shifts of 32 are encoded as 0, for those shifts that
3705 inst
.instruction
|= (num
<< 7) | shift
->properties
->bit_field
;
3709 inst
.reloc
.type
= BFD_RELOC_ARM_SHIFT_IMM
;
3710 inst
.reloc
.pc_rel
= 0;
3711 inst
.instruction
|= shift
->properties
->bit_field
;
3719 do_sat (char ** str
, int bias
)
3724 skip_whitespace (*str
);
3726 /* Parse <Rd>, field. */
3727 if ((rd
= reg_required_here (str
, 12)) == FAIL
3728 || skip_past_comma (str
) == FAIL
)
3730 inst
.error
= BAD_ARGS
;
3735 inst
.error
= BAD_PC
;
3739 /* Parse #<immed>, field. */
3740 if (is_immediate_prefix (**str
))
3744 inst
.error
= _("immediate expression expected");
3747 if (my_get_expression (&expr
, str
))
3749 inst
.error
= _("bad expression");
3752 if (expr
.X_op
!= O_constant
)
3754 inst
.error
= _("constant expression expected");
3757 if (expr
.X_add_number
+ bias
< 0
3758 || expr
.X_add_number
+ bias
> 31)
3760 inst
.error
= _("immediate value out of range");
3763 inst
.instruction
|= (expr
.X_add_number
+ bias
) << 16;
3764 if (skip_past_comma (str
) == FAIL
)
3766 inst
.error
= BAD_ARGS
;
3770 /* Parse <Rm> field. */
3771 if ((rm
= reg_required_here (str
, 0)) == FAIL
)
3773 inst
.error
= BAD_ARGS
;
3778 inst
.error
= BAD_PC
;
3782 if (skip_past_comma (str
) == SUCCESS
)
3783 decode_shift (str
, SHIFT_LSL_OR_ASR_IMMEDIATE
);
3786 /* ARM V6 ssat (argument parse). */
3789 do_ssat (char * str
)
3791 do_sat (&str
, /*bias=*/-1);
3795 /* ARM V6 usat (argument parse). */
3798 do_usat (char * str
)
3800 do_sat (&str
, /*bias=*/0);
3805 do_sat16 (char ** str
, int bias
)
3810 skip_whitespace (*str
);
3812 /* Parse the <Rd> field. */
3813 if ((rd
= reg_required_here (str
, 12)) == FAIL
3814 || skip_past_comma (str
) == FAIL
)
3816 inst
.error
= BAD_ARGS
;
3821 inst
.error
= BAD_PC
;
3825 /* Parse #<immed>, field. */
3826 if (is_immediate_prefix (**str
))
3830 inst
.error
= _("immediate expression expected");
3833 if (my_get_expression (&expr
, str
))
3835 inst
.error
= _("bad expression");
3838 if (expr
.X_op
!= O_constant
)
3840 inst
.error
= _("constant expression expected");
3843 if (expr
.X_add_number
+ bias
< 0
3844 || expr
.X_add_number
+ bias
> 15)
3846 inst
.error
= _("immediate value out of range");
3849 inst
.instruction
|= (expr
.X_add_number
+ bias
) << 16;
3850 if (skip_past_comma (str
) == FAIL
)
3852 inst
.error
= BAD_ARGS
;
3856 /* Parse <Rm> field. */
3857 if ((rm
= reg_required_here (str
, 0)) == FAIL
)
3859 inst
.error
= BAD_ARGS
;
3864 inst
.error
= BAD_PC
;
3869 /* ARM V6 ssat16 (argument parse). */
3872 do_ssat16 (char * str
)
3874 do_sat16 (&str
, /*bias=*/-1);
3879 do_usat16 (char * str
)
3881 do_sat16 (&str
, /*bias=*/0);
3886 do_cps_mode (char ** str
)
3890 skip_whitespace (*str
);
3892 if (! is_immediate_prefix (**str
))
3894 inst
.error
= _("immediate expression expected");
3898 (*str
)++; /* Strip off the immediate signifier. */
3899 if (my_get_expression (&expr
, str
))
3901 inst
.error
= _("bad expression");
3905 if (expr
.X_op
!= O_constant
)
3907 inst
.error
= _("constant expression expected");
3911 /* The mode is a 5 bit field. Valid values are 0-31. */
3912 if (((unsigned) expr
.X_add_number
) > 31
3913 || (inst
.reloc
.exp
.X_add_number
) < 0)
3915 inst
.error
= _("invalid constant");
3919 inst
.instruction
|= expr
.X_add_number
;
3922 /* ARM V6 srs (argument parse). */
3928 skip_whitespace (str
);
3929 exclam
= strchr (str
, '!');
3937 inst
.instruction
|= WRITE_BACK
;
3943 /* ARM V6 SMMUL (argument parse). */
3946 do_smmul (char * str
)
3950 skip_whitespace (str
);
3951 if ((rd
= reg_required_here (&str
, 16)) == FAIL
3952 || skip_past_comma (&str
) == FAIL
3953 || (rm
= reg_required_here (&str
, 0)) == FAIL
3954 || skip_past_comma (&str
) == FAIL
3955 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
3957 inst
.error
= BAD_ARGS
;
3965 inst
.error
= BAD_PC
;
3972 /* ARM V6 SMLALD (argument parse). */
3975 do_smlald (char * str
)
3977 int rdlo
, rdhi
, rm
, rs
;
3979 skip_whitespace (str
);
3980 if ((rdlo
= reg_required_here (&str
, 12)) == FAIL
3981 || skip_past_comma (&str
) == FAIL
3982 || (rdhi
= reg_required_here (&str
, 16)) == FAIL
3983 || skip_past_comma (&str
) == FAIL
3984 || (rm
= reg_required_here (&str
, 0)) == FAIL
3985 || skip_past_comma (&str
) == FAIL
3986 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
3988 inst
.error
= BAD_ARGS
;
3997 inst
.error
= BAD_PC
;
4004 /* ARM V6 SMLAD (argument parse). Signed multiply accumulate dual.
4005 smlad{x}{<cond>} Rd, Rm, Rs, Rn */
4008 do_smlad (char * str
)
4012 skip_whitespace (str
);
4013 if ((rd
= reg_required_here (&str
, 16)) == FAIL
4014 || skip_past_comma (&str
) == FAIL
4015 || (rm
= reg_required_here (&str
, 0)) == FAIL
4016 || skip_past_comma (&str
) == FAIL
4017 || (rs
= reg_required_here (&str
, 8)) == FAIL
4018 || skip_past_comma (&str
) == FAIL
4019 || (rn
= reg_required_here (&str
, 12)) == FAIL
)
4021 inst
.error
= BAD_ARGS
;
4030 inst
.error
= BAD_PC
;
4037 /* Returns true if the endian-specifier indicates big-endianness. */
4040 do_endian_specifier (char * str
)
4044 skip_whitespace (str
);
4045 if (strlen (str
) < 2)
4046 inst
.error
= _("missing endian specifier");
4047 else if (strncasecmp (str
, "BE", 2) == 0)
4052 else if (strncasecmp (str
, "LE", 2) == 0)
4055 inst
.error
= _("valid endian specifiers are be or le");
4062 /* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
4063 preserving the other bits.
4065 setend <endian_specifier>, where <endian_specifier> is either
4069 do_setend (char * str
)
4071 if (do_endian_specifier (str
))
4072 inst
.instruction
|= 0x200;
4077 SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
4078 Condition defaults to COND_ALWAYS.
4079 Error if any register uses R15. */
4082 do_sxth (char * str
)
4086 int rotation_clear_mask
= 0xfffff3ff;
4087 int rotation_eight_mask
= 0x00000400;
4088 int rotation_sixteen_mask
= 0x00000800;
4089 int rotation_twenty_four_mask
= 0x00000c00;
4091 skip_whitespace (str
);
4092 if ((rd
= reg_required_here (&str
, 12)) == FAIL
4093 || skip_past_comma (&str
) == FAIL
4094 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4096 inst
.error
= BAD_ARGS
;
4100 else if (rd
== REG_PC
|| rm
== REG_PC
)
4102 inst
.error
= BAD_PC
;
4106 /* Zero out the rotation field. */
4107 inst
.instruction
&= rotation_clear_mask
;
4109 /* Check for lack of optional rotation field. */
4110 if (skip_past_comma (&str
) == FAIL
)
4116 /* Move past 'ROR'. */
4117 skip_whitespace (str
);
4118 if (strncasecmp (str
, "ROR", 3) == 0)
4122 inst
.error
= _("missing rotation field after comma");
4126 /* Get the immediate constant. */
4127 skip_whitespace (str
);
4128 if (is_immediate_prefix (* str
))
4132 inst
.error
= _("immediate expression expected");
4136 if (my_get_expression (&expr
, &str
))
4138 inst
.error
= _("bad expression");
4142 if (expr
.X_op
!= O_constant
)
4144 inst
.error
= _("constant expression expected");
4148 switch (expr
.X_add_number
)
4151 /* Rotation field has already been zeroed. */
4154 inst
.instruction
|= rotation_eight_mask
;
4158 inst
.instruction
|= rotation_sixteen_mask
;
4162 inst
.instruction
|= rotation_twenty_four_mask
;
4166 inst
.error
= _("rotation can be 8, 16, 24 or 0 when field is ommited");
4173 /* ARM V6 SXTAH extracts a 16-bit value from a register, sign
4174 extends it to 32-bits, and adds the result to a value in another
4175 register. You can specify a rotation by 0, 8, 16, or 24 bits
4176 before extracting the 16-bit value.
4177 SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
4178 Condition defaults to COND_ALWAYS.
4179 Error if any register uses R15. */
4182 do_sxtah (char * str
)
4186 int rotation_clear_mask
= 0xfffff3ff;
4187 int rotation_eight_mask
= 0x00000400;
4188 int rotation_sixteen_mask
= 0x00000800;
4189 int rotation_twenty_four_mask
= 0x00000c00;
4191 skip_whitespace (str
);
4192 if ((rd
= reg_required_here (&str
, 12)) == FAIL
4193 || skip_past_comma (&str
) == FAIL
4194 || (rn
= reg_required_here (&str
, 16)) == FAIL
4195 || skip_past_comma (&str
) == FAIL
4196 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4198 inst
.error
= BAD_ARGS
;
4202 else if (rd
== REG_PC
|| rn
== REG_PC
|| rm
== REG_PC
)
4204 inst
.error
= BAD_PC
;
4208 /* Zero out the rotation field. */
4209 inst
.instruction
&= rotation_clear_mask
;
4211 /* Check for lack of optional rotation field. */
4212 if (skip_past_comma (&str
) == FAIL
)
4218 /* Move past 'ROR'. */
4219 skip_whitespace (str
);
4220 if (strncasecmp (str
, "ROR", 3) == 0)
4224 inst
.error
= _("missing rotation field after comma");
4228 /* Get the immediate constant. */
4229 skip_whitespace (str
);
4230 if (is_immediate_prefix (* str
))
4234 inst
.error
= _("immediate expression expected");
4238 if (my_get_expression (&expr
, &str
))
4240 inst
.error
= _("bad expression");
4244 if (expr
.X_op
!= O_constant
)
4246 inst
.error
= _("constant expression expected");
4250 switch (expr
.X_add_number
)
4253 /* Rotation field has already been zeroed. */
4257 inst
.instruction
|= rotation_eight_mask
;
4261 inst
.instruction
|= rotation_sixteen_mask
;
4265 inst
.instruction
|= rotation_twenty_four_mask
;
4269 inst
.error
= _("rotation can be 8, 16, 24 or 0 when field is ommited");
4277 /* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
4278 word at the specified address and the following word
4280 Unconditionally executed.
4281 Error if Rn is R15. */
4288 skip_whitespace (str
);
4290 if ((rn
= reg_required_here (&str
, 16)) == FAIL
)
4295 inst
.error
= BAD_PC
;
4299 skip_whitespace (str
);
4303 inst
.instruction
|= WRITE_BACK
;
4309 /* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
4310 register (argument parse).
4312 Condition defaults to COND_ALWAYS.
4313 Error if Rd or Rm are R15. */
4320 skip_whitespace (str
);
4322 if ((rd
= reg_required_here (&str
, 12)) == FAIL
4323 || skip_past_comma (&str
) == FAIL
4324 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4325 inst
.error
= BAD_ARGS
;
4327 else if (rd
== REG_PC
|| rm
== REG_PC
)
4328 inst
.error
= BAD_PC
;
4334 /* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
4335 QADD16{<cond>} <Rd>, <Rn>, <Rm>
4336 Condition defaults to COND_ALWAYS.
4337 Error if Rd, Rn or Rm are R15. */
4340 do_qadd16 (char * str
)
4344 skip_whitespace (str
);
4346 if ((rd
= reg_required_here (&str
, 12)) == FAIL
4347 || skip_past_comma (&str
) == FAIL
4348 || (rn
= reg_required_here (&str
, 16)) == FAIL
4349 || skip_past_comma (&str
) == FAIL
4350 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4351 inst
.error
= BAD_ARGS
;
4353 else if (rd
== REG_PC
|| rm
== REG_PC
|| rn
== REG_PC
)
4354 inst
.error
= BAD_PC
;
4361 do_pkh_core (char * str
, int shift
)
4365 skip_whitespace (str
);
4366 if (((rd
= reg_required_here (&str
, 12)) == FAIL
)
4367 || (skip_past_comma (&str
) == FAIL
)
4368 || ((rn
= reg_required_here (&str
, 16)) == FAIL
)
4369 || (skip_past_comma (&str
) == FAIL
)
4370 || ((rm
= reg_required_here (&str
, 0)) == FAIL
))
4372 inst
.error
= BAD_ARGS
;
4376 else if (rd
== REG_PC
|| rn
== REG_PC
|| rm
== REG_PC
)
4378 inst
.error
= BAD_PC
;
4382 /* Check for optional shift immediate constant. */
4383 if (skip_past_comma (&str
) == FAIL
)
4385 if (shift
== SHIFT_ASR_IMMEDIATE
)
4387 /* If the shift specifier is ommited, turn the instruction
4388 into pkhbt rd, rm, rn. First, switch the instruction
4389 code, and clear the rn and rm fields. */
4390 inst
.instruction
&= 0xfff0f010;
4391 /* Now, re-encode the registers. */
4392 inst
.instruction
|= (rm
<< 16) | rn
;
4397 decode_shift (&str
, shift
);
4400 /* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
4401 PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
4402 Condition defaults to COND_ALWAYS.
4403 Error if Rd, Rn or Rm are R15. */
4406 do_pkhbt (char * str
)
4408 do_pkh_core (str
, SHIFT_LSL_IMMEDIATE
);
4411 /* ARM V6 PKHTB (Argument Parse). */
4414 do_pkhtb (char * str
)
4416 do_pkh_core (str
, SHIFT_ASR_IMMEDIATE
);
4419 /* ARM V6 Load Register Exclusive instruction (argument parse).
4420 LDREX{,B,D,H}{<cond>} <Rd, [<Rn>]
4421 Condition defaults to COND_ALWAYS.
4422 Error if Rd or Rn are R15.
4423 See ARMARMv6 A4.1.27: LDREX. */
4426 do_ldrex (char * str
)
4430 skip_whitespace (str
);
4433 if (((rd
= reg_required_here (&str
, 12)) == FAIL
)
4434 || (skip_past_comma (&str
) == FAIL
))
4436 inst
.error
= BAD_ARGS
;
4439 else if (rd
== REG_PC
)
4441 inst
.error
= BAD_PC
;
4444 skip_whitespace (str
);
4446 /* Skip past '['. */
4447 if ((strlen (str
) >= 1)
4448 &&strncmp (str
, "[", 1) == 0)
4450 skip_whitespace (str
);
4453 if ((rn
= reg_required_here (&str
, 16)) == FAIL
)
4455 inst
.error
= BAD_ARGS
;
4458 else if (rn
== REG_PC
)
4460 inst
.error
= BAD_PC
;
4463 skip_whitespace (str
);
4465 /* Skip past ']'. */
4466 if ((strlen (str
) >= 1)
4467 && strncmp (str
, "]", 1) == 0)
4473 /* ARM V6 change processor state instruction (argument parse)
4474 CPS, CPSIE, CSPID . */
4484 do_cps_flags (char ** str
, int thumb_p
)
4489 unsigned long arm_value
;
4490 unsigned long thumb_value
;
4492 static struct cps_flag flag_table
[] =
4501 skip_whitespace (*str
);
4503 /* Get the a, f and i flags. */
4504 while (**str
&& **str
!= ',')
4507 struct cps_flag
*q
= flag_table
+ sizeof (flag_table
)/sizeof (*p
);
4509 for (p
= flag_table
; p
< q
; ++p
)
4510 if (strncasecmp (*str
, &p
->character
, 1) == 0)
4512 inst
.instruction
|= (thumb_p
? p
->thumb_value
: p
->arm_value
);
4518 inst
.error
= _("unrecognized flag");
4525 inst
.error
= _("no 'a', 'i', or 'f' flags for 'cps'");
4529 do_cpsi (char * str
)
4531 do_cps_flags (&str
, /*thumb_p=*/0);
4533 if (skip_past_comma (&str
) == SUCCESS
)
4535 skip_whitespace (str
);
4541 /* ARM V6T2 bitfield manipulation instructions. */
4544 five_bit_unsigned_immediate (char **str
)
4548 skip_whitespace (*str
);
4549 if (!is_immediate_prefix (**str
))
4551 inst
.error
= _("immediate expression expected");
4555 if (my_get_expression (&expr
, str
))
4557 inst
.error
= _("bad expression");
4560 if (expr
.X_op
!= O_constant
)
4562 inst
.error
= _("constant expression expected");
4565 if (expr
.X_add_number
< 0 || expr
.X_add_number
> 32)
4567 inst
.error
= _("immediate value out of range");
4571 return expr
.X_add_number
;
4575 bfci_lsb_and_width (char *str
)
4579 if ((lsb
= five_bit_unsigned_immediate (&str
)) == -1)
4582 if (skip_past_comma (&str
) == FAIL
)
4584 inst
.error
= BAD_ARGS
;
4587 if ((width
= five_bit_unsigned_immediate (&str
)) == -1)
4592 if (width
== 0 || lsb
== 32)
4594 inst
.error
= _("immediate value out of range");
4597 else if (width
+ lsb
> 32)
4599 inst
.error
= _("bit-field extends past end of register");
4603 /* Convert to LSB/MSB and write to register. */
4604 inst
.instruction
|= lsb
<< 7;
4605 inst
.instruction
|= (width
+ lsb
- 1) << 16;
4614 skip_whitespace (str
);
4615 if (((rd
= reg_required_here (&str
, 12)) == FAIL
)
4616 || (skip_past_comma (&str
) == FAIL
))
4618 inst
.error
= BAD_ARGS
;
4621 else if (rd
== REG_PC
)
4623 inst
.error
= BAD_PC
;
4627 bfci_lsb_and_width (str
);
4636 skip_whitespace (str
);
4637 if (((rd
= reg_required_here (&str
, 12)) == FAIL
)
4638 || (skip_past_comma (&str
) == FAIL
))
4640 inst
.error
= BAD_ARGS
;
4643 else if (rd
== REG_PC
)
4645 inst
.error
= BAD_PC
;
4649 /* Rm. Accept #0 in this position as an alternative syntax for bfc. */
4650 skip_whitespace (str
);
4651 if (is_immediate_prefix (*str
))
4655 if (my_get_expression (&expr
, &str
))
4657 inst
.error
= _("bad expression");
4660 if (expr
.X_op
!= O_constant
)
4662 inst
.error
= _("constant expression expected");
4665 if (expr
.X_add_number
!= 0)
4667 inst
.error
= _("immediate value out of range");
4670 inst
.instruction
|= 0x0000000f; /* Rm = PC -> bfc, not bfi. */
4674 if ((rm
= reg_required_here (&str
, 0)) == FAIL
)
4676 inst
.error
= BAD_ARGS
;
4679 else if (rm
== REG_PC
)
4681 inst
.error
= BAD_PC
;
4685 if (skip_past_comma (&str
) == FAIL
)
4687 inst
.error
= BAD_ARGS
;
4691 bfci_lsb_and_width (str
);
4700 skip_whitespace (str
);
4701 if (reg_required_here (&str
, 12) == FAIL
4702 || skip_past_comma (&str
) == FAIL
)
4704 inst
.error
= BAD_ARGS
;
4709 skip_whitespace (str
);
4710 if (reg_required_here (&str
, 0) == FAIL
4711 || skip_past_comma (&str
) == FAIL
)
4713 inst
.error
= BAD_ARGS
;
4717 if ((lsb
= five_bit_unsigned_immediate (&str
)) == -1)
4720 if (skip_past_comma (&str
) == FAIL
)
4722 inst
.error
= BAD_ARGS
;
4725 if ((width
= five_bit_unsigned_immediate (&str
)) == -1)
4730 if (width
== 0 || lsb
== 32)
4732 inst
.error
= _("immediate value out of range");
4735 else if (width
+ lsb
> 32)
4737 inst
.error
= _("bit-field extends past end of register");
4741 inst
.instruction
|= lsb
<< 7;
4742 inst
.instruction
|= (width
- 1) << 16;
4749 skip_whitespace (str
);
4750 if (reg_required_here (&str
, 12) == FAIL
4751 || skip_past_comma (&str
) == FAIL
)
4753 inst
.error
= BAD_ARGS
;
4758 skip_whitespace (str
);
4759 if (reg_required_here (&str
, 0) == FAIL
)
4761 inst
.error
= BAD_ARGS
;
4768 /* ARM V6T2 16-bit immediate register load: MOV[WT]{cond} Rd, #<imm16>. */
4770 do_mov16 (char *str
)
4776 skip_whitespace (str
);
4777 if (((rd
= reg_required_here (&str
, 12)) == FAIL
)
4778 || (skip_past_comma (&str
) == FAIL
))
4780 inst
.error
= BAD_ARGS
;
4783 else if (rd
== REG_PC
)
4785 inst
.error
= BAD_PC
;
4790 skip_whitespace (str
);
4791 if (!is_immediate_prefix (*str
))
4793 inst
.error
= _("immediate expression expected");
4797 if (my_get_expression (&expr
, &str
))
4799 inst
.error
= _("bad expression");
4802 if (expr
.X_op
!= O_constant
)
4804 inst
.error
= _("constant expression expected");
4807 if (expr
.X_add_number
< 0 || expr
.X_add_number
> 65535)
4809 inst
.error
= _("immediate value out of range");
4815 /* The value is in two pieces: 0:11, 16:19. */
4816 inst
.instruction
|= (expr
.X_add_number
& 0x00000fff);
4817 inst
.instruction
|= (expr
.X_add_number
& 0x0000f000) << 4;
4821 /* THUMB V5 breakpoint instruction (argument parse)
4825 do_t_bkpt (char * str
)
4828 unsigned long number
;
4830 skip_whitespace (str
);
4832 /* Allow optional leading '#'. */
4833 if (is_immediate_prefix (*str
))
4836 memset (& expr
, '\0', sizeof (expr
));
4837 if (my_get_expression (& expr
, & str
)
4838 || (expr
.X_op
!= O_constant
4839 /* As a convenience we allow 'bkpt' without an operand. */
4840 && expr
.X_op
!= O_absent
))
4842 inst
.error
= _("bad expression");
4846 number
= expr
.X_add_number
;
4848 /* Check it fits an 8 bit unsigned. */
4849 if (number
!= (number
& 0xff))
4851 inst
.error
= _("immediate value out of range");
4855 inst
.instruction
|= number
;
4861 static bfd_reloc_code_real_type
4862 arm_parse_reloc (void)
4871 bfd_reloc_code_real_type reloc
;
4875 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
4876 MAP ("(got)", BFD_RELOC_ARM_GOT32
),
4877 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF
),
4878 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
4879 branch instructions generated by GCC for PLT relocs. */
4880 MAP ("(plt)", BFD_RELOC_ARM_PLT32
),
4881 MAP ("(target1)", BFD_RELOC_ARM_TARGET1
),
4882 MAP ("(sbrel)", BFD_RELOC_ARM_SBREL32
),
4883 MAP ("(target2)", BFD_RELOC_ARM_TARGET2
),
4884 { NULL
, 0, BFD_RELOC_UNUSED
}
4888 for (i
= 0, ip
= input_line_pointer
;
4889 i
< sizeof (id
) && (ISALNUM (*ip
) || ISPUNCT (*ip
));
4891 id
[i
] = TOLOWER (*ip
);
4893 for (i
= 0; reloc_map
[i
].str
; i
++)
4894 if (strncmp (id
, reloc_map
[i
].str
, reloc_map
[i
].len
) == 0)
4897 input_line_pointer
+= reloc_map
[i
].len
;
4899 return reloc_map
[i
].reloc
;
4903 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
4904 Expects inst.instruction is set for BLX(1).
4905 Note: this is cloned from do_branch, and the reloc changed to be a
4906 new one that can cope with setting one extra bit (the H bit). */
4909 do_branch25 (char * str
)
4911 if (my_get_expression (& inst
.reloc
.exp
, & str
))
4918 /* ScottB: February 5, 1998 */
4919 /* Check to see of PLT32 reloc required for the instruction. */
4921 /* arm_parse_reloc() works on input_line_pointer.
4922 We actually want to parse the operands to the branch instruction
4923 passed in 'str'. Save the input pointer and restore it later. */
4924 save_in
= input_line_pointer
;
4925 input_line_pointer
= str
;
4927 if (inst
.reloc
.exp
.X_op
== O_symbol
4929 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
4931 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
4932 inst
.reloc
.pc_rel
= 0;
4933 /* Modify str to point to after parsed operands, otherwise
4934 end_of_line() will complain about the (PLT) left in str. */
4935 str
= input_line_pointer
;
4939 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
4940 inst
.reloc
.pc_rel
= 1;
4943 input_line_pointer
= save_in
;
4946 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
4947 inst
.reloc
.pc_rel
= 1;
4948 #endif /* OBJ_ELF */
4953 /* ARM V5 branch-link-exchange instruction (argument parse)
4954 BLX <target_addr> ie BLX(1)
4955 BLX{<condition>} <Rm> ie BLX(2)
4956 Unfortunately, there are two different opcodes for this mnemonic.
4957 So, the insns[].value is not used, and the code here zaps values
4958 into inst.instruction.
4959 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
4967 skip_whitespace (mystr
);
4968 rm
= reg_required_here (& mystr
, 0);
4970 /* The above may set inst.error. Ignore his opinion. */
4975 /* Arg is a register.
4976 Use the condition code our caller put in inst.instruction.
4977 Pass ourselves off as a BX with a funny opcode. */
4978 inst
.instruction
|= 0x012fff30;
4983 /* This must be is BLX <target address>, no condition allowed. */
4984 if (inst
.instruction
!= COND_ALWAYS
)
4986 inst
.error
= BAD_COND
;
4990 inst
.instruction
= 0xfafffffe;
4992 /* Process like a B/BL, but with a different reloc.
4993 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
4998 /* ARM V5 Thumb BLX (argument parse)
4999 BLX <target_addr> which is BLX(1)
5000 BLX <Rm> which is BLX(2)
5001 Unfortunately, there are two different opcodes for this mnemonic.
5002 So, the tinsns[].value is not used, and the code here zaps values
5003 into inst.instruction. */
5006 do_t_blx (char * str
)
5011 skip_whitespace (mystr
);
5012 inst
.instruction
= 0x4780;
5014 /* Note that this call is to the ARM register recognizer. BLX(2)
5015 uses the ARM register space, not the Thumb one, so a call to
5016 thumb_reg() would be wrong. */
5017 rm
= reg_required_here (& mystr
, 3);
5022 /* It's BLX(2). The .instruction was zapped with rm & is final. */
5027 /* No ARM register. This must be BLX(1). Change the .instruction. */
5028 inst
.instruction
= 0xf7ffeffe;
5031 if (my_get_expression (& inst
.reloc
.exp
, & mystr
))
5034 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BLX
;
5035 inst
.reloc
.pc_rel
= 1;
5038 end_of_line (mystr
);
5041 /* ARM V5 breakpoint instruction (argument parse)
5042 BKPT <16 bit unsigned immediate>
5043 Instruction is not conditional.
5044 The bit pattern given in insns[] has the COND_ALWAYS condition,
5045 and it is an error if the caller tried to override that. */
5048 do_bkpt (char * str
)
5051 unsigned long number
;
5053 skip_whitespace (str
);
5055 /* Allow optional leading '#'. */
5056 if (is_immediate_prefix (* str
))
5059 memset (& expr
, '\0', sizeof (expr
));
5061 if (my_get_expression (& expr
, & str
)
5062 || (expr
.X_op
!= O_constant
5063 /* As a convenience we allow 'bkpt' without an operand. */
5064 && expr
.X_op
!= O_absent
))
5066 inst
.error
= _("bad expression");
5070 number
= expr
.X_add_number
;
5072 /* Check it fits a 16 bit unsigned. */
5073 if (number
!= (number
& 0xffff))
5075 inst
.error
= _("immediate value out of range");
5079 /* Top 12 of 16 bits to bits 19:8. */
5080 inst
.instruction
|= (number
& 0xfff0) << 4;
5082 /* Bottom 4 of 16 bits to bits 3:0. */
5083 inst
.instruction
|= number
& 0xf;
5088 /* THUMB CPS instruction (argument parse). */
5091 do_t_cps (char * str
)
5093 do_cps_flags (&str
, /*thumb_p=*/1);
5097 /* Parse and validate that a register is of the right form, this saves
5098 repeated checking of this information in many similar cases.
5099 Unlike the 32-bit case we do not insert the register into the opcode
5100 here, since the position is often unknown until the full instruction
5104 thumb_reg (char ** strp
, int hi_lo
)
5108 if ((reg
= reg_required_here (strp
, -1)) == FAIL
)
5116 inst
.error
= _("lo register required");
5124 inst
.error
= _("hi register required");
5137 thumb_mov_compare (char * str
, int move
)
5141 skip_whitespace (str
);
5143 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
5144 || skip_past_comma (&str
) == FAIL
)
5147 inst
.error
= BAD_ARGS
;
5151 if (move
!= THUMB_CPY
&& is_immediate_prefix (*str
))
5154 if (my_get_expression (&inst
.reloc
.exp
, &str
))
5157 else if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
5162 if (move
!= THUMB_CPY
&& Rs
< 8 && Rd
< 8)
5164 if (move
== THUMB_MOVE
)
5165 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
5166 since a MOV instruction produces unpredictable results. */
5167 inst
.instruction
= T_OPCODE_ADD_I3
;
5169 inst
.instruction
= T_OPCODE_CMP_LR
;
5170 inst
.instruction
|= Rd
| (Rs
<< 3);
5174 if (move
== THUMB_MOVE
)
5175 inst
.instruction
= T_OPCODE_MOV_HR
;
5176 else if (move
!= THUMB_CPY
)
5177 inst
.instruction
= T_OPCODE_CMP_HR
;
5180 inst
.instruction
|= THUMB_H1
;
5183 inst
.instruction
|= THUMB_H2
;
5185 inst
.instruction
|= (Rd
& 7) | ((Rs
& 7) << 3);
5192 inst
.error
= _("only lo regs allowed with immediate");
5196 if (move
== THUMB_MOVE
)
5197 inst
.instruction
= T_OPCODE_MOV_I8
;
5199 inst
.instruction
= T_OPCODE_CMP_I8
;
5201 inst
.instruction
|= Rd
<< 8;
5203 if (inst
.reloc
.exp
.X_op
!= O_constant
)
5204 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_IMM
;
5207 unsigned value
= inst
.reloc
.exp
.X_add_number
;
5211 inst
.error
= _("invalid immediate");
5215 inst
.instruction
|= value
;
5222 /* THUMB CPY instruction (argument parse). */
5225 do_t_cpy (char * str
)
5227 thumb_mov_compare (str
, THUMB_CPY
);
5230 /* THUMB SETEND instruction (argument parse). */
5233 do_t_setend (char * str
)
5235 if (do_endian_specifier (str
))
5236 inst
.instruction
|= 0x8;
5239 /* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
5241 static unsigned long
5242 check_iwmmxt_insn (char * str
,
5243 enum iwmmxt_insn_type insn_type
,
5247 const char * inst_error
;
5249 unsigned long number
;
5251 inst_error
= inst
.error
;
5253 inst
.error
= BAD_ARGS
;
5254 skip_whitespace (str
);
5259 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
5264 if ((wreg_required_here (&str
, 0, IWMMXT_REG_WR
)) == FAIL
)
5269 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
5270 || skip_past_comma (&str
) == FAIL
5271 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
))
5276 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
5277 || skip_past_comma (&str
) == FAIL
5278 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5279 || skip_past_comma (&str
) == FAIL
5280 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
))
5285 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
5286 || skip_past_comma (&str
) == FAIL
5287 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5288 || skip_past_comma (&str
) == FAIL
5289 || wreg_required_here (&str
, 0, IWMMXT_REG_WCG
) == FAIL
))
5294 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5295 || skip_past_comma (&str
) == FAIL
5296 || reg_required_here (&str
, 12) == FAIL
))
5301 if ((reg_required_here (&str
, 12) == FAIL
5302 || skip_past_comma (&str
) == FAIL
5303 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
))
5308 if ((wreg_required_here (&str
, 5, IWMMXT_REG_WR
) == FAIL
5309 || skip_past_comma (&str
) == FAIL
5310 || reg_required_here (&str
, 0) == FAIL
5311 || skip_past_comma (&str
) == FAIL
5312 || reg_required_here (&str
, 12) == FAIL
))
5317 if ((wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
5318 || skip_past_comma (&str
) == FAIL
5319 || reg_required_here (&str
, 12) == FAIL
5320 || skip_past_comma (&str
) == FAIL
5321 || reg_required_here (&str
, 16) == FAIL
))
5326 if ((reg_required_here (&str
, 12) == FAIL
5327 || skip_past_comma (&str
) == FAIL
5328 || reg_required_here (&str
, 16) == FAIL
5329 || skip_past_comma (&str
) == FAIL
5330 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
))
5335 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WC
) == FAIL
5336 || skip_past_comma (&str
) == FAIL
5337 || reg_required_here (&str
, 12) == FAIL
))
5342 if ((reg_required_here (&str
, 12) == FAIL
5343 || skip_past_comma (&str
) == FAIL
5344 || wreg_required_here (&str
, 16, IWMMXT_REG_WC
) == FAIL
))
5349 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5350 || skip_past_comma (&str
) == FAIL
5351 || reg_required_here (&str
, 12) == FAIL
5352 || skip_past_comma (&str
) == FAIL
))
5357 if ((reg_required_here (&str
, 12) == FAIL
5358 || skip_past_comma (&str
) == FAIL
))
5363 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
5364 || skip_past_comma (&str
) == FAIL
5365 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5366 || skip_past_comma (&str
) == FAIL
5367 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
5368 || skip_past_comma (&str
) == FAIL
))
5373 if ((reg_required_here (&str
, 12) == FAIL
5374 || skip_past_comma (&str
) == FAIL
5375 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5376 || skip_past_comma (&str
) == FAIL
))
5381 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
5382 || skip_past_comma (&str
) == FAIL
5383 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5384 || skip_past_comma (&str
) == FAIL
))
5389 if (immediate_size
== 0)
5392 inst
.error
= inst_error
;
5397 skip_whitespace (str
);
5399 /* Allow optional leading '#'. */
5400 if (is_immediate_prefix (* str
))
5403 memset (& expr
, '\0', sizeof (expr
));
5405 if (my_get_expression (& expr
, & str
) || (expr
.X_op
!= O_constant
))
5407 inst
.error
= _("bad or missing expression");
5411 number
= expr
.X_add_number
;
5413 if (number
!= (number
& immediate_size
))
5415 inst
.error
= _("immediate value out of range");
5419 inst
.error
= inst_error
;
5425 do_iwmmxt_byte_addr (char * str
)
5427 int op
= (inst
.instruction
& 0x300) >> 8;
5430 inst
.instruction
&= ~0x300;
5431 inst
.instruction
|= (op
& 1) << 22 | (op
& 2) << 7;
5433 skip_whitespace (str
);
5435 if ((reg
= wreg_required_here (&str
, 12, IWMMXT_REG_WR_OR_WC
)) == FAIL
5436 || skip_past_comma (& str
) == FAIL
5437 || cp_byte_address_required_here (&str
) == FAIL
)
5440 inst
.error
= BAD_ARGS
;
5445 if (wc_register (reg
))
5447 as_bad (_("non-word size not supported with control register"));
5448 inst
.instruction
|= 0xf0000100;
5449 inst
.instruction
&= ~0x00400000;
5454 do_iwmmxt_tandc (char * str
)
5458 reg
= check_iwmmxt_insn (str
, check_rd
, 0);
5460 if (reg
!= REG_PC
&& !inst
.error
)
5461 inst
.error
= _("only r15 allowed here");
5465 do_iwmmxt_tbcst (char * str
)
5467 check_iwmmxt_insn (str
, check_tbcst
, 0);
5471 do_iwmmxt_textrc (char * str
)
5473 unsigned long number
;
5475 if ((number
= check_iwmmxt_insn (str
, check_textrc
, 7)) == (unsigned long) FAIL
)
5478 inst
.instruction
|= number
& 0x7;
5482 do_iwmmxt_textrm (char * str
)
5484 unsigned long number
;
5486 if ((number
= check_iwmmxt_insn (str
, check_textrm
, 7)) == (unsigned long) FAIL
)
5489 inst
.instruction
|= number
& 0x7;
5493 do_iwmmxt_tinsr (char * str
)
5495 unsigned long number
;
5497 if ((number
= check_iwmmxt_insn (str
, check_tinsr
, 7)) == (unsigned long) FAIL
)
5500 inst
.instruction
|= number
& 0x7;
5504 do_iwmmxt_tmcr (char * str
)
5506 check_iwmmxt_insn (str
, check_tmcr
, 0);
5510 do_iwmmxt_tmcrr (char * str
)
5512 check_iwmmxt_insn (str
, check_tmcrr
, 0);
5516 do_iwmmxt_tmia (char * str
)
5518 check_iwmmxt_insn (str
, check_tmia
, 0);
5522 do_iwmmxt_tmovmsk (char * str
)
5524 check_iwmmxt_insn (str
, check_tmovmsk
, 0);
5528 do_iwmmxt_tmrc (char * str
)
5530 check_iwmmxt_insn (str
, check_tmrc
, 0);
5534 do_iwmmxt_tmrrc (char * str
)
5536 check_iwmmxt_insn (str
, check_tmrrc
, 0);
5540 do_iwmmxt_torc (char * str
)
5542 check_iwmmxt_insn (str
, check_rd
, 0);
5546 do_iwmmxt_waligni (char * str
)
5548 unsigned long number
;
5550 if ((number
= check_iwmmxt_insn (str
, check_waligni
, 7)) == (unsigned long) FAIL
)
5553 inst
.instruction
|= ((number
& 0x7) << 20);
5557 do_iwmmxt_wmov (char * str
)
5559 if (check_iwmmxt_insn (str
, check_wrwr
, 0) == (unsigned long) FAIL
)
5562 inst
.instruction
|= ((inst
.instruction
>> 16) & 0xf);
5566 do_iwmmxt_word_addr (char * str
)
5568 int op
= (inst
.instruction
& 0x300) >> 8;
5571 inst
.instruction
&= ~0x300;
5572 inst
.instruction
|= (op
& 1) << 22 | (op
& 2) << 7;
5574 skip_whitespace (str
);
5576 if ((reg
= wreg_required_here (&str
, 12, IWMMXT_REG_WR_OR_WC
)) == FAIL
5577 || skip_past_comma (& str
) == FAIL
5578 || cp_address_required_here (& str
, CP_WB_OK
) == FAIL
)
5581 inst
.error
= BAD_ARGS
;
5586 if (wc_register (reg
))
5588 if ((inst
.instruction
& COND_MASK
) != COND_ALWAYS
)
5589 as_bad (_("conditional execution not supported with control register"));
5591 as_bad (_("non-word size not supported with control register"));
5592 inst
.instruction
|= 0xf0000100;
5593 inst
.instruction
&= ~0x00400000;
5598 do_iwmmxt_wrwr (char * str
)
5600 check_iwmmxt_insn (str
, check_wrwr
, 0);
5604 do_iwmmxt_wrwrwcg (char * str
)
5606 check_iwmmxt_insn (str
, check_wrwrwcg
, 0);
5610 do_iwmmxt_wrwrwr (char * str
)
5612 check_iwmmxt_insn (str
, check_wrwrwr
, 0);
5616 do_iwmmxt_wshufh (char * str
)
5618 unsigned long number
;
5620 if ((number
= check_iwmmxt_insn (str
, check_wshufh
, 0xff)) == (unsigned long) FAIL
)
5623 inst
.instruction
|= ((number
& 0xf0) << 16) | (number
& 0xf);
5627 do_iwmmxt_wzero (char * str
)
5629 if (check_iwmmxt_insn (str
, check_wr
, 0) == (unsigned long) FAIL
)
5632 inst
.instruction
|= ((inst
.instruction
& 0xf) << 12) | ((inst
.instruction
& 0xf) << 16);
5635 /* Xscale multiply-accumulate (argument parse)
5638 MIAxycc acc0,Rm,Rs. */
5641 do_xsc_mia (char * str
)
5646 if (accum0_required_here (& str
) == FAIL
)
5647 inst
.error
= ERR_NO_ACCUM
;
5649 else if (skip_past_comma (& str
) == FAIL
5650 || (rm
= reg_required_here (& str
, 0)) == FAIL
)
5651 inst
.error
= BAD_ARGS
;
5653 else if (skip_past_comma (& str
) == FAIL
5654 || (rs
= reg_required_here (& str
, 12)) == FAIL
)
5655 inst
.error
= BAD_ARGS
;
5657 /* inst.instruction has now been zapped with both rm and rs. */
5658 else if (rm
== REG_PC
|| rs
== REG_PC
)
5659 inst
.error
= BAD_PC
; /* Undefined result if rm or rs is R15. */
5665 /* Xscale move-accumulator-register (argument parse)
5667 MARcc acc0,RdLo,RdHi. */
5670 do_xsc_mar (char * str
)
5674 if (accum0_required_here (& str
) == FAIL
)
5675 inst
.error
= ERR_NO_ACCUM
;
5677 else if (skip_past_comma (& str
) == FAIL
5678 || (rdlo
= reg_required_here (& str
, 12)) == FAIL
)
5679 inst
.error
= BAD_ARGS
;
5681 else if (skip_past_comma (& str
) == FAIL
5682 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
5683 inst
.error
= BAD_ARGS
;
5685 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5686 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
5687 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
5693 /* Xscale move-register-accumulator (argument parse)
5695 MRAcc RdLo,RdHi,acc0. */
5698 do_xsc_mra (char * str
)
5703 skip_whitespace (str
);
5705 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
)
5706 inst
.error
= BAD_ARGS
;
5708 else if (skip_past_comma (& str
) == FAIL
5709 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
5710 inst
.error
= BAD_ARGS
;
5712 else if (skip_past_comma (& str
) == FAIL
5713 || accum0_required_here (& str
) == FAIL
)
5714 inst
.error
= ERR_NO_ACCUM
;
5716 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5717 else if (rdlo
== rdhi
)
5718 inst
.error
= BAD_ARGS
; /* Undefined result if 2 writes to same reg. */
5720 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
5721 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
5727 ldst_extend (char ** str
)
5736 if (my_get_expression (& inst
.reloc
.exp
, str
))
5739 if (inst
.reloc
.exp
.X_op
== O_constant
)
5741 int value
= inst
.reloc
.exp
.X_add_number
;
5743 if (value
< -4095 || value
> 4095)
5745 inst
.error
= _("address offset too large");
5755 inst
.instruction
|= add
| value
;
5759 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
5760 inst
.reloc
.pc_rel
= 0;
5773 if (reg_required_here (str
, 0) == FAIL
)
5776 inst
.instruction
|= add
| OFFSET_REG
;
5777 if (skip_past_comma (str
) == SUCCESS
)
5778 return decode_shift (str
, SHIFT_IMMEDIATE
);
5784 /* ARMv5TE: Preload-Cache
5788 Syntactically, like LDR with B=1, W=0, L=1. */
5795 skip_whitespace (str
);
5799 inst
.error
= _("'[' expected after PLD mnemonic");
5804 skip_whitespace (str
);
5806 if ((rd
= reg_required_here (& str
, 16)) == FAIL
)
5809 skip_whitespace (str
);
5815 skip_whitespace (str
);
5817 /* Post-indexed addressing is not allowed with PLD. */
5818 if (skip_past_comma (&str
) == SUCCESS
)
5821 = _("post-indexed expression used in preload instruction");
5824 else if (*str
== '!') /* [Rn]! */
5826 inst
.error
= _("writeback used in preload instruction");
5830 inst
.instruction
|= INDEX_UP
| PRE_INDEX
;
5832 else /* [Rn, ...] */
5834 if (skip_past_comma (& str
) == FAIL
)
5836 inst
.error
= _("pre-indexed expression expected");
5840 if (ldst_extend (&str
) == FAIL
)
5843 skip_whitespace (str
);
5847 inst
.error
= _("missing ]");
5852 skip_whitespace (str
);
5854 if (* str
== '!') /* [Rn]! */
5856 inst
.error
= _("writeback used in preload instruction");
5860 inst
.instruction
|= PRE_INDEX
;
5866 /* ARMv5TE load-consecutive (argument parse)
5873 do_ldrd (char * str
)
5878 skip_whitespace (str
);
5880 if ((rd
= reg_required_here (& str
, 12)) == FAIL
)
5882 inst
.error
= BAD_ARGS
;
5886 if (skip_past_comma (& str
) == FAIL
5887 || (rn
= ld_mode_required_here (& str
)) == FAIL
)
5890 inst
.error
= BAD_ARGS
;
5894 /* inst.instruction has now been zapped with Rd and the addressing mode. */
5895 if (rd
& 1) /* Unpredictable result if Rd is odd. */
5897 inst
.error
= _("destination register must be even");
5903 inst
.error
= _("r14 not allowed here");
5907 if (((rd
== rn
) || (rd
+ 1 == rn
))
5908 && ((inst
.instruction
& WRITE_BACK
)
5909 || (!(inst
.instruction
& PRE_INDEX
))))
5910 as_warn (_("pre/post-indexing used when modified address register is destination"));
5912 /* For an index-register load, the index register must not overlap the
5913 destination (even if not write-back). */
5914 if ((inst
.instruction
& V4_STR_BIT
) == 0
5915 && (inst
.instruction
& HWOFFSET_IMM
) == 0)
5917 int rm
= inst
.instruction
& 0x0000000f;
5919 if (rm
== rd
|| (rm
== rd
+ 1))
5920 as_warn (_("ldrd destination registers must not overlap index register"));
5926 /* Returns the index into fp_values of a floating point number,
5927 or -1 if not in the table. */
5930 my_get_float_expression (char ** str
)
5932 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
5938 memset (words
, 0, MAX_LITTLENUMS
* sizeof (LITTLENUM_TYPE
));
5940 /* Look for a raw floating point number. */
5941 if ((save_in
= atof_ieee (*str
, 'x', words
)) != NULL
5942 && is_end_of_line
[(unsigned char) *save_in
])
5944 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
5946 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
5948 if (words
[j
] != fp_values
[i
][j
])
5952 if (j
== MAX_LITTLENUMS
)
5960 /* Try and parse a more complex expression, this will probably fail
5961 unless the code uses a floating point prefix (eg "0f"). */
5962 save_in
= input_line_pointer
;
5963 input_line_pointer
= *str
;
5964 if (expression (&exp
) == absolute_section
5965 && exp
.X_op
== O_big
5966 && exp
.X_add_number
< 0)
5968 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
5970 if (gen_to_words (words
, 5, (long) 15) == 0)
5972 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
5974 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
5976 if (words
[j
] != fp_values
[i
][j
])
5980 if (j
== MAX_LITTLENUMS
)
5982 *str
= input_line_pointer
;
5983 input_line_pointer
= save_in
;
5990 *str
= input_line_pointer
;
5991 input_line_pointer
= save_in
;
5995 /* We handle all bad expressions here, so that we can report the faulty
5996 instruction in the error message. */
5998 md_operand (expressionS
* expr
)
6000 if (in_my_get_expression
)
6002 expr
->X_op
= O_illegal
;
6003 if (inst
.error
== NULL
)
6004 inst
.error
= _("bad expression");
6008 /* Do those data_ops which can take a negative immediate constant
6009 by altering the instruction. A bit of a hack really.
6013 by inverting the second operand, and
6016 by negating the second operand. */
6019 negate_data_op (unsigned long * instruction
,
6020 unsigned long value
)
6023 unsigned long negated
, inverted
;
6025 negated
= validate_immediate (-value
);
6026 inverted
= validate_immediate (~value
);
6028 op
= (*instruction
>> DATA_OP_SHIFT
) & 0xf;
6031 /* First negates. */
6032 case OPCODE_SUB
: /* ADD <-> SUB */
6033 new_inst
= OPCODE_ADD
;
6038 new_inst
= OPCODE_SUB
;
6042 case OPCODE_CMP
: /* CMP <-> CMN */
6043 new_inst
= OPCODE_CMN
;
6048 new_inst
= OPCODE_CMP
;
6052 /* Now Inverted ops. */
6053 case OPCODE_MOV
: /* MOV <-> MVN */
6054 new_inst
= OPCODE_MVN
;
6059 new_inst
= OPCODE_MOV
;
6063 case OPCODE_AND
: /* AND <-> BIC */
6064 new_inst
= OPCODE_BIC
;
6069 new_inst
= OPCODE_AND
;
6073 case OPCODE_ADC
: /* ADC <-> SBC */
6074 new_inst
= OPCODE_SBC
;
6079 new_inst
= OPCODE_ADC
;
6083 /* We cannot do anything. */
6088 if (value
== (unsigned) FAIL
)
6091 *instruction
&= OPCODE_MASK
;
6092 *instruction
|= new_inst
<< DATA_OP_SHIFT
;
6097 data_op2 (char ** str
)
6102 skip_whitespace (* str
);
6104 if (reg_required_here (str
, 0) != FAIL
)
6106 if (skip_past_comma (str
) == SUCCESS
)
6107 /* Shift operation on register. */
6108 return decode_shift (str
, NO_SHIFT_RESTRICT
);
6114 /* Immediate expression. */
6115 if (is_immediate_prefix (**str
))
6120 if (my_get_expression (&inst
.reloc
.exp
, str
))
6123 if (inst
.reloc
.exp
.X_add_symbol
)
6125 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
6126 inst
.reloc
.pc_rel
= 0;
6130 if (skip_past_comma (str
) == SUCCESS
)
6132 /* #x, y -- ie explicit rotation by Y. */
6133 if (my_get_expression (&expr
, str
))
6136 if (expr
.X_op
!= O_constant
)
6138 inst
.error
= _("constant expression expected");
6142 /* Rotate must be a multiple of 2. */
6143 if (((unsigned) expr
.X_add_number
) > 30
6144 || (expr
.X_add_number
& 1) != 0
6145 || ((unsigned) inst
.reloc
.exp
.X_add_number
) > 255)
6147 inst
.error
= _("invalid constant");
6150 inst
.instruction
|= INST_IMMEDIATE
;
6151 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
6152 inst
.instruction
|= expr
.X_add_number
<< 7;
6156 /* Implicit rotation, select a suitable one. */
6157 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
6161 /* Can't be done. Perhaps the code reads something like
6162 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
6163 if ((value
= negate_data_op (&inst
.instruction
,
6164 inst
.reloc
.exp
.X_add_number
))
6167 inst
.error
= _("invalid constant");
6172 inst
.instruction
|= value
;
6175 inst
.instruction
|= INST_IMMEDIATE
;
6180 inst
.error
= _("register or shift expression expected");
6186 fp_op2 (char ** str
)
6188 skip_whitespace (* str
);
6190 if (fp_reg_required_here (str
, 0) != FAIL
)
6194 /* Immediate expression. */
6195 if (*((*str
)++) == '#')
6201 skip_whitespace (* str
);
6203 /* First try and match exact strings, this is to guarantee
6204 that some formats will work even for cross assembly. */
6206 for (i
= 0; fp_const
[i
]; i
++)
6208 if (strncmp (*str
, fp_const
[i
], strlen (fp_const
[i
])) == 0)
6212 *str
+= strlen (fp_const
[i
]);
6213 if (is_end_of_line
[(unsigned char) **str
])
6215 inst
.instruction
|= i
+ 8;
6222 /* Just because we didn't get a match doesn't mean that the
6223 constant isn't valid, just that it is in a format that we
6224 don't automatically recognize. Try parsing it with
6225 the standard expression routines. */
6226 if ((i
= my_get_float_expression (str
)) >= 0)
6228 inst
.instruction
|= i
+ 8;
6232 inst
.error
= _("invalid floating point immediate expression");
6236 _("floating point register or immediate expression expected");
6242 do_arit (char * str
)
6244 skip_whitespace (str
);
6246 if (reg_required_here (&str
, 12) == FAIL
6247 || skip_past_comma (&str
) == FAIL
6248 || reg_required_here (&str
, 16) == FAIL
6249 || skip_past_comma (&str
) == FAIL
6250 || data_op2 (&str
) == FAIL
)
6253 inst
.error
= BAD_ARGS
;
6263 /* This is a pseudo-op of the form "adr rd, label" to be converted
6264 into a relative address of the form "add rd, pc, #label-.-8". */
6265 skip_whitespace (str
);
6267 if (reg_required_here (&str
, 12) == FAIL
6268 || skip_past_comma (&str
) == FAIL
6269 || my_get_expression (&inst
.reloc
.exp
, &str
))
6272 inst
.error
= BAD_ARGS
;
6276 /* Frag hacking will turn this into a sub instruction if the offset turns
6277 out to be negative. */
6278 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
6280 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust. */
6282 inst
.reloc
.pc_rel
= 1;
6288 do_adrl (char * str
)
6290 /* This is a pseudo-op of the form "adrl rd, label" to be converted
6291 into a relative address of the form:
6292 add rd, pc, #low(label-.-8)"
6293 add rd, rd, #high(label-.-8)" */
6295 skip_whitespace (str
);
6297 if (reg_required_here (&str
, 12) == FAIL
6298 || skip_past_comma (&str
) == FAIL
6299 || my_get_expression (&inst
.reloc
.exp
, &str
))
6302 inst
.error
= BAD_ARGS
;
6308 /* Frag hacking will turn this into a sub instruction if the offset turns
6309 out to be negative. */
6310 inst
.reloc
.type
= BFD_RELOC_ARM_ADRL_IMMEDIATE
;
6312 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust */
6314 inst
.reloc
.pc_rel
= 1;
6315 inst
.size
= INSN_SIZE
* 2;
6321 skip_whitespace (str
);
6323 if (reg_required_here (&str
, 16) == FAIL
)
6326 inst
.error
= BAD_ARGS
;
6330 if (skip_past_comma (&str
) == FAIL
6331 || data_op2 (&str
) == FAIL
)
6334 inst
.error
= BAD_ARGS
;
6344 skip_whitespace (str
);
6346 if (reg_required_here (&str
, 12) == FAIL
)
6349 inst
.error
= BAD_ARGS
;
6353 if (skip_past_comma (&str
) == FAIL
6354 || data_op2 (&str
) == FAIL
)
6357 inst
.error
= BAD_ARGS
;
6365 do_ldst (char * str
)
6371 skip_whitespace (str
);
6373 if ((conflict_reg
= reg_required_here (&str
, 12)) == FAIL
)
6376 inst
.error
= BAD_ARGS
;
6380 if (skip_past_comma (&str
) == FAIL
)
6382 inst
.error
= _("address expected");
6392 skip_whitespace (str
);
6394 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6397 /* Conflicts can occur on stores as well as loads. */
6398 conflict_reg
= (conflict_reg
== reg
);
6400 skip_whitespace (str
);
6406 if (skip_past_comma (&str
) == SUCCESS
)
6408 /* [Rn],... (post inc) */
6409 if (ldst_extend (&str
) == FAIL
)
6412 as_warn (_("%s register same as write-back base"),
6413 ((inst
.instruction
& LOAD_BIT
)
6414 ? _("destination") : _("source")));
6419 skip_whitespace (str
);
6424 as_warn (_("%s register same as write-back base"),
6425 ((inst
.instruction
& LOAD_BIT
)
6426 ? _("destination") : _("source")));
6428 inst
.instruction
|= WRITE_BACK
;
6431 inst
.instruction
|= INDEX_UP
;
6438 if (skip_past_comma (&str
) == FAIL
)
6440 inst
.error
= _("pre-indexed expression expected");
6445 if (ldst_extend (&str
) == FAIL
)
6448 skip_whitespace (str
);
6452 inst
.error
= _("missing ]");
6456 skip_whitespace (str
);
6461 as_warn (_("%s register same as write-back base"),
6462 ((inst
.instruction
& LOAD_BIT
)
6463 ? _("destination") : _("source")));
6465 inst
.instruction
|= WRITE_BACK
;
6469 else if (*str
== '=')
6471 if ((inst
.instruction
& LOAD_BIT
) == 0)
6473 inst
.error
= _("invalid pseudo operation");
6477 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6480 skip_whitespace (str
);
6482 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6485 if (inst
.reloc
.exp
.X_op
!= O_constant
6486 && inst
.reloc
.exp
.X_op
!= O_symbol
)
6488 inst
.error
= _("constant expression expected");
6492 if (inst
.reloc
.exp
.X_op
== O_constant
)
6494 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
6498 /* This can be done with a mov instruction. */
6499 inst
.instruction
&= LITERAL_MASK
;
6500 inst
.instruction
|= (INST_IMMEDIATE
6501 | (OPCODE_MOV
<< DATA_OP_SHIFT
));
6502 inst
.instruction
|= value
& 0xfff;
6507 value
= validate_immediate (~inst
.reloc
.exp
.X_add_number
);
6511 /* This can be done with a mvn instruction. */
6512 inst
.instruction
&= LITERAL_MASK
;
6513 inst
.instruction
|= (INST_IMMEDIATE
6514 | (OPCODE_MVN
<< DATA_OP_SHIFT
));
6515 inst
.instruction
|= value
& 0xfff;
6521 /* Insert into literal pool. */
6522 if (add_to_lit_pool () == FAIL
)
6525 inst
.error
= _("literal pool insertion failed");
6529 /* Change the instruction exp to point to the pool. */
6530 inst
.reloc
.type
= BFD_RELOC_ARM_LITERAL
;
6531 inst
.reloc
.pc_rel
= 1;
6532 inst
.instruction
|= (REG_PC
<< 16);
6537 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6540 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
6542 /* PC rel adjust. */
6543 inst
.reloc
.exp
.X_add_number
-= 8;
6545 inst
.reloc
.pc_rel
= 1;
6546 inst
.instruction
|= (REG_PC
<< 16);
6550 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
6555 do_ldstt (char * str
)
6559 skip_whitespace (str
);
6561 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
6564 inst
.error
= BAD_ARGS
;
6568 if (skip_past_comma (& str
) == FAIL
)
6570 inst
.error
= _("address expected");
6580 skip_whitespace (str
);
6582 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6585 /* ldrt/strt always use post-indexed addressing, so if the base is
6586 the same as Rd, we warn. */
6587 if (conflict_reg
== reg
)
6588 as_warn (_("%s register same as write-back base"),
6589 ((inst
.instruction
& LOAD_BIT
)
6590 ? _("destination") : _("source")));
6592 skip_whitespace (str
);
6598 if (skip_past_comma (&str
) == SUCCESS
)
6600 /* [Rn],... (post inc) */
6601 if (ldst_extend (&str
) == FAIL
)
6607 skip_whitespace (str
);
6609 /* Skip a write-back '!'. */
6613 inst
.instruction
|= INDEX_UP
;
6618 inst
.error
= _("post-indexed expression expected");
6624 inst
.error
= _("post-indexed expression expected");
6631 /* Halfword and signed-byte load/store operations. */
6634 do_ldstv4 (char * str
)
6640 skip_whitespace (str
);
6642 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
6645 inst
.error
= BAD_ARGS
;
6649 if (skip_past_comma (& str
) == FAIL
)
6651 inst
.error
= _("address expected");
6661 skip_whitespace (str
);
6663 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6666 /* Conflicts can occur on stores as well as loads. */
6667 conflict_reg
= (conflict_reg
== reg
);
6669 skip_whitespace (str
);
6675 if (skip_past_comma (&str
) == SUCCESS
)
6677 /* [Rn],... (post inc) */
6678 if (ldst_extend_v4 (&str
) == FAIL
)
6681 as_warn (_("%s register same as write-back base"),
6682 ((inst
.instruction
& LOAD_BIT
)
6683 ? _("destination") : _("source")));
6688 inst
.instruction
|= HWOFFSET_IMM
;
6690 skip_whitespace (str
);
6695 as_warn (_("%s register same as write-back base"),
6696 ((inst
.instruction
& LOAD_BIT
)
6697 ? _("destination") : _("source")));
6699 inst
.instruction
|= WRITE_BACK
;
6702 inst
.instruction
|= INDEX_UP
;
6709 if (skip_past_comma (&str
) == FAIL
)
6711 inst
.error
= _("pre-indexed expression expected");
6716 if (ldst_extend_v4 (&str
) == FAIL
)
6719 skip_whitespace (str
);
6723 inst
.error
= _("missing ]");
6727 skip_whitespace (str
);
6732 as_warn (_("%s register same as write-back base"),
6733 ((inst
.instruction
& LOAD_BIT
)
6734 ? _("destination") : _("source")));
6736 inst
.instruction
|= WRITE_BACK
;
6740 else if (*str
== '=')
6742 if ((inst
.instruction
& LOAD_BIT
) == 0)
6744 inst
.error
= _("invalid pseudo operation");
6748 /* XXX Does this work correctly for half-word/byte ops? */
6749 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6752 skip_whitespace (str
);
6754 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6757 if (inst
.reloc
.exp
.X_op
!= O_constant
6758 && inst
.reloc
.exp
.X_op
!= O_symbol
)
6760 inst
.error
= _("constant expression expected");
6764 if (inst
.reloc
.exp
.X_op
== O_constant
)
6766 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
6770 /* This can be done with a mov instruction. */
6771 inst
.instruction
&= LITERAL_MASK
;
6772 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MOV
<< DATA_OP_SHIFT
);
6773 inst
.instruction
|= value
& 0xfff;
6778 value
= validate_immediate (~ inst
.reloc
.exp
.X_add_number
);
6782 /* This can be done with a mvn instruction. */
6783 inst
.instruction
&= LITERAL_MASK
;
6784 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MVN
<< DATA_OP_SHIFT
);
6785 inst
.instruction
|= value
& 0xfff;
6791 /* Insert into literal pool. */
6792 if (add_to_lit_pool () == FAIL
)
6795 inst
.error
= _("literal pool insertion failed");
6799 /* Change the instruction exp to point to the pool. */
6800 inst
.instruction
|= HWOFFSET_IMM
;
6801 inst
.reloc
.type
= BFD_RELOC_ARM_HWLITERAL
;
6802 inst
.reloc
.pc_rel
= 1;
6803 inst
.instruction
|= (REG_PC
<< 16);
6808 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6811 inst
.instruction
|= HWOFFSET_IMM
;
6812 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
6814 /* PC rel adjust. */
6815 inst
.reloc
.exp
.X_add_number
-= 8;
6817 inst
.reloc
.pc_rel
= 1;
6818 inst
.instruction
|= (REG_PC
<< 16);
6822 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
6827 do_ldsttv4 (char * str
)
6831 skip_whitespace (str
);
6833 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
6836 inst
.error
= BAD_ARGS
;
6840 if (skip_past_comma (& str
) == FAIL
)
6842 inst
.error
= _("address expected");
6852 skip_whitespace (str
);
6854 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6857 /* ldrt/strt always use post-indexed addressing, so if the base is
6858 the same as Rd, we warn. */
6859 if (conflict_reg
== reg
)
6860 as_warn (_("%s register same as write-back base"),
6861 ((inst
.instruction
& LOAD_BIT
)
6862 ? _("destination") : _("source")));
6864 skip_whitespace (str
);
6870 if (skip_past_comma (&str
) == SUCCESS
)
6872 /* [Rn],... (post inc) */
6873 if (ldst_extend_v4 (&str
) == FAIL
)
6879 skip_whitespace (str
);
6881 /* Skip a write-back '!'. */
6885 inst
.instruction
|= (INDEX_UP
|HWOFFSET_IMM
);
6890 inst
.error
= _("post-indexed expression expected");
6896 inst
.error
= _("post-indexed expression expected");
6905 reg_list (char ** strp
)
6907 char * str
= * strp
;
6911 /* We come back here if we get ranges concatenated by '+' or '|'. */
6926 skip_whitespace (str
);
6928 if ((reg
= reg_required_here (& str
, -1)) == FAIL
)
6937 inst
.error
= _("bad range in register list");
6941 for (i
= cur_reg
+ 1; i
< reg
; i
++)
6943 if (range
& (1 << i
))
6945 (_("Warning: duplicated register (r%d) in register list"),
6953 if (range
& (1 << reg
))
6954 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
6956 else if (reg
<= cur_reg
)
6957 as_tsktsk (_("Warning: register range not in ascending order"));
6962 while (skip_past_comma (&str
) != FAIL
6963 || (in_range
= 1, *str
++ == '-'));
6965 skip_whitespace (str
);
6969 inst
.error
= _("missing `}'");
6977 if (my_get_expression (&expr
, &str
))
6980 if (expr
.X_op
== O_constant
)
6982 if (expr
.X_add_number
6983 != (expr
.X_add_number
& 0x0000ffff))
6985 inst
.error
= _("invalid register mask");
6989 if ((range
& expr
.X_add_number
) != 0)
6991 int regno
= range
& expr
.X_add_number
;
6994 regno
= (1 << regno
) - 1;
6996 (_("Warning: duplicated register (r%d) in register list"),
7000 range
|= expr
.X_add_number
;
7004 if (inst
.reloc
.type
!= 0)
7006 inst
.error
= _("expression too complex");
7010 memcpy (&inst
.reloc
.exp
, &expr
, sizeof (expressionS
));
7011 inst
.reloc
.type
= BFD_RELOC_ARM_MULTI
;
7012 inst
.reloc
.pc_rel
= 0;
7016 skip_whitespace (str
);
7018 if (*str
== '|' || *str
== '+')
7024 while (another_range
);
7031 do_ldmstm (char * str
)
7036 skip_whitespace (str
);
7038 if ((base_reg
= reg_required_here (&str
, 16)) == FAIL
)
7041 if (base_reg
== REG_PC
)
7043 inst
.error
= _("r15 not allowed as base register");
7047 skip_whitespace (str
);
7051 inst
.instruction
|= WRITE_BACK
;
7055 if (skip_past_comma (&str
) == FAIL
7056 || (range
= reg_list (&str
)) == FAIL
)
7059 inst
.error
= BAD_ARGS
;
7066 inst
.instruction
|= LDM_TYPE_2_OR_3
;
7069 if (inst
.instruction
& WRITE_BACK
)
7071 /* Check for unpredictable uses of writeback. */
7072 if (inst
.instruction
& LOAD_BIT
)
7074 /* Not allowed in LDM type 2. */
7075 if ((inst
.instruction
& LDM_TYPE_2_OR_3
)
7076 && ((range
& (1 << REG_PC
)) == 0))
7077 as_warn (_("writeback of base register is UNPREDICTABLE"));
7078 /* Only allowed if base reg not in list for other types. */
7079 else if (range
& (1 << base_reg
))
7080 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
7084 /* Not allowed for type 2. */
7085 if (inst
.instruction
& LDM_TYPE_2_OR_3
)
7086 as_warn (_("writeback of base register is UNPREDICTABLE"));
7087 /* Only allowed if base reg not in list, or first in list. */
7088 else if ((range
& (1 << base_reg
))
7089 && (range
& ((1 << base_reg
) - 1)))
7090 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
7094 inst
.instruction
|= range
;
7101 skip_whitespace (str
);
7103 /* Allow optional leading '#'. */
7104 if (is_immediate_prefix (*str
))
7107 if (my_get_expression (& inst
.reloc
.exp
, & str
))
7110 inst
.reloc
.type
= BFD_RELOC_ARM_SMI
;
7111 inst
.reloc
.pc_rel
= 0;
7118 skip_whitespace (str
);
7120 /* Allow optional leading '#'. */
7121 if (is_immediate_prefix (*str
))
7124 if (my_get_expression (& inst
.reloc
.exp
, & str
))
7127 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
7128 inst
.reloc
.pc_rel
= 0;
7133 do_swap (char * str
)
7137 skip_whitespace (str
);
7139 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
7144 inst
.error
= _("r15 not allowed in swap");
7148 if (skip_past_comma (&str
) == FAIL
7149 || (reg
= reg_required_here (&str
, 0)) == FAIL
)
7152 inst
.error
= BAD_ARGS
;
7158 inst
.error
= _("r15 not allowed in swap");
7162 if (skip_past_comma (&str
) == FAIL
7165 inst
.error
= BAD_ARGS
;
7169 skip_whitespace (str
);
7171 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
7176 inst
.error
= BAD_PC
;
7180 skip_whitespace (str
);
7184 inst
.error
= _("missing ]");
7192 do_branch (char * str
)
7194 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7201 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
7202 required for the instruction. */
7204 /* arm_parse_reloc () works on input_line_pointer.
7205 We actually want to parse the operands to the branch instruction
7206 passed in 'str'. Save the input pointer and restore it later. */
7207 save_in
= input_line_pointer
;
7208 input_line_pointer
= str
;
7209 if (inst
.reloc
.exp
.X_op
== O_symbol
7211 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
7213 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
7214 inst
.reloc
.pc_rel
= 0;
7215 /* Modify str to point to after parsed operands, otherwise
7216 end_of_line() will complain about the (PLT) left in str. */
7217 str
= input_line_pointer
;
7221 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
7222 inst
.reloc
.pc_rel
= 1;
7224 input_line_pointer
= save_in
;
7227 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
7228 inst
.reloc
.pc_rel
= 1;
7229 #endif /* OBJ_ELF */
7237 /* Co-processor data operation.
7238 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
7239 skip_whitespace (str
);
7241 if (co_proc_number (&str
) == FAIL
)
7244 inst
.error
= BAD_ARGS
;
7248 if (skip_past_comma (&str
) == FAIL
7249 || cp_opc_expr (&str
, 20,4) == FAIL
)
7252 inst
.error
= BAD_ARGS
;
7256 if (skip_past_comma (&str
) == FAIL
7257 || cp_reg_required_here (&str
, 12) == FAIL
)
7260 inst
.error
= BAD_ARGS
;
7264 if (skip_past_comma (&str
) == FAIL
7265 || cp_reg_required_here (&str
, 16) == FAIL
)
7268 inst
.error
= BAD_ARGS
;
7272 if (skip_past_comma (&str
) == FAIL
7273 || cp_reg_required_here (&str
, 0) == FAIL
)
7276 inst
.error
= BAD_ARGS
;
7280 if (skip_past_comma (&str
) == SUCCESS
)
7282 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
7285 inst
.error
= BAD_ARGS
;
7294 do_lstc (char * str
)
7296 /* Co-processor register load/store.
7297 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
7299 skip_whitespace (str
);
7301 if (co_proc_number (&str
) == FAIL
)
7304 inst
.error
= BAD_ARGS
;
7308 if (skip_past_comma (&str
) == FAIL
7309 || cp_reg_required_here (&str
, 12) == FAIL
)
7312 inst
.error
= BAD_ARGS
;
7316 if (skip_past_comma (&str
) == FAIL
7317 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
7320 inst
.error
= BAD_ARGS
;
7328 do_co_reg (char * str
)
7330 /* Co-processor register transfer.
7331 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
7333 skip_whitespace (str
);
7335 if (co_proc_number (&str
) == FAIL
)
7338 inst
.error
= BAD_ARGS
;
7342 if (skip_past_comma (&str
) == FAIL
7343 || cp_opc_expr (&str
, 21, 3) == FAIL
)
7346 inst
.error
= BAD_ARGS
;
7350 if (skip_past_comma (&str
) == FAIL
7351 || reg_required_here (&str
, 12) == FAIL
)
7354 inst
.error
= BAD_ARGS
;
7358 if (skip_past_comma (&str
) == FAIL
7359 || cp_reg_required_here (&str
, 16) == FAIL
)
7362 inst
.error
= BAD_ARGS
;
7366 if (skip_past_comma (&str
) == FAIL
7367 || cp_reg_required_here (&str
, 0) == FAIL
)
7370 inst
.error
= BAD_ARGS
;
7374 if (skip_past_comma (&str
) == SUCCESS
)
7376 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
7379 inst
.error
= BAD_ARGS
;
7388 do_fpa_ctrl (char * str
)
7390 /* FP control registers.
7391 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
7393 skip_whitespace (str
);
7395 if (reg_required_here (&str
, 12) == FAIL
)
7398 inst
.error
= BAD_ARGS
;
7406 do_fpa_ldst (char * str
)
7408 skip_whitespace (str
);
7410 if (fp_reg_required_here (&str
, 12) == FAIL
)
7413 inst
.error
= BAD_ARGS
;
7417 if (skip_past_comma (&str
) == FAIL
7418 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
7421 inst
.error
= BAD_ARGS
;
7429 do_fpa_ldmstm (char * str
)
7433 skip_whitespace (str
);
7435 if (fp_reg_required_here (&str
, 12) == FAIL
)
7438 inst
.error
= BAD_ARGS
;
7442 /* Get Number of registers to transfer. */
7443 if (skip_past_comma (&str
) == FAIL
7444 || my_get_expression (&inst
.reloc
.exp
, &str
))
7447 inst
.error
= _("constant expression expected");
7451 if (inst
.reloc
.exp
.X_op
!= O_constant
)
7453 inst
.error
= _("constant value required for number of registers");
7457 num_regs
= inst
.reloc
.exp
.X_add_number
;
7459 if (num_regs
< 1 || num_regs
> 4)
7461 inst
.error
= _("number of registers must be in the range [1:4]");
7468 inst
.instruction
|= CP_T_X
;
7471 inst
.instruction
|= CP_T_Y
;
7474 inst
.instruction
|= CP_T_Y
| CP_T_X
;
7482 if (inst
.instruction
& (CP_T_Pre
| CP_T_UD
)) /* ea/fd format. */
7488 /* The instruction specified "ea" or "fd", so we can only accept
7489 [Rn]{!}. The instruction does not really support stacking or
7490 unstacking, so we have to emulate these by setting appropriate
7491 bits and offsets. */
7492 if (skip_past_comma (&str
) == FAIL
7496 inst
.error
= BAD_ARGS
;
7501 skip_whitespace (str
);
7503 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
7506 skip_whitespace (str
);
7510 inst
.error
= BAD_ARGS
;
7522 _("r15 not allowed as base register with write-back");
7529 if (inst
.instruction
& CP_T_Pre
)
7531 /* Pre-decrement. */
7532 offset
= 3 * num_regs
;
7534 inst
.instruction
|= CP_T_WB
;
7538 /* Post-increment. */
7541 inst
.instruction
|= CP_T_WB
;
7542 offset
= 3 * num_regs
;
7546 /* No write-back, so convert this into a standard pre-increment
7547 instruction -- aesthetically more pleasing. */
7548 inst
.instruction
|= CP_T_Pre
| CP_T_UD
;
7553 inst
.instruction
|= offset
;
7555 else if (skip_past_comma (&str
) == FAIL
7556 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
7559 inst
.error
= BAD_ARGS
;
7567 do_fpa_dyadic (char * str
)
7569 skip_whitespace (str
);
7571 if (fp_reg_required_here (&str
, 12) == FAIL
)
7574 inst
.error
= BAD_ARGS
;
7578 if (skip_past_comma (&str
) == FAIL
7579 || fp_reg_required_here (&str
, 16) == FAIL
)
7582 inst
.error
= BAD_ARGS
;
7586 if (skip_past_comma (&str
) == FAIL
7587 || fp_op2 (&str
) == FAIL
)
7590 inst
.error
= BAD_ARGS
;
7598 do_fpa_monadic (char * str
)
7600 skip_whitespace (str
);
7602 if (fp_reg_required_here (&str
, 12) == FAIL
)
7605 inst
.error
= BAD_ARGS
;
7609 if (skip_past_comma (&str
) == FAIL
7610 || fp_op2 (&str
) == FAIL
)
7613 inst
.error
= BAD_ARGS
;
7621 do_fpa_cmp (char * str
)
7623 skip_whitespace (str
);
7625 if (fp_reg_required_here (&str
, 16) == FAIL
)
7628 inst
.error
= BAD_ARGS
;
7632 if (skip_past_comma (&str
) == FAIL
7633 || fp_op2 (&str
) == FAIL
)
7636 inst
.error
= BAD_ARGS
;
7644 do_fpa_from_reg (char * str
)
7646 skip_whitespace (str
);
7648 if (fp_reg_required_here (&str
, 16) == FAIL
)
7651 inst
.error
= BAD_ARGS
;
7655 if (skip_past_comma (&str
) == FAIL
7656 || reg_required_here (&str
, 12) == FAIL
)
7659 inst
.error
= BAD_ARGS
;
7667 do_fpa_to_reg (char * str
)
7669 skip_whitespace (str
);
7671 if (reg_required_here (&str
, 12) == FAIL
)
7674 if (skip_past_comma (&str
) == FAIL
7675 || fp_reg_required_here (&str
, 0) == FAIL
)
7678 inst
.error
= BAD_ARGS
;
7685 /* Encode a VFP SP register number. */
7688 vfp_sp_encode_reg (int reg
, enum vfp_sp_reg_pos pos
)
7693 inst
.instruction
|= ((reg
>> 1) << 12) | ((reg
& 1) << 22);
7697 inst
.instruction
|= ((reg
>> 1) << 16) | ((reg
& 1) << 7);
7701 inst
.instruction
|= ((reg
>> 1) << 0) | ((reg
& 1) << 5);
7710 vfp_sp_reg_required_here (char ** str
,
7711 enum vfp_sp_reg_pos pos
)
7714 char * start
= *str
;
7716 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_SN
].htab
)) != FAIL
)
7718 vfp_sp_encode_reg (reg
, pos
);
7722 /* In the few cases where we might be able to accept something else
7723 this error can be overridden. */
7724 inst
.error
= _(all_reg_maps
[REG_TYPE_SN
].expected
);
7726 /* Restore the start point. */
7732 vfp_dp_reg_required_here (char ** str
,
7733 enum vfp_dp_reg_pos pos
)
7736 char * start
= *str
;
7738 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_DN
].htab
)) != FAIL
)
7743 inst
.instruction
|= reg
<< 12;
7747 inst
.instruction
|= reg
<< 16;
7751 inst
.instruction
|= reg
<< 0;
7760 /* In the few cases where we might be able to accept something else
7761 this error can be overridden. */
7762 inst
.error
= _(all_reg_maps
[REG_TYPE_DN
].expected
);
7764 /* Restore the start point. */
7770 do_vfp_sp_monadic (char * str
)
7772 skip_whitespace (str
);
7774 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7777 if (skip_past_comma (&str
) == FAIL
7778 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
7781 inst
.error
= BAD_ARGS
;
7789 do_vfp_dp_monadic (char * str
)
7791 skip_whitespace (str
);
7793 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7796 if (skip_past_comma (&str
) == FAIL
7797 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7800 inst
.error
= BAD_ARGS
;
7808 do_vfp_sp_dyadic (char * str
)
7810 skip_whitespace (str
);
7812 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7815 if (skip_past_comma (&str
) == FAIL
7816 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
7817 || skip_past_comma (&str
) == FAIL
7818 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
7821 inst
.error
= BAD_ARGS
;
7829 do_vfp_dp_dyadic (char * str
)
7831 skip_whitespace (str
);
7833 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7836 if (skip_past_comma (&str
) == FAIL
7837 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
7838 || skip_past_comma (&str
) == FAIL
7839 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7842 inst
.error
= BAD_ARGS
;
7850 do_vfp_reg_from_sp (char * str
)
7852 skip_whitespace (str
);
7854 if (reg_required_here (&str
, 12) == FAIL
)
7857 if (skip_past_comma (&str
) == FAIL
7858 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
7861 inst
.error
= BAD_ARGS
;
7868 /* Parse a VFP register list. If the string is invalid return FAIL.
7869 Otherwise return the number of registers, and set PBASE to the first
7870 register. Double precision registers are matched if DP is nonzero. */
7873 vfp_parse_reg_list (char **str
, int *pbase
, int dp
)
7881 unsigned long mask
= 0;
7888 skip_whitespace (*str
);
7892 regtype
= REG_TYPE_DN
;
7897 regtype
= REG_TYPE_SN
;
7901 base_reg
= max_regs
;
7905 new_base
= arm_reg_parse (str
, all_reg_maps
[regtype
].htab
);
7906 if (new_base
== FAIL
)
7908 inst
.error
= _(all_reg_maps
[regtype
].expected
);
7912 if (new_base
< base_reg
)
7913 base_reg
= new_base
;
7915 if (mask
& (1 << new_base
))
7917 inst
.error
= _("invalid register list");
7921 if ((mask
>> new_base
) != 0 && ! warned
)
7923 as_tsktsk (_("register list not in ascending order"));
7927 mask
|= 1 << new_base
;
7930 skip_whitespace (*str
);
7932 if (**str
== '-') /* We have the start of a range expression */
7939 = arm_reg_parse (str
, all_reg_maps
[regtype
].htab
))
7942 inst
.error
= _(all_reg_maps
[regtype
].expected
);
7946 if (high_range
<= new_base
)
7948 inst
.error
= _("register range not in ascending order");
7952 for (new_base
++; new_base
<= high_range
; new_base
++)
7954 if (mask
& (1 << new_base
))
7956 inst
.error
= _("invalid register list");
7960 mask
|= 1 << new_base
;
7965 while (skip_past_comma (str
) != FAIL
);
7969 /* Sanity check -- should have raised a parse error above. */
7970 if (count
== 0 || count
> max_regs
)
7975 /* Final test -- the registers must be consecutive. */
7977 for (i
= 0; i
< count
; i
++)
7979 if ((mask
& (1u << i
)) == 0)
7981 inst
.error
= _("non-contiguous register range");
7990 do_vfp_reg2_from_sp2 (char * str
)
7994 skip_whitespace (str
);
7996 if (reg_required_here (&str
, 12) == FAIL
7997 || skip_past_comma (&str
) == FAIL
7998 || reg_required_here (&str
, 16) == FAIL
7999 || skip_past_comma (&str
) == FAIL
)
8002 inst
.error
= BAD_ARGS
;
8006 /* We require exactly two consecutive SP registers. */
8007 if (vfp_parse_reg_list (&str
, ®
, 0) != 2)
8010 inst
.error
= _("only two consecutive VFP SP registers allowed here");
8012 vfp_sp_encode_reg (reg
, VFP_REG_Sm
);
8018 do_vfp_sp_from_reg (char * str
)
8020 skip_whitespace (str
);
8022 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
8025 if (skip_past_comma (&str
) == FAIL
8026 || reg_required_here (&str
, 12) == FAIL
)
8029 inst
.error
= BAD_ARGS
;
8037 do_vfp_sp2_from_reg2 (char * str
)
8041 skip_whitespace (str
);
8043 /* We require exactly two consecutive SP registers. */
8044 if (vfp_parse_reg_list (&str
, ®
, 0) != 2)
8047 inst
.error
= _("only two consecutive VFP SP registers allowed here");
8049 vfp_sp_encode_reg (reg
, VFP_REG_Sm
);
8051 if (skip_past_comma (&str
) == FAIL
8052 || reg_required_here (&str
, 12) == FAIL
8053 || skip_past_comma (&str
) == FAIL
8054 || reg_required_here (&str
, 16) == FAIL
)
8057 inst
.error
= BAD_ARGS
;
8065 do_vfp_reg_from_dp (char * str
)
8067 skip_whitespace (str
);
8069 if (reg_required_here (&str
, 12) == FAIL
)
8072 if (skip_past_comma (&str
) == FAIL
8073 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
8076 inst
.error
= BAD_ARGS
;
8084 do_vfp_reg2_from_dp (char * str
)
8086 skip_whitespace (str
);
8088 if (reg_required_here (&str
, 12) == FAIL
)
8091 if (skip_past_comma (&str
) == FAIL
8092 || reg_required_here (&str
, 16) == FAIL
8093 || skip_past_comma (&str
) == FAIL
8094 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
8097 inst
.error
= BAD_ARGS
;
8105 do_vfp_dp_from_reg (char * str
)
8107 skip_whitespace (str
);
8109 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
8112 if (skip_past_comma (&str
) == FAIL
8113 || reg_required_here (&str
, 12) == FAIL
)
8116 inst
.error
= BAD_ARGS
;
8124 do_vfp_dp_from_reg2 (char * str
)
8126 skip_whitespace (str
);
8128 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
8131 if (skip_past_comma (&str
) == FAIL
8132 || reg_required_here (&str
, 12) == FAIL
8133 || skip_past_comma (&str
) == FAIL
8134 || reg_required_here (&str
, 16) == FAIL
)
8137 inst
.error
= BAD_ARGS
;
8144 static const struct vfp_reg
*
8145 vfp_psr_parse (char ** str
)
8150 const struct vfp_reg
*vreg
;
8154 /* Find the end of the current token. */
8159 while (ISALPHA (c
));
8164 for (vreg
= vfp_regs
+ 0;
8165 vreg
< vfp_regs
+ sizeof (vfp_regs
) / sizeof (struct vfp_reg
);
8168 if (streq (start
, vreg
->name
))
8181 vfp_psr_required_here (char ** str
)
8184 const struct vfp_reg
*vreg
;
8186 vreg
= vfp_psr_parse (str
);
8190 inst
.instruction
|= vreg
->regno
;
8194 inst
.error
= _("VFP system register expected");
8201 do_vfp_reg_from_ctrl (char * str
)
8203 skip_whitespace (str
);
8205 if (reg_required_here (&str
, 12) == FAIL
)
8208 if (skip_past_comma (&str
) == FAIL
8209 || vfp_psr_required_here (&str
) == FAIL
)
8212 inst
.error
= BAD_ARGS
;
8220 do_vfp_ctrl_from_reg (char * str
)
8222 skip_whitespace (str
);
8224 if (vfp_psr_required_here (&str
) == FAIL
)
8227 if (skip_past_comma (&str
) == FAIL
8228 || reg_required_here (&str
, 12) == FAIL
)
8231 inst
.error
= BAD_ARGS
;
8239 do_vfp_sp_ldst (char * str
)
8241 skip_whitespace (str
);
8243 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8246 inst
.error
= BAD_ARGS
;
8250 if (skip_past_comma (&str
) == FAIL
8251 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
8254 inst
.error
= BAD_ARGS
;
8262 do_vfp_dp_ldst (char * str
)
8264 skip_whitespace (str
);
8266 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8269 inst
.error
= BAD_ARGS
;
8273 if (skip_past_comma (&str
) == FAIL
8274 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
8277 inst
.error
= BAD_ARGS
;
8286 vfp_sp_ldstm (char * str
, enum vfp_ldstm_type ldstm_type
)
8291 skip_whitespace (str
);
8293 if (reg_required_here (&str
, 16) == FAIL
)
8296 skip_whitespace (str
);
8300 inst
.instruction
|= WRITE_BACK
;
8303 else if (ldstm_type
!= VFP_LDSTMIA
)
8305 inst
.error
= _("this addressing mode requires base-register writeback");
8309 if (skip_past_comma (&str
) == FAIL
8310 || (count
= vfp_parse_reg_list (&str
, ®
, 0)) == FAIL
)
8313 inst
.error
= BAD_ARGS
;
8316 vfp_sp_encode_reg (reg
, VFP_REG_Sd
);
8318 inst
.instruction
|= count
;
8323 vfp_dp_ldstm (char * str
, enum vfp_ldstm_type ldstm_type
)
8328 skip_whitespace (str
);
8330 if (reg_required_here (&str
, 16) == FAIL
)
8333 skip_whitespace (str
);
8337 inst
.instruction
|= WRITE_BACK
;
8340 else if (ldstm_type
!= VFP_LDSTMIA
&& ldstm_type
!= VFP_LDSTMIAX
)
8342 inst
.error
= _("this addressing mode requires base-register writeback");
8346 if (skip_past_comma (&str
) == FAIL
8347 || (count
= vfp_parse_reg_list (&str
, ®
, 1)) == FAIL
)
8350 inst
.error
= BAD_ARGS
;
8355 if (ldstm_type
== VFP_LDSTMIAX
|| ldstm_type
== VFP_LDSTMDBX
)
8358 inst
.instruction
|= (reg
<< 12) | count
;
8363 do_vfp_sp_ldstmia (char * str
)
8365 vfp_sp_ldstm (str
, VFP_LDSTMIA
);
8369 do_vfp_sp_ldstmdb (char * str
)
8371 vfp_sp_ldstm (str
, VFP_LDSTMDB
);
8375 do_vfp_dp_ldstmia (char * str
)
8377 vfp_dp_ldstm (str
, VFP_LDSTMIA
);
8381 do_vfp_dp_ldstmdb (char * str
)
8383 vfp_dp_ldstm (str
, VFP_LDSTMDB
);
8387 do_vfp_xp_ldstmia (char *str
)
8389 vfp_dp_ldstm (str
, VFP_LDSTMIAX
);
8393 do_vfp_xp_ldstmdb (char * str
)
8395 vfp_dp_ldstm (str
, VFP_LDSTMDBX
);
8399 do_vfp_sp_compare_z (char * str
)
8401 skip_whitespace (str
);
8403 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8406 inst
.error
= BAD_ARGS
;
8414 do_vfp_dp_compare_z (char * str
)
8416 skip_whitespace (str
);
8418 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8421 inst
.error
= BAD_ARGS
;
8429 do_vfp_dp_sp_cvt (char * str
)
8431 skip_whitespace (str
);
8433 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8436 if (skip_past_comma (&str
) == FAIL
8437 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
8440 inst
.error
= BAD_ARGS
;
8448 do_vfp_sp_dp_cvt (char * str
)
8450 skip_whitespace (str
);
8452 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8455 if (skip_past_comma (&str
) == FAIL
8456 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
8459 inst
.error
= BAD_ARGS
;
8466 /* Thumb specific routines. */
8468 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
8472 thumb_add_sub (char * str
, int subtract
)
8474 int Rd
, Rs
, Rn
= FAIL
;
8476 skip_whitespace (str
);
8478 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
8479 || skip_past_comma (&str
) == FAIL
)
8482 inst
.error
= BAD_ARGS
;
8486 if (is_immediate_prefix (*str
))
8490 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8495 if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8498 if (skip_past_comma (&str
) == FAIL
)
8500 /* Two operand format, shuffle the registers
8501 and pretend there are 3. */
8505 else if (is_immediate_prefix (*str
))
8508 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8511 else if ((Rn
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8515 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8516 for the latter case, EXPR contains the immediate that was found. */
8519 /* All register format. */
8520 if (Rd
> 7 || Rs
> 7 || Rn
> 7)
8524 inst
.error
= _("dest and source1 must be the same register");
8528 /* Can't do this for SUB. */
8531 inst
.error
= _("subtract valid only on lo regs");
8535 inst
.instruction
= (T_OPCODE_ADD_HI
8536 | (Rd
> 7 ? THUMB_H1
: 0)
8537 | (Rn
> 7 ? THUMB_H2
: 0));
8538 inst
.instruction
|= (Rd
& 7) | ((Rn
& 7) << 3);
8542 inst
.instruction
= subtract
? T_OPCODE_SUB_R3
: T_OPCODE_ADD_R3
;
8543 inst
.instruction
|= Rd
| (Rs
<< 3) | (Rn
<< 6);
8548 /* Immediate expression, now things start to get nasty. */
8550 /* First deal with HI regs, only very restricted cases allowed:
8551 Adjusting SP, and using PC or SP to get an address. */
8552 if ((Rd
> 7 && (Rd
!= REG_SP
|| Rs
!= REG_SP
))
8553 || (Rs
> 7 && Rs
!= REG_SP
&& Rs
!= REG_PC
))
8555 inst
.error
= _("invalid Hi register with immediate");
8559 if (inst
.reloc
.exp
.X_op
!= O_constant
)
8561 /* Value isn't known yet, all we can do is store all the fragments
8562 we know about in the instruction and let the reloc hacking
8564 inst
.instruction
= (subtract
? 0x8000 : 0) | (Rd
<< 4) | Rs
;
8565 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
8569 int offset
= inst
.reloc
.exp
.X_add_number
;
8579 /* Quick check, in case offset is MIN_INT. */
8582 inst
.error
= _("immediate value out of range");
8586 /* Note - you cannot convert a subtract of 0 into an
8587 add of 0 because the carry flag is set differently. */
8588 else if (offset
> 0)
8593 if (offset
& ~0x1fc)
8595 inst
.error
= _("invalid immediate value for stack adjust");
8598 inst
.instruction
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
8599 inst
.instruction
|= offset
>> 2;
8601 else if (Rs
== REG_PC
|| Rs
== REG_SP
)
8604 || (offset
& ~0x3fc))
8606 inst
.error
= _("invalid immediate for address calculation");
8609 inst
.instruction
= (Rs
== REG_PC
? T_OPCODE_ADD_PC
8611 inst
.instruction
|= (Rd
<< 8) | (offset
>> 2);
8617 inst
.error
= _("immediate value out of range");
8620 inst
.instruction
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
8621 inst
.instruction
|= (Rd
<< 8) | offset
;
8627 inst
.error
= _("immediate value out of range");
8630 inst
.instruction
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
8631 inst
.instruction
|= Rd
| (Rs
<< 3) | (offset
<< 6);
8640 thumb_shift (char * str
, int shift
)
8642 int Rd
, Rs
, Rn
= FAIL
;
8644 skip_whitespace (str
);
8646 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
8647 || skip_past_comma (&str
) == FAIL
)
8650 inst
.error
= BAD_ARGS
;
8654 if (is_immediate_prefix (*str
))
8656 /* Two operand immediate format, set Rs to Rd. */
8659 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8664 if ((Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8667 if (skip_past_comma (&str
) == FAIL
)
8669 /* Two operand format, shuffle the registers
8670 and pretend there are 3. */
8674 else if (is_immediate_prefix (*str
))
8677 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8680 else if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8684 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8685 for the latter case, EXPR contains the immediate that was found. */
8691 inst
.error
= _("source1 and dest must be same register");
8697 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_R
; break;
8698 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_R
; break;
8699 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_R
; break;
8702 inst
.instruction
|= Rd
| (Rn
<< 3);
8708 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_I
; break;
8709 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_I
; break;
8710 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_I
; break;
8713 if (inst
.reloc
.exp
.X_op
!= O_constant
)
8715 /* Value isn't known yet, create a dummy reloc and let reloc
8716 hacking fix it up. */
8717 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_SHIFT
;
8721 unsigned shift_value
= inst
.reloc
.exp
.X_add_number
;
8723 if (shift_value
> 32 || (shift_value
== 32 && shift
== THUMB_LSL
))
8725 inst
.error
= _("invalid immediate for shift");
8729 /* Shifts of zero are handled by converting to LSL. */
8730 if (shift_value
== 0)
8731 inst
.instruction
= T_OPCODE_LSL_I
;
8733 /* Shifts of 32 are encoded as a shift of zero. */
8734 if (shift_value
== 32)
8737 inst
.instruction
|= shift_value
<< 6;
8740 inst
.instruction
|= Rd
| (Rs
<< 3);
8747 thumb_load_store (char * str
, int load_store
, int size
)
8749 int Rd
, Rb
, Ro
= FAIL
;
8751 skip_whitespace (str
);
8753 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
8754 || skip_past_comma (&str
) == FAIL
)
8757 inst
.error
= BAD_ARGS
;
8764 if ((Rb
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8767 if (skip_past_comma (&str
) != FAIL
)
8769 if (is_immediate_prefix (*str
))
8772 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8775 else if ((Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8780 inst
.reloc
.exp
.X_op
= O_constant
;
8781 inst
.reloc
.exp
.X_add_number
= 0;
8786 inst
.error
= _("expected ']'");
8791 else if (*str
== '=')
8793 if (load_store
!= THUMB_LOAD
)
8795 inst
.error
= _("invalid pseudo operation");
8799 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
8802 skip_whitespace (str
);
8804 if (my_get_expression (& inst
.reloc
.exp
, & str
))
8809 if ( inst
.reloc
.exp
.X_op
!= O_constant
8810 && inst
.reloc
.exp
.X_op
!= O_symbol
)
8812 inst
.error
= "Constant expression expected";
8816 if (inst
.reloc
.exp
.X_op
== O_constant
8817 && ((inst
.reloc
.exp
.X_add_number
& ~0xFF) == 0))
8819 /* This can be done with a mov instruction. */
8821 inst
.instruction
= T_OPCODE_MOV_I8
| (Rd
<< 8);
8822 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
8826 /* Insert into literal pool. */
8827 if (add_to_lit_pool () == FAIL
)
8830 inst
.error
= "literal pool insertion failed";
8834 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8835 inst
.reloc
.pc_rel
= 1;
8836 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
8837 /* Adjust ARM pipeline offset to Thumb. */
8838 inst
.reloc
.exp
.X_add_number
+= 4;
8844 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8847 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
8848 inst
.reloc
.pc_rel
= 1;
8849 inst
.reloc
.exp
.X_add_number
-= 4; /* Pipeline offset. */
8850 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8855 if (Rb
== REG_PC
|| Rb
== REG_SP
)
8857 if (size
!= THUMB_WORD
)
8859 inst
.error
= _("byte or halfword not valid for base register");
8862 else if (Rb
== REG_PC
&& load_store
!= THUMB_LOAD
)
8864 inst
.error
= _("r15 based store not allowed");
8867 else if (Ro
!= FAIL
)
8869 inst
.error
= _("invalid base register for register offset");
8874 inst
.instruction
= T_OPCODE_LDR_PC
;
8875 else if (load_store
== THUMB_LOAD
)
8876 inst
.instruction
= T_OPCODE_LDR_SP
;
8878 inst
.instruction
= T_OPCODE_STR_SP
;
8880 inst
.instruction
|= Rd
<< 8;
8881 if (inst
.reloc
.exp
.X_op
== O_constant
)
8883 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
8885 if (offset
& ~0x3fc)
8887 inst
.error
= _("invalid offset");
8891 inst
.instruction
|= offset
>> 2;
8894 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8898 inst
.error
= _("invalid base register in load/store");
8901 else if (Ro
== FAIL
)
8903 /* Immediate offset. */
8904 if (size
== THUMB_WORD
)
8905 inst
.instruction
= (load_store
== THUMB_LOAD
8906 ? T_OPCODE_LDR_IW
: T_OPCODE_STR_IW
);
8907 else if (size
== THUMB_HALFWORD
)
8908 inst
.instruction
= (load_store
== THUMB_LOAD
8909 ? T_OPCODE_LDR_IH
: T_OPCODE_STR_IH
);
8911 inst
.instruction
= (load_store
== THUMB_LOAD
8912 ? T_OPCODE_LDR_IB
: T_OPCODE_STR_IB
);
8914 inst
.instruction
|= Rd
| (Rb
<< 3);
8916 if (inst
.reloc
.exp
.X_op
== O_constant
)
8918 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
8920 if (offset
& ~(0x1f << size
))
8922 inst
.error
= _("invalid offset");
8925 inst
.instruction
|= (offset
>> size
) << 6;
8928 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8932 /* Register offset. */
8933 if (size
== THUMB_WORD
)
8934 inst
.instruction
= (load_store
== THUMB_LOAD
8935 ? T_OPCODE_LDR_RW
: T_OPCODE_STR_RW
);
8936 else if (size
== THUMB_HALFWORD
)
8937 inst
.instruction
= (load_store
== THUMB_LOAD
8938 ? T_OPCODE_LDR_RH
: T_OPCODE_STR_RH
);
8940 inst
.instruction
= (load_store
== THUMB_LOAD
8941 ? T_OPCODE_LDR_RB
: T_OPCODE_STR_RB
);
8943 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
8949 /* A register must be given at this point.
8951 Shift is the place to put it in inst.instruction.
8953 Restores input start point on err.
8954 Returns the reg#, or FAIL. */
8957 mav_reg_required_here (char ** str
, int shift
, enum arm_reg_type regtype
)
8962 if ((reg
= arm_reg_parse (str
, all_reg_maps
[regtype
].htab
)) != FAIL
)
8965 inst
.instruction
|= reg
<< shift
;
8970 /* Restore the start point. */
8973 /* Try generic coprocessor name if applicable. */
8974 if (regtype
== REG_TYPE_MVF
||
8975 regtype
== REG_TYPE_MVD
||
8976 regtype
== REG_TYPE_MVFX
||
8977 regtype
== REG_TYPE_MVDX
)
8979 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CN
].htab
)) != FAIL
)
8982 inst
.instruction
|= reg
<< shift
;
8987 /* Restore the start point. */
8991 /* In the few cases where we might be able to accept something else
8992 this error can be overridden. */
8993 inst
.error
= _(all_reg_maps
[regtype
].expected
);
8998 /* Cirrus Maverick Instructions. */
9000 /* Isnsn like "foo X,Y". */
9003 do_mav_binops (char * str
,
9005 enum arm_reg_type reg0
,
9006 enum arm_reg_type reg1
)
9010 shift0
= mode
& 0xff;
9011 shift1
= (mode
>> 8) & 0xff;
9013 skip_whitespace (str
);
9015 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
9016 || skip_past_comma (&str
) == FAIL
9017 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
)
9020 inst
.error
= BAD_ARGS
;
9026 /* Isnsn like "foo X,Y,Z". */
9029 do_mav_triple (char * str
,
9031 enum arm_reg_type reg0
,
9032 enum arm_reg_type reg1
,
9033 enum arm_reg_type reg2
)
9035 int shift0
, shift1
, shift2
;
9037 shift0
= mode
& 0xff;
9038 shift1
= (mode
>> 8) & 0xff;
9039 shift2
= (mode
>> 16) & 0xff;
9041 skip_whitespace (str
);
9043 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
9044 || skip_past_comma (&str
) == FAIL
9045 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
9046 || skip_past_comma (&str
) == FAIL
9047 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
)
9050 inst
.error
= BAD_ARGS
;
9056 /* Wrapper functions. */
9059 do_mav_binops_1a (char * str
)
9061 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVF
);
9065 do_mav_binops_1b (char * str
)
9067 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVD
);
9071 do_mav_binops_1c (char * str
)
9073 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVDX
);
9077 do_mav_binops_1d (char * str
)
9079 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVF
);
9083 do_mav_binops_1e (char * str
)
9085 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVD
);
9089 do_mav_binops_1f (char * str
)
9091 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVF
);
9095 do_mav_binops_1g (char * str
)
9097 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVD
);
9101 do_mav_binops_1h (char * str
)
9103 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVFX
);
9107 do_mav_binops_1i (char * str
)
9109 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVFX
);
9113 do_mav_binops_1j (char * str
)
9115 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVDX
);
9119 do_mav_binops_1k (char * str
)
9121 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVDX
);
9125 do_mav_binops_1l (char * str
)
9127 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVF
);
9131 do_mav_binops_1m (char * str
)
9133 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVD
);
9137 do_mav_binops_1n (char * str
)
9139 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
9143 do_mav_binops_1o (char * str
)
9145 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
9149 do_mav_binops_2a (char * str
)
9151 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVF
, REG_TYPE_RN
);
9155 do_mav_binops_2b (char * str
)
9157 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVD
, REG_TYPE_RN
);
9161 do_mav_binops_2c (char * str
)
9163 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVDX
, REG_TYPE_RN
);
9167 do_mav_binops_3a (char * str
)
9169 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVFX
);
9173 do_mav_binops_3b (char * str
)
9175 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVFX
, REG_TYPE_MVAX
);
9179 do_mav_binops_3c (char * str
)
9181 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVDX
);
9185 do_mav_binops_3d (char * str
)
9187 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVDX
, REG_TYPE_MVAX
);
9191 do_mav_triple_4a (char * str
)
9193 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_RN
);
9197 do_mav_triple_4b (char * str
)
9199 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_RN
);
9203 do_mav_triple_5a (char * str
)
9205 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVF
, REG_TYPE_MVF
);
9209 do_mav_triple_5b (char * str
)
9211 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVD
, REG_TYPE_MVD
);
9215 do_mav_triple_5c (char * str
)
9217 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
9221 do_mav_triple_5d (char * str
)
9223 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
9227 do_mav_triple_5e (char * str
)
9229 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVF
, REG_TYPE_MVF
, REG_TYPE_MVF
);
9233 do_mav_triple_5f (char * str
)
9235 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVD
, REG_TYPE_MVD
, REG_TYPE_MVD
);
9239 do_mav_triple_5g (char * str
)
9241 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
9245 do_mav_triple_5h (char * str
)
9247 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
9250 /* Isnsn like "foo W,X,Y,Z".
9251 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
9254 do_mav_quad (char * str
,
9256 enum arm_reg_type reg0
,
9257 enum arm_reg_type reg1
,
9258 enum arm_reg_type reg2
,
9259 enum arm_reg_type reg3
)
9261 int shift0
, shift1
, shift2
, shift3
;
9263 shift0
= mode
& 0xff;
9264 shift1
= (mode
>> 8) & 0xff;
9265 shift2
= (mode
>> 16) & 0xff;
9266 shift3
= (mode
>> 24) & 0xff;
9268 skip_whitespace (str
);
9270 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
9271 || skip_past_comma (&str
) == FAIL
9272 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
9273 || skip_past_comma (&str
) == FAIL
9274 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
9275 || skip_past_comma (&str
) == FAIL
9276 || mav_reg_required_here (&str
, shift3
, reg3
) == FAIL
)
9279 inst
.error
= BAD_ARGS
;
9286 do_mav_quad_6a (char * str
)
9288 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
,
9293 do_mav_quad_6b (char * str
)
9295 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVAX
, REG_TYPE_MVFX
,
9299 /* cfmvsc32<cond> DSPSC,MVDX[15:0]. */
9301 do_mav_dspsc_1 (char * str
)
9303 skip_whitespace (str
);
9306 if (mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
9307 || skip_past_comma (&str
) == FAIL
9308 || mav_reg_required_here (&str
, 12, REG_TYPE_MVDX
) == FAIL
)
9311 inst
.error
= BAD_ARGS
;
9319 /* cfmv32sc<cond> MVDX[15:0],DSPSC. */
9321 do_mav_dspsc_2 (char * str
)
9323 skip_whitespace (str
);
9326 if (mav_reg_required_here (&str
, 12, REG_TYPE_MVDX
) == FAIL
9327 || skip_past_comma (&str
) == FAIL
9328 || mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
)
9331 inst
.error
= BAD_ARGS
;
9339 /* Maverick shift immediate instructions.
9340 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
9341 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
9344 do_mav_shift (char * str
,
9345 enum arm_reg_type reg0
,
9346 enum arm_reg_type reg1
)
9351 skip_whitespace (str
);
9355 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
9356 || skip_past_comma (&str
) == FAIL
9357 || mav_reg_required_here (&str
, 16, reg1
) == FAIL
9358 || skip_past_comma (&str
) == FAIL
)
9361 inst
.error
= BAD_ARGS
;
9365 /* Calculate the immediate operand.
9366 The operand is a 7bit signed number. */
9367 skip_whitespace (str
);
9372 if (!ISDIGIT (*str
) && *str
!= '-')
9374 inst
.error
= _("expecting immediate, 7bit operand");
9384 for (imm
= 0; *str
&& ISDIGIT (*str
); ++str
)
9385 imm
= imm
* 10 + *str
- '0';
9389 inst
.error
= _("immediate out of range");
9393 /* Make negative imm's into 7bit signed numbers. */
9400 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
9401 Bits 5-7 of the insn should have bits 4-6 of the immediate.
9402 Bit 4 should be 0. */
9403 imm
= (imm
& 0xf) | ((imm
& 0x70) << 1);
9405 inst
.instruction
|= imm
;
9410 do_mav_shift_1 (char * str
)
9412 do_mav_shift (str
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
9416 do_mav_shift_2 (char * str
)
9418 do_mav_shift (str
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
9422 mav_parse_offset (char ** str
, int * negative
)
9429 skip_whitespace (p
);
9442 inst
.error
= _("offset expected");
9446 for (offset
= 0; *p
&& ISDIGIT (*p
); ++p
)
9447 offset
= offset
* 10 + *p
- '0';
9451 inst
.error
= _("offset out of range");
9456 inst
.error
= _("offset not a multiple of 4");
9462 return *negative
? -offset
: offset
;
9465 /* Maverick load/store instructions.
9466 <insn><cond> CRd,[Rn,<offset>]{!}.
9467 <insn><cond> CRd,[Rn],<offset>. */
9470 do_mav_ldst (char * str
, enum arm_reg_type reg0
)
9472 int offset
, negative
;
9474 skip_whitespace (str
);
9476 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
9477 || skip_past_comma (&str
) == FAIL
9479 || reg_required_here (&str
, 16) == FAIL
)
9482 if (skip_past_comma (&str
) == SUCCESS
)
9484 /* You are here: "<offset>]{!}". */
9485 inst
.instruction
|= PRE_INDEX
;
9487 offset
= mav_parse_offset (&str
, &negative
);
9494 inst
.error
= _("missing ]");
9500 inst
.instruction
|= WRITE_BACK
;
9506 /* You are here: "], <offset>". */
9509 inst
.error
= _("missing ]");
9513 if (skip_past_comma (&str
) == FAIL
9514 || (offset
= mav_parse_offset (&str
, &negative
), inst
.error
))
9517 inst
.instruction
|= CP_T_WB
; /* Post indexed, set bit W. */
9523 inst
.instruction
|= CP_T_UD
; /* Positive, so set bit U. */
9525 inst
.instruction
|= offset
>> 2;
9531 inst
.error
= BAD_ARGS
;
9535 do_mav_ldst_1 (char * str
)
9537 do_mav_ldst (str
, REG_TYPE_MVF
);
9541 do_mav_ldst_2 (char * str
)
9543 do_mav_ldst (str
, REG_TYPE_MVD
);
9547 do_mav_ldst_3 (char * str
)
9549 do_mav_ldst (str
, REG_TYPE_MVFX
);
9553 do_mav_ldst_4 (char * str
)
9555 do_mav_ldst (str
, REG_TYPE_MVDX
);
9559 do_t_nop (char * str
)
9565 /* Handle the Format 4 instructions that do not have equivalents in other
9566 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
9570 do_t_arit (char * str
)
9574 skip_whitespace (str
);
9576 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9577 || skip_past_comma (&str
) == FAIL
9578 || (Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9580 inst
.error
= BAD_ARGS
;
9584 if (skip_past_comma (&str
) != FAIL
)
9586 /* Three operand format not allowed for TST, CMN, NEG and MVN.
9587 (It isn't allowed for CMP either, but that isn't handled by this
9589 if (inst
.instruction
== T_OPCODE_TST
9590 || inst
.instruction
== T_OPCODE_CMN
9591 || inst
.instruction
== T_OPCODE_NEG
9592 || inst
.instruction
== T_OPCODE_MVN
)
9594 inst
.error
= BAD_ARGS
;
9598 if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9603 inst
.error
= _("dest and source1 must be the same register");
9609 if (inst
.instruction
== T_OPCODE_MUL
9611 as_tsktsk (_("Rs and Rd must be different in MUL"));
9613 inst
.instruction
|= Rd
| (Rs
<< 3);
9618 do_t_add (char * str
)
9620 thumb_add_sub (str
, 0);
9624 do_t_asr (char * str
)
9626 thumb_shift (str
, THUMB_ASR
);
9630 do_t_branch9 (char * str
)
9632 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9634 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH9
;
9635 inst
.reloc
.pc_rel
= 1;
9640 do_t_branch12 (char * str
)
9642 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9644 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH12
;
9645 inst
.reloc
.pc_rel
= 1;
9649 /* Find the real, Thumb encoded start of a Thumb function. */
9652 find_real_start (symbolS
* symbolP
)
9655 const char * name
= S_GET_NAME (symbolP
);
9656 symbolS
* new_target
;
9658 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
9659 #define STUB_NAME ".real_start_of"
9664 /* Names that start with '.' are local labels, not function entry points.
9665 The compiler may generate BL instructions to these labels because it
9666 needs to perform a branch to a far away location. */
9670 real_start
= malloc (strlen (name
) + strlen (STUB_NAME
) + 1);
9671 sprintf (real_start
, "%s%s", STUB_NAME
, name
);
9673 new_target
= symbol_find (real_start
);
9675 if (new_target
== NULL
)
9677 as_warn ("Failed to find real start of function: %s\n", name
);
9678 new_target
= symbolP
;
9687 do_t_branch23 (char * str
)
9689 if (my_get_expression (& inst
.reloc
.exp
, & str
))
9692 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH23
;
9693 inst
.reloc
.pc_rel
= 1;
9696 /* If the destination of the branch is a defined symbol which does not have
9697 the THUMB_FUNC attribute, then we must be calling a function which has
9698 the (interfacearm) attribute. We look for the Thumb entry point to that
9699 function and change the branch to refer to that function instead. */
9700 if ( inst
.reloc
.exp
.X_op
== O_symbol
9701 && inst
.reloc
.exp
.X_add_symbol
!= NULL
9702 && S_IS_DEFINED (inst
.reloc
.exp
.X_add_symbol
)
9703 && ! THUMB_IS_FUNC (inst
.reloc
.exp
.X_add_symbol
))
9704 inst
.reloc
.exp
.X_add_symbol
=
9705 find_real_start (inst
.reloc
.exp
.X_add_symbol
);
9709 do_t_bx (char * str
)
9713 skip_whitespace (str
);
9715 if ((reg
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
9718 /* This sets THUMB_H2 from the top bit of reg. */
9719 inst
.instruction
|= reg
<< 3;
9721 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
9722 should cause the alignment to be checked once it is known. This is
9723 because BX PC only works if the instruction is word aligned. */
9729 do_t_compare (char * str
)
9731 thumb_mov_compare (str
, THUMB_COMPARE
);
9735 do_t_ldmstm (char * str
)
9740 skip_whitespace (str
);
9742 if ((Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9746 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
9750 if (skip_past_comma (&str
) == FAIL
9751 || (range
= reg_list (&str
)) == FAIL
)
9754 inst
.error
= BAD_ARGS
;
9758 if (inst
.reloc
.type
!= BFD_RELOC_UNUSED
)
9760 /* This really doesn't seem worth it. */
9761 inst
.reloc
.type
= BFD_RELOC_UNUSED
;
9762 inst
.error
= _("expression too complex");
9768 inst
.error
= _("only lo-regs valid in load/store multiple");
9772 inst
.instruction
|= (Rb
<< 8) | range
;
9777 do_t_ldr (char * str
)
9779 thumb_load_store (str
, THUMB_LOAD
, THUMB_WORD
);
9783 do_t_ldrb (char * str
)
9785 thumb_load_store (str
, THUMB_LOAD
, THUMB_BYTE
);
9789 do_t_ldrh (char * str
)
9791 thumb_load_store (str
, THUMB_LOAD
, THUMB_HALFWORD
);
9795 do_t_lds (char * str
)
9799 skip_whitespace (str
);
9801 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9802 || skip_past_comma (&str
) == FAIL
9804 || (Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9805 || skip_past_comma (&str
) == FAIL
9806 || (Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9810 inst
.error
= _("syntax: ldrs[b] Rd, [Rb, Ro]");
9814 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
9819 do_t_lsl (char * str
)
9821 thumb_shift (str
, THUMB_LSL
);
9825 do_t_lsr (char * str
)
9827 thumb_shift (str
, THUMB_LSR
);
9831 do_t_mov (char * str
)
9833 thumb_mov_compare (str
, THUMB_MOVE
);
9837 do_t_push_pop (char * str
)
9841 skip_whitespace (str
);
9843 if ((range
= reg_list (&str
)) == FAIL
)
9846 inst
.error
= BAD_ARGS
;
9850 if (inst
.reloc
.type
!= BFD_RELOC_UNUSED
)
9852 /* This really doesn't seem worth it. */
9853 inst
.reloc
.type
= BFD_RELOC_UNUSED
;
9854 inst
.error
= _("expression too complex");
9860 if ((inst
.instruction
== T_OPCODE_PUSH
9861 && (range
& ~0xff) == 1 << REG_LR
)
9862 || (inst
.instruction
== T_OPCODE_POP
9863 && (range
& ~0xff) == 1 << REG_PC
))
9865 inst
.instruction
|= THUMB_PP_PC_LR
;
9870 inst
.error
= _("invalid register list to push/pop instruction");
9875 inst
.instruction
|= range
;
9880 do_t_str (char * str
)
9882 thumb_load_store (str
, THUMB_STORE
, THUMB_WORD
);
9886 do_t_strb (char * str
)
9888 thumb_load_store (str
, THUMB_STORE
, THUMB_BYTE
);
9892 do_t_strh (char * str
)
9894 thumb_load_store (str
, THUMB_STORE
, THUMB_HALFWORD
);
9898 do_t_sub (char * str
)
9900 thumb_add_sub (str
, 1);
9904 do_t_swi (char * str
)
9906 skip_whitespace (str
);
9908 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9911 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
9916 do_t_adr (char * str
)
9920 /* This is a pseudo-op of the form "adr rd, label" to be converted
9921 into a relative address of the form "add rd, pc, #label-.-4". */
9922 skip_whitespace (str
);
9924 /* Store Rd in temporary location inside instruction. */
9925 if ((reg
= reg_required_here (&str
, 4)) == FAIL
9926 || (reg
> 7) /* For Thumb reg must be r0..r7. */
9927 || skip_past_comma (&str
) == FAIL
9928 || my_get_expression (&inst
.reloc
.exp
, &str
))
9931 inst
.error
= BAD_ARGS
;
9935 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
9936 inst
.reloc
.exp
.X_add_number
-= 4; /* PC relative adjust. */
9937 inst
.reloc
.pc_rel
= 1;
9938 inst
.instruction
|= REG_PC
; /* Rd is already placed into the instruction. */
9944 insert_reg (const struct reg_entry
* r
,
9945 struct hash_control
* htab
)
9947 int len
= strlen (r
->name
) + 2;
9948 char * buf
= xmalloc (len
);
9949 char * buf2
= xmalloc (len
);
9952 #ifdef REGISTER_PREFIX
9953 buf
[i
++] = REGISTER_PREFIX
;
9956 strcpy (buf
+ i
, r
->name
);
9958 for (i
= 0; buf
[i
]; i
++)
9959 buf2
[i
] = TOUPPER (buf
[i
]);
9963 hash_insert (htab
, buf
, (PTR
) r
);
9964 hash_insert (htab
, buf2
, (PTR
) r
);
9968 build_reg_hsh (struct reg_map
* map
)
9970 const struct reg_entry
*r
;
9972 if ((map
->htab
= hash_new ()) == NULL
)
9973 as_fatal (_("virtual memory exhausted"));
9975 for (r
= map
->names
; r
->name
!= NULL
; r
++)
9976 insert_reg (r
, map
->htab
);
9980 insert_reg_alias (char * str
,
9982 struct hash_control
*htab
)
9985 struct reg_entry
* new = xmalloc (sizeof (struct reg_entry
));
9986 const char * name
= xmalloc (strlen (str
) + 1);
9988 strcpy ((char *) name
, str
);
9991 new->number
= regnum
;
9992 new->builtin
= FALSE
;
9994 error
= hash_insert (htab
, name
, (PTR
) new);
9997 as_bad (_("failed to create an alias for %s, reason: %s"),
9999 free ((char *) name
);
10004 /* Look for the .req directive. This is of the form:
10006 new_register_name .req existing_register_name
10008 If we find one, or if it looks sufficiently like one that we want to
10009 handle any error here, return non-zero. Otherwise return zero. */
10012 create_register_alias (char * newname
, char * p
)
10018 skip_whitespace (q
);
10023 if (*q
&& !strncmp (q
, ".req ", 5))
10028 #ifndef IGNORE_OPCODE_CASE
10029 newname
= original_case_string
;
10031 copy_of_str
= newname
;
10034 skip_whitespace (q
);
10036 for (r
= q
; *r
!= '\0'; r
++)
10042 enum arm_reg_type new_type
, old_type
;
10047 old_type
= arm_reg_parse_any (q
);
10050 new_type
= arm_reg_parse_any (newname
);
10052 if (new_type
== REG_TYPE_MAX
)
10054 if (old_type
!= REG_TYPE_MAX
)
10056 old_regno
= arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
);
10057 insert_reg_alias (newname
, old_regno
,
10058 all_reg_maps
[old_type
].htab
);
10061 as_warn (_("register '%s' does not exist\n"), q
);
10063 else if (old_type
== REG_TYPE_MAX
)
10065 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
10070 /* Do not warn about redefinitions to the same alias. */
10071 if (new_type
!= old_type
10072 || (arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
)
10073 != arm_reg_parse (&q
, all_reg_maps
[new_type
].htab
)))
10074 as_warn (_("ignoring redefinition of register alias '%s'"),
10080 as_warn (_("ignoring incomplete .req pseuso op"));
10091 set_constant_flonums (void)
10095 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
10096 if (atof_ieee ((char *) fp_const
[i
], 'x', fp_values
[i
]) == NULL
)
10101 static const struct asm_opcode insns
[] =
10103 /* Core ARM Instructions. */
10104 {"and", 0xe0000000, 3, ARM_EXT_V1
, do_arit
},
10105 {"ands", 0xe0100000, 3, ARM_EXT_V1
, do_arit
},
10106 {"eor", 0xe0200000, 3, ARM_EXT_V1
, do_arit
},
10107 {"eors", 0xe0300000, 3, ARM_EXT_V1
, do_arit
},
10108 {"sub", 0xe0400000, 3, ARM_EXT_V1
, do_arit
},
10109 {"subs", 0xe0500000, 3, ARM_EXT_V1
, do_arit
},
10110 {"rsb", 0xe0600000, 3, ARM_EXT_V1
, do_arit
},
10111 {"rsbs", 0xe0700000, 3, ARM_EXT_V1
, do_arit
},
10112 {"add", 0xe0800000, 3, ARM_EXT_V1
, do_arit
},
10113 {"adds", 0xe0900000, 3, ARM_EXT_V1
, do_arit
},
10114 {"adc", 0xe0a00000, 3, ARM_EXT_V1
, do_arit
},
10115 {"adcs", 0xe0b00000, 3, ARM_EXT_V1
, do_arit
},
10116 {"sbc", 0xe0c00000, 3, ARM_EXT_V1
, do_arit
},
10117 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1
, do_arit
},
10118 {"rsc", 0xe0e00000, 3, ARM_EXT_V1
, do_arit
},
10119 {"rscs", 0xe0f00000, 3, ARM_EXT_V1
, do_arit
},
10120 {"orr", 0xe1800000, 3, ARM_EXT_V1
, do_arit
},
10121 {"orrs", 0xe1900000, 3, ARM_EXT_V1
, do_arit
},
10122 {"bic", 0xe1c00000, 3, ARM_EXT_V1
, do_arit
},
10123 {"bics", 0xe1d00000, 3, ARM_EXT_V1
, do_arit
},
10125 {"tst", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
10126 {"tsts", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
10127 {"tstp", 0xe110f000, 3, ARM_EXT_V1
, do_cmp
},
10128 {"teq", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
10129 {"teqs", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
10130 {"teqp", 0xe130f000, 3, ARM_EXT_V1
, do_cmp
},
10131 {"cmp", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
10132 {"cmps", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
10133 {"cmpp", 0xe150f000, 3, ARM_EXT_V1
, do_cmp
},
10134 {"cmn", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
10135 {"cmns", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
10136 {"cmnp", 0xe170f000, 3, ARM_EXT_V1
, do_cmp
},
10138 {"mov", 0xe1a00000, 3, ARM_EXT_V1
, do_mov
},
10139 {"movs", 0xe1b00000, 3, ARM_EXT_V1
, do_mov
},
10140 {"mvn", 0xe1e00000, 3, ARM_EXT_V1
, do_mov
},
10141 {"mvns", 0xe1f00000, 3, ARM_EXT_V1
, do_mov
},
10143 {"ldr", 0xe4100000, 3, ARM_EXT_V1
, do_ldst
},
10144 {"ldrb", 0xe4500000, 3, ARM_EXT_V1
, do_ldst
},
10145 {"ldrt", 0xe4300000, 3, ARM_EXT_V1
, do_ldstt
},
10146 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1
, do_ldstt
},
10147 {"str", 0xe4000000, 3, ARM_EXT_V1
, do_ldst
},
10148 {"strb", 0xe4400000, 3, ARM_EXT_V1
, do_ldst
},
10149 {"strt", 0xe4200000, 3, ARM_EXT_V1
, do_ldstt
},
10150 {"strbt", 0xe4600000, 3, ARM_EXT_V1
, do_ldstt
},
10152 {"stmia", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
10153 {"stmib", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
10154 {"stmda", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
10155 {"stmdb", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
10156 {"stmfd", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
10157 {"stmfa", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
10158 {"stmea", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
10159 {"stmed", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
10161 {"ldmia", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
10162 {"ldmib", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
10163 {"ldmda", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
10164 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
10165 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
10166 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
10167 {"ldmea", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
10168 {"ldmed", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
10170 {"swi", 0xef000000, 3, ARM_EXT_V1
, do_swi
},
10172 /* XXX This is the wrong place to do this. Think multi-arch. */
10173 {"bl", 0xeb000000, 2, ARM_EXT_V1
, do_branch
},
10174 {"b", 0xea000000, 1, ARM_EXT_V1
, do_branch
},
10176 {"bl", 0xebfffffe, 2, ARM_EXT_V1
, do_branch
},
10177 {"b", 0xeafffffe, 1, ARM_EXT_V1
, do_branch
},
10181 {"adr", 0xe28f0000, 3, ARM_EXT_V1
, do_adr
},
10182 {"adrl", 0xe28f0000, 3, ARM_EXT_V1
, do_adrl
},
10183 {"nop", 0xe1a00000, 3, ARM_EXT_V1
, do_nop
},
10185 /* ARM 2 multiplies. */
10186 {"mul", 0xe0000090, 3, ARM_EXT_V2
, do_mul
},
10187 {"muls", 0xe0100090, 3, ARM_EXT_V2
, do_mul
},
10188 {"mla", 0xe0200090, 3, ARM_EXT_V2
, do_mla
},
10189 {"mlas", 0xe0300090, 3, ARM_EXT_V2
, do_mla
},
10191 /* Generic coprocessor instructions. */
10192 {"cdp", 0xee000000, 3, ARM_EXT_V2
, do_cdp
},
10193 {"ldc", 0xec100000, 3, ARM_EXT_V2
, do_lstc
},
10194 {"ldcl", 0xec500000, 3, ARM_EXT_V2
, do_lstc
},
10195 {"stc", 0xec000000, 3, ARM_EXT_V2
, do_lstc
},
10196 {"stcl", 0xec400000, 3, ARM_EXT_V2
, do_lstc
},
10197 {"mcr", 0xee000010, 3, ARM_EXT_V2
, do_co_reg
},
10198 {"mrc", 0xee100010, 3, ARM_EXT_V2
, do_co_reg
},
10200 /* ARM 3 - swp instructions. */
10201 {"swp", 0xe1000090, 3, ARM_EXT_V2S
, do_swap
},
10202 {"swpb", 0xe1400090, 3, ARM_EXT_V2S
, do_swap
},
10204 /* ARM 6 Status register instructions. */
10205 {"mrs", 0xe10f0000, 3, ARM_EXT_V3
, do_mrs
},
10206 {"msr", 0xe120f000, 3, ARM_EXT_V3
, do_msr
},
10207 /* ScottB: our code uses 0xe128f000 for msr.
10208 NickC: but this is wrong because the bits 16 through 19 are
10209 handled by the PSR_xxx defines above. */
10211 /* ARM 7M long multiplies. */
10212 {"smull", 0xe0c00090, 5, ARM_EXT_V3M
, do_mull
},
10213 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M
, do_mull
},
10214 {"umull", 0xe0800090, 5, ARM_EXT_V3M
, do_mull
},
10215 {"umulls", 0xe0900090, 5, ARM_EXT_V3M
, do_mull
},
10216 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M
, do_mull
},
10217 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M
, do_mull
},
10218 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M
, do_mull
},
10219 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M
, do_mull
},
10221 /* ARM Architecture 4. */
10222 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4
, do_ldstv4
},
10223 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4
, do_ldstv4
},
10224 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4
, do_ldstv4
},
10225 {"strh", 0xe00000b0, 3, ARM_EXT_V4
, do_ldstv4
},
10227 /* ARM Architecture 4T. */
10228 /* Note: bx (and blx) are required on V5, even if the processor does
10229 not support Thumb. */
10230 {"bx", 0xe12fff10, 2, ARM_EXT_V4T
| ARM_EXT_V5
, do_bx
},
10232 /* ARM Architecture 5T. */
10233 /* Note: blx has 2 variants, so the .value is set dynamically.
10234 Only one of the variants has conditional execution. */
10235 {"blx", 0xe0000000, 3, ARM_EXT_V5
, do_blx
},
10236 {"clz", 0xe16f0f10, 3, ARM_EXT_V5
, do_clz
},
10237 {"bkpt", 0xe1200070, 0, ARM_EXT_V5
, do_bkpt
},
10238 {"ldc2", 0xfc100000, 0, ARM_EXT_V5
, do_lstc2
},
10239 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5
, do_lstc2
},
10240 {"stc2", 0xfc000000, 0, ARM_EXT_V5
, do_lstc2
},
10241 {"stc2l", 0xfc400000, 0, ARM_EXT_V5
, do_lstc2
},
10242 {"cdp2", 0xfe000000, 0, ARM_EXT_V5
, do_cdp2
},
10243 {"mcr2", 0xfe000010, 0, ARM_EXT_V5
, do_co_reg2
},
10244 {"mrc2", 0xfe100010, 0, ARM_EXT_V5
, do_co_reg2
},
10246 /* ARM Architecture 5TExP. */
10247 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP
, do_smla
},
10248 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP
, do_smla
},
10249 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP
, do_smla
},
10250 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP
, do_smla
},
10252 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP
, do_smla
},
10253 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP
, do_smla
},
10255 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP
, do_smlal
},
10256 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP
, do_smlal
},
10257 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP
, do_smlal
},
10258 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP
, do_smlal
},
10260 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP
, do_smul
},
10261 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP
, do_smul
},
10262 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP
, do_smul
},
10263 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP
, do_smul
},
10265 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP
, do_smul
},
10266 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP
, do_smul
},
10268 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP
, do_qadd
},
10269 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP
, do_qadd
},
10270 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP
, do_qadd
},
10271 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP
, do_qadd
},
10273 /* ARM Architecture 5TE. */
10274 {"pld", 0xf450f000, 0, ARM_EXT_V5E
, do_pld
},
10275 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E
, do_ldrd
},
10276 {"strd", 0xe00000f0, 3, ARM_EXT_V5E
, do_ldrd
},
10278 {"mcrr", 0xec400000, 4, ARM_EXT_V5E
, do_co_reg2c
},
10279 {"mrrc", 0xec500000, 4, ARM_EXT_V5E
, do_co_reg2c
},
10281 /* ARM Architecture 5TEJ. */
10282 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J
, do_bxj
},
10285 { "cps", 0xf1020000, 0, ARM_EXT_V6
, do_cps
},
10286 { "cpsie", 0xf1080000, 0, ARM_EXT_V6
, do_cpsi
},
10287 { "cpsid", 0xf10C0000, 0, ARM_EXT_V6
, do_cpsi
},
10288 { "ldrex", 0xe1900f9f, 5, ARM_EXT_V6
, do_ldrex
},
10289 { "mcrr2", 0xfc400000, 0, ARM_EXT_V6
, do_co_reg2c
},
10290 { "mrrc2", 0xfc500000, 0, ARM_EXT_V6
, do_co_reg2c
},
10291 { "pkhbt", 0xe6800010, 5, ARM_EXT_V6
, do_pkhbt
},
10292 { "pkhtb", 0xe6800050, 5, ARM_EXT_V6
, do_pkhtb
},
10293 { "qadd16", 0xe6200f10, 6, ARM_EXT_V6
, do_qadd16
},
10294 { "qadd8", 0xe6200f90, 5, ARM_EXT_V6
, do_qadd16
},
10295 { "qaddsubx", 0xe6200f30, 8, ARM_EXT_V6
, do_qadd16
},
10296 { "qsub16", 0xe6200f70, 6, ARM_EXT_V6
, do_qadd16
},
10297 { "qsub8", 0xe6200ff0, 5, ARM_EXT_V6
, do_qadd16
},
10298 { "qsubaddx", 0xe6200f50, 8, ARM_EXT_V6
, do_qadd16
},
10299 { "sadd16", 0xe6100f10, 6, ARM_EXT_V6
, do_qadd16
},
10300 { "sadd8", 0xe6100f90, 5, ARM_EXT_V6
, do_qadd16
},
10301 { "saddsubx", 0xe6100f30, 8, ARM_EXT_V6
, do_qadd16
},
10302 { "shadd16", 0xe6300f10, 7, ARM_EXT_V6
, do_qadd16
},
10303 { "shadd8", 0xe6300f90, 6, ARM_EXT_V6
, do_qadd16
},
10304 { "shaddsubx", 0xe6300f30, 9, ARM_EXT_V6
, do_qadd16
},
10305 { "shsub16", 0xe6300f70, 7, ARM_EXT_V6
, do_qadd16
},
10306 { "shsub8", 0xe6300ff0, 6, ARM_EXT_V6
, do_qadd16
},
10307 { "shsubaddx", 0xe6300f50, 9, ARM_EXT_V6
, do_qadd16
},
10308 { "ssub16", 0xe6100f70, 6, ARM_EXT_V6
, do_qadd16
},
10309 { "ssub8", 0xe6100ff0, 5, ARM_EXT_V6
, do_qadd16
},
10310 { "ssubaddx", 0xe6100f50, 8, ARM_EXT_V6
, do_qadd16
},
10311 { "uadd16", 0xe6500f10, 6, ARM_EXT_V6
, do_qadd16
},
10312 { "uadd8", 0xe6500f90, 5, ARM_EXT_V6
, do_qadd16
},
10313 { "uaddsubx", 0xe6500f30, 8, ARM_EXT_V6
, do_qadd16
},
10314 { "uhadd16", 0xe6700f10, 7, ARM_EXT_V6
, do_qadd16
},
10315 { "uhadd8", 0xe6700f90, 6, ARM_EXT_V6
, do_qadd16
},
10316 { "uhaddsubx", 0xe6700f30, 9, ARM_EXT_V6
, do_qadd16
},
10317 { "uhsub16", 0xe6700f70, 7, ARM_EXT_V6
, do_qadd16
},
10318 { "uhsub8", 0xe6700ff0, 6, ARM_EXT_V6
, do_qadd16
},
10319 { "uhsubaddx", 0xe6700f50, 9, ARM_EXT_V6
, do_qadd16
},
10320 { "uqadd16", 0xe6600f10, 7, ARM_EXT_V6
, do_qadd16
},
10321 { "uqadd8", 0xe6600f90, 6, ARM_EXT_V6
, do_qadd16
},
10322 { "uqaddsubx", 0xe6600f30, 9, ARM_EXT_V6
, do_qadd16
},
10323 { "uqsub16", 0xe6600f70, 7, ARM_EXT_V6
, do_qadd16
},
10324 { "uqsub8", 0xe6600ff0, 6, ARM_EXT_V6
, do_qadd16
},
10325 { "uqsubaddx", 0xe6600f50, 9, ARM_EXT_V6
, do_qadd16
},
10326 { "usub16", 0xe6500f70, 6, ARM_EXT_V6
, do_qadd16
},
10327 { "usub8", 0xe6500ff0, 5, ARM_EXT_V6
, do_qadd16
},
10328 { "usubaddx", 0xe6500f50, 8, ARM_EXT_V6
, do_qadd16
},
10329 { "rev", 0xe6bf0f30, 3, ARM_EXT_V6
, do_rev
},
10330 { "rev16", 0xe6bf0fb0, 5, ARM_EXT_V6
, do_rev
},
10331 { "revsh", 0xe6ff0fb0, 5, ARM_EXT_V6
, do_rev
},
10332 { "rfeia", 0xf8900a00, 0, ARM_EXT_V6
, do_rfe
},
10333 { "rfeib", 0xf9900a00, 0, ARM_EXT_V6
, do_rfe
},
10334 { "rfeda", 0xf8100a00, 0, ARM_EXT_V6
, do_rfe
},
10335 { "rfedb", 0xf9100a00, 0, ARM_EXT_V6
, do_rfe
},
10336 { "rfefd", 0xf8900a00, 0, ARM_EXT_V6
, do_rfe
},
10337 { "rfefa", 0xf9900a00, 0, ARM_EXT_V6
, do_rfe
},
10338 { "rfeea", 0xf8100a00, 0, ARM_EXT_V6
, do_rfe
},
10339 { "rfeed", 0xf9100a00, 0, ARM_EXT_V6
, do_rfe
},
10340 { "sxtah", 0xe6b00070, 5, ARM_EXT_V6
, do_sxtah
},
10341 { "sxtab16", 0xe6800070, 7, ARM_EXT_V6
, do_sxtah
},
10342 { "sxtab", 0xe6a00070, 5, ARM_EXT_V6
, do_sxtah
},
10343 { "sxth", 0xe6bf0070, 4, ARM_EXT_V6
, do_sxth
},
10344 { "sxtb16", 0xe68f0070, 6, ARM_EXT_V6
, do_sxth
},
10345 { "sxtb", 0xe6af0070, 4, ARM_EXT_V6
, do_sxth
},
10346 { "uxtah", 0xe6f00070, 5, ARM_EXT_V6
, do_sxtah
},
10347 { "uxtab16", 0xe6c00070, 7, ARM_EXT_V6
, do_sxtah
},
10348 { "uxtab", 0xe6e00070, 5, ARM_EXT_V6
, do_sxtah
},
10349 { "uxth", 0xe6ff0070, 4, ARM_EXT_V6
, do_sxth
},
10350 { "uxtb16", 0xe6cf0070, 6, ARM_EXT_V6
, do_sxth
},
10351 { "uxtb", 0xe6ef0070, 4, ARM_EXT_V6
, do_sxth
},
10352 { "sel", 0xe68000b0, 3, ARM_EXT_V6
, do_qadd16
},
10353 { "setend", 0xf1010000, 0, ARM_EXT_V6
, do_setend
},
10354 { "smlad", 0xe7000010, 5, ARM_EXT_V6
, do_smlad
},
10355 { "smladx", 0xe7000030, 6, ARM_EXT_V6
, do_smlad
},
10356 { "smlald", 0xe7400010, 6, ARM_EXT_V6
, do_smlald
},
10357 { "smlaldx", 0xe7400030, 7, ARM_EXT_V6
, do_smlald
},
10358 { "smlsd", 0xe7000050, 5, ARM_EXT_V6
, do_smlad
},
10359 { "smlsdx", 0xe7000070, 6, ARM_EXT_V6
, do_smlad
},
10360 { "smlsld", 0xe7400050, 6, ARM_EXT_V6
, do_smlald
},
10361 { "smlsldx", 0xe7400070, 7, ARM_EXT_V6
, do_smlald
},
10362 { "smmla", 0xe7500010, 5, ARM_EXT_V6
, do_smlad
},
10363 { "smmlar", 0xe7500030, 6, ARM_EXT_V6
, do_smlad
},
10364 { "smmls", 0xe75000d0, 5, ARM_EXT_V6
, do_smlad
},
10365 { "smmlsr", 0xe75000f0, 6, ARM_EXT_V6
, do_smlad
},
10366 { "smmul", 0xe750f010, 5, ARM_EXT_V6
, do_smmul
},
10367 { "smmulr", 0xe750f030, 6, ARM_EXT_V6
, do_smmul
},
10368 { "smuad", 0xe700f010, 5, ARM_EXT_V6
, do_smmul
},
10369 { "smuadx", 0xe700f030, 6, ARM_EXT_V6
, do_smmul
},
10370 { "smusd", 0xe700f050, 5, ARM_EXT_V6
, do_smmul
},
10371 { "smusdx", 0xe700f070, 6, ARM_EXT_V6
, do_smmul
},
10372 { "srsia", 0xf8cd0500, 0, ARM_EXT_V6
, do_srs
},
10373 { "srsib", 0xf9cd0500, 0, ARM_EXT_V6
, do_srs
},
10374 { "srsda", 0xf84d0500, 0, ARM_EXT_V6
, do_srs
},
10375 { "srsdb", 0xf94d0500, 0, ARM_EXT_V6
, do_srs
},
10376 { "ssat", 0xe6a00010, 4, ARM_EXT_V6
, do_ssat
},
10377 { "ssat16", 0xe6a00f30, 6, ARM_EXT_V6
, do_ssat16
},
10378 { "strex", 0xe1800f90, 5, ARM_EXT_V6
, do_strex
},
10379 { "umaal", 0xe0400090, 5, ARM_EXT_V6
, do_umaal
},
10380 { "usad8", 0xe780f010, 5, ARM_EXT_V6
, do_smmul
},
10381 { "usada8", 0xe7800010, 6, ARM_EXT_V6
, do_smlad
},
10382 { "usat", 0xe6e00010, 4, ARM_EXT_V6
, do_usat
},
10383 { "usat16", 0xe6e00f30, 6, ARM_EXT_V6
, do_usat16
},
10386 { "clrex", 0xf57ff01f, 0, ARM_EXT_V6K
, do_empty
},
10387 { "ldrexb", 0xe1d00f9f, 6, ARM_EXT_V6K
, do_ldrex
},
10388 { "ldrexd", 0xe1b00f9f, 6, ARM_EXT_V6K
, do_ldrex
},
10389 { "ldrexh", 0xe1f00f9f, 6, ARM_EXT_V6K
, do_ldrex
},
10390 { "sev", 0xe320f004, 3, ARM_EXT_V6K
, do_empty
},
10391 { "strexb", 0xe1c00f90, 6, ARM_EXT_V6K
, do_strex
},
10392 { "strexd", 0xe1a00f90, 6, ARM_EXT_V6K
, do_strex
},
10393 { "strexh", 0xe1e00f90, 6, ARM_EXT_V6K
, do_strex
},
10394 { "wfe", 0xe320f002, 3, ARM_EXT_V6K
, do_empty
},
10395 { "wfi", 0xe320f003, 3, ARM_EXT_V6K
, do_empty
},
10396 { "yield", 0xe320f001, 5, ARM_EXT_V6K
, do_empty
},
10399 { "smi", 0xe1600070, 3, ARM_EXT_V6Z
, do_smi
},
10402 { "bfc", 0xe7c0001f, 3, ARM_EXT_V6T2
, do_bfc
},
10403 { "bfi", 0xe7c00010, 3, ARM_EXT_V6T2
, do_bfi
},
10404 { "mls", 0xe0600090, 3, ARM_EXT_V6T2
, do_mls
},
10405 { "movw", 0xe3000000, 4, ARM_EXT_V6T2
, do_mov16
},
10406 { "movt", 0xe3400000, 4, ARM_EXT_V6T2
, do_mov16
},
10407 { "rbit", 0xe3ff0f30, 4, ARM_EXT_V6T2
, do_rbit
},
10408 { "sbfx", 0xe7a00050, 4, ARM_EXT_V6T2
, do_bfx
},
10409 { "ubfx", 0xe7e00050, 4, ARM_EXT_V6T2
, do_bfx
},
10411 { "ldrht", 0xe03000b0, 3, ARM_EXT_V6T2
, do_ldsttv4
},
10412 { "ldrsht", 0xe03000f0, 3, ARM_EXT_V6T2
, do_ldsttv4
},
10413 { "ldrsbt", 0xe03000d0, 3, ARM_EXT_V6T2
, do_ldsttv4
},
10414 { "strht", 0xe02000b0, 3, ARM_EXT_V6T2
, do_ldsttv4
},
10416 /* Core FPA instruction set (V1). */
10417 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
10418 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
10419 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
10420 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
10422 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10423 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10424 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10425 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10427 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10428 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10429 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10430 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10432 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10433 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10434 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10435 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10436 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10437 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10438 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10439 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10440 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10441 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10442 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10443 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10445 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10446 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10447 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10448 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10449 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10450 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10451 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10452 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10453 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10454 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10455 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10456 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10458 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10459 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10460 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10461 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10462 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10463 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10464 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10465 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10466 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10467 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10468 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10469 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10471 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10472 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10473 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10474 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10475 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10476 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10477 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10478 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10479 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10480 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10481 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10482 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10484 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10485 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10486 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10487 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10488 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10489 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10490 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10491 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10492 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10493 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10494 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10495 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10497 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10498 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10499 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10500 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10501 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10502 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10503 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10504 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10505 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10506 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10507 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10508 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10510 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10511 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10512 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10513 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10514 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10515 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10516 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10517 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10518 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10519 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10520 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10521 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10523 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10524 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10525 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10526 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10527 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10528 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10529 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10530 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10531 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10532 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10533 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10534 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10536 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10537 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10538 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10539 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10540 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10541 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10542 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10543 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10544 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10545 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10546 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10547 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10549 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10550 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10551 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10552 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10553 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10554 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10555 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10556 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10557 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10558 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10559 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10560 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10562 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10563 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10564 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10565 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10566 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10567 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10568 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10569 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10570 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10571 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10572 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10573 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10575 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10576 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10577 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10578 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10579 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10580 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10581 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10582 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10583 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10584 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10585 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10586 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10588 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10589 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10590 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10591 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10592 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10593 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10594 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10595 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10596 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10597 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10598 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10599 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10601 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10602 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10603 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10604 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10605 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10606 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10607 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10608 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10609 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10610 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10611 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10612 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10614 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10615 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10616 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10617 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10618 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10619 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10620 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10621 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10622 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10623 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10624 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10625 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10627 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10628 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10629 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10630 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10631 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10632 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10633 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10634 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10635 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10636 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10637 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10638 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10640 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10641 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10642 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10643 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10644 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10645 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10646 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10647 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10648 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10649 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10650 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10651 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10653 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10654 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10655 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10656 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10657 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10658 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10659 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10660 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10661 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10662 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10663 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10664 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10666 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10667 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10668 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10669 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10670 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10671 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10672 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10673 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10674 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10675 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10676 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10677 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10679 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10680 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10681 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10682 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10683 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10684 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10685 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10686 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10687 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10688 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10689 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10690 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10692 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10693 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10694 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10695 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10696 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10697 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10698 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10699 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10700 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10701 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10702 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10703 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10705 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10706 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10707 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10708 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10709 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10710 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10711 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10712 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10713 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10714 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10715 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10716 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10718 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10719 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10720 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10721 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10722 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10723 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10724 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10725 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10726 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10727 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10728 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10729 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10731 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10732 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10733 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10734 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10735 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10736 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10737 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10738 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10739 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10740 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10741 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10742 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10744 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10745 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10746 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10747 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10748 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10749 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10750 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10751 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10752 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10753 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10754 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10755 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10757 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10758 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10759 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10760 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10761 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10762 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10763 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10764 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10765 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10766 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10767 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10768 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10770 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10771 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10772 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10773 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10774 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10775 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10776 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10777 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10778 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10779 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10780 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10781 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10783 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10784 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10785 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10786 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10787 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10788 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10789 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10790 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10791 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10792 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10793 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10794 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10796 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10797 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10798 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10799 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10800 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10801 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10802 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10803 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10804 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10805 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10806 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10807 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10809 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10810 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10811 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10812 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10813 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
10814 not be an optional suffix, but part of the instruction. To be
10815 compatible, we accept either. */
10816 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10817 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10819 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10820 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10821 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10822 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10823 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10824 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10825 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10826 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10827 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10828 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10829 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10830 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10832 /* The implementation of the FIX instruction is broken on some
10833 assemblers, in that it accepts a precision specifier as well as a
10834 rounding specifier, despite the fact that this is meaningless.
10835 To be more compatible, we accept it as well, though of course it
10836 does not set any bits. */
10837 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10838 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10839 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10840 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10841 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10842 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10843 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10844 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10845 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10846 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10847 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10848 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10849 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10851 /* Instructions that were new with the real FPA, call them V2. */
10852 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10853 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10854 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10855 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10856 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10857 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10859 /* VFP V1xD (single precision). */
10860 /* Moves and type conversions. */
10861 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10862 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_reg_from_sp
},
10863 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_from_reg
},
10864 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD
, do_empty
},
10865 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10866 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10867 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10868 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10869 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10870 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10871 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_reg_from_ctrl
},
10872 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_ctrl_from_reg
},
10874 /* Memory operations. */
10875 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldst
},
10876 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldst
},
10877 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
10878 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
10879 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
10880 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
10881 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
10882 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
10883 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
10884 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
10885 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
10886 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
10887 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
10888 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
10889 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
10890 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
10891 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
10892 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
10894 /* Monadic operations. */
10895 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10896 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10897 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10899 /* Dyadic operations. */
10900 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10901 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10902 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10903 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10904 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10905 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10906 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10907 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10908 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10911 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10912 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_compare_z
},
10913 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10914 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_compare_z
},
10916 /* VFP V1 (Double precision). */
10917 /* Moves and type conversions. */
10918 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10919 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
10920 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10921 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1
, do_vfp_dp_from_reg
},
10922 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1
, do_vfp_dp_from_reg
},
10923 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1
, do_vfp_reg_from_dp
},
10924 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1
, do_vfp_reg_from_dp
},
10925 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
10926 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
10927 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10928 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10929 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10930 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10932 /* Memory operations. */
10933 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1
, do_vfp_dp_ldst
},
10934 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1
, do_vfp_dp_ldst
},
10935 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
10936 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
10937 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
10938 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
10939 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
10940 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
10941 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
10942 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
10944 /* Monadic operations. */
10945 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10946 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10947 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10949 /* Dyadic operations. */
10950 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10951 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10952 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10953 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10954 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10955 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10956 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10957 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10958 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10961 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10962 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_compare_z
},
10963 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10964 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1
, do_vfp_dp_compare_z
},
10967 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2
, do_vfp_sp2_from_reg2
},
10968 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2
, do_vfp_reg2_from_sp2
},
10969 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2
, do_vfp_dp_from_reg2
},
10970 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2
, do_vfp_reg2_from_dp
},
10972 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
10973 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE
, do_xsc_mia
},
10974 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10975 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10976 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10977 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10978 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10979 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE
, do_xsc_mar
},
10980 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE
, do_xsc_mra
},
10982 /* Intel Wireless MMX technology instructions. */
10983 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
10984 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
10985 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
10986 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
10987 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
10988 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
10989 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
10990 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
10991 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
10992 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10993 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10994 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10995 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10996 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10997 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10998 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
10999 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
11000 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
11001 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmcr
},
11002 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_tmcrr
},
11003 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
11004 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
11005 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
11006 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
11007 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
11008 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
11009 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
11010 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
11011 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
11012 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmrc
},
11013 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_tmrrc
},
11014 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
11015 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
11016 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
11017 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11018 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11019 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11020 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11021 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11022 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11023 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11024 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11025 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11026 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11027 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11028 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11029 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_waligni
},
11030 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11031 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11032 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11033 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11034 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11035 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11036 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11037 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11038 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11039 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11040 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11041 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11042 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11043 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11044 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11045 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11046 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11047 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11048 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11049 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
11050 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
11051 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
11052 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
11053 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11054 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11055 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11056 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11057 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11058 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11059 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11060 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11061 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11062 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11063 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11064 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11065 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11066 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11067 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11068 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11069 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11070 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11071 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wmov
},
11072 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11073 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11074 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11075 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11076 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11077 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11078 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11079 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11080 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11081 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11082 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11083 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11084 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
11085 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11086 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
11087 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11088 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
11089 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11090 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11091 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11092 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11093 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wshufh
},
11094 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11095 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
11096 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11097 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
11098 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11099 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
11100 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11101 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
11102 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11103 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
11104 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11105 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
11106 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11107 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
11108 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11109 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
11110 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11111 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
11112 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
11113 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
11114 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
11115 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
11116 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11117 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11118 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11119 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11120 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11121 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11122 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11123 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11124 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11125 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11126 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11127 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11128 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11129 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11130 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11131 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11132 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11133 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11134 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11135 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11136 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11137 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11138 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11139 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11140 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11141 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11142 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11143 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11144 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wzero
},
11146 /* Cirrus Maverick instructions. */
11147 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_1
},
11148 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_2
},
11149 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_3
},
11150 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_4
},
11151 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_1
},
11152 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_2
},
11153 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_3
},
11154 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_4
},
11155 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK
, do_mav_binops_2a
},
11156 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1a
},
11157 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK
, do_mav_binops_2b
},
11158 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1b
},
11159 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK
, do_mav_binops_2b
},
11160 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1b
},
11161 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK
, do_mav_binops_2c
},
11162 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1c
},
11163 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK
, do_mav_binops_2c
},
11164 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1c
},
11165 {"cfmval32", 0xee200440, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
11166 {"cfmv32al", 0xee100440, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
11167 {"cfmvam32", 0xee200460, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
11168 {"cfmv32am", 0xee100460, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
11169 {"cfmvah32", 0xee200480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
11170 {"cfmv32ah", 0xee100480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
11171 {"cfmva32", 0xee2004a0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
11172 {"cfmv32a", 0xee1004a0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
11173 {"cfmva64", 0xee2004c0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3c
},
11174 {"cfmv64a", 0xee1004c0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3d
},
11175 {"cfmvsc32", 0xee2004e0, 8, ARM_CEXT_MAVERICK
, do_mav_dspsc_1
},
11176 {"cfmv32sc", 0xee1004e0, 8, ARM_CEXT_MAVERICK
, do_mav_dspsc_2
},
11177 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
11178 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
11179 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1f
},
11180 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1g
},
11181 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1h
},
11182 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1i
},
11183 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1j
},
11184 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1k
},
11185 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1l
},
11186 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1m
},
11187 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK
, do_mav_binops_1l
},
11188 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK
, do_mav_binops_1m
},
11189 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK
, do_mav_triple_4a
},
11190 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK
, do_mav_triple_4b
},
11191 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK
, do_mav_shift_1
},
11192 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK
, do_mav_shift_2
},
11193 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5a
},
11194 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5b
},
11195 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5c
},
11196 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5d
},
11197 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
11198 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
11199 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
11200 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
11201 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
11202 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
11203 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
11204 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
11205 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
11206 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
11207 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1n
},
11208 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1o
},
11209 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1n
},
11210 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1o
},
11211 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
11212 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
11213 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
11214 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
11215 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
11216 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
11217 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
11218 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
11219 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK
, do_mav_quad_6a
},
11220 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK
, do_mav_quad_6a
},
11221 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK
, do_mav_quad_6b
},
11222 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK
, do_mav_quad_6b
},
11225 /* Iterate over the base tables to create the instruction patterns. */
11228 build_arm_ops_hsh (void)
11232 static struct obstack insn_obstack
;
11234 obstack_begin (&insn_obstack
, 4000);
11236 for (i
= 0; i
< sizeof (insns
) / sizeof (struct asm_opcode
); i
++)
11238 const struct asm_opcode
*insn
= insns
+ i
;
11240 if (insn
->cond_offset
!= 0)
11242 /* Insn supports conditional execution. Build the varaints
11243 and insert them in the hash table. */
11244 for (j
= 0; j
< sizeof (conds
) / sizeof (struct asm_cond
); j
++)
11246 unsigned len
= strlen (insn
->template);
11247 struct asm_opcode
*new;
11250 new = obstack_alloc (&insn_obstack
, sizeof (struct asm_opcode
));
11251 /* All condition codes are two characters. */
11252 template = obstack_alloc (&insn_obstack
, len
+ 3);
11254 strncpy (template, insn
->template, insn
->cond_offset
);
11255 strcpy (template + insn
->cond_offset
, conds
[j
].template);
11256 if (len
> insn
->cond_offset
)
11257 strcpy (template + insn
->cond_offset
+ 2,
11258 insn
->template + insn
->cond_offset
);
11259 new->template = template;
11260 new->cond_offset
= 0;
11261 new->variant
= insn
->variant
;
11262 new->parms
= insn
->parms
;
11263 new->value
= (insn
->value
& ~COND_MASK
) | conds
[j
].value
;
11265 hash_insert (arm_ops_hsh
, new->template, (PTR
) new);
11268 /* Finally, insert the unconditional insn in the table directly;
11269 no need to build a copy. */
11270 hash_insert (arm_ops_hsh
, insn
->template, (PTR
) insn
);
11275 static const struct thumb_opcode tinsns
[] =
11277 /* Thumb v1 (ARMv4T). */
11278 {"adc", 0x4140, 2, ARM_EXT_V4T
, do_t_arit
},
11279 {"add", 0x0000, 2, ARM_EXT_V4T
, do_t_add
},
11280 {"and", 0x4000, 2, ARM_EXT_V4T
, do_t_arit
},
11281 {"asr", 0x0000, 2, ARM_EXT_V4T
, do_t_asr
},
11282 {"b", T_OPCODE_BRANCH
, 2, ARM_EXT_V4T
, do_t_branch12
},
11283 {"beq", 0xd0fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11284 {"bne", 0xd1fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11285 {"bcs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11286 {"bhs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11287 {"bcc", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11288 {"bul", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11289 {"blo", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11290 {"bmi", 0xd4fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11291 {"bpl", 0xd5fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11292 {"bvs", 0xd6fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11293 {"bvc", 0xd7fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11294 {"bhi", 0xd8fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11295 {"bls", 0xd9fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11296 {"bge", 0xdafe, 2, ARM_EXT_V4T
, do_t_branch9
},
11297 {"blt", 0xdbfe, 2, ARM_EXT_V4T
, do_t_branch9
},
11298 {"bgt", 0xdcfe, 2, ARM_EXT_V4T
, do_t_branch9
},
11299 {"ble", 0xddfe, 2, ARM_EXT_V4T
, do_t_branch9
},
11300 {"bal", 0xdefe, 2, ARM_EXT_V4T
, do_t_branch9
},
11301 {"bic", 0x4380, 2, ARM_EXT_V4T
, do_t_arit
},
11302 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T
, do_t_branch23
},
11303 {"bx", 0x4700, 2, ARM_EXT_V4T
, do_t_bx
},
11304 {"cmn", T_OPCODE_CMN
, 2, ARM_EXT_V4T
, do_t_arit
},
11305 {"cmp", 0x0000, 2, ARM_EXT_V4T
, do_t_compare
},
11306 {"eor", 0x4040, 2, ARM_EXT_V4T
, do_t_arit
},
11307 {"ldmia", 0xc800, 2, ARM_EXT_V4T
, do_t_ldmstm
},
11308 {"ldr", 0x0000, 2, ARM_EXT_V4T
, do_t_ldr
},
11309 {"ldrb", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrb
},
11310 {"ldrh", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrh
},
11311 {"ldrsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
11312 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
11313 {"ldsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
11314 {"ldsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
11315 {"lsl", 0x0000, 2, ARM_EXT_V4T
, do_t_lsl
},
11316 {"lsr", 0x0000, 2, ARM_EXT_V4T
, do_t_lsr
},
11317 {"mov", 0x0000, 2, ARM_EXT_V4T
, do_t_mov
},
11318 {"mul", T_OPCODE_MUL
, 2, ARM_EXT_V4T
, do_t_arit
},
11319 {"mvn", T_OPCODE_MVN
, 2, ARM_EXT_V4T
, do_t_arit
},
11320 {"neg", T_OPCODE_NEG
, 2, ARM_EXT_V4T
, do_t_arit
},
11321 {"orr", 0x4300, 2, ARM_EXT_V4T
, do_t_arit
},
11322 {"pop", 0xbc00, 2, ARM_EXT_V4T
, do_t_push_pop
},
11323 {"push", 0xb400, 2, ARM_EXT_V4T
, do_t_push_pop
},
11324 {"ror", 0x41c0, 2, ARM_EXT_V4T
, do_t_arit
},
11325 {"sbc", 0x4180, 2, ARM_EXT_V4T
, do_t_arit
},
11326 {"stmia", 0xc000, 2, ARM_EXT_V4T
, do_t_ldmstm
},
11327 {"str", 0x0000, 2, ARM_EXT_V4T
, do_t_str
},
11328 {"strb", 0x0000, 2, ARM_EXT_V4T
, do_t_strb
},
11329 {"strh", 0x0000, 2, ARM_EXT_V4T
, do_t_strh
},
11330 {"swi", 0xdf00, 2, ARM_EXT_V4T
, do_t_swi
},
11331 {"sub", 0x0000, 2, ARM_EXT_V4T
, do_t_sub
},
11332 {"tst", T_OPCODE_TST
, 2, ARM_EXT_V4T
, do_t_arit
},
11334 {"adr", 0x0000, 2, ARM_EXT_V4T
, do_t_adr
},
11335 {"nop", 0x46C0, 2, ARM_EXT_V4T
, do_t_nop
}, /* mov r8,r8 */
11336 /* Thumb v2 (ARMv5T). */
11337 {"blx", 0, 0, ARM_EXT_V5T
, do_t_blx
},
11338 {"bkpt", 0xbe00, 2, ARM_EXT_V5T
, do_t_bkpt
},
11341 {"cpsie", 0xb660, 2, ARM_EXT_V6
, do_t_cps
},
11342 {"cpsid", 0xb670, 2, ARM_EXT_V6
, do_t_cps
},
11343 {"cpy", 0x4600, 2, ARM_EXT_V6
, do_t_cpy
},
11344 {"rev", 0xba00, 2, ARM_EXT_V6
, do_t_arit
},
11345 {"rev16", 0xba40, 2, ARM_EXT_V6
, do_t_arit
},
11346 {"revsh", 0xbac0, 2, ARM_EXT_V6
, do_t_arit
},
11347 {"setend", 0xb650, 2, ARM_EXT_V6
, do_t_setend
},
11348 {"sxth", 0xb200, 2, ARM_EXT_V6
, do_t_arit
},
11349 {"sxtb", 0xb240, 2, ARM_EXT_V6
, do_t_arit
},
11350 {"uxth", 0xb280, 2, ARM_EXT_V6
, do_t_arit
},
11351 {"uxtb", 0xb2c0, 2, ARM_EXT_V6
, do_t_arit
},
11354 {"sev", 0xbf40, 2, ARM_EXT_V6K
, do_empty
},
11355 {"wfe", 0xbf20, 2, ARM_EXT_V6K
, do_empty
},
11356 {"wfi", 0xbf30, 2, ARM_EXT_V6K
, do_empty
},
11357 {"yield", 0xbf10, 2, ARM_EXT_V6K
, do_empty
},
11366 if ( (arm_ops_hsh
= hash_new ()) == NULL
11367 || (arm_tops_hsh
= hash_new ()) == NULL
11368 || (arm_cond_hsh
= hash_new ()) == NULL
11369 || (arm_shift_hsh
= hash_new ()) == NULL
11370 || (arm_psr_hsh
= hash_new ()) == NULL
)
11371 as_fatal (_("virtual memory exhausted"));
11373 build_arm_ops_hsh ();
11374 for (i
= 0; i
< sizeof (tinsns
) / sizeof (struct thumb_opcode
); i
++)
11375 hash_insert (arm_tops_hsh
, tinsns
[i
].template, (PTR
) (tinsns
+ i
));
11376 for (i
= 0; i
< sizeof (conds
) / sizeof (struct asm_cond
); i
++)
11377 hash_insert (arm_cond_hsh
, conds
[i
].template, (PTR
) (conds
+ i
));
11378 for (i
= 0; i
< sizeof (shift_names
) / sizeof (struct asm_shift_name
); i
++)
11379 hash_insert (arm_shift_hsh
, shift_names
[i
].name
, (PTR
) (shift_names
+ i
));
11380 for (i
= 0; i
< sizeof (psrs
) / sizeof (struct asm_psr
); i
++)
11381 hash_insert (arm_psr_hsh
, psrs
[i
].template, (PTR
) (psrs
+ i
));
11383 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
11384 build_reg_hsh (all_reg_maps
+ i
);
11386 set_constant_flonums ();
11388 /* Set the cpu variant based on the command-line options. We prefer
11389 -mcpu= over -march= if both are set (as for GCC); and we prefer
11390 -mfpu= over any other way of setting the floating point unit.
11391 Use of legacy options with new options are faulted. */
11392 if (legacy_cpu
!= -1)
11394 if (mcpu_cpu_opt
!= -1 || march_cpu_opt
!= -1)
11395 as_bad (_("use of old and new-style options to set CPU type"));
11397 mcpu_cpu_opt
= legacy_cpu
;
11399 else if (mcpu_cpu_opt
== -1)
11400 mcpu_cpu_opt
= march_cpu_opt
;
11402 if (legacy_fpu
!= -1)
11404 if (mfpu_opt
!= -1)
11405 as_bad (_("use of old and new-style options to set FPU type"));
11407 mfpu_opt
= legacy_fpu
;
11409 else if (mfpu_opt
== -1)
11411 #if !(defined (TE_LINUX) || defined (TE_NetBSD) || defined (TE_VXWORKS))
11412 /* Some environments specify a default FPU. If they don't, infer it
11413 from the processor. */
11414 if (mcpu_fpu_opt
!= -1)
11415 mfpu_opt
= mcpu_fpu_opt
;
11417 mfpu_opt
= march_fpu_opt
;
11419 mfpu_opt
= FPU_DEFAULT
;
11423 if (mfpu_opt
== -1)
11425 if (mcpu_cpu_opt
== -1)
11426 mfpu_opt
= FPU_DEFAULT
;
11427 else if (mcpu_cpu_opt
& ARM_EXT_V5
)
11428 mfpu_opt
= FPU_ARCH_VFP_V2
;
11430 mfpu_opt
= FPU_ARCH_FPA
;
11433 if (mcpu_cpu_opt
== -1)
11434 mcpu_cpu_opt
= CPU_DEFAULT
;
11436 cpu_variant
= mcpu_cpu_opt
| mfpu_opt
;
11438 #if defined OBJ_COFF || defined OBJ_ELF
11440 unsigned int flags
= 0;
11442 #if defined OBJ_ELF
11443 flags
= meabi_flags
;
11445 switch (meabi_flags
)
11447 case EF_ARM_EABI_UNKNOWN
:
11449 /* Set the flags in the private structure. */
11450 if (uses_apcs_26
) flags
|= F_APCS26
;
11451 if (support_interwork
) flags
|= F_INTERWORK
;
11452 if (uses_apcs_float
) flags
|= F_APCS_FLOAT
;
11453 if (pic_code
) flags
|= F_PIC
;
11454 if ((cpu_variant
& FPU_ANY
) == FPU_NONE
11455 || (cpu_variant
& FPU_ANY
) == FPU_ARCH_VFP
) /* VFP layout only. */
11456 flags
|= F_SOFT_FLOAT
;
11458 switch (mfloat_abi_opt
)
11460 case ARM_FLOAT_ABI_SOFT
:
11461 case ARM_FLOAT_ABI_SOFTFP
:
11462 flags
|= F_SOFT_FLOAT
;
11465 case ARM_FLOAT_ABI_HARD
:
11466 if (flags
& F_SOFT_FLOAT
)
11467 as_bad (_("hard-float conflicts with specified fpu"));
11471 /* Using VFP conventions (even if soft-float). */
11472 if (cpu_variant
& FPU_VFP_EXT_NONE
)
11473 flags
|= F_VFP_FLOAT
;
11475 #if defined OBJ_ELF
11476 if (cpu_variant
& FPU_ARCH_MAVERICK
)
11477 flags
|= EF_ARM_MAVERICK_FLOAT
;
11480 case EF_ARM_EABI_VER4
:
11481 /* No additional flags to set. */
11488 bfd_set_private_flags (stdoutput
, flags
);
11490 /* We have run out flags in the COFF header to encode the
11491 status of ATPCS support, so instead we create a dummy,
11492 empty, debug section called .arm.atpcs. */
11497 sec
= bfd_make_section (stdoutput
, ".arm.atpcs");
11501 bfd_set_section_flags
11502 (stdoutput
, sec
, SEC_READONLY
| SEC_DEBUGGING
/* | SEC_HAS_CONTENTS */);
11503 bfd_set_section_size (stdoutput
, sec
, 0);
11504 bfd_set_section_contents (stdoutput
, sec
, NULL
, 0, 0);
11510 /* Record the CPU type as well. */
11511 switch (cpu_variant
& ARM_CPU_MASK
)
11514 mach
= bfd_mach_arm_2
;
11517 case ARM_3
: /* Also ARM_250. */
11518 mach
= bfd_mach_arm_2a
;
11521 case ARM_6
: /* Also ARM_7. */
11522 mach
= bfd_mach_arm_3
;
11526 mach
= bfd_mach_arm_unknown
;
11530 /* Catch special cases. */
11531 if (cpu_variant
& ARM_CEXT_IWMMXT
)
11532 mach
= bfd_mach_arm_iWMMXt
;
11533 else if (cpu_variant
& ARM_CEXT_XSCALE
)
11534 mach
= bfd_mach_arm_XScale
;
11535 else if (cpu_variant
& ARM_CEXT_MAVERICK
)
11536 mach
= bfd_mach_arm_ep9312
;
11537 else if (cpu_variant
& ARM_EXT_V5E
)
11538 mach
= bfd_mach_arm_5TE
;
11539 else if (cpu_variant
& ARM_EXT_V5
)
11541 if (cpu_variant
& ARM_EXT_V4T
)
11542 mach
= bfd_mach_arm_5T
;
11544 mach
= bfd_mach_arm_5
;
11546 else if (cpu_variant
& ARM_EXT_V4
)
11548 if (cpu_variant
& ARM_EXT_V4T
)
11549 mach
= bfd_mach_arm_4T
;
11551 mach
= bfd_mach_arm_4
;
11553 else if (cpu_variant
& ARM_EXT_V3M
)
11554 mach
= bfd_mach_arm_3M
;
11556 bfd_set_arch_mach (stdoutput
, TARGET_ARCH
, mach
);
11559 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11560 for use in the a.out file, and stores them in the array pointed to by buf.
11561 This knows about the endian-ness of the target machine and does
11562 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11563 2 (short) and 4 (long) Floating numbers are put out as a series of
11564 LITTLENUMS (shorts, here at least). */
11567 md_number_to_chars (char * buf
, valueT val
, int n
)
11569 if (target_big_endian
)
11570 number_to_chars_bigendian (buf
, val
, n
);
11572 number_to_chars_littleendian (buf
, val
, n
);
11576 md_chars_to_number (char * buf
, int n
)
11579 unsigned char * where
= (unsigned char *) buf
;
11581 if (target_big_endian
)
11586 result
|= (*where
++ & 255);
11594 result
|= (where
[n
] & 255);
11601 /* Turn a string in input_line_pointer into a floating point constant
11602 of type TYPE, and store the appropriate bytes in *LITP. The number
11603 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11604 returned, or NULL on OK.
11606 Note that fp constants aren't represent in the normal way on the ARM.
11607 In big endian mode, things are as expected. However, in little endian
11608 mode fp constants are big-endian word-wise, and little-endian byte-wise
11609 within the words. For example, (double) 1.1 in big endian mode is
11610 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11611 the byte sequence 99 99 f1 3f 9a 99 99 99.
11613 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11616 md_atof (int type
, char * litP
, int * sizeP
)
11619 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
11651 return _("bad call to MD_ATOF()");
11654 t
= atof_ieee (input_line_pointer
, type
, words
);
11656 input_line_pointer
= t
;
11659 if (target_big_endian
)
11661 for (i
= 0; i
< prec
; i
++)
11663 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
11669 if (cpu_variant
& FPU_ARCH_VFP
)
11670 for (i
= prec
- 1; i
>= 0; i
--)
11672 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
11676 /* For a 4 byte float the order of elements in `words' is 1 0.
11677 For an 8 byte float the order is 1 0 3 2. */
11678 for (i
= 0; i
< prec
; i
+= 2)
11680 md_number_to_chars (litP
, (valueT
) words
[i
+ 1], 2);
11681 md_number_to_chars (litP
+ 2, (valueT
) words
[i
], 2);
11689 /* The knowledge of the PC's pipeline offset is built into the insns
11693 md_pcrel_from (fixS
* fixP
)
11696 && S_GET_SEGMENT (fixP
->fx_addsy
) == undefined_section
11697 && fixP
->fx_subsy
== NULL
)
11700 if (fixP
->fx_pcrel
&& (fixP
->fx_r_type
== BFD_RELOC_ARM_THUMB_ADD
))
11702 /* PC relative addressing on the Thumb is slightly odd
11703 as the bottom two bits of the PC are forced to zero
11704 for the calculation. */
11705 return (fixP
->fx_where
+ fixP
->fx_frag
->fr_address
) & ~3;
11709 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
11710 so we un-adjust here to compensate for the accommodation. */
11711 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
+ 8;
11713 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
11717 /* Round up a section size to the appropriate boundary. */
11720 md_section_align (segT segment ATTRIBUTE_UNUSED
,
11726 /* Round all sects to multiple of 4. */
11727 return (size
+ 3) & ~3;
11731 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
11732 Otherwise we have no need to default values of symbols. */
11735 md_undefined_symbol (char * name ATTRIBUTE_UNUSED
)
11738 if (name
[0] == '_' && name
[1] == 'G'
11739 && streq (name
, GLOBAL_OFFSET_TABLE_NAME
))
11743 if (symbol_find (name
))
11744 as_bad ("GOT already in the symbol table");
11746 GOT_symbol
= symbol_new (name
, undefined_section
,
11747 (valueT
) 0, & zero_address_frag
);
11758 md_apply_fix3 (fixS
* fixP
,
11762 offsetT value
= * valP
;
11764 unsigned int newimm
;
11765 unsigned long temp
;
11767 char * buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
11768 arm_fix_data
* arm_data
= (arm_fix_data
*) fixP
->tc_fix_data
;
11770 assert (fixP
->fx_r_type
<= BFD_RELOC_UNUSED
);
11772 /* Note whether this will delete the relocation. */
11773 if (fixP
->fx_addsy
== 0 && !fixP
->fx_pcrel
)
11776 /* If this symbol is in a different section then we need to leave it for
11777 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
11778 so we have to undo it's effects here. */
11779 if (fixP
->fx_pcrel
)
11781 if (fixP
->fx_addsy
!= NULL
11782 && S_IS_DEFINED (fixP
->fx_addsy
)
11783 && S_GET_SEGMENT (fixP
->fx_addsy
) != seg
)
11784 value
+= md_pcrel_from (fixP
);
11787 /* Remember value for emit_reloc. */
11788 fixP
->fx_addnumber
= value
;
11790 switch (fixP
->fx_r_type
)
11792 case BFD_RELOC_NONE
:
11793 /* This will need to go in the object file. */
11797 case BFD_RELOC_ARM_IMMEDIATE
:
11798 /* We claim that this fixup has been processed here,
11799 even if in fact we generate an error because we do
11800 not have a reloc for it, so tc_gen_reloc will reject it. */
11804 && ! S_IS_DEFINED (fixP
->fx_addsy
))
11806 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11807 _("undefined symbol %s used as an immediate value"),
11808 S_GET_NAME (fixP
->fx_addsy
));
11812 newimm
= validate_immediate (value
);
11813 temp
= md_chars_to_number (buf
, INSN_SIZE
);
11815 /* If the instruction will fail, see if we can fix things up by
11816 changing the opcode. */
11817 if (newimm
== (unsigned int) FAIL
11818 && (newimm
= negate_data_op (&temp
, value
)) == (unsigned int) FAIL
)
11820 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11821 _("invalid constant (%lx) after fixup"),
11822 (unsigned long) value
);
11826 newimm
|= (temp
& 0xfffff000);
11827 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
11830 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
11832 unsigned int highpart
= 0;
11833 unsigned int newinsn
= 0xe1a00000; /* nop. */
11835 newimm
= validate_immediate (value
);
11836 temp
= md_chars_to_number (buf
, INSN_SIZE
);
11838 /* If the instruction will fail, see if we can fix things up by
11839 changing the opcode. */
11840 if (newimm
== (unsigned int) FAIL
11841 && (newimm
= negate_data_op (& temp
, value
)) == (unsigned int) FAIL
)
11843 /* No ? OK - try using two ADD instructions to generate
11845 newimm
= validate_immediate_twopart (value
, & highpart
);
11847 /* Yes - then make sure that the second instruction is
11849 if (newimm
!= (unsigned int) FAIL
)
11851 /* Still No ? Try using a negated value. */
11852 else if ((newimm
= validate_immediate_twopart (- value
, & highpart
)) != (unsigned int) FAIL
)
11853 temp
= newinsn
= (temp
& OPCODE_MASK
) | OPCODE_SUB
<< DATA_OP_SHIFT
;
11854 /* Otherwise - give up. */
11857 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11858 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
11863 /* Replace the first operand in the 2nd instruction (which
11864 is the PC) with the destination register. We have
11865 already added in the PC in the first instruction and we
11866 do not want to do it again. */
11867 newinsn
&= ~ 0xf0000;
11868 newinsn
|= ((newinsn
& 0x0f000) << 4);
11871 newimm
|= (temp
& 0xfffff000);
11872 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
11874 highpart
|= (newinsn
& 0xfffff000);
11875 md_number_to_chars (buf
+ INSN_SIZE
, (valueT
) highpart
, INSN_SIZE
);
11879 case BFD_RELOC_ARM_OFFSET_IMM
:
11885 if (validate_offset_imm (value
, 0) == FAIL
)
11887 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11888 _("bad immediate value for offset (%ld)"),
11893 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11894 newval
&= 0xff7ff000;
11895 newval
|= value
| (sign
? INDEX_UP
: 0);
11896 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11899 case BFD_RELOC_ARM_OFFSET_IMM8
:
11900 case BFD_RELOC_ARM_HWLITERAL
:
11906 if (validate_offset_imm (value
, 1) == FAIL
)
11908 if (fixP
->fx_r_type
== BFD_RELOC_ARM_HWLITERAL
)
11909 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11910 _("invalid literal constant: pool needs to be closer"));
11912 as_bad (_("bad immediate value for half-word offset (%ld)"),
11917 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11918 newval
&= 0xff7ff0f0;
11919 newval
|= ((value
>> 4) << 8) | (value
& 0xf) | (sign
? INDEX_UP
: 0);
11920 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11923 case BFD_RELOC_ARM_LITERAL
:
11929 if (validate_offset_imm (value
, 0) == FAIL
)
11931 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11932 _("invalid literal constant: pool needs to be closer"));
11936 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11937 newval
&= 0xff7ff000;
11938 newval
|= value
| (sign
? INDEX_UP
: 0);
11939 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11942 case BFD_RELOC_ARM_SHIFT_IMM
:
11943 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11944 if (((unsigned long) value
) > 32
11946 && (((newval
& 0x60) == 0) || (newval
& 0x60) == 0x60)))
11948 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11949 _("shift expression is too large"));
11954 /* Shifts of zero must be done as lsl. */
11956 else if (value
== 32)
11958 newval
&= 0xfffff07f;
11959 newval
|= (value
& 0x1f) << 7;
11960 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11963 case BFD_RELOC_ARM_SMI
:
11964 if (((unsigned long) value
) > 0xffff)
11965 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11966 _("invalid smi expression"));
11967 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xfff000f0;
11968 newval
|= (value
& 0xf) | ((value
& 0xfff0) << 4);
11969 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11972 case BFD_RELOC_ARM_SWI
:
11973 if (arm_data
->thumb_mode
)
11975 if (((unsigned long) value
) > 0xff)
11976 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11977 _("invalid swi expression"));
11978 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xff00;
11980 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11984 if (((unsigned long) value
) > 0x00ffffff)
11985 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11986 _("invalid swi expression"));
11987 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff000000;
11989 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11993 case BFD_RELOC_ARM_MULTI
:
11994 if (((unsigned long) value
) > 0xffff)
11995 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11996 _("invalid expression in load/store multiple"));
11997 newval
= value
| md_chars_to_number (buf
, INSN_SIZE
);
11998 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12001 case BFD_RELOC_ARM_PCREL_BRANCH
:
12002 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12004 /* Sign-extend a 24-bit number. */
12005 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
12008 value
= fixP
->fx_offset
;
12011 /* We are going to store value (shifted right by two) in the
12012 instruction, in a 24 bit, signed field. Thus we need to check
12013 that none of the top 8 bits of the shifted value (top 7 bits of
12014 the unshifted, unsigned value) are set, or that they are all set. */
12015 if ((value
& ~ ((offsetT
) 0x1ffffff)) != 0
12016 && ((value
& ~ ((offsetT
) 0x1ffffff)) != ~ ((offsetT
) 0x1ffffff)))
12019 /* Normally we would be stuck at this point, since we cannot store
12020 the absolute address that is the destination of the branch in the
12021 24 bits of the branch instruction. If however, we happen to know
12022 that the destination of the branch is in the same section as the
12023 branch instruction itself, then we can compute the relocation for
12024 ourselves and not have to bother the linker with it.
12026 FIXME: The test for OBJ_ELF is only here because I have not
12027 worked out how to do this for OBJ_COFF. */
12028 if (fixP
->fx_addsy
!= NULL
12029 && S_IS_DEFINED (fixP
->fx_addsy
)
12030 && S_GET_SEGMENT (fixP
->fx_addsy
) == seg
)
12032 /* Get pc relative value to go into the branch. */
12035 /* Permit a backward branch provided that enough bits
12036 are set. Allow a forwards branch, provided that
12037 enough bits are clear. */
12038 if ( (value
& ~ ((offsetT
) 0x1ffffff)) == ~ ((offsetT
) 0x1ffffff)
12039 || (value
& ~ ((offsetT
) 0x1ffffff)) == 0)
12043 if (! fixP
->fx_done
)
12045 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12046 _("GAS can't handle same-section branch dest >= 0x04000000"));
12050 value
+= SEXT24 (newval
);
12052 if ( (value
& ~ ((offsetT
) 0xffffff)) != 0
12053 && ((value
& ~ ((offsetT
) 0xffffff)) != ~ ((offsetT
) 0xffffff)))
12054 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12055 _("out of range branch"));
12057 if (seg
->use_rela_p
&& !fixP
->fx_done
)
12059 /* Must unshift the value before storing it in the addend. */
12062 fixP
->fx_offset
= value
;
12064 fixP
->fx_addnumber
= value
;
12065 newval
= newval
& 0xff000000;
12068 newval
= (value
& 0x00ffffff) | (newval
& 0xff000000);
12069 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12072 case BFD_RELOC_ARM_PCREL_BLX
:
12075 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12078 value
= fixP
->fx_offset
;
12080 hbit
= (value
>> 1) & 1;
12081 value
= (value
>> 2) & 0x00ffffff;
12082 value
= (value
+ (newval
& 0x00ffffff)) & 0x00ffffff;
12084 if (seg
->use_rela_p
&& !fixP
->fx_done
)
12086 /* Must sign-extend and unshift the value before storing
12087 it in the addend. */
12088 value
= SEXT24 (value
);
12089 value
= (value
<< 2) | hbit
;
12091 fixP
->fx_offset
= value
;
12093 fixP
->fx_addnumber
= value
;
12094 newval
= newval
& 0xfe000000;
12097 newval
= value
| (newval
& 0xfe000000) | (hbit
<< 24);
12098 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12102 case BFD_RELOC_THUMB_PCREL_BRANCH9
: /* Conditional branch. */
12103 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12105 addressT diff
= (newval
& 0xff) << 1;
12110 if ((value
& ~0xff) && ((value
& ~0xff) != ~0xff))
12111 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12112 _("branch out of range"));
12113 if (seg
->use_rela_p
&& !fixP
->fx_done
)
12116 fixP
->fx_offset
= value
;
12118 fixP
->fx_addnumber
= value
;
12119 newval
= newval
& 0xff00;
12122 newval
= (newval
& 0xff00) | ((value
& 0x1ff) >> 1);
12124 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12127 case BFD_RELOC_THUMB_PCREL_BRANCH12
: /* Unconditional branch. */
12128 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12130 addressT diff
= (newval
& 0x7ff) << 1;
12135 if ((value
& ~0x7ff) && ((value
& ~0x7ff) != ~0x7ff))
12136 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12137 _("branch out of range"));
12138 if (seg
->use_rela_p
&& !fixP
->fx_done
)
12141 fixP
->fx_offset
= value
;
12143 fixP
->fx_addnumber
= value
;
12144 newval
= newval
& 0xf800;
12147 newval
= (newval
& 0xf800) | ((value
& 0xfff) >> 1);
12149 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12152 case BFD_RELOC_THUMB_PCREL_BLX
:
12153 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
12158 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12159 newval2
= md_chars_to_number (buf
+ THUMB_SIZE
, THUMB_SIZE
);
12160 diff
= ((newval
& 0x7ff) << 12) | ((newval2
& 0x7ff) << 1);
12161 if (diff
& 0x400000)
12164 value
= fixP
->fx_offset
;
12168 if ((value
& ~0x3fffff) && ((value
& ~0x3fffff) != ~0x3fffff))
12169 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12170 _("branch with link out of range"));
12172 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
)
12173 /* For a BLX instruction, make sure that the relocation is rounded up
12174 to a word boundary. This follows the semantics of the instruction
12175 which specifies that bit 1 of the target address will come from bit
12176 1 of the base address. */
12177 value
= (value
+ 1) & ~ 1;
12179 if (seg
->use_rela_p
&& !fixP
->fx_done
)
12182 fixP
->fx_offset
= value
;
12184 fixP
->fx_addnumber
= value
;
12185 newval
= newval
& 0xf800;
12186 newval2
= newval2
& 0xf800;
12190 newval
= (newval
& 0xf800) | ((value
& 0x7fffff) >> 12);
12191 newval2
= (newval2
& 0xf800) | ((value
& 0xfff) >> 1);
12193 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12194 md_number_to_chars (buf
+ THUMB_SIZE
, newval2
, THUMB_SIZE
);
12199 if (seg
->use_rela_p
&& !fixP
->fx_done
)
12201 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
12202 md_number_to_chars (buf
, value
, 1);
12206 value
= fixP
->fx_offset
;
12207 md_number_to_chars (buf
, value
, 1);
12213 if (seg
->use_rela_p
&& !fixP
->fx_done
)
12215 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
12216 md_number_to_chars (buf
, value
, 2);
12220 value
= fixP
->fx_offset
;
12221 md_number_to_chars (buf
, value
, 2);
12227 case BFD_RELOC_ARM_GOT32
:
12228 case BFD_RELOC_ARM_GOTOFF
:
12229 case BFD_RELOC_ARM_TARGET2
:
12230 if (seg
->use_rela_p
&& !fixP
->fx_done
)
12232 md_number_to_chars (buf
, 0, 4);
12236 case BFD_RELOC_RVA
:
12238 case BFD_RELOC_ARM_TARGET1
:
12239 case BFD_RELOC_ARM_ROSEGREL32
:
12240 case BFD_RELOC_ARM_SBREL32
:
12241 case BFD_RELOC_32_PCREL
:
12242 if (seg
->use_rela_p
&& !fixP
->fx_done
)
12244 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
12245 md_number_to_chars (buf
, value
, 4);
12249 value
= fixP
->fx_offset
;
12250 md_number_to_chars (buf
, value
, 4);
12256 case BFD_RELOC_ARM_PREL31
:
12257 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
12259 newval
= md_chars_to_number (buf
, 4) & 0x80000000;
12260 if ((value
^ (value
>> 1)) & 0x40000000)
12262 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12263 _("rel31 relocation overflow"));
12265 newval
|= value
& 0x7fffffff;
12266 md_number_to_chars (buf
, newval
, 4);
12270 case BFD_RELOC_ARM_PLT32
:
12271 /* It appears the instruction is fully prepared at this point. */
12275 case BFD_RELOC_ARM_CP_OFF_IMM
:
12277 if (value
< -1023 || value
> 1023 || (value
& 3))
12278 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12279 _("illegal value for co-processor offset"));
12282 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
12283 newval
|= (value
>> 2) | (sign
? INDEX_UP
: 0);
12284 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12287 case BFD_RELOC_ARM_CP_OFF_IMM_S2
:
12289 if (value
< -255 || value
> 255)
12290 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12291 _("Illegal value for co-processor offset"));
12294 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
12295 newval
|= value
| (sign
? INDEX_UP
: 0);
12296 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12299 case BFD_RELOC_ARM_THUMB_OFFSET
:
12300 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12301 /* Exactly what ranges, and where the offset is inserted depends
12302 on the type of instruction, we can establish this from the
12304 switch (newval
>> 12)
12306 case 4: /* PC load. */
12307 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
12308 forced to zero for these loads, so we will need to round
12309 up the offset if the instruction address is not word
12310 aligned (since the final address produced must be, and
12311 we can only describe word-aligned immediate offsets). */
12313 if ((fixP
->fx_frag
->fr_address
+ fixP
->fx_where
+ value
) & 3)
12314 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12315 _("invalid offset, target not word aligned (0x%08X)"),
12316 (unsigned int) (fixP
->fx_frag
->fr_address
12317 + fixP
->fx_where
+ value
));
12319 if ((value
+ 2) & ~0x3fe)
12320 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12321 _("invalid offset, value too big (0x%08lX)"),
12324 /* Round up, since pc will be rounded down. */
12325 newval
|= (value
+ 2) >> 2;
12328 case 9: /* SP load/store. */
12329 if (value
& ~0x3fc)
12330 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12331 _("invalid offset, value too big (0x%08lX)"),
12333 newval
|= value
>> 2;
12336 case 6: /* Word load/store. */
12338 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12339 _("invalid offset, value too big (0x%08lX)"),
12341 newval
|= value
<< 4; /* 6 - 2. */
12344 case 7: /* Byte load/store. */
12346 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12347 _("invalid offset, value too big (0x%08lX)"),
12349 newval
|= value
<< 6;
12352 case 8: /* Halfword load/store. */
12354 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12355 _("invalid offset, value too big (0x%08lX)"),
12357 newval
|= value
<< 5; /* 6 - 1. */
12361 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12362 "Unable to process relocation for thumb opcode: %lx",
12363 (unsigned long) newval
);
12366 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12369 case BFD_RELOC_ARM_THUMB_ADD
:
12370 /* This is a complicated relocation, since we use it for all of
12371 the following immediate relocations:
12375 9bit ADD/SUB SP word-aligned
12376 10bit ADD PC/SP word-aligned
12378 The type of instruction being processed is encoded in the
12385 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12387 int rd
= (newval
>> 4) & 0xf;
12388 int rs
= newval
& 0xf;
12389 int subtract
= newval
& 0x8000;
12393 if (value
& ~0x1fc)
12394 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12395 _("invalid immediate for stack address calculation"));
12396 newval
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
12397 newval
|= value
>> 2;
12399 else if (rs
== REG_PC
|| rs
== REG_SP
)
12403 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12404 _("invalid immediate for address calculation (value = 0x%08lX)"),
12405 (unsigned long) value
);
12406 newval
= (rs
== REG_PC
? T_OPCODE_ADD_PC
: T_OPCODE_ADD_SP
);
12408 newval
|= value
>> 2;
12413 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12414 _("invalid 8bit immediate"));
12415 newval
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
12416 newval
|= (rd
<< 8) | value
;
12421 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12422 _("invalid 3bit immediate"));
12423 newval
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
12424 newval
|= rd
| (rs
<< 3) | (value
<< 6);
12427 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12430 case BFD_RELOC_ARM_THUMB_IMM
:
12431 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12432 switch (newval
>> 11)
12434 case 0x04: /* 8bit immediate MOV. */
12435 case 0x05: /* 8bit immediate CMP. */
12436 if (value
< 0 || value
> 255)
12437 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12438 _("invalid immediate: %ld is too large"),
12446 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12449 case BFD_RELOC_ARM_THUMB_SHIFT
:
12450 /* 5bit shift value (0..31). */
12451 if (value
< 0 || value
> 31)
12452 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12453 _("illegal Thumb shift value: %ld"), (long) value
);
12454 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xf03f;
12455 newval
|= value
<< 6;
12456 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12459 case BFD_RELOC_VTABLE_INHERIT
:
12460 case BFD_RELOC_VTABLE_ENTRY
:
12464 case BFD_RELOC_UNUSED
:
12466 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12467 _("bad relocation fixup type (%d)"), fixP
->fx_r_type
);
12471 /* Translate internal representation of relocation info to BFD target
12475 tc_gen_reloc (asection
* section ATTRIBUTE_UNUSED
,
12479 bfd_reloc_code_real_type code
;
12481 reloc
= xmalloc (sizeof (arelent
));
12483 reloc
->sym_ptr_ptr
= xmalloc (sizeof (asymbol
*));
12484 *reloc
->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
12485 reloc
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
12487 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12489 if (fixp
->fx_pcrel
== 0)
12490 reloc
->addend
= fixp
->fx_offset
;
12492 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
12493 #else /* OBJ_ELF */
12494 reloc
->addend
= fixp
->fx_offset
;
12497 switch (fixp
->fx_r_type
)
12500 if (fixp
->fx_pcrel
)
12502 code
= BFD_RELOC_8_PCREL
;
12507 if (fixp
->fx_pcrel
)
12509 code
= BFD_RELOC_16_PCREL
;
12514 if (fixp
->fx_pcrel
)
12516 code
= BFD_RELOC_32_PCREL
;
12520 case BFD_RELOC_NONE
:
12521 case BFD_RELOC_ARM_PCREL_BRANCH
:
12522 case BFD_RELOC_ARM_PCREL_BLX
:
12523 case BFD_RELOC_RVA
:
12524 case BFD_RELOC_THUMB_PCREL_BRANCH9
:
12525 case BFD_RELOC_THUMB_PCREL_BRANCH12
:
12526 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
12527 case BFD_RELOC_THUMB_PCREL_BLX
:
12528 case BFD_RELOC_VTABLE_ENTRY
:
12529 case BFD_RELOC_VTABLE_INHERIT
:
12530 code
= fixp
->fx_r_type
;
12533 case BFD_RELOC_ARM_LITERAL
:
12534 case BFD_RELOC_ARM_HWLITERAL
:
12535 /* If this is called then the a literal has
12536 been referenced across a section boundary. */
12537 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12538 _("literal referenced across section boundary"));
12542 case BFD_RELOC_ARM_GOT32
:
12543 case BFD_RELOC_ARM_GOTOFF
:
12544 case BFD_RELOC_ARM_PLT32
:
12545 case BFD_RELOC_ARM_TARGET1
:
12546 case BFD_RELOC_ARM_ROSEGREL32
:
12547 case BFD_RELOC_ARM_SBREL32
:
12548 case BFD_RELOC_ARM_PREL31
:
12549 case BFD_RELOC_ARM_TARGET2
:
12550 code
= fixp
->fx_r_type
;
12554 case BFD_RELOC_ARM_IMMEDIATE
:
12555 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12556 _("internal relocation (type: IMMEDIATE) not fixed up"));
12559 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
12560 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12561 _("ADRL used for a symbol not defined in the same file"));
12564 case BFD_RELOC_ARM_OFFSET_IMM
:
12565 if (fixp
->fx_addsy
!= NULL
12566 && !S_IS_DEFINED (fixp
->fx_addsy
)
12567 && S_IS_LOCAL (fixp
->fx_addsy
))
12569 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12570 _("undefined local label `%s'"),
12571 S_GET_NAME (fixp
->fx_addsy
));
12575 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12576 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
12583 switch (fixp
->fx_r_type
)
12585 case BFD_RELOC_NONE
: type
= "NONE"; break;
12586 case BFD_RELOC_ARM_OFFSET_IMM8
: type
= "OFFSET_IMM8"; break;
12587 case BFD_RELOC_ARM_SHIFT_IMM
: type
= "SHIFT_IMM"; break;
12588 case BFD_RELOC_ARM_SMI
: type
= "SMI"; break;
12589 case BFD_RELOC_ARM_SWI
: type
= "SWI"; break;
12590 case BFD_RELOC_ARM_MULTI
: type
= "MULTI"; break;
12591 case BFD_RELOC_ARM_CP_OFF_IMM
: type
= "CP_OFF_IMM"; break;
12592 case BFD_RELOC_ARM_THUMB_ADD
: type
= "THUMB_ADD"; break;
12593 case BFD_RELOC_ARM_THUMB_SHIFT
: type
= "THUMB_SHIFT"; break;
12594 case BFD_RELOC_ARM_THUMB_IMM
: type
= "THUMB_IMM"; break;
12595 case BFD_RELOC_ARM_THUMB_OFFSET
: type
= "THUMB_OFFSET"; break;
12596 default: type
= _("<unknown>"); break;
12598 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12599 _("cannot represent %s relocation in this object file format"),
12606 if ((code
== BFD_RELOC_32_PCREL
|| code
== BFD_RELOC_32
)
12608 && fixp
->fx_addsy
== GOT_symbol
)
12610 code
= BFD_RELOC_ARM_GOTPC
;
12611 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
12615 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, code
);
12617 if (reloc
->howto
== NULL
)
12619 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12620 _("cannot represent %s relocation in this object file format"),
12621 bfd_get_reloc_code_name (code
));
12625 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12626 vtable entry to be used in the relocation's section offset. */
12627 if (fixp
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
12628 reloc
->address
= fixp
->fx_offset
;
12634 md_estimate_size_before_relax (fragS
* fragP ATTRIBUTE_UNUSED
,
12635 segT segtype ATTRIBUTE_UNUSED
)
12637 as_fatal (_("md_estimate_size_before_relax\n"));
12641 /* We need to be able to fix up arbitrary expressions in some statements.
12642 This is so that we can handle symbols that are an arbitrary distance from
12643 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
12644 which returns part of an address in a form which will be valid for
12645 a data instruction. We do this by pushing the expression into a symbol
12646 in the expr_section, and creating a fix for that. */
12649 fix_new_arm (fragS
* frag
,
12657 arm_fix_data
* arm_data
;
12665 new_fix
= fix_new_exp (frag
, where
, size
, exp
, pc_rel
, reloc
);
12669 new_fix
= fix_new (frag
, where
, size
, make_expr_symbol (exp
), 0,
12674 /* Mark whether the fix is to a THUMB instruction, or an ARM
12676 arm_data
= obstack_alloc (& notes
, sizeof (arm_fix_data
));
12677 new_fix
->tc_fix_data
= (PTR
) arm_data
;
12678 arm_data
->thumb_mode
= thumb_mode
;
12682 output_inst (const char * str
)
12688 as_bad ("%s -- `%s'", inst
.error
, str
);
12692 to
= frag_more (inst
.size
);
12694 if (thumb_mode
&& (inst
.size
> THUMB_SIZE
))
12696 assert (inst
.size
== (2 * THUMB_SIZE
));
12697 md_number_to_chars (to
, inst
.instruction
>> 16, THUMB_SIZE
);
12698 md_number_to_chars (to
+ THUMB_SIZE
, inst
.instruction
, THUMB_SIZE
);
12700 else if (inst
.size
> INSN_SIZE
)
12702 assert (inst
.size
== (2 * INSN_SIZE
));
12703 md_number_to_chars (to
, inst
.instruction
, INSN_SIZE
);
12704 md_number_to_chars (to
+ INSN_SIZE
, inst
.instruction
, INSN_SIZE
);
12707 md_number_to_chars (to
, inst
.instruction
, inst
.size
);
12709 if (inst
.reloc
.type
!= BFD_RELOC_UNUSED
)
12710 fix_new_arm (frag_now
, to
- frag_now
->fr_literal
,
12711 inst
.size
, & inst
.reloc
.exp
, inst
.reloc
.pc_rel
,
12715 dwarf2_emit_insn (inst
.size
);
12720 md_assemble (char * str
)
12726 /* Align the previous label if needed. */
12727 if (last_label_seen
!= NULL
)
12729 symbol_set_frag (last_label_seen
, frag_now
);
12730 S_SET_VALUE (last_label_seen
, (valueT
) frag_now_fix ());
12731 S_SET_SEGMENT (last_label_seen
, now_seg
);
12734 memset (&inst
, '\0', sizeof (inst
));
12735 inst
.reloc
.type
= BFD_RELOC_UNUSED
;
12737 skip_whitespace (str
);
12739 /* Scan up to the end of the op-code, which must end in white space or
12741 for (start
= p
= str
; *p
!= '\0'; p
++)
12747 as_bad (_("no operator -- statement `%s'\n"), str
);
12753 const struct thumb_opcode
* opcode
;
12757 opcode
= (const struct thumb_opcode
*) hash_find (arm_tops_hsh
, str
);
12762 /* Check that this instruction is supported for this CPU. */
12763 if (thumb_mode
== 1 && (opcode
->variant
& cpu_variant
) == 0)
12765 as_bad (_("selected processor does not support `%s'"), str
);
12769 mapping_state (MAP_THUMB
);
12770 inst
.instruction
= opcode
->value
;
12771 inst
.size
= opcode
->size
;
12779 const struct asm_opcode
* opcode
;
12783 opcode
= (const struct asm_opcode
*) hash_find (arm_ops_hsh
, str
);
12788 /* Check that this instruction is supported for this CPU. */
12789 if ((opcode
->variant
& cpu_variant
) == 0)
12791 as_bad (_("selected processor does not support `%s'"), str
);
12795 mapping_state (MAP_ARM
);
12796 inst
.instruction
= opcode
->value
;
12797 inst
.size
= INSN_SIZE
;
12804 /* It wasn't an instruction, but it might be a register alias of the form
12806 if (create_register_alias (str
, p
))
12809 as_bad (_("bad instruction `%s'"), start
);
12813 Invocation line includes a switch not recognized by the base assembler.
12814 See if it's a processor-specific option.
12816 This routine is somewhat complicated by the need for backwards
12817 compatibility (since older releases of gcc can't be changed).
12818 The new options try to make the interface as compatible as
12821 New options (supported) are:
12823 -mcpu=<cpu name> Assemble for selected processor
12824 -march=<architecture name> Assemble for selected architecture
12825 -mfpu=<fpu architecture> Assemble for selected FPU.
12826 -EB/-mbig-endian Big-endian
12827 -EL/-mlittle-endian Little-endian
12828 -k Generate PIC code
12829 -mthumb Start in Thumb mode
12830 -mthumb-interwork Code supports ARM/Thumb interworking
12832 For now we will also provide support for:
12834 -mapcs-32 32-bit Program counter
12835 -mapcs-26 26-bit Program counter
12836 -macps-float Floats passed in FP registers
12837 -mapcs-reentrant Reentrant code
12839 (sometime these will probably be replaced with -mapcs=<list of options>
12840 and -matpcs=<list of options>)
12842 The remaining options are only supported for back-wards compatibility.
12843 Cpu variants, the arm part is optional:
12844 -m[arm]1 Currently not supported.
12845 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
12846 -m[arm]3 Arm 3 processor
12847 -m[arm]6[xx], Arm 6 processors
12848 -m[arm]7[xx][t][[d]m] Arm 7 processors
12849 -m[arm]8[10] Arm 8 processors
12850 -m[arm]9[20][tdmi] Arm 9 processors
12851 -mstrongarm[110[0]] StrongARM processors
12852 -mxscale XScale processors
12853 -m[arm]v[2345[t[e]]] Arm architectures
12854 -mall All (except the ARM1)
12856 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
12857 -mfpe-old (No float load/store multiples)
12858 -mvfpxd VFP Single precision
12860 -mno-fpu Disable all floating point instructions
12862 The following CPU names are recognized:
12863 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
12864 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
12865 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
12866 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
12867 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
12868 arm10t arm10e, arm1020t, arm1020e, arm10200e,
12869 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
12873 const char * md_shortopts
= "m:k";
12875 #ifdef ARM_BI_ENDIAN
12876 #define OPTION_EB (OPTION_MD_BASE + 0)
12877 #define OPTION_EL (OPTION_MD_BASE + 1)
12879 #if TARGET_BYTES_BIG_ENDIAN
12880 #define OPTION_EB (OPTION_MD_BASE + 0)
12882 #define OPTION_EL (OPTION_MD_BASE + 1)
12886 struct option md_longopts
[] =
12889 {"EB", no_argument
, NULL
, OPTION_EB
},
12892 {"EL", no_argument
, NULL
, OPTION_EL
},
12894 {NULL
, no_argument
, NULL
, 0}
12897 size_t md_longopts_size
= sizeof (md_longopts
);
12899 struct arm_option_table
12901 char *option
; /* Option name to match. */
12902 char *help
; /* Help information. */
12903 int *var
; /* Variable to change. */
12904 int value
; /* What to change it to. */
12905 char *deprecated
; /* If non-null, print this message. */
12908 struct arm_option_table arm_opts
[] =
12910 {"k", N_("generate PIC code"), &pic_code
, 1, NULL
},
12911 {"mthumb", N_("assemble Thumb code"), &thumb_mode
, 1, NULL
},
12912 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
12913 &support_interwork
, 1, NULL
},
12914 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26
, 0, NULL
},
12915 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26
, 1, NULL
},
12916 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float
,
12918 {"mapcs-reentrant", N_("re-entrant code"), &pic_code
, 1, NULL
},
12919 {"matpcs", N_("code is ATPCS conformant"), &atpcs
, 1, NULL
},
12920 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian
, 1, NULL
},
12921 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian
, 1,
12924 /* These are recognized by the assembler, but have no affect on code. */
12925 {"mapcs-frame", N_("use frame pointer"), NULL
, 0, NULL
},
12926 {"mapcs-stack-check", N_("use stack size checking"), NULL
, 0, NULL
},
12928 /* DON'T add any new processors to this list -- we want the whole list
12929 to go away... Add them to the processors table instead. */
12930 {"marm1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
12931 {"m1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
12932 {"marm2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
12933 {"m2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
12934 {"marm250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
12935 {"m250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
12936 {"marm3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
12937 {"m3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
12938 {"marm6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
12939 {"m6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
12940 {"marm600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
12941 {"m600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
12942 {"marm610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
12943 {"m610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
12944 {"marm620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
12945 {"m620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
12946 {"marm7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
12947 {"m7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
12948 {"marm70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
12949 {"m70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
12950 {"marm700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
12951 {"m700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
12952 {"marm700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
12953 {"m700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
12954 {"marm710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
12955 {"m710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
12956 {"marm710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
12957 {"m710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
12958 {"marm720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
12959 {"m720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
12960 {"marm7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
12961 {"m7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
12962 {"marm7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
12963 {"m7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
12964 {"marm7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
12965 {"m7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
12966 {"marm7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
12967 {"m7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
12968 {"marm7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
12969 {"m7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
12970 {"marm7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
12971 {"m7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
12972 {"marm7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
12973 {"m7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
12974 {"marm7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
12975 {"m7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
12976 {"marm7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12977 {"m7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12978 {"marm7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12979 {"m7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12980 {"marm710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
12981 {"m710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
12982 {"marm720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
12983 {"m720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
12984 {"marm740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
12985 {"m740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
12986 {"marm8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
12987 {"m8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
12988 {"marm810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
12989 {"m810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
12990 {"marm9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
12991 {"m9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
12992 {"marm9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
12993 {"m9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
12994 {"marm920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
12995 {"m920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
12996 {"marm940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
12997 {"m940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
12998 {"mstrongarm", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=strongarm")},
12999 {"mstrongarm110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
13000 N_("use -mcpu=strongarm110")},
13001 {"mstrongarm1100", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
13002 N_("use -mcpu=strongarm1100")},
13003 {"mstrongarm1110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
13004 N_("use -mcpu=strongarm1110")},
13005 {"mxscale", NULL
, &legacy_cpu
, ARM_ARCH_XSCALE
, N_("use -mcpu=xscale")},
13006 {"miwmmxt", NULL
, &legacy_cpu
, ARM_ARCH_IWMMXT
, N_("use -mcpu=iwmmxt")},
13007 {"mall", NULL
, &legacy_cpu
, ARM_ANY
, N_("use -mcpu=all")},
13009 /* Architecture variants -- don't add any more to this list either. */
13010 {"mv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
13011 {"marmv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
13012 {"mv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
13013 {"marmv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
13014 {"mv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
13015 {"marmv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
13016 {"mv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
13017 {"marmv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
13018 {"mv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
13019 {"marmv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
13020 {"mv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
13021 {"marmv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
13022 {"mv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
13023 {"marmv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
13024 {"mv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
13025 {"marmv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
13026 {"mv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
13027 {"marmv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
13029 /* Floating point variants -- don't add any more to this list either. */
13030 {"mfpe-old", NULL
, &legacy_fpu
, FPU_ARCH_FPE
, N_("use -mfpu=fpe")},
13031 {"mfpa10", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa10")},
13032 {"mfpa11", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa11")},
13033 {"mno-fpu", NULL
, &legacy_fpu
, 0,
13034 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
13036 {NULL
, NULL
, NULL
, 0, NULL
}
13039 struct arm_cpu_option_table
13043 /* For some CPUs we assume an FPU unless the user explicitly sets
13048 /* This list should, at a minimum, contain all the cpu names
13049 recognized by GCC. */
13050 static struct arm_cpu_option_table arm_cpus
[] =
13052 {"all", ARM_ANY
, FPU_ARCH_FPA
},
13053 {"arm1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
13054 {"arm2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
13055 {"arm250", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
13056 {"arm3", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
13057 {"arm6", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13058 {"arm60", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13059 {"arm600", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13060 {"arm610", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13061 {"arm620", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13062 {"arm7", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13063 {"arm7m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
13064 {"arm7d", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13065 {"arm7dm", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
13066 {"arm7di", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13067 {"arm7dmi", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
13068 {"arm70", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13069 {"arm700", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13070 {"arm700i", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13071 {"arm710", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13072 {"arm710t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13073 {"arm720", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13074 {"arm720t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13075 {"arm740t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13076 {"arm710c", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13077 {"arm7100", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13078 {"arm7500", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13079 {"arm7500fe", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13080 {"arm7t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13081 {"arm7tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13082 {"arm7tdmi-s", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13083 {"arm8", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13084 {"arm810", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13085 {"strongarm", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13086 {"strongarm1", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13087 {"strongarm110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13088 {"strongarm1100", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13089 {"strongarm1110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13090 {"arm9", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13091 {"arm920", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13092 {"arm920t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13093 {"arm922t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13094 {"arm940t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13095 {"arm9tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13096 /* For V5 or later processors we default to using VFP; but the user
13097 should really set the FPU type explicitly. */
13098 {"arm9e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
13099 {"arm9e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13100 {"arm926ej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
13101 {"arm926ejs", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
13102 {"arm926ej-s", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
13103 {"arm946e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
13104 {"arm946e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13105 {"arm966e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
13106 {"arm966e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13107 {"arm10t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
13108 {"arm10e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13109 {"arm1020", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13110 {"arm1020t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
13111 {"arm1020e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13112 {"arm1026ejs", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
13113 {"arm1026ej-s", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
13114 {"arm1136js", ARM_ARCH_V6
, FPU_NONE
},
13115 {"arm1136j-s", ARM_ARCH_V6
, FPU_NONE
},
13116 {"arm1136jfs", ARM_ARCH_V6
, FPU_ARCH_VFP_V2
},
13117 {"arm1136jf-s", ARM_ARCH_V6
, FPU_ARCH_VFP_V2
},
13118 {"mpcore", ARM_ARCH_V6K
, FPU_ARCH_VFP_V2
},
13119 {"mpcorenovfp", ARM_ARCH_V6K
, FPU_NONE
},
13120 {"arm1176jz-s", ARM_ARCH_V6ZK
, FPU_NONE
},
13121 {"arm1176jzf-s", ARM_ARCH_V6ZK
, FPU_ARCH_VFP_V2
},
13122 /* ??? XSCALE is really an architecture. */
13123 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
13124 /* ??? iwmmxt is not a processor. */
13125 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP_V2
},
13126 {"i80200", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
13128 {"ep9312", ARM_ARCH_V4T
| ARM_CEXT_MAVERICK
, FPU_ARCH_MAVERICK
},
13132 struct arm_arch_option_table
13139 /* This list should, at a minimum, contain all the architecture names
13140 recognized by GCC. */
13141 static struct arm_arch_option_table arm_archs
[] =
13143 {"all", ARM_ANY
, FPU_ARCH_FPA
},
13144 {"armv1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
13145 {"armv2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
13146 {"armv2a", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
13147 {"armv2s", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
13148 {"armv3", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13149 {"armv3m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
13150 {"armv4", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13151 {"armv4xm", ARM_ARCH_V4xM
, FPU_ARCH_FPA
},
13152 {"armv4t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13153 {"armv4txm", ARM_ARCH_V4TxM
, FPU_ARCH_FPA
},
13154 {"armv5", ARM_ARCH_V5
, FPU_ARCH_VFP
},
13155 {"armv5t", ARM_ARCH_V5T
, FPU_ARCH_VFP
},
13156 {"armv5txm", ARM_ARCH_V5TxM
, FPU_ARCH_VFP
},
13157 {"armv5te", ARM_ARCH_V5TE
, FPU_ARCH_VFP
},
13158 {"armv5texp", ARM_ARCH_V5TExP
, FPU_ARCH_VFP
},
13159 {"armv5tej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP
},
13160 {"armv6", ARM_ARCH_V6
, FPU_ARCH_VFP
},
13161 {"armv6j", ARM_ARCH_V6
, FPU_ARCH_VFP
},
13162 {"armv6k", ARM_ARCH_V6K
, FPU_ARCH_VFP
},
13163 {"armv6z", ARM_ARCH_V6Z
, FPU_ARCH_VFP
},
13164 {"armv6zk", ARM_ARCH_V6ZK
, FPU_ARCH_VFP
},
13165 {"armv6t2", ARM_ARCH_V6T2
, FPU_ARCH_VFP
},
13166 {"armv6kt2", ARM_ARCH_V6KT2
, FPU_ARCH_VFP
},
13167 {"armv6zt2", ARM_ARCH_V6ZT2
, FPU_ARCH_VFP
},
13168 {"armv6zkt2", ARM_ARCH_V6ZKT2
, FPU_ARCH_VFP
},
13169 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP
},
13170 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP
},
13174 /* ISA extensions in the co-processor space. */
13175 struct arm_arch_extension_table
13181 static struct arm_arch_extension_table arm_extensions
[] =
13183 {"maverick", ARM_CEXT_MAVERICK
},
13184 {"xscale", ARM_CEXT_XSCALE
},
13185 {"iwmmxt", ARM_CEXT_IWMMXT
},
13189 struct arm_fpu_option_table
13195 /* This list should, at a minimum, contain all the fpu names
13196 recognized by GCC. */
13197 static struct arm_fpu_option_table arm_fpus
[] =
13199 {"softfpa", FPU_NONE
},
13200 {"fpe", FPU_ARCH_FPE
},
13201 {"fpe2", FPU_ARCH_FPE
},
13202 {"fpe3", FPU_ARCH_FPA
}, /* Third release supports LFM/SFM. */
13203 {"fpa", FPU_ARCH_FPA
},
13204 {"fpa10", FPU_ARCH_FPA
},
13205 {"fpa11", FPU_ARCH_FPA
},
13206 {"arm7500fe", FPU_ARCH_FPA
},
13207 {"softvfp", FPU_ARCH_VFP
},
13208 {"softvfp+vfp", FPU_ARCH_VFP_V2
},
13209 {"vfp", FPU_ARCH_VFP_V2
},
13210 {"vfp9", FPU_ARCH_VFP_V2
},
13211 {"vfp10", FPU_ARCH_VFP_V2
},
13212 {"vfp10-r0", FPU_ARCH_VFP_V1
},
13213 {"vfpxd", FPU_ARCH_VFP_V1xD
},
13214 {"arm1020t", FPU_ARCH_VFP_V1
},
13215 {"arm1020e", FPU_ARCH_VFP_V2
},
13216 {"arm1136jfs", FPU_ARCH_VFP_V2
},
13217 {"arm1136jf-s", FPU_ARCH_VFP_V2
},
13218 {"maverick", FPU_ARCH_MAVERICK
},
13222 struct arm_float_abi_option_table
13228 static struct arm_float_abi_option_table arm_float_abis
[] =
13230 {"hard", ARM_FLOAT_ABI_HARD
},
13231 {"softfp", ARM_FLOAT_ABI_SOFTFP
},
13232 {"soft", ARM_FLOAT_ABI_SOFT
},
13236 struct arm_eabi_option_table
13239 unsigned int value
;
13243 /* We only know how to output GNU and ver 4 (AAELF) formats. */
13244 static struct arm_eabi_option_table arm_eabis
[] =
13246 {"gnu", EF_ARM_EABI_UNKNOWN
},
13247 {"4", EF_ARM_EABI_VER4
},
13252 struct arm_long_option_table
13254 char * option
; /* Substring to match. */
13255 char * help
; /* Help information. */
13256 int (* func
) (char * subopt
); /* Function to decode sub-option. */
13257 char * deprecated
; /* If non-null, print this message. */
13261 arm_parse_extension (char * str
, int * opt_p
)
13263 while (str
!= NULL
&& *str
!= 0)
13265 struct arm_arch_extension_table
* opt
;
13271 as_bad (_("invalid architectural extension"));
13276 ext
= strchr (str
, '+');
13279 optlen
= ext
- str
;
13281 optlen
= strlen (str
);
13285 as_bad (_("missing architectural extension"));
13289 for (opt
= arm_extensions
; opt
->name
!= NULL
; opt
++)
13290 if (strncmp (opt
->name
, str
, optlen
) == 0)
13292 *opt_p
|= opt
->value
;
13296 if (opt
->name
== NULL
)
13298 as_bad (_("unknown architectural extnsion `%s'"), str
);
13309 arm_parse_cpu (char * str
)
13311 struct arm_cpu_option_table
* opt
;
13312 char * ext
= strchr (str
, '+');
13316 optlen
= ext
- str
;
13318 optlen
= strlen (str
);
13322 as_bad (_("missing cpu name `%s'"), str
);
13326 for (opt
= arm_cpus
; opt
->name
!= NULL
; opt
++)
13327 if (strncmp (opt
->name
, str
, optlen
) == 0)
13329 mcpu_cpu_opt
= opt
->value
;
13330 mcpu_fpu_opt
= opt
->default_fpu
;
13333 return arm_parse_extension (ext
, &mcpu_cpu_opt
);
13338 as_bad (_("unknown cpu `%s'"), str
);
13343 arm_parse_arch (char * str
)
13345 struct arm_arch_option_table
*opt
;
13346 char *ext
= strchr (str
, '+');
13350 optlen
= ext
- str
;
13352 optlen
= strlen (str
);
13356 as_bad (_("missing architecture name `%s'"), str
);
13361 for (opt
= arm_archs
; opt
->name
!= NULL
; opt
++)
13362 if (streq (opt
->name
, str
))
13364 march_cpu_opt
= opt
->value
;
13365 march_fpu_opt
= opt
->default_fpu
;
13368 return arm_parse_extension (ext
, &march_cpu_opt
);
13373 as_bad (_("unknown architecture `%s'\n"), str
);
13378 arm_parse_fpu (char * str
)
13380 struct arm_fpu_option_table
* opt
;
13382 for (opt
= arm_fpus
; opt
->name
!= NULL
; opt
++)
13383 if (streq (opt
->name
, str
))
13385 mfpu_opt
= opt
->value
;
13389 as_bad (_("unknown floating point format `%s'\n"), str
);
13394 arm_parse_float_abi (char * str
)
13396 struct arm_float_abi_option_table
* opt
;
13398 for (opt
= arm_float_abis
; opt
->name
!= NULL
; opt
++)
13399 if (streq (opt
->name
, str
))
13401 mfloat_abi_opt
= opt
->value
;
13405 as_bad (_("unknown floating point abi `%s'\n"), str
);
13411 arm_parse_eabi (char * str
)
13413 struct arm_eabi_option_table
*opt
;
13415 for (opt
= arm_eabis
; opt
->name
!= NULL
; opt
++)
13416 if (streq (opt
->name
, str
))
13418 meabi_flags
= opt
->value
;
13421 as_bad (_("unknown EABI `%s'\n"), str
);
13426 struct arm_long_option_table arm_long_opts
[] =
13428 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13429 arm_parse_cpu
, NULL
},
13430 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13431 arm_parse_arch
, NULL
},
13432 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13433 arm_parse_fpu
, NULL
},
13434 {"mfloat-abi=", N_("<abi>\t assemble for floating point ABI <abi>"),
13435 arm_parse_float_abi
, NULL
},
13437 {"meabi=", N_("<ver>\t assemble for eabi version <ver>"),
13438 arm_parse_eabi
, NULL
},
13440 {NULL
, NULL
, 0, NULL
}
13444 md_parse_option (int c
, char * arg
)
13446 struct arm_option_table
*opt
;
13447 struct arm_long_option_table
*lopt
;
13453 target_big_endian
= 1;
13459 target_big_endian
= 0;
13464 /* Listing option. Just ignore these, we don't support additional
13469 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
13471 if (c
== opt
->option
[0]
13472 && ((arg
== NULL
&& opt
->option
[1] == 0)
13473 || streq (arg
, opt
->option
+ 1)))
13475 #if WARN_DEPRECATED
13476 /* If the option is deprecated, tell the user. */
13477 if (opt
->deprecated
!= NULL
)
13478 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
,
13479 arg
? arg
: "", _(opt
->deprecated
));
13482 if (opt
->var
!= NULL
)
13483 *opt
->var
= opt
->value
;
13489 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
13491 /* These options are expected to have an argument. */
13492 if (c
== lopt
->option
[0]
13494 && strncmp (arg
, lopt
->option
+ 1,
13495 strlen (lopt
->option
+ 1)) == 0)
13497 #if WARN_DEPRECATED
13498 /* If the option is deprecated, tell the user. */
13499 if (lopt
->deprecated
!= NULL
)
13500 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
, arg
,
13501 _(lopt
->deprecated
));
13504 /* Call the sup-option parser. */
13505 return lopt
->func (arg
+ strlen (lopt
->option
) - 1);
13516 md_show_usage (FILE * fp
)
13518 struct arm_option_table
*opt
;
13519 struct arm_long_option_table
*lopt
;
13521 fprintf (fp
, _(" ARM-specific assembler options:\n"));
13523 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
13524 if (opt
->help
!= NULL
)
13525 fprintf (fp
, " -%-23s%s\n", opt
->option
, _(opt
->help
));
13527 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
13528 if (lopt
->help
!= NULL
)
13529 fprintf (fp
, " -%s%s\n", lopt
->option
, _(lopt
->help
));
13533 -EB assemble code for a big-endian cpu\n"));
13538 -EL assemble code for a little-endian cpu\n"));
13542 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13545 cons_fix_new_arm (fragS
* frag
,
13550 bfd_reloc_code_real_type type
;
13554 FIXME: @@ Should look at CPU word size. */
13558 type
= BFD_RELOC_8
;
13561 type
= BFD_RELOC_16
;
13565 type
= BFD_RELOC_32
;
13568 type
= BFD_RELOC_64
;
13572 fix_new_exp (frag
, where
, (int) size
, exp
, pcrel
, type
);
13575 /* A good place to do this, although this was probably not intended
13576 for this kind of use. We need to dump the literal pool before
13577 references are made to a null symbol pointer. */
13582 literal_pool
* pool
;
13584 for (pool
= list_of_pools
; pool
; pool
= pool
->next
)
13586 /* Put it at the end of the relevent section. */
13587 subseg_set (pool
->section
, pool
->sub_section
);
13589 arm_elf_change_section ();
13596 arm_start_line_hook (void)
13598 last_label_seen
= NULL
;
13602 arm_frob_label (symbolS
* sym
)
13604 last_label_seen
= sym
;
13606 ARM_SET_THUMB (sym
, thumb_mode
);
13608 #if defined OBJ_COFF || defined OBJ_ELF
13609 ARM_SET_INTERWORK (sym
, support_interwork
);
13612 /* Note - do not allow local symbols (.Lxxx) to be labeled
13613 as Thumb functions. This is because these labels, whilst
13614 they exist inside Thumb code, are not the entry points for
13615 possible ARM->Thumb calls. Also, these labels can be used
13616 as part of a computed goto or switch statement. eg gcc
13617 can generate code that looks like this:
13619 ldr r2, [pc, .Laaa]
13629 The first instruction loads the address of the jump table.
13630 The second instruction converts a table index into a byte offset.
13631 The third instruction gets the jump address out of the table.
13632 The fourth instruction performs the jump.
13634 If the address stored at .Laaa is that of a symbol which has the
13635 Thumb_Func bit set, then the linker will arrange for this address
13636 to have the bottom bit set, which in turn would mean that the
13637 address computation performed by the third instruction would end
13638 up with the bottom bit set. Since the ARM is capable of unaligned
13639 word loads, the instruction would then load the incorrect address
13640 out of the jump table, and chaos would ensue. */
13641 if (label_is_thumb_function_name
13642 && (S_GET_NAME (sym
)[0] != '.' || S_GET_NAME (sym
)[1] != 'L')
13643 && (bfd_get_section_flags (stdoutput
, now_seg
) & SEC_CODE
) != 0)
13645 /* When the address of a Thumb function is taken the bottom
13646 bit of that address should be set. This will allow
13647 interworking between Arm and Thumb functions to work
13650 THUMB_SET_FUNC (sym
, 1);
13652 label_is_thumb_function_name
= FALSE
;
13656 /* Adjust the symbol table. This marks Thumb symbols as distinct from
13660 arm_adjust_symtab (void)
13665 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
13667 if (ARM_IS_THUMB (sym
))
13669 if (THUMB_IS_FUNC (sym
))
13671 /* Mark the symbol as a Thumb function. */
13672 if ( S_GET_STORAGE_CLASS (sym
) == C_STAT
13673 || S_GET_STORAGE_CLASS (sym
) == C_LABEL
) /* This can happen! */
13674 S_SET_STORAGE_CLASS (sym
, C_THUMBSTATFUNC
);
13676 else if (S_GET_STORAGE_CLASS (sym
) == C_EXT
)
13677 S_SET_STORAGE_CLASS (sym
, C_THUMBEXTFUNC
);
13679 as_bad (_("%s: unexpected function type: %d"),
13680 S_GET_NAME (sym
), S_GET_STORAGE_CLASS (sym
));
13682 else switch (S_GET_STORAGE_CLASS (sym
))
13685 S_SET_STORAGE_CLASS (sym
, C_THUMBEXT
);
13688 S_SET_STORAGE_CLASS (sym
, C_THUMBSTAT
);
13691 S_SET_STORAGE_CLASS (sym
, C_THUMBLABEL
);
13699 if (ARM_IS_INTERWORK (sym
))
13700 coffsymbol (symbol_get_bfdsym (sym
))->native
->u
.syment
.n_flags
= 0xFF;
13707 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
13709 if (ARM_IS_THUMB (sym
))
13711 elf_symbol_type
* elf_sym
;
13713 elf_sym
= elf_symbol (symbol_get_bfdsym (sym
));
13714 bind
= ELF_ST_BIND (elf_sym
->internal_elf_sym
.st_info
);
13716 /* If it's a .thumb_func, declare it as so,
13717 otherwise tag label as .code 16. */
13718 if (THUMB_IS_FUNC (sym
))
13719 elf_sym
->internal_elf_sym
.st_info
=
13720 ELF_ST_INFO (bind
, STT_ARM_TFUNC
);
13722 elf_sym
->internal_elf_sym
.st_info
=
13723 ELF_ST_INFO (bind
, STT_ARM_16BIT
);
13730 arm_data_in_code (void)
13732 if (thumb_mode
&& ! strncmp (input_line_pointer
+ 1, "data:", 5))
13734 *input_line_pointer
= '/';
13735 input_line_pointer
+= 5;
13736 *input_line_pointer
= 0;
13744 arm_canonicalize_symbol_name (char * name
)
13748 if (thumb_mode
&& (len
= strlen (name
)) > 5
13749 && streq (name
+ len
- 5, "/data"))
13750 *(name
+ len
- 5) = 0;
13755 #if defined OBJ_COFF || defined OBJ_ELF
13757 arm_validate_fix (fixS
* fixP
)
13759 /* If the destination of the branch is a defined symbol which does not have
13760 the THUMB_FUNC attribute, then we must be calling a function which has
13761 the (interfacearm) attribute. We look for the Thumb entry point to that
13762 function and change the branch to refer to that function instead. */
13763 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
13764 && fixP
->fx_addsy
!= NULL
13765 && S_IS_DEFINED (fixP
->fx_addsy
)
13766 && ! THUMB_IS_FUNC (fixP
->fx_addsy
))
13768 fixP
->fx_addsy
= find_real_start (fixP
->fx_addsy
);
13774 arm_force_relocation (struct fix
* fixp
)
13776 #if defined (OBJ_COFF) && defined (TE_PE)
13777 if (fixp
->fx_r_type
== BFD_RELOC_RVA
)
13781 if (fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
13782 || fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
13783 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
13784 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
)
13788 /* Resolve these relocations even if the symbol is extern or weak. */
13789 if (fixp
->fx_r_type
== BFD_RELOC_ARM_IMMEDIATE
13790 || fixp
->fx_r_type
== BFD_RELOC_ARM_OFFSET_IMM
13791 || fixp
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
13794 return generic_force_reloc (fixp
);
13798 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
13799 local labels from being added to the output symbol table when they
13800 are used with the ADRL pseudo op. The ADRL relocation should always
13801 be resolved before the binbary is emitted, so it is safe to say that
13802 it is adjustable. */
13805 arm_fix_adjustable (fixS
* fixP
)
13807 if (fixP
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
13814 /* Relocations against Thumb function names must be left unadjusted,
13815 so that the linker can use this information to correctly set the
13816 bottom bit of their addresses. The MIPS version of this function
13817 also prevents relocations that are mips-16 specific, but I do not
13818 know why it does this.
13821 There is one other problem that ought to be addressed here, but
13822 which currently is not: Taking the address of a label (rather
13823 than a function) and then later jumping to that address. Such
13824 addresses also ought to have their bottom bit set (assuming that
13825 they reside in Thumb code), but at the moment they will not. */
13828 arm_fix_adjustable (fixS
* fixP
)
13830 if (fixP
->fx_addsy
== NULL
)
13833 if (THUMB_IS_FUNC (fixP
->fx_addsy
)
13834 && fixP
->fx_subsy
== NULL
)
13837 /* We need the symbol name for the VTABLE entries. */
13838 if ( fixP
->fx_r_type
== BFD_RELOC_VTABLE_INHERIT
13839 || fixP
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
13842 /* Don't allow symbols to be discarded on GOT related relocs. */
13843 if (fixP
->fx_r_type
== BFD_RELOC_ARM_PLT32
13844 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOT32
13845 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOTOFF
13846 || fixP
->fx_r_type
== BFD_RELOC_ARM_TARGET2
)
13853 elf32_arm_target_format (void)
13856 return (target_big_endian
13857 ? "elf32-bigarm-symbian"
13858 : "elf32-littlearm-symbian");
13859 #elif defined (TE_VXWORKS)
13860 return (target_big_endian
13861 ? "elf32-bigarm-vxworks"
13862 : "elf32-littlearm-vxworks");
13864 if (target_big_endian
)
13865 return "elf32-bigarm";
13867 return "elf32-littlearm";
13872 armelf_frob_symbol (symbolS
* symp
,
13875 elf_frob_symbol (symp
, puntp
);
13879 s_arm_elf_cons (int nbytes
)
13883 #ifdef md_flush_pending_output
13884 md_flush_pending_output ();
13887 if (is_it_end_of_statement ())
13889 demand_empty_rest_of_line ();
13893 #ifdef md_cons_align
13894 md_cons_align (nbytes
);
13897 mapping_state (MAP_DATA
);
13900 bfd_reloc_code_real_type reloc
;
13902 expression (& exp
);
13904 if (exp
.X_op
== O_symbol
13905 && * input_line_pointer
== '('
13906 && (reloc
= arm_parse_reloc ()) != BFD_RELOC_UNUSED
)
13908 reloc_howto_type
*howto
= bfd_reloc_type_lookup (stdoutput
, reloc
);
13909 int size
= bfd_get_reloc_size (howto
);
13912 as_bad ("%s relocations do not fit in %d bytes",
13913 howto
->name
, nbytes
);
13916 char *p
= frag_more ((int) nbytes
);
13917 int offset
= nbytes
- size
;
13919 fix_new_exp (frag_now
, p
- frag_now
->fr_literal
+ offset
, size
,
13924 emit_expr (&exp
, (unsigned int) nbytes
);
13926 while (*input_line_pointer
++ == ',');
13928 /* Put terminator back into stream. */
13929 input_line_pointer
--;
13930 demand_empty_rest_of_line ();
13934 /* Parse a .rel31 directive. */
13937 s_arm_rel31 (int ignored ATTRIBUTE_UNUSED
)
13943 SKIP_WHITESPACE ();
13946 if (*input_line_pointer
== '1')
13947 highbit
= 0x80000000;
13948 else if (*input_line_pointer
!= '0')
13949 as_bad (_("expected 0 or 1"));
13951 input_line_pointer
++;
13952 SKIP_WHITESPACE ();
13953 if (*input_line_pointer
!= ',')
13954 as_bad (_("missing comma"));
13955 input_line_pointer
++;
13957 #ifdef md_flush_pending_output
13958 md_flush_pending_output ();
13961 #ifdef md_cons_align
13965 mapping_state (MAP_DATA
);
13970 md_number_to_chars (p
, highbit
, 4);
13971 fix_new_arm (frag_now
, p
- frag_now
->fr_literal
, 4, &exp
, 1,
13972 BFD_RELOC_ARM_PREL31
);
13974 demand_empty_rest_of_line ();
13977 /* Code to deal with unwinding tables. */
13979 static void add_unwind_adjustsp (offsetT
);
13981 /* Switch to section NAME and create section if necessary. It's
13982 rather ugly that we have to manipulate input_line_pointer but I
13983 don't see any other way to accomplish the same thing without
13984 changing obj-elf.c (which may be the Right Thing, in the end).
13985 Copied from tc-ia64.c. */
13988 set_section (char *name
)
13990 char *saved_input_line_pointer
;
13992 saved_input_line_pointer
= input_line_pointer
;
13993 input_line_pointer
= name
;
13994 obj_elf_section (0);
13995 input_line_pointer
= saved_input_line_pointer
;
13998 /* Cenerate and deferred unwind frame offset. */
14001 flush_pending_unwind (void)
14005 offset
= unwind
.pending_offset
;
14006 unwind
.pending_offset
= 0;
14008 add_unwind_adjustsp (offset
);
14011 /* Add an opcode to this list for this function. Two-byte opcodes should
14012 be passed as op[0] << 8 | op[1]. The list of opcodes is built in reverse
14016 add_unwind_opcode (valueT op
, int length
)
14018 /* Add any deferred stack adjustment. */
14019 if (unwind
.pending_offset
)
14020 flush_pending_unwind ();
14022 unwind
.sp_restored
= 0;
14024 if (unwind
.opcode_count
+ length
> unwind
.opcode_alloc
)
14026 unwind
.opcode_alloc
+= ARM_OPCODE_CHUNK_SIZE
;
14027 if (unwind
.opcodes
)
14028 unwind
.opcodes
= xrealloc (unwind
.opcodes
,
14029 unwind
.opcode_alloc
);
14031 unwind
.opcodes
= xmalloc (unwind
.opcode_alloc
);
14036 unwind
.opcodes
[unwind
.opcode_count
] = op
& 0xff;
14038 unwind
.opcode_count
++;
14042 /* Add unwind opcodes to adjust the stack pointer. */
14045 add_unwind_adjustsp (offsetT offset
)
14049 if (offset
> 0x200)
14051 /* We need at most 5 bytes to hold a 32-bit value in a uleb128. */
14056 /* Long form: 0xb2, uleb128. */
14057 /* This might not fit in a word so add the individual bytes,
14058 remembering the list is built in reverse order. */
14059 o
= (valueT
) ((offset
- 0x204) >> 2);
14061 add_unwind_opcode (0, 1);
14063 /* Calculate the uleb128 encoding of the offset. */
14067 bytes
[n
] = o
& 0x7f;
14073 /* Add the insn. */
14075 add_unwind_opcode (bytes
[n
- 1], 1);
14076 add_unwind_opcode (0xb2, 1);
14078 else if (offset
> 0x100)
14080 /* Two short opcodes. */
14081 add_unwind_opcode (0x3f, 1);
14082 op
= (offset
- 0x104) >> 2;
14083 add_unwind_opcode (op
, 1);
14085 else if (offset
> 0)
14087 /* Short opcode. */
14088 op
= (offset
- 4) >> 2;
14089 add_unwind_opcode (op
, 1);
14091 else if (offset
< 0)
14094 while (offset
> 0x100)
14096 add_unwind_opcode (0x7f, 1);
14099 op
= ((offset
- 4) >> 2) | 0x40;
14100 add_unwind_opcode (op
, 1);
14104 /* Finish the list of unwind opcodes for this function. */
14106 finish_unwind_opcodes (void)
14110 if (unwind
.fp_used
)
14112 /* Adjust sp as neccessary. */
14113 unwind
.pending_offset
+= unwind
.fp_offset
- unwind
.frame_size
;
14114 flush_pending_unwind ();
14116 /* After restoring sp from the frame pointer. */
14117 op
= 0x90 | unwind
.fp_reg
;
14118 add_unwind_opcode (op
, 1);
14121 flush_pending_unwind ();
14125 /* Start an exception table entry. If idx is nonzero this is an index table
14129 start_unwind_section (const segT text_seg
, int idx
)
14131 const char * text_name
;
14132 const char * prefix
;
14133 const char * prefix_once
;
14137 size_t sec_name_len
;
14141 prefix
= ELF_STRING_ARM_unwind
;
14142 prefix_once
= ELF_STRING_ARM_unwind_once
;
14146 prefix
= ELF_STRING_ARM_unwind_info
;
14147 prefix_once
= ELF_STRING_ARM_unwind_info_once
;
14150 text_name
= segment_name (text_seg
);
14151 if (streq (text_name
, ".text"))
14154 if (strncmp (text_name
, ".gnu.linkonce.t.",
14155 strlen (".gnu.linkonce.t.")) == 0)
14157 prefix
= prefix_once
;
14158 text_name
+= strlen (".gnu.linkonce.t.");
14161 prefix_len
= strlen (prefix
);
14162 text_len
= strlen (text_name
);
14163 sec_name_len
= prefix_len
+ text_len
;
14164 sec_name
= alloca (sec_name_len
+ 1);
14165 memcpy (sec_name
, prefix
, prefix_len
);
14166 memcpy (sec_name
+ prefix_len
, text_name
, text_len
);
14167 sec_name
[prefix_len
+ text_len
] = '\0';
14169 /* Handle COMDAT group. */
14170 if (prefix
!= prefix_once
&& (text_seg
->flags
& SEC_LINK_ONCE
) != 0)
14173 size_t len
, group_name_len
;
14174 const char *group_name
= elf_group_name (text_seg
);
14176 if (group_name
== NULL
)
14178 as_bad ("Group section `%s' has no group signature",
14179 segment_name (text_seg
));
14180 ignore_rest_of_line ();
14183 /* We have to construct a fake section directive. */
14184 group_name_len
= strlen (group_name
);
14190 len
= (sec_name_len
14191 + prefix_len
/* ,"aG",%sectiontype, */
14192 + group_name_len
/* ,group_name */
14193 + 7); /* ,comdat */
14195 section
= alloca (len
+ 1);
14196 memcpy (section
, sec_name
, sec_name_len
);
14198 memcpy (section
+ sec_name_len
, ",\"aG\",%exidx,", 13);
14200 memcpy (section
+ sec_name_len
, ",\"aG\",%progbits,", 16);
14201 memcpy (section
+ sec_name_len
+ prefix_len
, group_name
, group_name_len
);
14202 memcpy (section
+ len
- 7, ",comdat", 7);
14203 section
[len
] = '\0';
14204 set_section (section
);
14208 set_section (sec_name
);
14209 bfd_set_section_flags (stdoutput
, now_seg
,
14210 SEC_LOAD
| SEC_ALLOC
| SEC_READONLY
);
14213 /* Set the setion link for index tables. */
14215 elf_linked_to_section (now_seg
) = text_seg
;
14219 /* Start an unwind table entry. HAVE_DATA is nonzero if we have additional
14220 personality routine data. Returns zero, or the index table value for
14221 and inline entry. */
14224 create_unwind_entry (int have_data
)
14229 /* The current word of data. */
14231 /* The number of bytes left in this word. */
14234 finish_unwind_opcodes ();
14236 /* Remember the current text section. */
14237 unwind
.saved_seg
= now_seg
;
14238 unwind
.saved_subseg
= now_subseg
;
14240 start_unwind_section (now_seg
, 0);
14242 if (unwind
.personality_routine
== NULL
)
14244 if (unwind
.personality_index
== -2)
14247 as_bad (_("handerdata in cantunwind frame"));
14248 return 1; /* EXIDX_CANTUNWIND. */
14251 /* Use a default personality routine if none is specified. */
14252 if (unwind
.personality_index
== -1)
14254 if (unwind
.opcode_count
> 3)
14255 unwind
.personality_index
= 1;
14257 unwind
.personality_index
= 0;
14260 /* Space for the personality routine entry. */
14261 if (unwind
.personality_index
== 0)
14263 if (unwind
.opcode_count
> 3)
14264 as_bad (_("too many unwind opcodes for personality routine 0"));
14268 /* All the data is inline in the index table. */
14271 while (unwind
.opcode_count
> 0)
14273 unwind
.opcode_count
--;
14274 data
= (data
<< 8) | unwind
.opcodes
[unwind
.opcode_count
];
14278 /* Pad with "finish" opcodes. */
14280 data
= (data
<< 8) | 0xb0;
14287 /* We get two opcodes "free" in the first word. */
14288 size
= unwind
.opcode_count
- 2;
14291 /* An extra byte is required for the opcode count. */
14292 size
= unwind
.opcode_count
+ 1;
14294 size
= (size
+ 3) >> 2;
14296 as_bad (_("too many unwind opcodes"));
14298 frag_align (2, 0, 0);
14299 record_alignment (now_seg
, 2);
14300 unwind
.table_entry
= expr_build_dot ();
14302 /* Allocate the table entry. */
14303 ptr
= frag_more ((size
<< 2) + 4);
14304 where
= frag_now_fix () - ((size
<< 2) + 4);
14306 switch (unwind
.personality_index
)
14309 /* ??? Should this be a PLT generating relocation? */
14310 /* Custom personality routine. */
14311 fix_new (frag_now
, where
, 4, unwind
.personality_routine
, 0, 1,
14312 BFD_RELOC_ARM_PREL31
);
14317 /* Set the first byte to the number of additional words. */
14322 /* ABI defined personality routines. */
14324 /* Three opcodes bytes are packed into the first word. */
14331 /* The size and first two opcode bytes go in the first word. */
14332 data
= ((0x80 + unwind
.personality_index
) << 8) | size
;
14337 /* Should never happen. */
14341 /* Pack the opcodes into words (MSB first), reversing the list at the same
14343 while (unwind
.opcode_count
> 0)
14347 md_number_to_chars (ptr
, data
, 4);
14352 unwind
.opcode_count
--;
14354 data
= (data
<< 8) | unwind
.opcodes
[unwind
.opcode_count
];
14357 /* Finish off the last word. */
14360 /* Pad with "finish" opcodes. */
14362 data
= (data
<< 8) | 0xb0;
14364 md_number_to_chars (ptr
, data
, 4);
14369 /* Add an empty descriptor if there is no user-specified data. */
14370 ptr
= frag_more (4);
14371 md_number_to_chars (ptr
, 0, 4);
14378 /* Parse an unwind_fnstart directive. Simply records the current location. */
14381 s_arm_unwind_fnstart (int ignored ATTRIBUTE_UNUSED
)
14383 demand_empty_rest_of_line ();
14384 /* Mark the start of the function. */
14385 unwind
.proc_start
= expr_build_dot ();
14387 /* Reset the rest of the unwind info. */
14388 unwind
.opcode_count
= 0;
14389 unwind
.table_entry
= NULL
;
14390 unwind
.personality_routine
= NULL
;
14391 unwind
.personality_index
= -1;
14392 unwind
.frame_size
= 0;
14393 unwind
.fp_offset
= 0;
14394 unwind
.fp_reg
= 13;
14395 unwind
.fp_used
= 0;
14396 unwind
.sp_restored
= 0;
14400 /* Parse a handlerdata directive. Creates the exception handling table entry
14401 for the function. */
14404 s_arm_unwind_handlerdata (int ignored ATTRIBUTE_UNUSED
)
14406 demand_empty_rest_of_line ();
14407 if (unwind
.table_entry
)
14408 as_bad (_("dupicate .handlerdata directive"));
14410 create_unwind_entry (1);
14413 /* Parse an unwind_fnend directive. Generates the index table entry. */
14416 s_arm_unwind_fnend (int ignored ATTRIBUTE_UNUSED
)
14422 demand_empty_rest_of_line ();
14424 /* Add eh table entry. */
14425 if (unwind
.table_entry
== NULL
)
14426 val
= create_unwind_entry (0);
14430 /* Add index table entry. This is two words. */
14431 start_unwind_section (unwind
.saved_seg
, 1);
14432 frag_align (2, 0, 0);
14433 record_alignment (now_seg
, 2);
14435 ptr
= frag_more (8);
14436 where
= frag_now_fix () - 8;
14438 /* Self relative offset of the function start. */
14439 fix_new (frag_now
, where
, 4, unwind
.proc_start
, 0, 1,
14440 BFD_RELOC_ARM_PREL31
);
14442 /* Indicate dependency on EHABI-defined personality routines to the
14443 linker, if it hasn't been done already. */
14444 if (unwind
.personality_index
>= 0 && unwind
.personality_index
< 3)
14446 char *name
[] = { "__aeabi_unwind_cpp_pr0",
14447 "__aeabi_unwind_cpp_pr1",
14448 "__aeabi_unwind_cpp_pr2" };
14449 if (!(marked_pr_dependency
& (1 << unwind
.personality_index
)))
14451 symbolS
*pr
= symbol_find_or_make (name
[unwind
.personality_index
]);
14452 fix_new (frag_now
, where
, 0, pr
, 0, 1, BFD_RELOC_NONE
);
14453 marked_pr_dependency
|= 1 << unwind
.personality_index
;
14454 seg_info (now_seg
)->tc_segment_info_data
.marked_pr_dependency
14455 = marked_pr_dependency
;
14460 /* Inline exception table entry. */
14461 md_number_to_chars (ptr
+ 4, val
, 4);
14463 /* Self relative offset of the table entry. */
14464 fix_new (frag_now
, where
+ 4, 4, unwind
.table_entry
, 0, 1,
14465 BFD_RELOC_ARM_PREL31
);
14467 /* Restore the original section. */
14468 subseg_set (unwind
.saved_seg
, unwind
.saved_subseg
);
14472 /* Parse an unwind_cantunwind directive. */
14475 s_arm_unwind_cantunwind (int ignored ATTRIBUTE_UNUSED
)
14477 demand_empty_rest_of_line ();
14478 if (unwind
.personality_routine
|| unwind
.personality_index
!= -1)
14479 as_bad (_("personality routine specified for cantunwind frame"));
14481 unwind
.personality_index
= -2;
14485 /* Parse a personalityindex directive. */
14488 s_arm_unwind_personalityindex (int ignored ATTRIBUTE_UNUSED
)
14492 if (unwind
.personality_routine
|| unwind
.personality_index
!= -1)
14493 as_bad (_("duplicate .personalityindex directive"));
14495 SKIP_WHITESPACE ();
14499 if (exp
.X_op
!= O_constant
14500 || exp
.X_add_number
< 0 || exp
.X_add_number
> 15)
14502 as_bad (_("bad personality routine number"));
14503 ignore_rest_of_line ();
14507 unwind
.personality_index
= exp
.X_add_number
;
14509 demand_empty_rest_of_line ();
14513 /* Parse a personality directive. */
14516 s_arm_unwind_personality (int ignored ATTRIBUTE_UNUSED
)
14520 if (unwind
.personality_routine
|| unwind
.personality_index
!= -1)
14521 as_bad (_("duplicate .personality directive"));
14523 SKIP_WHITESPACE ();
14524 name
= input_line_pointer
;
14525 c
= get_symbol_end ();
14526 p
= input_line_pointer
;
14527 unwind
.personality_routine
= symbol_find_or_make (name
);
14529 SKIP_WHITESPACE ();
14530 demand_empty_rest_of_line ();
14534 /* Parse a directive saving core registers. */
14537 s_arm_unwind_save_core (void)
14543 SKIP_WHITESPACE ();
14544 range
= reg_list (&input_line_pointer
);
14547 as_bad (_("expected register list"));
14548 ignore_rest_of_line ();
14552 demand_empty_rest_of_line ();
14554 /* Turn .unwind_movsp ip followed by .unwind_save {..., ip, ...}
14555 into .unwind_save {..., sp...}. We aren't bothered about the value of
14556 ip because it is clobbered by calls. */
14557 if (unwind
.sp_restored
&& unwind
.fp_reg
== 12
14558 && (range
& 0x3000) == 0x1000)
14560 unwind
.opcode_count
--;
14561 unwind
.sp_restored
= 0;
14562 range
= (range
| 0x2000) & ~0x1000;
14563 unwind
.pending_offset
= 0;
14566 /* See if we can use the short opcodes. These pop a block of upto 8
14567 registers starting with r4, plus maybe r14. */
14568 for (n
= 0; n
< 8; n
++)
14570 /* Break at the first non-saved register. */
14571 if ((range
& (1 << (n
+ 4))) == 0)
14574 /* See if there are any other bits set. */
14575 if (n
== 0 || (range
& (0xfff0 << n
) & 0xbff0) != 0)
14577 /* Use the long form. */
14578 op
= 0x8000 | ((range
>> 4) & 0xfff);
14579 add_unwind_opcode (op
, 2);
14583 /* Use the short form. */
14584 if (range
& 0x4000)
14585 op
= 0xa8; /* Pop r14. */
14587 op
= 0xa0; /* Do not pop r14. */
14589 add_unwind_opcode (op
, 1);
14595 op
= 0xb100 | (range
& 0xf);
14596 add_unwind_opcode (op
, 2);
14599 /* Record the number of bytes pushed. */
14600 for (n
= 0; n
< 16; n
++)
14602 if (range
& (1 << n
))
14603 unwind
.frame_size
+= 4;
14608 /* Parse a directive saving FPA registers. */
14611 s_arm_unwind_save_fpa (int reg
)
14617 /* Get Number of registers to transfer. */
14618 if (skip_past_comma (&input_line_pointer
) != FAIL
)
14621 exp
.X_op
= O_illegal
;
14623 if (exp
.X_op
!= O_constant
)
14625 as_bad (_("expected , <constant>"));
14626 ignore_rest_of_line ();
14630 num_regs
= exp
.X_add_number
;
14632 if (num_regs
< 1 || num_regs
> 4)
14634 as_bad (_("number of registers must be in the range [1:4]"));
14635 ignore_rest_of_line ();
14639 demand_empty_rest_of_line ();
14644 op
= 0xb4 | (num_regs
- 1);
14645 add_unwind_opcode (op
, 1);
14650 op
= 0xc800 | (reg
<< 4) | (num_regs
- 1);
14651 add_unwind_opcode (op
, 2);
14653 unwind
.frame_size
+= num_regs
* 12;
14657 /* Parse a directive saving VFP registers. */
14660 s_arm_unwind_save_vfp (void)
14666 count
= vfp_parse_reg_list (&input_line_pointer
, ®
, 1);
14669 as_bad (_("expected register list"));
14670 ignore_rest_of_line ();
14674 demand_empty_rest_of_line ();
14679 op
= 0xb8 | (count
- 1);
14680 add_unwind_opcode (op
, 1);
14685 op
= 0xb300 | (reg
<< 4) | (count
- 1);
14686 add_unwind_opcode (op
, 2);
14688 unwind
.frame_size
+= count
* 8 + 4;
14692 /* Parse a directive saving iWMMXt registers. */
14695 s_arm_unwind_save_wmmx (void)
14704 if (*input_line_pointer
== '{')
14705 input_line_pointer
++;
14711 reg
= arm_reg_parse (&input_line_pointer
,
14712 all_reg_maps
[REG_TYPE_IWMMXT
].htab
);
14714 if (wr_register (reg
))
14716 i
= reg
& ~WR_PREFIX
;
14718 as_tsktsk (_("register list not in ascending order"));
14721 else if (wcg_register (reg
))
14723 i
= (reg
& ~WC_PREFIX
) - 8;
14725 as_tsktsk (_("register list not in ascending order"));
14726 wcg_mask
|= 1 << i
;
14730 as_bad (_("expected wr or wcgr"));
14734 SKIP_WHITESPACE ();
14735 if (*input_line_pointer
== '-')
14737 hi_reg
= arm_reg_parse (&input_line_pointer
,
14738 all_reg_maps
[REG_TYPE_IWMMXT
].htab
);
14739 if (wr_register (reg
) && wr_register (hi_reg
))
14741 for (; reg
< hi_reg
; reg
++)
14742 wr_mask
|= 1 << (reg
& ~WR_PREFIX
);
14744 else if (wcg_register (reg
) && wcg_register (hi_reg
))
14746 for (; reg
< hi_reg
; reg
++)
14747 wcg_mask
|= 1 << ((reg
& ~WC_PREFIX
) - 8);
14751 as_bad (_("bad register range"));
14756 while (skip_past_comma (&input_line_pointer
) != FAIL
);
14758 SKIP_WHITESPACE ();
14759 if (*input_line_pointer
== '}')
14760 input_line_pointer
++;
14762 demand_empty_rest_of_line ();
14764 if (wr_mask
&& wcg_mask
)
14766 as_bad (_("inconsistent register types"));
14770 /* Generate any deferred opcodes becuuse we're going to be looking at
14772 flush_pending_unwind ();
14776 for (i
= 0; i
< 16; i
++)
14778 if (wcg_mask
& (1 << i
))
14779 unwind
.frame_size
+= 4;
14781 op
= 0xc700 | wcg_mask
;
14782 add_unwind_opcode (op
, 2);
14786 for (i
= 0; i
< 16; i
++)
14788 if (wr_mask
& (1 << i
))
14789 unwind
.frame_size
+= 8;
14791 /* Attempt to combine with a previous opcode. We do this because gcc
14792 likes to output separate unwind directives for a single block of
14794 if (unwind
.opcode_count
> 0)
14796 i
= unwind
.opcodes
[unwind
.opcode_count
- 1];
14797 if ((i
& 0xf8) == 0xc0)
14800 /* Only merge if the blocks are contiguous. */
14803 if ((wr_mask
& 0xfe00) == (1 << 9))
14805 wr_mask
|= ((1 << (i
+ 11)) - 1) & 0xfc00;
14806 unwind
.opcode_count
--;
14809 else if (i
== 6 && unwind
.opcode_count
>= 2)
14811 i
= unwind
.opcodes
[unwind
.opcode_count
- 2];
14815 op
= 0xffff << (reg
- 1);
14817 || ((wr_mask
& op
) == (1u << (reg
- 1))))
14819 op
= (1 << (reg
+ i
+ 1)) - 1;
14820 op
&= ~((1 << reg
) - 1);
14822 unwind
.opcode_count
-= 2;
14829 /* We want to generate opcodes in the order the registers have been
14830 saved, ie. descending order. */
14831 for (reg
= 15; reg
>= -1; reg
--)
14833 /* Save registers in blocks. */
14835 || !(wr_mask
& (1 << reg
)))
14837 /* We found an unsaved reg. Generate opcodes to save the
14838 preceeding block. */
14844 op
= 0xc0 | (hi_reg
- 10);
14845 add_unwind_opcode (op
, 1);
14850 op
= 0xc600 | ((reg
+ 1) << 4) | ((hi_reg
- reg
) - 1);
14851 add_unwind_opcode (op
, 2);
14860 ignore_rest_of_line ();
14864 /* Parse an unwind_save directive. */
14867 s_arm_unwind_save (int ignored ATTRIBUTE_UNUSED
)
14872 /* Figure out what sort of save we have. */
14873 SKIP_WHITESPACE ();
14874 saved_ptr
= input_line_pointer
;
14876 reg
= arm_reg_parse (&input_line_pointer
, all_reg_maps
[REG_TYPE_FN
].htab
);
14879 s_arm_unwind_save_fpa (reg
);
14883 if (*input_line_pointer
== '{')
14884 input_line_pointer
++;
14886 SKIP_WHITESPACE ();
14888 reg
= arm_reg_parse (&input_line_pointer
, all_reg_maps
[REG_TYPE_RN
].htab
);
14891 input_line_pointer
= saved_ptr
;
14892 s_arm_unwind_save_core ();
14896 reg
= arm_reg_parse (&input_line_pointer
, all_reg_maps
[REG_TYPE_DN
].htab
);
14899 input_line_pointer
= saved_ptr
;
14900 s_arm_unwind_save_vfp ();
14904 reg
= arm_reg_parse (&input_line_pointer
,
14905 all_reg_maps
[REG_TYPE_IWMMXT
].htab
);
14908 input_line_pointer
= saved_ptr
;
14909 s_arm_unwind_save_wmmx ();
14913 /* TODO: Maverick registers. */
14914 as_bad (_("unrecognised register"));
14918 /* Parse an unwind_movsp directive. */
14921 s_arm_unwind_movsp (int ignored ATTRIBUTE_UNUSED
)
14926 SKIP_WHITESPACE ();
14927 reg
= reg_required_here (&input_line_pointer
, -1);
14930 as_bad (_("ARM register expected"));
14931 ignore_rest_of_line ();
14935 if (reg
== 13 || reg
== 15)
14937 as_bad (_("r%d not permitted in .unwind_movsp directive"), reg
);
14938 ignore_rest_of_line ();
14942 if (unwind
.fp_reg
!= 13)
14943 as_bad (_("unexpected .unwind_movsp directive"));
14945 /* Generate opcode to restore the value. */
14947 add_unwind_opcode (op
, 1);
14949 /* Record the information for later. */
14950 unwind
.fp_reg
= reg
;
14951 unwind
.fp_offset
= unwind
.frame_size
;
14952 unwind
.sp_restored
= 1;
14953 demand_empty_rest_of_line ();
14957 /* Parse #<number>. */
14960 require_hashconst (int * val
)
14964 SKIP_WHITESPACE ();
14965 if (*input_line_pointer
== '#')
14967 input_line_pointer
++;
14971 exp
.X_op
= O_illegal
;
14973 if (exp
.X_op
!= O_constant
)
14975 as_bad (_("expected #constant"));
14976 ignore_rest_of_line ();
14979 *val
= exp
.X_add_number
;
14983 /* Parse an unwind_pad directive. */
14986 s_arm_unwind_pad (int ignored ATTRIBUTE_UNUSED
)
14990 if (require_hashconst (&offset
) == FAIL
)
14995 as_bad (_("stack increment must be multiple of 4"));
14996 ignore_rest_of_line ();
15000 /* Don't generate any opcodes, just record the details for later. */
15001 unwind
.frame_size
+= offset
;
15002 unwind
.pending_offset
+= offset
;
15004 demand_empty_rest_of_line ();
15007 /* Parse an unwind_setfp directive. */
15010 s_arm_unwind_setfp (int ignored ATTRIBUTE_UNUSED
)
15016 fp_reg
= reg_required_here (&input_line_pointer
, -1);
15017 if (skip_past_comma (&input_line_pointer
) == FAIL
)
15020 sp_reg
= reg_required_here (&input_line_pointer
, -1);
15022 if (fp_reg
== FAIL
|| sp_reg
== FAIL
)
15024 as_bad (_("expected <reg>, <reg>"));
15025 ignore_rest_of_line ();
15029 /* Optonal constant. */
15030 if (skip_past_comma (&input_line_pointer
) != FAIL
)
15032 if (require_hashconst (&offset
) == FAIL
)
15038 demand_empty_rest_of_line ();
15040 if (sp_reg
!= 13 && sp_reg
!= unwind
.fp_reg
)
15042 as_bad (_("register must be either sp or set by a previous"
15043 "unwind_movsp directive"));
15047 /* Don't generate any opcodes, just record the information for later. */
15048 unwind
.fp_reg
= fp_reg
;
15049 unwind
.fp_used
= 1;
15051 unwind
.fp_offset
= unwind
.frame_size
- offset
;
15053 unwind
.fp_offset
-= offset
;
15056 /* Parse an unwind_raw directive. */
15059 s_arm_unwind_raw (int ignored ATTRIBUTE_UNUSED
)
15062 /* This is an arbitary limit. */
15063 unsigned char op
[16];
15066 SKIP_WHITESPACE ();
15068 if (exp
.X_op
== O_constant
15069 && skip_past_comma (&input_line_pointer
) != FAIL
)
15071 unwind
.frame_size
+= exp
.X_add_number
;
15075 exp
.X_op
= O_illegal
;
15077 if (exp
.X_op
!= O_constant
)
15079 as_bad (_("expected <offset>, <opcode>"));
15080 ignore_rest_of_line ();
15086 /* Parse the opcode. */
15091 as_bad (_("unwind opcode too long"));
15092 ignore_rest_of_line ();
15094 if (exp
.X_op
!= O_constant
|| exp
.X_add_number
& ~0xff)
15096 as_bad (_("invalid unwind opcode"));
15097 ignore_rest_of_line ();
15100 op
[count
++] = exp
.X_add_number
;
15102 /* Parse the next byte. */
15103 if (skip_past_comma (&input_line_pointer
) == FAIL
)
15109 /* Add the opcode bytes in reverse order. */
15111 add_unwind_opcode (op
[count
], 1);
15113 demand_empty_rest_of_line ();
15116 #endif /* OBJ_ELF */
15118 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
15119 of an rs_align_code fragment. */
15122 arm_handle_align (fragS
* fragP
)
15124 static char const arm_noop
[4] = { 0x00, 0x00, 0xa0, 0xe1 };
15125 static char const thumb_noop
[2] = { 0xc0, 0x46 };
15126 static char const arm_bigend_noop
[4] = { 0xe1, 0xa0, 0x00, 0x00 };
15127 static char const thumb_bigend_noop
[2] = { 0x46, 0xc0 };
15129 int bytes
, fix
, noop_size
;
15133 if (fragP
->fr_type
!= rs_align_code
)
15136 bytes
= fragP
->fr_next
->fr_address
- fragP
->fr_address
- fragP
->fr_fix
;
15137 p
= fragP
->fr_literal
+ fragP
->fr_fix
;
15140 if (bytes
> MAX_MEM_FOR_RS_ALIGN_CODE
)
15141 bytes
&= MAX_MEM_FOR_RS_ALIGN_CODE
;
15143 if (fragP
->tc_frag_data
)
15145 if (target_big_endian
)
15146 noop
= thumb_bigend_noop
;
15149 noop_size
= sizeof (thumb_noop
);
15153 if (target_big_endian
)
15154 noop
= arm_bigend_noop
;
15157 noop_size
= sizeof (arm_noop
);
15160 if (bytes
& (noop_size
- 1))
15162 fix
= bytes
& (noop_size
- 1);
15163 memset (p
, 0, fix
);
15168 while (bytes
>= noop_size
)
15170 memcpy (p
, noop
, noop_size
);
15172 bytes
-= noop_size
;
15176 fragP
->fr_fix
+= fix
;
15177 fragP
->fr_var
= noop_size
;
15180 /* Called from md_do_align. Used to create an alignment
15181 frag in a code section. */
15184 arm_frag_align_code (int n
, int max
)
15188 /* We assume that there will never be a requirement
15189 to support alignments greater than 32 bytes. */
15190 if (max
> MAX_MEM_FOR_RS_ALIGN_CODE
)
15191 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
15193 p
= frag_var (rs_align_code
,
15194 MAX_MEM_FOR_RS_ALIGN_CODE
,
15196 (relax_substateT
) max
,
15203 /* Perform target specific initialisation of a frag. */
15206 arm_init_frag (fragS
* fragP
)
15208 /* Record whether this frag is in an ARM or a THUMB area. */
15209 fragP
->tc_frag_data
= thumb_mode
;
15214 /* Convert REGNAME to a DWARF-2 register number. */
15217 tc_arm_regname_to_dw2regnum (const char *regname
)
15221 for (i
= 0; rn_table
[i
].name
; i
++)
15222 if (streq (regname
, rn_table
[i
].name
))
15223 return rn_table
[i
].number
;
15228 /* Initialize the DWARF-2 unwind information for this procedure. */
15231 tc_arm_frame_initial_instructions (void)
15233 cfi_add_CFA_def_cfa (REG_SP
, 0);
15237 /* This table describes all the machine specific pseudo-ops the assembler
15238 has to support. The fields are:
15239 pseudo-op name without dot
15240 function to call to execute this pseudo-op
15241 Integer arg to pass to the function. */
15243 const pseudo_typeS md_pseudo_table
[] =
15245 /* Never called because '.req' does not start a line. */
15246 { "req", s_req
, 0 },
15247 { "unreq", s_unreq
, 0 },
15248 { "bss", s_bss
, 0 },
15249 { "align", s_align
, 0 },
15250 { "arm", s_arm
, 0 },
15251 { "thumb", s_thumb
, 0 },
15252 { "code", s_code
, 0 },
15253 { "force_thumb", s_force_thumb
, 0 },
15254 { "thumb_func", s_thumb_func
, 0 },
15255 { "thumb_set", s_thumb_set
, 0 },
15256 { "even", s_even
, 0 },
15257 { "ltorg", s_ltorg
, 0 },
15258 { "pool", s_ltorg
, 0 },
15260 { "word", s_arm_elf_cons
, 4 },
15261 { "long", s_arm_elf_cons
, 4 },
15262 { "rel31", s_arm_rel31
, 0 },
15263 { "fnstart", s_arm_unwind_fnstart
, 0 },
15264 { "fnend", s_arm_unwind_fnend
, 0 },
15265 { "cantunwind", s_arm_unwind_cantunwind
, 0 },
15266 { "personality", s_arm_unwind_personality
, 0 },
15267 { "personalityindex", s_arm_unwind_personalityindex
, 0 },
15268 { "handlerdata", s_arm_unwind_handlerdata
, 0 },
15269 { "save", s_arm_unwind_save
, 0 },
15270 { "movsp", s_arm_unwind_movsp
, 0 },
15271 { "pad", s_arm_unwind_pad
, 0 },
15272 { "setfp", s_arm_unwind_setfp
, 0 },
15273 { "unwind_raw", s_arm_unwind_raw
, 0 },
15275 { "word", cons
, 4},
15277 { "extend", float_cons
, 'x' },
15278 { "ldouble", float_cons
, 'x' },
15279 { "packed", float_cons
, 'p' },