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;
95 /* Types of processor to assemble for. */
96 #define ARM_1 ARM_ARCH_V1
97 #define ARM_2 ARM_ARCH_V2
98 #define ARM_3 ARM_ARCH_V2S
99 #define ARM_250 ARM_ARCH_V2S
100 #define ARM_6 ARM_ARCH_V3
101 #define ARM_7 ARM_ARCH_V3
102 #define ARM_8 ARM_ARCH_V4
103 #define ARM_9 ARM_ARCH_V4T
104 #define ARM_STRONG ARM_ARCH_V4
105 #define ARM_CPU_MASK 0x0000000f /* XXX? */
108 #if defined __XSCALE__
109 #define CPU_DEFAULT (ARM_ARCH_XSCALE)
111 #if defined __thumb__
112 #define CPU_DEFAULT (ARM_ARCH_V5T)
114 #define CPU_DEFAULT ARM_ANY
121 # define FPU_DEFAULT FPU_ARCH_FPA
122 # elif defined (TE_NetBSD)
124 # define FPU_DEFAULT FPU_ARCH_VFP /* Soft-float, but VFP order. */
126 /* Legacy a.out format. */
127 # define FPU_DEFAULT FPU_ARCH_FPA /* Soft-float, but FPA order. */
129 # elif defined (TE_VXWORKS)
130 # define FPU_DEFAULT FPU_ARCH_VFP /* Soft-float, VFP order. */
132 /* For backwards compatibility, default to FPA. */
133 # define FPU_DEFAULT FPU_ARCH_FPA
135 #endif /* ifndef FPU_DEFAULT */
137 #define streq(a, b) (strcmp (a, b) == 0)
138 #define skip_whitespace(str) while (*(str) == ' ') ++(str)
140 static unsigned long cpu_variant
;
142 /* Flags stored in private area of BFD structure. */
143 static int uses_apcs_26
= FALSE
;
144 static int atpcs
= FALSE
;
145 static int support_interwork
= FALSE
;
146 static int uses_apcs_float
= FALSE
;
147 static int pic_code
= FALSE
;
149 /* Variables that we set while parsing command-line options. Once all
150 options have been read we re-process these values to set the real
152 static int legacy_cpu
= -1;
153 static int legacy_fpu
= -1;
155 static int mcpu_cpu_opt
= -1;
156 static int mcpu_fpu_opt
= -1;
157 static int march_cpu_opt
= -1;
158 static int march_fpu_opt
= -1;
159 static int mfpu_opt
= -1;
160 static int mfloat_abi_opt
= -1;
163 static int meabi_flags
= EABI_DEFAULT
;
165 static int meabi_flags
= EF_ARM_EABI_UNKNOWN
;
169 /* This array holds the chars that always start a comment. If the
170 pre-processor is disabled, these aren't very useful. */
171 const char comment_chars
[] = "@";
173 /* This array holds the chars that only start a comment at the beginning of
174 a line. If the line seems to have the form '# 123 filename'
175 .line and .file directives will appear in the pre-processed output. */
176 /* Note that input_file.c hand checks for '#' at the beginning of the
177 first line of the input file. This is because the compiler outputs
178 #NO_APP at the beginning of its output. */
179 /* Also note that comments like this one will always work. */
180 const char line_comment_chars
[] = "#";
182 const char line_separator_chars
[] = ";";
184 /* Chars that can be used to separate mant
185 from exp in floating point numbers. */
186 const char EXP_CHARS
[] = "eE";
188 /* Chars that mean this number is a floating point constant. */
192 const char FLT_CHARS
[] = "rRsSfFdDxXeEpP";
194 /* Prefix characters that indicate the start of an immediate
196 #define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
199 /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
200 symbolS
* GOT_symbol
;
203 /* Size of relocation record. */
204 const int md_reloc_size
= 8;
206 /* 0: assemble for ARM,
207 1: assemble for Thumb,
208 2: assemble for Thumb even though target CPU does not support thumb
210 static int thumb_mode
= 0;
212 typedef struct arm_fix
220 unsigned long instruction
;
224 bfd_reloc_code_real_type type
;
241 struct asm_shift_properties
243 enum asm_shift_index index
;
244 unsigned long bit_field
;
245 unsigned int allows_0
: 1;
246 unsigned int allows_32
: 1;
249 static const struct asm_shift_properties shift_properties
[] =
251 { SHIFT_LSL
, 0, 1, 0},
252 { SHIFT_LSR
, 0x20, 0, 1},
253 { SHIFT_ASR
, 0x40, 0, 1},
254 { SHIFT_ROR
, 0x60, 0, 0},
255 { SHIFT_RRX
, 0x60, 0, 0}
258 struct asm_shift_name
261 const struct asm_shift_properties
* properties
;
264 static const struct asm_shift_name shift_names
[] =
266 { "asl", shift_properties
+ SHIFT_LSL
},
267 { "lsl", shift_properties
+ SHIFT_LSL
},
268 { "lsr", shift_properties
+ SHIFT_LSR
},
269 { "asr", shift_properties
+ SHIFT_ASR
},
270 { "ror", shift_properties
+ SHIFT_ROR
},
271 { "rrx", shift_properties
+ SHIFT_RRX
},
272 { "ASL", shift_properties
+ SHIFT_LSL
},
273 { "LSL", shift_properties
+ SHIFT_LSL
},
274 { "LSR", shift_properties
+ SHIFT_LSR
},
275 { "ASR", shift_properties
+ SHIFT_ASR
},
276 { "ROR", shift_properties
+ SHIFT_ROR
},
277 { "RRX", shift_properties
+ SHIFT_RRX
}
280 /* Any kind of shift is accepted. */
281 #define NO_SHIFT_RESTRICT 1
282 /* The shift operand must be an immediate value, not a register. */
283 #define SHIFT_IMMEDIATE 0
284 /* The shift must be LSL or ASR and the operand must be an immediate. */
285 #define SHIFT_LSL_OR_ASR_IMMEDIATE 2
286 /* The shift must be ASR and the operand must be an immediate. */
287 #define SHIFT_ASR_IMMEDIATE 3
288 /* The shift must be LSL and the operand must be an immediate. */
289 #define SHIFT_LSL_IMMEDIATE 4
291 #define NUM_FLOAT_VALS 8
293 const char * fp_const
[] =
295 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
298 /* Number of littlenums required to hold an extended precision number. */
299 #define MAX_LITTLENUMS 6
301 LITTLENUM_TYPE fp_values
[NUM_FLOAT_VALS
][MAX_LITTLENUMS
];
306 /* Whether a Co-processor load/store operation accepts write-back forms. */
315 #define CP_T_X 0x00008000
316 #define CP_T_Y 0x00400000
317 #define CP_T_Pre 0x01000000
318 #define CP_T_UD 0x00800000
319 #define CP_T_WB 0x00200000
321 #define CONDS_BIT 0x00100000
322 #define LOAD_BIT 0x00100000
324 #define DOUBLE_LOAD_FLAG 0x00000001
328 const char * template;
332 #define COND_ALWAYS 0xe0000000
333 #define COND_MASK 0xf0000000
335 static const struct asm_cond conds
[] =
339 {"cs", 0x20000000}, {"hs", 0x20000000},
340 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
357 const char *template;
362 /* The bit that distinguishes CPSR and SPSR. */
363 #define SPSR_BIT (1 << 22)
365 /* How many bits to shift the PSR_xxx bits up by. */
368 #define PSR_c (1 << 0)
369 #define PSR_x (1 << 1)
370 #define PSR_s (1 << 2)
371 #define PSR_f (1 << 3)
373 static const struct asm_psr psrs
[] =
375 {"CPSR", TRUE
, PSR_c
| PSR_f
},
376 {"CPSR_all", TRUE
, PSR_c
| PSR_f
},
377 {"SPSR", FALSE
, PSR_c
| PSR_f
},
378 {"SPSR_all", FALSE
, PSR_c
| PSR_f
},
379 {"CPSR_flg", TRUE
, PSR_f
},
380 {"CPSR_f", TRUE
, PSR_f
},
381 {"SPSR_flg", FALSE
, PSR_f
},
382 {"SPSR_f", FALSE
, PSR_f
},
383 {"CPSR_c", TRUE
, PSR_c
},
384 {"CPSR_ctl", TRUE
, PSR_c
},
385 {"SPSR_c", FALSE
, PSR_c
},
386 {"SPSR_ctl", FALSE
, PSR_c
},
387 {"CPSR_x", TRUE
, PSR_x
},
388 {"CPSR_s", TRUE
, PSR_s
},
389 {"SPSR_x", FALSE
, PSR_x
},
390 {"SPSR_s", FALSE
, PSR_s
},
391 /* Combinations of flags. */
392 {"CPSR_fs", TRUE
, PSR_f
| PSR_s
},
393 {"CPSR_fx", TRUE
, PSR_f
| PSR_x
},
394 {"CPSR_fc", TRUE
, PSR_f
| PSR_c
},
395 {"CPSR_sf", TRUE
, PSR_s
| PSR_f
},
396 {"CPSR_sx", TRUE
, PSR_s
| PSR_x
},
397 {"CPSR_sc", TRUE
, PSR_s
| PSR_c
},
398 {"CPSR_xf", TRUE
, PSR_x
| PSR_f
},
399 {"CPSR_xs", TRUE
, PSR_x
| PSR_s
},
400 {"CPSR_xc", TRUE
, PSR_x
| PSR_c
},
401 {"CPSR_cf", TRUE
, PSR_c
| PSR_f
},
402 {"CPSR_cs", TRUE
, PSR_c
| PSR_s
},
403 {"CPSR_cx", TRUE
, PSR_c
| PSR_x
},
404 {"CPSR_fsx", TRUE
, PSR_f
| PSR_s
| PSR_x
},
405 {"CPSR_fsc", TRUE
, PSR_f
| PSR_s
| PSR_c
},
406 {"CPSR_fxs", TRUE
, PSR_f
| PSR_x
| PSR_s
},
407 {"CPSR_fxc", TRUE
, PSR_f
| PSR_x
| PSR_c
},
408 {"CPSR_fcs", TRUE
, PSR_f
| PSR_c
| PSR_s
},
409 {"CPSR_fcx", TRUE
, PSR_f
| PSR_c
| PSR_x
},
410 {"CPSR_sfx", TRUE
, PSR_s
| PSR_f
| PSR_x
},
411 {"CPSR_sfc", TRUE
, PSR_s
| PSR_f
| PSR_c
},
412 {"CPSR_sxf", TRUE
, PSR_s
| PSR_x
| PSR_f
},
413 {"CPSR_sxc", TRUE
, PSR_s
| PSR_x
| PSR_c
},
414 {"CPSR_scf", TRUE
, PSR_s
| PSR_c
| PSR_f
},
415 {"CPSR_scx", TRUE
, PSR_s
| PSR_c
| PSR_x
},
416 {"CPSR_xfs", TRUE
, PSR_x
| PSR_f
| PSR_s
},
417 {"CPSR_xfc", TRUE
, PSR_x
| PSR_f
| PSR_c
},
418 {"CPSR_xsf", TRUE
, PSR_x
| PSR_s
| PSR_f
},
419 {"CPSR_xsc", TRUE
, PSR_x
| PSR_s
| PSR_c
},
420 {"CPSR_xcf", TRUE
, PSR_x
| PSR_c
| PSR_f
},
421 {"CPSR_xcs", TRUE
, PSR_x
| PSR_c
| PSR_s
},
422 {"CPSR_cfs", TRUE
, PSR_c
| PSR_f
| PSR_s
},
423 {"CPSR_cfx", TRUE
, PSR_c
| PSR_f
| PSR_x
},
424 {"CPSR_csf", TRUE
, PSR_c
| PSR_s
| PSR_f
},
425 {"CPSR_csx", TRUE
, PSR_c
| PSR_s
| PSR_x
},
426 {"CPSR_cxf", TRUE
, PSR_c
| PSR_x
| PSR_f
},
427 {"CPSR_cxs", TRUE
, PSR_c
| PSR_x
| PSR_s
},
428 {"CPSR_fsxc", TRUE
, PSR_f
| PSR_s
| PSR_x
| PSR_c
},
429 {"CPSR_fscx", TRUE
, PSR_f
| PSR_s
| PSR_c
| PSR_x
},
430 {"CPSR_fxsc", TRUE
, PSR_f
| PSR_x
| PSR_s
| PSR_c
},
431 {"CPSR_fxcs", TRUE
, PSR_f
| PSR_x
| PSR_c
| PSR_s
},
432 {"CPSR_fcsx", TRUE
, PSR_f
| PSR_c
| PSR_s
| PSR_x
},
433 {"CPSR_fcxs", TRUE
, PSR_f
| PSR_c
| PSR_x
| PSR_s
},
434 {"CPSR_sfxc", TRUE
, PSR_s
| PSR_f
| PSR_x
| PSR_c
},
435 {"CPSR_sfcx", TRUE
, PSR_s
| PSR_f
| PSR_c
| PSR_x
},
436 {"CPSR_sxfc", TRUE
, PSR_s
| PSR_x
| PSR_f
| PSR_c
},
437 {"CPSR_sxcf", TRUE
, PSR_s
| PSR_x
| PSR_c
| PSR_f
},
438 {"CPSR_scfx", TRUE
, PSR_s
| PSR_c
| PSR_f
| PSR_x
},
439 {"CPSR_scxf", TRUE
, PSR_s
| PSR_c
| PSR_x
| PSR_f
},
440 {"CPSR_xfsc", TRUE
, PSR_x
| PSR_f
| PSR_s
| PSR_c
},
441 {"CPSR_xfcs", TRUE
, PSR_x
| PSR_f
| PSR_c
| PSR_s
},
442 {"CPSR_xsfc", TRUE
, PSR_x
| PSR_s
| PSR_f
| PSR_c
},
443 {"CPSR_xscf", TRUE
, PSR_x
| PSR_s
| PSR_c
| PSR_f
},
444 {"CPSR_xcfs", TRUE
, PSR_x
| PSR_c
| PSR_f
| PSR_s
},
445 {"CPSR_xcsf", TRUE
, PSR_x
| PSR_c
| PSR_s
| PSR_f
},
446 {"CPSR_cfsx", TRUE
, PSR_c
| PSR_f
| PSR_s
| PSR_x
},
447 {"CPSR_cfxs", TRUE
, PSR_c
| PSR_f
| PSR_x
| PSR_s
},
448 {"CPSR_csfx", TRUE
, PSR_c
| PSR_s
| PSR_f
| PSR_x
},
449 {"CPSR_csxf", TRUE
, PSR_c
| PSR_s
| PSR_x
| PSR_f
},
450 {"CPSR_cxfs", TRUE
, PSR_c
| PSR_x
| PSR_f
| PSR_s
},
451 {"CPSR_cxsf", TRUE
, PSR_c
| PSR_x
| PSR_s
| PSR_f
},
452 {"SPSR_fs", FALSE
, PSR_f
| PSR_s
},
453 {"SPSR_fx", FALSE
, PSR_f
| PSR_x
},
454 {"SPSR_fc", FALSE
, PSR_f
| PSR_c
},
455 {"SPSR_sf", FALSE
, PSR_s
| PSR_f
},
456 {"SPSR_sx", FALSE
, PSR_s
| PSR_x
},
457 {"SPSR_sc", FALSE
, PSR_s
| PSR_c
},
458 {"SPSR_xf", FALSE
, PSR_x
| PSR_f
},
459 {"SPSR_xs", FALSE
, PSR_x
| PSR_s
},
460 {"SPSR_xc", FALSE
, PSR_x
| PSR_c
},
461 {"SPSR_cf", FALSE
, PSR_c
| PSR_f
},
462 {"SPSR_cs", FALSE
, PSR_c
| PSR_s
},
463 {"SPSR_cx", FALSE
, PSR_c
| PSR_x
},
464 {"SPSR_fsx", FALSE
, PSR_f
| PSR_s
| PSR_x
},
465 {"SPSR_fsc", FALSE
, PSR_f
| PSR_s
| PSR_c
},
466 {"SPSR_fxs", FALSE
, PSR_f
| PSR_x
| PSR_s
},
467 {"SPSR_fxc", FALSE
, PSR_f
| PSR_x
| PSR_c
},
468 {"SPSR_fcs", FALSE
, PSR_f
| PSR_c
| PSR_s
},
469 {"SPSR_fcx", FALSE
, PSR_f
| PSR_c
| PSR_x
},
470 {"SPSR_sfx", FALSE
, PSR_s
| PSR_f
| PSR_x
},
471 {"SPSR_sfc", FALSE
, PSR_s
| PSR_f
| PSR_c
},
472 {"SPSR_sxf", FALSE
, PSR_s
| PSR_x
| PSR_f
},
473 {"SPSR_sxc", FALSE
, PSR_s
| PSR_x
| PSR_c
},
474 {"SPSR_scf", FALSE
, PSR_s
| PSR_c
| PSR_f
},
475 {"SPSR_scx", FALSE
, PSR_s
| PSR_c
| PSR_x
},
476 {"SPSR_xfs", FALSE
, PSR_x
| PSR_f
| PSR_s
},
477 {"SPSR_xfc", FALSE
, PSR_x
| PSR_f
| PSR_c
},
478 {"SPSR_xsf", FALSE
, PSR_x
| PSR_s
| PSR_f
},
479 {"SPSR_xsc", FALSE
, PSR_x
| PSR_s
| PSR_c
},
480 {"SPSR_xcf", FALSE
, PSR_x
| PSR_c
| PSR_f
},
481 {"SPSR_xcs", FALSE
, PSR_x
| PSR_c
| PSR_s
},
482 {"SPSR_cfs", FALSE
, PSR_c
| PSR_f
| PSR_s
},
483 {"SPSR_cfx", FALSE
, PSR_c
| PSR_f
| PSR_x
},
484 {"SPSR_csf", FALSE
, PSR_c
| PSR_s
| PSR_f
},
485 {"SPSR_csx", FALSE
, PSR_c
| PSR_s
| PSR_x
},
486 {"SPSR_cxf", FALSE
, PSR_c
| PSR_x
| PSR_f
},
487 {"SPSR_cxs", FALSE
, PSR_c
| PSR_x
| PSR_s
},
488 {"SPSR_fsxc", FALSE
, PSR_f
| PSR_s
| PSR_x
| PSR_c
},
489 {"SPSR_fscx", FALSE
, PSR_f
| PSR_s
| PSR_c
| PSR_x
},
490 {"SPSR_fxsc", FALSE
, PSR_f
| PSR_x
| PSR_s
| PSR_c
},
491 {"SPSR_fxcs", FALSE
, PSR_f
| PSR_x
| PSR_c
| PSR_s
},
492 {"SPSR_fcsx", FALSE
, PSR_f
| PSR_c
| PSR_s
| PSR_x
},
493 {"SPSR_fcxs", FALSE
, PSR_f
| PSR_c
| PSR_x
| PSR_s
},
494 {"SPSR_sfxc", FALSE
, PSR_s
| PSR_f
| PSR_x
| PSR_c
},
495 {"SPSR_sfcx", FALSE
, PSR_s
| PSR_f
| PSR_c
| PSR_x
},
496 {"SPSR_sxfc", FALSE
, PSR_s
| PSR_x
| PSR_f
| PSR_c
},
497 {"SPSR_sxcf", FALSE
, PSR_s
| PSR_x
| PSR_c
| PSR_f
},
498 {"SPSR_scfx", FALSE
, PSR_s
| PSR_c
| PSR_f
| PSR_x
},
499 {"SPSR_scxf", FALSE
, PSR_s
| PSR_c
| PSR_x
| PSR_f
},
500 {"SPSR_xfsc", FALSE
, PSR_x
| PSR_f
| PSR_s
| PSR_c
},
501 {"SPSR_xfcs", FALSE
, PSR_x
| PSR_f
| PSR_c
| PSR_s
},
502 {"SPSR_xsfc", FALSE
, PSR_x
| PSR_s
| PSR_f
| PSR_c
},
503 {"SPSR_xscf", FALSE
, PSR_x
| PSR_s
| PSR_c
| PSR_f
},
504 {"SPSR_xcfs", FALSE
, PSR_x
| PSR_c
| PSR_f
| PSR_s
},
505 {"SPSR_xcsf", FALSE
, PSR_x
| PSR_c
| PSR_s
| PSR_f
},
506 {"SPSR_cfsx", FALSE
, PSR_c
| PSR_f
| PSR_s
| PSR_x
},
507 {"SPSR_cfxs", FALSE
, PSR_c
| PSR_f
| PSR_x
| PSR_s
},
508 {"SPSR_csfx", FALSE
, PSR_c
| PSR_s
| PSR_f
| PSR_x
},
509 {"SPSR_csxf", FALSE
, PSR_c
| PSR_s
| PSR_x
| PSR_f
},
510 {"SPSR_cxfs", FALSE
, PSR_c
| PSR_x
| PSR_f
| PSR_s
},
511 {"SPSR_cxsf", FALSE
, PSR_c
| PSR_x
| PSR_s
| PSR_f
},
518 IWMMXT_REG_WR_OR_WC
= 2,
522 enum iwmmxt_insn_type
545 VFP_REG_Dd
, VFP_REG_Dm
, VFP_REG_Dn
550 VFP_REG_Sd
, VFP_REG_Sm
, VFP_REG_Sn
555 VFP_LDSTMIA
, VFP_LDSTMDB
, VFP_LDSTMIAX
, VFP_LDSTMDBX
558 /* VFP system registers. */
565 static const struct vfp_reg vfp_regs
[] =
567 {"fpsid", 0x00000000},
568 {"FPSID", 0x00000000},
569 {"fpscr", 0x00010000},
570 {"FPSCR", 0x00010000},
571 {"fpexc", 0x00080000},
572 {"FPEXC", 0x00080000}
575 /* Structure for a hash table entry for a register. */
583 /* Some well known registers that we refer to directly elsewhere. */
588 #define wr_register(reg) ((reg ^ WR_PREFIX) >= 0 && (reg ^ WR_PREFIX) <= 15)
589 #define wc_register(reg) ((reg ^ WC_PREFIX) >= 0 && (reg ^ WC_PREFIX) <= 15)
590 #define wcg_register(reg) ((reg ^ WC_PREFIX) >= 8 && (reg ^ WC_PREFIX) <= 11)
592 /* These are the standard names. Users can add aliases with .req.
593 and delete them with .unreq. */
595 /* Integer Register Numbers. */
596 static const struct reg_entry rn_table
[] =
598 {"r0", 0, TRUE
}, {"r1", 1, TRUE
}, {"r2", 2, TRUE
}, {"r3", 3, TRUE
},
599 {"r4", 4, TRUE
}, {"r5", 5, TRUE
}, {"r6", 6, TRUE
}, {"r7", 7, TRUE
},
600 {"r8", 8, TRUE
}, {"r9", 9, TRUE
}, {"r10", 10, TRUE
}, {"r11", 11, TRUE
},
601 {"r12", 12, TRUE
}, {"r13", REG_SP
, TRUE
}, {"r14", REG_LR
, TRUE
}, {"r15", REG_PC
, TRUE
},
602 /* ATPCS Synonyms. */
603 {"a1", 0, TRUE
}, {"a2", 1, TRUE
}, {"a3", 2, TRUE
}, {"a4", 3, TRUE
},
604 {"v1", 4, TRUE
}, {"v2", 5, TRUE
}, {"v3", 6, TRUE
}, {"v4", 7, TRUE
},
605 {"v5", 8, TRUE
}, {"v6", 9, TRUE
}, {"v7", 10, TRUE
}, {"v8", 11, TRUE
},
606 /* Well-known aliases. */
607 {"wr", 7, TRUE
}, {"sb", 9, TRUE
}, {"sl", 10, TRUE
}, {"fp", 11, TRUE
},
608 {"ip", 12, TRUE
}, {"sp", REG_SP
, TRUE
}, {"lr", REG_LR
, TRUE
}, {"pc", REG_PC
, TRUE
},
612 #define WR_PREFIX 0x200
613 #define WC_PREFIX 0x400
615 static const struct reg_entry iwmmxt_table
[] =
617 /* Intel Wireless MMX technology register names. */
618 { "wr0", 0x0 | WR_PREFIX
, TRUE
}, {"wr1", 0x1 | WR_PREFIX
, TRUE
},
619 { "wr2", 0x2 | WR_PREFIX
, TRUE
}, {"wr3", 0x3 | WR_PREFIX
, TRUE
},
620 { "wr4", 0x4 | WR_PREFIX
, TRUE
}, {"wr5", 0x5 | WR_PREFIX
, TRUE
},
621 { "wr6", 0x6 | WR_PREFIX
, TRUE
}, {"wr7", 0x7 | WR_PREFIX
, TRUE
},
622 { "wr8", 0x8 | WR_PREFIX
, TRUE
}, {"wr9", 0x9 | WR_PREFIX
, TRUE
},
623 { "wr10", 0xa | WR_PREFIX
, TRUE
}, {"wr11", 0xb | WR_PREFIX
, TRUE
},
624 { "wr12", 0xc | WR_PREFIX
, TRUE
}, {"wr13", 0xd | WR_PREFIX
, TRUE
},
625 { "wr14", 0xe | WR_PREFIX
, TRUE
}, {"wr15", 0xf | WR_PREFIX
, TRUE
},
626 { "wcid", 0x0 | WC_PREFIX
, TRUE
}, {"wcon", 0x1 | WC_PREFIX
, TRUE
},
627 {"wcssf", 0x2 | WC_PREFIX
, TRUE
}, {"wcasf", 0x3 | WC_PREFIX
, TRUE
},
628 {"wcgr0", 0x8 | WC_PREFIX
, TRUE
}, {"wcgr1", 0x9 | WC_PREFIX
, TRUE
},
629 {"wcgr2", 0xa | WC_PREFIX
, TRUE
}, {"wcgr3", 0xb | WC_PREFIX
, TRUE
},
631 { "wR0", 0x0 | WR_PREFIX
, TRUE
}, {"wR1", 0x1 | WR_PREFIX
, TRUE
},
632 { "wR2", 0x2 | WR_PREFIX
, TRUE
}, {"wR3", 0x3 | WR_PREFIX
, TRUE
},
633 { "wR4", 0x4 | WR_PREFIX
, TRUE
}, {"wR5", 0x5 | WR_PREFIX
, TRUE
},
634 { "wR6", 0x6 | WR_PREFIX
, TRUE
}, {"wR7", 0x7 | WR_PREFIX
, TRUE
},
635 { "wR8", 0x8 | WR_PREFIX
, TRUE
}, {"wR9", 0x9 | WR_PREFIX
, TRUE
},
636 { "wR10", 0xa | WR_PREFIX
, TRUE
}, {"wR11", 0xb | WR_PREFIX
, TRUE
},
637 { "wR12", 0xc | WR_PREFIX
, TRUE
}, {"wR13", 0xd | WR_PREFIX
, TRUE
},
638 { "wR14", 0xe | WR_PREFIX
, TRUE
}, {"wR15", 0xf | WR_PREFIX
, TRUE
},
639 { "wCID", 0x0 | WC_PREFIX
, TRUE
}, {"wCon", 0x1 | WC_PREFIX
, TRUE
},
640 {"wCSSF", 0x2 | WC_PREFIX
, TRUE
}, {"wCASF", 0x3 | WC_PREFIX
, TRUE
},
641 {"wCGR0", 0x8 | WC_PREFIX
, TRUE
}, {"wCGR1", 0x9 | WC_PREFIX
, TRUE
},
642 {"wCGR2", 0xa | WC_PREFIX
, TRUE
}, {"wCGR3", 0xb | WC_PREFIX
, TRUE
},
646 /* Co-processor Numbers. */
647 static const struct reg_entry cp_table
[] =
649 {"p0", 0, TRUE
}, {"p1", 1, TRUE
}, {"p2", 2, TRUE
}, {"p3", 3, TRUE
},
650 {"p4", 4, TRUE
}, {"p5", 5, TRUE
}, {"p6", 6, TRUE
}, {"p7", 7, TRUE
},
651 {"p8", 8, TRUE
}, {"p9", 9, TRUE
}, {"p10", 10, TRUE
}, {"p11", 11, TRUE
},
652 {"p12", 12, TRUE
}, {"p13", 13, TRUE
}, {"p14", 14, TRUE
}, {"p15", 15, TRUE
},
656 /* Co-processor Register Numbers. */
657 static const struct reg_entry cn_table
[] =
659 {"c0", 0, TRUE
}, {"c1", 1, TRUE
}, {"c2", 2, TRUE
}, {"c3", 3, TRUE
},
660 {"c4", 4, TRUE
}, {"c5", 5, TRUE
}, {"c6", 6, TRUE
}, {"c7", 7, TRUE
},
661 {"c8", 8, TRUE
}, {"c9", 9, TRUE
}, {"c10", 10, TRUE
}, {"c11", 11, TRUE
},
662 {"c12", 12, TRUE
}, {"c13", 13, TRUE
}, {"c14", 14, TRUE
}, {"c15", 15, TRUE
},
663 /* Not really valid, but kept for back-wards compatibility. */
664 {"cr0", 0, TRUE
}, {"cr1", 1, TRUE
}, {"cr2", 2, TRUE
}, {"cr3", 3, TRUE
},
665 {"cr4", 4, TRUE
}, {"cr5", 5, TRUE
}, {"cr6", 6, TRUE
}, {"cr7", 7, TRUE
},
666 {"cr8", 8, TRUE
}, {"cr9", 9, TRUE
}, {"cr10", 10, TRUE
}, {"cr11", 11, TRUE
},
667 {"cr12", 12, TRUE
}, {"cr13", 13, TRUE
}, {"cr14", 14, TRUE
}, {"cr15", 15, TRUE
},
672 static const struct reg_entry fn_table
[] =
674 {"f0", 0, TRUE
}, {"f1", 1, TRUE
}, {"f2", 2, TRUE
}, {"f3", 3, TRUE
},
675 {"f4", 4, TRUE
}, {"f5", 5, TRUE
}, {"f6", 6, TRUE
}, {"f7", 7, TRUE
},
679 /* VFP SP Registers. */
680 static const struct reg_entry sn_table
[] =
682 {"s0", 0, TRUE
}, {"s1", 1, TRUE
}, {"s2", 2, TRUE
}, {"s3", 3, TRUE
},
683 {"s4", 4, TRUE
}, {"s5", 5, TRUE
}, {"s6", 6, TRUE
}, {"s7", 7, TRUE
},
684 {"s8", 8, TRUE
}, {"s9", 9, TRUE
}, {"s10", 10, TRUE
}, {"s11", 11, TRUE
},
685 {"s12", 12, TRUE
}, {"s13", 13, TRUE
}, {"s14", 14, TRUE
}, {"s15", 15, TRUE
},
686 {"s16", 16, TRUE
}, {"s17", 17, TRUE
}, {"s18", 18, TRUE
}, {"s19", 19, TRUE
},
687 {"s20", 20, TRUE
}, {"s21", 21, TRUE
}, {"s22", 22, TRUE
}, {"s23", 23, TRUE
},
688 {"s24", 24, TRUE
}, {"s25", 25, TRUE
}, {"s26", 26, TRUE
}, {"s27", 27, TRUE
},
689 {"s28", 28, TRUE
}, {"s29", 29, TRUE
}, {"s30", 30, TRUE
}, {"s31", 31, TRUE
},
693 /* VFP DP Registers. */
694 static const struct reg_entry dn_table
[] =
696 {"d0", 0, TRUE
}, {"d1", 1, TRUE
}, {"d2", 2, TRUE
}, {"d3", 3, TRUE
},
697 {"d4", 4, TRUE
}, {"d5", 5, TRUE
}, {"d6", 6, TRUE
}, {"d7", 7, TRUE
},
698 {"d8", 8, TRUE
}, {"d9", 9, TRUE
}, {"d10", 10, TRUE
}, {"d11", 11, TRUE
},
699 {"d12", 12, TRUE
}, {"d13", 13, TRUE
}, {"d14", 14, TRUE
}, {"d15", 15, TRUE
},
703 /* Maverick DSP coprocessor registers. */
704 static const struct reg_entry mav_mvf_table
[] =
706 {"mvf0", 0, TRUE
}, {"mvf1", 1, TRUE
}, {"mvf2", 2, TRUE
}, {"mvf3", 3, TRUE
},
707 {"mvf4", 4, TRUE
}, {"mvf5", 5, TRUE
}, {"mvf6", 6, TRUE
}, {"mvf7", 7, TRUE
},
708 {"mvf8", 8, TRUE
}, {"mvf9", 9, TRUE
}, {"mvf10", 10, TRUE
}, {"mvf11", 11, TRUE
},
709 {"mvf12", 12, TRUE
}, {"mvf13", 13, TRUE
}, {"mvf14", 14, TRUE
}, {"mvf15", 15, TRUE
},
713 static const struct reg_entry mav_mvd_table
[] =
715 {"mvd0", 0, TRUE
}, {"mvd1", 1, TRUE
}, {"mvd2", 2, TRUE
}, {"mvd3", 3, TRUE
},
716 {"mvd4", 4, TRUE
}, {"mvd5", 5, TRUE
}, {"mvd6", 6, TRUE
}, {"mvd7", 7, TRUE
},
717 {"mvd8", 8, TRUE
}, {"mvd9", 9, TRUE
}, {"mvd10", 10, TRUE
}, {"mvd11", 11, TRUE
},
718 {"mvd12", 12, TRUE
}, {"mvd13", 13, TRUE
}, {"mvd14", 14, TRUE
}, {"mvd15", 15, TRUE
},
722 static const struct reg_entry mav_mvfx_table
[] =
724 {"mvfx0", 0, TRUE
}, {"mvfx1", 1, TRUE
}, {"mvfx2", 2, TRUE
}, {"mvfx3", 3, TRUE
},
725 {"mvfx4", 4, TRUE
}, {"mvfx5", 5, TRUE
}, {"mvfx6", 6, TRUE
}, {"mvfx7", 7, TRUE
},
726 {"mvfx8", 8, TRUE
}, {"mvfx9", 9, TRUE
}, {"mvfx10", 10, TRUE
}, {"mvfx11", 11, TRUE
},
727 {"mvfx12", 12, TRUE
}, {"mvfx13", 13, TRUE
}, {"mvfx14", 14, TRUE
}, {"mvfx15", 15, TRUE
},
731 static const struct reg_entry mav_mvdx_table
[] =
733 {"mvdx0", 0, TRUE
}, {"mvdx1", 1, TRUE
}, {"mvdx2", 2, TRUE
}, {"mvdx3", 3, TRUE
},
734 {"mvdx4", 4, TRUE
}, {"mvdx5", 5, TRUE
}, {"mvdx6", 6, TRUE
}, {"mvdx7", 7, TRUE
},
735 {"mvdx8", 8, TRUE
}, {"mvdx9", 9, TRUE
}, {"mvdx10", 10, TRUE
}, {"mvdx11", 11, TRUE
},
736 {"mvdx12", 12, TRUE
}, {"mvdx13", 13, TRUE
}, {"mvdx14", 14, TRUE
}, {"mvdx15", 15, TRUE
},
740 static const struct reg_entry mav_mvax_table
[] =
742 {"mvax0", 0, TRUE
}, {"mvax1", 1, TRUE
}, {"mvax2", 2, TRUE
}, {"mvax3", 3, TRUE
},
746 static const struct reg_entry mav_dspsc_table
[] =
754 const struct reg_entry
* names
;
756 struct hash_control
* htab
;
757 const char * expected
;
760 struct reg_map all_reg_maps
[] =
762 {rn_table
, 15, NULL
, N_("ARM register expected")},
763 {cp_table
, 15, NULL
, N_("bad or missing co-processor number")},
764 {cn_table
, 15, NULL
, N_("co-processor register expected")},
765 {fn_table
, 7, NULL
, N_("FPA register expected")},
766 {sn_table
, 31, NULL
, N_("VFP single precision register expected")},
767 {dn_table
, 15, NULL
, N_("VFP double precision register expected")},
768 {mav_mvf_table
, 15, NULL
, N_("Maverick MVF register expected")},
769 {mav_mvd_table
, 15, NULL
, N_("Maverick MVD register expected")},
770 {mav_mvfx_table
, 15, NULL
, N_("Maverick MVFX register expected")},
771 {mav_mvdx_table
, 15, NULL
, N_("Maverick MVDX register expected")},
772 {mav_mvax_table
, 3, NULL
, N_("Maverick MVAX register expected")},
773 {mav_dspsc_table
, 0, NULL
, N_("Maverick DSPSC register expected")},
774 {iwmmxt_table
, 23, NULL
, N_("Intel Wireless MMX technology register expected")},
777 /* Enumeration matching entries in table above. */
781 #define REG_TYPE_FIRST REG_TYPE_RN
793 REG_TYPE_IWMMXT
= 12,
798 /* ARM instructions take 4bytes in the object file, Thumb instructions
802 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
803 #define MAV_MODE1 0x100c
805 /* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
806 #define MAV_MODE2 0x0c10
808 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
809 #define MAV_MODE3 0x100c
811 /* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
812 #define MAV_MODE4 0x0c0010
814 /* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
815 #define MAV_MODE5 0x00100c
817 /* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
818 #define MAV_MODE6 0x00100c05
822 /* Basic string to match. */
823 const char * template;
825 /* Basic instruction code. */
828 /* Offset into the template where the condition code (if any) will be.
829 If zero, then the instruction is never conditional. */
830 unsigned cond_offset
;
832 /* Which architecture variant provides this instruction. */
833 unsigned long variant
;
835 /* Function to call to parse args. */
836 void (* parms
) (char *);
839 /* Defines for various bits that we will want to toggle. */
840 #define INST_IMMEDIATE 0x02000000
841 #define OFFSET_REG 0x02000000
842 #define HWOFFSET_IMM 0x00400000
843 #define SHIFT_BY_REG 0x00000010
844 #define PRE_INDEX 0x01000000
845 #define INDEX_UP 0x00800000
846 #define WRITE_BACK 0x00200000
847 #define LDM_TYPE_2_OR_3 0x00400000
849 #define LITERAL_MASK 0xf000f000
850 #define OPCODE_MASK 0xfe1fffff
851 #define V4_STR_BIT 0x00000020
853 #define DATA_OP_SHIFT 21
855 /* Codes to distinguish the arithmetic instructions. */
866 #define OPCODE_CMP 10
867 #define OPCODE_CMN 11
868 #define OPCODE_ORR 12
869 #define OPCODE_MOV 13
870 #define OPCODE_BIC 14
871 #define OPCODE_MVN 15
873 #define T_OPCODE_MUL 0x4340
874 #define T_OPCODE_TST 0x4200
875 #define T_OPCODE_CMN 0x42c0
876 #define T_OPCODE_NEG 0x4240
877 #define T_OPCODE_MVN 0x43c0
879 #define T_OPCODE_ADD_R3 0x1800
880 #define T_OPCODE_SUB_R3 0x1a00
881 #define T_OPCODE_ADD_HI 0x4400
882 #define T_OPCODE_ADD_ST 0xb000
883 #define T_OPCODE_SUB_ST 0xb080
884 #define T_OPCODE_ADD_SP 0xa800
885 #define T_OPCODE_ADD_PC 0xa000
886 #define T_OPCODE_ADD_I8 0x3000
887 #define T_OPCODE_SUB_I8 0x3800
888 #define T_OPCODE_ADD_I3 0x1c00
889 #define T_OPCODE_SUB_I3 0x1e00
891 #define T_OPCODE_ASR_R 0x4100
892 #define T_OPCODE_LSL_R 0x4080
893 #define T_OPCODE_LSR_R 0x40c0
894 #define T_OPCODE_ASR_I 0x1000
895 #define T_OPCODE_LSL_I 0x0000
896 #define T_OPCODE_LSR_I 0x0800
898 #define T_OPCODE_MOV_I8 0x2000
899 #define T_OPCODE_CMP_I8 0x2800
900 #define T_OPCODE_CMP_LR 0x4280
901 #define T_OPCODE_MOV_HR 0x4600
902 #define T_OPCODE_CMP_HR 0x4500
904 #define T_OPCODE_LDR_PC 0x4800
905 #define T_OPCODE_LDR_SP 0x9800
906 #define T_OPCODE_STR_SP 0x9000
907 #define T_OPCODE_LDR_IW 0x6800
908 #define T_OPCODE_STR_IW 0x6000
909 #define T_OPCODE_LDR_IH 0x8800
910 #define T_OPCODE_STR_IH 0x8000
911 #define T_OPCODE_LDR_IB 0x7800
912 #define T_OPCODE_STR_IB 0x7000
913 #define T_OPCODE_LDR_RW 0x5800
914 #define T_OPCODE_STR_RW 0x5000
915 #define T_OPCODE_LDR_RH 0x5a00
916 #define T_OPCODE_STR_RH 0x5200
917 #define T_OPCODE_LDR_RB 0x5c00
918 #define T_OPCODE_STR_RB 0x5400
920 #define T_OPCODE_PUSH 0xb400
921 #define T_OPCODE_POP 0xbc00
923 #define T_OPCODE_BRANCH 0xe7fe
925 #define THUMB_SIZE 2 /* Size of thumb instruction. */
926 #define THUMB_REG_LO 0x1
927 #define THUMB_REG_HI 0x2
928 #define THUMB_REG_ANY 0x3
930 #define THUMB_H1 0x0080
931 #define THUMB_H2 0x0040
938 #define THUMB_COMPARE 1
942 #define THUMB_STORE 1
944 #define THUMB_PP_PC_LR 0x0100
946 /* These three are used for immediate shifts, do not alter. */
948 #define THUMB_HALFWORD 1
953 /* Basic string to match. */
954 const char * template;
956 /* Basic instruction code. */
961 /* Which CPU variants this exists for. */
962 unsigned long variant
;
964 /* Function to call to parse args. */
965 void (* parms
) (char *);
968 #define BAD_ARGS _("bad arguments to instruction")
969 #define BAD_PC _("r15 not allowed here")
970 #define BAD_COND _("instruction is not conditional")
971 #define ERR_NO_ACCUM _("acc0 expected")
973 static struct hash_control
* arm_ops_hsh
= NULL
;
974 static struct hash_control
* arm_tops_hsh
= NULL
;
975 static struct hash_control
* arm_cond_hsh
= NULL
;
976 static struct hash_control
* arm_shift_hsh
= NULL
;
977 static struct hash_control
* arm_psr_hsh
= NULL
;
979 /* Stuff needed to resolve the label ambiguity
989 symbolS
* last_label_seen
;
990 static int label_is_thumb_function_name
= FALSE
;
992 /* Literal Pool stuff. */
994 #define MAX_LITERAL_POOL_SIZE 1024
996 /* Literal pool structure. Held on a per-section
997 and per-sub-section basis. */
999 typedef struct literal_pool
1001 expressionS literals
[MAX_LITERAL_POOL_SIZE
];
1002 unsigned int next_free_entry
;
1006 subsegT sub_section
;
1007 struct literal_pool
* next
;
1010 /* Pointer to a linked list of literal pools. */
1011 literal_pool
* list_of_pools
= NULL
;
1013 static literal_pool
*
1014 find_literal_pool (void)
1016 literal_pool
* pool
;
1018 for (pool
= list_of_pools
; pool
!= NULL
; pool
= pool
->next
)
1020 if (pool
->section
== now_seg
1021 && pool
->sub_section
== now_subseg
)
1028 static literal_pool
*
1029 find_or_make_literal_pool (void)
1031 /* Next literal pool ID number. */
1032 static unsigned int latest_pool_num
= 1;
1033 literal_pool
* pool
;
1035 pool
= find_literal_pool ();
1039 /* Create a new pool. */
1040 pool
= xmalloc (sizeof (* pool
));
1044 pool
->next_free_entry
= 0;
1045 pool
->section
= now_seg
;
1046 pool
->sub_section
= now_subseg
;
1047 pool
->next
= list_of_pools
;
1048 pool
->symbol
= NULL
;
1050 /* Add it to the list. */
1051 list_of_pools
= pool
;
1054 /* New pools, and emptied pools, will have a NULL symbol. */
1055 if (pool
->symbol
== NULL
)
1057 pool
->symbol
= symbol_create (FAKE_LABEL_NAME
, undefined_section
,
1058 (valueT
) 0, &zero_address_frag
);
1059 pool
->id
= latest_pool_num
++;
1066 /* Add the literal in the global 'inst'
1067 structure to the relevent literal pool. */
1070 add_to_lit_pool (void)
1072 literal_pool
* pool
;
1075 pool
= find_or_make_literal_pool ();
1077 /* Check if this literal value is already in the pool. */
1078 for (entry
= 0; entry
< pool
->next_free_entry
; entry
++)
1080 if ((pool
->literals
[entry
].X_op
== inst
.reloc
.exp
.X_op
)
1081 && (inst
.reloc
.exp
.X_op
== O_constant
)
1082 && (pool
->literals
[entry
].X_add_number
1083 == inst
.reloc
.exp
.X_add_number
)
1084 && (pool
->literals
[entry
].X_unsigned
1085 == inst
.reloc
.exp
.X_unsigned
))
1088 if ((pool
->literals
[entry
].X_op
== inst
.reloc
.exp
.X_op
)
1089 && (inst
.reloc
.exp
.X_op
== O_symbol
)
1090 && (pool
->literals
[entry
].X_add_number
1091 == inst
.reloc
.exp
.X_add_number
)
1092 && (pool
->literals
[entry
].X_add_symbol
1093 == inst
.reloc
.exp
.X_add_symbol
)
1094 && (pool
->literals
[entry
].X_op_symbol
1095 == inst
.reloc
.exp
.X_op_symbol
))
1099 /* Do we need to create a new entry? */
1100 if (entry
== pool
->next_free_entry
)
1102 if (entry
>= MAX_LITERAL_POOL_SIZE
)
1104 inst
.error
= _("literal pool overflow");
1108 pool
->literals
[entry
] = inst
.reloc
.exp
;
1109 pool
->next_free_entry
+= 1;
1112 inst
.reloc
.exp
.X_op
= O_symbol
;
1113 inst
.reloc
.exp
.X_add_number
= ((int) entry
) * 4 - 8;
1114 inst
.reloc
.exp
.X_add_symbol
= pool
->symbol
;
1119 /* Can't use symbol_new here, so have to create a symbol and then at
1120 a later date assign it a value. Thats what these functions do. */
1123 symbol_locate (symbolS
* symbolP
,
1124 const char * name
, /* It is copied, the caller can modify. */
1125 segT segment
, /* Segment identifier (SEG_<something>). */
1126 valueT valu
, /* Symbol value. */
1127 fragS
* frag
) /* Associated fragment. */
1129 unsigned int name_length
;
1130 char * preserved_copy_of_name
;
1132 name_length
= strlen (name
) + 1; /* +1 for \0. */
1133 obstack_grow (¬es
, name
, name_length
);
1134 preserved_copy_of_name
= obstack_finish (¬es
);
1135 #ifdef STRIP_UNDERSCORE
1136 if (preserved_copy_of_name
[0] == '_')
1137 preserved_copy_of_name
++;
1140 #ifdef tc_canonicalize_symbol_name
1141 preserved_copy_of_name
=
1142 tc_canonicalize_symbol_name (preserved_copy_of_name
);
1145 S_SET_NAME (symbolP
, preserved_copy_of_name
);
1147 S_SET_SEGMENT (symbolP
, segment
);
1148 S_SET_VALUE (symbolP
, valu
);
1149 symbol_clear_list_pointers (symbolP
);
1151 symbol_set_frag (symbolP
, frag
);
1153 /* Link to end of symbol chain. */
1155 extern int symbol_table_frozen
;
1157 if (symbol_table_frozen
)
1161 symbol_append (symbolP
, symbol_lastP
, & symbol_rootP
, & symbol_lastP
);
1163 obj_symbol_new_hook (symbolP
);
1165 #ifdef tc_symbol_new_hook
1166 tc_symbol_new_hook (symbolP
);
1170 verify_symbol_chain (symbol_rootP
, symbol_lastP
);
1171 #endif /* DEBUG_SYMS */
1174 /* Check that an immediate is valid.
1175 If so, convert it to the right format. */
1178 validate_immediate (unsigned int val
)
1183 #define rotate_left(v, n) (v << n | v >> (32 - n))
1185 for (i
= 0; i
< 32; i
+= 2)
1186 if ((a
= rotate_left (val
, i
)) <= 0xff)
1187 return a
| (i
<< 7); /* 12-bit pack: [shift-cnt,const]. */
1192 /* Check to see if an immediate can be computed as two separate immediate
1193 values, added together. We already know that this value cannot be
1194 computed by just one ARM instruction. */
1197 validate_immediate_twopart (unsigned int val
,
1198 unsigned int * highpart
)
1203 for (i
= 0; i
< 32; i
+= 2)
1204 if (((a
= rotate_left (val
, i
)) & 0xff) != 0)
1210 * highpart
= (a
>> 8) | ((i
+ 24) << 7);
1212 else if (a
& 0xff0000)
1216 * highpart
= (a
>> 16) | ((i
+ 16) << 7);
1220 assert (a
& 0xff000000);
1221 * highpart
= (a
>> 24) | ((i
+ 8) << 7);
1224 return (a
& 0xff) | (i
<< 7);
1231 validate_offset_imm (unsigned int val
, int hwse
)
1233 if ((hwse
&& val
> 255) || val
> 4095)
1240 /* This code is to handle mapping symbols as defined in the ARM ELF spec.
1241 (This text is taken from version B-02 of the spec):
1243 4.4.7 Mapping and tagging symbols
1245 A section of an ARM ELF file can contain a mixture of ARM code,
1246 Thumb code, and data. There are inline transitions between code
1247 and data at literal pool boundaries. There can also be inline
1248 transitions between ARM code and Thumb code, for example in
1249 ARM-Thumb inter-working veneers. Linkers, machine-level
1250 debuggers, profiling tools, and disassembly tools need to map
1251 images accurately. For example, setting an ARM breakpoint on a
1252 Thumb location, or in a literal pool, can crash the program
1253 being debugged, ruining the debugging session.
1255 ARM ELF entities are mapped (see section 4.4.7.1 below) and
1256 tagged (see section 4.4.7.2 below) using local symbols (with
1257 binding STB_LOCAL). To assist consumers, mapping and tagging
1258 symbols should be collated first in the symbol table, before
1259 other symbols with binding STB_LOCAL.
1261 To allow properly collated mapping and tagging symbols to be
1262 skipped by consumers that have no interest in them, the first
1263 such symbol should have the name $m and its st_value field equal
1264 to the total number of mapping and tagging symbols (including
1265 the $m) in the symbol table.
1267 4.4.7.1 Mapping symbols
1269 $a Labels the first byte of a sequence of ARM instructions.
1270 Its type is STT_FUNC.
1272 $d Labels the first byte of a sequence of data items.
1273 Its type is STT_OBJECT.
1275 $t Labels the first byte of a sequence of Thumb instructions.
1276 Its type is STT_FUNC.
1278 This list of mapping symbols may be extended in the future.
1280 Section-relative mapping symbols
1282 Mapping symbols defined in a section define a sequence of
1283 half-open address intervals that cover the address range of the
1284 section. Each interval starts at the address defined by a
1285 mapping symbol, and continues up to, but not including, the
1286 address defined by the next (in address order) mapping symbol or
1287 the end of the section. A corollary is that there must be a
1288 mapping symbol defined at the beginning of each section.
1289 Consumers can ignore the size of a section-relative mapping
1290 symbol. Producers can set it to 0.
1292 Absolute mapping symbols
1294 Because of the need to crystallize a Thumb address with the
1295 Thumb-bit set, absolute symbol of type STT_FUNC (symbols of type
1296 STT_FUNC defined in section SHN_ABS) need to be mapped with $a
1299 The extent of a mapping symbol defined in SHN_ABS is [st_value,
1300 st_value + st_size), or [st_value, st_value + 1) if st_size = 0,
1301 where [x, y) denotes the half-open address range from x,
1302 inclusive, to y, exclusive.
1304 In the absence of a mapping symbol, a consumer can interpret a
1305 function symbol with an odd value as the Thumb code address
1306 obtained by clearing the least significant bit of the
1307 value. This interpretation is deprecated, and it may not work in
1310 Note - the Tagging symbols ($b, $f, $p $m) have been dropped from
1311 the EABI (which is still under development), so they are not
1312 implemented here. */
1314 static enum mstate mapstate
= MAP_UNDEFINED
;
1317 mapping_state (enum mstate state
)
1320 const char * symname
;
1323 if (mapstate
== state
)
1324 /* The mapping symbol has already been emitted.
1325 There is nothing else to do. */
1338 type
= BSF_FUNCTION
;
1342 type
= BSF_FUNCTION
;
1350 seg_info (now_seg
)->tc_segment_info_data
= state
;
1352 symbolP
= symbol_new (symname
, now_seg
, (valueT
) frag_now_fix (), frag_now
);
1353 symbol_table_insert (symbolP
);
1354 symbol_get_bfdsym (symbolP
)->flags
|= type
| BSF_LOCAL
;
1359 THUMB_SET_FUNC (symbolP
, 0);
1360 ARM_SET_THUMB (symbolP
, 0);
1361 ARM_SET_INTERWORK (symbolP
, support_interwork
);
1365 THUMB_SET_FUNC (symbolP
, 1);
1366 ARM_SET_THUMB (symbolP
, 1);
1367 ARM_SET_INTERWORK (symbolP
, support_interwork
);
1376 /* When we change sections we need to issue a new mapping symbol. */
1379 arm_elf_change_section (void)
1383 /* Link an unlinked unwind index table section to the .text section. */
1384 if (elf_section_type (now_seg
) == SHT_ARM_EXIDX
1385 && elf_linked_to_section (now_seg
) == NULL
)
1386 elf_linked_to_section (now_seg
) = text_section
;
1388 if (!SEG_NORMAL (now_seg
))
1391 flags
= bfd_get_section_flags (stdoutput
, now_seg
);
1393 /* We can ignore sections that only contain debug info. */
1394 if ((flags
& SEC_ALLOC
) == 0)
1397 mapstate
= seg_info (now_seg
)->tc_segment_info_data
;
1401 arm_elf_section_type (const char * str
, size_t len
)
1403 if (len
== 5 && strncmp (str
, "exidx", 5) == 0)
1404 return SHT_ARM_EXIDX
;
1409 #define mapping_state(a)
1410 #endif /* OBJ_ELF */
1412 /* arm_reg_parse () := if it looks like a register, return its token and
1413 advance the pointer. */
1416 arm_reg_parse (char ** ccp
, struct hash_control
* htab
)
1418 char * start
= * ccp
;
1421 struct reg_entry
* reg
;
1423 #ifdef REGISTER_PREFIX
1424 if (*start
!= REGISTER_PREFIX
)
1429 #ifdef OPTIONAL_REGISTER_PREFIX
1430 if (*p
== OPTIONAL_REGISTER_PREFIX
)
1434 if (!ISALPHA (*p
) || !is_name_beginner (*p
))
1438 while (ISALPHA (c
) || ISDIGIT (c
) || c
== '_')
1442 reg
= (struct reg_entry
*) hash_find (htab
, start
);
1454 /* Search for the following register name in each of the possible reg name
1455 tables. Return the classification if found, or REG_TYPE_MAX if not
1458 static enum arm_reg_type
1459 arm_reg_parse_any (char *cp
)
1463 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
1464 if (arm_reg_parse (&cp
, all_reg_maps
[i
].htab
) != FAIL
)
1465 return (enum arm_reg_type
) i
;
1467 return REG_TYPE_MAX
;
1471 opcode_select (int width
)
1478 if (! (cpu_variant
& ARM_EXT_V4T
))
1479 as_bad (_("selected processor does not support THUMB opcodes"));
1482 /* No need to force the alignment, since we will have been
1483 coming from ARM mode, which is word-aligned. */
1484 record_alignment (now_seg
, 1);
1486 mapping_state (MAP_THUMB
);
1492 if ((cpu_variant
& ARM_ALL
) == ARM_EXT_V4T
)
1493 as_bad (_("selected processor does not support ARM opcodes"));
1498 frag_align (2, 0, 0);
1500 record_alignment (now_seg
, 1);
1502 mapping_state (MAP_ARM
);
1506 as_bad (_("invalid instruction size selected (%d)"), width
);
1511 s_req (int a ATTRIBUTE_UNUSED
)
1513 as_bad (_("invalid syntax for .req directive"));
1516 /* The .unreq directive deletes an alias which was previously defined
1517 by .req. For example:
1523 s_unreq (int a ATTRIBUTE_UNUSED
)
1528 skip_whitespace (input_line_pointer
);
1529 name
= input_line_pointer
;
1531 while (*input_line_pointer
!= 0
1532 && *input_line_pointer
!= ' '
1533 && *input_line_pointer
!= '\n')
1534 ++input_line_pointer
;
1536 saved_char
= *input_line_pointer
;
1537 *input_line_pointer
= 0;
1541 enum arm_reg_type req_type
= arm_reg_parse_any (name
);
1543 if (req_type
!= REG_TYPE_MAX
)
1545 char *temp_name
= name
;
1546 int req_no
= arm_reg_parse (&temp_name
, all_reg_maps
[req_type
].htab
);
1550 struct reg_entry
*req_entry
;
1552 /* Check to see if this alias is a builtin one. */
1553 req_entry
= hash_delete (all_reg_maps
[req_type
].htab
, name
);
1556 as_bad (_("unreq: missing hash entry for \"%s\""), name
);
1557 else if (req_entry
->builtin
)
1558 /* FIXME: We are deleting a built in register alias which
1559 points to a const data structure, so we only need to
1560 free up the memory used by the key in the hash table.
1561 Unfortunately we have not recorded this value, so this
1562 is a memory leak. */
1563 /* FIXME: Should we issue a warning message ? */
1567 /* Deleting a user defined alias. We need to free the
1568 key and the value, but fortunately the key is the same
1569 as the value->name field. */
1570 free ((char *) req_entry
->name
);
1575 as_bad (_(".unreq: unrecognized symbol \"%s\""), name
);
1578 as_bad (_(".unreq: unrecognized symbol \"%s\""), name
);
1581 as_bad (_("invalid syntax for .unreq directive"));
1583 *input_line_pointer
= saved_char
;
1584 demand_empty_rest_of_line ();
1588 s_bss (int ignore ATTRIBUTE_UNUSED
)
1590 /* We don't support putting frags in the BSS segment, we fake it by
1591 marking in_bss, then looking at s_skip for clues. */
1592 subseg_set (bss_section
, 0);
1593 demand_empty_rest_of_line ();
1594 mapping_state (MAP_DATA
);
1598 s_even (int ignore ATTRIBUTE_UNUSED
)
1600 /* Never make frag if expect extra pass. */
1602 frag_align (1, 0, 0);
1604 record_alignment (now_seg
, 1);
1606 demand_empty_rest_of_line ();
1610 s_ltorg (int ignored ATTRIBUTE_UNUSED
)
1613 literal_pool
* pool
;
1616 pool
= find_literal_pool ();
1618 || pool
->symbol
== NULL
1619 || pool
->next_free_entry
== 0)
1622 mapping_state (MAP_DATA
);
1624 /* Align pool as you have word accesses.
1625 Only make a frag if we have to. */
1627 frag_align (2, 0, 0);
1629 record_alignment (now_seg
, 2);
1631 sprintf (sym_name
, "$$lit_\002%x", pool
->id
);
1633 symbol_locate (pool
->symbol
, sym_name
, now_seg
,
1634 (valueT
) frag_now_fix (), frag_now
);
1635 symbol_table_insert (pool
->symbol
);
1637 ARM_SET_THUMB (pool
->symbol
, thumb_mode
);
1639 #if defined OBJ_COFF || defined OBJ_ELF
1640 ARM_SET_INTERWORK (pool
->symbol
, support_interwork
);
1643 for (entry
= 0; entry
< pool
->next_free_entry
; entry
++)
1644 /* First output the expression in the instruction to the pool. */
1645 emit_expr (&(pool
->literals
[entry
]), 4); /* .word */
1647 /* Mark the pool as empty. */
1648 pool
->next_free_entry
= 0;
1649 pool
->symbol
= NULL
;
1652 /* Same as s_align_ptwo but align 0 => align 2. */
1655 s_align (int unused ATTRIBUTE_UNUSED
)
1659 long max_alignment
= 15;
1661 temp
= get_absolute_expression ();
1662 if (temp
> max_alignment
)
1663 as_bad (_("alignment too large: %d assumed"), temp
= max_alignment
);
1666 as_bad (_("alignment negative. 0 assumed."));
1670 if (*input_line_pointer
== ',')
1672 input_line_pointer
++;
1673 temp_fill
= get_absolute_expression ();
1681 /* Only make a frag if we HAVE to. */
1682 if (temp
&& !need_pass_2
)
1683 frag_align (temp
, (int) temp_fill
, 0);
1684 demand_empty_rest_of_line ();
1686 record_alignment (now_seg
, temp
);
1690 s_force_thumb (int ignore ATTRIBUTE_UNUSED
)
1692 /* If we are not already in thumb mode go into it, EVEN if
1693 the target processor does not support thumb instructions.
1694 This is used by gcc/config/arm/lib1funcs.asm for example
1695 to compile interworking support functions even if the
1696 target processor should not support interworking. */
1701 record_alignment (now_seg
, 1);
1704 demand_empty_rest_of_line ();
1708 s_thumb_func (int ignore ATTRIBUTE_UNUSED
)
1713 /* The following label is the name/address of the start of a Thumb function.
1714 We need to know this for the interworking support. */
1715 label_is_thumb_function_name
= TRUE
;
1717 demand_empty_rest_of_line ();
1720 /* Perform a .set directive, but also mark the alias as
1721 being a thumb function. */
1724 s_thumb_set (int equiv
)
1726 /* XXX the following is a duplicate of the code for s_set() in read.c
1727 We cannot just call that code as we need to get at the symbol that
1734 /* Especial apologies for the random logic:
1735 This just grew, and could be parsed much more simply!
1737 name
= input_line_pointer
;
1738 delim
= get_symbol_end ();
1739 end_name
= input_line_pointer
;
1744 if (*input_line_pointer
!= ',')
1747 as_bad (_("expected comma after name \"%s\""), name
);
1749 ignore_rest_of_line ();
1753 input_line_pointer
++;
1756 if (name
[0] == '.' && name
[1] == '\0')
1758 /* XXX - this should not happen to .thumb_set. */
1762 if ((symbolP
= symbol_find (name
)) == NULL
1763 && (symbolP
= md_undefined_symbol (name
)) == NULL
)
1766 /* When doing symbol listings, play games with dummy fragments living
1767 outside the normal fragment chain to record the file and line info
1769 if (listing
& LISTING_SYMBOLS
)
1771 extern struct list_info_struct
* listing_tail
;
1772 fragS
* dummy_frag
= xmalloc (sizeof (fragS
));
1774 memset (dummy_frag
, 0, sizeof (fragS
));
1775 dummy_frag
->fr_type
= rs_fill
;
1776 dummy_frag
->line
= listing_tail
;
1777 symbolP
= symbol_new (name
, undefined_section
, 0, dummy_frag
);
1778 dummy_frag
->fr_symbol
= symbolP
;
1782 symbolP
= symbol_new (name
, undefined_section
, 0, &zero_address_frag
);
1785 /* "set" symbols are local unless otherwise specified. */
1786 SF_SET_LOCAL (symbolP
);
1787 #endif /* OBJ_COFF */
1788 } /* Make a new symbol. */
1790 symbol_table_insert (symbolP
);
1795 && S_IS_DEFINED (symbolP
)
1796 && S_GET_SEGMENT (symbolP
) != reg_section
)
1797 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP
));
1799 pseudo_set (symbolP
);
1801 demand_empty_rest_of_line ();
1803 /* XXX Now we come to the Thumb specific bit of code. */
1805 THUMB_SET_FUNC (symbolP
, 1);
1806 ARM_SET_THUMB (symbolP
, 1);
1807 #if defined OBJ_ELF || defined OBJ_COFF
1808 ARM_SET_INTERWORK (symbolP
, support_interwork
);
1813 s_arm (int ignore ATTRIBUTE_UNUSED
)
1816 demand_empty_rest_of_line ();
1820 s_thumb (int ignore ATTRIBUTE_UNUSED
)
1823 demand_empty_rest_of_line ();
1827 s_code (int unused ATTRIBUTE_UNUSED
)
1831 temp
= get_absolute_expression ();
1836 opcode_select (temp
);
1840 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp
);
1845 end_of_line (char * str
)
1847 skip_whitespace (str
);
1849 if (*str
!= '\0' && !inst
.error
)
1850 inst
.error
= _("garbage following instruction");
1854 skip_past_comma (char ** str
)
1856 char * p
= * str
, c
;
1859 while ((c
= *p
) == ' ' || c
== ',')
1862 if (c
== ',' && comma
++)
1870 return comma
? SUCCESS
: FAIL
;
1873 /* Return TRUE if anything in the expression is a bignum. */
1876 walk_no_bignums (symbolS
* sp
)
1878 if (symbol_get_value_expression (sp
)->X_op
== O_big
)
1881 if (symbol_get_value_expression (sp
)->X_add_symbol
)
1883 return (walk_no_bignums (symbol_get_value_expression (sp
)->X_add_symbol
)
1884 || (symbol_get_value_expression (sp
)->X_op_symbol
1885 && walk_no_bignums (symbol_get_value_expression (sp
)->X_op_symbol
)));
1891 static int in_my_get_expression
= 0;
1894 my_get_expression (expressionS
* ep
, char ** str
)
1899 save_in
= input_line_pointer
;
1900 input_line_pointer
= *str
;
1901 in_my_get_expression
= 1;
1902 seg
= expression (ep
);
1903 in_my_get_expression
= 0;
1905 if (ep
->X_op
== O_illegal
)
1907 /* We found a bad expression in md_operand(). */
1908 *str
= input_line_pointer
;
1909 input_line_pointer
= save_in
;
1914 if (seg
!= absolute_section
1915 && seg
!= text_section
1916 && seg
!= data_section
1917 && seg
!= bss_section
1918 && seg
!= undefined_section
)
1920 inst
.error
= _("bad_segment");
1921 *str
= input_line_pointer
;
1922 input_line_pointer
= save_in
;
1927 /* Get rid of any bignums now, so that we don't generate an error for which
1928 we can't establish a line number later on. Big numbers are never valid
1929 in instructions, which is where this routine is always called. */
1930 if (ep
->X_op
== O_big
1931 || (ep
->X_add_symbol
1932 && (walk_no_bignums (ep
->X_add_symbol
)
1934 && walk_no_bignums (ep
->X_op_symbol
)))))
1936 inst
.error
= _("invalid constant");
1937 *str
= input_line_pointer
;
1938 input_line_pointer
= save_in
;
1942 *str
= input_line_pointer
;
1943 input_line_pointer
= save_in
;
1947 /* A standard register must be given at this point.
1948 SHIFT is the place to put it in inst.instruction.
1949 Restores input start point on error.
1950 Returns the reg#, or FAIL. */
1953 reg_required_here (char ** str
, int shift
)
1955 static char buff
[128]; /* XXX */
1957 char * start
= * str
;
1959 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_RN
].htab
)) != FAIL
)
1962 inst
.instruction
|= reg
<< shift
;
1966 /* Restore the start point, we may have got a reg of the wrong class. */
1969 /* In the few cases where we might be able to accept something else
1970 this error can be overridden. */
1971 sprintf (buff
, _("register expected, not '%.100s'"), start
);
1977 /* A Intel Wireless MMX technology register
1978 must be given at this point.
1979 Shift is the place to put it in inst.instruction.
1980 Restores input start point on err.
1981 Returns the reg#, or FAIL. */
1984 wreg_required_here (char ** str
,
1986 enum wreg_type reg_type
)
1988 static char buff
[128];
1990 char * start
= *str
;
1992 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_IWMMXT
].htab
)) != FAIL
)
1994 if (wr_register (reg
)
1995 && (reg_type
== IWMMXT_REG_WR
|| reg_type
== IWMMXT_REG_WR_OR_WC
))
1998 inst
.instruction
|= (reg
^ WR_PREFIX
) << shift
;
2001 else if (wc_register (reg
)
2002 && (reg_type
== IWMMXT_REG_WC
|| reg_type
== IWMMXT_REG_WR_OR_WC
))
2005 inst
.instruction
|= (reg
^ WC_PREFIX
) << shift
;
2008 else if ((wcg_register (reg
) && reg_type
== IWMMXT_REG_WCG
))
2011 inst
.instruction
|= ((reg
^ WC_PREFIX
) - 8) << shift
;
2016 /* Restore the start point, we may have got a reg of the wrong class. */
2019 /* In the few cases where we might be able to accept
2020 something else this error can be overridden. */
2021 sprintf (buff
, _("Intel Wireless MMX technology register expected, not '%.100s'"), start
);
2027 static const struct asm_psr
*
2028 arm_psr_parse (char ** ccp
)
2030 char * start
= * ccp
;
2033 const struct asm_psr
* psr
;
2037 /* Skip to the end of the next word in the input stream. */
2042 while (ISALPHA (c
) || c
== '_');
2044 /* Terminate the word. */
2047 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
2048 feature for ease of use and backwards compatibility. */
2049 if (!strncmp (start
, "cpsr", 4))
2050 strncpy (start
, "CPSR", 4);
2051 else if (!strncmp (start
, "spsr", 4))
2052 strncpy (start
, "SPSR", 4);
2054 /* Now locate the word in the psr hash table. */
2055 psr
= (const struct asm_psr
*) hash_find (arm_psr_hsh
, start
);
2057 /* Restore the input stream. */
2060 /* If we found a valid match, advance the
2061 stream pointer past the end of the word. */
2067 /* Parse the input looking for a PSR flag. */
2070 psr_required_here (char ** str
)
2072 char * start
= * str
;
2073 const struct asm_psr
* psr
;
2075 psr
= arm_psr_parse (str
);
2079 /* If this is the SPSR that is being modified, set the R bit. */
2081 inst
.instruction
|= SPSR_BIT
;
2083 /* Set the psr flags in the MSR instruction. */
2084 inst
.instruction
|= psr
->field
<< PSR_SHIFT
;
2089 /* In the few cases where we might be able to accept
2090 something else this error can be overridden. */
2091 inst
.error
= _("flag for {c}psr instruction expected");
2093 /* Restore the start point. */
2099 co_proc_number (char ** str
)
2101 int processor
, pchar
;
2104 skip_whitespace (*str
);
2107 /* The data sheet seems to imply that just a number on its own is valid
2108 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
2110 if ((processor
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CP
].htab
))
2116 if (pchar
>= '0' && pchar
<= '9')
2118 processor
= pchar
- '0';
2119 if (**str
>= '0' && **str
<= '9')
2121 processor
= processor
* 10 + *(*str
)++ - '0';
2124 inst
.error
= _("illegal co-processor number");
2131 inst
.error
= all_reg_maps
[REG_TYPE_CP
].expected
;
2136 inst
.instruction
|= processor
<< 8;
2141 cp_opc_expr (char ** str
, int where
, int length
)
2145 skip_whitespace (* str
);
2147 memset (&expr
, '\0', sizeof (expr
));
2149 if (my_get_expression (&expr
, str
))
2151 if (expr
.X_op
!= O_constant
)
2153 inst
.error
= _("bad or missing expression");
2157 if ((expr
.X_add_number
& ((1 << length
) - 1)) != expr
.X_add_number
)
2159 inst
.error
= _("immediate co-processor expression too large");
2163 inst
.instruction
|= expr
.X_add_number
<< where
;
2168 cp_reg_required_here (char ** str
, int where
)
2171 char * start
= *str
;
2173 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CN
].htab
)) != FAIL
)
2175 inst
.instruction
|= reg
<< where
;
2179 /* In the few cases where we might be able to accept something else
2180 this error can be overridden. */
2181 inst
.error
= all_reg_maps
[REG_TYPE_CN
].expected
;
2183 /* Restore the start point. */
2189 fp_reg_required_here (char ** str
, int where
)
2192 char * start
= * str
;
2194 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_FN
].htab
)) != FAIL
)
2196 inst
.instruction
|= reg
<< where
;
2200 /* In the few cases where we might be able to accept something else
2201 this error can be overridden. */
2202 inst
.error
= all_reg_maps
[REG_TYPE_FN
].expected
;
2204 /* Restore the start point. */
2210 cp_address_offset (char ** str
)
2214 skip_whitespace (* str
);
2216 if (! is_immediate_prefix (**str
))
2218 inst
.error
= _("immediate expression expected");
2224 if (my_get_expression (& inst
.reloc
.exp
, str
))
2227 if (inst
.reloc
.exp
.X_op
== O_constant
)
2229 offset
= inst
.reloc
.exp
.X_add_number
;
2233 inst
.error
= _("co-processor address must be word aligned");
2237 if (offset
> 1023 || offset
< -1023)
2239 inst
.error
= _("offset too large");
2244 inst
.instruction
|= INDEX_UP
;
2248 inst
.instruction
|= offset
>> 2;
2251 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
2257 cp_address_required_here (char ** str
, int wb_ok
)
2268 skip_whitespace (p
);
2270 if ((reg
= reg_required_here (& p
, 16)) == FAIL
)
2273 skip_whitespace (p
);
2279 skip_whitespace (p
);
2283 /* As an extension to the official ARM syntax we allow:
2285 as a short hand for:
2287 inst
.instruction
|= PRE_INDEX
| INDEX_UP
;
2292 if (skip_past_comma (& p
) == FAIL
)
2294 inst
.error
= _("comma expected after closing square bracket");
2298 skip_whitespace (p
);
2305 write_back
= WRITE_BACK
;
2309 inst
.error
= _("pc may not be used in post-increment");
2313 if (cp_address_offset (& p
) == FAIL
)
2317 pre_inc
= PRE_INDEX
| INDEX_UP
;
2323 /* [Rn], {<expr>} */
2326 skip_whitespace (p
);
2328 if (my_get_expression (& inst
.reloc
.exp
, & p
))
2331 if (inst
.reloc
.exp
.X_op
== O_constant
)
2333 option
= inst
.reloc
.exp
.X_add_number
;
2335 if (option
> 255 || option
< 0)
2337 inst
.error
= _("'option' field too large");
2341 skip_whitespace (p
);
2345 inst
.error
= _("'}' expected at end of 'option' field");
2351 inst
.instruction
|= option
;
2352 inst
.instruction
|= INDEX_UP
;
2357 inst
.error
= _("non-constant expressions for 'option' field not supported");
2363 inst
.error
= _("# or { expected after comma");
2369 /* '['Rn, #expr']'[!] */
2371 if (skip_past_comma (& p
) == FAIL
)
2373 inst
.error
= _("pre-indexed expression expected");
2377 pre_inc
= PRE_INDEX
;
2379 if (cp_address_offset (& p
) == FAIL
)
2382 skip_whitespace (p
);
2386 inst
.error
= _("missing ]");
2390 skip_whitespace (p
);
2392 if (wb_ok
&& *p
== '!')
2396 inst
.error
= _("pc may not be used with write-back");
2401 write_back
= WRITE_BACK
;
2407 if (my_get_expression (&inst
.reloc
.exp
, &p
))
2410 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
2411 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
2412 inst
.reloc
.pc_rel
= 1;
2413 inst
.instruction
|= (REG_PC
<< 16);
2414 pre_inc
= PRE_INDEX
;
2417 inst
.instruction
|= write_back
| pre_inc
;
2423 cp_byte_address_offset (char ** str
)
2427 skip_whitespace (* str
);
2429 if (! is_immediate_prefix (**str
))
2431 inst
.error
= _("immediate expression expected");
2437 if (my_get_expression (& inst
.reloc
.exp
, str
))
2440 if (inst
.reloc
.exp
.X_op
== O_constant
)
2442 offset
= inst
.reloc
.exp
.X_add_number
;
2444 if (offset
> 255 || offset
< -255)
2446 inst
.error
= _("offset too large");
2451 inst
.instruction
|= INDEX_UP
;
2455 inst
.instruction
|= offset
;
2458 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM_S2
;
2464 cp_byte_address_required_here (char ** str
)
2475 skip_whitespace (p
);
2477 if ((reg
= reg_required_here (& p
, 16)) == FAIL
)
2480 skip_whitespace (p
);
2486 if (skip_past_comma (& p
) == SUCCESS
)
2489 write_back
= WRITE_BACK
;
2493 inst
.error
= _("pc may not be used in post-increment");
2497 if (cp_byte_address_offset (& p
) == FAIL
)
2501 pre_inc
= PRE_INDEX
| INDEX_UP
;
2505 /* '['Rn, #expr']'[!] */
2507 if (skip_past_comma (& p
) == FAIL
)
2509 inst
.error
= _("pre-indexed expression expected");
2513 pre_inc
= PRE_INDEX
;
2515 if (cp_byte_address_offset (& p
) == FAIL
)
2518 skip_whitespace (p
);
2522 inst
.error
= _("missing ]");
2526 skip_whitespace (p
);
2532 inst
.error
= _("pc may not be used with write-back");
2537 write_back
= WRITE_BACK
;
2543 if (my_get_expression (&inst
.reloc
.exp
, &p
))
2546 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM_S2
;
2547 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
2548 inst
.reloc
.pc_rel
= 1;
2549 inst
.instruction
|= (REG_PC
<< 16);
2550 pre_inc
= PRE_INDEX
;
2553 inst
.instruction
|= write_back
| pre_inc
;
2561 skip_whitespace (str
);
2566 if (my_get_expression (&inst
.reloc
.exp
, &str
))
2567 inst
.reloc
.exp
.X_op
= O_illegal
;
2570 skip_whitespace (str
);
2574 inst
.reloc
.exp
.X_op
= O_illegal
;
2577 if (inst
.reloc
.exp
.X_op
!= O_constant
2578 || inst
.reloc
.exp
.X_add_number
> 255
2579 || inst
.reloc
.exp
.X_add_number
< 0)
2581 inst
.error
= _("Invalid NOP hint");
2585 /* Arcitectural NOP hints are CPSR sets with no bits selected. */
2586 inst
.instruction
&= 0xf0000000;
2587 inst
.instruction
|= 0x0320f000 + inst
.reloc
.exp
.X_add_number
;
2594 do_empty (char * str
)
2596 /* Do nothing really. */
2605 /* Only one syntax. */
2606 skip_whitespace (str
);
2608 if (reg_required_here (&str
, 12) == FAIL
)
2610 inst
.error
= BAD_ARGS
;
2614 if (skip_past_comma (&str
) == FAIL
)
2616 inst
.error
= _("comma expected after register name");
2620 skip_whitespace (str
);
2622 if ( streq (str
, "CPSR")
2623 || streq (str
, "SPSR")
2624 /* Lower case versions for backwards compatibility. */
2625 || streq (str
, "cpsr")
2626 || streq (str
, "spsr"))
2629 /* This is for backwards compatibility with older toolchains. */
2630 else if ( streq (str
, "cpsr_all")
2631 || streq (str
, "spsr_all"))
2635 inst
.error
= _("CPSR or SPSR expected");
2639 if (* str
== 's' || * str
== 'S')
2640 inst
.instruction
|= SPSR_BIT
;
2646 /* Two possible forms:
2647 "{C|S}PSR_<field>, Rm",
2648 "{C|S}PSR_f, #expression". */
2653 skip_whitespace (str
);
2655 if (psr_required_here (& str
) == FAIL
)
2658 if (skip_past_comma (& str
) == FAIL
)
2660 inst
.error
= _("comma missing after psr flags");
2664 skip_whitespace (str
);
2666 if (reg_required_here (& str
, 0) != FAIL
)
2673 if (! is_immediate_prefix (* str
))
2676 _("only a register or immediate value can follow a psr flag");
2683 if (my_get_expression (& inst
.reloc
.exp
, & str
))
2686 _("only a register or immediate value can follow a psr flag");
2690 inst
.instruction
|= INST_IMMEDIATE
;
2692 if (inst
.reloc
.exp
.X_add_symbol
)
2694 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
2695 inst
.reloc
.pc_rel
= 0;
2699 unsigned value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
2701 if (value
== (unsigned) FAIL
)
2703 inst
.error
= _("invalid constant");
2707 inst
.instruction
|= value
;
2714 /* Long Multiply Parser
2715 UMULL RdLo, RdHi, Rm, Rs
2716 SMULL RdLo, RdHi, Rm, Rs
2717 UMLAL RdLo, RdHi, Rm, Rs
2718 SMLAL RdLo, RdHi, Rm, Rs. */
2721 do_mull (char * str
)
2723 int rdlo
, rdhi
, rm
, rs
;
2725 /* Only one format "rdlo, rdhi, rm, rs". */
2726 skip_whitespace (str
);
2728 if ((rdlo
= reg_required_here (&str
, 12)) == FAIL
)
2730 inst
.error
= BAD_ARGS
;
2734 if (skip_past_comma (&str
) == FAIL
2735 || (rdhi
= reg_required_here (&str
, 16)) == FAIL
)
2737 inst
.error
= BAD_ARGS
;
2741 if (skip_past_comma (&str
) == FAIL
2742 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
2744 inst
.error
= BAD_ARGS
;
2748 /* rdhi, rdlo and rm must all be different. */
2749 if (rdlo
== rdhi
|| rdlo
== rm
|| rdhi
== rm
)
2750 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
2752 if (skip_past_comma (&str
) == FAIL
2753 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
2755 inst
.error
= BAD_ARGS
;
2759 if (rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
)
2761 inst
.error
= BAD_PC
;
2773 /* Only one format "rd, rm, rs". */
2774 skip_whitespace (str
);
2776 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
2778 inst
.error
= BAD_ARGS
;
2784 inst
.error
= BAD_PC
;
2788 if (skip_past_comma (&str
) == FAIL
2789 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
2791 inst
.error
= BAD_ARGS
;
2797 inst
.error
= BAD_PC
;
2802 as_tsktsk (_("rd and rm should be different in mul"));
2804 if (skip_past_comma (&str
) == FAIL
2805 || (rm
= reg_required_here (&str
, 8)) == FAIL
)
2807 inst
.error
= BAD_ARGS
;
2813 inst
.error
= BAD_PC
;
2821 do_mlas (char * str
, bfd_boolean is_mls
)
2825 /* Only one format "rd, rm, rs, rn". */
2826 skip_whitespace (str
);
2828 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
2830 inst
.error
= BAD_ARGS
;
2836 inst
.error
= BAD_PC
;
2840 if (skip_past_comma (&str
) == FAIL
2841 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
2843 inst
.error
= BAD_ARGS
;
2849 inst
.error
= BAD_PC
;
2853 /* This restriction does not apply to mls (nor to mla in v6, but
2854 that's hard to detect at present). */
2855 if (rm
== rd
&& !is_mls
)
2856 as_tsktsk (_("rd and rm should be different in mla"));
2858 if (skip_past_comma (&str
) == FAIL
2859 || (rd
= reg_required_here (&str
, 8)) == FAIL
2860 || skip_past_comma (&str
) == FAIL
2861 || (rm
= reg_required_here (&str
, 12)) == FAIL
)
2863 inst
.error
= BAD_ARGS
;
2867 if (rd
== REG_PC
|| rm
== REG_PC
)
2869 inst
.error
= BAD_PC
;
2879 do_mlas (str
, FALSE
);
2885 do_mlas (str
, TRUE
);
2888 /* Expects *str -> the characters "acc0", possibly with leading blanks.
2889 Advances *str to the next non-alphanumeric.
2890 Returns 0, or else FAIL (in which case sets inst.error).
2892 (In a future XScale, there may be accumulators other than zero.
2893 At that time this routine and its callers can be upgraded to suit.) */
2896 accum0_required_here (char ** str
)
2898 static char buff
[128]; /* Note the address is taken. Hence, static. */
2901 int result
= 0; /* The accum number. */
2903 skip_whitespace (p
);
2905 *str
= p
; /* Advance caller's string pointer too. */
2910 *--p
= 0; /* Aap nul into input buffer at non-alnum. */
2912 if (! ( streq (*str
, "acc0") || streq (*str
, "ACC0")))
2914 sprintf (buff
, _("acc0 expected, not '%.100s'"), *str
);
2919 *p
= c
; /* Unzap. */
2920 *str
= p
; /* Caller's string pointer to after match. */
2925 ldst_extend_v4 (char ** str
)
2934 if (my_get_expression (& inst
.reloc
.exp
, str
))
2937 if (inst
.reloc
.exp
.X_op
== O_constant
)
2939 int value
= inst
.reloc
.exp
.X_add_number
;
2941 if (value
< -255 || value
> 255)
2943 inst
.error
= _("address offset too large");
2953 /* Halfword and signextension instructions have the
2954 immediate value split across bits 11..8 and bits 3..0. */
2955 inst
.instruction
|= (add
| HWOFFSET_IMM
2956 | ((value
>> 4) << 8) | (value
& 0xF));
2960 inst
.instruction
|= HWOFFSET_IMM
;
2961 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
2962 inst
.reloc
.pc_rel
= 0;
2975 if (reg_required_here (str
, 0) == FAIL
)
2978 inst
.instruction
|= add
;
2983 /* Expects **str -> after a comma. May be leading blanks.
2984 Advances *str, recognizing a load mode, and setting inst.instruction.
2985 Returns rn, or else FAIL (in which case may set inst.error
2986 and not advance str)
2988 Note: doesn't know Rd, so no err checks that require such knowledge. */
2991 ld_mode_required_here (char ** string
)
2993 char * str
= * string
;
2997 skip_whitespace (str
);
3003 skip_whitespace (str
);
3005 if ((rn
= reg_required_here (& str
, 16)) == FAIL
)
3008 skip_whitespace (str
);
3014 if (skip_past_comma (& str
) == SUCCESS
)
3016 /* [Rn],... (post inc) */
3017 if (ldst_extend_v4 (&str
) == FAIL
)
3022 skip_whitespace (str
);
3027 inst
.instruction
|= WRITE_BACK
;
3030 inst
.instruction
|= INDEX_UP
| HWOFFSET_IMM
;
3036 if (skip_past_comma (& str
) == FAIL
)
3038 inst
.error
= _("pre-indexed expression expected");
3044 if (ldst_extend_v4 (&str
) == FAIL
)
3047 skip_whitespace (str
);
3049 if (* str
++ != ']')
3051 inst
.error
= _("missing ]");
3055 skip_whitespace (str
);
3060 inst
.instruction
|= WRITE_BACK
;
3064 else if (* str
== '=') /* ldr's "r,=label" syntax */
3065 /* We should never reach here, because <text> = <expression> is
3066 caught gas/read.c read_a_source_file() as a .set operation. */
3068 else /* PC +- 8 bit immediate offset. */
3070 if (my_get_expression (& inst
.reloc
.exp
, & str
))
3073 inst
.instruction
|= HWOFFSET_IMM
; /* The I bit. */
3074 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
3075 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
3076 inst
.reloc
.pc_rel
= 1;
3077 inst
.instruction
|= (REG_PC
<< 16);
3083 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
3089 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
3090 SMLAxy{cond} Rd,Rm,Rs,Rn
3091 SMLAWy{cond} Rd,Rm,Rs,Rn
3092 Error if any register is R15. */
3095 do_smla (char * str
)
3099 skip_whitespace (str
);
3101 if ((rd
= reg_required_here (& str
, 16)) == FAIL
3102 || skip_past_comma (& str
) == FAIL
3103 || (rm
= reg_required_here (& str
, 0)) == FAIL
3104 || skip_past_comma (& str
) == FAIL
3105 || (rs
= reg_required_here (& str
, 8)) == FAIL
3106 || skip_past_comma (& str
) == FAIL
3107 || (rn
= reg_required_here (& str
, 12)) == FAIL
)
3108 inst
.error
= BAD_ARGS
;
3110 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
|| rn
== REG_PC
)
3111 inst
.error
= BAD_PC
;
3117 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
3118 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
3119 Error if any register is R15.
3120 Warning if Rdlo == Rdhi. */
3123 do_smlal (char * str
)
3125 int rdlo
, rdhi
, rm
, rs
;
3127 skip_whitespace (str
);
3129 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
3130 || skip_past_comma (& str
) == FAIL
3131 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
3132 || skip_past_comma (& str
) == FAIL
3133 || (rm
= reg_required_here (& str
, 0)) == FAIL
3134 || skip_past_comma (& str
) == FAIL
3135 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
3137 inst
.error
= BAD_ARGS
;
3141 if (rdlo
== REG_PC
|| rdhi
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
3143 inst
.error
= BAD_PC
;
3148 as_tsktsk (_("rdhi and rdlo must be different"));
3153 /* ARM V5E (El Segundo) signed-multiply (argument parse)
3154 SMULxy{cond} Rd,Rm,Rs
3155 Error if any register is R15. */
3158 do_smul (char * str
)
3162 skip_whitespace (str
);
3164 if ((rd
= reg_required_here (& str
, 16)) == FAIL
3165 || skip_past_comma (& str
) == FAIL
3166 || (rm
= reg_required_here (& str
, 0)) == FAIL
3167 || skip_past_comma (& str
) == FAIL
3168 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
3169 inst
.error
= BAD_ARGS
;
3171 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
3172 inst
.error
= BAD_PC
;
3178 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
3179 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
3180 Error if any register is R15. */
3183 do_qadd (char * str
)
3187 skip_whitespace (str
);
3189 if ((rd
= reg_required_here (& str
, 12)) == FAIL
3190 || skip_past_comma (& str
) == FAIL
3191 || (rm
= reg_required_here (& str
, 0)) == FAIL
3192 || skip_past_comma (& str
) == FAIL
3193 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
3194 inst
.error
= BAD_ARGS
;
3196 else if (rd
== REG_PC
|| rm
== REG_PC
|| rn
== REG_PC
)
3197 inst
.error
= BAD_PC
;
3203 /* ARM V5E (el Segundo)
3204 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3205 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3207 These are equivalent to the XScale instructions MAR and MRA,
3208 respectively, when coproc == 0, opcode == 0, and CRm == 0.
3210 Result unpredicatable if Rd or Rn is R15. */
3213 do_co_reg2c (char * str
)
3217 skip_whitespace (str
);
3219 if (co_proc_number (& str
) == FAIL
)
3222 inst
.error
= BAD_ARGS
;
3226 if (skip_past_comma (& str
) == FAIL
3227 || cp_opc_expr (& str
, 4, 4) == FAIL
)
3230 inst
.error
= BAD_ARGS
;
3234 if (skip_past_comma (& str
) == FAIL
3235 || (rd
= reg_required_here (& str
, 12)) == FAIL
)
3238 inst
.error
= BAD_ARGS
;
3242 if (skip_past_comma (& str
) == FAIL
3243 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
3246 inst
.error
= BAD_ARGS
;
3250 /* Unpredictable result if rd or rn is R15. */
3251 if (rd
== REG_PC
|| rn
== REG_PC
)
3253 (_("Warning: instruction unpredictable when using r15"));
3255 if (skip_past_comma (& str
) == FAIL
3256 || cp_reg_required_here (& str
, 0) == FAIL
)
3259 inst
.error
= BAD_ARGS
;
3266 /* ARM V5 count-leading-zeroes instruction (argument parse)
3267 CLZ{<cond>} <Rd>, <Rm>
3268 Condition defaults to COND_ALWAYS.
3269 Error if Rd or Rm are R15. */
3276 skip_whitespace (str
);
3278 if (((rd
= reg_required_here (& str
, 12)) == FAIL
)
3279 || (skip_past_comma (& str
) == FAIL
)
3280 || ((rm
= reg_required_here (& str
, 0)) == FAIL
))
3281 inst
.error
= BAD_ARGS
;
3283 else if (rd
== REG_PC
|| rm
== REG_PC
)
3284 inst
.error
= BAD_PC
;
3290 /* ARM V5 (argument parse)
3291 LDC2{L} <coproc>, <CRd>, <addressing mode>
3292 STC2{L} <coproc>, <CRd>, <addressing mode>
3293 Instruction is not conditional, and has 0xf in the condition field.
3294 Otherwise, it's the same as LDC/STC. */
3297 do_lstc2 (char * str
)
3299 skip_whitespace (str
);
3301 if (co_proc_number (& str
) == FAIL
)
3304 inst
.error
= BAD_ARGS
;
3306 else if (skip_past_comma (& str
) == FAIL
3307 || cp_reg_required_here (& str
, 12) == FAIL
)
3310 inst
.error
= BAD_ARGS
;
3312 else if (skip_past_comma (& str
) == FAIL
3313 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
3316 inst
.error
= BAD_ARGS
;
3322 /* ARM V5 (argument parse)
3323 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
3324 Instruction is not conditional, and has 0xf in the condition field.
3325 Otherwise, it's the same as CDP. */
3328 do_cdp2 (char * str
)
3330 skip_whitespace (str
);
3332 if (co_proc_number (& str
) == FAIL
)
3335 inst
.error
= BAD_ARGS
;
3339 if (skip_past_comma (& str
) == FAIL
3340 || cp_opc_expr (& str
, 20,4) == FAIL
)
3343 inst
.error
= BAD_ARGS
;
3347 if (skip_past_comma (& str
) == FAIL
3348 || cp_reg_required_here (& str
, 12) == FAIL
)
3351 inst
.error
= BAD_ARGS
;
3355 if (skip_past_comma (& str
) == FAIL
3356 || cp_reg_required_here (& str
, 16) == FAIL
)
3359 inst
.error
= BAD_ARGS
;
3363 if (skip_past_comma (& str
) == FAIL
3364 || cp_reg_required_here (& str
, 0) == FAIL
)
3367 inst
.error
= BAD_ARGS
;
3371 if (skip_past_comma (& str
) == SUCCESS
)
3373 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
3376 inst
.error
= BAD_ARGS
;
3384 /* ARM V5 (argument parse)
3385 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3386 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3387 Instruction is not conditional, and has 0xf in the condition field.
3388 Otherwise, it's the same as MCR/MRC. */
3391 do_co_reg2 (char * str
)
3393 skip_whitespace (str
);
3395 if (co_proc_number (& str
) == FAIL
)
3398 inst
.error
= BAD_ARGS
;
3402 if (skip_past_comma (& str
) == FAIL
3403 || cp_opc_expr (& str
, 21, 3) == FAIL
)
3406 inst
.error
= BAD_ARGS
;
3410 if (skip_past_comma (& str
) == FAIL
3411 || reg_required_here (& str
, 12) == FAIL
)
3414 inst
.error
= BAD_ARGS
;
3418 if (skip_past_comma (& str
) == FAIL
3419 || cp_reg_required_here (& str
, 16) == FAIL
)
3422 inst
.error
= BAD_ARGS
;
3426 if (skip_past_comma (& str
) == FAIL
3427 || cp_reg_required_here (& str
, 0) == FAIL
)
3430 inst
.error
= BAD_ARGS
;
3434 if (skip_past_comma (& str
) == SUCCESS
)
3436 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
3439 inst
.error
= BAD_ARGS
;
3452 skip_whitespace (str
);
3454 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
3456 inst
.error
= BAD_ARGS
;
3460 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
3462 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
3467 /* ARM v5TEJ. Jump to Jazelle code. */
3474 skip_whitespace (str
);
3476 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
3478 inst
.error
= BAD_ARGS
;
3482 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
3484 as_tsktsk (_("use of r15 in bxj is not really useful"));
3489 /* ARM V6 umaal (argument parse). */
3492 do_umaal (char * str
)
3494 int rdlo
, rdhi
, rm
, rs
;
3496 skip_whitespace (str
);
3497 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
3498 || skip_past_comma (& str
) == FAIL
3499 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
3500 || skip_past_comma (& str
) == FAIL
3501 || (rm
= reg_required_here (& str
, 0)) == FAIL
3502 || skip_past_comma (& str
) == FAIL
3503 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
3505 inst
.error
= BAD_ARGS
;
3509 if (rdlo
== REG_PC
|| rdhi
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
3511 inst
.error
= BAD_PC
;
3518 /* ARM V6 strex (argument parse). */
3521 do_strex (char * str
)
3525 /* Parse Rd, Rm,. */
3526 skip_whitespace (str
);
3527 if ((rd
= reg_required_here (& str
, 12)) == FAIL
3528 || skip_past_comma (& str
) == FAIL
3529 || (rm
= reg_required_here (& str
, 0)) == FAIL
3530 || skip_past_comma (& str
) == FAIL
)
3532 inst
.error
= BAD_ARGS
;
3535 if (rd
== REG_PC
|| rm
== REG_PC
)
3537 inst
.error
= BAD_PC
;
3542 inst
.error
= _("Rd equal to Rm or Rn yields unpredictable results");
3546 /* Skip past '['. */
3547 if ((strlen (str
) >= 1)
3548 && strncmp (str
, "[", 1) == 0)
3551 skip_whitespace (str
);
3554 if ((rn
= reg_required_here (& str
, 16)) == FAIL
)
3556 inst
.error
= BAD_ARGS
;
3559 else if (rn
== REG_PC
)
3561 inst
.error
= BAD_PC
;
3566 inst
.error
= _("Rd equal to Rm or Rn yields unpredictable results");
3569 skip_whitespace (str
);
3571 /* Skip past ']'. */
3572 if ((strlen (str
) >= 1)
3573 && strncmp (str
, "]", 1) == 0)
3579 /* KIND indicates what kind of shifts are accepted. */
3582 decode_shift (char ** str
, int kind
)
3584 const struct asm_shift_name
* shift
;
3588 skip_whitespace (* str
);
3590 for (p
= * str
; ISALPHA (* p
); p
++)
3595 inst
.error
= _("shift expression expected");
3601 shift
= (const struct asm_shift_name
*) hash_find (arm_shift_hsh
, * str
);
3606 inst
.error
= _("shift expression expected");
3610 assert (shift
->properties
->index
== shift_properties
[shift
->properties
->index
].index
);
3612 if (kind
== SHIFT_LSL_OR_ASR_IMMEDIATE
3613 && shift
->properties
->index
!= SHIFT_LSL
3614 && shift
->properties
->index
!= SHIFT_ASR
)
3616 inst
.error
= _("'LSL' or 'ASR' required");
3619 else if (kind
== SHIFT_LSL_IMMEDIATE
3620 && shift
->properties
->index
!= SHIFT_LSL
)
3622 inst
.error
= _("'LSL' required");
3625 else if (kind
== SHIFT_ASR_IMMEDIATE
3626 && shift
->properties
->index
!= SHIFT_ASR
)
3628 inst
.error
= _("'ASR' required");
3632 if (shift
->properties
->index
== SHIFT_RRX
)
3635 inst
.instruction
|= shift
->properties
->bit_field
;
3639 skip_whitespace (p
);
3641 if (kind
== NO_SHIFT_RESTRICT
&& reg_required_here (& p
, 8) != FAIL
)
3643 inst
.instruction
|= shift
->properties
->bit_field
| SHIFT_BY_REG
;
3647 else if (! is_immediate_prefix (* p
))
3649 inst
.error
= (NO_SHIFT_RESTRICT
3650 ? _("shift requires register or #expression")
3651 : _("shift requires #expression"));
3659 if (my_get_expression (& inst
.reloc
.exp
, & p
))
3662 /* Validate some simple #expressions. */
3663 if (inst
.reloc
.exp
.X_op
== O_constant
)
3665 unsigned num
= inst
.reloc
.exp
.X_add_number
;
3667 /* Reject operations greater than 32. */
3669 /* Reject a shift of 0 unless the mode allows it. */
3670 || (num
== 0 && shift
->properties
->allows_0
== 0)
3671 /* Reject a shift of 32 unless the mode allows it. */
3672 || (num
== 32 && shift
->properties
->allows_32
== 0)
3675 /* As a special case we allow a shift of zero for
3676 modes that do not support it to be recoded as an
3677 logical shift left of zero (ie nothing). We warn
3678 about this though. */
3681 as_warn (_("shift of 0 ignored."));
3682 shift
= & shift_names
[0];
3683 assert (shift
->properties
->index
== SHIFT_LSL
);
3687 inst
.error
= _("invalid immediate shift");
3692 /* Shifts of 32 are encoded as 0, for those shifts that
3697 inst
.instruction
|= (num
<< 7) | shift
->properties
->bit_field
;
3701 inst
.reloc
.type
= BFD_RELOC_ARM_SHIFT_IMM
;
3702 inst
.reloc
.pc_rel
= 0;
3703 inst
.instruction
|= shift
->properties
->bit_field
;
3711 do_sat (char ** str
, int bias
)
3716 skip_whitespace (*str
);
3718 /* Parse <Rd>, field. */
3719 if ((rd
= reg_required_here (str
, 12)) == FAIL
3720 || skip_past_comma (str
) == FAIL
)
3722 inst
.error
= BAD_ARGS
;
3727 inst
.error
= BAD_PC
;
3731 /* Parse #<immed>, field. */
3732 if (is_immediate_prefix (**str
))
3736 inst
.error
= _("immediate expression expected");
3739 if (my_get_expression (&expr
, str
))
3741 inst
.error
= _("bad expression");
3744 if (expr
.X_op
!= O_constant
)
3746 inst
.error
= _("constant expression expected");
3749 if (expr
.X_add_number
+ bias
< 0
3750 || expr
.X_add_number
+ bias
> 31)
3752 inst
.error
= _("immediate value out of range");
3755 inst
.instruction
|= (expr
.X_add_number
+ bias
) << 16;
3756 if (skip_past_comma (str
) == FAIL
)
3758 inst
.error
= BAD_ARGS
;
3762 /* Parse <Rm> field. */
3763 if ((rm
= reg_required_here (str
, 0)) == FAIL
)
3765 inst
.error
= BAD_ARGS
;
3770 inst
.error
= BAD_PC
;
3774 if (skip_past_comma (str
) == SUCCESS
)
3775 decode_shift (str
, SHIFT_LSL_OR_ASR_IMMEDIATE
);
3778 /* ARM V6 ssat (argument parse). */
3781 do_ssat (char * str
)
3783 do_sat (&str
, /*bias=*/-1);
3787 /* ARM V6 usat (argument parse). */
3790 do_usat (char * str
)
3792 do_sat (&str
, /*bias=*/0);
3797 do_sat16 (char ** str
, int bias
)
3802 skip_whitespace (*str
);
3804 /* Parse the <Rd> field. */
3805 if ((rd
= reg_required_here (str
, 12)) == FAIL
3806 || skip_past_comma (str
) == FAIL
)
3808 inst
.error
= BAD_ARGS
;
3813 inst
.error
= BAD_PC
;
3817 /* Parse #<immed>, field. */
3818 if (is_immediate_prefix (**str
))
3822 inst
.error
= _("immediate expression expected");
3825 if (my_get_expression (&expr
, str
))
3827 inst
.error
= _("bad expression");
3830 if (expr
.X_op
!= O_constant
)
3832 inst
.error
= _("constant expression expected");
3835 if (expr
.X_add_number
+ bias
< 0
3836 || expr
.X_add_number
+ bias
> 15)
3838 inst
.error
= _("immediate value out of range");
3841 inst
.instruction
|= (expr
.X_add_number
+ bias
) << 16;
3842 if (skip_past_comma (str
) == FAIL
)
3844 inst
.error
= BAD_ARGS
;
3848 /* Parse <Rm> field. */
3849 if ((rm
= reg_required_here (str
, 0)) == FAIL
)
3851 inst
.error
= BAD_ARGS
;
3856 inst
.error
= BAD_PC
;
3861 /* ARM V6 ssat16 (argument parse). */
3864 do_ssat16 (char * str
)
3866 do_sat16 (&str
, /*bias=*/-1);
3871 do_usat16 (char * str
)
3873 do_sat16 (&str
, /*bias=*/0);
3878 do_cps_mode (char ** str
)
3882 skip_whitespace (*str
);
3884 if (! is_immediate_prefix (**str
))
3886 inst
.error
= _("immediate expression expected");
3890 (*str
)++; /* Strip off the immediate signifier. */
3891 if (my_get_expression (&expr
, str
))
3893 inst
.error
= _("bad expression");
3897 if (expr
.X_op
!= O_constant
)
3899 inst
.error
= _("constant expression expected");
3903 /* The mode is a 5 bit field. Valid values are 0-31. */
3904 if (((unsigned) expr
.X_add_number
) > 31
3905 || (inst
.reloc
.exp
.X_add_number
) < 0)
3907 inst
.error
= _("invalid constant");
3911 inst
.instruction
|= expr
.X_add_number
;
3914 /* ARM V6 srs (argument parse). */
3920 skip_whitespace (str
);
3921 exclam
= strchr (str
, '!');
3929 inst
.instruction
|= WRITE_BACK
;
3935 /* ARM V6 SMMUL (argument parse). */
3938 do_smmul (char * str
)
3942 skip_whitespace (str
);
3943 if ((rd
= reg_required_here (&str
, 16)) == FAIL
3944 || skip_past_comma (&str
) == FAIL
3945 || (rm
= reg_required_here (&str
, 0)) == FAIL
3946 || skip_past_comma (&str
) == FAIL
3947 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
3949 inst
.error
= BAD_ARGS
;
3957 inst
.error
= BAD_PC
;
3964 /* ARM V6 SMLALD (argument parse). */
3967 do_smlald (char * str
)
3969 int rdlo
, rdhi
, rm
, rs
;
3971 skip_whitespace (str
);
3972 if ((rdlo
= reg_required_here (&str
, 12)) == FAIL
3973 || skip_past_comma (&str
) == FAIL
3974 || (rdhi
= reg_required_here (&str
, 16)) == FAIL
3975 || skip_past_comma (&str
) == FAIL
3976 || (rm
= reg_required_here (&str
, 0)) == FAIL
3977 || skip_past_comma (&str
) == FAIL
3978 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
3980 inst
.error
= BAD_ARGS
;
3989 inst
.error
= BAD_PC
;
3996 /* ARM V6 SMLAD (argument parse). Signed multiply accumulate dual.
3997 smlad{x}{<cond>} Rd, Rm, Rs, Rn */
4000 do_smlad (char * str
)
4004 skip_whitespace (str
);
4005 if ((rd
= reg_required_here (&str
, 16)) == FAIL
4006 || skip_past_comma (&str
) == FAIL
4007 || (rm
= reg_required_here (&str
, 0)) == FAIL
4008 || skip_past_comma (&str
) == FAIL
4009 || (rs
= reg_required_here (&str
, 8)) == FAIL
4010 || skip_past_comma (&str
) == FAIL
4011 || (rn
= reg_required_here (&str
, 12)) == FAIL
)
4013 inst
.error
= BAD_ARGS
;
4022 inst
.error
= BAD_PC
;
4029 /* Returns true if the endian-specifier indicates big-endianness. */
4032 do_endian_specifier (char * str
)
4036 skip_whitespace (str
);
4037 if (strlen (str
) < 2)
4038 inst
.error
= _("missing endian specifier");
4039 else if (strncasecmp (str
, "BE", 2) == 0)
4044 else if (strncasecmp (str
, "LE", 2) == 0)
4047 inst
.error
= _("valid endian specifiers are be or le");
4054 /* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
4055 preserving the other bits.
4057 setend <endian_specifier>, where <endian_specifier> is either
4061 do_setend (char * str
)
4063 if (do_endian_specifier (str
))
4064 inst
.instruction
|= 0x200;
4069 SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
4070 Condition defaults to COND_ALWAYS.
4071 Error if any register uses R15. */
4074 do_sxth (char * str
)
4078 int rotation_clear_mask
= 0xfffff3ff;
4079 int rotation_eight_mask
= 0x00000400;
4080 int rotation_sixteen_mask
= 0x00000800;
4081 int rotation_twenty_four_mask
= 0x00000c00;
4083 skip_whitespace (str
);
4084 if ((rd
= reg_required_here (&str
, 12)) == FAIL
4085 || skip_past_comma (&str
) == FAIL
4086 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4088 inst
.error
= BAD_ARGS
;
4092 else if (rd
== REG_PC
|| rm
== REG_PC
)
4094 inst
.error
= BAD_PC
;
4098 /* Zero out the rotation field. */
4099 inst
.instruction
&= rotation_clear_mask
;
4101 /* Check for lack of optional rotation field. */
4102 if (skip_past_comma (&str
) == FAIL
)
4108 /* Move past 'ROR'. */
4109 skip_whitespace (str
);
4110 if (strncasecmp (str
, "ROR", 3) == 0)
4114 inst
.error
= _("missing rotation field after comma");
4118 /* Get the immediate constant. */
4119 skip_whitespace (str
);
4120 if (is_immediate_prefix (* str
))
4124 inst
.error
= _("immediate expression expected");
4128 if (my_get_expression (&expr
, &str
))
4130 inst
.error
= _("bad expression");
4134 if (expr
.X_op
!= O_constant
)
4136 inst
.error
= _("constant expression expected");
4140 switch (expr
.X_add_number
)
4143 /* Rotation field has already been zeroed. */
4146 inst
.instruction
|= rotation_eight_mask
;
4150 inst
.instruction
|= rotation_sixteen_mask
;
4154 inst
.instruction
|= rotation_twenty_four_mask
;
4158 inst
.error
= _("rotation can be 8, 16, 24 or 0 when field is ommited");
4165 /* ARM V6 SXTAH extracts a 16-bit value from a register, sign
4166 extends it to 32-bits, and adds the result to a value in another
4167 register. You can specify a rotation by 0, 8, 16, or 24 bits
4168 before extracting the 16-bit value.
4169 SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
4170 Condition defaults to COND_ALWAYS.
4171 Error if any register uses R15. */
4174 do_sxtah (char * str
)
4178 int rotation_clear_mask
= 0xfffff3ff;
4179 int rotation_eight_mask
= 0x00000400;
4180 int rotation_sixteen_mask
= 0x00000800;
4181 int rotation_twenty_four_mask
= 0x00000c00;
4183 skip_whitespace (str
);
4184 if ((rd
= reg_required_here (&str
, 12)) == FAIL
4185 || skip_past_comma (&str
) == FAIL
4186 || (rn
= reg_required_here (&str
, 16)) == FAIL
4187 || skip_past_comma (&str
) == FAIL
4188 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4190 inst
.error
= BAD_ARGS
;
4194 else if (rd
== REG_PC
|| rn
== REG_PC
|| rm
== REG_PC
)
4196 inst
.error
= BAD_PC
;
4200 /* Zero out the rotation field. */
4201 inst
.instruction
&= rotation_clear_mask
;
4203 /* Check for lack of optional rotation field. */
4204 if (skip_past_comma (&str
) == FAIL
)
4210 /* Move past 'ROR'. */
4211 skip_whitespace (str
);
4212 if (strncasecmp (str
, "ROR", 3) == 0)
4216 inst
.error
= _("missing rotation field after comma");
4220 /* Get the immediate constant. */
4221 skip_whitespace (str
);
4222 if (is_immediate_prefix (* str
))
4226 inst
.error
= _("immediate expression expected");
4230 if (my_get_expression (&expr
, &str
))
4232 inst
.error
= _("bad expression");
4236 if (expr
.X_op
!= O_constant
)
4238 inst
.error
= _("constant expression expected");
4242 switch (expr
.X_add_number
)
4245 /* Rotation field has already been zeroed. */
4249 inst
.instruction
|= rotation_eight_mask
;
4253 inst
.instruction
|= rotation_sixteen_mask
;
4257 inst
.instruction
|= rotation_twenty_four_mask
;
4261 inst
.error
= _("rotation can be 8, 16, 24 or 0 when field is ommited");
4269 /* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
4270 word at the specified address and the following word
4272 Unconditionally executed.
4273 Error if Rn is R15. */
4280 skip_whitespace (str
);
4282 if ((rn
= reg_required_here (&str
, 16)) == FAIL
)
4287 inst
.error
= BAD_PC
;
4291 skip_whitespace (str
);
4295 inst
.instruction
|= WRITE_BACK
;
4301 /* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
4302 register (argument parse).
4304 Condition defaults to COND_ALWAYS.
4305 Error if Rd or Rm are R15. */
4312 skip_whitespace (str
);
4314 if ((rd
= reg_required_here (&str
, 12)) == FAIL
4315 || skip_past_comma (&str
) == FAIL
4316 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4317 inst
.error
= BAD_ARGS
;
4319 else if (rd
== REG_PC
|| rm
== REG_PC
)
4320 inst
.error
= BAD_PC
;
4326 /* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
4327 QADD16{<cond>} <Rd>, <Rn>, <Rm>
4328 Condition defaults to COND_ALWAYS.
4329 Error if Rd, Rn or Rm are R15. */
4332 do_qadd16 (char * str
)
4336 skip_whitespace (str
);
4338 if ((rd
= reg_required_here (&str
, 12)) == FAIL
4339 || skip_past_comma (&str
) == FAIL
4340 || (rn
= reg_required_here (&str
, 16)) == FAIL
4341 || skip_past_comma (&str
) == FAIL
4342 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4343 inst
.error
= BAD_ARGS
;
4345 else if (rd
== REG_PC
|| rm
== REG_PC
|| rn
== REG_PC
)
4346 inst
.error
= BAD_PC
;
4353 do_pkh_core (char * str
, int shift
)
4357 skip_whitespace (str
);
4358 if (((rd
= reg_required_here (&str
, 12)) == FAIL
)
4359 || (skip_past_comma (&str
) == FAIL
)
4360 || ((rn
= reg_required_here (&str
, 16)) == FAIL
)
4361 || (skip_past_comma (&str
) == FAIL
)
4362 || ((rm
= reg_required_here (&str
, 0)) == FAIL
))
4364 inst
.error
= BAD_ARGS
;
4368 else if (rd
== REG_PC
|| rn
== REG_PC
|| rm
== REG_PC
)
4370 inst
.error
= BAD_PC
;
4374 /* Check for optional shift immediate constant. */
4375 if (skip_past_comma (&str
) == FAIL
)
4377 if (shift
== SHIFT_ASR_IMMEDIATE
)
4379 /* If the shift specifier is ommited, turn the instruction
4380 into pkhbt rd, rm, rn. First, switch the instruction
4381 code, and clear the rn and rm fields. */
4382 inst
.instruction
&= 0xfff0f010;
4383 /* Now, re-encode the registers. */
4384 inst
.instruction
|= (rm
<< 16) | rn
;
4389 decode_shift (&str
, shift
);
4392 /* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
4393 PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
4394 Condition defaults to COND_ALWAYS.
4395 Error if Rd, Rn or Rm are R15. */
4398 do_pkhbt (char * str
)
4400 do_pkh_core (str
, SHIFT_LSL_IMMEDIATE
);
4403 /* ARM V6 PKHTB (Argument Parse). */
4406 do_pkhtb (char * str
)
4408 do_pkh_core (str
, SHIFT_ASR_IMMEDIATE
);
4411 /* ARM V6 Load Register Exclusive instruction (argument parse).
4412 LDREX{,B,D,H}{<cond>} <Rd, [<Rn>]
4413 Condition defaults to COND_ALWAYS.
4414 Error if Rd or Rn are R15.
4415 See ARMARMv6 A4.1.27: LDREX. */
4418 do_ldrex (char * str
)
4422 skip_whitespace (str
);
4425 if (((rd
= reg_required_here (&str
, 12)) == FAIL
)
4426 || (skip_past_comma (&str
) == FAIL
))
4428 inst
.error
= BAD_ARGS
;
4431 else if (rd
== REG_PC
)
4433 inst
.error
= BAD_PC
;
4436 skip_whitespace (str
);
4438 /* Skip past '['. */
4439 if ((strlen (str
) >= 1)
4440 &&strncmp (str
, "[", 1) == 0)
4442 skip_whitespace (str
);
4445 if ((rn
= reg_required_here (&str
, 16)) == FAIL
)
4447 inst
.error
= BAD_ARGS
;
4450 else if (rn
== REG_PC
)
4452 inst
.error
= BAD_PC
;
4455 skip_whitespace (str
);
4457 /* Skip past ']'. */
4458 if ((strlen (str
) >= 1)
4459 && strncmp (str
, "]", 1) == 0)
4465 /* ARM V6 change processor state instruction (argument parse)
4466 CPS, CPSIE, CSPID . */
4476 do_cps_flags (char ** str
, int thumb_p
)
4481 unsigned long arm_value
;
4482 unsigned long thumb_value
;
4484 static struct cps_flag flag_table
[] =
4493 skip_whitespace (*str
);
4495 /* Get the a, f and i flags. */
4496 while (**str
&& **str
!= ',')
4499 struct cps_flag
*q
= flag_table
+ sizeof (flag_table
)/sizeof (*p
);
4501 for (p
= flag_table
; p
< q
; ++p
)
4502 if (strncasecmp (*str
, &p
->character
, 1) == 0)
4504 inst
.instruction
|= (thumb_p
? p
->thumb_value
: p
->arm_value
);
4510 inst
.error
= _("unrecognized flag");
4517 inst
.error
= _("no 'a', 'i', or 'f' flags for 'cps'");
4521 do_cpsi (char * str
)
4523 do_cps_flags (&str
, /*thumb_p=*/0);
4525 if (skip_past_comma (&str
) == SUCCESS
)
4527 skip_whitespace (str
);
4533 /* ARM V6T2 bitfield manipulation instructions. */
4536 five_bit_unsigned_immediate (char **str
)
4540 skip_whitespace (*str
);
4541 if (!is_immediate_prefix (**str
))
4543 inst
.error
= _("immediate expression expected");
4547 if (my_get_expression (&expr
, str
))
4549 inst
.error
= _("bad expression");
4552 if (expr
.X_op
!= O_constant
)
4554 inst
.error
= _("constant expression expected");
4557 if (expr
.X_add_number
< 0 || expr
.X_add_number
> 32)
4559 inst
.error
= _("immediate value out of range");
4563 return expr
.X_add_number
;
4567 bfci_lsb_and_width (char *str
)
4571 if ((lsb
= five_bit_unsigned_immediate (&str
)) == -1)
4574 if (skip_past_comma (&str
) == FAIL
)
4576 inst
.error
= BAD_ARGS
;
4579 if ((width
= five_bit_unsigned_immediate (&str
)) == -1)
4584 if (width
== 0 || lsb
== 32)
4586 inst
.error
= _("immediate value out of range");
4589 else if (width
+ lsb
> 32)
4591 inst
.error
= _("bit-field extends past end of register");
4595 /* Convert to LSB/MSB and write to register. */
4596 inst
.instruction
|= lsb
<< 7;
4597 inst
.instruction
|= (width
+ lsb
- 1) << 16;
4606 skip_whitespace (str
);
4607 if (((rd
= reg_required_here (&str
, 12)) == FAIL
)
4608 || (skip_past_comma (&str
) == FAIL
))
4610 inst
.error
= BAD_ARGS
;
4613 else if (rd
== REG_PC
)
4615 inst
.error
= BAD_PC
;
4619 bfci_lsb_and_width (str
);
4628 skip_whitespace (str
);
4629 if (((rd
= reg_required_here (&str
, 12)) == FAIL
)
4630 || (skip_past_comma (&str
) == FAIL
))
4632 inst
.error
= BAD_ARGS
;
4635 else if (rd
== REG_PC
)
4637 inst
.error
= BAD_PC
;
4641 /* Rm. Accept #0 in this position as an alternative syntax for bfc. */
4642 skip_whitespace (str
);
4643 if (is_immediate_prefix (*str
))
4647 if (my_get_expression (&expr
, &str
))
4649 inst
.error
= _("bad expression");
4652 if (expr
.X_op
!= O_constant
)
4654 inst
.error
= _("constant expression expected");
4657 if (expr
.X_add_number
!= 0)
4659 inst
.error
= _("immediate value out of range");
4662 inst
.instruction
|= 0x0000000f; /* Rm = PC -> bfc, not bfi. */
4666 if ((rm
= reg_required_here (&str
, 0)) == FAIL
)
4668 inst
.error
= BAD_ARGS
;
4671 else if (rm
== REG_PC
)
4673 inst
.error
= BAD_PC
;
4677 if (skip_past_comma (&str
) == FAIL
)
4679 inst
.error
= BAD_ARGS
;
4683 bfci_lsb_and_width (str
);
4692 skip_whitespace (str
);
4693 if (reg_required_here (&str
, 12) == FAIL
4694 || skip_past_comma (&str
) == FAIL
)
4696 inst
.error
= BAD_ARGS
;
4701 skip_whitespace (str
);
4702 if (reg_required_here (&str
, 0) == FAIL
4703 || skip_past_comma (&str
) == FAIL
)
4705 inst
.error
= BAD_ARGS
;
4709 if ((lsb
= five_bit_unsigned_immediate (&str
)) == -1)
4712 if (skip_past_comma (&str
) == FAIL
)
4714 inst
.error
= BAD_ARGS
;
4717 if ((width
= five_bit_unsigned_immediate (&str
)) == -1)
4722 if (width
== 0 || lsb
== 32)
4724 inst
.error
= _("immediate value out of range");
4727 else if (width
+ lsb
> 32)
4729 inst
.error
= _("bit-field extends past end of register");
4733 inst
.instruction
|= lsb
<< 7;
4734 inst
.instruction
|= (width
- 1) << 16;
4741 skip_whitespace (str
);
4742 if (reg_required_here (&str
, 12) == FAIL
4743 || skip_past_comma (&str
) == FAIL
)
4745 inst
.error
= BAD_ARGS
;
4750 skip_whitespace (str
);
4751 if (reg_required_here (&str
, 0) == FAIL
)
4753 inst
.error
= BAD_ARGS
;
4760 /* ARM V6T2 16-bit immediate register load: MOV[WT]{cond} Rd, #<imm16>. */
4762 do_mov16 (char *str
)
4768 skip_whitespace (str
);
4769 if (((rd
= reg_required_here (&str
, 12)) == FAIL
)
4770 || (skip_past_comma (&str
) == FAIL
))
4772 inst
.error
= BAD_ARGS
;
4775 else if (rd
== REG_PC
)
4777 inst
.error
= BAD_PC
;
4782 skip_whitespace (str
);
4783 if (!is_immediate_prefix (*str
))
4785 inst
.error
= _("immediate expression expected");
4789 if (my_get_expression (&expr
, &str
))
4791 inst
.error
= _("bad expression");
4794 if (expr
.X_op
!= O_constant
)
4796 inst
.error
= _("constant expression expected");
4799 if (expr
.X_add_number
< 0 || expr
.X_add_number
> 65535)
4801 inst
.error
= _("immediate value out of range");
4807 /* The value is in two pieces: 0:11, 16:19. */
4808 inst
.instruction
|= (expr
.X_add_number
& 0x00000fff);
4809 inst
.instruction
|= (expr
.X_add_number
& 0x0000f000) << 4;
4813 /* THUMB V5 breakpoint instruction (argument parse)
4817 do_t_bkpt (char * str
)
4820 unsigned long number
;
4822 skip_whitespace (str
);
4824 /* Allow optional leading '#'. */
4825 if (is_immediate_prefix (*str
))
4828 memset (& expr
, '\0', sizeof (expr
));
4829 if (my_get_expression (& expr
, & str
)
4830 || (expr
.X_op
!= O_constant
4831 /* As a convenience we allow 'bkpt' without an operand. */
4832 && expr
.X_op
!= O_absent
))
4834 inst
.error
= _("bad expression");
4838 number
= expr
.X_add_number
;
4840 /* Check it fits an 8 bit unsigned. */
4841 if (number
!= (number
& 0xff))
4843 inst
.error
= _("immediate value out of range");
4847 inst
.instruction
|= number
;
4853 static bfd_reloc_code_real_type
4854 arm_parse_reloc (void)
4863 bfd_reloc_code_real_type reloc
;
4867 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
4868 MAP ("(got)", BFD_RELOC_ARM_GOT32
),
4869 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF
),
4870 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
4871 branch instructions generated by GCC for PLT relocs. */
4872 MAP ("(plt)", BFD_RELOC_ARM_PLT32
),
4873 MAP ("(target1)", BFD_RELOC_ARM_TARGET1
),
4874 MAP ("(sbrel)", BFD_RELOC_ARM_SBREL32
),
4875 MAP ("(target2)", BFD_RELOC_ARM_TARGET2
),
4876 { NULL
, 0, BFD_RELOC_UNUSED
}
4880 for (i
= 0, ip
= input_line_pointer
;
4881 i
< sizeof (id
) && (ISALNUM (*ip
) || ISPUNCT (*ip
));
4883 id
[i
] = TOLOWER (*ip
);
4885 for (i
= 0; reloc_map
[i
].str
; i
++)
4886 if (strncmp (id
, reloc_map
[i
].str
, reloc_map
[i
].len
) == 0)
4889 input_line_pointer
+= reloc_map
[i
].len
;
4891 return reloc_map
[i
].reloc
;
4895 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
4896 Expects inst.instruction is set for BLX(1).
4897 Note: this is cloned from do_branch, and the reloc changed to be a
4898 new one that can cope with setting one extra bit (the H bit). */
4901 do_branch25 (char * str
)
4903 if (my_get_expression (& inst
.reloc
.exp
, & str
))
4910 /* ScottB: February 5, 1998 */
4911 /* Check to see of PLT32 reloc required for the instruction. */
4913 /* arm_parse_reloc() works on input_line_pointer.
4914 We actually want to parse the operands to the branch instruction
4915 passed in 'str'. Save the input pointer and restore it later. */
4916 save_in
= input_line_pointer
;
4917 input_line_pointer
= str
;
4919 if (inst
.reloc
.exp
.X_op
== O_symbol
4921 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
4923 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
4924 inst
.reloc
.pc_rel
= 0;
4925 /* Modify str to point to after parsed operands, otherwise
4926 end_of_line() will complain about the (PLT) left in str. */
4927 str
= input_line_pointer
;
4931 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
4932 inst
.reloc
.pc_rel
= 1;
4935 input_line_pointer
= save_in
;
4938 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
4939 inst
.reloc
.pc_rel
= 1;
4940 #endif /* OBJ_ELF */
4945 /* ARM V5 branch-link-exchange instruction (argument parse)
4946 BLX <target_addr> ie BLX(1)
4947 BLX{<condition>} <Rm> ie BLX(2)
4948 Unfortunately, there are two different opcodes for this mnemonic.
4949 So, the insns[].value is not used, and the code here zaps values
4950 into inst.instruction.
4951 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
4959 skip_whitespace (mystr
);
4960 rm
= reg_required_here (& mystr
, 0);
4962 /* The above may set inst.error. Ignore his opinion. */
4967 /* Arg is a register.
4968 Use the condition code our caller put in inst.instruction.
4969 Pass ourselves off as a BX with a funny opcode. */
4970 inst
.instruction
|= 0x012fff30;
4975 /* This must be is BLX <target address>, no condition allowed. */
4976 if (inst
.instruction
!= COND_ALWAYS
)
4978 inst
.error
= BAD_COND
;
4982 inst
.instruction
= 0xfafffffe;
4984 /* Process like a B/BL, but with a different reloc.
4985 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
4990 /* ARM V5 Thumb BLX (argument parse)
4991 BLX <target_addr> which is BLX(1)
4992 BLX <Rm> which is BLX(2)
4993 Unfortunately, there are two different opcodes for this mnemonic.
4994 So, the tinsns[].value is not used, and the code here zaps values
4995 into inst.instruction. */
4998 do_t_blx (char * str
)
5003 skip_whitespace (mystr
);
5004 inst
.instruction
= 0x4780;
5006 /* Note that this call is to the ARM register recognizer. BLX(2)
5007 uses the ARM register space, not the Thumb one, so a call to
5008 thumb_reg() would be wrong. */
5009 rm
= reg_required_here (& mystr
, 3);
5014 /* It's BLX(2). The .instruction was zapped with rm & is final. */
5019 /* No ARM register. This must be BLX(1). Change the .instruction. */
5020 inst
.instruction
= 0xf7ffeffe;
5023 if (my_get_expression (& inst
.reloc
.exp
, & mystr
))
5026 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BLX
;
5027 inst
.reloc
.pc_rel
= 1;
5030 end_of_line (mystr
);
5033 /* ARM V5 breakpoint instruction (argument parse)
5034 BKPT <16 bit unsigned immediate>
5035 Instruction is not conditional.
5036 The bit pattern given in insns[] has the COND_ALWAYS condition,
5037 and it is an error if the caller tried to override that. */
5040 do_bkpt (char * str
)
5043 unsigned long number
;
5045 skip_whitespace (str
);
5047 /* Allow optional leading '#'. */
5048 if (is_immediate_prefix (* str
))
5051 memset (& expr
, '\0', sizeof (expr
));
5053 if (my_get_expression (& expr
, & str
)
5054 || (expr
.X_op
!= O_constant
5055 /* As a convenience we allow 'bkpt' without an operand. */
5056 && expr
.X_op
!= O_absent
))
5058 inst
.error
= _("bad expression");
5062 number
= expr
.X_add_number
;
5064 /* Check it fits a 16 bit unsigned. */
5065 if (number
!= (number
& 0xffff))
5067 inst
.error
= _("immediate value out of range");
5071 /* Top 12 of 16 bits to bits 19:8. */
5072 inst
.instruction
|= (number
& 0xfff0) << 4;
5074 /* Bottom 4 of 16 bits to bits 3:0. */
5075 inst
.instruction
|= number
& 0xf;
5080 /* THUMB CPS instruction (argument parse). */
5083 do_t_cps (char * str
)
5085 do_cps_flags (&str
, /*thumb_p=*/1);
5089 /* Parse and validate that a register is of the right form, this saves
5090 repeated checking of this information in many similar cases.
5091 Unlike the 32-bit case we do not insert the register into the opcode
5092 here, since the position is often unknown until the full instruction
5096 thumb_reg (char ** strp
, int hi_lo
)
5100 if ((reg
= reg_required_here (strp
, -1)) == FAIL
)
5108 inst
.error
= _("lo register required");
5116 inst
.error
= _("hi register required");
5129 thumb_mov_compare (char * str
, int move
)
5133 skip_whitespace (str
);
5135 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
5136 || skip_past_comma (&str
) == FAIL
)
5139 inst
.error
= BAD_ARGS
;
5143 if (move
!= THUMB_CPY
&& is_immediate_prefix (*str
))
5146 if (my_get_expression (&inst
.reloc
.exp
, &str
))
5149 else if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
5154 if (move
!= THUMB_CPY
&& Rs
< 8 && Rd
< 8)
5156 if (move
== THUMB_MOVE
)
5157 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
5158 since a MOV instruction produces unpredictable results. */
5159 inst
.instruction
= T_OPCODE_ADD_I3
;
5161 inst
.instruction
= T_OPCODE_CMP_LR
;
5162 inst
.instruction
|= Rd
| (Rs
<< 3);
5166 if (move
== THUMB_MOVE
)
5167 inst
.instruction
= T_OPCODE_MOV_HR
;
5168 else if (move
!= THUMB_CPY
)
5169 inst
.instruction
= T_OPCODE_CMP_HR
;
5172 inst
.instruction
|= THUMB_H1
;
5175 inst
.instruction
|= THUMB_H2
;
5177 inst
.instruction
|= (Rd
& 7) | ((Rs
& 7) << 3);
5184 inst
.error
= _("only lo regs allowed with immediate");
5188 if (move
== THUMB_MOVE
)
5189 inst
.instruction
= T_OPCODE_MOV_I8
;
5191 inst
.instruction
= T_OPCODE_CMP_I8
;
5193 inst
.instruction
|= Rd
<< 8;
5195 if (inst
.reloc
.exp
.X_op
!= O_constant
)
5196 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_IMM
;
5199 unsigned value
= inst
.reloc
.exp
.X_add_number
;
5203 inst
.error
= _("invalid immediate");
5207 inst
.instruction
|= value
;
5214 /* THUMB CPY instruction (argument parse). */
5217 do_t_cpy (char * str
)
5219 thumb_mov_compare (str
, THUMB_CPY
);
5222 /* THUMB SETEND instruction (argument parse). */
5225 do_t_setend (char * str
)
5227 if (do_endian_specifier (str
))
5228 inst
.instruction
|= 0x8;
5231 /* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
5233 static unsigned long
5234 check_iwmmxt_insn (char * str
,
5235 enum iwmmxt_insn_type insn_type
,
5239 const char * inst_error
;
5241 unsigned long number
;
5243 inst_error
= inst
.error
;
5245 inst
.error
= BAD_ARGS
;
5246 skip_whitespace (str
);
5251 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
5256 if ((wreg_required_here (&str
, 0, IWMMXT_REG_WR
)) == FAIL
)
5261 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
5262 || skip_past_comma (&str
) == FAIL
5263 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
))
5268 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
5269 || skip_past_comma (&str
) == FAIL
5270 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5271 || skip_past_comma (&str
) == FAIL
5272 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
))
5277 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
5278 || skip_past_comma (&str
) == FAIL
5279 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5280 || skip_past_comma (&str
) == FAIL
5281 || wreg_required_here (&str
, 0, IWMMXT_REG_WCG
) == FAIL
))
5286 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5287 || skip_past_comma (&str
) == FAIL
5288 || reg_required_here (&str
, 12) == FAIL
))
5293 if ((reg_required_here (&str
, 12) == FAIL
5294 || skip_past_comma (&str
) == FAIL
5295 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
))
5300 if ((wreg_required_here (&str
, 5, IWMMXT_REG_WR
) == FAIL
5301 || skip_past_comma (&str
) == FAIL
5302 || reg_required_here (&str
, 0) == FAIL
5303 || skip_past_comma (&str
) == FAIL
5304 || reg_required_here (&str
, 12) == FAIL
))
5309 if ((wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
5310 || skip_past_comma (&str
) == FAIL
5311 || reg_required_here (&str
, 12) == FAIL
5312 || skip_past_comma (&str
) == FAIL
5313 || reg_required_here (&str
, 16) == FAIL
))
5318 if ((reg_required_here (&str
, 12) == FAIL
5319 || skip_past_comma (&str
) == FAIL
5320 || reg_required_here (&str
, 16) == FAIL
5321 || skip_past_comma (&str
) == FAIL
5322 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
))
5327 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WC
) == FAIL
5328 || skip_past_comma (&str
) == FAIL
5329 || reg_required_here (&str
, 12) == FAIL
))
5334 if ((reg_required_here (&str
, 12) == FAIL
5335 || skip_past_comma (&str
) == FAIL
5336 || wreg_required_here (&str
, 16, IWMMXT_REG_WC
) == FAIL
))
5341 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5342 || skip_past_comma (&str
) == FAIL
5343 || reg_required_here (&str
, 12) == FAIL
5344 || skip_past_comma (&str
) == FAIL
))
5349 if ((reg_required_here (&str
, 12) == FAIL
5350 || skip_past_comma (&str
) == FAIL
))
5355 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
5356 || skip_past_comma (&str
) == FAIL
5357 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5358 || skip_past_comma (&str
) == FAIL
5359 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
5360 || skip_past_comma (&str
) == FAIL
))
5365 if ((reg_required_here (&str
, 12) == FAIL
5366 || skip_past_comma (&str
) == FAIL
5367 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5368 || skip_past_comma (&str
) == FAIL
))
5373 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == 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 (immediate_size
== 0)
5384 inst
.error
= inst_error
;
5389 skip_whitespace (str
);
5391 /* Allow optional leading '#'. */
5392 if (is_immediate_prefix (* str
))
5395 memset (& expr
, '\0', sizeof (expr
));
5397 if (my_get_expression (& expr
, & str
) || (expr
.X_op
!= O_constant
))
5399 inst
.error
= _("bad or missing expression");
5403 number
= expr
.X_add_number
;
5405 if (number
!= (number
& immediate_size
))
5407 inst
.error
= _("immediate value out of range");
5411 inst
.error
= inst_error
;
5417 do_iwmmxt_byte_addr (char * str
)
5419 int op
= (inst
.instruction
& 0x300) >> 8;
5422 inst
.instruction
&= ~0x300;
5423 inst
.instruction
|= (op
& 1) << 22 | (op
& 2) << 7;
5425 skip_whitespace (str
);
5427 if ((reg
= wreg_required_here (&str
, 12, IWMMXT_REG_WR_OR_WC
)) == FAIL
5428 || skip_past_comma (& str
) == FAIL
5429 || cp_byte_address_required_here (&str
) == FAIL
)
5432 inst
.error
= BAD_ARGS
;
5437 if (wc_register (reg
))
5439 as_bad (_("non-word size not supported with control register"));
5440 inst
.instruction
|= 0xf0000100;
5441 inst
.instruction
&= ~0x00400000;
5446 do_iwmmxt_tandc (char * str
)
5450 reg
= check_iwmmxt_insn (str
, check_rd
, 0);
5452 if (reg
!= REG_PC
&& !inst
.error
)
5453 inst
.error
= _("only r15 allowed here");
5457 do_iwmmxt_tbcst (char * str
)
5459 check_iwmmxt_insn (str
, check_tbcst
, 0);
5463 do_iwmmxt_textrc (char * str
)
5465 unsigned long number
;
5467 if ((number
= check_iwmmxt_insn (str
, check_textrc
, 7)) == (unsigned long) FAIL
)
5470 inst
.instruction
|= number
& 0x7;
5474 do_iwmmxt_textrm (char * str
)
5476 unsigned long number
;
5478 if ((number
= check_iwmmxt_insn (str
, check_textrm
, 7)) == (unsigned long) FAIL
)
5481 inst
.instruction
|= number
& 0x7;
5485 do_iwmmxt_tinsr (char * str
)
5487 unsigned long number
;
5489 if ((number
= check_iwmmxt_insn (str
, check_tinsr
, 7)) == (unsigned long) FAIL
)
5492 inst
.instruction
|= number
& 0x7;
5496 do_iwmmxt_tmcr (char * str
)
5498 check_iwmmxt_insn (str
, check_tmcr
, 0);
5502 do_iwmmxt_tmcrr (char * str
)
5504 check_iwmmxt_insn (str
, check_tmcrr
, 0);
5508 do_iwmmxt_tmia (char * str
)
5510 check_iwmmxt_insn (str
, check_tmia
, 0);
5514 do_iwmmxt_tmovmsk (char * str
)
5516 check_iwmmxt_insn (str
, check_tmovmsk
, 0);
5520 do_iwmmxt_tmrc (char * str
)
5522 check_iwmmxt_insn (str
, check_tmrc
, 0);
5526 do_iwmmxt_tmrrc (char * str
)
5528 check_iwmmxt_insn (str
, check_tmrrc
, 0);
5532 do_iwmmxt_torc (char * str
)
5534 check_iwmmxt_insn (str
, check_rd
, 0);
5538 do_iwmmxt_waligni (char * str
)
5540 unsigned long number
;
5542 if ((number
= check_iwmmxt_insn (str
, check_waligni
, 7)) == (unsigned long) FAIL
)
5545 inst
.instruction
|= ((number
& 0x7) << 20);
5549 do_iwmmxt_wmov (char * str
)
5551 if (check_iwmmxt_insn (str
, check_wrwr
, 0) == (unsigned long) FAIL
)
5554 inst
.instruction
|= ((inst
.instruction
>> 16) & 0xf);
5558 do_iwmmxt_word_addr (char * str
)
5560 int op
= (inst
.instruction
& 0x300) >> 8;
5563 inst
.instruction
&= ~0x300;
5564 inst
.instruction
|= (op
& 1) << 22 | (op
& 2) << 7;
5566 skip_whitespace (str
);
5568 if ((reg
= wreg_required_here (&str
, 12, IWMMXT_REG_WR_OR_WC
)) == FAIL
5569 || skip_past_comma (& str
) == FAIL
5570 || cp_address_required_here (& str
, CP_WB_OK
) == FAIL
)
5573 inst
.error
= BAD_ARGS
;
5578 if (wc_register (reg
))
5580 if ((inst
.instruction
& COND_MASK
) != COND_ALWAYS
)
5581 as_bad (_("conditional execution not supported with control register"));
5583 as_bad (_("non-word size not supported with control register"));
5584 inst
.instruction
|= 0xf0000100;
5585 inst
.instruction
&= ~0x00400000;
5590 do_iwmmxt_wrwr (char * str
)
5592 check_iwmmxt_insn (str
, check_wrwr
, 0);
5596 do_iwmmxt_wrwrwcg (char * str
)
5598 check_iwmmxt_insn (str
, check_wrwrwcg
, 0);
5602 do_iwmmxt_wrwrwr (char * str
)
5604 check_iwmmxt_insn (str
, check_wrwrwr
, 0);
5608 do_iwmmxt_wshufh (char * str
)
5610 unsigned long number
;
5612 if ((number
= check_iwmmxt_insn (str
, check_wshufh
, 0xff)) == (unsigned long) FAIL
)
5615 inst
.instruction
|= ((number
& 0xf0) << 16) | (number
& 0xf);
5619 do_iwmmxt_wzero (char * str
)
5621 if (check_iwmmxt_insn (str
, check_wr
, 0) == (unsigned long) FAIL
)
5624 inst
.instruction
|= ((inst
.instruction
& 0xf) << 12) | ((inst
.instruction
& 0xf) << 16);
5627 /* Xscale multiply-accumulate (argument parse)
5630 MIAxycc acc0,Rm,Rs. */
5633 do_xsc_mia (char * str
)
5638 if (accum0_required_here (& str
) == FAIL
)
5639 inst
.error
= ERR_NO_ACCUM
;
5641 else if (skip_past_comma (& str
) == FAIL
5642 || (rm
= reg_required_here (& str
, 0)) == FAIL
)
5643 inst
.error
= BAD_ARGS
;
5645 else if (skip_past_comma (& str
) == FAIL
5646 || (rs
= reg_required_here (& str
, 12)) == FAIL
)
5647 inst
.error
= BAD_ARGS
;
5649 /* inst.instruction has now been zapped with both rm and rs. */
5650 else if (rm
== REG_PC
|| rs
== REG_PC
)
5651 inst
.error
= BAD_PC
; /* Undefined result if rm or rs is R15. */
5657 /* Xscale move-accumulator-register (argument parse)
5659 MARcc acc0,RdLo,RdHi. */
5662 do_xsc_mar (char * str
)
5666 if (accum0_required_here (& str
) == FAIL
)
5667 inst
.error
= ERR_NO_ACCUM
;
5669 else if (skip_past_comma (& str
) == FAIL
5670 || (rdlo
= reg_required_here (& str
, 12)) == FAIL
)
5671 inst
.error
= BAD_ARGS
;
5673 else if (skip_past_comma (& str
) == FAIL
5674 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
5675 inst
.error
= BAD_ARGS
;
5677 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5678 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
5679 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
5685 /* Xscale move-register-accumulator (argument parse)
5687 MRAcc RdLo,RdHi,acc0. */
5690 do_xsc_mra (char * str
)
5695 skip_whitespace (str
);
5697 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
)
5698 inst
.error
= BAD_ARGS
;
5700 else if (skip_past_comma (& str
) == FAIL
5701 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
5702 inst
.error
= BAD_ARGS
;
5704 else if (skip_past_comma (& str
) == FAIL
5705 || accum0_required_here (& str
) == FAIL
)
5706 inst
.error
= ERR_NO_ACCUM
;
5708 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5709 else if (rdlo
== rdhi
)
5710 inst
.error
= BAD_ARGS
; /* Undefined result if 2 writes to same reg. */
5712 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
5713 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
5719 ldst_extend (char ** str
)
5728 if (my_get_expression (& inst
.reloc
.exp
, str
))
5731 if (inst
.reloc
.exp
.X_op
== O_constant
)
5733 int value
= inst
.reloc
.exp
.X_add_number
;
5735 if (value
< -4095 || value
> 4095)
5737 inst
.error
= _("address offset too large");
5747 inst
.instruction
|= add
| value
;
5751 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
5752 inst
.reloc
.pc_rel
= 0;
5765 if (reg_required_here (str
, 0) == FAIL
)
5768 inst
.instruction
|= add
| OFFSET_REG
;
5769 if (skip_past_comma (str
) == SUCCESS
)
5770 return decode_shift (str
, SHIFT_IMMEDIATE
);
5776 /* ARMv5TE: Preload-Cache
5780 Syntactically, like LDR with B=1, W=0, L=1. */
5787 skip_whitespace (str
);
5791 inst
.error
= _("'[' expected after PLD mnemonic");
5796 skip_whitespace (str
);
5798 if ((rd
= reg_required_here (& str
, 16)) == FAIL
)
5801 skip_whitespace (str
);
5807 skip_whitespace (str
);
5809 /* Post-indexed addressing is not allowed with PLD. */
5810 if (skip_past_comma (&str
) == SUCCESS
)
5813 = _("post-indexed expression used in preload instruction");
5816 else if (*str
== '!') /* [Rn]! */
5818 inst
.error
= _("writeback used in preload instruction");
5822 inst
.instruction
|= INDEX_UP
| PRE_INDEX
;
5824 else /* [Rn, ...] */
5826 if (skip_past_comma (& str
) == FAIL
)
5828 inst
.error
= _("pre-indexed expression expected");
5832 if (ldst_extend (&str
) == FAIL
)
5835 skip_whitespace (str
);
5839 inst
.error
= _("missing ]");
5844 skip_whitespace (str
);
5846 if (* str
== '!') /* [Rn]! */
5848 inst
.error
= _("writeback used in preload instruction");
5852 inst
.instruction
|= PRE_INDEX
;
5858 /* ARMv5TE load-consecutive (argument parse)
5865 do_ldrd (char * str
)
5870 skip_whitespace (str
);
5872 if ((rd
= reg_required_here (& str
, 12)) == FAIL
)
5874 inst
.error
= BAD_ARGS
;
5878 if (skip_past_comma (& str
) == FAIL
5879 || (rn
= ld_mode_required_here (& str
)) == FAIL
)
5882 inst
.error
= BAD_ARGS
;
5886 /* inst.instruction has now been zapped with Rd and the addressing mode. */
5887 if (rd
& 1) /* Unpredictable result if Rd is odd. */
5889 inst
.error
= _("destination register must be even");
5895 inst
.error
= _("r14 not allowed here");
5899 if (((rd
== rn
) || (rd
+ 1 == rn
))
5900 && ((inst
.instruction
& WRITE_BACK
)
5901 || (!(inst
.instruction
& PRE_INDEX
))))
5902 as_warn (_("pre/post-indexing used when modified address register is destination"));
5904 /* For an index-register load, the index register must not overlap the
5905 destination (even if not write-back). */
5906 if ((inst
.instruction
& V4_STR_BIT
) == 0
5907 && (inst
.instruction
& HWOFFSET_IMM
) == 0)
5909 int rm
= inst
.instruction
& 0x0000000f;
5911 if (rm
== rd
|| (rm
== rd
+ 1))
5912 as_warn (_("ldrd destination registers must not overlap index register"));
5918 /* Returns the index into fp_values of a floating point number,
5919 or -1 if not in the table. */
5922 my_get_float_expression (char ** str
)
5924 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
5930 memset (words
, 0, MAX_LITTLENUMS
* sizeof (LITTLENUM_TYPE
));
5932 /* Look for a raw floating point number. */
5933 if ((save_in
= atof_ieee (*str
, 'x', words
)) != NULL
5934 && is_end_of_line
[(unsigned char) *save_in
])
5936 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
5938 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
5940 if (words
[j
] != fp_values
[i
][j
])
5944 if (j
== MAX_LITTLENUMS
)
5952 /* Try and parse a more complex expression, this will probably fail
5953 unless the code uses a floating point prefix (eg "0f"). */
5954 save_in
= input_line_pointer
;
5955 input_line_pointer
= *str
;
5956 if (expression (&exp
) == absolute_section
5957 && exp
.X_op
== O_big
5958 && exp
.X_add_number
< 0)
5960 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
5962 if (gen_to_words (words
, 5, (long) 15) == 0)
5964 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
5966 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
5968 if (words
[j
] != fp_values
[i
][j
])
5972 if (j
== MAX_LITTLENUMS
)
5974 *str
= input_line_pointer
;
5975 input_line_pointer
= save_in
;
5982 *str
= input_line_pointer
;
5983 input_line_pointer
= save_in
;
5987 /* We handle all bad expressions here, so that we can report the faulty
5988 instruction in the error message. */
5990 md_operand (expressionS
* expr
)
5992 if (in_my_get_expression
)
5994 expr
->X_op
= O_illegal
;
5995 if (inst
.error
== NULL
)
5996 inst
.error
= _("bad expression");
6000 /* Do those data_ops which can take a negative immediate constant
6001 by altering the instruction. A bit of a hack really.
6005 by inverting the second operand, and
6008 by negating the second operand. */
6011 negate_data_op (unsigned long * instruction
,
6012 unsigned long value
)
6015 unsigned long negated
, inverted
;
6017 negated
= validate_immediate (-value
);
6018 inverted
= validate_immediate (~value
);
6020 op
= (*instruction
>> DATA_OP_SHIFT
) & 0xf;
6023 /* First negates. */
6024 case OPCODE_SUB
: /* ADD <-> SUB */
6025 new_inst
= OPCODE_ADD
;
6030 new_inst
= OPCODE_SUB
;
6034 case OPCODE_CMP
: /* CMP <-> CMN */
6035 new_inst
= OPCODE_CMN
;
6040 new_inst
= OPCODE_CMP
;
6044 /* Now Inverted ops. */
6045 case OPCODE_MOV
: /* MOV <-> MVN */
6046 new_inst
= OPCODE_MVN
;
6051 new_inst
= OPCODE_MOV
;
6055 case OPCODE_AND
: /* AND <-> BIC */
6056 new_inst
= OPCODE_BIC
;
6061 new_inst
= OPCODE_AND
;
6065 case OPCODE_ADC
: /* ADC <-> SBC */
6066 new_inst
= OPCODE_SBC
;
6071 new_inst
= OPCODE_ADC
;
6075 /* We cannot do anything. */
6080 if (value
== (unsigned) FAIL
)
6083 *instruction
&= OPCODE_MASK
;
6084 *instruction
|= new_inst
<< DATA_OP_SHIFT
;
6089 data_op2 (char ** str
)
6094 skip_whitespace (* str
);
6096 if (reg_required_here (str
, 0) != FAIL
)
6098 if (skip_past_comma (str
) == SUCCESS
)
6099 /* Shift operation on register. */
6100 return decode_shift (str
, NO_SHIFT_RESTRICT
);
6106 /* Immediate expression. */
6107 if (is_immediate_prefix (**str
))
6112 if (my_get_expression (&inst
.reloc
.exp
, str
))
6115 if (inst
.reloc
.exp
.X_add_symbol
)
6117 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
6118 inst
.reloc
.pc_rel
= 0;
6122 if (skip_past_comma (str
) == SUCCESS
)
6124 /* #x, y -- ie explicit rotation by Y. */
6125 if (my_get_expression (&expr
, str
))
6128 if (expr
.X_op
!= O_constant
)
6130 inst
.error
= _("constant expression expected");
6134 /* Rotate must be a multiple of 2. */
6135 if (((unsigned) expr
.X_add_number
) > 30
6136 || (expr
.X_add_number
& 1) != 0
6137 || ((unsigned) inst
.reloc
.exp
.X_add_number
) > 255)
6139 inst
.error
= _("invalid constant");
6142 inst
.instruction
|= INST_IMMEDIATE
;
6143 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
6144 inst
.instruction
|= expr
.X_add_number
<< 7;
6148 /* Implicit rotation, select a suitable one. */
6149 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
6153 /* Can't be done. Perhaps the code reads something like
6154 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
6155 if ((value
= negate_data_op (&inst
.instruction
,
6156 inst
.reloc
.exp
.X_add_number
))
6159 inst
.error
= _("invalid constant");
6164 inst
.instruction
|= value
;
6167 inst
.instruction
|= INST_IMMEDIATE
;
6172 inst
.error
= _("register or shift expression expected");
6178 fp_op2 (char ** str
)
6180 skip_whitespace (* str
);
6182 if (fp_reg_required_here (str
, 0) != FAIL
)
6186 /* Immediate expression. */
6187 if (*((*str
)++) == '#')
6193 skip_whitespace (* str
);
6195 /* First try and match exact strings, this is to guarantee
6196 that some formats will work even for cross assembly. */
6198 for (i
= 0; fp_const
[i
]; i
++)
6200 if (strncmp (*str
, fp_const
[i
], strlen (fp_const
[i
])) == 0)
6204 *str
+= strlen (fp_const
[i
]);
6205 if (is_end_of_line
[(unsigned char) **str
])
6207 inst
.instruction
|= i
+ 8;
6214 /* Just because we didn't get a match doesn't mean that the
6215 constant isn't valid, just that it is in a format that we
6216 don't automatically recognize. Try parsing it with
6217 the standard expression routines. */
6218 if ((i
= my_get_float_expression (str
)) >= 0)
6220 inst
.instruction
|= i
+ 8;
6224 inst
.error
= _("invalid floating point immediate expression");
6228 _("floating point register or immediate expression expected");
6234 do_arit (char * str
)
6236 skip_whitespace (str
);
6238 if (reg_required_here (&str
, 12) == FAIL
6239 || skip_past_comma (&str
) == FAIL
6240 || reg_required_here (&str
, 16) == FAIL
6241 || skip_past_comma (&str
) == FAIL
6242 || data_op2 (&str
) == FAIL
)
6245 inst
.error
= BAD_ARGS
;
6255 /* This is a pseudo-op of the form "adr rd, label" to be converted
6256 into a relative address of the form "add rd, pc, #label-.-8". */
6257 skip_whitespace (str
);
6259 if (reg_required_here (&str
, 12) == FAIL
6260 || skip_past_comma (&str
) == FAIL
6261 || my_get_expression (&inst
.reloc
.exp
, &str
))
6264 inst
.error
= BAD_ARGS
;
6268 /* Frag hacking will turn this into a sub instruction if the offset turns
6269 out to be negative. */
6270 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
6272 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust. */
6274 inst
.reloc
.pc_rel
= 1;
6280 do_adrl (char * str
)
6282 /* This is a pseudo-op of the form "adrl rd, label" to be converted
6283 into a relative address of the form:
6284 add rd, pc, #low(label-.-8)"
6285 add rd, rd, #high(label-.-8)" */
6287 skip_whitespace (str
);
6289 if (reg_required_here (&str
, 12) == FAIL
6290 || skip_past_comma (&str
) == FAIL
6291 || my_get_expression (&inst
.reloc
.exp
, &str
))
6294 inst
.error
= BAD_ARGS
;
6300 /* Frag hacking will turn this into a sub instruction if the offset turns
6301 out to be negative. */
6302 inst
.reloc
.type
= BFD_RELOC_ARM_ADRL_IMMEDIATE
;
6304 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust */
6306 inst
.reloc
.pc_rel
= 1;
6307 inst
.size
= INSN_SIZE
* 2;
6313 skip_whitespace (str
);
6315 if (reg_required_here (&str
, 16) == FAIL
)
6318 inst
.error
= BAD_ARGS
;
6322 if (skip_past_comma (&str
) == FAIL
6323 || data_op2 (&str
) == FAIL
)
6326 inst
.error
= BAD_ARGS
;
6336 skip_whitespace (str
);
6338 if (reg_required_here (&str
, 12) == FAIL
)
6341 inst
.error
= BAD_ARGS
;
6345 if (skip_past_comma (&str
) == FAIL
6346 || data_op2 (&str
) == FAIL
)
6349 inst
.error
= BAD_ARGS
;
6357 do_ldst (char * str
)
6363 skip_whitespace (str
);
6365 if ((conflict_reg
= reg_required_here (&str
, 12)) == FAIL
)
6368 inst
.error
= BAD_ARGS
;
6372 if (skip_past_comma (&str
) == FAIL
)
6374 inst
.error
= _("address expected");
6384 skip_whitespace (str
);
6386 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6389 /* Conflicts can occur on stores as well as loads. */
6390 conflict_reg
= (conflict_reg
== reg
);
6392 skip_whitespace (str
);
6398 if (skip_past_comma (&str
) == SUCCESS
)
6400 /* [Rn],... (post inc) */
6401 if (ldst_extend (&str
) == FAIL
)
6404 as_warn (_("%s register same as write-back base"),
6405 ((inst
.instruction
& LOAD_BIT
)
6406 ? _("destination") : _("source")));
6411 skip_whitespace (str
);
6416 as_warn (_("%s register same as write-back base"),
6417 ((inst
.instruction
& LOAD_BIT
)
6418 ? _("destination") : _("source")));
6420 inst
.instruction
|= WRITE_BACK
;
6423 inst
.instruction
|= INDEX_UP
;
6430 if (skip_past_comma (&str
) == FAIL
)
6432 inst
.error
= _("pre-indexed expression expected");
6437 if (ldst_extend (&str
) == FAIL
)
6440 skip_whitespace (str
);
6444 inst
.error
= _("missing ]");
6448 skip_whitespace (str
);
6453 as_warn (_("%s register same as write-back base"),
6454 ((inst
.instruction
& LOAD_BIT
)
6455 ? _("destination") : _("source")));
6457 inst
.instruction
|= WRITE_BACK
;
6461 else if (*str
== '=')
6463 if ((inst
.instruction
& LOAD_BIT
) == 0)
6465 inst
.error
= _("invalid pseudo operation");
6469 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6472 skip_whitespace (str
);
6474 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6477 if (inst
.reloc
.exp
.X_op
!= O_constant
6478 && inst
.reloc
.exp
.X_op
!= O_symbol
)
6480 inst
.error
= _("constant expression expected");
6484 if (inst
.reloc
.exp
.X_op
== O_constant
)
6486 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
6490 /* This can be done with a mov instruction. */
6491 inst
.instruction
&= LITERAL_MASK
;
6492 inst
.instruction
|= (INST_IMMEDIATE
6493 | (OPCODE_MOV
<< DATA_OP_SHIFT
));
6494 inst
.instruction
|= value
& 0xfff;
6499 value
= validate_immediate (~inst
.reloc
.exp
.X_add_number
);
6503 /* This can be done with a mvn instruction. */
6504 inst
.instruction
&= LITERAL_MASK
;
6505 inst
.instruction
|= (INST_IMMEDIATE
6506 | (OPCODE_MVN
<< DATA_OP_SHIFT
));
6507 inst
.instruction
|= value
& 0xfff;
6513 /* Insert into literal pool. */
6514 if (add_to_lit_pool () == FAIL
)
6517 inst
.error
= _("literal pool insertion failed");
6521 /* Change the instruction exp to point to the pool. */
6522 inst
.reloc
.type
= BFD_RELOC_ARM_LITERAL
;
6523 inst
.reloc
.pc_rel
= 1;
6524 inst
.instruction
|= (REG_PC
<< 16);
6529 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6532 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
6534 /* PC rel adjust. */
6535 inst
.reloc
.exp
.X_add_number
-= 8;
6537 inst
.reloc
.pc_rel
= 1;
6538 inst
.instruction
|= (REG_PC
<< 16);
6542 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
6547 do_ldstt (char * str
)
6551 skip_whitespace (str
);
6553 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
6556 inst
.error
= BAD_ARGS
;
6560 if (skip_past_comma (& str
) == FAIL
)
6562 inst
.error
= _("address expected");
6572 skip_whitespace (str
);
6574 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6577 /* ldrt/strt always use post-indexed addressing, so if the base is
6578 the same as Rd, we warn. */
6579 if (conflict_reg
== reg
)
6580 as_warn (_("%s register same as write-back base"),
6581 ((inst
.instruction
& LOAD_BIT
)
6582 ? _("destination") : _("source")));
6584 skip_whitespace (str
);
6590 if (skip_past_comma (&str
) == SUCCESS
)
6592 /* [Rn],... (post inc) */
6593 if (ldst_extend (&str
) == FAIL
)
6599 skip_whitespace (str
);
6601 /* Skip a write-back '!'. */
6605 inst
.instruction
|= INDEX_UP
;
6610 inst
.error
= _("post-indexed expression expected");
6616 inst
.error
= _("post-indexed expression expected");
6623 /* Halfword and signed-byte load/store operations. */
6626 do_ldstv4 (char * str
)
6632 skip_whitespace (str
);
6634 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
6637 inst
.error
= BAD_ARGS
;
6641 if (skip_past_comma (& str
) == FAIL
)
6643 inst
.error
= _("address expected");
6653 skip_whitespace (str
);
6655 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6658 /* Conflicts can occur on stores as well as loads. */
6659 conflict_reg
= (conflict_reg
== reg
);
6661 skip_whitespace (str
);
6667 if (skip_past_comma (&str
) == SUCCESS
)
6669 /* [Rn],... (post inc) */
6670 if (ldst_extend_v4 (&str
) == FAIL
)
6673 as_warn (_("%s register same as write-back base"),
6674 ((inst
.instruction
& LOAD_BIT
)
6675 ? _("destination") : _("source")));
6680 inst
.instruction
|= HWOFFSET_IMM
;
6682 skip_whitespace (str
);
6687 as_warn (_("%s register same as write-back base"),
6688 ((inst
.instruction
& LOAD_BIT
)
6689 ? _("destination") : _("source")));
6691 inst
.instruction
|= WRITE_BACK
;
6694 inst
.instruction
|= INDEX_UP
;
6701 if (skip_past_comma (&str
) == FAIL
)
6703 inst
.error
= _("pre-indexed expression expected");
6708 if (ldst_extend_v4 (&str
) == FAIL
)
6711 skip_whitespace (str
);
6715 inst
.error
= _("missing ]");
6719 skip_whitespace (str
);
6724 as_warn (_("%s register same as write-back base"),
6725 ((inst
.instruction
& LOAD_BIT
)
6726 ? _("destination") : _("source")));
6728 inst
.instruction
|= WRITE_BACK
;
6732 else if (*str
== '=')
6734 if ((inst
.instruction
& LOAD_BIT
) == 0)
6736 inst
.error
= _("invalid pseudo operation");
6740 /* XXX Does this work correctly for half-word/byte ops? */
6741 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6744 skip_whitespace (str
);
6746 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6749 if (inst
.reloc
.exp
.X_op
!= O_constant
6750 && inst
.reloc
.exp
.X_op
!= O_symbol
)
6752 inst
.error
= _("constant expression expected");
6756 if (inst
.reloc
.exp
.X_op
== O_constant
)
6758 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
6762 /* This can be done with a mov instruction. */
6763 inst
.instruction
&= LITERAL_MASK
;
6764 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MOV
<< DATA_OP_SHIFT
);
6765 inst
.instruction
|= value
& 0xfff;
6770 value
= validate_immediate (~ inst
.reloc
.exp
.X_add_number
);
6774 /* This can be done with a mvn instruction. */
6775 inst
.instruction
&= LITERAL_MASK
;
6776 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MVN
<< DATA_OP_SHIFT
);
6777 inst
.instruction
|= value
& 0xfff;
6783 /* Insert into literal pool. */
6784 if (add_to_lit_pool () == FAIL
)
6787 inst
.error
= _("literal pool insertion failed");
6791 /* Change the instruction exp to point to the pool. */
6792 inst
.instruction
|= HWOFFSET_IMM
;
6793 inst
.reloc
.type
= BFD_RELOC_ARM_HWLITERAL
;
6794 inst
.reloc
.pc_rel
= 1;
6795 inst
.instruction
|= (REG_PC
<< 16);
6800 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6803 inst
.instruction
|= HWOFFSET_IMM
;
6804 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
6806 /* PC rel adjust. */
6807 inst
.reloc
.exp
.X_add_number
-= 8;
6809 inst
.reloc
.pc_rel
= 1;
6810 inst
.instruction
|= (REG_PC
<< 16);
6814 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
6819 do_ldsttv4 (char * str
)
6823 skip_whitespace (str
);
6825 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
6828 inst
.error
= BAD_ARGS
;
6832 if (skip_past_comma (& str
) == FAIL
)
6834 inst
.error
= _("address expected");
6844 skip_whitespace (str
);
6846 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6849 /* ldrt/strt always use post-indexed addressing, so if the base is
6850 the same as Rd, we warn. */
6851 if (conflict_reg
== reg
)
6852 as_warn (_("%s register same as write-back base"),
6853 ((inst
.instruction
& LOAD_BIT
)
6854 ? _("destination") : _("source")));
6856 skip_whitespace (str
);
6862 if (skip_past_comma (&str
) == SUCCESS
)
6864 /* [Rn],... (post inc) */
6865 if (ldst_extend_v4 (&str
) == FAIL
)
6871 skip_whitespace (str
);
6873 /* Skip a write-back '!'. */
6877 inst
.instruction
|= (INDEX_UP
|HWOFFSET_IMM
);
6882 inst
.error
= _("post-indexed expression expected");
6888 inst
.error
= _("post-indexed expression expected");
6897 reg_list (char ** strp
)
6899 char * str
= * strp
;
6903 /* We come back here if we get ranges concatenated by '+' or '|'. */
6918 skip_whitespace (str
);
6920 if ((reg
= reg_required_here (& str
, -1)) == FAIL
)
6929 inst
.error
= _("bad range in register list");
6933 for (i
= cur_reg
+ 1; i
< reg
; i
++)
6935 if (range
& (1 << i
))
6937 (_("Warning: duplicated register (r%d) in register list"),
6945 if (range
& (1 << reg
))
6946 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
6948 else if (reg
<= cur_reg
)
6949 as_tsktsk (_("Warning: register range not in ascending order"));
6954 while (skip_past_comma (&str
) != FAIL
6955 || (in_range
= 1, *str
++ == '-'));
6957 skip_whitespace (str
);
6961 inst
.error
= _("missing `}'");
6969 if (my_get_expression (&expr
, &str
))
6972 if (expr
.X_op
== O_constant
)
6974 if (expr
.X_add_number
6975 != (expr
.X_add_number
& 0x0000ffff))
6977 inst
.error
= _("invalid register mask");
6981 if ((range
& expr
.X_add_number
) != 0)
6983 int regno
= range
& expr
.X_add_number
;
6986 regno
= (1 << regno
) - 1;
6988 (_("Warning: duplicated register (r%d) in register list"),
6992 range
|= expr
.X_add_number
;
6996 if (inst
.reloc
.type
!= 0)
6998 inst
.error
= _("expression too complex");
7002 memcpy (&inst
.reloc
.exp
, &expr
, sizeof (expressionS
));
7003 inst
.reloc
.type
= BFD_RELOC_ARM_MULTI
;
7004 inst
.reloc
.pc_rel
= 0;
7008 skip_whitespace (str
);
7010 if (*str
== '|' || *str
== '+')
7016 while (another_range
);
7023 do_ldmstm (char * str
)
7028 skip_whitespace (str
);
7030 if ((base_reg
= reg_required_here (&str
, 16)) == FAIL
)
7033 if (base_reg
== REG_PC
)
7035 inst
.error
= _("r15 not allowed as base register");
7039 skip_whitespace (str
);
7043 inst
.instruction
|= WRITE_BACK
;
7047 if (skip_past_comma (&str
) == FAIL
7048 || (range
= reg_list (&str
)) == FAIL
)
7051 inst
.error
= BAD_ARGS
;
7058 inst
.instruction
|= LDM_TYPE_2_OR_3
;
7061 if (inst
.instruction
& WRITE_BACK
)
7063 /* Check for unpredictable uses of writeback. */
7064 if (inst
.instruction
& LOAD_BIT
)
7066 /* Not allowed in LDM type 2. */
7067 if ((inst
.instruction
& LDM_TYPE_2_OR_3
)
7068 && ((range
& (1 << REG_PC
)) == 0))
7069 as_warn (_("writeback of base register is UNPREDICTABLE"));
7070 /* Only allowed if base reg not in list for other types. */
7071 else if (range
& (1 << base_reg
))
7072 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
7076 /* Not allowed for type 2. */
7077 if (inst
.instruction
& LDM_TYPE_2_OR_3
)
7078 as_warn (_("writeback of base register is UNPREDICTABLE"));
7079 /* Only allowed if base reg not in list, or first in list. */
7080 else if ((range
& (1 << base_reg
))
7081 && (range
& ((1 << base_reg
) - 1)))
7082 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
7086 inst
.instruction
|= range
;
7093 skip_whitespace (str
);
7095 /* Allow optional leading '#'. */
7096 if (is_immediate_prefix (*str
))
7099 if (my_get_expression (& inst
.reloc
.exp
, & str
))
7102 inst
.reloc
.type
= BFD_RELOC_ARM_SMI
;
7103 inst
.reloc
.pc_rel
= 0;
7110 skip_whitespace (str
);
7112 /* Allow optional leading '#'. */
7113 if (is_immediate_prefix (*str
))
7116 if (my_get_expression (& inst
.reloc
.exp
, & str
))
7119 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
7120 inst
.reloc
.pc_rel
= 0;
7125 do_swap (char * str
)
7129 skip_whitespace (str
);
7131 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
7136 inst
.error
= _("r15 not allowed in swap");
7140 if (skip_past_comma (&str
) == FAIL
7141 || (reg
= reg_required_here (&str
, 0)) == FAIL
)
7144 inst
.error
= BAD_ARGS
;
7150 inst
.error
= _("r15 not allowed in swap");
7154 if (skip_past_comma (&str
) == FAIL
7157 inst
.error
= BAD_ARGS
;
7161 skip_whitespace (str
);
7163 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
7168 inst
.error
= BAD_PC
;
7172 skip_whitespace (str
);
7176 inst
.error
= _("missing ]");
7184 do_branch (char * str
)
7186 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7193 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
7194 required for the instruction. */
7196 /* arm_parse_reloc () works on input_line_pointer.
7197 We actually want to parse the operands to the branch instruction
7198 passed in 'str'. Save the input pointer and restore it later. */
7199 save_in
= input_line_pointer
;
7200 input_line_pointer
= str
;
7201 if (inst
.reloc
.exp
.X_op
== O_symbol
7203 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
7205 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
7206 inst
.reloc
.pc_rel
= 0;
7207 /* Modify str to point to after parsed operands, otherwise
7208 end_of_line() will complain about the (PLT) left in str. */
7209 str
= input_line_pointer
;
7213 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
7214 inst
.reloc
.pc_rel
= 1;
7216 input_line_pointer
= save_in
;
7219 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
7220 inst
.reloc
.pc_rel
= 1;
7221 #endif /* OBJ_ELF */
7229 /* Co-processor data operation.
7230 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
7231 skip_whitespace (str
);
7233 if (co_proc_number (&str
) == FAIL
)
7236 inst
.error
= BAD_ARGS
;
7240 if (skip_past_comma (&str
) == FAIL
7241 || cp_opc_expr (&str
, 20,4) == FAIL
)
7244 inst
.error
= BAD_ARGS
;
7248 if (skip_past_comma (&str
) == FAIL
7249 || cp_reg_required_here (&str
, 12) == FAIL
)
7252 inst
.error
= BAD_ARGS
;
7256 if (skip_past_comma (&str
) == FAIL
7257 || cp_reg_required_here (&str
, 16) == FAIL
)
7260 inst
.error
= BAD_ARGS
;
7264 if (skip_past_comma (&str
) == FAIL
7265 || cp_reg_required_here (&str
, 0) == FAIL
)
7268 inst
.error
= BAD_ARGS
;
7272 if (skip_past_comma (&str
) == SUCCESS
)
7274 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
7277 inst
.error
= BAD_ARGS
;
7286 do_lstc (char * str
)
7288 /* Co-processor register load/store.
7289 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
7291 skip_whitespace (str
);
7293 if (co_proc_number (&str
) == FAIL
)
7296 inst
.error
= BAD_ARGS
;
7300 if (skip_past_comma (&str
) == FAIL
7301 || cp_reg_required_here (&str
, 12) == FAIL
)
7304 inst
.error
= BAD_ARGS
;
7308 if (skip_past_comma (&str
) == FAIL
7309 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
7312 inst
.error
= BAD_ARGS
;
7320 do_co_reg (char * str
)
7322 /* Co-processor register transfer.
7323 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
7325 skip_whitespace (str
);
7327 if (co_proc_number (&str
) == FAIL
)
7330 inst
.error
= BAD_ARGS
;
7334 if (skip_past_comma (&str
) == FAIL
7335 || cp_opc_expr (&str
, 21, 3) == FAIL
)
7338 inst
.error
= BAD_ARGS
;
7342 if (skip_past_comma (&str
) == FAIL
7343 || reg_required_here (&str
, 12) == FAIL
)
7346 inst
.error
= BAD_ARGS
;
7350 if (skip_past_comma (&str
) == FAIL
7351 || cp_reg_required_here (&str
, 16) == FAIL
)
7354 inst
.error
= BAD_ARGS
;
7358 if (skip_past_comma (&str
) == FAIL
7359 || cp_reg_required_here (&str
, 0) == FAIL
)
7362 inst
.error
= BAD_ARGS
;
7366 if (skip_past_comma (&str
) == SUCCESS
)
7368 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
7371 inst
.error
= BAD_ARGS
;
7380 do_fpa_ctrl (char * str
)
7382 /* FP control registers.
7383 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
7385 skip_whitespace (str
);
7387 if (reg_required_here (&str
, 12) == FAIL
)
7390 inst
.error
= BAD_ARGS
;
7398 do_fpa_ldst (char * str
)
7400 skip_whitespace (str
);
7402 if (fp_reg_required_here (&str
, 12) == FAIL
)
7405 inst
.error
= BAD_ARGS
;
7409 if (skip_past_comma (&str
) == FAIL
7410 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
7413 inst
.error
= BAD_ARGS
;
7421 do_fpa_ldmstm (char * str
)
7425 skip_whitespace (str
);
7427 if (fp_reg_required_here (&str
, 12) == FAIL
)
7430 inst
.error
= BAD_ARGS
;
7434 /* Get Number of registers to transfer. */
7435 if (skip_past_comma (&str
) == FAIL
7436 || my_get_expression (&inst
.reloc
.exp
, &str
))
7439 inst
.error
= _("constant expression expected");
7443 if (inst
.reloc
.exp
.X_op
!= O_constant
)
7445 inst
.error
= _("constant value required for number of registers");
7449 num_regs
= inst
.reloc
.exp
.X_add_number
;
7451 if (num_regs
< 1 || num_regs
> 4)
7453 inst
.error
= _("number of registers must be in the range [1:4]");
7460 inst
.instruction
|= CP_T_X
;
7463 inst
.instruction
|= CP_T_Y
;
7466 inst
.instruction
|= CP_T_Y
| CP_T_X
;
7474 if (inst
.instruction
& (CP_T_Pre
| CP_T_UD
)) /* ea/fd format. */
7480 /* The instruction specified "ea" or "fd", so we can only accept
7481 [Rn]{!}. The instruction does not really support stacking or
7482 unstacking, so we have to emulate these by setting appropriate
7483 bits and offsets. */
7484 if (skip_past_comma (&str
) == FAIL
7488 inst
.error
= BAD_ARGS
;
7493 skip_whitespace (str
);
7495 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
7498 skip_whitespace (str
);
7502 inst
.error
= BAD_ARGS
;
7514 _("r15 not allowed as base register with write-back");
7521 if (inst
.instruction
& CP_T_Pre
)
7523 /* Pre-decrement. */
7524 offset
= 3 * num_regs
;
7526 inst
.instruction
|= CP_T_WB
;
7530 /* Post-increment. */
7533 inst
.instruction
|= CP_T_WB
;
7534 offset
= 3 * num_regs
;
7538 /* No write-back, so convert this into a standard pre-increment
7539 instruction -- aesthetically more pleasing. */
7540 inst
.instruction
|= CP_T_Pre
| CP_T_UD
;
7545 inst
.instruction
|= offset
;
7547 else if (skip_past_comma (&str
) == FAIL
7548 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
7551 inst
.error
= BAD_ARGS
;
7559 do_fpa_dyadic (char * str
)
7561 skip_whitespace (str
);
7563 if (fp_reg_required_here (&str
, 12) == FAIL
)
7566 inst
.error
= BAD_ARGS
;
7570 if (skip_past_comma (&str
) == FAIL
7571 || fp_reg_required_here (&str
, 16) == FAIL
)
7574 inst
.error
= BAD_ARGS
;
7578 if (skip_past_comma (&str
) == FAIL
7579 || fp_op2 (&str
) == FAIL
)
7582 inst
.error
= BAD_ARGS
;
7590 do_fpa_monadic (char * str
)
7592 skip_whitespace (str
);
7594 if (fp_reg_required_here (&str
, 12) == FAIL
)
7597 inst
.error
= BAD_ARGS
;
7601 if (skip_past_comma (&str
) == FAIL
7602 || fp_op2 (&str
) == FAIL
)
7605 inst
.error
= BAD_ARGS
;
7613 do_fpa_cmp (char * str
)
7615 skip_whitespace (str
);
7617 if (fp_reg_required_here (&str
, 16) == FAIL
)
7620 inst
.error
= BAD_ARGS
;
7624 if (skip_past_comma (&str
) == FAIL
7625 || fp_op2 (&str
) == FAIL
)
7628 inst
.error
= BAD_ARGS
;
7636 do_fpa_from_reg (char * str
)
7638 skip_whitespace (str
);
7640 if (fp_reg_required_here (&str
, 16) == FAIL
)
7643 inst
.error
= BAD_ARGS
;
7647 if (skip_past_comma (&str
) == FAIL
7648 || reg_required_here (&str
, 12) == FAIL
)
7651 inst
.error
= BAD_ARGS
;
7659 do_fpa_to_reg (char * str
)
7661 skip_whitespace (str
);
7663 if (reg_required_here (&str
, 12) == FAIL
)
7666 if (skip_past_comma (&str
) == FAIL
7667 || fp_reg_required_here (&str
, 0) == FAIL
)
7670 inst
.error
= BAD_ARGS
;
7677 /* Encode a VFP SP register number. */
7680 vfp_sp_encode_reg (int reg
, enum vfp_sp_reg_pos pos
)
7685 inst
.instruction
|= ((reg
>> 1) << 12) | ((reg
& 1) << 22);
7689 inst
.instruction
|= ((reg
>> 1) << 16) | ((reg
& 1) << 7);
7693 inst
.instruction
|= ((reg
>> 1) << 0) | ((reg
& 1) << 5);
7702 vfp_sp_reg_required_here (char ** str
,
7703 enum vfp_sp_reg_pos pos
)
7706 char * start
= *str
;
7708 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_SN
].htab
)) != FAIL
)
7710 vfp_sp_encode_reg (reg
, pos
);
7714 /* In the few cases where we might be able to accept something else
7715 this error can be overridden. */
7716 inst
.error
= _(all_reg_maps
[REG_TYPE_SN
].expected
);
7718 /* Restore the start point. */
7724 vfp_dp_reg_required_here (char ** str
,
7725 enum vfp_dp_reg_pos pos
)
7728 char * start
= *str
;
7730 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_DN
].htab
)) != FAIL
)
7735 inst
.instruction
|= reg
<< 12;
7739 inst
.instruction
|= reg
<< 16;
7743 inst
.instruction
|= reg
<< 0;
7752 /* In the few cases where we might be able to accept something else
7753 this error can be overridden. */
7754 inst
.error
= _(all_reg_maps
[REG_TYPE_DN
].expected
);
7756 /* Restore the start point. */
7762 do_vfp_sp_monadic (char * str
)
7764 skip_whitespace (str
);
7766 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7769 if (skip_past_comma (&str
) == FAIL
7770 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
7773 inst
.error
= BAD_ARGS
;
7781 do_vfp_dp_monadic (char * str
)
7783 skip_whitespace (str
);
7785 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7788 if (skip_past_comma (&str
) == FAIL
7789 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7792 inst
.error
= BAD_ARGS
;
7800 do_vfp_sp_dyadic (char * str
)
7802 skip_whitespace (str
);
7804 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7807 if (skip_past_comma (&str
) == FAIL
7808 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
7809 || skip_past_comma (&str
) == FAIL
7810 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
7813 inst
.error
= BAD_ARGS
;
7821 do_vfp_dp_dyadic (char * str
)
7823 skip_whitespace (str
);
7825 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7828 if (skip_past_comma (&str
) == FAIL
7829 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
7830 || skip_past_comma (&str
) == FAIL
7831 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7834 inst
.error
= BAD_ARGS
;
7842 do_vfp_reg_from_sp (char * str
)
7844 skip_whitespace (str
);
7846 if (reg_required_here (&str
, 12) == FAIL
)
7849 if (skip_past_comma (&str
) == FAIL
7850 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
7853 inst
.error
= BAD_ARGS
;
7860 /* Parse a VFP register list. If the string is invalid return FAIL.
7861 Otherwise return the number of registers, and set PBASE to the first
7862 register. Double precision registers are matched if DP is nonzero. */
7865 vfp_parse_reg_list (char **str
, int *pbase
, int dp
)
7873 unsigned long mask
= 0;
7880 skip_whitespace (*str
);
7884 regtype
= REG_TYPE_DN
;
7889 regtype
= REG_TYPE_SN
;
7893 base_reg
= max_regs
;
7897 new_base
= arm_reg_parse (str
, all_reg_maps
[regtype
].htab
);
7898 if (new_base
== FAIL
)
7900 inst
.error
= _(all_reg_maps
[regtype
].expected
);
7904 if (new_base
< base_reg
)
7905 base_reg
= new_base
;
7907 if (mask
& (1 << new_base
))
7909 inst
.error
= _("invalid register list");
7913 if ((mask
>> new_base
) != 0 && ! warned
)
7915 as_tsktsk (_("register list not in ascending order"));
7919 mask
|= 1 << new_base
;
7922 skip_whitespace (*str
);
7924 if (**str
== '-') /* We have the start of a range expression */
7931 = arm_reg_parse (str
, all_reg_maps
[regtype
].htab
))
7934 inst
.error
= _(all_reg_maps
[regtype
].expected
);
7938 if (high_range
<= new_base
)
7940 inst
.error
= _("register range not in ascending order");
7944 for (new_base
++; new_base
<= high_range
; new_base
++)
7946 if (mask
& (1 << new_base
))
7948 inst
.error
= _("invalid register list");
7952 mask
|= 1 << new_base
;
7957 while (skip_past_comma (str
) != FAIL
);
7961 /* Sanity check -- should have raised a parse error above. */
7962 if (count
== 0 || count
> max_regs
)
7967 /* Final test -- the registers must be consecutive. */
7969 for (i
= 0; i
< count
; i
++)
7971 if ((mask
& (1u << i
)) == 0)
7973 inst
.error
= _("non-contiguous register range");
7982 do_vfp_reg2_from_sp2 (char * str
)
7986 skip_whitespace (str
);
7988 if (reg_required_here (&str
, 12) == FAIL
7989 || skip_past_comma (&str
) == FAIL
7990 || reg_required_here (&str
, 16) == FAIL
7991 || skip_past_comma (&str
) == FAIL
)
7994 inst
.error
= BAD_ARGS
;
7998 /* We require exactly two consecutive SP registers. */
7999 if (vfp_parse_reg_list (&str
, ®
, 0) != 2)
8002 inst
.error
= _("only two consecutive VFP SP registers allowed here");
8004 vfp_sp_encode_reg (reg
, VFP_REG_Sm
);
8010 do_vfp_sp_from_reg (char * str
)
8012 skip_whitespace (str
);
8014 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
8017 if (skip_past_comma (&str
) == FAIL
8018 || reg_required_here (&str
, 12) == FAIL
)
8021 inst
.error
= BAD_ARGS
;
8029 do_vfp_sp2_from_reg2 (char * str
)
8033 skip_whitespace (str
);
8035 /* We require exactly two consecutive SP registers. */
8036 if (vfp_parse_reg_list (&str
, ®
, 0) != 2)
8039 inst
.error
= _("only two consecutive VFP SP registers allowed here");
8041 vfp_sp_encode_reg (reg
, VFP_REG_Sm
);
8043 if (skip_past_comma (&str
) == FAIL
8044 || reg_required_here (&str
, 12) == FAIL
8045 || skip_past_comma (&str
) == FAIL
8046 || reg_required_here (&str
, 16) == FAIL
)
8049 inst
.error
= BAD_ARGS
;
8057 do_vfp_reg_from_dp (char * str
)
8059 skip_whitespace (str
);
8061 if (reg_required_here (&str
, 12) == FAIL
)
8064 if (skip_past_comma (&str
) == FAIL
8065 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
8068 inst
.error
= BAD_ARGS
;
8076 do_vfp_reg2_from_dp (char * str
)
8078 skip_whitespace (str
);
8080 if (reg_required_here (&str
, 12) == FAIL
)
8083 if (skip_past_comma (&str
) == FAIL
8084 || reg_required_here (&str
, 16) == FAIL
8085 || skip_past_comma (&str
) == FAIL
8086 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
8089 inst
.error
= BAD_ARGS
;
8097 do_vfp_dp_from_reg (char * str
)
8099 skip_whitespace (str
);
8101 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
8104 if (skip_past_comma (&str
) == FAIL
8105 || reg_required_here (&str
, 12) == FAIL
)
8108 inst
.error
= BAD_ARGS
;
8116 do_vfp_dp_from_reg2 (char * str
)
8118 skip_whitespace (str
);
8120 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
8123 if (skip_past_comma (&str
) == FAIL
8124 || reg_required_here (&str
, 12) == FAIL
8125 || skip_past_comma (&str
) == FAIL
8126 || reg_required_here (&str
, 16) == FAIL
)
8129 inst
.error
= BAD_ARGS
;
8136 static const struct vfp_reg
*
8137 vfp_psr_parse (char ** str
)
8142 const struct vfp_reg
*vreg
;
8146 /* Find the end of the current token. */
8151 while (ISALPHA (c
));
8156 for (vreg
= vfp_regs
+ 0;
8157 vreg
< vfp_regs
+ sizeof (vfp_regs
) / sizeof (struct vfp_reg
);
8160 if (streq (start
, vreg
->name
))
8173 vfp_psr_required_here (char ** str
)
8176 const struct vfp_reg
*vreg
;
8178 vreg
= vfp_psr_parse (str
);
8182 inst
.instruction
|= vreg
->regno
;
8186 inst
.error
= _("VFP system register expected");
8193 do_vfp_reg_from_ctrl (char * str
)
8195 skip_whitespace (str
);
8197 if (reg_required_here (&str
, 12) == FAIL
)
8200 if (skip_past_comma (&str
) == FAIL
8201 || vfp_psr_required_here (&str
) == FAIL
)
8204 inst
.error
= BAD_ARGS
;
8212 do_vfp_ctrl_from_reg (char * str
)
8214 skip_whitespace (str
);
8216 if (vfp_psr_required_here (&str
) == FAIL
)
8219 if (skip_past_comma (&str
) == FAIL
8220 || reg_required_here (&str
, 12) == FAIL
)
8223 inst
.error
= BAD_ARGS
;
8231 do_vfp_sp_ldst (char * str
)
8233 skip_whitespace (str
);
8235 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8238 inst
.error
= BAD_ARGS
;
8242 if (skip_past_comma (&str
) == FAIL
8243 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
8246 inst
.error
= BAD_ARGS
;
8254 do_vfp_dp_ldst (char * str
)
8256 skip_whitespace (str
);
8258 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8261 inst
.error
= BAD_ARGS
;
8265 if (skip_past_comma (&str
) == FAIL
8266 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
8269 inst
.error
= BAD_ARGS
;
8278 vfp_sp_ldstm (char * str
, enum vfp_ldstm_type ldstm_type
)
8283 skip_whitespace (str
);
8285 if (reg_required_here (&str
, 16) == FAIL
)
8288 skip_whitespace (str
);
8292 inst
.instruction
|= WRITE_BACK
;
8295 else if (ldstm_type
!= VFP_LDSTMIA
)
8297 inst
.error
= _("this addressing mode requires base-register writeback");
8301 if (skip_past_comma (&str
) == FAIL
8302 || (count
= vfp_parse_reg_list (&str
, ®
, 0)) == FAIL
)
8305 inst
.error
= BAD_ARGS
;
8308 vfp_sp_encode_reg (reg
, VFP_REG_Sd
);
8310 inst
.instruction
|= count
;
8315 vfp_dp_ldstm (char * str
, enum vfp_ldstm_type ldstm_type
)
8320 skip_whitespace (str
);
8322 if (reg_required_here (&str
, 16) == FAIL
)
8325 skip_whitespace (str
);
8329 inst
.instruction
|= WRITE_BACK
;
8332 else if (ldstm_type
!= VFP_LDSTMIA
&& ldstm_type
!= VFP_LDSTMIAX
)
8334 inst
.error
= _("this addressing mode requires base-register writeback");
8338 if (skip_past_comma (&str
) == FAIL
8339 || (count
= vfp_parse_reg_list (&str
, ®
, 1)) == FAIL
)
8342 inst
.error
= BAD_ARGS
;
8347 if (ldstm_type
== VFP_LDSTMIAX
|| ldstm_type
== VFP_LDSTMDBX
)
8350 inst
.instruction
|= (reg
<< 12) | count
;
8355 do_vfp_sp_ldstmia (char * str
)
8357 vfp_sp_ldstm (str
, VFP_LDSTMIA
);
8361 do_vfp_sp_ldstmdb (char * str
)
8363 vfp_sp_ldstm (str
, VFP_LDSTMDB
);
8367 do_vfp_dp_ldstmia (char * str
)
8369 vfp_dp_ldstm (str
, VFP_LDSTMIA
);
8373 do_vfp_dp_ldstmdb (char * str
)
8375 vfp_dp_ldstm (str
, VFP_LDSTMDB
);
8379 do_vfp_xp_ldstmia (char *str
)
8381 vfp_dp_ldstm (str
, VFP_LDSTMIAX
);
8385 do_vfp_xp_ldstmdb (char * str
)
8387 vfp_dp_ldstm (str
, VFP_LDSTMDBX
);
8391 do_vfp_sp_compare_z (char * str
)
8393 skip_whitespace (str
);
8395 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8398 inst
.error
= BAD_ARGS
;
8406 do_vfp_dp_compare_z (char * str
)
8408 skip_whitespace (str
);
8410 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8413 inst
.error
= BAD_ARGS
;
8421 do_vfp_dp_sp_cvt (char * str
)
8423 skip_whitespace (str
);
8425 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8428 if (skip_past_comma (&str
) == FAIL
8429 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
8432 inst
.error
= BAD_ARGS
;
8440 do_vfp_sp_dp_cvt (char * str
)
8442 skip_whitespace (str
);
8444 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8447 if (skip_past_comma (&str
) == FAIL
8448 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
8451 inst
.error
= BAD_ARGS
;
8458 /* Thumb specific routines. */
8460 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
8464 thumb_add_sub (char * str
, int subtract
)
8466 int Rd
, Rs
, Rn
= FAIL
;
8468 skip_whitespace (str
);
8470 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
8471 || skip_past_comma (&str
) == FAIL
)
8474 inst
.error
= BAD_ARGS
;
8478 if (is_immediate_prefix (*str
))
8482 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8487 if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8490 if (skip_past_comma (&str
) == FAIL
)
8492 /* Two operand format, shuffle the registers
8493 and pretend there are 3. */
8497 else if (is_immediate_prefix (*str
))
8500 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8503 else if ((Rn
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8507 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8508 for the latter case, EXPR contains the immediate that was found. */
8511 /* All register format. */
8512 if (Rd
> 7 || Rs
> 7 || Rn
> 7)
8516 inst
.error
= _("dest and source1 must be the same register");
8520 /* Can't do this for SUB. */
8523 inst
.error
= _("subtract valid only on lo regs");
8527 inst
.instruction
= (T_OPCODE_ADD_HI
8528 | (Rd
> 7 ? THUMB_H1
: 0)
8529 | (Rn
> 7 ? THUMB_H2
: 0));
8530 inst
.instruction
|= (Rd
& 7) | ((Rn
& 7) << 3);
8534 inst
.instruction
= subtract
? T_OPCODE_SUB_R3
: T_OPCODE_ADD_R3
;
8535 inst
.instruction
|= Rd
| (Rs
<< 3) | (Rn
<< 6);
8540 /* Immediate expression, now things start to get nasty. */
8542 /* First deal with HI regs, only very restricted cases allowed:
8543 Adjusting SP, and using PC or SP to get an address. */
8544 if ((Rd
> 7 && (Rd
!= REG_SP
|| Rs
!= REG_SP
))
8545 || (Rs
> 7 && Rs
!= REG_SP
&& Rs
!= REG_PC
))
8547 inst
.error
= _("invalid Hi register with immediate");
8551 if (inst
.reloc
.exp
.X_op
!= O_constant
)
8553 /* Value isn't known yet, all we can do is store all the fragments
8554 we know about in the instruction and let the reloc hacking
8556 inst
.instruction
= (subtract
? 0x8000 : 0) | (Rd
<< 4) | Rs
;
8557 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
8561 int offset
= inst
.reloc
.exp
.X_add_number
;
8571 /* Quick check, in case offset is MIN_INT. */
8574 inst
.error
= _("immediate value out of range");
8578 /* Note - you cannot convert a subtract of 0 into an
8579 add of 0 because the carry flag is set differently. */
8580 else if (offset
> 0)
8585 if (offset
& ~0x1fc)
8587 inst
.error
= _("invalid immediate value for stack adjust");
8590 inst
.instruction
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
8591 inst
.instruction
|= offset
>> 2;
8593 else if (Rs
== REG_PC
|| Rs
== REG_SP
)
8596 || (offset
& ~0x3fc))
8598 inst
.error
= _("invalid immediate for address calculation");
8601 inst
.instruction
= (Rs
== REG_PC
? T_OPCODE_ADD_PC
8603 inst
.instruction
|= (Rd
<< 8) | (offset
>> 2);
8609 inst
.error
= _("immediate value out of range");
8612 inst
.instruction
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
8613 inst
.instruction
|= (Rd
<< 8) | offset
;
8619 inst
.error
= _("immediate value out of range");
8622 inst
.instruction
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
8623 inst
.instruction
|= Rd
| (Rs
<< 3) | (offset
<< 6);
8632 thumb_shift (char * str
, int shift
)
8634 int Rd
, Rs
, Rn
= FAIL
;
8636 skip_whitespace (str
);
8638 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
8639 || skip_past_comma (&str
) == FAIL
)
8642 inst
.error
= BAD_ARGS
;
8646 if (is_immediate_prefix (*str
))
8648 /* Two operand immediate format, set Rs to Rd. */
8651 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8656 if ((Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8659 if (skip_past_comma (&str
) == FAIL
)
8661 /* Two operand format, shuffle the registers
8662 and pretend there are 3. */
8666 else if (is_immediate_prefix (*str
))
8669 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8672 else if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8676 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8677 for the latter case, EXPR contains the immediate that was found. */
8683 inst
.error
= _("source1 and dest must be same register");
8689 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_R
; break;
8690 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_R
; break;
8691 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_R
; break;
8694 inst
.instruction
|= Rd
| (Rn
<< 3);
8700 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_I
; break;
8701 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_I
; break;
8702 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_I
; break;
8705 if (inst
.reloc
.exp
.X_op
!= O_constant
)
8707 /* Value isn't known yet, create a dummy reloc and let reloc
8708 hacking fix it up. */
8709 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_SHIFT
;
8713 unsigned shift_value
= inst
.reloc
.exp
.X_add_number
;
8715 if (shift_value
> 32 || (shift_value
== 32 && shift
== THUMB_LSL
))
8717 inst
.error
= _("invalid immediate for shift");
8721 /* Shifts of zero are handled by converting to LSL. */
8722 if (shift_value
== 0)
8723 inst
.instruction
= T_OPCODE_LSL_I
;
8725 /* Shifts of 32 are encoded as a shift of zero. */
8726 if (shift_value
== 32)
8729 inst
.instruction
|= shift_value
<< 6;
8732 inst
.instruction
|= Rd
| (Rs
<< 3);
8739 thumb_load_store (char * str
, int load_store
, int size
)
8741 int Rd
, Rb
, Ro
= FAIL
;
8743 skip_whitespace (str
);
8745 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
8746 || skip_past_comma (&str
) == FAIL
)
8749 inst
.error
= BAD_ARGS
;
8756 if ((Rb
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8759 if (skip_past_comma (&str
) != FAIL
)
8761 if (is_immediate_prefix (*str
))
8764 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8767 else if ((Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8772 inst
.reloc
.exp
.X_op
= O_constant
;
8773 inst
.reloc
.exp
.X_add_number
= 0;
8778 inst
.error
= _("expected ']'");
8783 else if (*str
== '=')
8785 if (load_store
!= THUMB_LOAD
)
8787 inst
.error
= _("invalid pseudo operation");
8791 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
8794 skip_whitespace (str
);
8796 if (my_get_expression (& inst
.reloc
.exp
, & str
))
8801 if ( inst
.reloc
.exp
.X_op
!= O_constant
8802 && inst
.reloc
.exp
.X_op
!= O_symbol
)
8804 inst
.error
= "Constant expression expected";
8808 if (inst
.reloc
.exp
.X_op
== O_constant
8809 && ((inst
.reloc
.exp
.X_add_number
& ~0xFF) == 0))
8811 /* This can be done with a mov instruction. */
8813 inst
.instruction
= T_OPCODE_MOV_I8
| (Rd
<< 8);
8814 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
8818 /* Insert into literal pool. */
8819 if (add_to_lit_pool () == FAIL
)
8822 inst
.error
= "literal pool insertion failed";
8826 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8827 inst
.reloc
.pc_rel
= 1;
8828 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
8829 /* Adjust ARM pipeline offset to Thumb. */
8830 inst
.reloc
.exp
.X_add_number
+= 4;
8836 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8839 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
8840 inst
.reloc
.pc_rel
= 1;
8841 inst
.reloc
.exp
.X_add_number
-= 4; /* Pipeline offset. */
8842 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8847 if (Rb
== REG_PC
|| Rb
== REG_SP
)
8849 if (size
!= THUMB_WORD
)
8851 inst
.error
= _("byte or halfword not valid for base register");
8854 else if (Rb
== REG_PC
&& load_store
!= THUMB_LOAD
)
8856 inst
.error
= _("r15 based store not allowed");
8859 else if (Ro
!= FAIL
)
8861 inst
.error
= _("invalid base register for register offset");
8866 inst
.instruction
= T_OPCODE_LDR_PC
;
8867 else if (load_store
== THUMB_LOAD
)
8868 inst
.instruction
= T_OPCODE_LDR_SP
;
8870 inst
.instruction
= T_OPCODE_STR_SP
;
8872 inst
.instruction
|= Rd
<< 8;
8873 if (inst
.reloc
.exp
.X_op
== O_constant
)
8875 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
8877 if (offset
& ~0x3fc)
8879 inst
.error
= _("invalid offset");
8883 inst
.instruction
|= offset
>> 2;
8886 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8890 inst
.error
= _("invalid base register in load/store");
8893 else if (Ro
== FAIL
)
8895 /* Immediate offset. */
8896 if (size
== THUMB_WORD
)
8897 inst
.instruction
= (load_store
== THUMB_LOAD
8898 ? T_OPCODE_LDR_IW
: T_OPCODE_STR_IW
);
8899 else if (size
== THUMB_HALFWORD
)
8900 inst
.instruction
= (load_store
== THUMB_LOAD
8901 ? T_OPCODE_LDR_IH
: T_OPCODE_STR_IH
);
8903 inst
.instruction
= (load_store
== THUMB_LOAD
8904 ? T_OPCODE_LDR_IB
: T_OPCODE_STR_IB
);
8906 inst
.instruction
|= Rd
| (Rb
<< 3);
8908 if (inst
.reloc
.exp
.X_op
== O_constant
)
8910 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
8912 if (offset
& ~(0x1f << size
))
8914 inst
.error
= _("invalid offset");
8917 inst
.instruction
|= (offset
>> size
) << 6;
8920 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8924 /* Register offset. */
8925 if (size
== THUMB_WORD
)
8926 inst
.instruction
= (load_store
== THUMB_LOAD
8927 ? T_OPCODE_LDR_RW
: T_OPCODE_STR_RW
);
8928 else if (size
== THUMB_HALFWORD
)
8929 inst
.instruction
= (load_store
== THUMB_LOAD
8930 ? T_OPCODE_LDR_RH
: T_OPCODE_STR_RH
);
8932 inst
.instruction
= (load_store
== THUMB_LOAD
8933 ? T_OPCODE_LDR_RB
: T_OPCODE_STR_RB
);
8935 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
8941 /* A register must be given at this point.
8943 Shift is the place to put it in inst.instruction.
8945 Restores input start point on err.
8946 Returns the reg#, or FAIL. */
8949 mav_reg_required_here (char ** str
, int shift
, enum arm_reg_type regtype
)
8954 if ((reg
= arm_reg_parse (str
, all_reg_maps
[regtype
].htab
)) != FAIL
)
8957 inst
.instruction
|= reg
<< shift
;
8962 /* Restore the start point. */
8965 /* Try generic coprocessor name if applicable. */
8966 if (regtype
== REG_TYPE_MVF
||
8967 regtype
== REG_TYPE_MVD
||
8968 regtype
== REG_TYPE_MVFX
||
8969 regtype
== REG_TYPE_MVDX
)
8971 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CN
].htab
)) != FAIL
)
8974 inst
.instruction
|= reg
<< shift
;
8979 /* Restore the start point. */
8983 /* In the few cases where we might be able to accept something else
8984 this error can be overridden. */
8985 inst
.error
= _(all_reg_maps
[regtype
].expected
);
8990 /* Cirrus Maverick Instructions. */
8992 /* Isnsn like "foo X,Y". */
8995 do_mav_binops (char * str
,
8997 enum arm_reg_type reg0
,
8998 enum arm_reg_type reg1
)
9002 shift0
= mode
& 0xff;
9003 shift1
= (mode
>> 8) & 0xff;
9005 skip_whitespace (str
);
9007 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
9008 || skip_past_comma (&str
) == FAIL
9009 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
)
9012 inst
.error
= BAD_ARGS
;
9018 /* Isnsn like "foo X,Y,Z". */
9021 do_mav_triple (char * str
,
9023 enum arm_reg_type reg0
,
9024 enum arm_reg_type reg1
,
9025 enum arm_reg_type reg2
)
9027 int shift0
, shift1
, shift2
;
9029 shift0
= mode
& 0xff;
9030 shift1
= (mode
>> 8) & 0xff;
9031 shift2
= (mode
>> 16) & 0xff;
9033 skip_whitespace (str
);
9035 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
9036 || skip_past_comma (&str
) == FAIL
9037 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
9038 || skip_past_comma (&str
) == FAIL
9039 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
)
9042 inst
.error
= BAD_ARGS
;
9048 /* Wrapper functions. */
9051 do_mav_binops_1a (char * str
)
9053 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVF
);
9057 do_mav_binops_1b (char * str
)
9059 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVD
);
9063 do_mav_binops_1c (char * str
)
9065 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVDX
);
9069 do_mav_binops_1d (char * str
)
9071 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVF
);
9075 do_mav_binops_1e (char * str
)
9077 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVD
);
9081 do_mav_binops_1f (char * str
)
9083 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVF
);
9087 do_mav_binops_1g (char * str
)
9089 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVD
);
9093 do_mav_binops_1h (char * str
)
9095 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVFX
);
9099 do_mav_binops_1i (char * str
)
9101 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVFX
);
9105 do_mav_binops_1j (char * str
)
9107 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVDX
);
9111 do_mav_binops_1k (char * str
)
9113 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVDX
);
9117 do_mav_binops_1l (char * str
)
9119 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVF
);
9123 do_mav_binops_1m (char * str
)
9125 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVD
);
9129 do_mav_binops_1n (char * str
)
9131 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
9135 do_mav_binops_1o (char * str
)
9137 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
9141 do_mav_binops_2a (char * str
)
9143 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVF
, REG_TYPE_RN
);
9147 do_mav_binops_2b (char * str
)
9149 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVD
, REG_TYPE_RN
);
9153 do_mav_binops_2c (char * str
)
9155 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVDX
, REG_TYPE_RN
);
9159 do_mav_binops_3a (char * str
)
9161 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVFX
);
9165 do_mav_binops_3b (char * str
)
9167 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVFX
, REG_TYPE_MVAX
);
9171 do_mav_binops_3c (char * str
)
9173 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVDX
);
9177 do_mav_binops_3d (char * str
)
9179 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVDX
, REG_TYPE_MVAX
);
9183 do_mav_triple_4a (char * str
)
9185 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_RN
);
9189 do_mav_triple_4b (char * str
)
9191 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_RN
);
9195 do_mav_triple_5a (char * str
)
9197 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVF
, REG_TYPE_MVF
);
9201 do_mav_triple_5b (char * str
)
9203 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVD
, REG_TYPE_MVD
);
9207 do_mav_triple_5c (char * str
)
9209 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
9213 do_mav_triple_5d (char * str
)
9215 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
9219 do_mav_triple_5e (char * str
)
9221 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVF
, REG_TYPE_MVF
, REG_TYPE_MVF
);
9225 do_mav_triple_5f (char * str
)
9227 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVD
, REG_TYPE_MVD
, REG_TYPE_MVD
);
9231 do_mav_triple_5g (char * str
)
9233 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
9237 do_mav_triple_5h (char * str
)
9239 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
9242 /* Isnsn like "foo W,X,Y,Z".
9243 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
9246 do_mav_quad (char * str
,
9248 enum arm_reg_type reg0
,
9249 enum arm_reg_type reg1
,
9250 enum arm_reg_type reg2
,
9251 enum arm_reg_type reg3
)
9253 int shift0
, shift1
, shift2
, shift3
;
9255 shift0
= mode
& 0xff;
9256 shift1
= (mode
>> 8) & 0xff;
9257 shift2
= (mode
>> 16) & 0xff;
9258 shift3
= (mode
>> 24) & 0xff;
9260 skip_whitespace (str
);
9262 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
9263 || skip_past_comma (&str
) == FAIL
9264 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
9265 || skip_past_comma (&str
) == FAIL
9266 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
9267 || skip_past_comma (&str
) == FAIL
9268 || mav_reg_required_here (&str
, shift3
, reg3
) == FAIL
)
9271 inst
.error
= BAD_ARGS
;
9278 do_mav_quad_6a (char * str
)
9280 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
,
9285 do_mav_quad_6b (char * str
)
9287 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVAX
, REG_TYPE_MVFX
,
9291 /* cfmvsc32<cond> DSPSC,MVDX[15:0]. */
9293 do_mav_dspsc_1 (char * str
)
9295 skip_whitespace (str
);
9298 if (mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
9299 || skip_past_comma (&str
) == FAIL
9300 || mav_reg_required_here (&str
, 12, REG_TYPE_MVDX
) == FAIL
)
9303 inst
.error
= BAD_ARGS
;
9311 /* cfmv32sc<cond> MVDX[15:0],DSPSC. */
9313 do_mav_dspsc_2 (char * str
)
9315 skip_whitespace (str
);
9318 if (mav_reg_required_here (&str
, 12, REG_TYPE_MVDX
) == FAIL
9319 || skip_past_comma (&str
) == FAIL
9320 || mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
)
9323 inst
.error
= BAD_ARGS
;
9331 /* Maverick shift immediate instructions.
9332 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
9333 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
9336 do_mav_shift (char * str
,
9337 enum arm_reg_type reg0
,
9338 enum arm_reg_type reg1
)
9343 skip_whitespace (str
);
9347 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
9348 || skip_past_comma (&str
) == FAIL
9349 || mav_reg_required_here (&str
, 16, reg1
) == FAIL
9350 || skip_past_comma (&str
) == FAIL
)
9353 inst
.error
= BAD_ARGS
;
9357 /* Calculate the immediate operand.
9358 The operand is a 7bit signed number. */
9359 skip_whitespace (str
);
9364 if (!ISDIGIT (*str
) && *str
!= '-')
9366 inst
.error
= _("expecting immediate, 7bit operand");
9376 for (imm
= 0; *str
&& ISDIGIT (*str
); ++str
)
9377 imm
= imm
* 10 + *str
- '0';
9381 inst
.error
= _("immediate out of range");
9385 /* Make negative imm's into 7bit signed numbers. */
9392 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
9393 Bits 5-7 of the insn should have bits 4-6 of the immediate.
9394 Bit 4 should be 0. */
9395 imm
= (imm
& 0xf) | ((imm
& 0x70) << 1);
9397 inst
.instruction
|= imm
;
9402 do_mav_shift_1 (char * str
)
9404 do_mav_shift (str
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
9408 do_mav_shift_2 (char * str
)
9410 do_mav_shift (str
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
9414 mav_parse_offset (char ** str
, int * negative
)
9421 skip_whitespace (p
);
9434 inst
.error
= _("offset expected");
9438 for (offset
= 0; *p
&& ISDIGIT (*p
); ++p
)
9439 offset
= offset
* 10 + *p
- '0';
9443 inst
.error
= _("offset out of range");
9448 inst
.error
= _("offset not a multiple of 4");
9454 return *negative
? -offset
: offset
;
9457 /* Maverick load/store instructions.
9458 <insn><cond> CRd,[Rn,<offset>]{!}.
9459 <insn><cond> CRd,[Rn],<offset>. */
9462 do_mav_ldst (char * str
, enum arm_reg_type reg0
)
9464 int offset
, negative
;
9466 skip_whitespace (str
);
9468 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
9469 || skip_past_comma (&str
) == FAIL
9471 || reg_required_here (&str
, 16) == FAIL
)
9474 if (skip_past_comma (&str
) == SUCCESS
)
9476 /* You are here: "<offset>]{!}". */
9477 inst
.instruction
|= PRE_INDEX
;
9479 offset
= mav_parse_offset (&str
, &negative
);
9486 inst
.error
= _("missing ]");
9492 inst
.instruction
|= WRITE_BACK
;
9498 /* You are here: "], <offset>". */
9501 inst
.error
= _("missing ]");
9505 if (skip_past_comma (&str
) == FAIL
9506 || (offset
= mav_parse_offset (&str
, &negative
), inst
.error
))
9509 inst
.instruction
|= CP_T_WB
; /* Post indexed, set bit W. */
9515 inst
.instruction
|= CP_T_UD
; /* Positive, so set bit U. */
9517 inst
.instruction
|= offset
>> 2;
9523 inst
.error
= BAD_ARGS
;
9527 do_mav_ldst_1 (char * str
)
9529 do_mav_ldst (str
, REG_TYPE_MVF
);
9533 do_mav_ldst_2 (char * str
)
9535 do_mav_ldst (str
, REG_TYPE_MVD
);
9539 do_mav_ldst_3 (char * str
)
9541 do_mav_ldst (str
, REG_TYPE_MVFX
);
9545 do_mav_ldst_4 (char * str
)
9547 do_mav_ldst (str
, REG_TYPE_MVDX
);
9551 do_t_nop (char * str
)
9557 /* Handle the Format 4 instructions that do not have equivalents in other
9558 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
9562 do_t_arit (char * str
)
9566 skip_whitespace (str
);
9568 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9569 || skip_past_comma (&str
) == FAIL
9570 || (Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9572 inst
.error
= BAD_ARGS
;
9576 if (skip_past_comma (&str
) != FAIL
)
9578 /* Three operand format not allowed for TST, CMN, NEG and MVN.
9579 (It isn't allowed for CMP either, but that isn't handled by this
9581 if (inst
.instruction
== T_OPCODE_TST
9582 || inst
.instruction
== T_OPCODE_CMN
9583 || inst
.instruction
== T_OPCODE_NEG
9584 || inst
.instruction
== T_OPCODE_MVN
)
9586 inst
.error
= BAD_ARGS
;
9590 if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9595 inst
.error
= _("dest and source1 must be the same register");
9601 if (inst
.instruction
== T_OPCODE_MUL
9603 as_tsktsk (_("Rs and Rd must be different in MUL"));
9605 inst
.instruction
|= Rd
| (Rs
<< 3);
9610 do_t_add (char * str
)
9612 thumb_add_sub (str
, 0);
9616 do_t_asr (char * str
)
9618 thumb_shift (str
, THUMB_ASR
);
9622 do_t_branch9 (char * str
)
9624 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9626 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH9
;
9627 inst
.reloc
.pc_rel
= 1;
9632 do_t_branch12 (char * str
)
9634 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9636 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH12
;
9637 inst
.reloc
.pc_rel
= 1;
9641 /* Find the real, Thumb encoded start of a Thumb function. */
9644 find_real_start (symbolS
* symbolP
)
9647 const char * name
= S_GET_NAME (symbolP
);
9648 symbolS
* new_target
;
9650 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
9651 #define STUB_NAME ".real_start_of"
9656 /* Names that start with '.' are local labels, not function entry points.
9657 The compiler may generate BL instructions to these labels because it
9658 needs to perform a branch to a far away location. */
9662 real_start
= malloc (strlen (name
) + strlen (STUB_NAME
) + 1);
9663 sprintf (real_start
, "%s%s", STUB_NAME
, name
);
9665 new_target
= symbol_find (real_start
);
9667 if (new_target
== NULL
)
9669 as_warn ("Failed to find real start of function: %s\n", name
);
9670 new_target
= symbolP
;
9679 do_t_branch23 (char * str
)
9681 if (my_get_expression (& inst
.reloc
.exp
, & str
))
9684 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH23
;
9685 inst
.reloc
.pc_rel
= 1;
9688 /* If the destination of the branch is a defined symbol which does not have
9689 the THUMB_FUNC attribute, then we must be calling a function which has
9690 the (interfacearm) attribute. We look for the Thumb entry point to that
9691 function and change the branch to refer to that function instead. */
9692 if ( inst
.reloc
.exp
.X_op
== O_symbol
9693 && inst
.reloc
.exp
.X_add_symbol
!= NULL
9694 && S_IS_DEFINED (inst
.reloc
.exp
.X_add_symbol
)
9695 && ! THUMB_IS_FUNC (inst
.reloc
.exp
.X_add_symbol
))
9696 inst
.reloc
.exp
.X_add_symbol
=
9697 find_real_start (inst
.reloc
.exp
.X_add_symbol
);
9701 do_t_bx (char * str
)
9705 skip_whitespace (str
);
9707 if ((reg
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
9710 /* This sets THUMB_H2 from the top bit of reg. */
9711 inst
.instruction
|= reg
<< 3;
9713 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
9714 should cause the alignment to be checked once it is known. This is
9715 because BX PC only works if the instruction is word aligned. */
9721 do_t_compare (char * str
)
9723 thumb_mov_compare (str
, THUMB_COMPARE
);
9727 do_t_ldmstm (char * str
)
9732 skip_whitespace (str
);
9734 if ((Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9738 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
9742 if (skip_past_comma (&str
) == FAIL
9743 || (range
= reg_list (&str
)) == FAIL
)
9746 inst
.error
= BAD_ARGS
;
9750 if (inst
.reloc
.type
!= BFD_RELOC_UNUSED
)
9752 /* This really doesn't seem worth it. */
9753 inst
.reloc
.type
= BFD_RELOC_UNUSED
;
9754 inst
.error
= _("expression too complex");
9760 inst
.error
= _("only lo-regs valid in load/store multiple");
9764 inst
.instruction
|= (Rb
<< 8) | range
;
9769 do_t_ldr (char * str
)
9771 thumb_load_store (str
, THUMB_LOAD
, THUMB_WORD
);
9775 do_t_ldrb (char * str
)
9777 thumb_load_store (str
, THUMB_LOAD
, THUMB_BYTE
);
9781 do_t_ldrh (char * str
)
9783 thumb_load_store (str
, THUMB_LOAD
, THUMB_HALFWORD
);
9787 do_t_lds (char * str
)
9791 skip_whitespace (str
);
9793 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9794 || skip_past_comma (&str
) == FAIL
9796 || (Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9797 || skip_past_comma (&str
) == FAIL
9798 || (Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9802 inst
.error
= _("syntax: ldrs[b] Rd, [Rb, Ro]");
9806 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
9811 do_t_lsl (char * str
)
9813 thumb_shift (str
, THUMB_LSL
);
9817 do_t_lsr (char * str
)
9819 thumb_shift (str
, THUMB_LSR
);
9823 do_t_mov (char * str
)
9825 thumb_mov_compare (str
, THUMB_MOVE
);
9829 do_t_push_pop (char * str
)
9833 skip_whitespace (str
);
9835 if ((range
= reg_list (&str
)) == FAIL
)
9838 inst
.error
= BAD_ARGS
;
9842 if (inst
.reloc
.type
!= BFD_RELOC_UNUSED
)
9844 /* This really doesn't seem worth it. */
9845 inst
.reloc
.type
= BFD_RELOC_UNUSED
;
9846 inst
.error
= _("expression too complex");
9852 if ((inst
.instruction
== T_OPCODE_PUSH
9853 && (range
& ~0xff) == 1 << REG_LR
)
9854 || (inst
.instruction
== T_OPCODE_POP
9855 && (range
& ~0xff) == 1 << REG_PC
))
9857 inst
.instruction
|= THUMB_PP_PC_LR
;
9862 inst
.error
= _("invalid register list to push/pop instruction");
9867 inst
.instruction
|= range
;
9872 do_t_str (char * str
)
9874 thumb_load_store (str
, THUMB_STORE
, THUMB_WORD
);
9878 do_t_strb (char * str
)
9880 thumb_load_store (str
, THUMB_STORE
, THUMB_BYTE
);
9884 do_t_strh (char * str
)
9886 thumb_load_store (str
, THUMB_STORE
, THUMB_HALFWORD
);
9890 do_t_sub (char * str
)
9892 thumb_add_sub (str
, 1);
9896 do_t_swi (char * str
)
9898 skip_whitespace (str
);
9900 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9903 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
9908 do_t_adr (char * str
)
9912 /* This is a pseudo-op of the form "adr rd, label" to be converted
9913 into a relative address of the form "add rd, pc, #label-.-4". */
9914 skip_whitespace (str
);
9916 /* Store Rd in temporary location inside instruction. */
9917 if ((reg
= reg_required_here (&str
, 4)) == FAIL
9918 || (reg
> 7) /* For Thumb reg must be r0..r7. */
9919 || skip_past_comma (&str
) == FAIL
9920 || my_get_expression (&inst
.reloc
.exp
, &str
))
9923 inst
.error
= BAD_ARGS
;
9927 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
9928 inst
.reloc
.exp
.X_add_number
-= 4; /* PC relative adjust. */
9929 inst
.reloc
.pc_rel
= 1;
9930 inst
.instruction
|= REG_PC
; /* Rd is already placed into the instruction. */
9936 insert_reg (const struct reg_entry
* r
,
9937 struct hash_control
* htab
)
9939 int len
= strlen (r
->name
) + 2;
9940 char * buf
= xmalloc (len
);
9941 char * buf2
= xmalloc (len
);
9944 #ifdef REGISTER_PREFIX
9945 buf
[i
++] = REGISTER_PREFIX
;
9948 strcpy (buf
+ i
, r
->name
);
9950 for (i
= 0; buf
[i
]; i
++)
9951 buf2
[i
] = TOUPPER (buf
[i
]);
9955 hash_insert (htab
, buf
, (PTR
) r
);
9956 hash_insert (htab
, buf2
, (PTR
) r
);
9960 build_reg_hsh (struct reg_map
* map
)
9962 const struct reg_entry
*r
;
9964 if ((map
->htab
= hash_new ()) == NULL
)
9965 as_fatal (_("virtual memory exhausted"));
9967 for (r
= map
->names
; r
->name
!= NULL
; r
++)
9968 insert_reg (r
, map
->htab
);
9972 insert_reg_alias (char * str
,
9974 struct hash_control
*htab
)
9977 struct reg_entry
* new = xmalloc (sizeof (struct reg_entry
));
9978 const char * name
= xmalloc (strlen (str
) + 1);
9980 strcpy ((char *) name
, str
);
9983 new->number
= regnum
;
9984 new->builtin
= FALSE
;
9986 error
= hash_insert (htab
, name
, (PTR
) new);
9989 as_bad (_("failed to create an alias for %s, reason: %s"),
9991 free ((char *) name
);
9996 /* Look for the .req directive. This is of the form:
9998 new_register_name .req existing_register_name
10000 If we find one, or if it looks sufficiently like one that we want to
10001 handle any error here, return non-zero. Otherwise return zero. */
10004 create_register_alias (char * newname
, char * p
)
10010 skip_whitespace (q
);
10015 if (*q
&& !strncmp (q
, ".req ", 5))
10020 #ifndef IGNORE_OPCODE_CASE
10021 newname
= original_case_string
;
10023 copy_of_str
= newname
;
10026 skip_whitespace (q
);
10028 for (r
= q
; *r
!= '\0'; r
++)
10034 enum arm_reg_type new_type
, old_type
;
10039 old_type
= arm_reg_parse_any (q
);
10042 new_type
= arm_reg_parse_any (newname
);
10044 if (new_type
== REG_TYPE_MAX
)
10046 if (old_type
!= REG_TYPE_MAX
)
10048 old_regno
= arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
);
10049 insert_reg_alias (newname
, old_regno
,
10050 all_reg_maps
[old_type
].htab
);
10053 as_warn (_("register '%s' does not exist\n"), q
);
10055 else if (old_type
== REG_TYPE_MAX
)
10057 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
10062 /* Do not warn about redefinitions to the same alias. */
10063 if (new_type
!= old_type
10064 || (arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
)
10065 != arm_reg_parse (&q
, all_reg_maps
[new_type
].htab
)))
10066 as_warn (_("ignoring redefinition of register alias '%s'"),
10072 as_warn (_("ignoring incomplete .req pseuso op"));
10083 set_constant_flonums (void)
10087 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
10088 if (atof_ieee ((char *) fp_const
[i
], 'x', fp_values
[i
]) == NULL
)
10093 static const struct asm_opcode insns
[] =
10095 /* Core ARM Instructions. */
10096 {"and", 0xe0000000, 3, ARM_EXT_V1
, do_arit
},
10097 {"ands", 0xe0100000, 3, ARM_EXT_V1
, do_arit
},
10098 {"eor", 0xe0200000, 3, ARM_EXT_V1
, do_arit
},
10099 {"eors", 0xe0300000, 3, ARM_EXT_V1
, do_arit
},
10100 {"sub", 0xe0400000, 3, ARM_EXT_V1
, do_arit
},
10101 {"subs", 0xe0500000, 3, ARM_EXT_V1
, do_arit
},
10102 {"rsb", 0xe0600000, 3, ARM_EXT_V1
, do_arit
},
10103 {"rsbs", 0xe0700000, 3, ARM_EXT_V1
, do_arit
},
10104 {"add", 0xe0800000, 3, ARM_EXT_V1
, do_arit
},
10105 {"adds", 0xe0900000, 3, ARM_EXT_V1
, do_arit
},
10106 {"adc", 0xe0a00000, 3, ARM_EXT_V1
, do_arit
},
10107 {"adcs", 0xe0b00000, 3, ARM_EXT_V1
, do_arit
},
10108 {"sbc", 0xe0c00000, 3, ARM_EXT_V1
, do_arit
},
10109 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1
, do_arit
},
10110 {"rsc", 0xe0e00000, 3, ARM_EXT_V1
, do_arit
},
10111 {"rscs", 0xe0f00000, 3, ARM_EXT_V1
, do_arit
},
10112 {"orr", 0xe1800000, 3, ARM_EXT_V1
, do_arit
},
10113 {"orrs", 0xe1900000, 3, ARM_EXT_V1
, do_arit
},
10114 {"bic", 0xe1c00000, 3, ARM_EXT_V1
, do_arit
},
10115 {"bics", 0xe1d00000, 3, ARM_EXT_V1
, do_arit
},
10117 {"tst", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
10118 {"tsts", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
10119 {"tstp", 0xe110f000, 3, ARM_EXT_V1
, do_cmp
},
10120 {"teq", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
10121 {"teqs", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
10122 {"teqp", 0xe130f000, 3, ARM_EXT_V1
, do_cmp
},
10123 {"cmp", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
10124 {"cmps", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
10125 {"cmpp", 0xe150f000, 3, ARM_EXT_V1
, do_cmp
},
10126 {"cmn", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
10127 {"cmns", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
10128 {"cmnp", 0xe170f000, 3, ARM_EXT_V1
, do_cmp
},
10130 {"mov", 0xe1a00000, 3, ARM_EXT_V1
, do_mov
},
10131 {"movs", 0xe1b00000, 3, ARM_EXT_V1
, do_mov
},
10132 {"mvn", 0xe1e00000, 3, ARM_EXT_V1
, do_mov
},
10133 {"mvns", 0xe1f00000, 3, ARM_EXT_V1
, do_mov
},
10135 {"ldr", 0xe4100000, 3, ARM_EXT_V1
, do_ldst
},
10136 {"ldrb", 0xe4500000, 3, ARM_EXT_V1
, do_ldst
},
10137 {"ldrt", 0xe4300000, 3, ARM_EXT_V1
, do_ldstt
},
10138 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1
, do_ldstt
},
10139 {"str", 0xe4000000, 3, ARM_EXT_V1
, do_ldst
},
10140 {"strb", 0xe4400000, 3, ARM_EXT_V1
, do_ldst
},
10141 {"strt", 0xe4200000, 3, ARM_EXT_V1
, do_ldstt
},
10142 {"strbt", 0xe4600000, 3, ARM_EXT_V1
, do_ldstt
},
10144 {"stmia", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
10145 {"stmib", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
10146 {"stmda", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
10147 {"stmdb", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
10148 {"stmfd", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
10149 {"stmfa", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
10150 {"stmea", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
10151 {"stmed", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
10153 {"ldmia", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
10154 {"ldmib", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
10155 {"ldmda", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
10156 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
10157 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
10158 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
10159 {"ldmea", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
10160 {"ldmed", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
10162 {"swi", 0xef000000, 3, ARM_EXT_V1
, do_swi
},
10164 /* XXX This is the wrong place to do this. Think multi-arch. */
10165 {"bl", 0xeb000000, 2, ARM_EXT_V1
, do_branch
},
10166 {"b", 0xea000000, 1, ARM_EXT_V1
, do_branch
},
10168 {"bl", 0xebfffffe, 2, ARM_EXT_V1
, do_branch
},
10169 {"b", 0xeafffffe, 1, ARM_EXT_V1
, do_branch
},
10173 {"adr", 0xe28f0000, 3, ARM_EXT_V1
, do_adr
},
10174 {"adrl", 0xe28f0000, 3, ARM_EXT_V1
, do_adrl
},
10175 {"nop", 0xe1a00000, 3, ARM_EXT_V1
, do_nop
},
10177 /* ARM 2 multiplies. */
10178 {"mul", 0xe0000090, 3, ARM_EXT_V2
, do_mul
},
10179 {"muls", 0xe0100090, 3, ARM_EXT_V2
, do_mul
},
10180 {"mla", 0xe0200090, 3, ARM_EXT_V2
, do_mla
},
10181 {"mlas", 0xe0300090, 3, ARM_EXT_V2
, do_mla
},
10183 /* Generic coprocessor instructions. */
10184 {"cdp", 0xee000000, 3, ARM_EXT_V2
, do_cdp
},
10185 {"ldc", 0xec100000, 3, ARM_EXT_V2
, do_lstc
},
10186 {"ldcl", 0xec500000, 3, ARM_EXT_V2
, do_lstc
},
10187 {"stc", 0xec000000, 3, ARM_EXT_V2
, do_lstc
},
10188 {"stcl", 0xec400000, 3, ARM_EXT_V2
, do_lstc
},
10189 {"mcr", 0xee000010, 3, ARM_EXT_V2
, do_co_reg
},
10190 {"mrc", 0xee100010, 3, ARM_EXT_V2
, do_co_reg
},
10192 /* ARM 3 - swp instructions. */
10193 {"swp", 0xe1000090, 3, ARM_EXT_V2S
, do_swap
},
10194 {"swpb", 0xe1400090, 3, ARM_EXT_V2S
, do_swap
},
10196 /* ARM 6 Status register instructions. */
10197 {"mrs", 0xe10f0000, 3, ARM_EXT_V3
, do_mrs
},
10198 {"msr", 0xe120f000, 3, ARM_EXT_V3
, do_msr
},
10199 /* ScottB: our code uses 0xe128f000 for msr.
10200 NickC: but this is wrong because the bits 16 through 19 are
10201 handled by the PSR_xxx defines above. */
10203 /* ARM 7M long multiplies. */
10204 {"smull", 0xe0c00090, 5, ARM_EXT_V3M
, do_mull
},
10205 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M
, do_mull
},
10206 {"umull", 0xe0800090, 5, ARM_EXT_V3M
, do_mull
},
10207 {"umulls", 0xe0900090, 5, ARM_EXT_V3M
, do_mull
},
10208 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M
, do_mull
},
10209 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M
, do_mull
},
10210 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M
, do_mull
},
10211 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M
, do_mull
},
10213 /* ARM Architecture 4. */
10214 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4
, do_ldstv4
},
10215 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4
, do_ldstv4
},
10216 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4
, do_ldstv4
},
10217 {"strh", 0xe00000b0, 3, ARM_EXT_V4
, do_ldstv4
},
10219 /* ARM Architecture 4T. */
10220 /* Note: bx (and blx) are required on V5, even if the processor does
10221 not support Thumb. */
10222 {"bx", 0xe12fff10, 2, ARM_EXT_V4T
| ARM_EXT_V5
, do_bx
},
10224 /* ARM Architecture 5T. */
10225 /* Note: blx has 2 variants, so the .value is set dynamically.
10226 Only one of the variants has conditional execution. */
10227 {"blx", 0xe0000000, 3, ARM_EXT_V5
, do_blx
},
10228 {"clz", 0xe16f0f10, 3, ARM_EXT_V5
, do_clz
},
10229 {"bkpt", 0xe1200070, 0, ARM_EXT_V5
, do_bkpt
},
10230 {"ldc2", 0xfc100000, 0, ARM_EXT_V5
, do_lstc2
},
10231 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5
, do_lstc2
},
10232 {"stc2", 0xfc000000, 0, ARM_EXT_V5
, do_lstc2
},
10233 {"stc2l", 0xfc400000, 0, ARM_EXT_V5
, do_lstc2
},
10234 {"cdp2", 0xfe000000, 0, ARM_EXT_V5
, do_cdp2
},
10235 {"mcr2", 0xfe000010, 0, ARM_EXT_V5
, do_co_reg2
},
10236 {"mrc2", 0xfe100010, 0, ARM_EXT_V5
, do_co_reg2
},
10238 /* ARM Architecture 5TExP. */
10239 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP
, do_smla
},
10240 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP
, do_smla
},
10241 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP
, do_smla
},
10242 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP
, do_smla
},
10244 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP
, do_smla
},
10245 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP
, do_smla
},
10247 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP
, do_smlal
},
10248 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP
, do_smlal
},
10249 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP
, do_smlal
},
10250 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP
, do_smlal
},
10252 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP
, do_smul
},
10253 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP
, do_smul
},
10254 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP
, do_smul
},
10255 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP
, do_smul
},
10257 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP
, do_smul
},
10258 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP
, do_smul
},
10260 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP
, do_qadd
},
10261 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP
, do_qadd
},
10262 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP
, do_qadd
},
10263 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP
, do_qadd
},
10265 /* ARM Architecture 5TE. */
10266 {"pld", 0xf450f000, 0, ARM_EXT_V5E
, do_pld
},
10267 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E
, do_ldrd
},
10268 {"strd", 0xe00000f0, 3, ARM_EXT_V5E
, do_ldrd
},
10270 {"mcrr", 0xec400000, 4, ARM_EXT_V5E
, do_co_reg2c
},
10271 {"mrrc", 0xec500000, 4, ARM_EXT_V5E
, do_co_reg2c
},
10273 /* ARM Architecture 5TEJ. */
10274 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J
, do_bxj
},
10277 { "cps", 0xf1020000, 0, ARM_EXT_V6
, do_cps
},
10278 { "cpsie", 0xf1080000, 0, ARM_EXT_V6
, do_cpsi
},
10279 { "cpsid", 0xf10C0000, 0, ARM_EXT_V6
, do_cpsi
},
10280 { "ldrex", 0xe1900f9f, 5, ARM_EXT_V6
, do_ldrex
},
10281 { "mcrr2", 0xfc400000, 0, ARM_EXT_V6
, do_co_reg2c
},
10282 { "mrrc2", 0xfc500000, 0, ARM_EXT_V6
, do_co_reg2c
},
10283 { "pkhbt", 0xe6800010, 5, ARM_EXT_V6
, do_pkhbt
},
10284 { "pkhtb", 0xe6800050, 5, ARM_EXT_V6
, do_pkhtb
},
10285 { "qadd16", 0xe6200f10, 6, ARM_EXT_V6
, do_qadd16
},
10286 { "qadd8", 0xe6200f90, 5, ARM_EXT_V6
, do_qadd16
},
10287 { "qaddsubx", 0xe6200f30, 8, ARM_EXT_V6
, do_qadd16
},
10288 { "qsub16", 0xe6200f70, 6, ARM_EXT_V6
, do_qadd16
},
10289 { "qsub8", 0xe6200ff0, 5, ARM_EXT_V6
, do_qadd16
},
10290 { "qsubaddx", 0xe6200f50, 8, ARM_EXT_V6
, do_qadd16
},
10291 { "sadd16", 0xe6100f10, 6, ARM_EXT_V6
, do_qadd16
},
10292 { "sadd8", 0xe6100f90, 5, ARM_EXT_V6
, do_qadd16
},
10293 { "saddsubx", 0xe6100f30, 8, ARM_EXT_V6
, do_qadd16
},
10294 { "shadd16", 0xe6300f10, 7, ARM_EXT_V6
, do_qadd16
},
10295 { "shadd8", 0xe6300f90, 6, ARM_EXT_V6
, do_qadd16
},
10296 { "shaddsubx", 0xe6300f30, 9, ARM_EXT_V6
, do_qadd16
},
10297 { "shsub16", 0xe6300f70, 7, ARM_EXT_V6
, do_qadd16
},
10298 { "shsub8", 0xe6300ff0, 6, ARM_EXT_V6
, do_qadd16
},
10299 { "shsubaddx", 0xe6300f50, 9, ARM_EXT_V6
, do_qadd16
},
10300 { "ssub16", 0xe6100f70, 6, ARM_EXT_V6
, do_qadd16
},
10301 { "ssub8", 0xe6100ff0, 5, ARM_EXT_V6
, do_qadd16
},
10302 { "ssubaddx", 0xe6100f50, 8, ARM_EXT_V6
, do_qadd16
},
10303 { "uadd16", 0xe6500f10, 6, ARM_EXT_V6
, do_qadd16
},
10304 { "uadd8", 0xe6500f90, 5, ARM_EXT_V6
, do_qadd16
},
10305 { "uaddsubx", 0xe6500f30, 8, ARM_EXT_V6
, do_qadd16
},
10306 { "uhadd16", 0xe6700f10, 7, ARM_EXT_V6
, do_qadd16
},
10307 { "uhadd8", 0xe6700f90, 6, ARM_EXT_V6
, do_qadd16
},
10308 { "uhaddsubx", 0xe6700f30, 9, ARM_EXT_V6
, do_qadd16
},
10309 { "uhsub16", 0xe6700f70, 7, ARM_EXT_V6
, do_qadd16
},
10310 { "uhsub8", 0xe6700ff0, 6, ARM_EXT_V6
, do_qadd16
},
10311 { "uhsubaddx", 0xe6700f50, 9, ARM_EXT_V6
, do_qadd16
},
10312 { "uqadd16", 0xe6600f10, 7, ARM_EXT_V6
, do_qadd16
},
10313 { "uqadd8", 0xe6600f90, 6, ARM_EXT_V6
, do_qadd16
},
10314 { "uqaddsubx", 0xe6600f30, 9, ARM_EXT_V6
, do_qadd16
},
10315 { "uqsub16", 0xe6600f70, 7, ARM_EXT_V6
, do_qadd16
},
10316 { "uqsub8", 0xe6600ff0, 6, ARM_EXT_V6
, do_qadd16
},
10317 { "uqsubaddx", 0xe6600f50, 9, ARM_EXT_V6
, do_qadd16
},
10318 { "usub16", 0xe6500f70, 6, ARM_EXT_V6
, do_qadd16
},
10319 { "usub8", 0xe6500ff0, 5, ARM_EXT_V6
, do_qadd16
},
10320 { "usubaddx", 0xe6500f50, 8, ARM_EXT_V6
, do_qadd16
},
10321 { "rev", 0xe6bf0f30, 3, ARM_EXT_V6
, do_rev
},
10322 { "rev16", 0xe6bf0fb0, 5, ARM_EXT_V6
, do_rev
},
10323 { "revsh", 0xe6ff0fb0, 5, ARM_EXT_V6
, do_rev
},
10324 { "rfeia", 0xf8900a00, 0, ARM_EXT_V6
, do_rfe
},
10325 { "rfeib", 0xf9900a00, 0, ARM_EXT_V6
, do_rfe
},
10326 { "rfeda", 0xf8100a00, 0, ARM_EXT_V6
, do_rfe
},
10327 { "rfedb", 0xf9100a00, 0, ARM_EXT_V6
, do_rfe
},
10328 { "rfefd", 0xf8900a00, 0, ARM_EXT_V6
, do_rfe
},
10329 { "rfefa", 0xf9900a00, 0, ARM_EXT_V6
, do_rfe
},
10330 { "rfeea", 0xf8100a00, 0, ARM_EXT_V6
, do_rfe
},
10331 { "rfeed", 0xf9100a00, 0, ARM_EXT_V6
, do_rfe
},
10332 { "sxtah", 0xe6b00070, 5, ARM_EXT_V6
, do_sxtah
},
10333 { "sxtab16", 0xe6800070, 7, ARM_EXT_V6
, do_sxtah
},
10334 { "sxtab", 0xe6a00070, 5, ARM_EXT_V6
, do_sxtah
},
10335 { "sxth", 0xe6bf0070, 4, ARM_EXT_V6
, do_sxth
},
10336 { "sxtb16", 0xe68f0070, 6, ARM_EXT_V6
, do_sxth
},
10337 { "sxtb", 0xe6af0070, 4, ARM_EXT_V6
, do_sxth
},
10338 { "uxtah", 0xe6f00070, 5, ARM_EXT_V6
, do_sxtah
},
10339 { "uxtab16", 0xe6c00070, 7, ARM_EXT_V6
, do_sxtah
},
10340 { "uxtab", 0xe6e00070, 5, ARM_EXT_V6
, do_sxtah
},
10341 { "uxth", 0xe6ff0070, 4, ARM_EXT_V6
, do_sxth
},
10342 { "uxtb16", 0xe6cf0070, 6, ARM_EXT_V6
, do_sxth
},
10343 { "uxtb", 0xe6ef0070, 4, ARM_EXT_V6
, do_sxth
},
10344 { "sel", 0xe68000b0, 3, ARM_EXT_V6
, do_qadd16
},
10345 { "setend", 0xf1010000, 0, ARM_EXT_V6
, do_setend
},
10346 { "smlad", 0xe7000010, 5, ARM_EXT_V6
, do_smlad
},
10347 { "smladx", 0xe7000030, 6, ARM_EXT_V6
, do_smlad
},
10348 { "smlald", 0xe7400010, 6, ARM_EXT_V6
, do_smlald
},
10349 { "smlaldx", 0xe7400030, 7, ARM_EXT_V6
, do_smlald
},
10350 { "smlsd", 0xe7000050, 5, ARM_EXT_V6
, do_smlad
},
10351 { "smlsdx", 0xe7000070, 6, ARM_EXT_V6
, do_smlad
},
10352 { "smlsld", 0xe7400050, 6, ARM_EXT_V6
, do_smlald
},
10353 { "smlsldx", 0xe7400070, 7, ARM_EXT_V6
, do_smlald
},
10354 { "smmla", 0xe7500010, 5, ARM_EXT_V6
, do_smlad
},
10355 { "smmlar", 0xe7500030, 6, ARM_EXT_V6
, do_smlad
},
10356 { "smmls", 0xe75000d0, 5, ARM_EXT_V6
, do_smlad
},
10357 { "smmlsr", 0xe75000f0, 6, ARM_EXT_V6
, do_smlad
},
10358 { "smmul", 0xe750f010, 5, ARM_EXT_V6
, do_smmul
},
10359 { "smmulr", 0xe750f030, 6, ARM_EXT_V6
, do_smmul
},
10360 { "smuad", 0xe700f010, 5, ARM_EXT_V6
, do_smmul
},
10361 { "smuadx", 0xe700f030, 6, ARM_EXT_V6
, do_smmul
},
10362 { "smusd", 0xe700f050, 5, ARM_EXT_V6
, do_smmul
},
10363 { "smusdx", 0xe700f070, 6, ARM_EXT_V6
, do_smmul
},
10364 { "srsia", 0xf8cd0500, 0, ARM_EXT_V6
, do_srs
},
10365 { "srsib", 0xf9cd0500, 0, ARM_EXT_V6
, do_srs
},
10366 { "srsda", 0xf84d0500, 0, ARM_EXT_V6
, do_srs
},
10367 { "srsdb", 0xf94d0500, 0, ARM_EXT_V6
, do_srs
},
10368 { "ssat", 0xe6a00010, 4, ARM_EXT_V6
, do_ssat
},
10369 { "ssat16", 0xe6a00f30, 6, ARM_EXT_V6
, do_ssat16
},
10370 { "strex", 0xe1800f90, 5, ARM_EXT_V6
, do_strex
},
10371 { "umaal", 0xe0400090, 5, ARM_EXT_V6
, do_umaal
},
10372 { "usad8", 0xe780f010, 5, ARM_EXT_V6
, do_smmul
},
10373 { "usada8", 0xe7800010, 6, ARM_EXT_V6
, do_smlad
},
10374 { "usat", 0xe6e00010, 4, ARM_EXT_V6
, do_usat
},
10375 { "usat16", 0xe6e00f30, 6, ARM_EXT_V6
, do_usat16
},
10378 { "clrex", 0xf57ff01f, 0, ARM_EXT_V6K
, do_empty
},
10379 { "ldrexb", 0xe1d00f9f, 6, ARM_EXT_V6K
, do_ldrex
},
10380 { "ldrexd", 0xe1b00f9f, 6, ARM_EXT_V6K
, do_ldrex
},
10381 { "ldrexh", 0xe1f00f9f, 6, ARM_EXT_V6K
, do_ldrex
},
10382 { "sev", 0xe320f004, 3, ARM_EXT_V6K
, do_empty
},
10383 { "strexb", 0xe1c00f90, 6, ARM_EXT_V6K
, do_strex
},
10384 { "strexd", 0xe1a00f90, 6, ARM_EXT_V6K
, do_strex
},
10385 { "strexh", 0xe1e00f90, 6, ARM_EXT_V6K
, do_strex
},
10386 { "wfe", 0xe320f002, 3, ARM_EXT_V6K
, do_empty
},
10387 { "wfi", 0xe320f003, 3, ARM_EXT_V6K
, do_empty
},
10388 { "yield", 0xe320f001, 5, ARM_EXT_V6K
, do_empty
},
10391 { "smi", 0xe1600070, 3, ARM_EXT_V6Z
, do_smi
},
10394 { "bfc", 0xe7c0001f, 3, ARM_EXT_V6T2
, do_bfc
},
10395 { "bfi", 0xe7c00010, 3, ARM_EXT_V6T2
, do_bfi
},
10396 { "mls", 0xe0600090, 3, ARM_EXT_V6T2
, do_mls
},
10397 { "movw", 0xe3000000, 4, ARM_EXT_V6T2
, do_mov16
},
10398 { "movt", 0xe3400000, 4, ARM_EXT_V6T2
, do_mov16
},
10399 { "rbit", 0xe3ff0f30, 4, ARM_EXT_V6T2
, do_rbit
},
10400 { "sbfx", 0xe7a00050, 4, ARM_EXT_V6T2
, do_bfx
},
10401 { "ubfx", 0xe7e00050, 4, ARM_EXT_V6T2
, do_bfx
},
10403 { "ldrht", 0xe03000b0, 3, ARM_EXT_V6T2
, do_ldsttv4
},
10404 { "ldrsht", 0xe03000f0, 3, ARM_EXT_V6T2
, do_ldsttv4
},
10405 { "ldrsbt", 0xe03000d0, 3, ARM_EXT_V6T2
, do_ldsttv4
},
10406 { "strht", 0xe02000b0, 3, ARM_EXT_V6T2
, do_ldsttv4
},
10408 /* Core FPA instruction set (V1). */
10409 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
10410 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
10411 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
10412 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
10414 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10415 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10416 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10417 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10419 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10420 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10421 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10422 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10424 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10425 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10426 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10427 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10428 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10429 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10430 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10431 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10432 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10433 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10434 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10435 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10437 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10438 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10439 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10440 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10441 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10442 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10443 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10444 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10445 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10446 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10447 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10448 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10450 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10451 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10452 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10453 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10454 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10455 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10456 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10457 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10458 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10459 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10460 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10461 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10463 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10464 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10465 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10466 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10467 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10468 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10469 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10470 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10471 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10472 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10473 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10474 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10476 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10477 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10478 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10479 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10480 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10481 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10482 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10483 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10484 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10485 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10486 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10487 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10489 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10490 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10491 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10492 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10493 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10494 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10495 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10496 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10497 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10498 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10499 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10500 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10502 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10503 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10504 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10505 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10506 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10507 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10508 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10509 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10510 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10511 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10512 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10513 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10515 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10516 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10517 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10518 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10519 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10520 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10521 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10522 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10523 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10524 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10525 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10526 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10528 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10529 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10530 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10531 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10532 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10533 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10534 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10535 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10536 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10537 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10538 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10539 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10541 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10542 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10543 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10544 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10545 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10546 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10547 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10548 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10549 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10550 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10551 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10552 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10554 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10555 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10556 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10557 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10558 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10559 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10560 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10561 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10562 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10563 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10564 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10565 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10567 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10568 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10569 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10570 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10571 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10572 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10573 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10574 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10575 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10576 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10577 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10578 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10580 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10581 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10582 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10583 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10584 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10585 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10586 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10587 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10588 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10589 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10590 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10591 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10593 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10594 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10595 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10596 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10597 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10598 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10599 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10600 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10601 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10602 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10603 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10604 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10606 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10607 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10608 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10609 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10610 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10611 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10612 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10613 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10614 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10615 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10616 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10617 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10619 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10620 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10621 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10622 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10623 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10624 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10625 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10626 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10627 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10628 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10629 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10630 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10632 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10633 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10634 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10635 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10636 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10637 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10638 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10639 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10640 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10641 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10642 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10643 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10645 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10646 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10647 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10648 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10649 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10650 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10651 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10652 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10653 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10654 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10655 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10656 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10658 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10659 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10660 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10661 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10662 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10663 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10664 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10665 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10666 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10667 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10668 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10669 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10671 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10672 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10673 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10674 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10675 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10676 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10677 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10678 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10679 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10680 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10681 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10682 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10684 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10685 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10686 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10687 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10688 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10689 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10690 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10691 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10692 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10693 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10694 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10695 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10697 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10698 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10699 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10700 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10701 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10702 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10703 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10704 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10705 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10706 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10707 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10708 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10710 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10711 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10712 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10713 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10714 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10715 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10716 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10717 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10718 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10719 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10720 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10721 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10723 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10724 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10725 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10726 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10727 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10728 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10729 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10730 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10731 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10732 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10733 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10734 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10736 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10737 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10738 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10739 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10740 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10741 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10742 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10743 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10744 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10745 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10746 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10747 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10749 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10750 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10751 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10752 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10753 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10754 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10755 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10756 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10757 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10758 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10759 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10760 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10762 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10763 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10764 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10765 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10766 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10767 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10768 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10769 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10770 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10771 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10772 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10773 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10775 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10776 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10777 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10778 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10779 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10780 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10781 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10782 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10783 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10784 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10785 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10786 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10788 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10789 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10790 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10791 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10792 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10793 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10794 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10795 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10796 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10797 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10798 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10799 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10801 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10802 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10803 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10804 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10805 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
10806 not be an optional suffix, but part of the instruction. To be
10807 compatible, we accept either. */
10808 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10809 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10811 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10812 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10813 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10814 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10815 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10816 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10817 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10818 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10819 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10820 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10821 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10822 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10824 /* The implementation of the FIX instruction is broken on some
10825 assemblers, in that it accepts a precision specifier as well as a
10826 rounding specifier, despite the fact that this is meaningless.
10827 To be more compatible, we accept it as well, though of course it
10828 does not set any bits. */
10829 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10830 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10831 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10832 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10833 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10834 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10835 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10836 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10837 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10838 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10839 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10840 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10841 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10843 /* Instructions that were new with the real FPA, call them V2. */
10844 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10845 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10846 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10847 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10848 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10849 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10851 /* VFP V1xD (single precision). */
10852 /* Moves and type conversions. */
10853 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10854 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_reg_from_sp
},
10855 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_from_reg
},
10856 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD
, do_empty
},
10857 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10858 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10859 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10860 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10861 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10862 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10863 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_reg_from_ctrl
},
10864 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_ctrl_from_reg
},
10866 /* Memory operations. */
10867 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldst
},
10868 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldst
},
10869 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
10870 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
10871 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
10872 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
10873 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
10874 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
10875 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
10876 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
10877 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
10878 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
10879 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
10880 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
10881 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
10882 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
10883 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
10884 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
10886 /* Monadic operations. */
10887 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10888 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10889 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10891 /* Dyadic operations. */
10892 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10893 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10894 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10895 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10896 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10897 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10898 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10899 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10900 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10903 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10904 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_compare_z
},
10905 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10906 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_compare_z
},
10908 /* VFP V1 (Double precision). */
10909 /* Moves and type conversions. */
10910 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10911 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
10912 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10913 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1
, do_vfp_dp_from_reg
},
10914 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1
, do_vfp_dp_from_reg
},
10915 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1
, do_vfp_reg_from_dp
},
10916 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1
, do_vfp_reg_from_dp
},
10917 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
10918 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
10919 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10920 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10921 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10922 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10924 /* Memory operations. */
10925 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1
, do_vfp_dp_ldst
},
10926 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1
, do_vfp_dp_ldst
},
10927 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
10928 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
10929 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
10930 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
10931 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
10932 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
10933 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
10934 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
10936 /* Monadic operations. */
10937 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10938 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10939 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10941 /* Dyadic operations. */
10942 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10943 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10944 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10945 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10946 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10947 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10948 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10949 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10950 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10953 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10954 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_compare_z
},
10955 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10956 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1
, do_vfp_dp_compare_z
},
10959 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2
, do_vfp_sp2_from_reg2
},
10960 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2
, do_vfp_reg2_from_sp2
},
10961 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2
, do_vfp_dp_from_reg2
},
10962 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2
, do_vfp_reg2_from_dp
},
10964 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
10965 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE
, do_xsc_mia
},
10966 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10967 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10968 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10969 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10970 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10971 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE
, do_xsc_mar
},
10972 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE
, do_xsc_mra
},
10974 /* Intel Wireless MMX technology instructions. */
10975 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
10976 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
10977 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
10978 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
10979 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
10980 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
10981 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
10982 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
10983 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
10984 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10985 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10986 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10987 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10988 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10989 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10990 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
10991 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
10992 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
10993 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmcr
},
10994 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_tmcrr
},
10995 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10996 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10997 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10998 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10999 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
11000 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
11001 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
11002 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
11003 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
11004 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmrc
},
11005 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_tmrrc
},
11006 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
11007 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
11008 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
11009 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11010 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11011 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11012 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11013 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11014 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11015 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11016 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11017 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11018 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11019 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11020 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11021 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_waligni
},
11022 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11023 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11024 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11025 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11026 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11027 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11028 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11029 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11030 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11031 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11032 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11033 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11034 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11035 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11036 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11037 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11038 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11039 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11040 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11041 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
11042 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
11043 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
11044 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
11045 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11046 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11047 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11048 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11049 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11050 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11051 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11052 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11053 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11054 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11055 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11056 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11057 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11058 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11059 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11060 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11061 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11062 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11063 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wmov
},
11064 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11065 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11066 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11067 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11068 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11069 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11070 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11071 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11072 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11073 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11074 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11075 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11076 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
11077 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11078 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
11079 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11080 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
11081 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11082 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11083 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11084 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11085 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wshufh
},
11086 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11087 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
11088 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11089 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
11090 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11091 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
11092 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11093 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
11094 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11095 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
11096 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11097 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
11098 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11099 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
11100 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11101 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
11102 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11103 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
11104 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
11105 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
11106 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
11107 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
11108 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11109 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11110 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11111 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11112 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11113 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11114 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11115 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11116 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11117 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11118 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11119 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11120 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11121 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11122 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11123 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11124 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11125 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11126 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11127 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11128 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11129 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11130 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11131 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11132 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11133 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11134 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11135 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11136 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wzero
},
11138 /* Cirrus Maverick instructions. */
11139 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_1
},
11140 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_2
},
11141 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_3
},
11142 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_4
},
11143 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_1
},
11144 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_2
},
11145 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_3
},
11146 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_4
},
11147 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK
, do_mav_binops_2a
},
11148 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1a
},
11149 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK
, do_mav_binops_2b
},
11150 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1b
},
11151 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK
, do_mav_binops_2b
},
11152 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1b
},
11153 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK
, do_mav_binops_2c
},
11154 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1c
},
11155 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK
, do_mav_binops_2c
},
11156 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1c
},
11157 {"cfmval32", 0xee200440, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
11158 {"cfmv32al", 0xee100440, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
11159 {"cfmvam32", 0xee200460, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
11160 {"cfmv32am", 0xee100460, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
11161 {"cfmvah32", 0xee200480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
11162 {"cfmv32ah", 0xee100480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
11163 {"cfmva32", 0xee2004a0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
11164 {"cfmv32a", 0xee1004a0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
11165 {"cfmva64", 0xee2004c0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3c
},
11166 {"cfmv64a", 0xee1004c0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3d
},
11167 {"cfmvsc32", 0xee2004e0, 8, ARM_CEXT_MAVERICK
, do_mav_dspsc_1
},
11168 {"cfmv32sc", 0xee1004e0, 8, ARM_CEXT_MAVERICK
, do_mav_dspsc_2
},
11169 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
11170 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
11171 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1f
},
11172 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1g
},
11173 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1h
},
11174 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1i
},
11175 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1j
},
11176 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1k
},
11177 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1l
},
11178 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1m
},
11179 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK
, do_mav_binops_1l
},
11180 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK
, do_mav_binops_1m
},
11181 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK
, do_mav_triple_4a
},
11182 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK
, do_mav_triple_4b
},
11183 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK
, do_mav_shift_1
},
11184 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK
, do_mav_shift_2
},
11185 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5a
},
11186 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5b
},
11187 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5c
},
11188 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5d
},
11189 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
11190 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
11191 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
11192 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
11193 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
11194 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
11195 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
11196 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
11197 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
11198 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
11199 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1n
},
11200 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1o
},
11201 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1n
},
11202 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1o
},
11203 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
11204 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
11205 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
11206 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
11207 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
11208 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
11209 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
11210 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
11211 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK
, do_mav_quad_6a
},
11212 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK
, do_mav_quad_6a
},
11213 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK
, do_mav_quad_6b
},
11214 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK
, do_mav_quad_6b
},
11217 /* Iterate over the base tables to create the instruction patterns. */
11220 build_arm_ops_hsh (void)
11224 static struct obstack insn_obstack
;
11226 obstack_begin (&insn_obstack
, 4000);
11228 for (i
= 0; i
< sizeof (insns
) / sizeof (struct asm_opcode
); i
++)
11230 const struct asm_opcode
*insn
= insns
+ i
;
11232 if (insn
->cond_offset
!= 0)
11234 /* Insn supports conditional execution. Build the varaints
11235 and insert them in the hash table. */
11236 for (j
= 0; j
< sizeof (conds
) / sizeof (struct asm_cond
); j
++)
11238 unsigned len
= strlen (insn
->template);
11239 struct asm_opcode
*new;
11242 new = obstack_alloc (&insn_obstack
, sizeof (struct asm_opcode
));
11243 /* All condition codes are two characters. */
11244 template = obstack_alloc (&insn_obstack
, len
+ 3);
11246 strncpy (template, insn
->template, insn
->cond_offset
);
11247 strcpy (template + insn
->cond_offset
, conds
[j
].template);
11248 if (len
> insn
->cond_offset
)
11249 strcpy (template + insn
->cond_offset
+ 2,
11250 insn
->template + insn
->cond_offset
);
11251 new->template = template;
11252 new->cond_offset
= 0;
11253 new->variant
= insn
->variant
;
11254 new->parms
= insn
->parms
;
11255 new->value
= (insn
->value
& ~COND_MASK
) | conds
[j
].value
;
11257 hash_insert (arm_ops_hsh
, new->template, (PTR
) new);
11260 /* Finally, insert the unconditional insn in the table directly;
11261 no need to build a copy. */
11262 hash_insert (arm_ops_hsh
, insn
->template, (PTR
) insn
);
11267 static const struct thumb_opcode tinsns
[] =
11269 /* Thumb v1 (ARMv4T). */
11270 {"adc", 0x4140, 2, ARM_EXT_V4T
, do_t_arit
},
11271 {"add", 0x0000, 2, ARM_EXT_V4T
, do_t_add
},
11272 {"and", 0x4000, 2, ARM_EXT_V4T
, do_t_arit
},
11273 {"asr", 0x0000, 2, ARM_EXT_V4T
, do_t_asr
},
11274 {"b", T_OPCODE_BRANCH
, 2, ARM_EXT_V4T
, do_t_branch12
},
11275 {"beq", 0xd0fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11276 {"bne", 0xd1fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11277 {"bcs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11278 {"bhs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11279 {"bcc", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11280 {"bul", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11281 {"blo", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11282 {"bmi", 0xd4fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11283 {"bpl", 0xd5fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11284 {"bvs", 0xd6fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11285 {"bvc", 0xd7fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11286 {"bhi", 0xd8fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11287 {"bls", 0xd9fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11288 {"bge", 0xdafe, 2, ARM_EXT_V4T
, do_t_branch9
},
11289 {"blt", 0xdbfe, 2, ARM_EXT_V4T
, do_t_branch9
},
11290 {"bgt", 0xdcfe, 2, ARM_EXT_V4T
, do_t_branch9
},
11291 {"ble", 0xddfe, 2, ARM_EXT_V4T
, do_t_branch9
},
11292 {"bal", 0xdefe, 2, ARM_EXT_V4T
, do_t_branch9
},
11293 {"bic", 0x4380, 2, ARM_EXT_V4T
, do_t_arit
},
11294 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T
, do_t_branch23
},
11295 {"bx", 0x4700, 2, ARM_EXT_V4T
, do_t_bx
},
11296 {"cmn", T_OPCODE_CMN
, 2, ARM_EXT_V4T
, do_t_arit
},
11297 {"cmp", 0x0000, 2, ARM_EXT_V4T
, do_t_compare
},
11298 {"eor", 0x4040, 2, ARM_EXT_V4T
, do_t_arit
},
11299 {"ldmia", 0xc800, 2, ARM_EXT_V4T
, do_t_ldmstm
},
11300 {"ldr", 0x0000, 2, ARM_EXT_V4T
, do_t_ldr
},
11301 {"ldrb", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrb
},
11302 {"ldrh", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrh
},
11303 {"ldrsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
11304 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
11305 {"ldsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
11306 {"ldsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
11307 {"lsl", 0x0000, 2, ARM_EXT_V4T
, do_t_lsl
},
11308 {"lsr", 0x0000, 2, ARM_EXT_V4T
, do_t_lsr
},
11309 {"mov", 0x0000, 2, ARM_EXT_V4T
, do_t_mov
},
11310 {"mul", T_OPCODE_MUL
, 2, ARM_EXT_V4T
, do_t_arit
},
11311 {"mvn", T_OPCODE_MVN
, 2, ARM_EXT_V4T
, do_t_arit
},
11312 {"neg", T_OPCODE_NEG
, 2, ARM_EXT_V4T
, do_t_arit
},
11313 {"orr", 0x4300, 2, ARM_EXT_V4T
, do_t_arit
},
11314 {"pop", 0xbc00, 2, ARM_EXT_V4T
, do_t_push_pop
},
11315 {"push", 0xb400, 2, ARM_EXT_V4T
, do_t_push_pop
},
11316 {"ror", 0x41c0, 2, ARM_EXT_V4T
, do_t_arit
},
11317 {"sbc", 0x4180, 2, ARM_EXT_V4T
, do_t_arit
},
11318 {"stmia", 0xc000, 2, ARM_EXT_V4T
, do_t_ldmstm
},
11319 {"str", 0x0000, 2, ARM_EXT_V4T
, do_t_str
},
11320 {"strb", 0x0000, 2, ARM_EXT_V4T
, do_t_strb
},
11321 {"strh", 0x0000, 2, ARM_EXT_V4T
, do_t_strh
},
11322 {"swi", 0xdf00, 2, ARM_EXT_V4T
, do_t_swi
},
11323 {"sub", 0x0000, 2, ARM_EXT_V4T
, do_t_sub
},
11324 {"tst", T_OPCODE_TST
, 2, ARM_EXT_V4T
, do_t_arit
},
11326 {"adr", 0x0000, 2, ARM_EXT_V4T
, do_t_adr
},
11327 {"nop", 0x46C0, 2, ARM_EXT_V4T
, do_t_nop
}, /* mov r8,r8 */
11328 /* Thumb v2 (ARMv5T). */
11329 {"blx", 0, 0, ARM_EXT_V5T
, do_t_blx
},
11330 {"bkpt", 0xbe00, 2, ARM_EXT_V5T
, do_t_bkpt
},
11333 {"cpsie", 0xb660, 2, ARM_EXT_V6
, do_t_cps
},
11334 {"cpsid", 0xb670, 2, ARM_EXT_V6
, do_t_cps
},
11335 {"cpy", 0x4600, 2, ARM_EXT_V6
, do_t_cpy
},
11336 {"rev", 0xba00, 2, ARM_EXT_V6
, do_t_arit
},
11337 {"rev16", 0xba40, 2, ARM_EXT_V6
, do_t_arit
},
11338 {"revsh", 0xbac0, 2, ARM_EXT_V6
, do_t_arit
},
11339 {"setend", 0xb650, 2, ARM_EXT_V6
, do_t_setend
},
11340 {"sxth", 0xb200, 2, ARM_EXT_V6
, do_t_arit
},
11341 {"sxtb", 0xb240, 2, ARM_EXT_V6
, do_t_arit
},
11342 {"uxth", 0xb280, 2, ARM_EXT_V6
, do_t_arit
},
11343 {"uxtb", 0xb2c0, 2, ARM_EXT_V6
, do_t_arit
},
11346 {"sev", 0xbf40, 2, ARM_EXT_V6K
, do_empty
},
11347 {"wfe", 0xbf20, 2, ARM_EXT_V6K
, do_empty
},
11348 {"wfi", 0xbf30, 2, ARM_EXT_V6K
, do_empty
},
11349 {"yield", 0xbf10, 2, ARM_EXT_V6K
, do_empty
},
11358 if ( (arm_ops_hsh
= hash_new ()) == NULL
11359 || (arm_tops_hsh
= hash_new ()) == NULL
11360 || (arm_cond_hsh
= hash_new ()) == NULL
11361 || (arm_shift_hsh
= hash_new ()) == NULL
11362 || (arm_psr_hsh
= hash_new ()) == NULL
)
11363 as_fatal (_("virtual memory exhausted"));
11365 build_arm_ops_hsh ();
11366 for (i
= 0; i
< sizeof (tinsns
) / sizeof (struct thumb_opcode
); i
++)
11367 hash_insert (arm_tops_hsh
, tinsns
[i
].template, (PTR
) (tinsns
+ i
));
11368 for (i
= 0; i
< sizeof (conds
) / sizeof (struct asm_cond
); i
++)
11369 hash_insert (arm_cond_hsh
, conds
[i
].template, (PTR
) (conds
+ i
));
11370 for (i
= 0; i
< sizeof (shift_names
) / sizeof (struct asm_shift_name
); i
++)
11371 hash_insert (arm_shift_hsh
, shift_names
[i
].name
, (PTR
) (shift_names
+ i
));
11372 for (i
= 0; i
< sizeof (psrs
) / sizeof (struct asm_psr
); i
++)
11373 hash_insert (arm_psr_hsh
, psrs
[i
].template, (PTR
) (psrs
+ i
));
11375 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
11376 build_reg_hsh (all_reg_maps
+ i
);
11378 set_constant_flonums ();
11380 /* Set the cpu variant based on the command-line options. We prefer
11381 -mcpu= over -march= if both are set (as for GCC); and we prefer
11382 -mfpu= over any other way of setting the floating point unit.
11383 Use of legacy options with new options are faulted. */
11384 if (legacy_cpu
!= -1)
11386 if (mcpu_cpu_opt
!= -1 || march_cpu_opt
!= -1)
11387 as_bad (_("use of old and new-style options to set CPU type"));
11389 mcpu_cpu_opt
= legacy_cpu
;
11391 else if (mcpu_cpu_opt
== -1)
11392 mcpu_cpu_opt
= march_cpu_opt
;
11394 if (legacy_fpu
!= -1)
11396 if (mfpu_opt
!= -1)
11397 as_bad (_("use of old and new-style options to set FPU type"));
11399 mfpu_opt
= legacy_fpu
;
11401 else if (mfpu_opt
== -1)
11403 #if !(defined (TE_LINUX) || defined (TE_NetBSD) || defined (TE_VXWORKS))
11404 /* Some environments specify a default FPU. If they don't, infer it
11405 from the processor. */
11406 if (mcpu_fpu_opt
!= -1)
11407 mfpu_opt
= mcpu_fpu_opt
;
11409 mfpu_opt
= march_fpu_opt
;
11411 mfpu_opt
= FPU_DEFAULT
;
11415 if (mfpu_opt
== -1)
11417 if (mcpu_cpu_opt
== -1)
11418 mfpu_opt
= FPU_DEFAULT
;
11419 else if (mcpu_cpu_opt
& ARM_EXT_V5
)
11420 mfpu_opt
= FPU_ARCH_VFP_V2
;
11422 mfpu_opt
= FPU_ARCH_FPA
;
11425 if (mcpu_cpu_opt
== -1)
11426 mcpu_cpu_opt
= CPU_DEFAULT
;
11428 cpu_variant
= mcpu_cpu_opt
| mfpu_opt
;
11430 #if defined OBJ_COFF || defined OBJ_ELF
11432 unsigned int flags
= 0;
11434 #if defined OBJ_ELF
11435 flags
= meabi_flags
;
11437 switch (meabi_flags
)
11439 case EF_ARM_EABI_UNKNOWN
:
11441 /* Set the flags in the private structure. */
11442 if (uses_apcs_26
) flags
|= F_APCS26
;
11443 if (support_interwork
) flags
|= F_INTERWORK
;
11444 if (uses_apcs_float
) flags
|= F_APCS_FLOAT
;
11445 if (pic_code
) flags
|= F_PIC
;
11446 if ((cpu_variant
& FPU_ANY
) == FPU_NONE
11447 || (cpu_variant
& FPU_ANY
) == FPU_ARCH_VFP
) /* VFP layout only. */
11448 flags
|= F_SOFT_FLOAT
;
11450 switch (mfloat_abi_opt
)
11452 case ARM_FLOAT_ABI_SOFT
:
11453 case ARM_FLOAT_ABI_SOFTFP
:
11454 flags
|= F_SOFT_FLOAT
;
11457 case ARM_FLOAT_ABI_HARD
:
11458 if (flags
& F_SOFT_FLOAT
)
11459 as_bad (_("hard-float conflicts with specified fpu"));
11463 /* Using VFP conventions (even if soft-float). */
11464 if (cpu_variant
& FPU_VFP_EXT_NONE
)
11465 flags
|= F_VFP_FLOAT
;
11467 #if defined OBJ_ELF
11468 if (cpu_variant
& FPU_ARCH_MAVERICK
)
11469 flags
|= EF_ARM_MAVERICK_FLOAT
;
11472 case EF_ARM_EABI_VER4
:
11473 /* No additional flags to set. */
11480 bfd_set_private_flags (stdoutput
, flags
);
11482 /* We have run out flags in the COFF header to encode the
11483 status of ATPCS support, so instead we create a dummy,
11484 empty, debug section called .arm.atpcs. */
11489 sec
= bfd_make_section (stdoutput
, ".arm.atpcs");
11493 bfd_set_section_flags
11494 (stdoutput
, sec
, SEC_READONLY
| SEC_DEBUGGING
/* | SEC_HAS_CONTENTS */);
11495 bfd_set_section_size (stdoutput
, sec
, 0);
11496 bfd_set_section_contents (stdoutput
, sec
, NULL
, 0, 0);
11502 /* Record the CPU type as well. */
11503 switch (cpu_variant
& ARM_CPU_MASK
)
11506 mach
= bfd_mach_arm_2
;
11509 case ARM_3
: /* Also ARM_250. */
11510 mach
= bfd_mach_arm_2a
;
11513 case ARM_6
: /* Also ARM_7. */
11514 mach
= bfd_mach_arm_3
;
11518 mach
= bfd_mach_arm_unknown
;
11522 /* Catch special cases. */
11523 if (cpu_variant
& ARM_CEXT_IWMMXT
)
11524 mach
= bfd_mach_arm_iWMMXt
;
11525 else if (cpu_variant
& ARM_CEXT_XSCALE
)
11526 mach
= bfd_mach_arm_XScale
;
11527 else if (cpu_variant
& ARM_CEXT_MAVERICK
)
11528 mach
= bfd_mach_arm_ep9312
;
11529 else if (cpu_variant
& ARM_EXT_V5E
)
11530 mach
= bfd_mach_arm_5TE
;
11531 else if (cpu_variant
& ARM_EXT_V5
)
11533 if (cpu_variant
& ARM_EXT_V4T
)
11534 mach
= bfd_mach_arm_5T
;
11536 mach
= bfd_mach_arm_5
;
11538 else if (cpu_variant
& ARM_EXT_V4
)
11540 if (cpu_variant
& ARM_EXT_V4T
)
11541 mach
= bfd_mach_arm_4T
;
11543 mach
= bfd_mach_arm_4
;
11545 else if (cpu_variant
& ARM_EXT_V3M
)
11546 mach
= bfd_mach_arm_3M
;
11548 bfd_set_arch_mach (stdoutput
, TARGET_ARCH
, mach
);
11551 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11552 for use in the a.out file, and stores them in the array pointed to by buf.
11553 This knows about the endian-ness of the target machine and does
11554 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11555 2 (short) and 4 (long) Floating numbers are put out as a series of
11556 LITTLENUMS (shorts, here at least). */
11559 md_number_to_chars (char * buf
, valueT val
, int n
)
11561 if (target_big_endian
)
11562 number_to_chars_bigendian (buf
, val
, n
);
11564 number_to_chars_littleendian (buf
, val
, n
);
11568 md_chars_to_number (char * buf
, int n
)
11571 unsigned char * where
= (unsigned char *) buf
;
11573 if (target_big_endian
)
11578 result
|= (*where
++ & 255);
11586 result
|= (where
[n
] & 255);
11593 /* Turn a string in input_line_pointer into a floating point constant
11594 of type TYPE, and store the appropriate bytes in *LITP. The number
11595 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11596 returned, or NULL on OK.
11598 Note that fp constants aren't represent in the normal way on the ARM.
11599 In big endian mode, things are as expected. However, in little endian
11600 mode fp constants are big-endian word-wise, and little-endian byte-wise
11601 within the words. For example, (double) 1.1 in big endian mode is
11602 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11603 the byte sequence 99 99 f1 3f 9a 99 99 99.
11605 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11608 md_atof (int type
, char * litP
, int * sizeP
)
11611 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
11643 return _("bad call to MD_ATOF()");
11646 t
= atof_ieee (input_line_pointer
, type
, words
);
11648 input_line_pointer
= t
;
11651 if (target_big_endian
)
11653 for (i
= 0; i
< prec
; i
++)
11655 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
11661 if (cpu_variant
& FPU_ARCH_VFP
)
11662 for (i
= prec
- 1; i
>= 0; i
--)
11664 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
11668 /* For a 4 byte float the order of elements in `words' is 1 0.
11669 For an 8 byte float the order is 1 0 3 2. */
11670 for (i
= 0; i
< prec
; i
+= 2)
11672 md_number_to_chars (litP
, (valueT
) words
[i
+ 1], 2);
11673 md_number_to_chars (litP
+ 2, (valueT
) words
[i
], 2);
11681 /* The knowledge of the PC's pipeline offset is built into the insns
11685 md_pcrel_from (fixS
* fixP
)
11688 && S_GET_SEGMENT (fixP
->fx_addsy
) == undefined_section
11689 && fixP
->fx_subsy
== NULL
)
11692 if (fixP
->fx_pcrel
&& (fixP
->fx_r_type
== BFD_RELOC_ARM_THUMB_ADD
))
11694 /* PC relative addressing on the Thumb is slightly odd
11695 as the bottom two bits of the PC are forced to zero
11696 for the calculation. */
11697 return (fixP
->fx_where
+ fixP
->fx_frag
->fr_address
) & ~3;
11701 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
11702 so we un-adjust here to compensate for the accommodation. */
11703 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
+ 8;
11705 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
11709 /* Round up a section size to the appropriate boundary. */
11712 md_section_align (segT segment ATTRIBUTE_UNUSED
,
11718 /* Round all sects to multiple of 4. */
11719 return (size
+ 3) & ~3;
11723 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
11724 Otherwise we have no need to default values of symbols. */
11727 md_undefined_symbol (char * name ATTRIBUTE_UNUSED
)
11730 if (name
[0] == '_' && name
[1] == 'G'
11731 && streq (name
, GLOBAL_OFFSET_TABLE_NAME
))
11735 if (symbol_find (name
))
11736 as_bad ("GOT already in the symbol table");
11738 GOT_symbol
= symbol_new (name
, undefined_section
,
11739 (valueT
) 0, & zero_address_frag
);
11750 md_apply_fix3 (fixS
* fixP
,
11754 offsetT value
= * valP
;
11756 unsigned int newimm
;
11757 unsigned long temp
;
11759 char * buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
11760 arm_fix_data
* arm_data
= (arm_fix_data
*) fixP
->tc_fix_data
;
11762 assert (fixP
->fx_r_type
<= BFD_RELOC_UNUSED
);
11764 /* Note whether this will delete the relocation. */
11765 if (fixP
->fx_addsy
== 0 && !fixP
->fx_pcrel
)
11768 /* If this symbol is in a different section then we need to leave it for
11769 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
11770 so we have to undo it's effects here. */
11771 if (fixP
->fx_pcrel
)
11773 if (fixP
->fx_addsy
!= NULL
11774 && S_IS_DEFINED (fixP
->fx_addsy
)
11775 && S_GET_SEGMENT (fixP
->fx_addsy
) != seg
)
11776 value
+= md_pcrel_from (fixP
);
11779 /* Remember value for emit_reloc. */
11780 fixP
->fx_addnumber
= value
;
11782 switch (fixP
->fx_r_type
)
11784 case BFD_RELOC_NONE
:
11785 /* This will need to go in the object file. */
11789 case BFD_RELOC_ARM_IMMEDIATE
:
11790 /* We claim that this fixup has been processed here,
11791 even if in fact we generate an error because we do
11792 not have a reloc for it, so tc_gen_reloc will reject it. */
11796 && ! S_IS_DEFINED (fixP
->fx_addsy
))
11798 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11799 _("undefined symbol %s used as an immediate value"),
11800 S_GET_NAME (fixP
->fx_addsy
));
11804 newimm
= validate_immediate (value
);
11805 temp
= md_chars_to_number (buf
, INSN_SIZE
);
11807 /* If the instruction will fail, see if we can fix things up by
11808 changing the opcode. */
11809 if (newimm
== (unsigned int) FAIL
11810 && (newimm
= negate_data_op (&temp
, value
)) == (unsigned int) FAIL
)
11812 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11813 _("invalid constant (%lx) after fixup"),
11814 (unsigned long) value
);
11818 newimm
|= (temp
& 0xfffff000);
11819 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
11822 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
11824 unsigned int highpart
= 0;
11825 unsigned int newinsn
= 0xe1a00000; /* nop. */
11827 newimm
= validate_immediate (value
);
11828 temp
= md_chars_to_number (buf
, INSN_SIZE
);
11830 /* If the instruction will fail, see if we can fix things up by
11831 changing the opcode. */
11832 if (newimm
== (unsigned int) FAIL
11833 && (newimm
= negate_data_op (& temp
, value
)) == (unsigned int) FAIL
)
11835 /* No ? OK - try using two ADD instructions to generate
11837 newimm
= validate_immediate_twopart (value
, & highpart
);
11839 /* Yes - then make sure that the second instruction is
11841 if (newimm
!= (unsigned int) FAIL
)
11843 /* Still No ? Try using a negated value. */
11844 else if ((newimm
= validate_immediate_twopart (- value
, & highpart
)) != (unsigned int) FAIL
)
11845 temp
= newinsn
= (temp
& OPCODE_MASK
) | OPCODE_SUB
<< DATA_OP_SHIFT
;
11846 /* Otherwise - give up. */
11849 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11850 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
11855 /* Replace the first operand in the 2nd instruction (which
11856 is the PC) with the destination register. We have
11857 already added in the PC in the first instruction and we
11858 do not want to do it again. */
11859 newinsn
&= ~ 0xf0000;
11860 newinsn
|= ((newinsn
& 0x0f000) << 4);
11863 newimm
|= (temp
& 0xfffff000);
11864 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
11866 highpart
|= (newinsn
& 0xfffff000);
11867 md_number_to_chars (buf
+ INSN_SIZE
, (valueT
) highpart
, INSN_SIZE
);
11871 case BFD_RELOC_ARM_OFFSET_IMM
:
11877 if (validate_offset_imm (value
, 0) == FAIL
)
11879 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11880 _("bad immediate value for offset (%ld)"),
11885 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11886 newval
&= 0xff7ff000;
11887 newval
|= value
| (sign
? INDEX_UP
: 0);
11888 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11891 case BFD_RELOC_ARM_OFFSET_IMM8
:
11892 case BFD_RELOC_ARM_HWLITERAL
:
11898 if (validate_offset_imm (value
, 1) == FAIL
)
11900 if (fixP
->fx_r_type
== BFD_RELOC_ARM_HWLITERAL
)
11901 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11902 _("invalid literal constant: pool needs to be closer"));
11904 as_bad (_("bad immediate value for half-word offset (%ld)"),
11909 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11910 newval
&= 0xff7ff0f0;
11911 newval
|= ((value
>> 4) << 8) | (value
& 0xf) | (sign
? INDEX_UP
: 0);
11912 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11915 case BFD_RELOC_ARM_LITERAL
:
11921 if (validate_offset_imm (value
, 0) == FAIL
)
11923 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11924 _("invalid literal constant: pool needs to be closer"));
11928 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11929 newval
&= 0xff7ff000;
11930 newval
|= value
| (sign
? INDEX_UP
: 0);
11931 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11934 case BFD_RELOC_ARM_SHIFT_IMM
:
11935 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11936 if (((unsigned long) value
) > 32
11938 && (((newval
& 0x60) == 0) || (newval
& 0x60) == 0x60)))
11940 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11941 _("shift expression is too large"));
11946 /* Shifts of zero must be done as lsl. */
11948 else if (value
== 32)
11950 newval
&= 0xfffff07f;
11951 newval
|= (value
& 0x1f) << 7;
11952 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11955 case BFD_RELOC_ARM_SMI
:
11956 if (((unsigned long) value
) > 0xffff)
11957 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11958 _("invalid smi expression"));
11959 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xfff000f0;
11960 newval
|= (value
& 0xf) | ((value
& 0xfff0) << 4);
11961 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11964 case BFD_RELOC_ARM_SWI
:
11965 if (arm_data
->thumb_mode
)
11967 if (((unsigned long) value
) > 0xff)
11968 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11969 _("invalid swi expression"));
11970 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xff00;
11972 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11976 if (((unsigned long) value
) > 0x00ffffff)
11977 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11978 _("invalid swi expression"));
11979 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff000000;
11981 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11985 case BFD_RELOC_ARM_MULTI
:
11986 if (((unsigned long) value
) > 0xffff)
11987 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11988 _("invalid expression in load/store multiple"));
11989 newval
= value
| md_chars_to_number (buf
, INSN_SIZE
);
11990 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11993 case BFD_RELOC_ARM_PCREL_BRANCH
:
11994 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11996 /* Sign-extend a 24-bit number. */
11997 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
12000 value
= fixP
->fx_offset
;
12003 /* We are going to store value (shifted right by two) in the
12004 instruction, in a 24 bit, signed field. Thus we need to check
12005 that none of the top 8 bits of the shifted value (top 7 bits of
12006 the unshifted, unsigned value) are set, or that they are all set. */
12007 if ((value
& ~ ((offsetT
) 0x1ffffff)) != 0
12008 && ((value
& ~ ((offsetT
) 0x1ffffff)) != ~ ((offsetT
) 0x1ffffff)))
12011 /* Normally we would be stuck at this point, since we cannot store
12012 the absolute address that is the destination of the branch in the
12013 24 bits of the branch instruction. If however, we happen to know
12014 that the destination of the branch is in the same section as the
12015 branch instruction itself, then we can compute the relocation for
12016 ourselves and not have to bother the linker with it.
12018 FIXME: The test for OBJ_ELF is only here because I have not
12019 worked out how to do this for OBJ_COFF. */
12020 if (fixP
->fx_addsy
!= NULL
12021 && S_IS_DEFINED (fixP
->fx_addsy
)
12022 && S_GET_SEGMENT (fixP
->fx_addsy
) == seg
)
12024 /* Get pc relative value to go into the branch. */
12027 /* Permit a backward branch provided that enough bits
12028 are set. Allow a forwards branch, provided that
12029 enough bits are clear. */
12030 if ( (value
& ~ ((offsetT
) 0x1ffffff)) == ~ ((offsetT
) 0x1ffffff)
12031 || (value
& ~ ((offsetT
) 0x1ffffff)) == 0)
12035 if (! fixP
->fx_done
)
12037 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12038 _("GAS can't handle same-section branch dest >= 0x04000000"));
12042 value
+= SEXT24 (newval
);
12044 if ( (value
& ~ ((offsetT
) 0xffffff)) != 0
12045 && ((value
& ~ ((offsetT
) 0xffffff)) != ~ ((offsetT
) 0xffffff)))
12046 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12047 _("out of range branch"));
12049 if (seg
->use_rela_p
&& !fixP
->fx_done
)
12051 /* Must unshift the value before storing it in the addend. */
12054 fixP
->fx_offset
= value
;
12056 fixP
->fx_addnumber
= value
;
12057 newval
= newval
& 0xff000000;
12060 newval
= (value
& 0x00ffffff) | (newval
& 0xff000000);
12061 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12064 case BFD_RELOC_ARM_PCREL_BLX
:
12067 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12070 value
= fixP
->fx_offset
;
12072 hbit
= (value
>> 1) & 1;
12073 value
= (value
>> 2) & 0x00ffffff;
12074 value
= (value
+ (newval
& 0x00ffffff)) & 0x00ffffff;
12076 if (seg
->use_rela_p
&& !fixP
->fx_done
)
12078 /* Must sign-extend and unshift the value before storing
12079 it in the addend. */
12080 value
= SEXT24 (value
);
12081 value
= (value
<< 2) | hbit
;
12083 fixP
->fx_offset
= value
;
12085 fixP
->fx_addnumber
= value
;
12086 newval
= newval
& 0xfe000000;
12089 newval
= value
| (newval
& 0xfe000000) | (hbit
<< 24);
12090 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12094 case BFD_RELOC_THUMB_PCREL_BRANCH9
: /* Conditional branch. */
12095 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12097 addressT diff
= (newval
& 0xff) << 1;
12102 if ((value
& ~0xff) && ((value
& ~0xff) != ~0xff))
12103 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12104 _("branch out of range"));
12105 if (seg
->use_rela_p
&& !fixP
->fx_done
)
12108 fixP
->fx_offset
= value
;
12110 fixP
->fx_addnumber
= value
;
12111 newval
= newval
& 0xff00;
12114 newval
= (newval
& 0xff00) | ((value
& 0x1ff) >> 1);
12116 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12119 case BFD_RELOC_THUMB_PCREL_BRANCH12
: /* Unconditional branch. */
12120 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12122 addressT diff
= (newval
& 0x7ff) << 1;
12127 if ((value
& ~0x7ff) && ((value
& ~0x7ff) != ~0x7ff))
12128 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12129 _("branch out of range"));
12130 if (seg
->use_rela_p
&& !fixP
->fx_done
)
12133 fixP
->fx_offset
= value
;
12135 fixP
->fx_addnumber
= value
;
12136 newval
= newval
& 0xf800;
12139 newval
= (newval
& 0xf800) | ((value
& 0xfff) >> 1);
12141 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12144 case BFD_RELOC_THUMB_PCREL_BLX
:
12145 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
12150 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12151 newval2
= md_chars_to_number (buf
+ THUMB_SIZE
, THUMB_SIZE
);
12152 diff
= ((newval
& 0x7ff) << 12) | ((newval2
& 0x7ff) << 1);
12153 if (diff
& 0x400000)
12156 value
= fixP
->fx_offset
;
12160 if ((value
& ~0x3fffff) && ((value
& ~0x3fffff) != ~0x3fffff))
12161 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12162 _("branch with link out of range"));
12164 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
)
12165 /* For a BLX instruction, make sure that the relocation is rounded up
12166 to a word boundary. This follows the semantics of the instruction
12167 which specifies that bit 1 of the target address will come from bit
12168 1 of the base address. */
12169 value
= (value
+ 1) & ~ 1;
12171 if (seg
->use_rela_p
&& !fixP
->fx_done
)
12174 fixP
->fx_offset
= value
;
12176 fixP
->fx_addnumber
= value
;
12177 newval
= newval
& 0xf800;
12178 newval2
= newval2
& 0xf800;
12182 newval
= (newval
& 0xf800) | ((value
& 0x7fffff) >> 12);
12183 newval2
= (newval2
& 0xf800) | ((value
& 0xfff) >> 1);
12185 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12186 md_number_to_chars (buf
+ THUMB_SIZE
, newval2
, THUMB_SIZE
);
12191 if (seg
->use_rela_p
&& !fixP
->fx_done
)
12193 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
12194 md_number_to_chars (buf
, value
, 1);
12198 value
= fixP
->fx_offset
;
12199 md_number_to_chars (buf
, value
, 1);
12205 if (seg
->use_rela_p
&& !fixP
->fx_done
)
12207 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
12208 md_number_to_chars (buf
, value
, 2);
12212 value
= fixP
->fx_offset
;
12213 md_number_to_chars (buf
, value
, 2);
12219 case BFD_RELOC_ARM_GOT32
:
12220 case BFD_RELOC_ARM_GOTOFF
:
12221 case BFD_RELOC_ARM_TARGET2
:
12222 if (seg
->use_rela_p
&& !fixP
->fx_done
)
12224 md_number_to_chars (buf
, 0, 4);
12228 case BFD_RELOC_RVA
:
12230 case BFD_RELOC_ARM_TARGET1
:
12231 case BFD_RELOC_ARM_ROSEGREL32
:
12232 case BFD_RELOC_ARM_SBREL32
:
12233 case BFD_RELOC_32_PCREL
:
12234 if (seg
->use_rela_p
&& !fixP
->fx_done
)
12236 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
12237 md_number_to_chars (buf
, value
, 4);
12241 value
= fixP
->fx_offset
;
12242 md_number_to_chars (buf
, value
, 4);
12248 case BFD_RELOC_ARM_PREL31
:
12249 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
12251 newval
= md_chars_to_number (buf
, 4) & 0x80000000;
12252 if ((value
^ (value
>> 1)) & 0x40000000)
12254 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12255 _("rel31 relocation overflow"));
12257 newval
|= value
& 0x7fffffff;
12258 md_number_to_chars (buf
, newval
, 4);
12262 case BFD_RELOC_ARM_PLT32
:
12263 /* It appears the instruction is fully prepared at this point. */
12267 case BFD_RELOC_ARM_CP_OFF_IMM
:
12269 if (value
< -1023 || value
> 1023 || (value
& 3))
12270 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12271 _("illegal value for co-processor offset"));
12274 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
12275 newval
|= (value
>> 2) | (sign
? INDEX_UP
: 0);
12276 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12279 case BFD_RELOC_ARM_CP_OFF_IMM_S2
:
12281 if (value
< -255 || value
> 255)
12282 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12283 _("Illegal value for co-processor offset"));
12286 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
12287 newval
|= value
| (sign
? INDEX_UP
: 0);
12288 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12291 case BFD_RELOC_ARM_THUMB_OFFSET
:
12292 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12293 /* Exactly what ranges, and where the offset is inserted depends
12294 on the type of instruction, we can establish this from the
12296 switch (newval
>> 12)
12298 case 4: /* PC load. */
12299 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
12300 forced to zero for these loads, so we will need to round
12301 up the offset if the instruction address is not word
12302 aligned (since the final address produced must be, and
12303 we can only describe word-aligned immediate offsets). */
12305 if ((fixP
->fx_frag
->fr_address
+ fixP
->fx_where
+ value
) & 3)
12306 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12307 _("invalid offset, target not word aligned (0x%08X)"),
12308 (unsigned int) (fixP
->fx_frag
->fr_address
12309 + fixP
->fx_where
+ value
));
12311 if ((value
+ 2) & ~0x3fe)
12312 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12313 _("invalid offset, value too big (0x%08lX)"),
12316 /* Round up, since pc will be rounded down. */
12317 newval
|= (value
+ 2) >> 2;
12320 case 9: /* SP load/store. */
12321 if (value
& ~0x3fc)
12322 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12323 _("invalid offset, value too big (0x%08lX)"),
12325 newval
|= value
>> 2;
12328 case 6: /* Word load/store. */
12330 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12331 _("invalid offset, value too big (0x%08lX)"),
12333 newval
|= value
<< 4; /* 6 - 2. */
12336 case 7: /* Byte load/store. */
12338 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12339 _("invalid offset, value too big (0x%08lX)"),
12341 newval
|= value
<< 6;
12344 case 8: /* Halfword load/store. */
12346 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12347 _("invalid offset, value too big (0x%08lX)"),
12349 newval
|= value
<< 5; /* 6 - 1. */
12353 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12354 "Unable to process relocation for thumb opcode: %lx",
12355 (unsigned long) newval
);
12358 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12361 case BFD_RELOC_ARM_THUMB_ADD
:
12362 /* This is a complicated relocation, since we use it for all of
12363 the following immediate relocations:
12367 9bit ADD/SUB SP word-aligned
12368 10bit ADD PC/SP word-aligned
12370 The type of instruction being processed is encoded in the
12377 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12379 int rd
= (newval
>> 4) & 0xf;
12380 int rs
= newval
& 0xf;
12381 int subtract
= newval
& 0x8000;
12385 if (value
& ~0x1fc)
12386 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12387 _("invalid immediate for stack address calculation"));
12388 newval
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
12389 newval
|= value
>> 2;
12391 else if (rs
== REG_PC
|| rs
== REG_SP
)
12395 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12396 _("invalid immediate for address calculation (value = 0x%08lX)"),
12397 (unsigned long) value
);
12398 newval
= (rs
== REG_PC
? T_OPCODE_ADD_PC
: T_OPCODE_ADD_SP
);
12400 newval
|= value
>> 2;
12405 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12406 _("invalid 8bit immediate"));
12407 newval
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
12408 newval
|= (rd
<< 8) | value
;
12413 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12414 _("invalid 3bit immediate"));
12415 newval
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
12416 newval
|= rd
| (rs
<< 3) | (value
<< 6);
12419 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12422 case BFD_RELOC_ARM_THUMB_IMM
:
12423 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12424 switch (newval
>> 11)
12426 case 0x04: /* 8bit immediate MOV. */
12427 case 0x05: /* 8bit immediate CMP. */
12428 if (value
< 0 || value
> 255)
12429 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12430 _("invalid immediate: %ld is too large"),
12438 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12441 case BFD_RELOC_ARM_THUMB_SHIFT
:
12442 /* 5bit shift value (0..31). */
12443 if (value
< 0 || value
> 31)
12444 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12445 _("illegal Thumb shift value: %ld"), (long) value
);
12446 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xf03f;
12447 newval
|= value
<< 6;
12448 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12451 case BFD_RELOC_VTABLE_INHERIT
:
12452 case BFD_RELOC_VTABLE_ENTRY
:
12456 case BFD_RELOC_UNUSED
:
12458 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12459 _("bad relocation fixup type (%d)"), fixP
->fx_r_type
);
12463 /* Translate internal representation of relocation info to BFD target
12467 tc_gen_reloc (asection
* section ATTRIBUTE_UNUSED
,
12471 bfd_reloc_code_real_type code
;
12473 reloc
= xmalloc (sizeof (arelent
));
12475 reloc
->sym_ptr_ptr
= xmalloc (sizeof (asymbol
*));
12476 *reloc
->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
12477 reloc
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
12479 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12481 if (fixp
->fx_pcrel
== 0)
12482 reloc
->addend
= fixp
->fx_offset
;
12484 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
12485 #else /* OBJ_ELF */
12486 reloc
->addend
= fixp
->fx_offset
;
12489 switch (fixp
->fx_r_type
)
12492 if (fixp
->fx_pcrel
)
12494 code
= BFD_RELOC_8_PCREL
;
12499 if (fixp
->fx_pcrel
)
12501 code
= BFD_RELOC_16_PCREL
;
12506 if (fixp
->fx_pcrel
)
12508 code
= BFD_RELOC_32_PCREL
;
12512 case BFD_RELOC_NONE
:
12513 case BFD_RELOC_ARM_PCREL_BRANCH
:
12514 case BFD_RELOC_ARM_PCREL_BLX
:
12515 case BFD_RELOC_RVA
:
12516 case BFD_RELOC_THUMB_PCREL_BRANCH9
:
12517 case BFD_RELOC_THUMB_PCREL_BRANCH12
:
12518 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
12519 case BFD_RELOC_THUMB_PCREL_BLX
:
12520 case BFD_RELOC_VTABLE_ENTRY
:
12521 case BFD_RELOC_VTABLE_INHERIT
:
12522 code
= fixp
->fx_r_type
;
12525 case BFD_RELOC_ARM_LITERAL
:
12526 case BFD_RELOC_ARM_HWLITERAL
:
12527 /* If this is called then the a literal has
12528 been referenced across a section boundary. */
12529 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12530 _("literal referenced across section boundary"));
12534 case BFD_RELOC_ARM_GOT32
:
12535 case BFD_RELOC_ARM_GOTOFF
:
12536 case BFD_RELOC_ARM_PLT32
:
12537 case BFD_RELOC_ARM_TARGET1
:
12538 case BFD_RELOC_ARM_ROSEGREL32
:
12539 case BFD_RELOC_ARM_SBREL32
:
12540 case BFD_RELOC_ARM_PREL31
:
12541 case BFD_RELOC_ARM_TARGET2
:
12542 code
= fixp
->fx_r_type
;
12546 case BFD_RELOC_ARM_IMMEDIATE
:
12547 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12548 _("internal relocation (type: IMMEDIATE) not fixed up"));
12551 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
12552 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12553 _("ADRL used for a symbol not defined in the same file"));
12556 case BFD_RELOC_ARM_OFFSET_IMM
:
12557 if (fixp
->fx_addsy
!= NULL
12558 && !S_IS_DEFINED (fixp
->fx_addsy
)
12559 && S_IS_LOCAL (fixp
->fx_addsy
))
12561 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12562 _("undefined local label `%s'"),
12563 S_GET_NAME (fixp
->fx_addsy
));
12567 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12568 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
12575 switch (fixp
->fx_r_type
)
12577 case BFD_RELOC_NONE
: type
= "NONE"; break;
12578 case BFD_RELOC_ARM_OFFSET_IMM8
: type
= "OFFSET_IMM8"; break;
12579 case BFD_RELOC_ARM_SHIFT_IMM
: type
= "SHIFT_IMM"; break;
12580 case BFD_RELOC_ARM_SMI
: type
= "SMI"; break;
12581 case BFD_RELOC_ARM_SWI
: type
= "SWI"; break;
12582 case BFD_RELOC_ARM_MULTI
: type
= "MULTI"; break;
12583 case BFD_RELOC_ARM_CP_OFF_IMM
: type
= "CP_OFF_IMM"; break;
12584 case BFD_RELOC_ARM_THUMB_ADD
: type
= "THUMB_ADD"; break;
12585 case BFD_RELOC_ARM_THUMB_SHIFT
: type
= "THUMB_SHIFT"; break;
12586 case BFD_RELOC_ARM_THUMB_IMM
: type
= "THUMB_IMM"; break;
12587 case BFD_RELOC_ARM_THUMB_OFFSET
: type
= "THUMB_OFFSET"; break;
12588 default: type
= _("<unknown>"); break;
12590 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12591 _("cannot represent %s relocation in this object file format"),
12598 if ((code
== BFD_RELOC_32_PCREL
|| code
== BFD_RELOC_32
)
12600 && fixp
->fx_addsy
== GOT_symbol
)
12602 code
= BFD_RELOC_ARM_GOTPC
;
12603 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
12607 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, code
);
12609 if (reloc
->howto
== NULL
)
12611 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12612 _("cannot represent %s relocation in this object file format"),
12613 bfd_get_reloc_code_name (code
));
12617 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12618 vtable entry to be used in the relocation's section offset. */
12619 if (fixp
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
12620 reloc
->address
= fixp
->fx_offset
;
12626 md_estimate_size_before_relax (fragS
* fragP ATTRIBUTE_UNUSED
,
12627 segT segtype ATTRIBUTE_UNUSED
)
12629 as_fatal (_("md_estimate_size_before_relax\n"));
12633 /* We need to be able to fix up arbitrary expressions in some statements.
12634 This is so that we can handle symbols that are an arbitrary distance from
12635 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
12636 which returns part of an address in a form which will be valid for
12637 a data instruction. We do this by pushing the expression into a symbol
12638 in the expr_section, and creating a fix for that. */
12641 fix_new_arm (fragS
* frag
,
12649 arm_fix_data
* arm_data
;
12657 new_fix
= fix_new_exp (frag
, where
, size
, exp
, pc_rel
, reloc
);
12661 new_fix
= fix_new (frag
, where
, size
, make_expr_symbol (exp
), 0,
12666 /* Mark whether the fix is to a THUMB instruction, or an ARM
12668 arm_data
= obstack_alloc (& notes
, sizeof (arm_fix_data
));
12669 new_fix
->tc_fix_data
= (PTR
) arm_data
;
12670 arm_data
->thumb_mode
= thumb_mode
;
12674 output_inst (const char * str
)
12680 as_bad ("%s -- `%s'", inst
.error
, str
);
12684 to
= frag_more (inst
.size
);
12686 if (thumb_mode
&& (inst
.size
> THUMB_SIZE
))
12688 assert (inst
.size
== (2 * THUMB_SIZE
));
12689 md_number_to_chars (to
, inst
.instruction
>> 16, THUMB_SIZE
);
12690 md_number_to_chars (to
+ THUMB_SIZE
, inst
.instruction
, THUMB_SIZE
);
12692 else if (inst
.size
> INSN_SIZE
)
12694 assert (inst
.size
== (2 * INSN_SIZE
));
12695 md_number_to_chars (to
, inst
.instruction
, INSN_SIZE
);
12696 md_number_to_chars (to
+ INSN_SIZE
, inst
.instruction
, INSN_SIZE
);
12699 md_number_to_chars (to
, inst
.instruction
, inst
.size
);
12701 if (inst
.reloc
.type
!= BFD_RELOC_UNUSED
)
12702 fix_new_arm (frag_now
, to
- frag_now
->fr_literal
,
12703 inst
.size
, & inst
.reloc
.exp
, inst
.reloc
.pc_rel
,
12707 dwarf2_emit_insn (inst
.size
);
12712 md_assemble (char * str
)
12718 /* Align the previous label if needed. */
12719 if (last_label_seen
!= NULL
)
12721 symbol_set_frag (last_label_seen
, frag_now
);
12722 S_SET_VALUE (last_label_seen
, (valueT
) frag_now_fix ());
12723 S_SET_SEGMENT (last_label_seen
, now_seg
);
12726 memset (&inst
, '\0', sizeof (inst
));
12727 inst
.reloc
.type
= BFD_RELOC_UNUSED
;
12729 skip_whitespace (str
);
12731 /* Scan up to the end of the op-code, which must end in white space or
12733 for (start
= p
= str
; *p
!= '\0'; p
++)
12739 as_bad (_("no operator -- statement `%s'\n"), str
);
12745 const struct thumb_opcode
* opcode
;
12749 opcode
= (const struct thumb_opcode
*) hash_find (arm_tops_hsh
, str
);
12754 /* Check that this instruction is supported for this CPU. */
12755 if (thumb_mode
== 1 && (opcode
->variant
& cpu_variant
) == 0)
12757 as_bad (_("selected processor does not support `%s'"), str
);
12761 mapping_state (MAP_THUMB
);
12762 inst
.instruction
= opcode
->value
;
12763 inst
.size
= opcode
->size
;
12771 const struct asm_opcode
* opcode
;
12775 opcode
= (const struct asm_opcode
*) hash_find (arm_ops_hsh
, str
);
12780 /* Check that this instruction is supported for this CPU. */
12781 if ((opcode
->variant
& cpu_variant
) == 0)
12783 as_bad (_("selected processor does not support `%s'"), str
);
12787 mapping_state (MAP_ARM
);
12788 inst
.instruction
= opcode
->value
;
12789 inst
.size
= INSN_SIZE
;
12796 /* It wasn't an instruction, but it might be a register alias of the form
12798 if (create_register_alias (str
, p
))
12801 as_bad (_("bad instruction `%s'"), start
);
12805 Invocation line includes a switch not recognized by the base assembler.
12806 See if it's a processor-specific option.
12808 This routine is somewhat complicated by the need for backwards
12809 compatibility (since older releases of gcc can't be changed).
12810 The new options try to make the interface as compatible as
12813 New options (supported) are:
12815 -mcpu=<cpu name> Assemble for selected processor
12816 -march=<architecture name> Assemble for selected architecture
12817 -mfpu=<fpu architecture> Assemble for selected FPU.
12818 -EB/-mbig-endian Big-endian
12819 -EL/-mlittle-endian Little-endian
12820 -k Generate PIC code
12821 -mthumb Start in Thumb mode
12822 -mthumb-interwork Code supports ARM/Thumb interworking
12824 For now we will also provide support for:
12826 -mapcs-32 32-bit Program counter
12827 -mapcs-26 26-bit Program counter
12828 -macps-float Floats passed in FP registers
12829 -mapcs-reentrant Reentrant code
12831 (sometime these will probably be replaced with -mapcs=<list of options>
12832 and -matpcs=<list of options>)
12834 The remaining options are only supported for back-wards compatibility.
12835 Cpu variants, the arm part is optional:
12836 -m[arm]1 Currently not supported.
12837 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
12838 -m[arm]3 Arm 3 processor
12839 -m[arm]6[xx], Arm 6 processors
12840 -m[arm]7[xx][t][[d]m] Arm 7 processors
12841 -m[arm]8[10] Arm 8 processors
12842 -m[arm]9[20][tdmi] Arm 9 processors
12843 -mstrongarm[110[0]] StrongARM processors
12844 -mxscale XScale processors
12845 -m[arm]v[2345[t[e]]] Arm architectures
12846 -mall All (except the ARM1)
12848 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
12849 -mfpe-old (No float load/store multiples)
12850 -mvfpxd VFP Single precision
12852 -mno-fpu Disable all floating point instructions
12854 The following CPU names are recognized:
12855 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
12856 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
12857 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
12858 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
12859 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
12860 arm10t arm10e, arm1020t, arm1020e, arm10200e,
12861 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
12865 const char * md_shortopts
= "m:k";
12867 #ifdef ARM_BI_ENDIAN
12868 #define OPTION_EB (OPTION_MD_BASE + 0)
12869 #define OPTION_EL (OPTION_MD_BASE + 1)
12871 #if TARGET_BYTES_BIG_ENDIAN
12872 #define OPTION_EB (OPTION_MD_BASE + 0)
12874 #define OPTION_EL (OPTION_MD_BASE + 1)
12878 struct option md_longopts
[] =
12881 {"EB", no_argument
, NULL
, OPTION_EB
},
12884 {"EL", no_argument
, NULL
, OPTION_EL
},
12886 {NULL
, no_argument
, NULL
, 0}
12889 size_t md_longopts_size
= sizeof (md_longopts
);
12891 struct arm_option_table
12893 char *option
; /* Option name to match. */
12894 char *help
; /* Help information. */
12895 int *var
; /* Variable to change. */
12896 int value
; /* What to change it to. */
12897 char *deprecated
; /* If non-null, print this message. */
12900 struct arm_option_table arm_opts
[] =
12902 {"k", N_("generate PIC code"), &pic_code
, 1, NULL
},
12903 {"mthumb", N_("assemble Thumb code"), &thumb_mode
, 1, NULL
},
12904 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
12905 &support_interwork
, 1, NULL
},
12906 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26
, 0, NULL
},
12907 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26
, 1, NULL
},
12908 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float
,
12910 {"mapcs-reentrant", N_("re-entrant code"), &pic_code
, 1, NULL
},
12911 {"matpcs", N_("code is ATPCS conformant"), &atpcs
, 1, NULL
},
12912 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian
, 1, NULL
},
12913 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian
, 1,
12916 /* These are recognized by the assembler, but have no affect on code. */
12917 {"mapcs-frame", N_("use frame pointer"), NULL
, 0, NULL
},
12918 {"mapcs-stack-check", N_("use stack size checking"), NULL
, 0, NULL
},
12920 /* DON'T add any new processors to this list -- we want the whole list
12921 to go away... Add them to the processors table instead. */
12922 {"marm1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
12923 {"m1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
12924 {"marm2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
12925 {"m2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
12926 {"marm250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
12927 {"m250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
12928 {"marm3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
12929 {"m3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
12930 {"marm6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
12931 {"m6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
12932 {"marm600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
12933 {"m600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
12934 {"marm610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
12935 {"m610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
12936 {"marm620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
12937 {"m620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
12938 {"marm7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
12939 {"m7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
12940 {"marm70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
12941 {"m70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
12942 {"marm700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
12943 {"m700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
12944 {"marm700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
12945 {"m700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
12946 {"marm710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
12947 {"m710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
12948 {"marm710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
12949 {"m710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
12950 {"marm720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
12951 {"m720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
12952 {"marm7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
12953 {"m7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
12954 {"marm7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
12955 {"m7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
12956 {"marm7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
12957 {"m7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
12958 {"marm7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
12959 {"m7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
12960 {"marm7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
12961 {"m7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
12962 {"marm7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
12963 {"m7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
12964 {"marm7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
12965 {"m7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
12966 {"marm7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
12967 {"m7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
12968 {"marm7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12969 {"m7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12970 {"marm7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12971 {"m7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12972 {"marm710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
12973 {"m710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
12974 {"marm720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
12975 {"m720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
12976 {"marm740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
12977 {"m740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
12978 {"marm8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
12979 {"m8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
12980 {"marm810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
12981 {"m810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
12982 {"marm9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
12983 {"m9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
12984 {"marm9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
12985 {"m9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
12986 {"marm920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
12987 {"m920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
12988 {"marm940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
12989 {"m940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
12990 {"mstrongarm", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=strongarm")},
12991 {"mstrongarm110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
12992 N_("use -mcpu=strongarm110")},
12993 {"mstrongarm1100", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
12994 N_("use -mcpu=strongarm1100")},
12995 {"mstrongarm1110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
12996 N_("use -mcpu=strongarm1110")},
12997 {"mxscale", NULL
, &legacy_cpu
, ARM_ARCH_XSCALE
, N_("use -mcpu=xscale")},
12998 {"miwmmxt", NULL
, &legacy_cpu
, ARM_ARCH_IWMMXT
, N_("use -mcpu=iwmmxt")},
12999 {"mall", NULL
, &legacy_cpu
, ARM_ANY
, N_("use -mcpu=all")},
13001 /* Architecture variants -- don't add any more to this list either. */
13002 {"mv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
13003 {"marmv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
13004 {"mv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
13005 {"marmv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
13006 {"mv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
13007 {"marmv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
13008 {"mv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
13009 {"marmv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
13010 {"mv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
13011 {"marmv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
13012 {"mv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
13013 {"marmv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
13014 {"mv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
13015 {"marmv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
13016 {"mv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
13017 {"marmv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
13018 {"mv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
13019 {"marmv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
13021 /* Floating point variants -- don't add any more to this list either. */
13022 {"mfpe-old", NULL
, &legacy_fpu
, FPU_ARCH_FPE
, N_("use -mfpu=fpe")},
13023 {"mfpa10", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa10")},
13024 {"mfpa11", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa11")},
13025 {"mno-fpu", NULL
, &legacy_fpu
, 0,
13026 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
13028 {NULL
, NULL
, NULL
, 0, NULL
}
13031 struct arm_cpu_option_table
13035 /* For some CPUs we assume an FPU unless the user explicitly sets
13040 /* This list should, at a minimum, contain all the cpu names
13041 recognized by GCC. */
13042 static struct arm_cpu_option_table arm_cpus
[] =
13044 {"all", ARM_ANY
, FPU_ARCH_FPA
},
13045 {"arm1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
13046 {"arm2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
13047 {"arm250", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
13048 {"arm3", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
13049 {"arm6", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13050 {"arm60", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13051 {"arm600", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13052 {"arm610", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13053 {"arm620", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13054 {"arm7", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13055 {"arm7m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
13056 {"arm7d", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13057 {"arm7dm", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
13058 {"arm7di", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13059 {"arm7dmi", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
13060 {"arm70", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13061 {"arm700", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13062 {"arm700i", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13063 {"arm710", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13064 {"arm710t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13065 {"arm720", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13066 {"arm720t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13067 {"arm740t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13068 {"arm710c", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13069 {"arm7100", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13070 {"arm7500", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13071 {"arm7500fe", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13072 {"arm7t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13073 {"arm7tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13074 {"arm7tdmi-s", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13075 {"arm8", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13076 {"arm810", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13077 {"strongarm", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13078 {"strongarm1", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13079 {"strongarm110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13080 {"strongarm1100", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13081 {"strongarm1110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13082 {"arm9", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13083 {"arm920", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13084 {"arm920t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13085 {"arm922t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13086 {"arm940t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13087 {"arm9tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13088 /* For V5 or later processors we default to using VFP; but the user
13089 should really set the FPU type explicitly. */
13090 {"arm9e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
13091 {"arm9e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13092 {"arm926ej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
13093 {"arm926ejs", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
13094 {"arm926ej-s", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
13095 {"arm946e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
13096 {"arm946e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13097 {"arm966e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
13098 {"arm966e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13099 {"arm10t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
13100 {"arm10e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13101 {"arm1020", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13102 {"arm1020t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
13103 {"arm1020e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13104 {"arm1026ejs", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
13105 {"arm1026ej-s", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
13106 {"arm1136js", ARM_ARCH_V6
, FPU_NONE
},
13107 {"arm1136j-s", ARM_ARCH_V6
, FPU_NONE
},
13108 {"arm1136jfs", ARM_ARCH_V6
, FPU_ARCH_VFP_V2
},
13109 {"arm1136jf-s", ARM_ARCH_V6
, FPU_ARCH_VFP_V2
},
13110 {"mpcore", ARM_ARCH_V6K
, FPU_ARCH_VFP_V2
},
13111 {"mpcorenovfp", ARM_ARCH_V6K
, FPU_NONE
},
13112 {"arm1176jz-s", ARM_ARCH_V6ZK
, FPU_NONE
},
13113 {"arm1176jzf-s", ARM_ARCH_V6ZK
, FPU_ARCH_VFP_V2
},
13114 /* ??? XSCALE is really an architecture. */
13115 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
13116 /* ??? iwmmxt is not a processor. */
13117 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP_V2
},
13118 {"i80200", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
13120 {"ep9312", ARM_ARCH_V4T
| ARM_CEXT_MAVERICK
, FPU_ARCH_MAVERICK
},
13124 struct arm_arch_option_table
13131 /* This list should, at a minimum, contain all the architecture names
13132 recognized by GCC. */
13133 static struct arm_arch_option_table arm_archs
[] =
13135 {"all", ARM_ANY
, FPU_ARCH_FPA
},
13136 {"armv1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
13137 {"armv2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
13138 {"armv2a", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
13139 {"armv2s", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
13140 {"armv3", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13141 {"armv3m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
13142 {"armv4", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13143 {"armv4xm", ARM_ARCH_V4xM
, FPU_ARCH_FPA
},
13144 {"armv4t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13145 {"armv4txm", ARM_ARCH_V4TxM
, FPU_ARCH_FPA
},
13146 {"armv5", ARM_ARCH_V5
, FPU_ARCH_VFP
},
13147 {"armv5t", ARM_ARCH_V5T
, FPU_ARCH_VFP
},
13148 {"armv5txm", ARM_ARCH_V5TxM
, FPU_ARCH_VFP
},
13149 {"armv5te", ARM_ARCH_V5TE
, FPU_ARCH_VFP
},
13150 {"armv5texp", ARM_ARCH_V5TExP
, FPU_ARCH_VFP
},
13151 {"armv5tej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP
},
13152 {"armv6", ARM_ARCH_V6
, FPU_ARCH_VFP
},
13153 {"armv6j", ARM_ARCH_V6
, FPU_ARCH_VFP
},
13154 {"armv6k", ARM_ARCH_V6K
, FPU_ARCH_VFP
},
13155 {"armv6z", ARM_ARCH_V6Z
, FPU_ARCH_VFP
},
13156 {"armv6zk", ARM_ARCH_V6ZK
, FPU_ARCH_VFP
},
13157 {"armv6t2", ARM_ARCH_V6T2
, FPU_ARCH_VFP
},
13158 {"armv6kt2", ARM_ARCH_V6KT2
, FPU_ARCH_VFP
},
13159 {"armv6zt2", ARM_ARCH_V6ZT2
, FPU_ARCH_VFP
},
13160 {"armv6zkt2", ARM_ARCH_V6ZKT2
, FPU_ARCH_VFP
},
13161 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP
},
13162 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP
},
13166 /* ISA extensions in the co-processor space. */
13167 struct arm_arch_extension_table
13173 static struct arm_arch_extension_table arm_extensions
[] =
13175 {"maverick", ARM_CEXT_MAVERICK
},
13176 {"xscale", ARM_CEXT_XSCALE
},
13177 {"iwmmxt", ARM_CEXT_IWMMXT
},
13181 struct arm_fpu_option_table
13187 /* This list should, at a minimum, contain all the fpu names
13188 recognized by GCC. */
13189 static struct arm_fpu_option_table arm_fpus
[] =
13191 {"softfpa", FPU_NONE
},
13192 {"fpe", FPU_ARCH_FPE
},
13193 {"fpe2", FPU_ARCH_FPE
},
13194 {"fpe3", FPU_ARCH_FPA
}, /* Third release supports LFM/SFM. */
13195 {"fpa", FPU_ARCH_FPA
},
13196 {"fpa10", FPU_ARCH_FPA
},
13197 {"fpa11", FPU_ARCH_FPA
},
13198 {"arm7500fe", FPU_ARCH_FPA
},
13199 {"softvfp", FPU_ARCH_VFP
},
13200 {"softvfp+vfp", FPU_ARCH_VFP_V2
},
13201 {"vfp", FPU_ARCH_VFP_V2
},
13202 {"vfp9", FPU_ARCH_VFP_V2
},
13203 {"vfp10", FPU_ARCH_VFP_V2
},
13204 {"vfp10-r0", FPU_ARCH_VFP_V1
},
13205 {"vfpxd", FPU_ARCH_VFP_V1xD
},
13206 {"arm1020t", FPU_ARCH_VFP_V1
},
13207 {"arm1020e", FPU_ARCH_VFP_V2
},
13208 {"arm1136jfs", FPU_ARCH_VFP_V2
},
13209 {"arm1136jf-s", FPU_ARCH_VFP_V2
},
13210 {"maverick", FPU_ARCH_MAVERICK
},
13214 struct arm_float_abi_option_table
13220 static struct arm_float_abi_option_table arm_float_abis
[] =
13222 {"hard", ARM_FLOAT_ABI_HARD
},
13223 {"softfp", ARM_FLOAT_ABI_SOFTFP
},
13224 {"soft", ARM_FLOAT_ABI_SOFT
},
13228 struct arm_eabi_option_table
13231 unsigned int value
;
13235 /* We only know how to output GNU and ver 4 (AAELF) formats. */
13236 static struct arm_eabi_option_table arm_eabis
[] =
13238 {"gnu", EF_ARM_EABI_UNKNOWN
},
13239 {"4", EF_ARM_EABI_VER4
},
13244 struct arm_long_option_table
13246 char * option
; /* Substring to match. */
13247 char * help
; /* Help information. */
13248 int (* func
) (char * subopt
); /* Function to decode sub-option. */
13249 char * deprecated
; /* If non-null, print this message. */
13253 arm_parse_extension (char * str
, int * opt_p
)
13255 while (str
!= NULL
&& *str
!= 0)
13257 struct arm_arch_extension_table
* opt
;
13263 as_bad (_("invalid architectural extension"));
13268 ext
= strchr (str
, '+');
13271 optlen
= ext
- str
;
13273 optlen
= strlen (str
);
13277 as_bad (_("missing architectural extension"));
13281 for (opt
= arm_extensions
; opt
->name
!= NULL
; opt
++)
13282 if (strncmp (opt
->name
, str
, optlen
) == 0)
13284 *opt_p
|= opt
->value
;
13288 if (opt
->name
== NULL
)
13290 as_bad (_("unknown architectural extnsion `%s'"), str
);
13301 arm_parse_cpu (char * str
)
13303 struct arm_cpu_option_table
* opt
;
13304 char * ext
= strchr (str
, '+');
13308 optlen
= ext
- str
;
13310 optlen
= strlen (str
);
13314 as_bad (_("missing cpu name `%s'"), str
);
13318 for (opt
= arm_cpus
; opt
->name
!= NULL
; opt
++)
13319 if (strncmp (opt
->name
, str
, optlen
) == 0)
13321 mcpu_cpu_opt
= opt
->value
;
13322 mcpu_fpu_opt
= opt
->default_fpu
;
13325 return arm_parse_extension (ext
, &mcpu_cpu_opt
);
13330 as_bad (_("unknown cpu `%s'"), str
);
13335 arm_parse_arch (char * str
)
13337 struct arm_arch_option_table
*opt
;
13338 char *ext
= strchr (str
, '+');
13342 optlen
= ext
- str
;
13344 optlen
= strlen (str
);
13348 as_bad (_("missing architecture name `%s'"), str
);
13353 for (opt
= arm_archs
; opt
->name
!= NULL
; opt
++)
13354 if (streq (opt
->name
, str
))
13356 march_cpu_opt
= opt
->value
;
13357 march_fpu_opt
= opt
->default_fpu
;
13360 return arm_parse_extension (ext
, &march_cpu_opt
);
13365 as_bad (_("unknown architecture `%s'\n"), str
);
13370 arm_parse_fpu (char * str
)
13372 struct arm_fpu_option_table
* opt
;
13374 for (opt
= arm_fpus
; opt
->name
!= NULL
; opt
++)
13375 if (streq (opt
->name
, str
))
13377 mfpu_opt
= opt
->value
;
13381 as_bad (_("unknown floating point format `%s'\n"), str
);
13386 arm_parse_float_abi (char * str
)
13388 struct arm_float_abi_option_table
* opt
;
13390 for (opt
= arm_float_abis
; opt
->name
!= NULL
; opt
++)
13391 if (streq (opt
->name
, str
))
13393 mfloat_abi_opt
= opt
->value
;
13397 as_bad (_("unknown floating point abi `%s'\n"), str
);
13403 arm_parse_eabi (char * str
)
13405 struct arm_eabi_option_table
*opt
;
13407 for (opt
= arm_eabis
; opt
->name
!= NULL
; opt
++)
13408 if (streq (opt
->name
, str
))
13410 meabi_flags
= opt
->value
;
13413 as_bad (_("unknown EABI `%s'\n"), str
);
13418 struct arm_long_option_table arm_long_opts
[] =
13420 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13421 arm_parse_cpu
, NULL
},
13422 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13423 arm_parse_arch
, NULL
},
13424 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13425 arm_parse_fpu
, NULL
},
13426 {"mfloat-abi=", N_("<abi>\t assemble for floating point ABI <abi>"),
13427 arm_parse_float_abi
, NULL
},
13429 {"meabi=", N_("<ver>\t assemble for eabi version <ver>"),
13430 arm_parse_eabi
, NULL
},
13432 {NULL
, NULL
, 0, NULL
}
13436 md_parse_option (int c
, char * arg
)
13438 struct arm_option_table
*opt
;
13439 struct arm_long_option_table
*lopt
;
13445 target_big_endian
= 1;
13451 target_big_endian
= 0;
13456 /* Listing option. Just ignore these, we don't support additional
13461 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
13463 if (c
== opt
->option
[0]
13464 && ((arg
== NULL
&& opt
->option
[1] == 0)
13465 || streq (arg
, opt
->option
+ 1)))
13467 #if WARN_DEPRECATED
13468 /* If the option is deprecated, tell the user. */
13469 if (opt
->deprecated
!= NULL
)
13470 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
,
13471 arg
? arg
: "", _(opt
->deprecated
));
13474 if (opt
->var
!= NULL
)
13475 *opt
->var
= opt
->value
;
13481 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
13483 /* These options are expected to have an argument. */
13484 if (c
== lopt
->option
[0]
13486 && strncmp (arg
, lopt
->option
+ 1,
13487 strlen (lopt
->option
+ 1)) == 0)
13489 #if WARN_DEPRECATED
13490 /* If the option is deprecated, tell the user. */
13491 if (lopt
->deprecated
!= NULL
)
13492 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
, arg
,
13493 _(lopt
->deprecated
));
13496 /* Call the sup-option parser. */
13497 return lopt
->func (arg
+ strlen (lopt
->option
) - 1);
13508 md_show_usage (FILE * fp
)
13510 struct arm_option_table
*opt
;
13511 struct arm_long_option_table
*lopt
;
13513 fprintf (fp
, _(" ARM-specific assembler options:\n"));
13515 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
13516 if (opt
->help
!= NULL
)
13517 fprintf (fp
, " -%-23s%s\n", opt
->option
, _(opt
->help
));
13519 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
13520 if (lopt
->help
!= NULL
)
13521 fprintf (fp
, " -%s%s\n", lopt
->option
, _(lopt
->help
));
13525 -EB assemble code for a big-endian cpu\n"));
13530 -EL assemble code for a little-endian cpu\n"));
13534 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13537 cons_fix_new_arm (fragS
* frag
,
13542 bfd_reloc_code_real_type type
;
13546 FIXME: @@ Should look at CPU word size. */
13550 type
= BFD_RELOC_8
;
13553 type
= BFD_RELOC_16
;
13557 type
= BFD_RELOC_32
;
13560 type
= BFD_RELOC_64
;
13564 fix_new_exp (frag
, where
, (int) size
, exp
, pcrel
, type
);
13567 /* A good place to do this, although this was probably not intended
13568 for this kind of use. We need to dump the literal pool before
13569 references are made to a null symbol pointer. */
13574 literal_pool
* pool
;
13576 for (pool
= list_of_pools
; pool
; pool
= pool
->next
)
13578 /* Put it at the end of the relevent section. */
13579 subseg_set (pool
->section
, pool
->sub_section
);
13581 arm_elf_change_section ();
13588 arm_start_line_hook (void)
13590 last_label_seen
= NULL
;
13594 arm_frob_label (symbolS
* sym
)
13596 last_label_seen
= sym
;
13598 ARM_SET_THUMB (sym
, thumb_mode
);
13600 #if defined OBJ_COFF || defined OBJ_ELF
13601 ARM_SET_INTERWORK (sym
, support_interwork
);
13604 /* Note - do not allow local symbols (.Lxxx) to be labeled
13605 as Thumb functions. This is because these labels, whilst
13606 they exist inside Thumb code, are not the entry points for
13607 possible ARM->Thumb calls. Also, these labels can be used
13608 as part of a computed goto or switch statement. eg gcc
13609 can generate code that looks like this:
13611 ldr r2, [pc, .Laaa]
13621 The first instruction loads the address of the jump table.
13622 The second instruction converts a table index into a byte offset.
13623 The third instruction gets the jump address out of the table.
13624 The fourth instruction performs the jump.
13626 If the address stored at .Laaa is that of a symbol which has the
13627 Thumb_Func bit set, then the linker will arrange for this address
13628 to have the bottom bit set, which in turn would mean that the
13629 address computation performed by the third instruction would end
13630 up with the bottom bit set. Since the ARM is capable of unaligned
13631 word loads, the instruction would then load the incorrect address
13632 out of the jump table, and chaos would ensue. */
13633 if (label_is_thumb_function_name
13634 && (S_GET_NAME (sym
)[0] != '.' || S_GET_NAME (sym
)[1] != 'L')
13635 && (bfd_get_section_flags (stdoutput
, now_seg
) & SEC_CODE
) != 0)
13637 /* When the address of a Thumb function is taken the bottom
13638 bit of that address should be set. This will allow
13639 interworking between Arm and Thumb functions to work
13642 THUMB_SET_FUNC (sym
, 1);
13644 label_is_thumb_function_name
= FALSE
;
13648 /* Adjust the symbol table. This marks Thumb symbols as distinct from
13652 arm_adjust_symtab (void)
13657 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
13659 if (ARM_IS_THUMB (sym
))
13661 if (THUMB_IS_FUNC (sym
))
13663 /* Mark the symbol as a Thumb function. */
13664 if ( S_GET_STORAGE_CLASS (sym
) == C_STAT
13665 || S_GET_STORAGE_CLASS (sym
) == C_LABEL
) /* This can happen! */
13666 S_SET_STORAGE_CLASS (sym
, C_THUMBSTATFUNC
);
13668 else if (S_GET_STORAGE_CLASS (sym
) == C_EXT
)
13669 S_SET_STORAGE_CLASS (sym
, C_THUMBEXTFUNC
);
13671 as_bad (_("%s: unexpected function type: %d"),
13672 S_GET_NAME (sym
), S_GET_STORAGE_CLASS (sym
));
13674 else switch (S_GET_STORAGE_CLASS (sym
))
13677 S_SET_STORAGE_CLASS (sym
, C_THUMBEXT
);
13680 S_SET_STORAGE_CLASS (sym
, C_THUMBSTAT
);
13683 S_SET_STORAGE_CLASS (sym
, C_THUMBLABEL
);
13691 if (ARM_IS_INTERWORK (sym
))
13692 coffsymbol (symbol_get_bfdsym (sym
))->native
->u
.syment
.n_flags
= 0xFF;
13699 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
13701 if (ARM_IS_THUMB (sym
))
13703 elf_symbol_type
* elf_sym
;
13705 elf_sym
= elf_symbol (symbol_get_bfdsym (sym
));
13706 bind
= ELF_ST_BIND (elf_sym
);
13708 /* If it's a .thumb_func, declare it as so,
13709 otherwise tag label as .code 16. */
13710 if (THUMB_IS_FUNC (sym
))
13711 elf_sym
->internal_elf_sym
.st_info
=
13712 ELF_ST_INFO (bind
, STT_ARM_TFUNC
);
13714 elf_sym
->internal_elf_sym
.st_info
=
13715 ELF_ST_INFO (bind
, STT_ARM_16BIT
);
13722 arm_data_in_code (void)
13724 if (thumb_mode
&& ! strncmp (input_line_pointer
+ 1, "data:", 5))
13726 *input_line_pointer
= '/';
13727 input_line_pointer
+= 5;
13728 *input_line_pointer
= 0;
13736 arm_canonicalize_symbol_name (char * name
)
13740 if (thumb_mode
&& (len
= strlen (name
)) > 5
13741 && streq (name
+ len
- 5, "/data"))
13742 *(name
+ len
- 5) = 0;
13747 #if defined OBJ_COFF || defined OBJ_ELF
13749 arm_validate_fix (fixS
* fixP
)
13751 /* If the destination of the branch is a defined symbol which does not have
13752 the THUMB_FUNC attribute, then we must be calling a function which has
13753 the (interfacearm) attribute. We look for the Thumb entry point to that
13754 function and change the branch to refer to that function instead. */
13755 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
13756 && fixP
->fx_addsy
!= NULL
13757 && S_IS_DEFINED (fixP
->fx_addsy
)
13758 && ! THUMB_IS_FUNC (fixP
->fx_addsy
))
13760 fixP
->fx_addsy
= find_real_start (fixP
->fx_addsy
);
13766 arm_force_relocation (struct fix
* fixp
)
13768 #if defined (OBJ_COFF) && defined (TE_PE)
13769 if (fixp
->fx_r_type
== BFD_RELOC_RVA
)
13773 if (fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
13774 || fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
13775 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
13776 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
)
13780 /* Resolve these relocations even if the symbol is extern or weak. */
13781 if (fixp
->fx_r_type
== BFD_RELOC_ARM_IMMEDIATE
13782 || fixp
->fx_r_type
== BFD_RELOC_ARM_OFFSET_IMM
13783 || fixp
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
13786 return generic_force_reloc (fixp
);
13790 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
13791 local labels from being added to the output symbol table when they
13792 are used with the ADRL pseudo op. The ADRL relocation should always
13793 be resolved before the binbary is emitted, so it is safe to say that
13794 it is adjustable. */
13797 arm_fix_adjustable (fixS
* fixP
)
13799 if (fixP
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
13806 /* Relocations against Thumb function names must be left unadjusted,
13807 so that the linker can use this information to correctly set the
13808 bottom bit of their addresses. The MIPS version of this function
13809 also prevents relocations that are mips-16 specific, but I do not
13810 know why it does this.
13813 There is one other problem that ought to be addressed here, but
13814 which currently is not: Taking the address of a label (rather
13815 than a function) and then later jumping to that address. Such
13816 addresses also ought to have their bottom bit set (assuming that
13817 they reside in Thumb code), but at the moment they will not. */
13820 arm_fix_adjustable (fixS
* fixP
)
13822 if (fixP
->fx_addsy
== NULL
)
13825 if (THUMB_IS_FUNC (fixP
->fx_addsy
)
13826 && fixP
->fx_subsy
== NULL
)
13829 /* We need the symbol name for the VTABLE entries. */
13830 if ( fixP
->fx_r_type
== BFD_RELOC_VTABLE_INHERIT
13831 || fixP
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
13834 /* Don't allow symbols to be discarded on GOT related relocs. */
13835 if (fixP
->fx_r_type
== BFD_RELOC_ARM_PLT32
13836 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOT32
13837 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOTOFF
13838 || fixP
->fx_r_type
== BFD_RELOC_ARM_TARGET2
)
13845 elf32_arm_target_format (void)
13848 return (target_big_endian
13849 ? "elf32-bigarm-symbian"
13850 : "elf32-littlearm-symbian");
13851 #elif defined (TE_VXWORKS)
13852 return (target_big_endian
13853 ? "elf32-bigarm-vxworks"
13854 : "elf32-littlearm-vxworks");
13856 if (target_big_endian
)
13857 return "elf32-bigarm";
13859 return "elf32-littlearm";
13864 armelf_frob_symbol (symbolS
* symp
,
13867 elf_frob_symbol (symp
, puntp
);
13871 s_arm_elf_cons (int nbytes
)
13875 #ifdef md_flush_pending_output
13876 md_flush_pending_output ();
13879 if (is_it_end_of_statement ())
13881 demand_empty_rest_of_line ();
13885 #ifdef md_cons_align
13886 md_cons_align (nbytes
);
13889 mapping_state (MAP_DATA
);
13892 bfd_reloc_code_real_type reloc
;
13894 expression (& exp
);
13896 if (exp
.X_op
== O_symbol
13897 && * input_line_pointer
== '('
13898 && (reloc
= arm_parse_reloc ()) != BFD_RELOC_UNUSED
)
13900 reloc_howto_type
*howto
= bfd_reloc_type_lookup (stdoutput
, reloc
);
13901 int size
= bfd_get_reloc_size (howto
);
13904 as_bad ("%s relocations do not fit in %d bytes",
13905 howto
->name
, nbytes
);
13908 char *p
= frag_more ((int) nbytes
);
13909 int offset
= nbytes
- size
;
13911 fix_new_exp (frag_now
, p
- frag_now
->fr_literal
+ offset
, size
,
13916 emit_expr (&exp
, (unsigned int) nbytes
);
13918 while (*input_line_pointer
++ == ',');
13920 /* Put terminator back into stream. */
13921 input_line_pointer
--;
13922 demand_empty_rest_of_line ();
13926 /* Parse a .rel31 directive. */
13929 s_arm_rel31 (int ignored ATTRIBUTE_UNUSED
)
13935 SKIP_WHITESPACE ();
13938 if (*input_line_pointer
== '1')
13939 highbit
= 0x80000000;
13940 else if (*input_line_pointer
!= '0')
13941 as_bad (_("expected 0 or 1"));
13943 input_line_pointer
++;
13944 SKIP_WHITESPACE ();
13945 if (*input_line_pointer
!= ',')
13946 as_bad (_("missing comma"));
13947 input_line_pointer
++;
13949 #ifdef md_flush_pending_output
13950 md_flush_pending_output ();
13953 #ifdef md_cons_align
13957 mapping_state (MAP_DATA
);
13962 md_number_to_chars (p
, highbit
, 4);
13963 fix_new_arm (frag_now
, p
- frag_now
->fr_literal
, 4, &exp
, 1,
13964 BFD_RELOC_ARM_PREL31
);
13966 demand_empty_rest_of_line ();
13969 /* Code to deal with unwinding tables. */
13971 static void add_unwind_adjustsp (offsetT
);
13973 /* Switch to section NAME and create section if necessary. It's
13974 rather ugly that we have to manipulate input_line_pointer but I
13975 don't see any other way to accomplish the same thing without
13976 changing obj-elf.c (which may be the Right Thing, in the end).
13977 Copied from tc-ia64.c. */
13980 set_section (char *name
)
13982 char *saved_input_line_pointer
;
13984 saved_input_line_pointer
= input_line_pointer
;
13985 input_line_pointer
= name
;
13986 obj_elf_section (0);
13987 input_line_pointer
= saved_input_line_pointer
;
13990 /* Cenerate and deferred unwind frame offset. */
13993 flush_pending_unwind (void)
13997 offset
= unwind
.pending_offset
;
13998 unwind
.pending_offset
= 0;
14000 add_unwind_adjustsp (offset
);
14003 /* Add an opcode to this list for this function. Two-byte opcodes should
14004 be passed as op[0] << 8 | op[1]. The list of opcodes is built in reverse
14008 add_unwind_opcode (valueT op
, int length
)
14010 /* Add any deferred stack adjustment. */
14011 if (unwind
.pending_offset
)
14012 flush_pending_unwind ();
14014 unwind
.sp_restored
= 0;
14016 if (unwind
.opcode_count
+ length
> unwind
.opcode_alloc
)
14018 unwind
.opcode_alloc
+= ARM_OPCODE_CHUNK_SIZE
;
14019 if (unwind
.opcodes
)
14020 unwind
.opcodes
= xrealloc (unwind
.opcodes
,
14021 unwind
.opcode_alloc
);
14023 unwind
.opcodes
= xmalloc (unwind
.opcode_alloc
);
14028 unwind
.opcodes
[unwind
.opcode_count
] = op
& 0xff;
14030 unwind
.opcode_count
++;
14034 /* Add unwind opcodes to adjust the stack pointer. */
14037 add_unwind_adjustsp (offsetT offset
)
14041 if (offset
> 0x200)
14043 /* We need at most 5 bytes to hold a 32-bit value in a uleb128. */
14048 /* Long form: 0xb2, uleb128. */
14049 /* This might not fit in a word so add the individual bytes,
14050 remembering the list is built in reverse order. */
14051 o
= (valueT
) ((offset
- 0x204) >> 2);
14053 add_unwind_opcode (0, 1);
14055 /* Calculate the uleb128 encoding of the offset. */
14059 bytes
[n
] = o
& 0x7f;
14065 /* Add the insn. */
14067 add_unwind_opcode (bytes
[n
- 1], 1);
14068 add_unwind_opcode (0xb2, 1);
14070 else if (offset
> 0x100)
14072 /* Two short opcodes. */
14073 add_unwind_opcode (0x3f, 1);
14074 op
= (offset
- 0x104) >> 2;
14075 add_unwind_opcode (op
, 1);
14077 else if (offset
> 0)
14079 /* Short opcode. */
14080 op
= (offset
- 4) >> 2;
14081 add_unwind_opcode (op
, 1);
14083 else if (offset
< 0)
14086 while (offset
> 0x100)
14088 add_unwind_opcode (0x7f, 1);
14091 op
= ((offset
- 4) >> 2) | 0x40;
14092 add_unwind_opcode (op
, 1);
14096 /* Finish the list of unwind opcodes for this function. */
14098 finish_unwind_opcodes (void)
14102 if (unwind
.fp_used
)
14104 /* Adjust sp as neccessary. */
14105 unwind
.pending_offset
+= unwind
.fp_offset
- unwind
.frame_size
;
14106 flush_pending_unwind ();
14108 /* After restoring sp from the frame pointer. */
14109 op
= 0x90 | unwind
.fp_reg
;
14110 add_unwind_opcode (op
, 1);
14113 flush_pending_unwind ();
14117 /* Start an exception table entry. If idx is nonzero this is an index table
14121 start_unwind_section (const segT text_seg
, int idx
)
14123 const char * text_name
;
14124 const char * prefix
;
14125 const char * prefix_once
;
14129 size_t sec_name_len
;
14133 prefix
= ELF_STRING_ARM_unwind
;
14134 prefix_once
= ELF_STRING_ARM_unwind_once
;
14138 prefix
= ELF_STRING_ARM_unwind_info
;
14139 prefix_once
= ELF_STRING_ARM_unwind_info_once
;
14142 text_name
= segment_name (text_seg
);
14143 if (streq (text_name
, ".text"))
14146 if (strncmp (text_name
, ".gnu.linkonce.t.",
14147 strlen (".gnu.linkonce.t.")) == 0)
14149 prefix
= prefix_once
;
14150 text_name
+= strlen (".gnu.linkonce.t.");
14153 prefix_len
= strlen (prefix
);
14154 text_len
= strlen (text_name
);
14155 sec_name_len
= prefix_len
+ text_len
;
14156 sec_name
= alloca (sec_name_len
+ 1);
14157 memcpy (sec_name
, prefix
, prefix_len
);
14158 memcpy (sec_name
+ prefix_len
, text_name
, text_len
);
14159 sec_name
[prefix_len
+ text_len
] = '\0';
14161 /* Handle COMDAT group. */
14162 if (prefix
!= prefix_once
&& (text_seg
->flags
& SEC_LINK_ONCE
) != 0)
14165 size_t len
, group_name_len
;
14166 const char *group_name
= elf_group_name (text_seg
);
14168 if (group_name
== NULL
)
14170 as_bad ("Group section `%s' has no group signature",
14171 segment_name (text_seg
));
14172 ignore_rest_of_line ();
14175 /* We have to construct a fake section directive. */
14176 group_name_len
= strlen (group_name
);
14182 len
= (sec_name_len
14183 + prefix_len
/* ,"aG",%sectiontype, */
14184 + group_name_len
/* ,group_name */
14185 + 7); /* ,comdat */
14187 section
= alloca (len
+ 1);
14188 memcpy (section
, sec_name
, sec_name_len
);
14190 memcpy (section
+ sec_name_len
, ",\"aG\",%exidx,", 13);
14192 memcpy (section
+ sec_name_len
, ",\"aG\",%progbits,", 16);
14193 memcpy (section
+ sec_name_len
+ prefix_len
, group_name
, group_name_len
);
14194 memcpy (section
+ len
- 7, ",comdat", 7);
14195 section
[len
] = '\0';
14196 set_section (section
);
14200 set_section (sec_name
);
14201 bfd_set_section_flags (stdoutput
, now_seg
,
14202 SEC_LOAD
| SEC_ALLOC
| SEC_READONLY
);
14205 /* Set the setion link for index tables. */
14207 elf_linked_to_section (now_seg
) = text_seg
;
14211 /* Start an unwind table entry. HAVE_DATA is nonzero if we have additional
14212 personality routine data. Returns zero, or the index table value for
14213 and inline entry. */
14216 create_unwind_entry (int have_data
)
14221 /* The current word of data. */
14223 /* The number of bytes left in this word. */
14226 finish_unwind_opcodes ();
14228 /* Remember the current text section. */
14229 unwind
.saved_seg
= now_seg
;
14230 unwind
.saved_subseg
= now_subseg
;
14232 start_unwind_section (now_seg
, 0);
14234 if (unwind
.personality_routine
== NULL
)
14236 if (unwind
.personality_index
== -2)
14239 as_bad (_("handerdata in cantunwind frame"));
14240 return 1; /* EXIDX_CANTUNWIND. */
14243 /* Use a default personality routine if none is specified. */
14244 if (unwind
.personality_index
== -1)
14246 if (unwind
.opcode_count
> 3)
14247 unwind
.personality_index
= 1;
14249 unwind
.personality_index
= 0;
14252 /* Space for the personality routine entry. */
14253 if (unwind
.personality_index
== 0)
14255 if (unwind
.opcode_count
> 3)
14256 as_bad (_("too many unwind opcodes for personality routine 0"));
14260 /* All the data is inline in the index table. */
14263 while (unwind
.opcode_count
> 0)
14265 unwind
.opcode_count
--;
14266 data
= (data
<< 8) | unwind
.opcodes
[unwind
.opcode_count
];
14270 /* Pad with "finish" opcodes. */
14272 data
= (data
<< 8) | 0xb0;
14279 /* We get two opcodes "free" in the first word. */
14280 size
= unwind
.opcode_count
- 2;
14283 /* An extra byte is required for the opcode count. */
14284 size
= unwind
.opcode_count
+ 1;
14286 size
= (size
+ 3) >> 2;
14288 as_bad (_("too many unwind opcodes"));
14290 frag_align (2, 0, 0);
14291 record_alignment (now_seg
, 2);
14292 unwind
.table_entry
= expr_build_dot ();
14294 /* Allocate the table entry. */
14295 ptr
= frag_more ((size
<< 2) + 4);
14296 where
= frag_now_fix () - ((size
<< 2) + 4);
14298 switch (unwind
.personality_index
)
14301 /* ??? Should this be a PLT generating relocation? */
14302 /* Custom personality routine. */
14303 fix_new (frag_now
, where
, 4, unwind
.personality_routine
, 0, 1,
14304 BFD_RELOC_ARM_PREL31
);
14306 /* Indicate dependency to linker. */
14308 char *name
= "__aeabi_unwind_cpp_pr0";
14309 symbolS
*pr
= symbol_find_or_make (name
);
14310 fix_new (frag_now
, where
, 4, pr
, 0, 1, BFD_RELOC_NONE
);
14316 /* Set the first byte to the number of additional words. */
14321 /* ABI defined personality routines. */
14323 /* Three opcodes bytes are packed into the first word. */
14330 /* The size and first two opcode bytes go in the first word. */
14331 data
= ((0x80 + unwind
.personality_index
) << 8) | size
;
14337 /* Indicate dependency to linker. */
14338 char *name
[] = { "__aeabi_unwind_cpp_pr0",
14339 "__aeabi_unwind_cpp_pr1",
14340 "__aeabi_unwind_cpp_pr2" };
14341 symbolS
*pr
= symbol_find_or_make (name
[unwind
.personality_index
]);
14342 fix_new (frag_now
, where
, 4, pr
, 0, 1, BFD_RELOC_NONE
);
14347 /* Should never happen. */
14351 /* Pack the opcodes into words (MSB first), reversing the list at the same
14353 while (unwind
.opcode_count
> 0)
14357 md_number_to_chars (ptr
, data
, 4);
14362 unwind
.opcode_count
--;
14364 data
= (data
<< 8) | unwind
.opcodes
[unwind
.opcode_count
];
14367 /* Finish off the last word. */
14370 /* Pad with "finish" opcodes. */
14372 data
= (data
<< 8) | 0xb0;
14374 md_number_to_chars (ptr
, data
, 4);
14379 /* Add an empty descriptor if there is no user-specified data. */
14380 ptr
= frag_more (4);
14381 md_number_to_chars (ptr
, 0, 4);
14388 /* Parse an unwind_fnstart directive. Simply records the current location. */
14391 s_arm_unwind_fnstart (int ignored ATTRIBUTE_UNUSED
)
14393 demand_empty_rest_of_line ();
14394 /* Mark the start of the function. */
14395 unwind
.proc_start
= expr_build_dot ();
14397 /* Reset the rest of the unwind info. */
14398 unwind
.opcode_count
= 0;
14399 unwind
.table_entry
= NULL
;
14400 unwind
.personality_routine
= NULL
;
14401 unwind
.personality_index
= -1;
14402 unwind
.frame_size
= 0;
14403 unwind
.fp_offset
= 0;
14404 unwind
.fp_reg
= 13;
14405 unwind
.fp_used
= 0;
14406 unwind
.sp_restored
= 0;
14410 /* Parse a handlerdata directive. Creates the exception handling table entry
14411 for the function. */
14414 s_arm_unwind_handlerdata (int ignored ATTRIBUTE_UNUSED
)
14416 demand_empty_rest_of_line ();
14417 if (unwind
.table_entry
)
14418 as_bad (_("dupicate .handlerdata directive"));
14420 create_unwind_entry (1);
14423 /* Parse an unwind_fnend directive. Generates the index table entry. */
14426 s_arm_unwind_fnend (int ignored ATTRIBUTE_UNUSED
)
14432 demand_empty_rest_of_line ();
14434 /* Add eh table entry. */
14435 if (unwind
.table_entry
== NULL
)
14436 val
= create_unwind_entry (0);
14440 /* Add index table entry. This is two words. */
14441 start_unwind_section (unwind
.saved_seg
, 1);
14442 frag_align (2, 0, 0);
14443 record_alignment (now_seg
, 2);
14445 ptr
= frag_more (8);
14446 where
= frag_now_fix () - 8;
14448 /* Self relative offset of the function start. */
14449 fix_new (frag_now
, where
, 4, unwind
.proc_start
, 0, 1,
14450 BFD_RELOC_ARM_PREL31
);
14453 /* Inline exception table entry. */
14454 md_number_to_chars (ptr
+ 4, val
, 4);
14456 /* Self relative offset of the table entry. */
14457 fix_new (frag_now
, where
+ 4, 4, unwind
.table_entry
, 0, 1,
14458 BFD_RELOC_ARM_PREL31
);
14460 /* Restore the original section. */
14461 subseg_set (unwind
.saved_seg
, unwind
.saved_subseg
);
14465 /* Parse an unwind_cantunwind directive. */
14468 s_arm_unwind_cantunwind (int ignored ATTRIBUTE_UNUSED
)
14470 demand_empty_rest_of_line ();
14471 if (unwind
.personality_routine
|| unwind
.personality_index
!= -1)
14472 as_bad (_("personality routine specified for cantunwind frame"));
14474 unwind
.personality_index
= -2;
14478 /* Parse a personalityindex directive. */
14481 s_arm_unwind_personalityindex (int ignored ATTRIBUTE_UNUSED
)
14485 if (unwind
.personality_routine
|| unwind
.personality_index
!= -1)
14486 as_bad (_("duplicate .personalityindex directive"));
14488 SKIP_WHITESPACE ();
14492 if (exp
.X_op
!= O_constant
14493 || exp
.X_add_number
< 0 || exp
.X_add_number
> 15)
14495 as_bad (_("bad personality routine number"));
14496 ignore_rest_of_line ();
14500 unwind
.personality_index
= exp
.X_add_number
;
14502 demand_empty_rest_of_line ();
14506 /* Parse a personality directive. */
14509 s_arm_unwind_personality (int ignored ATTRIBUTE_UNUSED
)
14513 if (unwind
.personality_routine
|| unwind
.personality_index
!= -1)
14514 as_bad (_("duplicate .personality directive"));
14516 SKIP_WHITESPACE ();
14517 name
= input_line_pointer
;
14518 c
= get_symbol_end ();
14519 p
= input_line_pointer
;
14520 unwind
.personality_routine
= symbol_find_or_make (name
);
14522 SKIP_WHITESPACE ();
14523 demand_empty_rest_of_line ();
14527 /* Parse a directive saving core registers. */
14530 s_arm_unwind_save_core (void)
14536 SKIP_WHITESPACE ();
14537 range
= reg_list (&input_line_pointer
);
14540 as_bad (_("expected register list"));
14541 ignore_rest_of_line ();
14545 demand_empty_rest_of_line ();
14547 /* Turn .unwind_movsp ip followed by .unwind_save {..., ip, ...}
14548 into .unwind_save {..., sp...}. We aren't bothered about the value of
14549 ip because it is clobbered by calls. */
14550 if (unwind
.sp_restored
&& unwind
.fp_reg
== 12
14551 && (range
& 0x3000) == 0x1000)
14553 unwind
.opcode_count
--;
14554 unwind
.sp_restored
= 0;
14555 range
= (range
| 0x2000) & ~0x1000;
14556 unwind
.pending_offset
= 0;
14559 /* See if we can use the short opcodes. These pop a block of upto 8
14560 registers starting with r4, plus maybe r14. */
14561 for (n
= 0; n
< 8; n
++)
14563 /* Break at the first non-saved register. */
14564 if ((range
& (1 << (n
+ 4))) == 0)
14567 /* See if there are any other bits set. */
14568 if (n
== 0 || (range
& (0xfff0 << n
) & 0xbff0) != 0)
14570 /* Use the long form. */
14571 op
= 0x8000 | ((range
>> 4) & 0xfff);
14572 add_unwind_opcode (op
, 2);
14576 /* Use the short form. */
14577 if (range
& 0x4000)
14578 op
= 0xa8; /* Pop r14. */
14580 op
= 0xa0; /* Do not pop r14. */
14582 add_unwind_opcode (op
, 1);
14588 op
= 0xb100 | (range
& 0xf);
14589 add_unwind_opcode (op
, 2);
14592 /* Record the number of bytes pushed. */
14593 for (n
= 0; n
< 16; n
++)
14595 if (range
& (1 << n
))
14596 unwind
.frame_size
+= 4;
14601 /* Parse a directive saving FPA registers. */
14604 s_arm_unwind_save_fpa (int reg
)
14610 /* Get Number of registers to transfer. */
14611 if (skip_past_comma (&input_line_pointer
) != FAIL
)
14614 exp
.X_op
= O_illegal
;
14616 if (exp
.X_op
!= O_constant
)
14618 as_bad (_("expected , <constant>"));
14619 ignore_rest_of_line ();
14623 num_regs
= exp
.X_add_number
;
14625 if (num_regs
< 1 || num_regs
> 4)
14627 as_bad (_("number of registers must be in the range [1:4]"));
14628 ignore_rest_of_line ();
14632 demand_empty_rest_of_line ();
14637 op
= 0xb4 | (num_regs
- 1);
14638 add_unwind_opcode (op
, 1);
14643 op
= 0xc800 | (reg
<< 4) | (num_regs
- 1);
14644 add_unwind_opcode (op
, 2);
14646 unwind
.frame_size
+= num_regs
* 12;
14650 /* Parse a directive saving VFP registers. */
14653 s_arm_unwind_save_vfp (void)
14659 count
= vfp_parse_reg_list (&input_line_pointer
, ®
, 1);
14662 as_bad (_("expected register list"));
14663 ignore_rest_of_line ();
14667 demand_empty_rest_of_line ();
14672 op
= 0xb8 | (count
- 1);
14673 add_unwind_opcode (op
, 1);
14678 op
= 0xb300 | (reg
<< 4) | (count
- 1);
14679 add_unwind_opcode (op
, 2);
14681 unwind
.frame_size
+= count
* 8 + 4;
14685 /* Parse a directive saving iWMMXt registers. */
14688 s_arm_unwind_save_wmmx (void)
14697 if (*input_line_pointer
== '{')
14698 input_line_pointer
++;
14704 reg
= arm_reg_parse (&input_line_pointer
,
14705 all_reg_maps
[REG_TYPE_IWMMXT
].htab
);
14707 if (wr_register (reg
))
14709 i
= reg
& ~WR_PREFIX
;
14711 as_tsktsk (_("register list not in ascending order"));
14714 else if (wcg_register (reg
))
14716 i
= (reg
& ~WC_PREFIX
) - 8;
14718 as_tsktsk (_("register list not in ascending order"));
14719 wcg_mask
|= 1 << i
;
14723 as_bad (_("expected wr or wcgr"));
14727 SKIP_WHITESPACE ();
14728 if (*input_line_pointer
== '-')
14730 hi_reg
= arm_reg_parse (&input_line_pointer
,
14731 all_reg_maps
[REG_TYPE_IWMMXT
].htab
);
14732 if (wr_register (reg
) && wr_register (hi_reg
))
14734 for (; reg
< hi_reg
; reg
++)
14735 wr_mask
|= 1 << (reg
& ~WR_PREFIX
);
14737 else if (wcg_register (reg
) && wcg_register (hi_reg
))
14739 for (; reg
< hi_reg
; reg
++)
14740 wcg_mask
|= 1 << ((reg
& ~WC_PREFIX
) - 8);
14744 as_bad (_("bad register range"));
14749 while (skip_past_comma (&input_line_pointer
) != FAIL
);
14751 SKIP_WHITESPACE ();
14752 if (*input_line_pointer
== '}')
14753 input_line_pointer
++;
14755 demand_empty_rest_of_line ();
14757 if (wr_mask
&& wcg_mask
)
14759 as_bad (_("inconsistent register types"));
14763 /* Generate any deferred opcodes becuuse we're going to be looking at
14765 flush_pending_unwind ();
14769 for (i
= 0; i
< 16; i
++)
14771 if (wcg_mask
& (1 << i
))
14772 unwind
.frame_size
+= 4;
14774 op
= 0xc700 | wcg_mask
;
14775 add_unwind_opcode (op
, 2);
14779 for (i
= 0; i
< 16; i
++)
14781 if (wr_mask
& (1 << i
))
14782 unwind
.frame_size
+= 8;
14784 /* Attempt to combine with a previous opcode. We do this because gcc
14785 likes to output separate unwind directives for a single block of
14787 if (unwind
.opcode_count
> 0)
14789 i
= unwind
.opcodes
[unwind
.opcode_count
- 1];
14790 if ((i
& 0xf8) == 0xc0)
14793 /* Only merge if the blocks are contiguous. */
14796 if ((wr_mask
& 0xfe00) == (1 << 9))
14798 wr_mask
|= ((1 << (i
+ 11)) - 1) & 0xfc00;
14799 unwind
.opcode_count
--;
14802 else if (i
== 6 && unwind
.opcode_count
>= 2)
14804 i
= unwind
.opcodes
[unwind
.opcode_count
- 2];
14808 op
= 0xffff << (reg
- 1);
14810 || ((wr_mask
& op
) == (1u << (reg
- 1))))
14812 op
= (1 << (reg
+ i
+ 1)) - 1;
14813 op
&= ~((1 << reg
) - 1);
14815 unwind
.opcode_count
-= 2;
14822 /* We want to generate opcodes in the order the registers have been
14823 saved, ie. descending order. */
14824 for (reg
= 15; reg
>= -1; reg
--)
14826 /* Save registers in blocks. */
14828 || !(wr_mask
& (1 << reg
)))
14830 /* We found an unsaved reg. Generate opcodes to save the
14831 preceeding block. */
14837 op
= 0xc0 | (hi_reg
- 10);
14838 add_unwind_opcode (op
, 1);
14843 op
= 0xc600 | ((reg
+ 1) << 4) | ((hi_reg
- reg
) - 1);
14844 add_unwind_opcode (op
, 2);
14853 ignore_rest_of_line ();
14857 /* Parse an unwind_save directive. */
14860 s_arm_unwind_save (int ignored ATTRIBUTE_UNUSED
)
14865 /* Figure out what sort of save we have. */
14866 SKIP_WHITESPACE ();
14867 saved_ptr
= input_line_pointer
;
14869 reg
= arm_reg_parse (&input_line_pointer
, all_reg_maps
[REG_TYPE_FN
].htab
);
14872 s_arm_unwind_save_fpa (reg
);
14876 if (*input_line_pointer
== '{')
14877 input_line_pointer
++;
14879 SKIP_WHITESPACE ();
14881 reg
= arm_reg_parse (&input_line_pointer
, all_reg_maps
[REG_TYPE_RN
].htab
);
14884 input_line_pointer
= saved_ptr
;
14885 s_arm_unwind_save_core ();
14889 reg
= arm_reg_parse (&input_line_pointer
, all_reg_maps
[REG_TYPE_DN
].htab
);
14892 input_line_pointer
= saved_ptr
;
14893 s_arm_unwind_save_vfp ();
14897 reg
= arm_reg_parse (&input_line_pointer
,
14898 all_reg_maps
[REG_TYPE_IWMMXT
].htab
);
14901 input_line_pointer
= saved_ptr
;
14902 s_arm_unwind_save_wmmx ();
14906 /* TODO: Maverick registers. */
14907 as_bad (_("unrecognised register"));
14911 /* Parse an unwind_movsp directive. */
14914 s_arm_unwind_movsp (int ignored ATTRIBUTE_UNUSED
)
14919 SKIP_WHITESPACE ();
14920 reg
= reg_required_here (&input_line_pointer
, -1);
14923 as_bad (_("ARM register expected"));
14924 ignore_rest_of_line ();
14928 if (reg
== 13 || reg
== 15)
14930 as_bad (_("r%d not permitted in .unwind_movsp directive"), reg
);
14931 ignore_rest_of_line ();
14935 if (unwind
.fp_reg
!= 13)
14936 as_bad (_("unexpected .unwind_movsp directive"));
14938 /* Generate opcode to restore the value. */
14940 add_unwind_opcode (op
, 1);
14942 /* Record the information for later. */
14943 unwind
.fp_reg
= reg
;
14944 unwind
.fp_offset
= unwind
.frame_size
;
14945 unwind
.sp_restored
= 1;
14946 demand_empty_rest_of_line ();
14950 /* Parse #<number>. */
14953 require_hashconst (int * val
)
14957 SKIP_WHITESPACE ();
14958 if (*input_line_pointer
== '#')
14960 input_line_pointer
++;
14964 exp
.X_op
= O_illegal
;
14966 if (exp
.X_op
!= O_constant
)
14968 as_bad (_("expected #constant"));
14969 ignore_rest_of_line ();
14972 *val
= exp
.X_add_number
;
14976 /* Parse an unwind_pad directive. */
14979 s_arm_unwind_pad (int ignored ATTRIBUTE_UNUSED
)
14983 if (require_hashconst (&offset
) == FAIL
)
14988 as_bad (_("stack increment must be multiple of 4"));
14989 ignore_rest_of_line ();
14993 /* Don't generate any opcodes, just record the details for later. */
14994 unwind
.frame_size
+= offset
;
14995 unwind
.pending_offset
+= offset
;
14997 demand_empty_rest_of_line ();
15000 /* Parse an unwind_setfp directive. */
15003 s_arm_unwind_setfp (int ignored ATTRIBUTE_UNUSED
)
15009 fp_reg
= reg_required_here (&input_line_pointer
, -1);
15010 if (skip_past_comma (&input_line_pointer
) == FAIL
)
15013 sp_reg
= reg_required_here (&input_line_pointer
, -1);
15015 if (fp_reg
== FAIL
|| sp_reg
== FAIL
)
15017 as_bad (_("expected <reg>, <reg>"));
15018 ignore_rest_of_line ();
15022 /* Optonal constant. */
15023 if (skip_past_comma (&input_line_pointer
) != FAIL
)
15025 if (require_hashconst (&offset
) == FAIL
)
15031 demand_empty_rest_of_line ();
15033 if (sp_reg
!= 13 && sp_reg
!= unwind
.fp_reg
)
15035 as_bad (_("register must be either sp or set by a previous"
15036 "unwind_movsp directive"));
15040 /* Don't generate any opcodes, just record the information for later. */
15041 unwind
.fp_reg
= fp_reg
;
15042 unwind
.fp_used
= 1;
15044 unwind
.fp_offset
= unwind
.frame_size
- offset
;
15046 unwind
.fp_offset
-= offset
;
15049 /* Parse an unwind_raw directive. */
15052 s_arm_unwind_raw (int ignored ATTRIBUTE_UNUSED
)
15055 /* This is an arbitary limit. */
15056 unsigned char op
[16];
15059 SKIP_WHITESPACE ();
15061 if (exp
.X_op
== O_constant
15062 && skip_past_comma (&input_line_pointer
) != FAIL
)
15064 unwind
.frame_size
+= exp
.X_add_number
;
15068 exp
.X_op
= O_illegal
;
15070 if (exp
.X_op
!= O_constant
)
15072 as_bad (_("expected <offset>, <opcode>"));
15073 ignore_rest_of_line ();
15079 /* Parse the opcode. */
15084 as_bad (_("unwind opcode too long"));
15085 ignore_rest_of_line ();
15087 if (exp
.X_op
!= O_constant
|| exp
.X_add_number
& ~0xff)
15089 as_bad (_("invalid unwind opcode"));
15090 ignore_rest_of_line ();
15093 op
[count
++] = exp
.X_add_number
;
15095 /* Parse the next byte. */
15096 if (skip_past_comma (&input_line_pointer
) == FAIL
)
15102 /* Add the opcode bytes in reverse order. */
15104 add_unwind_opcode (op
[count
], 1);
15106 demand_empty_rest_of_line ();
15109 #endif /* OBJ_ELF */
15111 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
15112 of an rs_align_code fragment. */
15115 arm_handle_align (fragS
* fragP
)
15117 static char const arm_noop
[4] = { 0x00, 0x00, 0xa0, 0xe1 };
15118 static char const thumb_noop
[2] = { 0xc0, 0x46 };
15119 static char const arm_bigend_noop
[4] = { 0xe1, 0xa0, 0x00, 0x00 };
15120 static char const thumb_bigend_noop
[2] = { 0x46, 0xc0 };
15122 int bytes
, fix
, noop_size
;
15126 if (fragP
->fr_type
!= rs_align_code
)
15129 bytes
= fragP
->fr_next
->fr_address
- fragP
->fr_address
- fragP
->fr_fix
;
15130 p
= fragP
->fr_literal
+ fragP
->fr_fix
;
15133 if (bytes
> MAX_MEM_FOR_RS_ALIGN_CODE
)
15134 bytes
&= MAX_MEM_FOR_RS_ALIGN_CODE
;
15136 if (fragP
->tc_frag_data
)
15138 if (target_big_endian
)
15139 noop
= thumb_bigend_noop
;
15142 noop_size
= sizeof (thumb_noop
);
15146 if (target_big_endian
)
15147 noop
= arm_bigend_noop
;
15150 noop_size
= sizeof (arm_noop
);
15153 if (bytes
& (noop_size
- 1))
15155 fix
= bytes
& (noop_size
- 1);
15156 memset (p
, 0, fix
);
15161 while (bytes
>= noop_size
)
15163 memcpy (p
, noop
, noop_size
);
15165 bytes
-= noop_size
;
15169 fragP
->fr_fix
+= fix
;
15170 fragP
->fr_var
= noop_size
;
15173 /* Called from md_do_align. Used to create an alignment
15174 frag in a code section. */
15177 arm_frag_align_code (int n
, int max
)
15181 /* We assume that there will never be a requirement
15182 to support alignments greater than 32 bytes. */
15183 if (max
> MAX_MEM_FOR_RS_ALIGN_CODE
)
15184 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
15186 p
= frag_var (rs_align_code
,
15187 MAX_MEM_FOR_RS_ALIGN_CODE
,
15189 (relax_substateT
) max
,
15196 /* Perform target specific initialisation of a frag. */
15199 arm_init_frag (fragS
* fragP
)
15201 /* Record whether this frag is in an ARM or a THUMB area. */
15202 fragP
->tc_frag_data
= thumb_mode
;
15207 /* Convert REGNAME to a DWARF-2 register number. */
15210 tc_arm_regname_to_dw2regnum (const char *regname
)
15214 for (i
= 0; rn_table
[i
].name
; i
++)
15215 if (streq (regname
, rn_table
[i
].name
))
15216 return rn_table
[i
].number
;
15221 /* Initialize the DWARF-2 unwind information for this procedure. */
15224 tc_arm_frame_initial_instructions (void)
15226 cfi_add_CFA_def_cfa (REG_SP
, 0);
15230 /* This table describes all the machine specific pseudo-ops the assembler
15231 has to support. The fields are:
15232 pseudo-op name without dot
15233 function to call to execute this pseudo-op
15234 Integer arg to pass to the function. */
15236 const pseudo_typeS md_pseudo_table
[] =
15238 /* Never called because '.req' does not start a line. */
15239 { "req", s_req
, 0 },
15240 { "unreq", s_unreq
, 0 },
15241 { "bss", s_bss
, 0 },
15242 { "align", s_align
, 0 },
15243 { "arm", s_arm
, 0 },
15244 { "thumb", s_thumb
, 0 },
15245 { "code", s_code
, 0 },
15246 { "force_thumb", s_force_thumb
, 0 },
15247 { "thumb_func", s_thumb_func
, 0 },
15248 { "thumb_set", s_thumb_set
, 0 },
15249 { "even", s_even
, 0 },
15250 { "ltorg", s_ltorg
, 0 },
15251 { "pool", s_ltorg
, 0 },
15253 { "word", s_arm_elf_cons
, 4 },
15254 { "long", s_arm_elf_cons
, 4 },
15255 { "rel31", s_arm_rel31
, 0 },
15256 { "fnstart", s_arm_unwind_fnstart
, 0 },
15257 { "fnend", s_arm_unwind_fnend
, 0 },
15258 { "cantunwind", s_arm_unwind_cantunwind
, 0 },
15259 { "personality", s_arm_unwind_personality
, 0 },
15260 { "personalityindex", s_arm_unwind_personalityindex
, 0 },
15261 { "handlerdata", s_arm_unwind_handlerdata
, 0 },
15262 { "save", s_arm_unwind_save
, 0 },
15263 { "movsp", s_arm_unwind_movsp
, 0 },
15264 { "pad", s_arm_unwind_pad
, 0 },
15265 { "setfp", s_arm_unwind_setfp
, 0 },
15266 { "unwind_raw", s_arm_unwind_raw
, 0 },
15268 { "word", cons
, 4},
15270 { "extend", float_cons
, 'x' },
15271 { "ldouble", float_cons
, 'x' },
15272 { "packed", float_cons
, 'p' },