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;
162 static int meabi_flags
= EF_ARM_EABI_UNKNOWN
;
165 /* This array holds the chars that always start a comment. If the
166 pre-processor is disabled, these aren't very useful. */
167 const char comment_chars
[] = "@";
169 /* This array holds the chars that only start a comment at the beginning of
170 a line. If the line seems to have the form '# 123 filename'
171 .line and .file directives will appear in the pre-processed output. */
172 /* Note that input_file.c hand checks for '#' at the beginning of the
173 first line of the input file. This is because the compiler outputs
174 #NO_APP at the beginning of its output. */
175 /* Also note that comments like this one will always work. */
176 const char line_comment_chars
[] = "#";
178 const char line_separator_chars
[] = ";";
180 /* Chars that can be used to separate mant
181 from exp in floating point numbers. */
182 const char EXP_CHARS
[] = "eE";
184 /* Chars that mean this number is a floating point constant. */
188 const char FLT_CHARS
[] = "rRsSfFdDxXeEpP";
190 /* Prefix characters that indicate the start of an immediate
192 #define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
195 /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
196 symbolS
* GOT_symbol
;
199 /* Size of relocation record. */
200 const int md_reloc_size
= 8;
202 /* 0: assemble for ARM,
203 1: assemble for Thumb,
204 2: assemble for Thumb even though target CPU does not support thumb
206 static int thumb_mode
= 0;
208 typedef struct arm_fix
216 unsigned long instruction
;
220 bfd_reloc_code_real_type type
;
237 struct asm_shift_properties
239 enum asm_shift_index index
;
240 unsigned long bit_field
;
241 unsigned int allows_0
: 1;
242 unsigned int allows_32
: 1;
245 static const struct asm_shift_properties shift_properties
[] =
247 { SHIFT_LSL
, 0, 1, 0},
248 { SHIFT_LSR
, 0x20, 0, 1},
249 { SHIFT_ASR
, 0x40, 0, 1},
250 { SHIFT_ROR
, 0x60, 0, 0},
251 { SHIFT_RRX
, 0x60, 0, 0}
254 struct asm_shift_name
257 const struct asm_shift_properties
* properties
;
260 static const struct asm_shift_name shift_names
[] =
262 { "asl", shift_properties
+ SHIFT_LSL
},
263 { "lsl", shift_properties
+ SHIFT_LSL
},
264 { "lsr", shift_properties
+ SHIFT_LSR
},
265 { "asr", shift_properties
+ SHIFT_ASR
},
266 { "ror", shift_properties
+ SHIFT_ROR
},
267 { "rrx", shift_properties
+ SHIFT_RRX
},
268 { "ASL", shift_properties
+ SHIFT_LSL
},
269 { "LSL", shift_properties
+ SHIFT_LSL
},
270 { "LSR", shift_properties
+ SHIFT_LSR
},
271 { "ASR", shift_properties
+ SHIFT_ASR
},
272 { "ROR", shift_properties
+ SHIFT_ROR
},
273 { "RRX", shift_properties
+ SHIFT_RRX
}
276 /* Any kind of shift is accepted. */
277 #define NO_SHIFT_RESTRICT 1
278 /* The shift operand must be an immediate value, not a register. */
279 #define SHIFT_IMMEDIATE 0
280 /* The shift must be LSL or ASR and the operand must be an immediate. */
281 #define SHIFT_LSL_OR_ASR_IMMEDIATE 2
282 /* The shift must be ASR and the operand must be an immediate. */
283 #define SHIFT_ASR_IMMEDIATE 3
284 /* The shift must be LSL and the operand must be an immediate. */
285 #define SHIFT_LSL_IMMEDIATE 4
287 #define NUM_FLOAT_VALS 8
289 const char * fp_const
[] =
291 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
294 /* Number of littlenums required to hold an extended precision number. */
295 #define MAX_LITTLENUMS 6
297 LITTLENUM_TYPE fp_values
[NUM_FLOAT_VALS
][MAX_LITTLENUMS
];
302 /* Whether a Co-processor load/store operation accepts write-back forms. */
311 #define CP_T_X 0x00008000
312 #define CP_T_Y 0x00400000
313 #define CP_T_Pre 0x01000000
314 #define CP_T_UD 0x00800000
315 #define CP_T_WB 0x00200000
317 #define CONDS_BIT 0x00100000
318 #define LOAD_BIT 0x00100000
320 #define DOUBLE_LOAD_FLAG 0x00000001
324 const char * template;
328 #define COND_ALWAYS 0xe0000000
329 #define COND_MASK 0xf0000000
331 static const struct asm_cond conds
[] =
335 {"cs", 0x20000000}, {"hs", 0x20000000},
336 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
353 const char *template;
358 /* The bit that distinguishes CPSR and SPSR. */
359 #define SPSR_BIT (1 << 22)
361 /* How many bits to shift the PSR_xxx bits up by. */
364 #define PSR_c (1 << 0)
365 #define PSR_x (1 << 1)
366 #define PSR_s (1 << 2)
367 #define PSR_f (1 << 3)
369 static const struct asm_psr psrs
[] =
371 {"CPSR", TRUE
, PSR_c
| PSR_f
},
372 {"CPSR_all", TRUE
, PSR_c
| PSR_f
},
373 {"SPSR", FALSE
, PSR_c
| PSR_f
},
374 {"SPSR_all", FALSE
, PSR_c
| PSR_f
},
375 {"CPSR_flg", TRUE
, PSR_f
},
376 {"CPSR_f", TRUE
, PSR_f
},
377 {"SPSR_flg", FALSE
, PSR_f
},
378 {"SPSR_f", FALSE
, PSR_f
},
379 {"CPSR_c", TRUE
, PSR_c
},
380 {"CPSR_ctl", TRUE
, PSR_c
},
381 {"SPSR_c", FALSE
, PSR_c
},
382 {"SPSR_ctl", FALSE
, PSR_c
},
383 {"CPSR_x", TRUE
, PSR_x
},
384 {"CPSR_s", TRUE
, PSR_s
},
385 {"SPSR_x", FALSE
, PSR_x
},
386 {"SPSR_s", FALSE
, PSR_s
},
387 /* Combinations of flags. */
388 {"CPSR_fs", TRUE
, PSR_f
| PSR_s
},
389 {"CPSR_fx", TRUE
, PSR_f
| PSR_x
},
390 {"CPSR_fc", TRUE
, PSR_f
| PSR_c
},
391 {"CPSR_sf", TRUE
, PSR_s
| PSR_f
},
392 {"CPSR_sx", TRUE
, PSR_s
| PSR_x
},
393 {"CPSR_sc", TRUE
, PSR_s
| PSR_c
},
394 {"CPSR_xf", TRUE
, PSR_x
| PSR_f
},
395 {"CPSR_xs", TRUE
, PSR_x
| PSR_s
},
396 {"CPSR_xc", TRUE
, PSR_x
| PSR_c
},
397 {"CPSR_cf", TRUE
, PSR_c
| PSR_f
},
398 {"CPSR_cs", TRUE
, PSR_c
| PSR_s
},
399 {"CPSR_cx", TRUE
, PSR_c
| PSR_x
},
400 {"CPSR_fsx", TRUE
, PSR_f
| PSR_s
| PSR_x
},
401 {"CPSR_fsc", TRUE
, PSR_f
| PSR_s
| PSR_c
},
402 {"CPSR_fxs", TRUE
, PSR_f
| PSR_x
| PSR_s
},
403 {"CPSR_fxc", TRUE
, PSR_f
| PSR_x
| PSR_c
},
404 {"CPSR_fcs", TRUE
, PSR_f
| PSR_c
| PSR_s
},
405 {"CPSR_fcx", TRUE
, PSR_f
| PSR_c
| PSR_x
},
406 {"CPSR_sfx", TRUE
, PSR_s
| PSR_f
| PSR_x
},
407 {"CPSR_sfc", TRUE
, PSR_s
| PSR_f
| PSR_c
},
408 {"CPSR_sxf", TRUE
, PSR_s
| PSR_x
| PSR_f
},
409 {"CPSR_sxc", TRUE
, PSR_s
| PSR_x
| PSR_c
},
410 {"CPSR_scf", TRUE
, PSR_s
| PSR_c
| PSR_f
},
411 {"CPSR_scx", TRUE
, PSR_s
| PSR_c
| PSR_x
},
412 {"CPSR_xfs", TRUE
, PSR_x
| PSR_f
| PSR_s
},
413 {"CPSR_xfc", TRUE
, PSR_x
| PSR_f
| PSR_c
},
414 {"CPSR_xsf", TRUE
, PSR_x
| PSR_s
| PSR_f
},
415 {"CPSR_xsc", TRUE
, PSR_x
| PSR_s
| PSR_c
},
416 {"CPSR_xcf", TRUE
, PSR_x
| PSR_c
| PSR_f
},
417 {"CPSR_xcs", TRUE
, PSR_x
| PSR_c
| PSR_s
},
418 {"CPSR_cfs", TRUE
, PSR_c
| PSR_f
| PSR_s
},
419 {"CPSR_cfx", TRUE
, PSR_c
| PSR_f
| PSR_x
},
420 {"CPSR_csf", TRUE
, PSR_c
| PSR_s
| PSR_f
},
421 {"CPSR_csx", TRUE
, PSR_c
| PSR_s
| PSR_x
},
422 {"CPSR_cxf", TRUE
, PSR_c
| PSR_x
| PSR_f
},
423 {"CPSR_cxs", TRUE
, PSR_c
| PSR_x
| PSR_s
},
424 {"CPSR_fsxc", TRUE
, PSR_f
| PSR_s
| PSR_x
| PSR_c
},
425 {"CPSR_fscx", TRUE
, PSR_f
| PSR_s
| PSR_c
| PSR_x
},
426 {"CPSR_fxsc", TRUE
, PSR_f
| PSR_x
| PSR_s
| PSR_c
},
427 {"CPSR_fxcs", TRUE
, PSR_f
| PSR_x
| PSR_c
| PSR_s
},
428 {"CPSR_fcsx", TRUE
, PSR_f
| PSR_c
| PSR_s
| PSR_x
},
429 {"CPSR_fcxs", TRUE
, PSR_f
| PSR_c
| PSR_x
| PSR_s
},
430 {"CPSR_sfxc", TRUE
, PSR_s
| PSR_f
| PSR_x
| PSR_c
},
431 {"CPSR_sfcx", TRUE
, PSR_s
| PSR_f
| PSR_c
| PSR_x
},
432 {"CPSR_sxfc", TRUE
, PSR_s
| PSR_x
| PSR_f
| PSR_c
},
433 {"CPSR_sxcf", TRUE
, PSR_s
| PSR_x
| PSR_c
| PSR_f
},
434 {"CPSR_scfx", TRUE
, PSR_s
| PSR_c
| PSR_f
| PSR_x
},
435 {"CPSR_scxf", TRUE
, PSR_s
| PSR_c
| PSR_x
| PSR_f
},
436 {"CPSR_xfsc", TRUE
, PSR_x
| PSR_f
| PSR_s
| PSR_c
},
437 {"CPSR_xfcs", TRUE
, PSR_x
| PSR_f
| PSR_c
| PSR_s
},
438 {"CPSR_xsfc", TRUE
, PSR_x
| PSR_s
| PSR_f
| PSR_c
},
439 {"CPSR_xscf", TRUE
, PSR_x
| PSR_s
| PSR_c
| PSR_f
},
440 {"CPSR_xcfs", TRUE
, PSR_x
| PSR_c
| PSR_f
| PSR_s
},
441 {"CPSR_xcsf", TRUE
, PSR_x
| PSR_c
| PSR_s
| PSR_f
},
442 {"CPSR_cfsx", TRUE
, PSR_c
| PSR_f
| PSR_s
| PSR_x
},
443 {"CPSR_cfxs", TRUE
, PSR_c
| PSR_f
| PSR_x
| PSR_s
},
444 {"CPSR_csfx", TRUE
, PSR_c
| PSR_s
| PSR_f
| PSR_x
},
445 {"CPSR_csxf", TRUE
, PSR_c
| PSR_s
| PSR_x
| PSR_f
},
446 {"CPSR_cxfs", TRUE
, PSR_c
| PSR_x
| PSR_f
| PSR_s
},
447 {"CPSR_cxsf", TRUE
, PSR_c
| PSR_x
| PSR_s
| PSR_f
},
448 {"SPSR_fs", FALSE
, PSR_f
| PSR_s
},
449 {"SPSR_fx", FALSE
, PSR_f
| PSR_x
},
450 {"SPSR_fc", FALSE
, PSR_f
| PSR_c
},
451 {"SPSR_sf", FALSE
, PSR_s
| PSR_f
},
452 {"SPSR_sx", FALSE
, PSR_s
| PSR_x
},
453 {"SPSR_sc", FALSE
, PSR_s
| PSR_c
},
454 {"SPSR_xf", FALSE
, PSR_x
| PSR_f
},
455 {"SPSR_xs", FALSE
, PSR_x
| PSR_s
},
456 {"SPSR_xc", FALSE
, PSR_x
| PSR_c
},
457 {"SPSR_cf", FALSE
, PSR_c
| PSR_f
},
458 {"SPSR_cs", FALSE
, PSR_c
| PSR_s
},
459 {"SPSR_cx", FALSE
, PSR_c
| PSR_x
},
460 {"SPSR_fsx", FALSE
, PSR_f
| PSR_s
| PSR_x
},
461 {"SPSR_fsc", FALSE
, PSR_f
| PSR_s
| PSR_c
},
462 {"SPSR_fxs", FALSE
, PSR_f
| PSR_x
| PSR_s
},
463 {"SPSR_fxc", FALSE
, PSR_f
| PSR_x
| PSR_c
},
464 {"SPSR_fcs", FALSE
, PSR_f
| PSR_c
| PSR_s
},
465 {"SPSR_fcx", FALSE
, PSR_f
| PSR_c
| PSR_x
},
466 {"SPSR_sfx", FALSE
, PSR_s
| PSR_f
| PSR_x
},
467 {"SPSR_sfc", FALSE
, PSR_s
| PSR_f
| PSR_c
},
468 {"SPSR_sxf", FALSE
, PSR_s
| PSR_x
| PSR_f
},
469 {"SPSR_sxc", FALSE
, PSR_s
| PSR_x
| PSR_c
},
470 {"SPSR_scf", FALSE
, PSR_s
| PSR_c
| PSR_f
},
471 {"SPSR_scx", FALSE
, PSR_s
| PSR_c
| PSR_x
},
472 {"SPSR_xfs", FALSE
, PSR_x
| PSR_f
| PSR_s
},
473 {"SPSR_xfc", FALSE
, PSR_x
| PSR_f
| PSR_c
},
474 {"SPSR_xsf", FALSE
, PSR_x
| PSR_s
| PSR_f
},
475 {"SPSR_xsc", FALSE
, PSR_x
| PSR_s
| PSR_c
},
476 {"SPSR_xcf", FALSE
, PSR_x
| PSR_c
| PSR_f
},
477 {"SPSR_xcs", FALSE
, PSR_x
| PSR_c
| PSR_s
},
478 {"SPSR_cfs", FALSE
, PSR_c
| PSR_f
| PSR_s
},
479 {"SPSR_cfx", FALSE
, PSR_c
| PSR_f
| PSR_x
},
480 {"SPSR_csf", FALSE
, PSR_c
| PSR_s
| PSR_f
},
481 {"SPSR_csx", FALSE
, PSR_c
| PSR_s
| PSR_x
},
482 {"SPSR_cxf", FALSE
, PSR_c
| PSR_x
| PSR_f
},
483 {"SPSR_cxs", FALSE
, PSR_c
| PSR_x
| PSR_s
},
484 {"SPSR_fsxc", FALSE
, PSR_f
| PSR_s
| PSR_x
| PSR_c
},
485 {"SPSR_fscx", FALSE
, PSR_f
| PSR_s
| PSR_c
| PSR_x
},
486 {"SPSR_fxsc", FALSE
, PSR_f
| PSR_x
| PSR_s
| PSR_c
},
487 {"SPSR_fxcs", FALSE
, PSR_f
| PSR_x
| PSR_c
| PSR_s
},
488 {"SPSR_fcsx", FALSE
, PSR_f
| PSR_c
| PSR_s
| PSR_x
},
489 {"SPSR_fcxs", FALSE
, PSR_f
| PSR_c
| PSR_x
| PSR_s
},
490 {"SPSR_sfxc", FALSE
, PSR_s
| PSR_f
| PSR_x
| PSR_c
},
491 {"SPSR_sfcx", FALSE
, PSR_s
| PSR_f
| PSR_c
| PSR_x
},
492 {"SPSR_sxfc", FALSE
, PSR_s
| PSR_x
| PSR_f
| PSR_c
},
493 {"SPSR_sxcf", FALSE
, PSR_s
| PSR_x
| PSR_c
| PSR_f
},
494 {"SPSR_scfx", FALSE
, PSR_s
| PSR_c
| PSR_f
| PSR_x
},
495 {"SPSR_scxf", FALSE
, PSR_s
| PSR_c
| PSR_x
| PSR_f
},
496 {"SPSR_xfsc", FALSE
, PSR_x
| PSR_f
| PSR_s
| PSR_c
},
497 {"SPSR_xfcs", FALSE
, PSR_x
| PSR_f
| PSR_c
| PSR_s
},
498 {"SPSR_xsfc", FALSE
, PSR_x
| PSR_s
| PSR_f
| PSR_c
},
499 {"SPSR_xscf", FALSE
, PSR_x
| PSR_s
| PSR_c
| PSR_f
},
500 {"SPSR_xcfs", FALSE
, PSR_x
| PSR_c
| PSR_f
| PSR_s
},
501 {"SPSR_xcsf", FALSE
, PSR_x
| PSR_c
| PSR_s
| PSR_f
},
502 {"SPSR_cfsx", FALSE
, PSR_c
| PSR_f
| PSR_s
| PSR_x
},
503 {"SPSR_cfxs", FALSE
, PSR_c
| PSR_f
| PSR_x
| PSR_s
},
504 {"SPSR_csfx", FALSE
, PSR_c
| PSR_s
| PSR_f
| PSR_x
},
505 {"SPSR_csxf", FALSE
, PSR_c
| PSR_s
| PSR_x
| PSR_f
},
506 {"SPSR_cxfs", FALSE
, PSR_c
| PSR_x
| PSR_f
| PSR_s
},
507 {"SPSR_cxsf", FALSE
, PSR_c
| PSR_x
| PSR_s
| PSR_f
},
514 IWMMXT_REG_WR_OR_WC
= 2,
518 enum iwmmxt_insn_type
541 VFP_REG_Dd
, VFP_REG_Dm
, VFP_REG_Dn
546 VFP_REG_Sd
, VFP_REG_Sm
, VFP_REG_Sn
551 VFP_LDSTMIA
, VFP_LDSTMDB
, VFP_LDSTMIAX
, VFP_LDSTMDBX
554 /* VFP system registers. */
561 static const struct vfp_reg vfp_regs
[] =
563 {"fpsid", 0x00000000},
564 {"FPSID", 0x00000000},
565 {"fpscr", 0x00010000},
566 {"FPSCR", 0x00010000},
567 {"fpexc", 0x00080000},
568 {"FPEXC", 0x00080000}
571 /* Structure for a hash table entry for a register. */
579 /* Some well known registers that we refer to directly elsewhere. */
584 #define wr_register(reg) ((reg ^ WR_PREFIX) >= 0 && (reg ^ WR_PREFIX) <= 15)
585 #define wc_register(reg) ((reg ^ WC_PREFIX) >= 0 && (reg ^ WC_PREFIX) <= 15)
586 #define wcg_register(reg) ((reg ^ WC_PREFIX) >= 8 && (reg ^ WC_PREFIX) <= 11)
588 /* These are the standard names. Users can add aliases with .req.
589 and delete them with .unreq. */
591 /* Integer Register Numbers. */
592 static const struct reg_entry rn_table
[] =
594 {"r0", 0, TRUE
}, {"r1", 1, TRUE
}, {"r2", 2, TRUE
}, {"r3", 3, TRUE
},
595 {"r4", 4, TRUE
}, {"r5", 5, TRUE
}, {"r6", 6, TRUE
}, {"r7", 7, TRUE
},
596 {"r8", 8, TRUE
}, {"r9", 9, TRUE
}, {"r10", 10, TRUE
}, {"r11", 11, TRUE
},
597 {"r12", 12, TRUE
}, {"r13", REG_SP
, TRUE
}, {"r14", REG_LR
, TRUE
}, {"r15", REG_PC
, TRUE
},
598 /* ATPCS Synonyms. */
599 {"a1", 0, TRUE
}, {"a2", 1, TRUE
}, {"a3", 2, TRUE
}, {"a4", 3, TRUE
},
600 {"v1", 4, TRUE
}, {"v2", 5, TRUE
}, {"v3", 6, TRUE
}, {"v4", 7, TRUE
},
601 {"v5", 8, TRUE
}, {"v6", 9, TRUE
}, {"v7", 10, TRUE
}, {"v8", 11, TRUE
},
602 /* Well-known aliases. */
603 {"wr", 7, TRUE
}, {"sb", 9, TRUE
}, {"sl", 10, TRUE
}, {"fp", 11, TRUE
},
604 {"ip", 12, TRUE
}, {"sp", REG_SP
, TRUE
}, {"lr", REG_LR
, TRUE
}, {"pc", REG_PC
, TRUE
},
608 #define WR_PREFIX 0x200
609 #define WC_PREFIX 0x400
611 static const struct reg_entry iwmmxt_table
[] =
613 /* Intel Wireless MMX technology register names. */
614 { "wr0", 0x0 | WR_PREFIX
, TRUE
}, {"wr1", 0x1 | WR_PREFIX
, TRUE
},
615 { "wr2", 0x2 | WR_PREFIX
, TRUE
}, {"wr3", 0x3 | WR_PREFIX
, TRUE
},
616 { "wr4", 0x4 | WR_PREFIX
, TRUE
}, {"wr5", 0x5 | WR_PREFIX
, TRUE
},
617 { "wr6", 0x6 | WR_PREFIX
, TRUE
}, {"wr7", 0x7 | WR_PREFIX
, TRUE
},
618 { "wr8", 0x8 | WR_PREFIX
, TRUE
}, {"wr9", 0x9 | WR_PREFIX
, TRUE
},
619 { "wr10", 0xa | WR_PREFIX
, TRUE
}, {"wr11", 0xb | WR_PREFIX
, TRUE
},
620 { "wr12", 0xc | WR_PREFIX
, TRUE
}, {"wr13", 0xd | WR_PREFIX
, TRUE
},
621 { "wr14", 0xe | WR_PREFIX
, TRUE
}, {"wr15", 0xf | WR_PREFIX
, TRUE
},
622 { "wcid", 0x0 | WC_PREFIX
, TRUE
}, {"wcon", 0x1 | WC_PREFIX
, TRUE
},
623 {"wcssf", 0x2 | WC_PREFIX
, TRUE
}, {"wcasf", 0x3 | WC_PREFIX
, TRUE
},
624 {"wcgr0", 0x8 | WC_PREFIX
, TRUE
}, {"wcgr1", 0x9 | WC_PREFIX
, TRUE
},
625 {"wcgr2", 0xa | WC_PREFIX
, TRUE
}, {"wcgr3", 0xb | WC_PREFIX
, TRUE
},
627 { "wR0", 0x0 | WR_PREFIX
, TRUE
}, {"wR1", 0x1 | WR_PREFIX
, TRUE
},
628 { "wR2", 0x2 | WR_PREFIX
, TRUE
}, {"wR3", 0x3 | WR_PREFIX
, TRUE
},
629 { "wR4", 0x4 | WR_PREFIX
, TRUE
}, {"wR5", 0x5 | WR_PREFIX
, TRUE
},
630 { "wR6", 0x6 | WR_PREFIX
, TRUE
}, {"wR7", 0x7 | WR_PREFIX
, TRUE
},
631 { "wR8", 0x8 | WR_PREFIX
, TRUE
}, {"wR9", 0x9 | WR_PREFIX
, TRUE
},
632 { "wR10", 0xa | WR_PREFIX
, TRUE
}, {"wR11", 0xb | WR_PREFIX
, TRUE
},
633 { "wR12", 0xc | WR_PREFIX
, TRUE
}, {"wR13", 0xd | WR_PREFIX
, TRUE
},
634 { "wR14", 0xe | WR_PREFIX
, TRUE
}, {"wR15", 0xf | WR_PREFIX
, TRUE
},
635 { "wCID", 0x0 | WC_PREFIX
, TRUE
}, {"wCon", 0x1 | WC_PREFIX
, TRUE
},
636 {"wCSSF", 0x2 | WC_PREFIX
, TRUE
}, {"wCASF", 0x3 | WC_PREFIX
, TRUE
},
637 {"wCGR0", 0x8 | WC_PREFIX
, TRUE
}, {"wCGR1", 0x9 | WC_PREFIX
, TRUE
},
638 {"wCGR2", 0xa | WC_PREFIX
, TRUE
}, {"wCGR3", 0xb | WC_PREFIX
, TRUE
},
642 /* Co-processor Numbers. */
643 static const struct reg_entry cp_table
[] =
645 {"p0", 0, TRUE
}, {"p1", 1, TRUE
}, {"p2", 2, TRUE
}, {"p3", 3, TRUE
},
646 {"p4", 4, TRUE
}, {"p5", 5, TRUE
}, {"p6", 6, TRUE
}, {"p7", 7, TRUE
},
647 {"p8", 8, TRUE
}, {"p9", 9, TRUE
}, {"p10", 10, TRUE
}, {"p11", 11, TRUE
},
648 {"p12", 12, TRUE
}, {"p13", 13, TRUE
}, {"p14", 14, TRUE
}, {"p15", 15, TRUE
},
652 /* Co-processor Register Numbers. */
653 static const struct reg_entry cn_table
[] =
655 {"c0", 0, TRUE
}, {"c1", 1, TRUE
}, {"c2", 2, TRUE
}, {"c3", 3, TRUE
},
656 {"c4", 4, TRUE
}, {"c5", 5, TRUE
}, {"c6", 6, TRUE
}, {"c7", 7, TRUE
},
657 {"c8", 8, TRUE
}, {"c9", 9, TRUE
}, {"c10", 10, TRUE
}, {"c11", 11, TRUE
},
658 {"c12", 12, TRUE
}, {"c13", 13, TRUE
}, {"c14", 14, TRUE
}, {"c15", 15, TRUE
},
659 /* Not really valid, but kept for back-wards compatibility. */
660 {"cr0", 0, TRUE
}, {"cr1", 1, TRUE
}, {"cr2", 2, TRUE
}, {"cr3", 3, TRUE
},
661 {"cr4", 4, TRUE
}, {"cr5", 5, TRUE
}, {"cr6", 6, TRUE
}, {"cr7", 7, TRUE
},
662 {"cr8", 8, TRUE
}, {"cr9", 9, TRUE
}, {"cr10", 10, TRUE
}, {"cr11", 11, TRUE
},
663 {"cr12", 12, TRUE
}, {"cr13", 13, TRUE
}, {"cr14", 14, TRUE
}, {"cr15", 15, TRUE
},
668 static const struct reg_entry fn_table
[] =
670 {"f0", 0, TRUE
}, {"f1", 1, TRUE
}, {"f2", 2, TRUE
}, {"f3", 3, TRUE
},
671 {"f4", 4, TRUE
}, {"f5", 5, TRUE
}, {"f6", 6, TRUE
}, {"f7", 7, TRUE
},
675 /* VFP SP Registers. */
676 static const struct reg_entry sn_table
[] =
678 {"s0", 0, TRUE
}, {"s1", 1, TRUE
}, {"s2", 2, TRUE
}, {"s3", 3, TRUE
},
679 {"s4", 4, TRUE
}, {"s5", 5, TRUE
}, {"s6", 6, TRUE
}, {"s7", 7, TRUE
},
680 {"s8", 8, TRUE
}, {"s9", 9, TRUE
}, {"s10", 10, TRUE
}, {"s11", 11, TRUE
},
681 {"s12", 12, TRUE
}, {"s13", 13, TRUE
}, {"s14", 14, TRUE
}, {"s15", 15, TRUE
},
682 {"s16", 16, TRUE
}, {"s17", 17, TRUE
}, {"s18", 18, TRUE
}, {"s19", 19, TRUE
},
683 {"s20", 20, TRUE
}, {"s21", 21, TRUE
}, {"s22", 22, TRUE
}, {"s23", 23, TRUE
},
684 {"s24", 24, TRUE
}, {"s25", 25, TRUE
}, {"s26", 26, TRUE
}, {"s27", 27, TRUE
},
685 {"s28", 28, TRUE
}, {"s29", 29, TRUE
}, {"s30", 30, TRUE
}, {"s31", 31, TRUE
},
689 /* VFP DP Registers. */
690 static const struct reg_entry dn_table
[] =
692 {"d0", 0, TRUE
}, {"d1", 1, TRUE
}, {"d2", 2, TRUE
}, {"d3", 3, TRUE
},
693 {"d4", 4, TRUE
}, {"d5", 5, TRUE
}, {"d6", 6, TRUE
}, {"d7", 7, TRUE
},
694 {"d8", 8, TRUE
}, {"d9", 9, TRUE
}, {"d10", 10, TRUE
}, {"d11", 11, TRUE
},
695 {"d12", 12, TRUE
}, {"d13", 13, TRUE
}, {"d14", 14, TRUE
}, {"d15", 15, TRUE
},
699 /* Maverick DSP coprocessor registers. */
700 static const struct reg_entry mav_mvf_table
[] =
702 {"mvf0", 0, TRUE
}, {"mvf1", 1, TRUE
}, {"mvf2", 2, TRUE
}, {"mvf3", 3, TRUE
},
703 {"mvf4", 4, TRUE
}, {"mvf5", 5, TRUE
}, {"mvf6", 6, TRUE
}, {"mvf7", 7, TRUE
},
704 {"mvf8", 8, TRUE
}, {"mvf9", 9, TRUE
}, {"mvf10", 10, TRUE
}, {"mvf11", 11, TRUE
},
705 {"mvf12", 12, TRUE
}, {"mvf13", 13, TRUE
}, {"mvf14", 14, TRUE
}, {"mvf15", 15, TRUE
},
709 static const struct reg_entry mav_mvd_table
[] =
711 {"mvd0", 0, TRUE
}, {"mvd1", 1, TRUE
}, {"mvd2", 2, TRUE
}, {"mvd3", 3, TRUE
},
712 {"mvd4", 4, TRUE
}, {"mvd5", 5, TRUE
}, {"mvd6", 6, TRUE
}, {"mvd7", 7, TRUE
},
713 {"mvd8", 8, TRUE
}, {"mvd9", 9, TRUE
}, {"mvd10", 10, TRUE
}, {"mvd11", 11, TRUE
},
714 {"mvd12", 12, TRUE
}, {"mvd13", 13, TRUE
}, {"mvd14", 14, TRUE
}, {"mvd15", 15, TRUE
},
718 static const struct reg_entry mav_mvfx_table
[] =
720 {"mvfx0", 0, TRUE
}, {"mvfx1", 1, TRUE
}, {"mvfx2", 2, TRUE
}, {"mvfx3", 3, TRUE
},
721 {"mvfx4", 4, TRUE
}, {"mvfx5", 5, TRUE
}, {"mvfx6", 6, TRUE
}, {"mvfx7", 7, TRUE
},
722 {"mvfx8", 8, TRUE
}, {"mvfx9", 9, TRUE
}, {"mvfx10", 10, TRUE
}, {"mvfx11", 11, TRUE
},
723 {"mvfx12", 12, TRUE
}, {"mvfx13", 13, TRUE
}, {"mvfx14", 14, TRUE
}, {"mvfx15", 15, TRUE
},
727 static const struct reg_entry mav_mvdx_table
[] =
729 {"mvdx0", 0, TRUE
}, {"mvdx1", 1, TRUE
}, {"mvdx2", 2, TRUE
}, {"mvdx3", 3, TRUE
},
730 {"mvdx4", 4, TRUE
}, {"mvdx5", 5, TRUE
}, {"mvdx6", 6, TRUE
}, {"mvdx7", 7, TRUE
},
731 {"mvdx8", 8, TRUE
}, {"mvdx9", 9, TRUE
}, {"mvdx10", 10, TRUE
}, {"mvdx11", 11, TRUE
},
732 {"mvdx12", 12, TRUE
}, {"mvdx13", 13, TRUE
}, {"mvdx14", 14, TRUE
}, {"mvdx15", 15, TRUE
},
736 static const struct reg_entry mav_mvax_table
[] =
738 {"mvax0", 0, TRUE
}, {"mvax1", 1, TRUE
}, {"mvax2", 2, TRUE
}, {"mvax3", 3, TRUE
},
742 static const struct reg_entry mav_dspsc_table
[] =
750 const struct reg_entry
* names
;
752 struct hash_control
* htab
;
753 const char * expected
;
756 struct reg_map all_reg_maps
[] =
758 {rn_table
, 15, NULL
, N_("ARM register expected")},
759 {cp_table
, 15, NULL
, N_("bad or missing co-processor number")},
760 {cn_table
, 15, NULL
, N_("co-processor register expected")},
761 {fn_table
, 7, NULL
, N_("FPA register expected")},
762 {sn_table
, 31, NULL
, N_("VFP single precision register expected")},
763 {dn_table
, 15, NULL
, N_("VFP double precision register expected")},
764 {mav_mvf_table
, 15, NULL
, N_("Maverick MVF register expected")},
765 {mav_mvd_table
, 15, NULL
, N_("Maverick MVD register expected")},
766 {mav_mvfx_table
, 15, NULL
, N_("Maverick MVFX register expected")},
767 {mav_mvdx_table
, 15, NULL
, N_("Maverick MVDX register expected")},
768 {mav_mvax_table
, 3, NULL
, N_("Maverick MVAX register expected")},
769 {mav_dspsc_table
, 0, NULL
, N_("Maverick DSPSC register expected")},
770 {iwmmxt_table
, 23, NULL
, N_("Intel Wireless MMX technology register expected")},
773 /* Enumeration matching entries in table above. */
777 #define REG_TYPE_FIRST REG_TYPE_RN
789 REG_TYPE_IWMMXT
= 12,
794 /* ARM instructions take 4bytes in the object file, Thumb instructions
798 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
799 #define MAV_MODE1 0x100c
801 /* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
802 #define MAV_MODE2 0x0c10
804 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
805 #define MAV_MODE3 0x100c
807 /* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
808 #define MAV_MODE4 0x0c0010
810 /* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
811 #define MAV_MODE5 0x00100c
813 /* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
814 #define MAV_MODE6 0x00100c05
818 /* Basic string to match. */
819 const char * template;
821 /* Basic instruction code. */
824 /* Offset into the template where the condition code (if any) will be.
825 If zero, then the instruction is never conditional. */
826 unsigned cond_offset
;
828 /* Which architecture variant provides this instruction. */
829 unsigned long variant
;
831 /* Function to call to parse args. */
832 void (* parms
) (char *);
835 /* Defines for various bits that we will want to toggle. */
836 #define INST_IMMEDIATE 0x02000000
837 #define OFFSET_REG 0x02000000
838 #define HWOFFSET_IMM 0x00400000
839 #define SHIFT_BY_REG 0x00000010
840 #define PRE_INDEX 0x01000000
841 #define INDEX_UP 0x00800000
842 #define WRITE_BACK 0x00200000
843 #define LDM_TYPE_2_OR_3 0x00400000
845 #define LITERAL_MASK 0xf000f000
846 #define OPCODE_MASK 0xfe1fffff
847 #define V4_STR_BIT 0x00000020
849 #define DATA_OP_SHIFT 21
851 /* Codes to distinguish the arithmetic instructions. */
862 #define OPCODE_CMP 10
863 #define OPCODE_CMN 11
864 #define OPCODE_ORR 12
865 #define OPCODE_MOV 13
866 #define OPCODE_BIC 14
867 #define OPCODE_MVN 15
869 #define T_OPCODE_MUL 0x4340
870 #define T_OPCODE_TST 0x4200
871 #define T_OPCODE_CMN 0x42c0
872 #define T_OPCODE_NEG 0x4240
873 #define T_OPCODE_MVN 0x43c0
875 #define T_OPCODE_ADD_R3 0x1800
876 #define T_OPCODE_SUB_R3 0x1a00
877 #define T_OPCODE_ADD_HI 0x4400
878 #define T_OPCODE_ADD_ST 0xb000
879 #define T_OPCODE_SUB_ST 0xb080
880 #define T_OPCODE_ADD_SP 0xa800
881 #define T_OPCODE_ADD_PC 0xa000
882 #define T_OPCODE_ADD_I8 0x3000
883 #define T_OPCODE_SUB_I8 0x3800
884 #define T_OPCODE_ADD_I3 0x1c00
885 #define T_OPCODE_SUB_I3 0x1e00
887 #define T_OPCODE_ASR_R 0x4100
888 #define T_OPCODE_LSL_R 0x4080
889 #define T_OPCODE_LSR_R 0x40c0
890 #define T_OPCODE_ASR_I 0x1000
891 #define T_OPCODE_LSL_I 0x0000
892 #define T_OPCODE_LSR_I 0x0800
894 #define T_OPCODE_MOV_I8 0x2000
895 #define T_OPCODE_CMP_I8 0x2800
896 #define T_OPCODE_CMP_LR 0x4280
897 #define T_OPCODE_MOV_HR 0x4600
898 #define T_OPCODE_CMP_HR 0x4500
900 #define T_OPCODE_LDR_PC 0x4800
901 #define T_OPCODE_LDR_SP 0x9800
902 #define T_OPCODE_STR_SP 0x9000
903 #define T_OPCODE_LDR_IW 0x6800
904 #define T_OPCODE_STR_IW 0x6000
905 #define T_OPCODE_LDR_IH 0x8800
906 #define T_OPCODE_STR_IH 0x8000
907 #define T_OPCODE_LDR_IB 0x7800
908 #define T_OPCODE_STR_IB 0x7000
909 #define T_OPCODE_LDR_RW 0x5800
910 #define T_OPCODE_STR_RW 0x5000
911 #define T_OPCODE_LDR_RH 0x5a00
912 #define T_OPCODE_STR_RH 0x5200
913 #define T_OPCODE_LDR_RB 0x5c00
914 #define T_OPCODE_STR_RB 0x5400
916 #define T_OPCODE_PUSH 0xb400
917 #define T_OPCODE_POP 0xbc00
919 #define T_OPCODE_BRANCH 0xe7fe
921 #define THUMB_SIZE 2 /* Size of thumb instruction. */
922 #define THUMB_REG_LO 0x1
923 #define THUMB_REG_HI 0x2
924 #define THUMB_REG_ANY 0x3
926 #define THUMB_H1 0x0080
927 #define THUMB_H2 0x0040
934 #define THUMB_COMPARE 1
938 #define THUMB_STORE 1
940 #define THUMB_PP_PC_LR 0x0100
942 /* These three are used for immediate shifts, do not alter. */
944 #define THUMB_HALFWORD 1
949 /* Basic string to match. */
950 const char * template;
952 /* Basic instruction code. */
957 /* Which CPU variants this exists for. */
958 unsigned long variant
;
960 /* Function to call to parse args. */
961 void (* parms
) (char *);
964 #define BAD_ARGS _("bad arguments to instruction")
965 #define BAD_PC _("r15 not allowed here")
966 #define BAD_COND _("instruction is not conditional")
967 #define ERR_NO_ACCUM _("acc0 expected")
969 static struct hash_control
* arm_ops_hsh
= NULL
;
970 static struct hash_control
* arm_tops_hsh
= NULL
;
971 static struct hash_control
* arm_cond_hsh
= NULL
;
972 static struct hash_control
* arm_shift_hsh
= NULL
;
973 static struct hash_control
* arm_psr_hsh
= NULL
;
975 /* Stuff needed to resolve the label ambiguity
985 symbolS
* last_label_seen
;
986 static int label_is_thumb_function_name
= FALSE
;
988 /* Literal Pool stuff. */
990 #define MAX_LITERAL_POOL_SIZE 1024
992 /* Literal pool structure. Held on a per-section
993 and per-sub-section basis. */
995 typedef struct literal_pool
997 expressionS literals
[MAX_LITERAL_POOL_SIZE
];
998 unsigned int next_free_entry
;
1002 subsegT sub_section
;
1003 struct literal_pool
* next
;
1006 /* Pointer to a linked list of literal pools. */
1007 literal_pool
* list_of_pools
= NULL
;
1009 static literal_pool
*
1010 find_literal_pool (void)
1012 literal_pool
* pool
;
1014 for (pool
= list_of_pools
; pool
!= NULL
; pool
= pool
->next
)
1016 if (pool
->section
== now_seg
1017 && pool
->sub_section
== now_subseg
)
1024 static literal_pool
*
1025 find_or_make_literal_pool (void)
1027 /* Next literal pool ID number. */
1028 static unsigned int latest_pool_num
= 1;
1029 literal_pool
* pool
;
1031 pool
= find_literal_pool ();
1035 /* Create a new pool. */
1036 pool
= xmalloc (sizeof (* pool
));
1040 pool
->next_free_entry
= 0;
1041 pool
->section
= now_seg
;
1042 pool
->sub_section
= now_subseg
;
1043 pool
->next
= list_of_pools
;
1044 pool
->symbol
= NULL
;
1046 /* Add it to the list. */
1047 list_of_pools
= pool
;
1050 /* New pools, and emptied pools, will have a NULL symbol. */
1051 if (pool
->symbol
== NULL
)
1053 pool
->symbol
= symbol_create (FAKE_LABEL_NAME
, undefined_section
,
1054 (valueT
) 0, &zero_address_frag
);
1055 pool
->id
= latest_pool_num
++;
1062 /* Add the literal in the global 'inst'
1063 structure to the relevent literal pool. */
1066 add_to_lit_pool (void)
1068 literal_pool
* pool
;
1071 pool
= find_or_make_literal_pool ();
1073 /* Check if this literal value is already in the pool. */
1074 for (entry
= 0; entry
< pool
->next_free_entry
; entry
++)
1076 if ((pool
->literals
[entry
].X_op
== inst
.reloc
.exp
.X_op
)
1077 && (inst
.reloc
.exp
.X_op
== O_constant
)
1078 && (pool
->literals
[entry
].X_add_number
1079 == inst
.reloc
.exp
.X_add_number
)
1080 && (pool
->literals
[entry
].X_unsigned
1081 == inst
.reloc
.exp
.X_unsigned
))
1084 if ((pool
->literals
[entry
].X_op
== inst
.reloc
.exp
.X_op
)
1085 && (inst
.reloc
.exp
.X_op
== O_symbol
)
1086 && (pool
->literals
[entry
].X_add_number
1087 == inst
.reloc
.exp
.X_add_number
)
1088 && (pool
->literals
[entry
].X_add_symbol
1089 == inst
.reloc
.exp
.X_add_symbol
)
1090 && (pool
->literals
[entry
].X_op_symbol
1091 == inst
.reloc
.exp
.X_op_symbol
))
1095 /* Do we need to create a new entry? */
1096 if (entry
== pool
->next_free_entry
)
1098 if (entry
>= MAX_LITERAL_POOL_SIZE
)
1100 inst
.error
= _("literal pool overflow");
1104 pool
->literals
[entry
] = inst
.reloc
.exp
;
1105 pool
->next_free_entry
+= 1;
1108 inst
.reloc
.exp
.X_op
= O_symbol
;
1109 inst
.reloc
.exp
.X_add_number
= ((int) entry
) * 4 - 8;
1110 inst
.reloc
.exp
.X_add_symbol
= pool
->symbol
;
1115 /* Can't use symbol_new here, so have to create a symbol and then at
1116 a later date assign it a value. Thats what these functions do. */
1119 symbol_locate (symbolS
* symbolP
,
1120 const char * name
, /* It is copied, the caller can modify. */
1121 segT segment
, /* Segment identifier (SEG_<something>). */
1122 valueT valu
, /* Symbol value. */
1123 fragS
* frag
) /* Associated fragment. */
1125 unsigned int name_length
;
1126 char * preserved_copy_of_name
;
1128 name_length
= strlen (name
) + 1; /* +1 for \0. */
1129 obstack_grow (¬es
, name
, name_length
);
1130 preserved_copy_of_name
= obstack_finish (¬es
);
1131 #ifdef STRIP_UNDERSCORE
1132 if (preserved_copy_of_name
[0] == '_')
1133 preserved_copy_of_name
++;
1136 #ifdef tc_canonicalize_symbol_name
1137 preserved_copy_of_name
=
1138 tc_canonicalize_symbol_name (preserved_copy_of_name
);
1141 S_SET_NAME (symbolP
, preserved_copy_of_name
);
1143 S_SET_SEGMENT (symbolP
, segment
);
1144 S_SET_VALUE (symbolP
, valu
);
1145 symbol_clear_list_pointers (symbolP
);
1147 symbol_set_frag (symbolP
, frag
);
1149 /* Link to end of symbol chain. */
1151 extern int symbol_table_frozen
;
1153 if (symbol_table_frozen
)
1157 symbol_append (symbolP
, symbol_lastP
, & symbol_rootP
, & symbol_lastP
);
1159 obj_symbol_new_hook (symbolP
);
1161 #ifdef tc_symbol_new_hook
1162 tc_symbol_new_hook (symbolP
);
1166 verify_symbol_chain (symbol_rootP
, symbol_lastP
);
1167 #endif /* DEBUG_SYMS */
1170 /* Check that an immediate is valid.
1171 If so, convert it to the right format. */
1174 validate_immediate (unsigned int val
)
1179 #define rotate_left(v, n) (v << n | v >> (32 - n))
1181 for (i
= 0; i
< 32; i
+= 2)
1182 if ((a
= rotate_left (val
, i
)) <= 0xff)
1183 return a
| (i
<< 7); /* 12-bit pack: [shift-cnt,const]. */
1188 /* Check to see if an immediate can be computed as two separate immediate
1189 values, added together. We already know that this value cannot be
1190 computed by just one ARM instruction. */
1193 validate_immediate_twopart (unsigned int val
,
1194 unsigned int * highpart
)
1199 for (i
= 0; i
< 32; i
+= 2)
1200 if (((a
= rotate_left (val
, i
)) & 0xff) != 0)
1206 * highpart
= (a
>> 8) | ((i
+ 24) << 7);
1208 else if (a
& 0xff0000)
1212 * highpart
= (a
>> 16) | ((i
+ 16) << 7);
1216 assert (a
& 0xff000000);
1217 * highpart
= (a
>> 24) | ((i
+ 8) << 7);
1220 return (a
& 0xff) | (i
<< 7);
1227 validate_offset_imm (unsigned int val
, int hwse
)
1229 if ((hwse
&& val
> 255) || val
> 4095)
1236 /* This code is to handle mapping symbols as defined in the ARM ELF spec.
1237 (This text is taken from version B-02 of the spec):
1239 4.4.7 Mapping and tagging symbols
1241 A section of an ARM ELF file can contain a mixture of ARM code,
1242 Thumb code, and data. There are inline transitions between code
1243 and data at literal pool boundaries. There can also be inline
1244 transitions between ARM code and Thumb code, for example in
1245 ARM-Thumb inter-working veneers. Linkers, machine-level
1246 debuggers, profiling tools, and disassembly tools need to map
1247 images accurately. For example, setting an ARM breakpoint on a
1248 Thumb location, or in a literal pool, can crash the program
1249 being debugged, ruining the debugging session.
1251 ARM ELF entities are mapped (see section 4.4.7.1 below) and
1252 tagged (see section 4.4.7.2 below) using local symbols (with
1253 binding STB_LOCAL). To assist consumers, mapping and tagging
1254 symbols should be collated first in the symbol table, before
1255 other symbols with binding STB_LOCAL.
1257 To allow properly collated mapping and tagging symbols to be
1258 skipped by consumers that have no interest in them, the first
1259 such symbol should have the name $m and its st_value field equal
1260 to the total number of mapping and tagging symbols (including
1261 the $m) in the symbol table.
1263 4.4.7.1 Mapping symbols
1265 $a Labels the first byte of a sequence of ARM instructions.
1266 Its type is STT_FUNC.
1268 $d Labels the first byte of a sequence of data items.
1269 Its type is STT_OBJECT.
1271 $t Labels the first byte of a sequence of Thumb instructions.
1272 Its type is STT_FUNC.
1274 This list of mapping symbols may be extended in the future.
1276 Section-relative mapping symbols
1278 Mapping symbols defined in a section define a sequence of
1279 half-open address intervals that cover the address range of the
1280 section. Each interval starts at the address defined by a
1281 mapping symbol, and continues up to, but not including, the
1282 address defined by the next (in address order) mapping symbol or
1283 the end of the section. A corollary is that there must be a
1284 mapping symbol defined at the beginning of each section.
1285 Consumers can ignore the size of a section-relative mapping
1286 symbol. Producers can set it to 0.
1288 Absolute mapping symbols
1290 Because of the need to crystallize a Thumb address with the
1291 Thumb-bit set, absolute symbol of type STT_FUNC (symbols of type
1292 STT_FUNC defined in section SHN_ABS) need to be mapped with $a
1295 The extent of a mapping symbol defined in SHN_ABS is [st_value,
1296 st_value + st_size), or [st_value, st_value + 1) if st_size = 0,
1297 where [x, y) denotes the half-open address range from x,
1298 inclusive, to y, exclusive.
1300 In the absence of a mapping symbol, a consumer can interpret a
1301 function symbol with an odd value as the Thumb code address
1302 obtained by clearing the least significant bit of the
1303 value. This interpretation is deprecated, and it may not work in
1306 Note - the Tagging symbols ($b, $f, $p $m) have been dropped from
1307 the EABI (which is still under development), so they are not
1308 implemented here. */
1310 static enum mstate mapstate
= MAP_UNDEFINED
;
1313 mapping_state (enum mstate state
)
1316 const char * symname
;
1319 if (mapstate
== state
)
1320 /* The mapping symbol has already been emitted.
1321 There is nothing else to do. */
1334 type
= BSF_FUNCTION
;
1338 type
= BSF_FUNCTION
;
1346 seg_info (now_seg
)->tc_segment_info_data
= state
;
1348 symbolP
= symbol_new (symname
, now_seg
, (valueT
) frag_now_fix (), frag_now
);
1349 symbol_table_insert (symbolP
);
1350 symbol_get_bfdsym (symbolP
)->flags
|= type
| BSF_LOCAL
;
1355 THUMB_SET_FUNC (symbolP
, 0);
1356 ARM_SET_THUMB (symbolP
, 0);
1357 ARM_SET_INTERWORK (symbolP
, support_interwork
);
1361 THUMB_SET_FUNC (symbolP
, 1);
1362 ARM_SET_THUMB (symbolP
, 1);
1363 ARM_SET_INTERWORK (symbolP
, support_interwork
);
1372 /* When we change sections we need to issue a new mapping symbol. */
1375 arm_elf_change_section (void)
1379 /* Link an unlinked unwind index table section to the .text section. */
1380 if (elf_section_type (now_seg
) == SHT_ARM_EXIDX
1381 && elf_linked_to_section (now_seg
) == NULL
)
1382 elf_linked_to_section (now_seg
) = text_section
;
1384 if (!SEG_NORMAL (now_seg
))
1387 flags
= bfd_get_section_flags (stdoutput
, now_seg
);
1389 /* We can ignore sections that only contain debug info. */
1390 if ((flags
& SEC_ALLOC
) == 0)
1393 mapstate
= seg_info (now_seg
)->tc_segment_info_data
;
1397 arm_elf_section_type (const char * str
, size_t len
)
1399 if (len
== 5 && strncmp (str
, "exidx", 5) == 0)
1400 return SHT_ARM_EXIDX
;
1405 #define mapping_state(a)
1406 #endif /* OBJ_ELF */
1408 /* arm_reg_parse () := if it looks like a register, return its token and
1409 advance the pointer. */
1412 arm_reg_parse (char ** ccp
, struct hash_control
* htab
)
1414 char * start
= * ccp
;
1417 struct reg_entry
* reg
;
1419 #ifdef REGISTER_PREFIX
1420 if (*start
!= REGISTER_PREFIX
)
1425 #ifdef OPTIONAL_REGISTER_PREFIX
1426 if (*p
== OPTIONAL_REGISTER_PREFIX
)
1430 if (!ISALPHA (*p
) || !is_name_beginner (*p
))
1434 while (ISALPHA (c
) || ISDIGIT (c
) || c
== '_')
1438 reg
= (struct reg_entry
*) hash_find (htab
, start
);
1450 /* Search for the following register name in each of the possible reg name
1451 tables. Return the classification if found, or REG_TYPE_MAX if not
1454 static enum arm_reg_type
1455 arm_reg_parse_any (char *cp
)
1459 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
1460 if (arm_reg_parse (&cp
, all_reg_maps
[i
].htab
) != FAIL
)
1461 return (enum arm_reg_type
) i
;
1463 return REG_TYPE_MAX
;
1467 opcode_select (int width
)
1474 if (! (cpu_variant
& ARM_EXT_V4T
))
1475 as_bad (_("selected processor does not support THUMB opcodes"));
1478 /* No need to force the alignment, since we will have been
1479 coming from ARM mode, which is word-aligned. */
1480 record_alignment (now_seg
, 1);
1482 mapping_state (MAP_THUMB
);
1488 if ((cpu_variant
& ARM_ALL
) == ARM_EXT_V4T
)
1489 as_bad (_("selected processor does not support ARM opcodes"));
1494 frag_align (2, 0, 0);
1496 record_alignment (now_seg
, 1);
1498 mapping_state (MAP_ARM
);
1502 as_bad (_("invalid instruction size selected (%d)"), width
);
1507 s_req (int a ATTRIBUTE_UNUSED
)
1509 as_bad (_("invalid syntax for .req directive"));
1512 /* The .unreq directive deletes an alias which was previously defined
1513 by .req. For example:
1519 s_unreq (int a ATTRIBUTE_UNUSED
)
1524 skip_whitespace (input_line_pointer
);
1525 name
= input_line_pointer
;
1527 while (*input_line_pointer
!= 0
1528 && *input_line_pointer
!= ' '
1529 && *input_line_pointer
!= '\n')
1530 ++input_line_pointer
;
1532 saved_char
= *input_line_pointer
;
1533 *input_line_pointer
= 0;
1537 enum arm_reg_type req_type
= arm_reg_parse_any (name
);
1539 if (req_type
!= REG_TYPE_MAX
)
1541 char *temp_name
= name
;
1542 int req_no
= arm_reg_parse (&temp_name
, all_reg_maps
[req_type
].htab
);
1546 struct reg_entry
*req_entry
;
1548 /* Check to see if this alias is a builtin one. */
1549 req_entry
= hash_delete (all_reg_maps
[req_type
].htab
, name
);
1552 as_bad (_("unreq: missing hash entry for \"%s\""), name
);
1553 else if (req_entry
->builtin
)
1554 /* FIXME: We are deleting a built in register alias which
1555 points to a const data structure, so we only need to
1556 free up the memory used by the key in the hash table.
1557 Unfortunately we have not recorded this value, so this
1558 is a memory leak. */
1559 /* FIXME: Should we issue a warning message ? */
1563 /* Deleting a user defined alias. We need to free the
1564 key and the value, but fortunately the key is the same
1565 as the value->name field. */
1566 free ((char *) req_entry
->name
);
1571 as_bad (_(".unreq: unrecognized symbol \"%s\""), name
);
1574 as_bad (_(".unreq: unrecognized symbol \"%s\""), name
);
1577 as_bad (_("invalid syntax for .unreq directive"));
1579 *input_line_pointer
= saved_char
;
1580 demand_empty_rest_of_line ();
1584 s_bss (int ignore ATTRIBUTE_UNUSED
)
1586 /* We don't support putting frags in the BSS segment, we fake it by
1587 marking in_bss, then looking at s_skip for clues. */
1588 subseg_set (bss_section
, 0);
1589 demand_empty_rest_of_line ();
1590 mapping_state (MAP_DATA
);
1594 s_even (int ignore ATTRIBUTE_UNUSED
)
1596 /* Never make frag if expect extra pass. */
1598 frag_align (1, 0, 0);
1600 record_alignment (now_seg
, 1);
1602 demand_empty_rest_of_line ();
1606 s_ltorg (int ignored ATTRIBUTE_UNUSED
)
1609 literal_pool
* pool
;
1612 pool
= find_literal_pool ();
1614 || pool
->symbol
== NULL
1615 || pool
->next_free_entry
== 0)
1618 mapping_state (MAP_DATA
);
1620 /* Align pool as you have word accesses.
1621 Only make a frag if we have to. */
1623 frag_align (2, 0, 0);
1625 record_alignment (now_seg
, 2);
1627 sprintf (sym_name
, "$$lit_\002%x", pool
->id
);
1629 symbol_locate (pool
->symbol
, sym_name
, now_seg
,
1630 (valueT
) frag_now_fix (), frag_now
);
1631 symbol_table_insert (pool
->symbol
);
1633 ARM_SET_THUMB (pool
->symbol
, thumb_mode
);
1635 #if defined OBJ_COFF || defined OBJ_ELF
1636 ARM_SET_INTERWORK (pool
->symbol
, support_interwork
);
1639 for (entry
= 0; entry
< pool
->next_free_entry
; entry
++)
1640 /* First output the expression in the instruction to the pool. */
1641 emit_expr (&(pool
->literals
[entry
]), 4); /* .word */
1643 /* Mark the pool as empty. */
1644 pool
->next_free_entry
= 0;
1645 pool
->symbol
= NULL
;
1648 /* Same as s_align_ptwo but align 0 => align 2. */
1651 s_align (int unused ATTRIBUTE_UNUSED
)
1655 long max_alignment
= 15;
1657 temp
= get_absolute_expression ();
1658 if (temp
> max_alignment
)
1659 as_bad (_("alignment too large: %d assumed"), temp
= max_alignment
);
1662 as_bad (_("alignment negative. 0 assumed."));
1666 if (*input_line_pointer
== ',')
1668 input_line_pointer
++;
1669 temp_fill
= get_absolute_expression ();
1677 /* Only make a frag if we HAVE to. */
1678 if (temp
&& !need_pass_2
)
1679 frag_align (temp
, (int) temp_fill
, 0);
1680 demand_empty_rest_of_line ();
1682 record_alignment (now_seg
, temp
);
1686 s_force_thumb (int ignore ATTRIBUTE_UNUSED
)
1688 /* If we are not already in thumb mode go into it, EVEN if
1689 the target processor does not support thumb instructions.
1690 This is used by gcc/config/arm/lib1funcs.asm for example
1691 to compile interworking support functions even if the
1692 target processor should not support interworking. */
1697 record_alignment (now_seg
, 1);
1700 demand_empty_rest_of_line ();
1704 s_thumb_func (int ignore ATTRIBUTE_UNUSED
)
1709 /* The following label is the name/address of the start of a Thumb function.
1710 We need to know this for the interworking support. */
1711 label_is_thumb_function_name
= TRUE
;
1713 demand_empty_rest_of_line ();
1716 /* Perform a .set directive, but also mark the alias as
1717 being a thumb function. */
1720 s_thumb_set (int equiv
)
1722 /* XXX the following is a duplicate of the code for s_set() in read.c
1723 We cannot just call that code as we need to get at the symbol that
1730 /* Especial apologies for the random logic:
1731 This just grew, and could be parsed much more simply!
1733 name
= input_line_pointer
;
1734 delim
= get_symbol_end ();
1735 end_name
= input_line_pointer
;
1740 if (*input_line_pointer
!= ',')
1743 as_bad (_("expected comma after name \"%s\""), name
);
1745 ignore_rest_of_line ();
1749 input_line_pointer
++;
1752 if (name
[0] == '.' && name
[1] == '\0')
1754 /* XXX - this should not happen to .thumb_set. */
1758 if ((symbolP
= symbol_find (name
)) == NULL
1759 && (symbolP
= md_undefined_symbol (name
)) == NULL
)
1762 /* When doing symbol listings, play games with dummy fragments living
1763 outside the normal fragment chain to record the file and line info
1765 if (listing
& LISTING_SYMBOLS
)
1767 extern struct list_info_struct
* listing_tail
;
1768 fragS
* dummy_frag
= xmalloc (sizeof (fragS
));
1770 memset (dummy_frag
, 0, sizeof (fragS
));
1771 dummy_frag
->fr_type
= rs_fill
;
1772 dummy_frag
->line
= listing_tail
;
1773 symbolP
= symbol_new (name
, undefined_section
, 0, dummy_frag
);
1774 dummy_frag
->fr_symbol
= symbolP
;
1778 symbolP
= symbol_new (name
, undefined_section
, 0, &zero_address_frag
);
1781 /* "set" symbols are local unless otherwise specified. */
1782 SF_SET_LOCAL (symbolP
);
1783 #endif /* OBJ_COFF */
1784 } /* Make a new symbol. */
1786 symbol_table_insert (symbolP
);
1791 && S_IS_DEFINED (symbolP
)
1792 && S_GET_SEGMENT (symbolP
) != reg_section
)
1793 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP
));
1795 pseudo_set (symbolP
);
1797 demand_empty_rest_of_line ();
1799 /* XXX Now we come to the Thumb specific bit of code. */
1801 THUMB_SET_FUNC (symbolP
, 1);
1802 ARM_SET_THUMB (symbolP
, 1);
1803 #if defined OBJ_ELF || defined OBJ_COFF
1804 ARM_SET_INTERWORK (symbolP
, support_interwork
);
1809 s_arm (int ignore ATTRIBUTE_UNUSED
)
1812 demand_empty_rest_of_line ();
1816 s_thumb (int ignore ATTRIBUTE_UNUSED
)
1819 demand_empty_rest_of_line ();
1823 s_code (int unused ATTRIBUTE_UNUSED
)
1827 temp
= get_absolute_expression ();
1832 opcode_select (temp
);
1836 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp
);
1841 end_of_line (char * str
)
1843 skip_whitespace (str
);
1845 if (*str
!= '\0' && !inst
.error
)
1846 inst
.error
= _("garbage following instruction");
1850 skip_past_comma (char ** str
)
1852 char * p
= * str
, c
;
1855 while ((c
= *p
) == ' ' || c
== ',')
1858 if (c
== ',' && comma
++)
1866 return comma
? SUCCESS
: FAIL
;
1869 /* Return TRUE if anything in the expression is a bignum. */
1872 walk_no_bignums (symbolS
* sp
)
1874 if (symbol_get_value_expression (sp
)->X_op
== O_big
)
1877 if (symbol_get_value_expression (sp
)->X_add_symbol
)
1879 return (walk_no_bignums (symbol_get_value_expression (sp
)->X_add_symbol
)
1880 || (symbol_get_value_expression (sp
)->X_op_symbol
1881 && walk_no_bignums (symbol_get_value_expression (sp
)->X_op_symbol
)));
1887 static int in_my_get_expression
= 0;
1890 my_get_expression (expressionS
* ep
, char ** str
)
1895 save_in
= input_line_pointer
;
1896 input_line_pointer
= *str
;
1897 in_my_get_expression
= 1;
1898 seg
= expression (ep
);
1899 in_my_get_expression
= 0;
1901 if (ep
->X_op
== O_illegal
)
1903 /* We found a bad expression in md_operand(). */
1904 *str
= input_line_pointer
;
1905 input_line_pointer
= save_in
;
1910 if (seg
!= absolute_section
1911 && seg
!= text_section
1912 && seg
!= data_section
1913 && seg
!= bss_section
1914 && seg
!= undefined_section
)
1916 inst
.error
= _("bad_segment");
1917 *str
= input_line_pointer
;
1918 input_line_pointer
= save_in
;
1923 /* Get rid of any bignums now, so that we don't generate an error for which
1924 we can't establish a line number later on. Big numbers are never valid
1925 in instructions, which is where this routine is always called. */
1926 if (ep
->X_op
== O_big
1927 || (ep
->X_add_symbol
1928 && (walk_no_bignums (ep
->X_add_symbol
)
1930 && walk_no_bignums (ep
->X_op_symbol
)))))
1932 inst
.error
= _("invalid constant");
1933 *str
= input_line_pointer
;
1934 input_line_pointer
= save_in
;
1938 *str
= input_line_pointer
;
1939 input_line_pointer
= save_in
;
1943 /* A standard register must be given at this point.
1944 SHIFT is the place to put it in inst.instruction.
1945 Restores input start point on error.
1946 Returns the reg#, or FAIL. */
1949 reg_required_here (char ** str
, int shift
)
1951 static char buff
[128]; /* XXX */
1953 char * start
= * str
;
1955 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_RN
].htab
)) != FAIL
)
1958 inst
.instruction
|= reg
<< shift
;
1962 /* Restore the start point, we may have got a reg of the wrong class. */
1965 /* In the few cases where we might be able to accept something else
1966 this error can be overridden. */
1967 sprintf (buff
, _("register expected, not '%.100s'"), start
);
1973 /* A Intel Wireless MMX technology register
1974 must be given at this point.
1975 Shift is the place to put it in inst.instruction.
1976 Restores input start point on err.
1977 Returns the reg#, or FAIL. */
1980 wreg_required_here (char ** str
,
1982 enum wreg_type reg_type
)
1984 static char buff
[128];
1986 char * start
= *str
;
1988 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_IWMMXT
].htab
)) != FAIL
)
1990 if (wr_register (reg
)
1991 && (reg_type
== IWMMXT_REG_WR
|| reg_type
== IWMMXT_REG_WR_OR_WC
))
1994 inst
.instruction
|= (reg
^ WR_PREFIX
) << shift
;
1997 else if (wc_register (reg
)
1998 && (reg_type
== IWMMXT_REG_WC
|| reg_type
== IWMMXT_REG_WR_OR_WC
))
2001 inst
.instruction
|= (reg
^ WC_PREFIX
) << shift
;
2004 else if ((wcg_register (reg
) && reg_type
== IWMMXT_REG_WCG
))
2007 inst
.instruction
|= ((reg
^ WC_PREFIX
) - 8) << shift
;
2012 /* Restore the start point, we may have got a reg of the wrong class. */
2015 /* In the few cases where we might be able to accept
2016 something else this error can be overridden. */
2017 sprintf (buff
, _("Intel Wireless MMX technology register expected, not '%.100s'"), start
);
2023 static const struct asm_psr
*
2024 arm_psr_parse (char ** ccp
)
2026 char * start
= * ccp
;
2029 const struct asm_psr
* psr
;
2033 /* Skip to the end of the next word in the input stream. */
2038 while (ISALPHA (c
) || c
== '_');
2040 /* Terminate the word. */
2043 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
2044 feature for ease of use and backwards compatibility. */
2045 if (!strncmp (start
, "cpsr", 4))
2046 strncpy (start
, "CPSR", 4);
2047 else if (!strncmp (start
, "spsr", 4))
2048 strncpy (start
, "SPSR", 4);
2050 /* Now locate the word in the psr hash table. */
2051 psr
= (const struct asm_psr
*) hash_find (arm_psr_hsh
, start
);
2053 /* Restore the input stream. */
2056 /* If we found a valid match, advance the
2057 stream pointer past the end of the word. */
2063 /* Parse the input looking for a PSR flag. */
2066 psr_required_here (char ** str
)
2068 char * start
= * str
;
2069 const struct asm_psr
* psr
;
2071 psr
= arm_psr_parse (str
);
2075 /* If this is the SPSR that is being modified, set the R bit. */
2077 inst
.instruction
|= SPSR_BIT
;
2079 /* Set the psr flags in the MSR instruction. */
2080 inst
.instruction
|= psr
->field
<< PSR_SHIFT
;
2085 /* In the few cases where we might be able to accept
2086 something else this error can be overridden. */
2087 inst
.error
= _("flag for {c}psr instruction expected");
2089 /* Restore the start point. */
2095 co_proc_number (char ** str
)
2097 int processor
, pchar
;
2100 skip_whitespace (*str
);
2103 /* The data sheet seems to imply that just a number on its own is valid
2104 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
2106 if ((processor
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CP
].htab
))
2112 if (pchar
>= '0' && pchar
<= '9')
2114 processor
= pchar
- '0';
2115 if (**str
>= '0' && **str
<= '9')
2117 processor
= processor
* 10 + *(*str
)++ - '0';
2120 inst
.error
= _("illegal co-processor number");
2127 inst
.error
= all_reg_maps
[REG_TYPE_CP
].expected
;
2132 inst
.instruction
|= processor
<< 8;
2137 cp_opc_expr (char ** str
, int where
, int length
)
2141 skip_whitespace (* str
);
2143 memset (&expr
, '\0', sizeof (expr
));
2145 if (my_get_expression (&expr
, str
))
2147 if (expr
.X_op
!= O_constant
)
2149 inst
.error
= _("bad or missing expression");
2153 if ((expr
.X_add_number
& ((1 << length
) - 1)) != expr
.X_add_number
)
2155 inst
.error
= _("immediate co-processor expression too large");
2159 inst
.instruction
|= expr
.X_add_number
<< where
;
2164 cp_reg_required_here (char ** str
, int where
)
2167 char * start
= *str
;
2169 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CN
].htab
)) != FAIL
)
2171 inst
.instruction
|= reg
<< where
;
2175 /* In the few cases where we might be able to accept something else
2176 this error can be overridden. */
2177 inst
.error
= all_reg_maps
[REG_TYPE_CN
].expected
;
2179 /* Restore the start point. */
2185 fp_reg_required_here (char ** str
, int where
)
2188 char * start
= * str
;
2190 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_FN
].htab
)) != FAIL
)
2192 inst
.instruction
|= reg
<< where
;
2196 /* In the few cases where we might be able to accept something else
2197 this error can be overridden. */
2198 inst
.error
= all_reg_maps
[REG_TYPE_FN
].expected
;
2200 /* Restore the start point. */
2206 cp_address_offset (char ** str
)
2210 skip_whitespace (* str
);
2212 if (! is_immediate_prefix (**str
))
2214 inst
.error
= _("immediate expression expected");
2220 if (my_get_expression (& inst
.reloc
.exp
, str
))
2223 if (inst
.reloc
.exp
.X_op
== O_constant
)
2225 offset
= inst
.reloc
.exp
.X_add_number
;
2229 inst
.error
= _("co-processor address must be word aligned");
2233 if (offset
> 1023 || offset
< -1023)
2235 inst
.error
= _("offset too large");
2240 inst
.instruction
|= INDEX_UP
;
2244 inst
.instruction
|= offset
>> 2;
2247 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
2253 cp_address_required_here (char ** str
, int wb_ok
)
2264 skip_whitespace (p
);
2266 if ((reg
= reg_required_here (& p
, 16)) == FAIL
)
2269 skip_whitespace (p
);
2275 skip_whitespace (p
);
2279 /* As an extension to the official ARM syntax we allow:
2281 as a short hand for:
2283 inst
.instruction
|= PRE_INDEX
| INDEX_UP
;
2288 if (skip_past_comma (& p
) == FAIL
)
2290 inst
.error
= _("comma expected after closing square bracket");
2294 skip_whitespace (p
);
2301 write_back
= WRITE_BACK
;
2305 inst
.error
= _("pc may not be used in post-increment");
2309 if (cp_address_offset (& p
) == FAIL
)
2313 pre_inc
= PRE_INDEX
| INDEX_UP
;
2319 /* [Rn], {<expr>} */
2322 skip_whitespace (p
);
2324 if (my_get_expression (& inst
.reloc
.exp
, & p
))
2327 if (inst
.reloc
.exp
.X_op
== O_constant
)
2329 option
= inst
.reloc
.exp
.X_add_number
;
2331 if (option
> 255 || option
< 0)
2333 inst
.error
= _("'option' field too large");
2337 skip_whitespace (p
);
2341 inst
.error
= _("'}' expected at end of 'option' field");
2347 inst
.instruction
|= option
;
2348 inst
.instruction
|= INDEX_UP
;
2353 inst
.error
= _("non-constant expressions for 'option' field not supported");
2359 inst
.error
= _("# or { expected after comma");
2365 /* '['Rn, #expr']'[!] */
2367 if (skip_past_comma (& p
) == FAIL
)
2369 inst
.error
= _("pre-indexed expression expected");
2373 pre_inc
= PRE_INDEX
;
2375 if (cp_address_offset (& p
) == FAIL
)
2378 skip_whitespace (p
);
2382 inst
.error
= _("missing ]");
2386 skip_whitespace (p
);
2388 if (wb_ok
&& *p
== '!')
2392 inst
.error
= _("pc may not be used with write-back");
2397 write_back
= WRITE_BACK
;
2403 if (my_get_expression (&inst
.reloc
.exp
, &p
))
2406 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
2407 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
2408 inst
.reloc
.pc_rel
= 1;
2409 inst
.instruction
|= (REG_PC
<< 16);
2410 pre_inc
= PRE_INDEX
;
2413 inst
.instruction
|= write_back
| pre_inc
;
2419 cp_byte_address_offset (char ** str
)
2423 skip_whitespace (* str
);
2425 if (! is_immediate_prefix (**str
))
2427 inst
.error
= _("immediate expression expected");
2433 if (my_get_expression (& inst
.reloc
.exp
, str
))
2436 if (inst
.reloc
.exp
.X_op
== O_constant
)
2438 offset
= inst
.reloc
.exp
.X_add_number
;
2440 if (offset
> 255 || offset
< -255)
2442 inst
.error
= _("offset too large");
2447 inst
.instruction
|= INDEX_UP
;
2451 inst
.instruction
|= offset
;
2454 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM_S2
;
2460 cp_byte_address_required_here (char ** str
)
2471 skip_whitespace (p
);
2473 if ((reg
= reg_required_here (& p
, 16)) == FAIL
)
2476 skip_whitespace (p
);
2482 if (skip_past_comma (& p
) == SUCCESS
)
2485 write_back
= WRITE_BACK
;
2489 inst
.error
= _("pc may not be used in post-increment");
2493 if (cp_byte_address_offset (& p
) == FAIL
)
2497 pre_inc
= PRE_INDEX
| INDEX_UP
;
2501 /* '['Rn, #expr']'[!] */
2503 if (skip_past_comma (& p
) == FAIL
)
2505 inst
.error
= _("pre-indexed expression expected");
2509 pre_inc
= PRE_INDEX
;
2511 if (cp_byte_address_offset (& p
) == FAIL
)
2514 skip_whitespace (p
);
2518 inst
.error
= _("missing ]");
2522 skip_whitespace (p
);
2528 inst
.error
= _("pc may not be used with write-back");
2533 write_back
= WRITE_BACK
;
2539 if (my_get_expression (&inst
.reloc
.exp
, &p
))
2542 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM_S2
;
2543 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
2544 inst
.reloc
.pc_rel
= 1;
2545 inst
.instruction
|= (REG_PC
<< 16);
2546 pre_inc
= PRE_INDEX
;
2549 inst
.instruction
|= write_back
| pre_inc
;
2557 skip_whitespace (str
);
2562 if (my_get_expression (&inst
.reloc
.exp
, &str
))
2563 inst
.reloc
.exp
.X_op
= O_illegal
;
2566 skip_whitespace (str
);
2570 inst
.reloc
.exp
.X_op
= O_illegal
;
2573 if (inst
.reloc
.exp
.X_op
!= O_constant
2574 || inst
.reloc
.exp
.X_add_number
> 255
2575 || inst
.reloc
.exp
.X_add_number
< 0)
2577 inst
.error
= _("Invalid NOP hint");
2581 /* Arcitectural NOP hints are CPSR sets with no bits selected. */
2582 inst
.instruction
&= 0xf0000000;
2583 inst
.instruction
|= 0x0320f000 + inst
.reloc
.exp
.X_add_number
;
2590 do_empty (char * str
)
2592 /* Do nothing really. */
2601 /* Only one syntax. */
2602 skip_whitespace (str
);
2604 if (reg_required_here (&str
, 12) == FAIL
)
2606 inst
.error
= BAD_ARGS
;
2610 if (skip_past_comma (&str
) == FAIL
)
2612 inst
.error
= _("comma expected after register name");
2616 skip_whitespace (str
);
2618 if ( streq (str
, "CPSR")
2619 || streq (str
, "SPSR")
2620 /* Lower case versions for backwards compatibility. */
2621 || streq (str
, "cpsr")
2622 || streq (str
, "spsr"))
2625 /* This is for backwards compatibility with older toolchains. */
2626 else if ( streq (str
, "cpsr_all")
2627 || streq (str
, "spsr_all"))
2631 inst
.error
= _("CPSR or SPSR expected");
2635 if (* str
== 's' || * str
== 'S')
2636 inst
.instruction
|= SPSR_BIT
;
2642 /* Two possible forms:
2643 "{C|S}PSR_<field>, Rm",
2644 "{C|S}PSR_f, #expression". */
2649 skip_whitespace (str
);
2651 if (psr_required_here (& str
) == FAIL
)
2654 if (skip_past_comma (& str
) == FAIL
)
2656 inst
.error
= _("comma missing after psr flags");
2660 skip_whitespace (str
);
2662 if (reg_required_here (& str
, 0) != FAIL
)
2669 if (! is_immediate_prefix (* str
))
2672 _("only a register or immediate value can follow a psr flag");
2679 if (my_get_expression (& inst
.reloc
.exp
, & str
))
2682 _("only a register or immediate value can follow a psr flag");
2686 inst
.instruction
|= INST_IMMEDIATE
;
2688 if (inst
.reloc
.exp
.X_add_symbol
)
2690 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
2691 inst
.reloc
.pc_rel
= 0;
2695 unsigned value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
2697 if (value
== (unsigned) FAIL
)
2699 inst
.error
= _("invalid constant");
2703 inst
.instruction
|= value
;
2710 /* Long Multiply Parser
2711 UMULL RdLo, RdHi, Rm, Rs
2712 SMULL RdLo, RdHi, Rm, Rs
2713 UMLAL RdLo, RdHi, Rm, Rs
2714 SMLAL RdLo, RdHi, Rm, Rs. */
2717 do_mull (char * str
)
2719 int rdlo
, rdhi
, rm
, rs
;
2721 /* Only one format "rdlo, rdhi, rm, rs". */
2722 skip_whitespace (str
);
2724 if ((rdlo
= reg_required_here (&str
, 12)) == FAIL
)
2726 inst
.error
= BAD_ARGS
;
2730 if (skip_past_comma (&str
) == FAIL
2731 || (rdhi
= reg_required_here (&str
, 16)) == FAIL
)
2733 inst
.error
= BAD_ARGS
;
2737 if (skip_past_comma (&str
) == FAIL
2738 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
2740 inst
.error
= BAD_ARGS
;
2744 /* rdhi, rdlo and rm must all be different. */
2745 if (rdlo
== rdhi
|| rdlo
== rm
|| rdhi
== rm
)
2746 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
2748 if (skip_past_comma (&str
) == FAIL
2749 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
2751 inst
.error
= BAD_ARGS
;
2755 if (rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
)
2757 inst
.error
= BAD_PC
;
2769 /* Only one format "rd, rm, rs". */
2770 skip_whitespace (str
);
2772 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
2774 inst
.error
= BAD_ARGS
;
2780 inst
.error
= BAD_PC
;
2784 if (skip_past_comma (&str
) == FAIL
2785 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
2787 inst
.error
= BAD_ARGS
;
2793 inst
.error
= BAD_PC
;
2798 as_tsktsk (_("rd and rm should be different in mul"));
2800 if (skip_past_comma (&str
) == FAIL
2801 || (rm
= reg_required_here (&str
, 8)) == FAIL
)
2803 inst
.error
= BAD_ARGS
;
2809 inst
.error
= BAD_PC
;
2817 do_mlas (char * str
, bfd_boolean is_mls
)
2821 /* Only one format "rd, rm, rs, rn". */
2822 skip_whitespace (str
);
2824 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
2826 inst
.error
= BAD_ARGS
;
2832 inst
.error
= BAD_PC
;
2836 if (skip_past_comma (&str
) == FAIL
2837 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
2839 inst
.error
= BAD_ARGS
;
2845 inst
.error
= BAD_PC
;
2849 /* This restriction does not apply to mls (nor to mla in v6, but
2850 that's hard to detect at present). */
2851 if (rm
== rd
&& !is_mls
)
2852 as_tsktsk (_("rd and rm should be different in mla"));
2854 if (skip_past_comma (&str
) == FAIL
2855 || (rd
= reg_required_here (&str
, 8)) == FAIL
2856 || skip_past_comma (&str
) == FAIL
2857 || (rm
= reg_required_here (&str
, 12)) == FAIL
)
2859 inst
.error
= BAD_ARGS
;
2863 if (rd
== REG_PC
|| rm
== REG_PC
)
2865 inst
.error
= BAD_PC
;
2875 do_mlas (str
, FALSE
);
2881 do_mlas (str
, TRUE
);
2884 /* Expects *str -> the characters "acc0", possibly with leading blanks.
2885 Advances *str to the next non-alphanumeric.
2886 Returns 0, or else FAIL (in which case sets inst.error).
2888 (In a future XScale, there may be accumulators other than zero.
2889 At that time this routine and its callers can be upgraded to suit.) */
2892 accum0_required_here (char ** str
)
2894 static char buff
[128]; /* Note the address is taken. Hence, static. */
2897 int result
= 0; /* The accum number. */
2899 skip_whitespace (p
);
2901 *str
= p
; /* Advance caller's string pointer too. */
2906 *--p
= 0; /* Aap nul into input buffer at non-alnum. */
2908 if (! ( streq (*str
, "acc0") || streq (*str
, "ACC0")))
2910 sprintf (buff
, _("acc0 expected, not '%.100s'"), *str
);
2915 *p
= c
; /* Unzap. */
2916 *str
= p
; /* Caller's string pointer to after match. */
2921 ldst_extend_v4 (char ** str
)
2930 if (my_get_expression (& inst
.reloc
.exp
, str
))
2933 if (inst
.reloc
.exp
.X_op
== O_constant
)
2935 int value
= inst
.reloc
.exp
.X_add_number
;
2937 if (value
< -255 || value
> 255)
2939 inst
.error
= _("address offset too large");
2949 /* Halfword and signextension instructions have the
2950 immediate value split across bits 11..8 and bits 3..0. */
2951 inst
.instruction
|= (add
| HWOFFSET_IMM
2952 | ((value
>> 4) << 8) | (value
& 0xF));
2956 inst
.instruction
|= HWOFFSET_IMM
;
2957 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
2958 inst
.reloc
.pc_rel
= 0;
2971 if (reg_required_here (str
, 0) == FAIL
)
2974 inst
.instruction
|= add
;
2979 /* Expects **str -> after a comma. May be leading blanks.
2980 Advances *str, recognizing a load mode, and setting inst.instruction.
2981 Returns rn, or else FAIL (in which case may set inst.error
2982 and not advance str)
2984 Note: doesn't know Rd, so no err checks that require such knowledge. */
2987 ld_mode_required_here (char ** string
)
2989 char * str
= * string
;
2993 skip_whitespace (str
);
2999 skip_whitespace (str
);
3001 if ((rn
= reg_required_here (& str
, 16)) == FAIL
)
3004 skip_whitespace (str
);
3010 if (skip_past_comma (& str
) == SUCCESS
)
3012 /* [Rn],... (post inc) */
3013 if (ldst_extend_v4 (&str
) == FAIL
)
3018 skip_whitespace (str
);
3023 inst
.instruction
|= WRITE_BACK
;
3026 inst
.instruction
|= INDEX_UP
| HWOFFSET_IMM
;
3032 if (skip_past_comma (& str
) == FAIL
)
3034 inst
.error
= _("pre-indexed expression expected");
3040 if (ldst_extend_v4 (&str
) == FAIL
)
3043 skip_whitespace (str
);
3045 if (* str
++ != ']')
3047 inst
.error
= _("missing ]");
3051 skip_whitespace (str
);
3056 inst
.instruction
|= WRITE_BACK
;
3060 else if (* str
== '=') /* ldr's "r,=label" syntax */
3061 /* We should never reach here, because <text> = <expression> is
3062 caught gas/read.c read_a_source_file() as a .set operation. */
3064 else /* PC +- 8 bit immediate offset. */
3066 if (my_get_expression (& inst
.reloc
.exp
, & str
))
3069 inst
.instruction
|= HWOFFSET_IMM
; /* The I bit. */
3070 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
3071 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
3072 inst
.reloc
.pc_rel
= 1;
3073 inst
.instruction
|= (REG_PC
<< 16);
3079 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
3085 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
3086 SMLAxy{cond} Rd,Rm,Rs,Rn
3087 SMLAWy{cond} Rd,Rm,Rs,Rn
3088 Error if any register is R15. */
3091 do_smla (char * str
)
3095 skip_whitespace (str
);
3097 if ((rd
= reg_required_here (& str
, 16)) == FAIL
3098 || skip_past_comma (& str
) == FAIL
3099 || (rm
= reg_required_here (& str
, 0)) == FAIL
3100 || skip_past_comma (& str
) == FAIL
3101 || (rs
= reg_required_here (& str
, 8)) == FAIL
3102 || skip_past_comma (& str
) == FAIL
3103 || (rn
= reg_required_here (& str
, 12)) == FAIL
)
3104 inst
.error
= BAD_ARGS
;
3106 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
|| rn
== REG_PC
)
3107 inst
.error
= BAD_PC
;
3113 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
3114 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
3115 Error if any register is R15.
3116 Warning if Rdlo == Rdhi. */
3119 do_smlal (char * str
)
3121 int rdlo
, rdhi
, rm
, rs
;
3123 skip_whitespace (str
);
3125 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
3126 || skip_past_comma (& str
) == FAIL
3127 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
3128 || skip_past_comma (& str
) == FAIL
3129 || (rm
= reg_required_here (& str
, 0)) == FAIL
3130 || skip_past_comma (& str
) == FAIL
3131 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
3133 inst
.error
= BAD_ARGS
;
3137 if (rdlo
== REG_PC
|| rdhi
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
3139 inst
.error
= BAD_PC
;
3144 as_tsktsk (_("rdhi and rdlo must be different"));
3149 /* ARM V5E (El Segundo) signed-multiply (argument parse)
3150 SMULxy{cond} Rd,Rm,Rs
3151 Error if any register is R15. */
3154 do_smul (char * str
)
3158 skip_whitespace (str
);
3160 if ((rd
= reg_required_here (& str
, 16)) == FAIL
3161 || skip_past_comma (& str
) == FAIL
3162 || (rm
= reg_required_here (& str
, 0)) == FAIL
3163 || skip_past_comma (& str
) == FAIL
3164 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
3165 inst
.error
= BAD_ARGS
;
3167 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
3168 inst
.error
= BAD_PC
;
3174 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
3175 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
3176 Error if any register is R15. */
3179 do_qadd (char * str
)
3183 skip_whitespace (str
);
3185 if ((rd
= reg_required_here (& str
, 12)) == FAIL
3186 || skip_past_comma (& str
) == FAIL
3187 || (rm
= reg_required_here (& str
, 0)) == FAIL
3188 || skip_past_comma (& str
) == FAIL
3189 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
3190 inst
.error
= BAD_ARGS
;
3192 else if (rd
== REG_PC
|| rm
== REG_PC
|| rn
== REG_PC
)
3193 inst
.error
= BAD_PC
;
3199 /* ARM V5E (el Segundo)
3200 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3201 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3203 These are equivalent to the XScale instructions MAR and MRA,
3204 respectively, when coproc == 0, opcode == 0, and CRm == 0.
3206 Result unpredicatable if Rd or Rn is R15. */
3209 do_co_reg2c (char * str
)
3213 skip_whitespace (str
);
3215 if (co_proc_number (& str
) == FAIL
)
3218 inst
.error
= BAD_ARGS
;
3222 if (skip_past_comma (& str
) == FAIL
3223 || cp_opc_expr (& str
, 4, 4) == FAIL
)
3226 inst
.error
= BAD_ARGS
;
3230 if (skip_past_comma (& str
) == FAIL
3231 || (rd
= reg_required_here (& str
, 12)) == FAIL
)
3234 inst
.error
= BAD_ARGS
;
3238 if (skip_past_comma (& str
) == FAIL
3239 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
3242 inst
.error
= BAD_ARGS
;
3246 /* Unpredictable result if rd or rn is R15. */
3247 if (rd
== REG_PC
|| rn
== REG_PC
)
3249 (_("Warning: instruction unpredictable when using r15"));
3251 if (skip_past_comma (& str
) == FAIL
3252 || cp_reg_required_here (& str
, 0) == FAIL
)
3255 inst
.error
= BAD_ARGS
;
3262 /* ARM V5 count-leading-zeroes instruction (argument parse)
3263 CLZ{<cond>} <Rd>, <Rm>
3264 Condition defaults to COND_ALWAYS.
3265 Error if Rd or Rm are R15. */
3272 skip_whitespace (str
);
3274 if (((rd
= reg_required_here (& str
, 12)) == FAIL
)
3275 || (skip_past_comma (& str
) == FAIL
)
3276 || ((rm
= reg_required_here (& str
, 0)) == FAIL
))
3277 inst
.error
= BAD_ARGS
;
3279 else if (rd
== REG_PC
|| rm
== REG_PC
)
3280 inst
.error
= BAD_PC
;
3286 /* ARM V5 (argument parse)
3287 LDC2{L} <coproc>, <CRd>, <addressing mode>
3288 STC2{L} <coproc>, <CRd>, <addressing mode>
3289 Instruction is not conditional, and has 0xf in the condition field.
3290 Otherwise, it's the same as LDC/STC. */
3293 do_lstc2 (char * str
)
3295 skip_whitespace (str
);
3297 if (co_proc_number (& str
) == FAIL
)
3300 inst
.error
= BAD_ARGS
;
3302 else if (skip_past_comma (& str
) == FAIL
3303 || cp_reg_required_here (& str
, 12) == FAIL
)
3306 inst
.error
= BAD_ARGS
;
3308 else if (skip_past_comma (& str
) == FAIL
3309 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
3312 inst
.error
= BAD_ARGS
;
3318 /* ARM V5 (argument parse)
3319 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
3320 Instruction is not conditional, and has 0xf in the condition field.
3321 Otherwise, it's the same as CDP. */
3324 do_cdp2 (char * str
)
3326 skip_whitespace (str
);
3328 if (co_proc_number (& str
) == FAIL
)
3331 inst
.error
= BAD_ARGS
;
3335 if (skip_past_comma (& str
) == FAIL
3336 || cp_opc_expr (& str
, 20,4) == FAIL
)
3339 inst
.error
= BAD_ARGS
;
3343 if (skip_past_comma (& str
) == FAIL
3344 || cp_reg_required_here (& str
, 12) == FAIL
)
3347 inst
.error
= BAD_ARGS
;
3351 if (skip_past_comma (& str
) == FAIL
3352 || cp_reg_required_here (& str
, 16) == FAIL
)
3355 inst
.error
= BAD_ARGS
;
3359 if (skip_past_comma (& str
) == FAIL
3360 || cp_reg_required_here (& str
, 0) == FAIL
)
3363 inst
.error
= BAD_ARGS
;
3367 if (skip_past_comma (& str
) == SUCCESS
)
3369 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
3372 inst
.error
= BAD_ARGS
;
3380 /* ARM V5 (argument parse)
3381 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3382 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3383 Instruction is not conditional, and has 0xf in the condition field.
3384 Otherwise, it's the same as MCR/MRC. */
3387 do_co_reg2 (char * str
)
3389 skip_whitespace (str
);
3391 if (co_proc_number (& str
) == FAIL
)
3394 inst
.error
= BAD_ARGS
;
3398 if (skip_past_comma (& str
) == FAIL
3399 || cp_opc_expr (& str
, 21, 3) == FAIL
)
3402 inst
.error
= BAD_ARGS
;
3406 if (skip_past_comma (& str
) == FAIL
3407 || reg_required_here (& str
, 12) == FAIL
)
3410 inst
.error
= BAD_ARGS
;
3414 if (skip_past_comma (& str
) == FAIL
3415 || cp_reg_required_here (& str
, 16) == FAIL
)
3418 inst
.error
= BAD_ARGS
;
3422 if (skip_past_comma (& str
) == FAIL
3423 || cp_reg_required_here (& str
, 0) == FAIL
)
3426 inst
.error
= BAD_ARGS
;
3430 if (skip_past_comma (& str
) == SUCCESS
)
3432 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
3435 inst
.error
= BAD_ARGS
;
3448 skip_whitespace (str
);
3450 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
3452 inst
.error
= BAD_ARGS
;
3456 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
3458 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
3463 /* ARM v5TEJ. Jump to Jazelle code. */
3470 skip_whitespace (str
);
3472 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
3474 inst
.error
= BAD_ARGS
;
3478 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
3480 as_tsktsk (_("use of r15 in bxj is not really useful"));
3485 /* ARM V6 umaal (argument parse). */
3488 do_umaal (char * str
)
3490 int rdlo
, rdhi
, rm
, rs
;
3492 skip_whitespace (str
);
3493 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
3494 || skip_past_comma (& str
) == FAIL
3495 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
3496 || skip_past_comma (& str
) == FAIL
3497 || (rm
= reg_required_here (& str
, 0)) == FAIL
3498 || skip_past_comma (& str
) == FAIL
3499 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
3501 inst
.error
= BAD_ARGS
;
3505 if (rdlo
== REG_PC
|| rdhi
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
3507 inst
.error
= BAD_PC
;
3514 /* ARM V6 strex (argument parse). */
3517 do_strex (char * str
)
3521 /* Parse Rd, Rm,. */
3522 skip_whitespace (str
);
3523 if ((rd
= reg_required_here (& str
, 12)) == FAIL
3524 || skip_past_comma (& str
) == FAIL
3525 || (rm
= reg_required_here (& str
, 0)) == FAIL
3526 || skip_past_comma (& str
) == FAIL
)
3528 inst
.error
= BAD_ARGS
;
3531 if (rd
== REG_PC
|| rm
== REG_PC
)
3533 inst
.error
= BAD_PC
;
3538 inst
.error
= _("Rd equal to Rm or Rn yields unpredictable results");
3542 /* Skip past '['. */
3543 if ((strlen (str
) >= 1)
3544 && strncmp (str
, "[", 1) == 0)
3547 skip_whitespace (str
);
3550 if ((rn
= reg_required_here (& str
, 16)) == FAIL
)
3552 inst
.error
= BAD_ARGS
;
3555 else if (rn
== REG_PC
)
3557 inst
.error
= BAD_PC
;
3562 inst
.error
= _("Rd equal to Rm or Rn yields unpredictable results");
3565 skip_whitespace (str
);
3567 /* Skip past ']'. */
3568 if ((strlen (str
) >= 1)
3569 && strncmp (str
, "]", 1) == 0)
3575 /* KIND indicates what kind of shifts are accepted. */
3578 decode_shift (char ** str
, int kind
)
3580 const struct asm_shift_name
* shift
;
3584 skip_whitespace (* str
);
3586 for (p
= * str
; ISALPHA (* p
); p
++)
3591 inst
.error
= _("shift expression expected");
3597 shift
= (const struct asm_shift_name
*) hash_find (arm_shift_hsh
, * str
);
3602 inst
.error
= _("shift expression expected");
3606 assert (shift
->properties
->index
== shift_properties
[shift
->properties
->index
].index
);
3608 if (kind
== SHIFT_LSL_OR_ASR_IMMEDIATE
3609 && shift
->properties
->index
!= SHIFT_LSL
3610 && shift
->properties
->index
!= SHIFT_ASR
)
3612 inst
.error
= _("'LSL' or 'ASR' required");
3615 else if (kind
== SHIFT_LSL_IMMEDIATE
3616 && shift
->properties
->index
!= SHIFT_LSL
)
3618 inst
.error
= _("'LSL' required");
3621 else if (kind
== SHIFT_ASR_IMMEDIATE
3622 && shift
->properties
->index
!= SHIFT_ASR
)
3624 inst
.error
= _("'ASR' required");
3628 if (shift
->properties
->index
== SHIFT_RRX
)
3631 inst
.instruction
|= shift
->properties
->bit_field
;
3635 skip_whitespace (p
);
3637 if (kind
== NO_SHIFT_RESTRICT
&& reg_required_here (& p
, 8) != FAIL
)
3639 inst
.instruction
|= shift
->properties
->bit_field
| SHIFT_BY_REG
;
3643 else if (! is_immediate_prefix (* p
))
3645 inst
.error
= (NO_SHIFT_RESTRICT
3646 ? _("shift requires register or #expression")
3647 : _("shift requires #expression"));
3655 if (my_get_expression (& inst
.reloc
.exp
, & p
))
3658 /* Validate some simple #expressions. */
3659 if (inst
.reloc
.exp
.X_op
== O_constant
)
3661 unsigned num
= inst
.reloc
.exp
.X_add_number
;
3663 /* Reject operations greater than 32. */
3665 /* Reject a shift of 0 unless the mode allows it. */
3666 || (num
== 0 && shift
->properties
->allows_0
== 0)
3667 /* Reject a shift of 32 unless the mode allows it. */
3668 || (num
== 32 && shift
->properties
->allows_32
== 0)
3671 /* As a special case we allow a shift of zero for
3672 modes that do not support it to be recoded as an
3673 logical shift left of zero (ie nothing). We warn
3674 about this though. */
3677 as_warn (_("shift of 0 ignored."));
3678 shift
= & shift_names
[0];
3679 assert (shift
->properties
->index
== SHIFT_LSL
);
3683 inst
.error
= _("invalid immediate shift");
3688 /* Shifts of 32 are encoded as 0, for those shifts that
3693 inst
.instruction
|= (num
<< 7) | shift
->properties
->bit_field
;
3697 inst
.reloc
.type
= BFD_RELOC_ARM_SHIFT_IMM
;
3698 inst
.reloc
.pc_rel
= 0;
3699 inst
.instruction
|= shift
->properties
->bit_field
;
3707 do_sat (char ** str
, int bias
)
3712 skip_whitespace (*str
);
3714 /* Parse <Rd>, field. */
3715 if ((rd
= reg_required_here (str
, 12)) == FAIL
3716 || skip_past_comma (str
) == FAIL
)
3718 inst
.error
= BAD_ARGS
;
3723 inst
.error
= BAD_PC
;
3727 /* Parse #<immed>, field. */
3728 if (is_immediate_prefix (**str
))
3732 inst
.error
= _("immediate expression expected");
3735 if (my_get_expression (&expr
, str
))
3737 inst
.error
= _("bad expression");
3740 if (expr
.X_op
!= O_constant
)
3742 inst
.error
= _("constant expression expected");
3745 if (expr
.X_add_number
+ bias
< 0
3746 || expr
.X_add_number
+ bias
> 31)
3748 inst
.error
= _("immediate value out of range");
3751 inst
.instruction
|= (expr
.X_add_number
+ bias
) << 16;
3752 if (skip_past_comma (str
) == FAIL
)
3754 inst
.error
= BAD_ARGS
;
3758 /* Parse <Rm> field. */
3759 if ((rm
= reg_required_here (str
, 0)) == FAIL
)
3761 inst
.error
= BAD_ARGS
;
3766 inst
.error
= BAD_PC
;
3770 if (skip_past_comma (str
) == SUCCESS
)
3771 decode_shift (str
, SHIFT_LSL_OR_ASR_IMMEDIATE
);
3774 /* ARM V6 ssat (argument parse). */
3777 do_ssat (char * str
)
3779 do_sat (&str
, /*bias=*/-1);
3783 /* ARM V6 usat (argument parse). */
3786 do_usat (char * str
)
3788 do_sat (&str
, /*bias=*/0);
3793 do_sat16 (char ** str
, int bias
)
3798 skip_whitespace (*str
);
3800 /* Parse the <Rd> field. */
3801 if ((rd
= reg_required_here (str
, 12)) == FAIL
3802 || skip_past_comma (str
) == FAIL
)
3804 inst
.error
= BAD_ARGS
;
3809 inst
.error
= BAD_PC
;
3813 /* Parse #<immed>, field. */
3814 if (is_immediate_prefix (**str
))
3818 inst
.error
= _("immediate expression expected");
3821 if (my_get_expression (&expr
, str
))
3823 inst
.error
= _("bad expression");
3826 if (expr
.X_op
!= O_constant
)
3828 inst
.error
= _("constant expression expected");
3831 if (expr
.X_add_number
+ bias
< 0
3832 || expr
.X_add_number
+ bias
> 15)
3834 inst
.error
= _("immediate value out of range");
3837 inst
.instruction
|= (expr
.X_add_number
+ bias
) << 16;
3838 if (skip_past_comma (str
) == FAIL
)
3840 inst
.error
= BAD_ARGS
;
3844 /* Parse <Rm> field. */
3845 if ((rm
= reg_required_here (str
, 0)) == FAIL
)
3847 inst
.error
= BAD_ARGS
;
3852 inst
.error
= BAD_PC
;
3857 /* ARM V6 ssat16 (argument parse). */
3860 do_ssat16 (char * str
)
3862 do_sat16 (&str
, /*bias=*/-1);
3867 do_usat16 (char * str
)
3869 do_sat16 (&str
, /*bias=*/0);
3874 do_cps_mode (char ** str
)
3878 skip_whitespace (*str
);
3880 if (! is_immediate_prefix (**str
))
3882 inst
.error
= _("immediate expression expected");
3886 (*str
)++; /* Strip off the immediate signifier. */
3887 if (my_get_expression (&expr
, str
))
3889 inst
.error
= _("bad expression");
3893 if (expr
.X_op
!= O_constant
)
3895 inst
.error
= _("constant expression expected");
3899 /* The mode is a 5 bit field. Valid values are 0-31. */
3900 if (((unsigned) expr
.X_add_number
) > 31
3901 || (inst
.reloc
.exp
.X_add_number
) < 0)
3903 inst
.error
= _("invalid constant");
3907 inst
.instruction
|= expr
.X_add_number
;
3910 /* ARM V6 srs (argument parse). */
3916 skip_whitespace (str
);
3917 exclam
= strchr (str
, '!');
3925 inst
.instruction
|= WRITE_BACK
;
3931 /* ARM V6 SMMUL (argument parse). */
3934 do_smmul (char * str
)
3938 skip_whitespace (str
);
3939 if ((rd
= reg_required_here (&str
, 16)) == FAIL
3940 || skip_past_comma (&str
) == FAIL
3941 || (rm
= reg_required_here (&str
, 0)) == FAIL
3942 || skip_past_comma (&str
) == FAIL
3943 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
3945 inst
.error
= BAD_ARGS
;
3953 inst
.error
= BAD_PC
;
3960 /* ARM V6 SMLALD (argument parse). */
3963 do_smlald (char * str
)
3965 int rdlo
, rdhi
, rm
, rs
;
3967 skip_whitespace (str
);
3968 if ((rdlo
= reg_required_here (&str
, 12)) == FAIL
3969 || skip_past_comma (&str
) == FAIL
3970 || (rdhi
= reg_required_here (&str
, 16)) == FAIL
3971 || skip_past_comma (&str
) == FAIL
3972 || (rm
= reg_required_here (&str
, 0)) == FAIL
3973 || skip_past_comma (&str
) == FAIL
3974 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
3976 inst
.error
= BAD_ARGS
;
3985 inst
.error
= BAD_PC
;
3992 /* ARM V6 SMLAD (argument parse). Signed multiply accumulate dual.
3993 smlad{x}{<cond>} Rd, Rm, Rs, Rn */
3996 do_smlad (char * str
)
4000 skip_whitespace (str
);
4001 if ((rd
= reg_required_here (&str
, 16)) == FAIL
4002 || skip_past_comma (&str
) == FAIL
4003 || (rm
= reg_required_here (&str
, 0)) == FAIL
4004 || skip_past_comma (&str
) == FAIL
4005 || (rs
= reg_required_here (&str
, 8)) == FAIL
4006 || skip_past_comma (&str
) == FAIL
4007 || (rn
= reg_required_here (&str
, 12)) == FAIL
)
4009 inst
.error
= BAD_ARGS
;
4018 inst
.error
= BAD_PC
;
4025 /* Returns true if the endian-specifier indicates big-endianness. */
4028 do_endian_specifier (char * str
)
4032 skip_whitespace (str
);
4033 if (strlen (str
) < 2)
4034 inst
.error
= _("missing endian specifier");
4035 else if (strncasecmp (str
, "BE", 2) == 0)
4040 else if (strncasecmp (str
, "LE", 2) == 0)
4043 inst
.error
= _("valid endian specifiers are be or le");
4050 /* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
4051 preserving the other bits.
4053 setend <endian_specifier>, where <endian_specifier> is either
4057 do_setend (char * str
)
4059 if (do_endian_specifier (str
))
4060 inst
.instruction
|= 0x200;
4065 SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
4066 Condition defaults to COND_ALWAYS.
4067 Error if any register uses R15. */
4070 do_sxth (char * str
)
4074 int rotation_clear_mask
= 0xfffff3ff;
4075 int rotation_eight_mask
= 0x00000400;
4076 int rotation_sixteen_mask
= 0x00000800;
4077 int rotation_twenty_four_mask
= 0x00000c00;
4079 skip_whitespace (str
);
4080 if ((rd
= reg_required_here (&str
, 12)) == FAIL
4081 || skip_past_comma (&str
) == FAIL
4082 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4084 inst
.error
= BAD_ARGS
;
4088 else if (rd
== REG_PC
|| rm
== REG_PC
)
4090 inst
.error
= BAD_PC
;
4094 /* Zero out the rotation field. */
4095 inst
.instruction
&= rotation_clear_mask
;
4097 /* Check for lack of optional rotation field. */
4098 if (skip_past_comma (&str
) == FAIL
)
4104 /* Move past 'ROR'. */
4105 skip_whitespace (str
);
4106 if (strncasecmp (str
, "ROR", 3) == 0)
4110 inst
.error
= _("missing rotation field after comma");
4114 /* Get the immediate constant. */
4115 skip_whitespace (str
);
4116 if (is_immediate_prefix (* str
))
4120 inst
.error
= _("immediate expression expected");
4124 if (my_get_expression (&expr
, &str
))
4126 inst
.error
= _("bad expression");
4130 if (expr
.X_op
!= O_constant
)
4132 inst
.error
= _("constant expression expected");
4136 switch (expr
.X_add_number
)
4139 /* Rotation field has already been zeroed. */
4142 inst
.instruction
|= rotation_eight_mask
;
4146 inst
.instruction
|= rotation_sixteen_mask
;
4150 inst
.instruction
|= rotation_twenty_four_mask
;
4154 inst
.error
= _("rotation can be 8, 16, 24 or 0 when field is ommited");
4161 /* ARM V6 SXTAH extracts a 16-bit value from a register, sign
4162 extends it to 32-bits, and adds the result to a value in another
4163 register. You can specify a rotation by 0, 8, 16, or 24 bits
4164 before extracting the 16-bit value.
4165 SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
4166 Condition defaults to COND_ALWAYS.
4167 Error if any register uses R15. */
4170 do_sxtah (char * str
)
4174 int rotation_clear_mask
= 0xfffff3ff;
4175 int rotation_eight_mask
= 0x00000400;
4176 int rotation_sixteen_mask
= 0x00000800;
4177 int rotation_twenty_four_mask
= 0x00000c00;
4179 skip_whitespace (str
);
4180 if ((rd
= reg_required_here (&str
, 12)) == FAIL
4181 || skip_past_comma (&str
) == FAIL
4182 || (rn
= reg_required_here (&str
, 16)) == FAIL
4183 || skip_past_comma (&str
) == FAIL
4184 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4186 inst
.error
= BAD_ARGS
;
4190 else if (rd
== REG_PC
|| rn
== REG_PC
|| rm
== REG_PC
)
4192 inst
.error
= BAD_PC
;
4196 /* Zero out the rotation field. */
4197 inst
.instruction
&= rotation_clear_mask
;
4199 /* Check for lack of optional rotation field. */
4200 if (skip_past_comma (&str
) == FAIL
)
4206 /* Move past 'ROR'. */
4207 skip_whitespace (str
);
4208 if (strncasecmp (str
, "ROR", 3) == 0)
4212 inst
.error
= _("missing rotation field after comma");
4216 /* Get the immediate constant. */
4217 skip_whitespace (str
);
4218 if (is_immediate_prefix (* str
))
4222 inst
.error
= _("immediate expression expected");
4226 if (my_get_expression (&expr
, &str
))
4228 inst
.error
= _("bad expression");
4232 if (expr
.X_op
!= O_constant
)
4234 inst
.error
= _("constant expression expected");
4238 switch (expr
.X_add_number
)
4241 /* Rotation field has already been zeroed. */
4245 inst
.instruction
|= rotation_eight_mask
;
4249 inst
.instruction
|= rotation_sixteen_mask
;
4253 inst
.instruction
|= rotation_twenty_four_mask
;
4257 inst
.error
= _("rotation can be 8, 16, 24 or 0 when field is ommited");
4265 /* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
4266 word at the specified address and the following word
4268 Unconditionally executed.
4269 Error if Rn is R15. */
4276 skip_whitespace (str
);
4278 if ((rn
= reg_required_here (&str
, 16)) == FAIL
)
4283 inst
.error
= BAD_PC
;
4287 skip_whitespace (str
);
4291 inst
.instruction
|= WRITE_BACK
;
4297 /* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
4298 register (argument parse).
4300 Condition defaults to COND_ALWAYS.
4301 Error if Rd or Rm are R15. */
4308 skip_whitespace (str
);
4310 if ((rd
= reg_required_here (&str
, 12)) == FAIL
4311 || skip_past_comma (&str
) == FAIL
4312 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4313 inst
.error
= BAD_ARGS
;
4315 else if (rd
== REG_PC
|| rm
== REG_PC
)
4316 inst
.error
= BAD_PC
;
4322 /* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
4323 QADD16{<cond>} <Rd>, <Rn>, <Rm>
4324 Condition defaults to COND_ALWAYS.
4325 Error if Rd, Rn or Rm are R15. */
4328 do_qadd16 (char * str
)
4332 skip_whitespace (str
);
4334 if ((rd
= reg_required_here (&str
, 12)) == FAIL
4335 || skip_past_comma (&str
) == FAIL
4336 || (rn
= reg_required_here (&str
, 16)) == FAIL
4337 || skip_past_comma (&str
) == FAIL
4338 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4339 inst
.error
= BAD_ARGS
;
4341 else if (rd
== REG_PC
|| rm
== REG_PC
|| rn
== REG_PC
)
4342 inst
.error
= BAD_PC
;
4349 do_pkh_core (char * str
, int shift
)
4353 skip_whitespace (str
);
4354 if (((rd
= reg_required_here (&str
, 12)) == FAIL
)
4355 || (skip_past_comma (&str
) == FAIL
)
4356 || ((rn
= reg_required_here (&str
, 16)) == FAIL
)
4357 || (skip_past_comma (&str
) == FAIL
)
4358 || ((rm
= reg_required_here (&str
, 0)) == FAIL
))
4360 inst
.error
= BAD_ARGS
;
4364 else if (rd
== REG_PC
|| rn
== REG_PC
|| rm
== REG_PC
)
4366 inst
.error
= BAD_PC
;
4370 /* Check for optional shift immediate constant. */
4371 if (skip_past_comma (&str
) == FAIL
)
4373 if (shift
== SHIFT_ASR_IMMEDIATE
)
4375 /* If the shift specifier is ommited, turn the instruction
4376 into pkhbt rd, rm, rn. First, switch the instruction
4377 code, and clear the rn and rm fields. */
4378 inst
.instruction
&= 0xfff0f010;
4379 /* Now, re-encode the registers. */
4380 inst
.instruction
|= (rm
<< 16) | rn
;
4385 decode_shift (&str
, shift
);
4388 /* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
4389 PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
4390 Condition defaults to COND_ALWAYS.
4391 Error if Rd, Rn or Rm are R15. */
4394 do_pkhbt (char * str
)
4396 do_pkh_core (str
, SHIFT_LSL_IMMEDIATE
);
4399 /* ARM V6 PKHTB (Argument Parse). */
4402 do_pkhtb (char * str
)
4404 do_pkh_core (str
, SHIFT_ASR_IMMEDIATE
);
4407 /* ARM V6 Load Register Exclusive instruction (argument parse).
4408 LDREX{,B,D,H}{<cond>} <Rd, [<Rn>]
4409 Condition defaults to COND_ALWAYS.
4410 Error if Rd or Rn are R15.
4411 See ARMARMv6 A4.1.27: LDREX. */
4414 do_ldrex (char * str
)
4418 skip_whitespace (str
);
4421 if (((rd
= reg_required_here (&str
, 12)) == FAIL
)
4422 || (skip_past_comma (&str
) == FAIL
))
4424 inst
.error
= BAD_ARGS
;
4427 else if (rd
== REG_PC
)
4429 inst
.error
= BAD_PC
;
4432 skip_whitespace (str
);
4434 /* Skip past '['. */
4435 if ((strlen (str
) >= 1)
4436 &&strncmp (str
, "[", 1) == 0)
4438 skip_whitespace (str
);
4441 if ((rn
= reg_required_here (&str
, 16)) == FAIL
)
4443 inst
.error
= BAD_ARGS
;
4446 else if (rn
== REG_PC
)
4448 inst
.error
= BAD_PC
;
4451 skip_whitespace (str
);
4453 /* Skip past ']'. */
4454 if ((strlen (str
) >= 1)
4455 && strncmp (str
, "]", 1) == 0)
4461 /* ARM V6 change processor state instruction (argument parse)
4462 CPS, CPSIE, CSPID . */
4472 do_cps_flags (char ** str
, int thumb_p
)
4477 unsigned long arm_value
;
4478 unsigned long thumb_value
;
4480 static struct cps_flag flag_table
[] =
4489 skip_whitespace (*str
);
4491 /* Get the a, f and i flags. */
4492 while (**str
&& **str
!= ',')
4495 struct cps_flag
*q
= flag_table
+ sizeof (flag_table
)/sizeof (*p
);
4497 for (p
= flag_table
; p
< q
; ++p
)
4498 if (strncasecmp (*str
, &p
->character
, 1) == 0)
4500 inst
.instruction
|= (thumb_p
? p
->thumb_value
: p
->arm_value
);
4506 inst
.error
= _("unrecognized flag");
4513 inst
.error
= _("no 'a', 'i', or 'f' flags for 'cps'");
4517 do_cpsi (char * str
)
4519 do_cps_flags (&str
, /*thumb_p=*/0);
4521 if (skip_past_comma (&str
) == SUCCESS
)
4523 skip_whitespace (str
);
4529 /* ARM V6T2 bitfield manipulation instructions. */
4532 five_bit_unsigned_immediate (char **str
)
4536 skip_whitespace (*str
);
4537 if (!is_immediate_prefix (**str
))
4539 inst
.error
= _("immediate expression expected");
4543 if (my_get_expression (&expr
, str
))
4545 inst
.error
= _("bad expression");
4548 if (expr
.X_op
!= O_constant
)
4550 inst
.error
= _("constant expression expected");
4553 if (expr
.X_add_number
< 0 || expr
.X_add_number
> 32)
4555 inst
.error
= _("immediate value out of range");
4559 return expr
.X_add_number
;
4563 bfci_lsb_and_width (char *str
)
4567 if ((lsb
= five_bit_unsigned_immediate (&str
)) == -1)
4570 if (skip_past_comma (&str
) == FAIL
)
4572 inst
.error
= BAD_ARGS
;
4575 if ((width
= five_bit_unsigned_immediate (&str
)) == -1)
4580 if (width
== 0 || lsb
== 32)
4582 inst
.error
= _("immediate value out of range");
4585 else if (width
+ lsb
> 32)
4587 inst
.error
= _("bit-field extends past end of register");
4591 /* Convert to LSB/MSB and write to register. */
4592 inst
.instruction
|= lsb
<< 7;
4593 inst
.instruction
|= (width
+ lsb
- 1) << 16;
4602 skip_whitespace (str
);
4603 if (((rd
= reg_required_here (&str
, 12)) == FAIL
)
4604 || (skip_past_comma (&str
) == FAIL
))
4606 inst
.error
= BAD_ARGS
;
4609 else if (rd
== REG_PC
)
4611 inst
.error
= BAD_PC
;
4615 bfci_lsb_and_width (str
);
4624 skip_whitespace (str
);
4625 if (((rd
= reg_required_here (&str
, 12)) == FAIL
)
4626 || (skip_past_comma (&str
) == FAIL
))
4628 inst
.error
= BAD_ARGS
;
4631 else if (rd
== REG_PC
)
4633 inst
.error
= BAD_PC
;
4637 /* Rm. Accept #0 in this position as an alternative syntax for bfc. */
4638 skip_whitespace (str
);
4639 if (is_immediate_prefix (*str
))
4643 if (my_get_expression (&expr
, &str
))
4645 inst
.error
= _("bad expression");
4648 if (expr
.X_op
!= O_constant
)
4650 inst
.error
= _("constant expression expected");
4653 if (expr
.X_add_number
!= 0)
4655 inst
.error
= _("immediate value out of range");
4658 inst
.instruction
|= 0x0000000f; /* Rm = PC -> bfc, not bfi. */
4662 if ((rm
= reg_required_here (&str
, 0)) == FAIL
)
4664 inst
.error
= BAD_ARGS
;
4667 else if (rm
== REG_PC
)
4669 inst
.error
= BAD_PC
;
4673 if (skip_past_comma (&str
) == FAIL
)
4675 inst
.error
= BAD_ARGS
;
4679 bfci_lsb_and_width (str
);
4688 skip_whitespace (str
);
4689 if (reg_required_here (&str
, 12) == FAIL
4690 || skip_past_comma (&str
) == FAIL
)
4692 inst
.error
= BAD_ARGS
;
4697 skip_whitespace (str
);
4698 if (reg_required_here (&str
, 0) == FAIL
4699 || skip_past_comma (&str
) == FAIL
)
4701 inst
.error
= BAD_ARGS
;
4705 if ((lsb
= five_bit_unsigned_immediate (&str
)) == -1)
4708 if (skip_past_comma (&str
) == FAIL
)
4710 inst
.error
= BAD_ARGS
;
4713 if ((width
= five_bit_unsigned_immediate (&str
)) == -1)
4718 if (width
== 0 || lsb
== 32)
4720 inst
.error
= _("immediate value out of range");
4723 else if (width
+ lsb
> 32)
4725 inst
.error
= _("bit-field extends past end of register");
4729 inst
.instruction
|= lsb
<< 7;
4730 inst
.instruction
|= (width
- 1) << 16;
4737 skip_whitespace (str
);
4738 if (reg_required_here (&str
, 12) == FAIL
4739 || skip_past_comma (&str
) == FAIL
)
4741 inst
.error
= BAD_ARGS
;
4746 skip_whitespace (str
);
4747 if (reg_required_here (&str
, 0) == FAIL
)
4749 inst
.error
= BAD_ARGS
;
4756 /* ARM V6T2 16-bit immediate register load: MOV[WT]{cond} Rd, #<imm16>. */
4758 do_mov16 (char *str
)
4764 skip_whitespace (str
);
4765 if (((rd
= reg_required_here (&str
, 12)) == FAIL
)
4766 || (skip_past_comma (&str
) == FAIL
))
4768 inst
.error
= BAD_ARGS
;
4771 else if (rd
== REG_PC
)
4773 inst
.error
= BAD_PC
;
4778 skip_whitespace (str
);
4779 if (!is_immediate_prefix (*str
))
4781 inst
.error
= _("immediate expression expected");
4785 if (my_get_expression (&expr
, &str
))
4787 inst
.error
= _("bad expression");
4790 if (expr
.X_op
!= O_constant
)
4792 inst
.error
= _("constant expression expected");
4795 if (expr
.X_add_number
< 0 || expr
.X_add_number
> 65535)
4797 inst
.error
= _("immediate value out of range");
4803 /* The value is in two pieces: 0:11, 16:19. */
4804 inst
.instruction
|= (expr
.X_add_number
& 0x00000fff);
4805 inst
.instruction
|= (expr
.X_add_number
& 0x0000f000) << 4;
4809 /* THUMB V5 breakpoint instruction (argument parse)
4813 do_t_bkpt (char * str
)
4816 unsigned long number
;
4818 skip_whitespace (str
);
4820 /* Allow optional leading '#'. */
4821 if (is_immediate_prefix (*str
))
4824 memset (& expr
, '\0', sizeof (expr
));
4825 if (my_get_expression (& expr
, & str
)
4826 || (expr
.X_op
!= O_constant
4827 /* As a convenience we allow 'bkpt' without an operand. */
4828 && expr
.X_op
!= O_absent
))
4830 inst
.error
= _("bad expression");
4834 number
= expr
.X_add_number
;
4836 /* Check it fits an 8 bit unsigned. */
4837 if (number
!= (number
& 0xff))
4839 inst
.error
= _("immediate value out of range");
4843 inst
.instruction
|= number
;
4849 static bfd_reloc_code_real_type
4850 arm_parse_reloc (void)
4859 bfd_reloc_code_real_type reloc
;
4863 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
4864 MAP ("(got)", BFD_RELOC_ARM_GOT32
),
4865 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF
),
4866 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
4867 branch instructions generated by GCC for PLT relocs. */
4868 MAP ("(plt)", BFD_RELOC_ARM_PLT32
),
4869 MAP ("(target1)", BFD_RELOC_ARM_TARGET1
),
4870 MAP ("(sbrel)", BFD_RELOC_ARM_SBREL32
),
4871 MAP ("(target2)", BFD_RELOC_ARM_TARGET2
),
4872 { NULL
, 0, BFD_RELOC_UNUSED
}
4876 for (i
= 0, ip
= input_line_pointer
;
4877 i
< sizeof (id
) && (ISALNUM (*ip
) || ISPUNCT (*ip
));
4879 id
[i
] = TOLOWER (*ip
);
4881 for (i
= 0; reloc_map
[i
].str
; i
++)
4882 if (strncmp (id
, reloc_map
[i
].str
, reloc_map
[i
].len
) == 0)
4885 input_line_pointer
+= reloc_map
[i
].len
;
4887 return reloc_map
[i
].reloc
;
4891 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
4892 Expects inst.instruction is set for BLX(1).
4893 Note: this is cloned from do_branch, and the reloc changed to be a
4894 new one that can cope with setting one extra bit (the H bit). */
4897 do_branch25 (char * str
)
4899 if (my_get_expression (& inst
.reloc
.exp
, & str
))
4906 /* ScottB: February 5, 1998 */
4907 /* Check to see of PLT32 reloc required for the instruction. */
4909 /* arm_parse_reloc() works on input_line_pointer.
4910 We actually want to parse the operands to the branch instruction
4911 passed in 'str'. Save the input pointer and restore it later. */
4912 save_in
= input_line_pointer
;
4913 input_line_pointer
= str
;
4915 if (inst
.reloc
.exp
.X_op
== O_symbol
4917 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
4919 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
4920 inst
.reloc
.pc_rel
= 0;
4921 /* Modify str to point to after parsed operands, otherwise
4922 end_of_line() will complain about the (PLT) left in str. */
4923 str
= input_line_pointer
;
4927 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
4928 inst
.reloc
.pc_rel
= 1;
4931 input_line_pointer
= save_in
;
4934 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
4935 inst
.reloc
.pc_rel
= 1;
4936 #endif /* OBJ_ELF */
4941 /* ARM V5 branch-link-exchange instruction (argument parse)
4942 BLX <target_addr> ie BLX(1)
4943 BLX{<condition>} <Rm> ie BLX(2)
4944 Unfortunately, there are two different opcodes for this mnemonic.
4945 So, the insns[].value is not used, and the code here zaps values
4946 into inst.instruction.
4947 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
4955 skip_whitespace (mystr
);
4956 rm
= reg_required_here (& mystr
, 0);
4958 /* The above may set inst.error. Ignore his opinion. */
4963 /* Arg is a register.
4964 Use the condition code our caller put in inst.instruction.
4965 Pass ourselves off as a BX with a funny opcode. */
4966 inst
.instruction
|= 0x012fff30;
4971 /* This must be is BLX <target address>, no condition allowed. */
4972 if (inst
.instruction
!= COND_ALWAYS
)
4974 inst
.error
= BAD_COND
;
4978 inst
.instruction
= 0xfafffffe;
4980 /* Process like a B/BL, but with a different reloc.
4981 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
4986 /* ARM V5 Thumb BLX (argument parse)
4987 BLX <target_addr> which is BLX(1)
4988 BLX <Rm> which is BLX(2)
4989 Unfortunately, there are two different opcodes for this mnemonic.
4990 So, the tinsns[].value is not used, and the code here zaps values
4991 into inst.instruction. */
4994 do_t_blx (char * str
)
4999 skip_whitespace (mystr
);
5000 inst
.instruction
= 0x4780;
5002 /* Note that this call is to the ARM register recognizer. BLX(2)
5003 uses the ARM register space, not the Thumb one, so a call to
5004 thumb_reg() would be wrong. */
5005 rm
= reg_required_here (& mystr
, 3);
5010 /* It's BLX(2). The .instruction was zapped with rm & is final. */
5015 /* No ARM register. This must be BLX(1). Change the .instruction. */
5016 inst
.instruction
= 0xf7ffeffe;
5019 if (my_get_expression (& inst
.reloc
.exp
, & mystr
))
5022 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BLX
;
5023 inst
.reloc
.pc_rel
= 1;
5026 end_of_line (mystr
);
5029 /* ARM V5 breakpoint instruction (argument parse)
5030 BKPT <16 bit unsigned immediate>
5031 Instruction is not conditional.
5032 The bit pattern given in insns[] has the COND_ALWAYS condition,
5033 and it is an error if the caller tried to override that. */
5036 do_bkpt (char * str
)
5039 unsigned long number
;
5041 skip_whitespace (str
);
5043 /* Allow optional leading '#'. */
5044 if (is_immediate_prefix (* str
))
5047 memset (& expr
, '\0', sizeof (expr
));
5049 if (my_get_expression (& expr
, & str
)
5050 || (expr
.X_op
!= O_constant
5051 /* As a convenience we allow 'bkpt' without an operand. */
5052 && expr
.X_op
!= O_absent
))
5054 inst
.error
= _("bad expression");
5058 number
= expr
.X_add_number
;
5060 /* Check it fits a 16 bit unsigned. */
5061 if (number
!= (number
& 0xffff))
5063 inst
.error
= _("immediate value out of range");
5067 /* Top 12 of 16 bits to bits 19:8. */
5068 inst
.instruction
|= (number
& 0xfff0) << 4;
5070 /* Bottom 4 of 16 bits to bits 3:0. */
5071 inst
.instruction
|= number
& 0xf;
5076 /* THUMB CPS instruction (argument parse). */
5079 do_t_cps (char * str
)
5081 do_cps_flags (&str
, /*thumb_p=*/1);
5085 /* Parse and validate that a register is of the right form, this saves
5086 repeated checking of this information in many similar cases.
5087 Unlike the 32-bit case we do not insert the register into the opcode
5088 here, since the position is often unknown until the full instruction
5092 thumb_reg (char ** strp
, int hi_lo
)
5096 if ((reg
= reg_required_here (strp
, -1)) == FAIL
)
5104 inst
.error
= _("lo register required");
5112 inst
.error
= _("hi register required");
5125 thumb_mov_compare (char * str
, int move
)
5129 skip_whitespace (str
);
5131 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
5132 || skip_past_comma (&str
) == FAIL
)
5135 inst
.error
= BAD_ARGS
;
5139 if (move
!= THUMB_CPY
&& is_immediate_prefix (*str
))
5142 if (my_get_expression (&inst
.reloc
.exp
, &str
))
5145 else if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
5150 if (move
!= THUMB_CPY
&& Rs
< 8 && Rd
< 8)
5152 if (move
== THUMB_MOVE
)
5153 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
5154 since a MOV instruction produces unpredictable results. */
5155 inst
.instruction
= T_OPCODE_ADD_I3
;
5157 inst
.instruction
= T_OPCODE_CMP_LR
;
5158 inst
.instruction
|= Rd
| (Rs
<< 3);
5162 if (move
== THUMB_MOVE
)
5163 inst
.instruction
= T_OPCODE_MOV_HR
;
5164 else if (move
!= THUMB_CPY
)
5165 inst
.instruction
= T_OPCODE_CMP_HR
;
5168 inst
.instruction
|= THUMB_H1
;
5171 inst
.instruction
|= THUMB_H2
;
5173 inst
.instruction
|= (Rd
& 7) | ((Rs
& 7) << 3);
5180 inst
.error
= _("only lo regs allowed with immediate");
5184 if (move
== THUMB_MOVE
)
5185 inst
.instruction
= T_OPCODE_MOV_I8
;
5187 inst
.instruction
= T_OPCODE_CMP_I8
;
5189 inst
.instruction
|= Rd
<< 8;
5191 if (inst
.reloc
.exp
.X_op
!= O_constant
)
5192 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_IMM
;
5195 unsigned value
= inst
.reloc
.exp
.X_add_number
;
5199 inst
.error
= _("invalid immediate");
5203 inst
.instruction
|= value
;
5210 /* THUMB CPY instruction (argument parse). */
5213 do_t_cpy (char * str
)
5215 thumb_mov_compare (str
, THUMB_CPY
);
5218 /* THUMB SETEND instruction (argument parse). */
5221 do_t_setend (char * str
)
5223 if (do_endian_specifier (str
))
5224 inst
.instruction
|= 0x8;
5227 /* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
5229 static unsigned long
5230 check_iwmmxt_insn (char * str
,
5231 enum iwmmxt_insn_type insn_type
,
5235 const char * inst_error
;
5237 unsigned long number
;
5239 inst_error
= inst
.error
;
5241 inst
.error
= BAD_ARGS
;
5242 skip_whitespace (str
);
5247 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
5252 if ((wreg_required_here (&str
, 0, IWMMXT_REG_WR
)) == FAIL
)
5257 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
5258 || skip_past_comma (&str
) == FAIL
5259 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
))
5264 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
5265 || skip_past_comma (&str
) == FAIL
5266 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5267 || skip_past_comma (&str
) == FAIL
5268 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
))
5273 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
5274 || skip_past_comma (&str
) == FAIL
5275 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5276 || skip_past_comma (&str
) == FAIL
5277 || wreg_required_here (&str
, 0, IWMMXT_REG_WCG
) == FAIL
))
5282 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5283 || skip_past_comma (&str
) == FAIL
5284 || reg_required_here (&str
, 12) == FAIL
))
5289 if ((reg_required_here (&str
, 12) == FAIL
5290 || skip_past_comma (&str
) == FAIL
5291 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
))
5296 if ((wreg_required_here (&str
, 5, IWMMXT_REG_WR
) == FAIL
5297 || skip_past_comma (&str
) == FAIL
5298 || reg_required_here (&str
, 0) == FAIL
5299 || skip_past_comma (&str
) == FAIL
5300 || reg_required_here (&str
, 12) == FAIL
))
5305 if ((wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
5306 || skip_past_comma (&str
) == FAIL
5307 || reg_required_here (&str
, 12) == FAIL
5308 || skip_past_comma (&str
) == FAIL
5309 || reg_required_here (&str
, 16) == FAIL
))
5314 if ((reg_required_here (&str
, 12) == FAIL
5315 || skip_past_comma (&str
) == FAIL
5316 || reg_required_here (&str
, 16) == FAIL
5317 || skip_past_comma (&str
) == FAIL
5318 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
))
5323 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WC
) == FAIL
5324 || skip_past_comma (&str
) == FAIL
5325 || reg_required_here (&str
, 12) == FAIL
))
5330 if ((reg_required_here (&str
, 12) == FAIL
5331 || skip_past_comma (&str
) == FAIL
5332 || wreg_required_here (&str
, 16, IWMMXT_REG_WC
) == FAIL
))
5337 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5338 || skip_past_comma (&str
) == FAIL
5339 || reg_required_here (&str
, 12) == FAIL
5340 || skip_past_comma (&str
) == FAIL
))
5345 if ((reg_required_here (&str
, 12) == FAIL
5346 || skip_past_comma (&str
) == FAIL
))
5351 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
5352 || skip_past_comma (&str
) == FAIL
5353 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5354 || skip_past_comma (&str
) == FAIL
5355 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
5356 || skip_past_comma (&str
) == FAIL
))
5361 if ((reg_required_here (&str
, 12) == FAIL
5362 || skip_past_comma (&str
) == FAIL
5363 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5364 || skip_past_comma (&str
) == FAIL
))
5369 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
5370 || skip_past_comma (&str
) == FAIL
5371 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5372 || skip_past_comma (&str
) == FAIL
))
5377 if (immediate_size
== 0)
5380 inst
.error
= inst_error
;
5385 skip_whitespace (str
);
5387 /* Allow optional leading '#'. */
5388 if (is_immediate_prefix (* str
))
5391 memset (& expr
, '\0', sizeof (expr
));
5393 if (my_get_expression (& expr
, & str
) || (expr
.X_op
!= O_constant
))
5395 inst
.error
= _("bad or missing expression");
5399 number
= expr
.X_add_number
;
5401 if (number
!= (number
& immediate_size
))
5403 inst
.error
= _("immediate value out of range");
5407 inst
.error
= inst_error
;
5413 do_iwmmxt_byte_addr (char * str
)
5415 int op
= (inst
.instruction
& 0x300) >> 8;
5418 inst
.instruction
&= ~0x300;
5419 inst
.instruction
|= (op
& 1) << 22 | (op
& 2) << 7;
5421 skip_whitespace (str
);
5423 if ((reg
= wreg_required_here (&str
, 12, IWMMXT_REG_WR_OR_WC
)) == FAIL
5424 || skip_past_comma (& str
) == FAIL
5425 || cp_byte_address_required_here (&str
) == FAIL
)
5428 inst
.error
= BAD_ARGS
;
5433 if (wc_register (reg
))
5435 as_bad (_("non-word size not supported with control register"));
5436 inst
.instruction
|= 0xf0000100;
5437 inst
.instruction
&= ~0x00400000;
5442 do_iwmmxt_tandc (char * str
)
5446 reg
= check_iwmmxt_insn (str
, check_rd
, 0);
5448 if (reg
!= REG_PC
&& !inst
.error
)
5449 inst
.error
= _("only r15 allowed here");
5453 do_iwmmxt_tbcst (char * str
)
5455 check_iwmmxt_insn (str
, check_tbcst
, 0);
5459 do_iwmmxt_textrc (char * str
)
5461 unsigned long number
;
5463 if ((number
= check_iwmmxt_insn (str
, check_textrc
, 7)) == (unsigned long) FAIL
)
5466 inst
.instruction
|= number
& 0x7;
5470 do_iwmmxt_textrm (char * str
)
5472 unsigned long number
;
5474 if ((number
= check_iwmmxt_insn (str
, check_textrm
, 7)) == (unsigned long) FAIL
)
5477 inst
.instruction
|= number
& 0x7;
5481 do_iwmmxt_tinsr (char * str
)
5483 unsigned long number
;
5485 if ((number
= check_iwmmxt_insn (str
, check_tinsr
, 7)) == (unsigned long) FAIL
)
5488 inst
.instruction
|= number
& 0x7;
5492 do_iwmmxt_tmcr (char * str
)
5494 check_iwmmxt_insn (str
, check_tmcr
, 0);
5498 do_iwmmxt_tmcrr (char * str
)
5500 check_iwmmxt_insn (str
, check_tmcrr
, 0);
5504 do_iwmmxt_tmia (char * str
)
5506 check_iwmmxt_insn (str
, check_tmia
, 0);
5510 do_iwmmxt_tmovmsk (char * str
)
5512 check_iwmmxt_insn (str
, check_tmovmsk
, 0);
5516 do_iwmmxt_tmrc (char * str
)
5518 check_iwmmxt_insn (str
, check_tmrc
, 0);
5522 do_iwmmxt_tmrrc (char * str
)
5524 check_iwmmxt_insn (str
, check_tmrrc
, 0);
5528 do_iwmmxt_torc (char * str
)
5530 check_iwmmxt_insn (str
, check_rd
, 0);
5534 do_iwmmxt_waligni (char * str
)
5536 unsigned long number
;
5538 if ((number
= check_iwmmxt_insn (str
, check_waligni
, 7)) == (unsigned long) FAIL
)
5541 inst
.instruction
|= ((number
& 0x7) << 20);
5545 do_iwmmxt_wmov (char * str
)
5547 if (check_iwmmxt_insn (str
, check_wrwr
, 0) == (unsigned long) FAIL
)
5550 inst
.instruction
|= ((inst
.instruction
>> 16) & 0xf);
5554 do_iwmmxt_word_addr (char * str
)
5556 int op
= (inst
.instruction
& 0x300) >> 8;
5559 inst
.instruction
&= ~0x300;
5560 inst
.instruction
|= (op
& 1) << 22 | (op
& 2) << 7;
5562 skip_whitespace (str
);
5564 if ((reg
= wreg_required_here (&str
, 12, IWMMXT_REG_WR_OR_WC
)) == FAIL
5565 || skip_past_comma (& str
) == FAIL
5566 || cp_address_required_here (& str
, CP_WB_OK
) == FAIL
)
5569 inst
.error
= BAD_ARGS
;
5574 if (wc_register (reg
))
5576 if ((inst
.instruction
& COND_MASK
) != COND_ALWAYS
)
5577 as_bad (_("conditional execution not supported with control register"));
5579 as_bad (_("non-word size not supported with control register"));
5580 inst
.instruction
|= 0xf0000100;
5581 inst
.instruction
&= ~0x00400000;
5586 do_iwmmxt_wrwr (char * str
)
5588 check_iwmmxt_insn (str
, check_wrwr
, 0);
5592 do_iwmmxt_wrwrwcg (char * str
)
5594 check_iwmmxt_insn (str
, check_wrwrwcg
, 0);
5598 do_iwmmxt_wrwrwr (char * str
)
5600 check_iwmmxt_insn (str
, check_wrwrwr
, 0);
5604 do_iwmmxt_wshufh (char * str
)
5606 unsigned long number
;
5608 if ((number
= check_iwmmxt_insn (str
, check_wshufh
, 0xff)) == (unsigned long) FAIL
)
5611 inst
.instruction
|= ((number
& 0xf0) << 16) | (number
& 0xf);
5615 do_iwmmxt_wzero (char * str
)
5617 if (check_iwmmxt_insn (str
, check_wr
, 0) == (unsigned long) FAIL
)
5620 inst
.instruction
|= ((inst
.instruction
& 0xf) << 12) | ((inst
.instruction
& 0xf) << 16);
5623 /* Xscale multiply-accumulate (argument parse)
5626 MIAxycc acc0,Rm,Rs. */
5629 do_xsc_mia (char * str
)
5634 if (accum0_required_here (& str
) == FAIL
)
5635 inst
.error
= ERR_NO_ACCUM
;
5637 else if (skip_past_comma (& str
) == FAIL
5638 || (rm
= reg_required_here (& str
, 0)) == FAIL
)
5639 inst
.error
= BAD_ARGS
;
5641 else if (skip_past_comma (& str
) == FAIL
5642 || (rs
= reg_required_here (& str
, 12)) == FAIL
)
5643 inst
.error
= BAD_ARGS
;
5645 /* inst.instruction has now been zapped with both rm and rs. */
5646 else if (rm
== REG_PC
|| rs
== REG_PC
)
5647 inst
.error
= BAD_PC
; /* Undefined result if rm or rs is R15. */
5653 /* Xscale move-accumulator-register (argument parse)
5655 MARcc acc0,RdLo,RdHi. */
5658 do_xsc_mar (char * str
)
5662 if (accum0_required_here (& str
) == FAIL
)
5663 inst
.error
= ERR_NO_ACCUM
;
5665 else if (skip_past_comma (& str
) == FAIL
5666 || (rdlo
= reg_required_here (& str
, 12)) == FAIL
)
5667 inst
.error
= BAD_ARGS
;
5669 else if (skip_past_comma (& str
) == FAIL
5670 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
5671 inst
.error
= BAD_ARGS
;
5673 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5674 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
5675 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
5681 /* Xscale move-register-accumulator (argument parse)
5683 MRAcc RdLo,RdHi,acc0. */
5686 do_xsc_mra (char * str
)
5691 skip_whitespace (str
);
5693 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
)
5694 inst
.error
= BAD_ARGS
;
5696 else if (skip_past_comma (& str
) == FAIL
5697 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
5698 inst
.error
= BAD_ARGS
;
5700 else if (skip_past_comma (& str
) == FAIL
5701 || accum0_required_here (& str
) == FAIL
)
5702 inst
.error
= ERR_NO_ACCUM
;
5704 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5705 else if (rdlo
== rdhi
)
5706 inst
.error
= BAD_ARGS
; /* Undefined result if 2 writes to same reg. */
5708 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
5709 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
5715 ldst_extend (char ** str
)
5724 if (my_get_expression (& inst
.reloc
.exp
, str
))
5727 if (inst
.reloc
.exp
.X_op
== O_constant
)
5729 int value
= inst
.reloc
.exp
.X_add_number
;
5731 if (value
< -4095 || value
> 4095)
5733 inst
.error
= _("address offset too large");
5743 inst
.instruction
|= add
| value
;
5747 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
5748 inst
.reloc
.pc_rel
= 0;
5761 if (reg_required_here (str
, 0) == FAIL
)
5764 inst
.instruction
|= add
| OFFSET_REG
;
5765 if (skip_past_comma (str
) == SUCCESS
)
5766 return decode_shift (str
, SHIFT_IMMEDIATE
);
5772 /* ARMv5TE: Preload-Cache
5776 Syntactically, like LDR with B=1, W=0, L=1. */
5783 skip_whitespace (str
);
5787 inst
.error
= _("'[' expected after PLD mnemonic");
5792 skip_whitespace (str
);
5794 if ((rd
= reg_required_here (& str
, 16)) == FAIL
)
5797 skip_whitespace (str
);
5803 skip_whitespace (str
);
5805 /* Post-indexed addressing is not allowed with PLD. */
5806 if (skip_past_comma (&str
) == SUCCESS
)
5809 = _("post-indexed expression used in preload instruction");
5812 else if (*str
== '!') /* [Rn]! */
5814 inst
.error
= _("writeback used in preload instruction");
5818 inst
.instruction
|= INDEX_UP
| PRE_INDEX
;
5820 else /* [Rn, ...] */
5822 if (skip_past_comma (& str
) == FAIL
)
5824 inst
.error
= _("pre-indexed expression expected");
5828 if (ldst_extend (&str
) == FAIL
)
5831 skip_whitespace (str
);
5835 inst
.error
= _("missing ]");
5840 skip_whitespace (str
);
5842 if (* str
== '!') /* [Rn]! */
5844 inst
.error
= _("writeback used in preload instruction");
5848 inst
.instruction
|= PRE_INDEX
;
5854 /* ARMv5TE load-consecutive (argument parse)
5861 do_ldrd (char * str
)
5866 skip_whitespace (str
);
5868 if ((rd
= reg_required_here (& str
, 12)) == FAIL
)
5870 inst
.error
= BAD_ARGS
;
5874 if (skip_past_comma (& str
) == FAIL
5875 || (rn
= ld_mode_required_here (& str
)) == FAIL
)
5878 inst
.error
= BAD_ARGS
;
5882 /* inst.instruction has now been zapped with Rd and the addressing mode. */
5883 if (rd
& 1) /* Unpredictable result if Rd is odd. */
5885 inst
.error
= _("destination register must be even");
5891 inst
.error
= _("r14 not allowed here");
5895 if (((rd
== rn
) || (rd
+ 1 == rn
))
5896 && ((inst
.instruction
& WRITE_BACK
)
5897 || (!(inst
.instruction
& PRE_INDEX
))))
5898 as_warn (_("pre/post-indexing used when modified address register is destination"));
5900 /* For an index-register load, the index register must not overlap the
5901 destination (even if not write-back). */
5902 if ((inst
.instruction
& V4_STR_BIT
) == 0
5903 && (inst
.instruction
& HWOFFSET_IMM
) == 0)
5905 int rm
= inst
.instruction
& 0x0000000f;
5907 if (rm
== rd
|| (rm
== rd
+ 1))
5908 as_warn (_("ldrd destination registers must not overlap index register"));
5914 /* Returns the index into fp_values of a floating point number,
5915 or -1 if not in the table. */
5918 my_get_float_expression (char ** str
)
5920 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
5926 memset (words
, 0, MAX_LITTLENUMS
* sizeof (LITTLENUM_TYPE
));
5928 /* Look for a raw floating point number. */
5929 if ((save_in
= atof_ieee (*str
, 'x', words
)) != NULL
5930 && is_end_of_line
[(unsigned char) *save_in
])
5932 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
5934 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
5936 if (words
[j
] != fp_values
[i
][j
])
5940 if (j
== MAX_LITTLENUMS
)
5948 /* Try and parse a more complex expression, this will probably fail
5949 unless the code uses a floating point prefix (eg "0f"). */
5950 save_in
= input_line_pointer
;
5951 input_line_pointer
= *str
;
5952 if (expression (&exp
) == absolute_section
5953 && exp
.X_op
== O_big
5954 && exp
.X_add_number
< 0)
5956 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
5958 if (gen_to_words (words
, 5, (long) 15) == 0)
5960 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
5962 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
5964 if (words
[j
] != fp_values
[i
][j
])
5968 if (j
== MAX_LITTLENUMS
)
5970 *str
= input_line_pointer
;
5971 input_line_pointer
= save_in
;
5978 *str
= input_line_pointer
;
5979 input_line_pointer
= save_in
;
5983 /* We handle all bad expressions here, so that we can report the faulty
5984 instruction in the error message. */
5986 md_operand (expressionS
* expr
)
5988 if (in_my_get_expression
)
5990 expr
->X_op
= O_illegal
;
5991 if (inst
.error
== NULL
)
5992 inst
.error
= _("bad expression");
5996 /* Do those data_ops which can take a negative immediate constant
5997 by altering the instruction. A bit of a hack really.
6001 by inverting the second operand, and
6004 by negating the second operand. */
6007 negate_data_op (unsigned long * instruction
,
6008 unsigned long value
)
6011 unsigned long negated
, inverted
;
6013 negated
= validate_immediate (-value
);
6014 inverted
= validate_immediate (~value
);
6016 op
= (*instruction
>> DATA_OP_SHIFT
) & 0xf;
6019 /* First negates. */
6020 case OPCODE_SUB
: /* ADD <-> SUB */
6021 new_inst
= OPCODE_ADD
;
6026 new_inst
= OPCODE_SUB
;
6030 case OPCODE_CMP
: /* CMP <-> CMN */
6031 new_inst
= OPCODE_CMN
;
6036 new_inst
= OPCODE_CMP
;
6040 /* Now Inverted ops. */
6041 case OPCODE_MOV
: /* MOV <-> MVN */
6042 new_inst
= OPCODE_MVN
;
6047 new_inst
= OPCODE_MOV
;
6051 case OPCODE_AND
: /* AND <-> BIC */
6052 new_inst
= OPCODE_BIC
;
6057 new_inst
= OPCODE_AND
;
6061 case OPCODE_ADC
: /* ADC <-> SBC */
6062 new_inst
= OPCODE_SBC
;
6067 new_inst
= OPCODE_ADC
;
6071 /* We cannot do anything. */
6076 if (value
== (unsigned) FAIL
)
6079 *instruction
&= OPCODE_MASK
;
6080 *instruction
|= new_inst
<< DATA_OP_SHIFT
;
6085 data_op2 (char ** str
)
6090 skip_whitespace (* str
);
6092 if (reg_required_here (str
, 0) != FAIL
)
6094 if (skip_past_comma (str
) == SUCCESS
)
6095 /* Shift operation on register. */
6096 return decode_shift (str
, NO_SHIFT_RESTRICT
);
6102 /* Immediate expression. */
6103 if (is_immediate_prefix (**str
))
6108 if (my_get_expression (&inst
.reloc
.exp
, str
))
6111 if (inst
.reloc
.exp
.X_add_symbol
)
6113 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
6114 inst
.reloc
.pc_rel
= 0;
6118 if (skip_past_comma (str
) == SUCCESS
)
6120 /* #x, y -- ie explicit rotation by Y. */
6121 if (my_get_expression (&expr
, str
))
6124 if (expr
.X_op
!= O_constant
)
6126 inst
.error
= _("constant expression expected");
6130 /* Rotate must be a multiple of 2. */
6131 if (((unsigned) expr
.X_add_number
) > 30
6132 || (expr
.X_add_number
& 1) != 0
6133 || ((unsigned) inst
.reloc
.exp
.X_add_number
) > 255)
6135 inst
.error
= _("invalid constant");
6138 inst
.instruction
|= INST_IMMEDIATE
;
6139 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
6140 inst
.instruction
|= expr
.X_add_number
<< 7;
6144 /* Implicit rotation, select a suitable one. */
6145 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
6149 /* Can't be done. Perhaps the code reads something like
6150 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
6151 if ((value
= negate_data_op (&inst
.instruction
,
6152 inst
.reloc
.exp
.X_add_number
))
6155 inst
.error
= _("invalid constant");
6160 inst
.instruction
|= value
;
6163 inst
.instruction
|= INST_IMMEDIATE
;
6168 inst
.error
= _("register or shift expression expected");
6174 fp_op2 (char ** str
)
6176 skip_whitespace (* str
);
6178 if (fp_reg_required_here (str
, 0) != FAIL
)
6182 /* Immediate expression. */
6183 if (*((*str
)++) == '#')
6189 skip_whitespace (* str
);
6191 /* First try and match exact strings, this is to guarantee
6192 that some formats will work even for cross assembly. */
6194 for (i
= 0; fp_const
[i
]; i
++)
6196 if (strncmp (*str
, fp_const
[i
], strlen (fp_const
[i
])) == 0)
6200 *str
+= strlen (fp_const
[i
]);
6201 if (is_end_of_line
[(unsigned char) **str
])
6203 inst
.instruction
|= i
+ 8;
6210 /* Just because we didn't get a match doesn't mean that the
6211 constant isn't valid, just that it is in a format that we
6212 don't automatically recognize. Try parsing it with
6213 the standard expression routines. */
6214 if ((i
= my_get_float_expression (str
)) >= 0)
6216 inst
.instruction
|= i
+ 8;
6220 inst
.error
= _("invalid floating point immediate expression");
6224 _("floating point register or immediate expression expected");
6230 do_arit (char * str
)
6232 skip_whitespace (str
);
6234 if (reg_required_here (&str
, 12) == FAIL
6235 || skip_past_comma (&str
) == FAIL
6236 || reg_required_here (&str
, 16) == FAIL
6237 || skip_past_comma (&str
) == FAIL
6238 || data_op2 (&str
) == FAIL
)
6241 inst
.error
= BAD_ARGS
;
6251 /* This is a pseudo-op of the form "adr rd, label" to be converted
6252 into a relative address of the form "add rd, pc, #label-.-8". */
6253 skip_whitespace (str
);
6255 if (reg_required_here (&str
, 12) == FAIL
6256 || skip_past_comma (&str
) == FAIL
6257 || my_get_expression (&inst
.reloc
.exp
, &str
))
6260 inst
.error
= BAD_ARGS
;
6264 /* Frag hacking will turn this into a sub instruction if the offset turns
6265 out to be negative. */
6266 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
6268 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust. */
6270 inst
.reloc
.pc_rel
= 1;
6276 do_adrl (char * str
)
6278 /* This is a pseudo-op of the form "adrl rd, label" to be converted
6279 into a relative address of the form:
6280 add rd, pc, #low(label-.-8)"
6281 add rd, rd, #high(label-.-8)" */
6283 skip_whitespace (str
);
6285 if (reg_required_here (&str
, 12) == FAIL
6286 || skip_past_comma (&str
) == FAIL
6287 || my_get_expression (&inst
.reloc
.exp
, &str
))
6290 inst
.error
= BAD_ARGS
;
6296 /* Frag hacking will turn this into a sub instruction if the offset turns
6297 out to be negative. */
6298 inst
.reloc
.type
= BFD_RELOC_ARM_ADRL_IMMEDIATE
;
6300 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust */
6302 inst
.reloc
.pc_rel
= 1;
6303 inst
.size
= INSN_SIZE
* 2;
6309 skip_whitespace (str
);
6311 if (reg_required_here (&str
, 16) == FAIL
)
6314 inst
.error
= BAD_ARGS
;
6318 if (skip_past_comma (&str
) == FAIL
6319 || data_op2 (&str
) == FAIL
)
6322 inst
.error
= BAD_ARGS
;
6332 skip_whitespace (str
);
6334 if (reg_required_here (&str
, 12) == FAIL
)
6337 inst
.error
= BAD_ARGS
;
6341 if (skip_past_comma (&str
) == FAIL
6342 || data_op2 (&str
) == FAIL
)
6345 inst
.error
= BAD_ARGS
;
6353 do_ldst (char * str
)
6359 skip_whitespace (str
);
6361 if ((conflict_reg
= reg_required_here (&str
, 12)) == FAIL
)
6364 inst
.error
= BAD_ARGS
;
6368 if (skip_past_comma (&str
) == FAIL
)
6370 inst
.error
= _("address expected");
6380 skip_whitespace (str
);
6382 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6385 /* Conflicts can occur on stores as well as loads. */
6386 conflict_reg
= (conflict_reg
== reg
);
6388 skip_whitespace (str
);
6394 if (skip_past_comma (&str
) == SUCCESS
)
6396 /* [Rn],... (post inc) */
6397 if (ldst_extend (&str
) == FAIL
)
6400 as_warn (_("%s register same as write-back base"),
6401 ((inst
.instruction
& LOAD_BIT
)
6402 ? _("destination") : _("source")));
6407 skip_whitespace (str
);
6412 as_warn (_("%s register same as write-back base"),
6413 ((inst
.instruction
& LOAD_BIT
)
6414 ? _("destination") : _("source")));
6416 inst
.instruction
|= WRITE_BACK
;
6419 inst
.instruction
|= INDEX_UP
;
6426 if (skip_past_comma (&str
) == FAIL
)
6428 inst
.error
= _("pre-indexed expression expected");
6433 if (ldst_extend (&str
) == FAIL
)
6436 skip_whitespace (str
);
6440 inst
.error
= _("missing ]");
6444 skip_whitespace (str
);
6449 as_warn (_("%s register same as write-back base"),
6450 ((inst
.instruction
& LOAD_BIT
)
6451 ? _("destination") : _("source")));
6453 inst
.instruction
|= WRITE_BACK
;
6457 else if (*str
== '=')
6459 if ((inst
.instruction
& LOAD_BIT
) == 0)
6461 inst
.error
= _("invalid pseudo operation");
6465 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6468 skip_whitespace (str
);
6470 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6473 if (inst
.reloc
.exp
.X_op
!= O_constant
6474 && inst
.reloc
.exp
.X_op
!= O_symbol
)
6476 inst
.error
= _("constant expression expected");
6480 if (inst
.reloc
.exp
.X_op
== O_constant
)
6482 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
6486 /* This can be done with a mov instruction. */
6487 inst
.instruction
&= LITERAL_MASK
;
6488 inst
.instruction
|= (INST_IMMEDIATE
6489 | (OPCODE_MOV
<< DATA_OP_SHIFT
));
6490 inst
.instruction
|= value
& 0xfff;
6495 value
= validate_immediate (~inst
.reloc
.exp
.X_add_number
);
6499 /* This can be done with a mvn instruction. */
6500 inst
.instruction
&= LITERAL_MASK
;
6501 inst
.instruction
|= (INST_IMMEDIATE
6502 | (OPCODE_MVN
<< DATA_OP_SHIFT
));
6503 inst
.instruction
|= value
& 0xfff;
6509 /* Insert into literal pool. */
6510 if (add_to_lit_pool () == FAIL
)
6513 inst
.error
= _("literal pool insertion failed");
6517 /* Change the instruction exp to point to the pool. */
6518 inst
.reloc
.type
= BFD_RELOC_ARM_LITERAL
;
6519 inst
.reloc
.pc_rel
= 1;
6520 inst
.instruction
|= (REG_PC
<< 16);
6525 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6528 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
6530 /* PC rel adjust. */
6531 inst
.reloc
.exp
.X_add_number
-= 8;
6533 inst
.reloc
.pc_rel
= 1;
6534 inst
.instruction
|= (REG_PC
<< 16);
6538 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
6543 do_ldstt (char * str
)
6547 skip_whitespace (str
);
6549 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
6552 inst
.error
= BAD_ARGS
;
6556 if (skip_past_comma (& str
) == FAIL
)
6558 inst
.error
= _("address expected");
6568 skip_whitespace (str
);
6570 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6573 /* ldrt/strt always use post-indexed addressing, so if the base is
6574 the same as Rd, we warn. */
6575 if (conflict_reg
== reg
)
6576 as_warn (_("%s register same as write-back base"),
6577 ((inst
.instruction
& LOAD_BIT
)
6578 ? _("destination") : _("source")));
6580 skip_whitespace (str
);
6586 if (skip_past_comma (&str
) == SUCCESS
)
6588 /* [Rn],... (post inc) */
6589 if (ldst_extend (&str
) == FAIL
)
6595 skip_whitespace (str
);
6597 /* Skip a write-back '!'. */
6601 inst
.instruction
|= INDEX_UP
;
6606 inst
.error
= _("post-indexed expression expected");
6612 inst
.error
= _("post-indexed expression expected");
6619 /* Halfword and signed-byte load/store operations. */
6622 do_ldstv4 (char * str
)
6628 skip_whitespace (str
);
6630 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
6633 inst
.error
= BAD_ARGS
;
6637 if (skip_past_comma (& str
) == FAIL
)
6639 inst
.error
= _("address expected");
6649 skip_whitespace (str
);
6651 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6654 /* Conflicts can occur on stores as well as loads. */
6655 conflict_reg
= (conflict_reg
== reg
);
6657 skip_whitespace (str
);
6663 if (skip_past_comma (&str
) == SUCCESS
)
6665 /* [Rn],... (post inc) */
6666 if (ldst_extend_v4 (&str
) == FAIL
)
6669 as_warn (_("%s register same as write-back base"),
6670 ((inst
.instruction
& LOAD_BIT
)
6671 ? _("destination") : _("source")));
6676 inst
.instruction
|= HWOFFSET_IMM
;
6678 skip_whitespace (str
);
6683 as_warn (_("%s register same as write-back base"),
6684 ((inst
.instruction
& LOAD_BIT
)
6685 ? _("destination") : _("source")));
6687 inst
.instruction
|= WRITE_BACK
;
6690 inst
.instruction
|= INDEX_UP
;
6697 if (skip_past_comma (&str
) == FAIL
)
6699 inst
.error
= _("pre-indexed expression expected");
6704 if (ldst_extend_v4 (&str
) == FAIL
)
6707 skip_whitespace (str
);
6711 inst
.error
= _("missing ]");
6715 skip_whitespace (str
);
6720 as_warn (_("%s register same as write-back base"),
6721 ((inst
.instruction
& LOAD_BIT
)
6722 ? _("destination") : _("source")));
6724 inst
.instruction
|= WRITE_BACK
;
6728 else if (*str
== '=')
6730 if ((inst
.instruction
& LOAD_BIT
) == 0)
6732 inst
.error
= _("invalid pseudo operation");
6736 /* XXX Does this work correctly for half-word/byte ops? */
6737 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6740 skip_whitespace (str
);
6742 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6745 if (inst
.reloc
.exp
.X_op
!= O_constant
6746 && inst
.reloc
.exp
.X_op
!= O_symbol
)
6748 inst
.error
= _("constant expression expected");
6752 if (inst
.reloc
.exp
.X_op
== O_constant
)
6754 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
6758 /* This can be done with a mov instruction. */
6759 inst
.instruction
&= LITERAL_MASK
;
6760 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MOV
<< DATA_OP_SHIFT
);
6761 inst
.instruction
|= value
& 0xfff;
6766 value
= validate_immediate (~ inst
.reloc
.exp
.X_add_number
);
6770 /* This can be done with a mvn instruction. */
6771 inst
.instruction
&= LITERAL_MASK
;
6772 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MVN
<< DATA_OP_SHIFT
);
6773 inst
.instruction
|= value
& 0xfff;
6779 /* Insert into literal pool. */
6780 if (add_to_lit_pool () == FAIL
)
6783 inst
.error
= _("literal pool insertion failed");
6787 /* Change the instruction exp to point to the pool. */
6788 inst
.instruction
|= HWOFFSET_IMM
;
6789 inst
.reloc
.type
= BFD_RELOC_ARM_HWLITERAL
;
6790 inst
.reloc
.pc_rel
= 1;
6791 inst
.instruction
|= (REG_PC
<< 16);
6796 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6799 inst
.instruction
|= HWOFFSET_IMM
;
6800 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
6802 /* PC rel adjust. */
6803 inst
.reloc
.exp
.X_add_number
-= 8;
6805 inst
.reloc
.pc_rel
= 1;
6806 inst
.instruction
|= (REG_PC
<< 16);
6810 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
6815 do_ldsttv4 (char * str
)
6819 skip_whitespace (str
);
6821 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
6824 inst
.error
= BAD_ARGS
;
6828 if (skip_past_comma (& str
) == FAIL
)
6830 inst
.error
= _("address expected");
6840 skip_whitespace (str
);
6842 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6845 /* ldrt/strt always use post-indexed addressing, so if the base is
6846 the same as Rd, we warn. */
6847 if (conflict_reg
== reg
)
6848 as_warn (_("%s register same as write-back base"),
6849 ((inst
.instruction
& LOAD_BIT
)
6850 ? _("destination") : _("source")));
6852 skip_whitespace (str
);
6858 if (skip_past_comma (&str
) == SUCCESS
)
6860 /* [Rn],... (post inc) */
6861 if (ldst_extend_v4 (&str
) == FAIL
)
6867 skip_whitespace (str
);
6869 /* Skip a write-back '!'. */
6873 inst
.instruction
|= (INDEX_UP
|HWOFFSET_IMM
);
6878 inst
.error
= _("post-indexed expression expected");
6884 inst
.error
= _("post-indexed expression expected");
6893 reg_list (char ** strp
)
6895 char * str
= * strp
;
6899 /* We come back here if we get ranges concatenated by '+' or '|'. */
6914 skip_whitespace (str
);
6916 if ((reg
= reg_required_here (& str
, -1)) == FAIL
)
6925 inst
.error
= _("bad range in register list");
6929 for (i
= cur_reg
+ 1; i
< reg
; i
++)
6931 if (range
& (1 << i
))
6933 (_("Warning: duplicated register (r%d) in register list"),
6941 if (range
& (1 << reg
))
6942 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
6944 else if (reg
<= cur_reg
)
6945 as_tsktsk (_("Warning: register range not in ascending order"));
6950 while (skip_past_comma (&str
) != FAIL
6951 || (in_range
= 1, *str
++ == '-'));
6953 skip_whitespace (str
);
6957 inst
.error
= _("missing `}'");
6965 if (my_get_expression (&expr
, &str
))
6968 if (expr
.X_op
== O_constant
)
6970 if (expr
.X_add_number
6971 != (expr
.X_add_number
& 0x0000ffff))
6973 inst
.error
= _("invalid register mask");
6977 if ((range
& expr
.X_add_number
) != 0)
6979 int regno
= range
& expr
.X_add_number
;
6982 regno
= (1 << regno
) - 1;
6984 (_("Warning: duplicated register (r%d) in register list"),
6988 range
|= expr
.X_add_number
;
6992 if (inst
.reloc
.type
!= 0)
6994 inst
.error
= _("expression too complex");
6998 memcpy (&inst
.reloc
.exp
, &expr
, sizeof (expressionS
));
6999 inst
.reloc
.type
= BFD_RELOC_ARM_MULTI
;
7000 inst
.reloc
.pc_rel
= 0;
7004 skip_whitespace (str
);
7006 if (*str
== '|' || *str
== '+')
7012 while (another_range
);
7019 do_ldmstm (char * str
)
7024 skip_whitespace (str
);
7026 if ((base_reg
= reg_required_here (&str
, 16)) == FAIL
)
7029 if (base_reg
== REG_PC
)
7031 inst
.error
= _("r15 not allowed as base register");
7035 skip_whitespace (str
);
7039 inst
.instruction
|= WRITE_BACK
;
7043 if (skip_past_comma (&str
) == FAIL
7044 || (range
= reg_list (&str
)) == FAIL
)
7047 inst
.error
= BAD_ARGS
;
7054 inst
.instruction
|= LDM_TYPE_2_OR_3
;
7057 if (inst
.instruction
& WRITE_BACK
)
7059 /* Check for unpredictable uses of writeback. */
7060 if (inst
.instruction
& LOAD_BIT
)
7062 /* Not allowed in LDM type 2. */
7063 if ((inst
.instruction
& LDM_TYPE_2_OR_3
)
7064 && ((range
& (1 << REG_PC
)) == 0))
7065 as_warn (_("writeback of base register is UNPREDICTABLE"));
7066 /* Only allowed if base reg not in list for other types. */
7067 else if (range
& (1 << base_reg
))
7068 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
7072 /* Not allowed for type 2. */
7073 if (inst
.instruction
& LDM_TYPE_2_OR_3
)
7074 as_warn (_("writeback of base register is UNPREDICTABLE"));
7075 /* Only allowed if base reg not in list, or first in list. */
7076 else if ((range
& (1 << base_reg
))
7077 && (range
& ((1 << base_reg
) - 1)))
7078 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
7082 inst
.instruction
|= range
;
7089 skip_whitespace (str
);
7091 /* Allow optional leading '#'. */
7092 if (is_immediate_prefix (*str
))
7095 if (my_get_expression (& inst
.reloc
.exp
, & str
))
7098 inst
.reloc
.type
= BFD_RELOC_ARM_SMI
;
7099 inst
.reloc
.pc_rel
= 0;
7106 skip_whitespace (str
);
7108 /* Allow optional leading '#'. */
7109 if (is_immediate_prefix (*str
))
7112 if (my_get_expression (& inst
.reloc
.exp
, & str
))
7115 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
7116 inst
.reloc
.pc_rel
= 0;
7121 do_swap (char * str
)
7125 skip_whitespace (str
);
7127 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
7132 inst
.error
= _("r15 not allowed in swap");
7136 if (skip_past_comma (&str
) == FAIL
7137 || (reg
= reg_required_here (&str
, 0)) == FAIL
)
7140 inst
.error
= BAD_ARGS
;
7146 inst
.error
= _("r15 not allowed in swap");
7150 if (skip_past_comma (&str
) == FAIL
7153 inst
.error
= BAD_ARGS
;
7157 skip_whitespace (str
);
7159 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
7164 inst
.error
= BAD_PC
;
7168 skip_whitespace (str
);
7172 inst
.error
= _("missing ]");
7180 do_branch (char * str
)
7182 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7189 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
7190 required for the instruction. */
7192 /* arm_parse_reloc () works on input_line_pointer.
7193 We actually want to parse the operands to the branch instruction
7194 passed in 'str'. Save the input pointer and restore it later. */
7195 save_in
= input_line_pointer
;
7196 input_line_pointer
= str
;
7197 if (inst
.reloc
.exp
.X_op
== O_symbol
7199 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
7201 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
7202 inst
.reloc
.pc_rel
= 0;
7203 /* Modify str to point to after parsed operands, otherwise
7204 end_of_line() will complain about the (PLT) left in str. */
7205 str
= input_line_pointer
;
7209 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
7210 inst
.reloc
.pc_rel
= 1;
7212 input_line_pointer
= save_in
;
7215 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
7216 inst
.reloc
.pc_rel
= 1;
7217 #endif /* OBJ_ELF */
7225 /* Co-processor data operation.
7226 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
7227 skip_whitespace (str
);
7229 if (co_proc_number (&str
) == FAIL
)
7232 inst
.error
= BAD_ARGS
;
7236 if (skip_past_comma (&str
) == FAIL
7237 || cp_opc_expr (&str
, 20,4) == FAIL
)
7240 inst
.error
= BAD_ARGS
;
7244 if (skip_past_comma (&str
) == FAIL
7245 || cp_reg_required_here (&str
, 12) == FAIL
)
7248 inst
.error
= BAD_ARGS
;
7252 if (skip_past_comma (&str
) == FAIL
7253 || cp_reg_required_here (&str
, 16) == FAIL
)
7256 inst
.error
= BAD_ARGS
;
7260 if (skip_past_comma (&str
) == FAIL
7261 || cp_reg_required_here (&str
, 0) == FAIL
)
7264 inst
.error
= BAD_ARGS
;
7268 if (skip_past_comma (&str
) == SUCCESS
)
7270 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
7273 inst
.error
= BAD_ARGS
;
7282 do_lstc (char * str
)
7284 /* Co-processor register load/store.
7285 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
7287 skip_whitespace (str
);
7289 if (co_proc_number (&str
) == FAIL
)
7292 inst
.error
= BAD_ARGS
;
7296 if (skip_past_comma (&str
) == FAIL
7297 || cp_reg_required_here (&str
, 12) == FAIL
)
7300 inst
.error
= BAD_ARGS
;
7304 if (skip_past_comma (&str
) == FAIL
7305 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
7308 inst
.error
= BAD_ARGS
;
7316 do_co_reg (char * str
)
7318 /* Co-processor register transfer.
7319 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
7321 skip_whitespace (str
);
7323 if (co_proc_number (&str
) == FAIL
)
7326 inst
.error
= BAD_ARGS
;
7330 if (skip_past_comma (&str
) == FAIL
7331 || cp_opc_expr (&str
, 21, 3) == FAIL
)
7334 inst
.error
= BAD_ARGS
;
7338 if (skip_past_comma (&str
) == FAIL
7339 || reg_required_here (&str
, 12) == FAIL
)
7342 inst
.error
= BAD_ARGS
;
7346 if (skip_past_comma (&str
) == FAIL
7347 || cp_reg_required_here (&str
, 16) == FAIL
)
7350 inst
.error
= BAD_ARGS
;
7354 if (skip_past_comma (&str
) == FAIL
7355 || cp_reg_required_here (&str
, 0) == FAIL
)
7358 inst
.error
= BAD_ARGS
;
7362 if (skip_past_comma (&str
) == SUCCESS
)
7364 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
7367 inst
.error
= BAD_ARGS
;
7376 do_fpa_ctrl (char * str
)
7378 /* FP control registers.
7379 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
7381 skip_whitespace (str
);
7383 if (reg_required_here (&str
, 12) == FAIL
)
7386 inst
.error
= BAD_ARGS
;
7394 do_fpa_ldst (char * str
)
7396 skip_whitespace (str
);
7398 if (fp_reg_required_here (&str
, 12) == FAIL
)
7401 inst
.error
= BAD_ARGS
;
7405 if (skip_past_comma (&str
) == FAIL
7406 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
7409 inst
.error
= BAD_ARGS
;
7417 do_fpa_ldmstm (char * str
)
7421 skip_whitespace (str
);
7423 if (fp_reg_required_here (&str
, 12) == FAIL
)
7426 inst
.error
= BAD_ARGS
;
7430 /* Get Number of registers to transfer. */
7431 if (skip_past_comma (&str
) == FAIL
7432 || my_get_expression (&inst
.reloc
.exp
, &str
))
7435 inst
.error
= _("constant expression expected");
7439 if (inst
.reloc
.exp
.X_op
!= O_constant
)
7441 inst
.error
= _("constant value required for number of registers");
7445 num_regs
= inst
.reloc
.exp
.X_add_number
;
7447 if (num_regs
< 1 || num_regs
> 4)
7449 inst
.error
= _("number of registers must be in the range [1:4]");
7456 inst
.instruction
|= CP_T_X
;
7459 inst
.instruction
|= CP_T_Y
;
7462 inst
.instruction
|= CP_T_Y
| CP_T_X
;
7470 if (inst
.instruction
& (CP_T_Pre
| CP_T_UD
)) /* ea/fd format. */
7476 /* The instruction specified "ea" or "fd", so we can only accept
7477 [Rn]{!}. The instruction does not really support stacking or
7478 unstacking, so we have to emulate these by setting appropriate
7479 bits and offsets. */
7480 if (skip_past_comma (&str
) == FAIL
7484 inst
.error
= BAD_ARGS
;
7489 skip_whitespace (str
);
7491 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
7494 skip_whitespace (str
);
7498 inst
.error
= BAD_ARGS
;
7510 _("r15 not allowed as base register with write-back");
7517 if (inst
.instruction
& CP_T_Pre
)
7519 /* Pre-decrement. */
7520 offset
= 3 * num_regs
;
7522 inst
.instruction
|= CP_T_WB
;
7526 /* Post-increment. */
7529 inst
.instruction
|= CP_T_WB
;
7530 offset
= 3 * num_regs
;
7534 /* No write-back, so convert this into a standard pre-increment
7535 instruction -- aesthetically more pleasing. */
7536 inst
.instruction
|= CP_T_Pre
| CP_T_UD
;
7541 inst
.instruction
|= offset
;
7543 else if (skip_past_comma (&str
) == FAIL
7544 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
7547 inst
.error
= BAD_ARGS
;
7555 do_fpa_dyadic (char * str
)
7557 skip_whitespace (str
);
7559 if (fp_reg_required_here (&str
, 12) == FAIL
)
7562 inst
.error
= BAD_ARGS
;
7566 if (skip_past_comma (&str
) == FAIL
7567 || fp_reg_required_here (&str
, 16) == FAIL
)
7570 inst
.error
= BAD_ARGS
;
7574 if (skip_past_comma (&str
) == FAIL
7575 || fp_op2 (&str
) == FAIL
)
7578 inst
.error
= BAD_ARGS
;
7586 do_fpa_monadic (char * str
)
7588 skip_whitespace (str
);
7590 if (fp_reg_required_here (&str
, 12) == FAIL
)
7593 inst
.error
= BAD_ARGS
;
7597 if (skip_past_comma (&str
) == FAIL
7598 || fp_op2 (&str
) == FAIL
)
7601 inst
.error
= BAD_ARGS
;
7609 do_fpa_cmp (char * str
)
7611 skip_whitespace (str
);
7613 if (fp_reg_required_here (&str
, 16) == FAIL
)
7616 inst
.error
= BAD_ARGS
;
7620 if (skip_past_comma (&str
) == FAIL
7621 || fp_op2 (&str
) == FAIL
)
7624 inst
.error
= BAD_ARGS
;
7632 do_fpa_from_reg (char * str
)
7634 skip_whitespace (str
);
7636 if (fp_reg_required_here (&str
, 16) == FAIL
)
7639 inst
.error
= BAD_ARGS
;
7643 if (skip_past_comma (&str
) == FAIL
7644 || reg_required_here (&str
, 12) == FAIL
)
7647 inst
.error
= BAD_ARGS
;
7655 do_fpa_to_reg (char * str
)
7657 skip_whitespace (str
);
7659 if (reg_required_here (&str
, 12) == FAIL
)
7662 if (skip_past_comma (&str
) == FAIL
7663 || fp_reg_required_here (&str
, 0) == FAIL
)
7666 inst
.error
= BAD_ARGS
;
7673 /* Encode a VFP SP register number. */
7676 vfp_sp_encode_reg (int reg
, enum vfp_sp_reg_pos pos
)
7681 inst
.instruction
|= ((reg
>> 1) << 12) | ((reg
& 1) << 22);
7685 inst
.instruction
|= ((reg
>> 1) << 16) | ((reg
& 1) << 7);
7689 inst
.instruction
|= ((reg
>> 1) << 0) | ((reg
& 1) << 5);
7698 vfp_sp_reg_required_here (char ** str
,
7699 enum vfp_sp_reg_pos pos
)
7702 char * start
= *str
;
7704 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_SN
].htab
)) != FAIL
)
7706 vfp_sp_encode_reg (reg
, pos
);
7710 /* In the few cases where we might be able to accept something else
7711 this error can be overridden. */
7712 inst
.error
= _(all_reg_maps
[REG_TYPE_SN
].expected
);
7714 /* Restore the start point. */
7720 vfp_dp_reg_required_here (char ** str
,
7721 enum vfp_dp_reg_pos pos
)
7724 char * start
= *str
;
7726 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_DN
].htab
)) != FAIL
)
7731 inst
.instruction
|= reg
<< 12;
7735 inst
.instruction
|= reg
<< 16;
7739 inst
.instruction
|= reg
<< 0;
7748 /* In the few cases where we might be able to accept something else
7749 this error can be overridden. */
7750 inst
.error
= _(all_reg_maps
[REG_TYPE_DN
].expected
);
7752 /* Restore the start point. */
7758 do_vfp_sp_monadic (char * str
)
7760 skip_whitespace (str
);
7762 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7765 if (skip_past_comma (&str
) == FAIL
7766 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
7769 inst
.error
= BAD_ARGS
;
7777 do_vfp_dp_monadic (char * str
)
7779 skip_whitespace (str
);
7781 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7784 if (skip_past_comma (&str
) == FAIL
7785 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7788 inst
.error
= BAD_ARGS
;
7796 do_vfp_sp_dyadic (char * str
)
7798 skip_whitespace (str
);
7800 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7803 if (skip_past_comma (&str
) == FAIL
7804 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
7805 || skip_past_comma (&str
) == FAIL
7806 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
7809 inst
.error
= BAD_ARGS
;
7817 do_vfp_dp_dyadic (char * str
)
7819 skip_whitespace (str
);
7821 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7824 if (skip_past_comma (&str
) == FAIL
7825 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
7826 || skip_past_comma (&str
) == FAIL
7827 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7830 inst
.error
= BAD_ARGS
;
7838 do_vfp_reg_from_sp (char * str
)
7840 skip_whitespace (str
);
7842 if (reg_required_here (&str
, 12) == FAIL
)
7845 if (skip_past_comma (&str
) == FAIL
7846 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
7849 inst
.error
= BAD_ARGS
;
7856 /* Parse a VFP register list. If the string is invalid return FAIL.
7857 Otherwise return the number of registers, and set PBASE to the first
7858 register. Double precision registers are matched if DP is nonzero. */
7861 vfp_parse_reg_list (char **str
, int *pbase
, int dp
)
7869 unsigned long mask
= 0;
7876 skip_whitespace (*str
);
7880 regtype
= REG_TYPE_DN
;
7885 regtype
= REG_TYPE_SN
;
7889 base_reg
= max_regs
;
7893 new_base
= arm_reg_parse (str
, all_reg_maps
[regtype
].htab
);
7894 if (new_base
== FAIL
)
7896 inst
.error
= _(all_reg_maps
[regtype
].expected
);
7900 if (new_base
< base_reg
)
7901 base_reg
= new_base
;
7903 if (mask
& (1 << new_base
))
7905 inst
.error
= _("invalid register list");
7909 if ((mask
>> new_base
) != 0 && ! warned
)
7911 as_tsktsk (_("register list not in ascending order"));
7915 mask
|= 1 << new_base
;
7918 skip_whitespace (*str
);
7920 if (**str
== '-') /* We have the start of a range expression */
7927 = arm_reg_parse (str
, all_reg_maps
[regtype
].htab
))
7930 inst
.error
= _(all_reg_maps
[regtype
].expected
);
7934 if (high_range
<= new_base
)
7936 inst
.error
= _("register range not in ascending order");
7940 for (new_base
++; new_base
<= high_range
; new_base
++)
7942 if (mask
& (1 << new_base
))
7944 inst
.error
= _("invalid register list");
7948 mask
|= 1 << new_base
;
7953 while (skip_past_comma (str
) != FAIL
);
7957 /* Sanity check -- should have raised a parse error above. */
7958 if (count
== 0 || count
> max_regs
)
7963 /* Final test -- the registers must be consecutive. */
7965 for (i
= 0; i
< count
; i
++)
7967 if ((mask
& (1u << i
)) == 0)
7969 inst
.error
= _("non-contiguous register range");
7978 do_vfp_reg2_from_sp2 (char * str
)
7982 skip_whitespace (str
);
7984 if (reg_required_here (&str
, 12) == FAIL
7985 || skip_past_comma (&str
) == FAIL
7986 || reg_required_here (&str
, 16) == FAIL
7987 || skip_past_comma (&str
) == FAIL
)
7990 inst
.error
= BAD_ARGS
;
7994 /* We require exactly two consecutive SP registers. */
7995 if (vfp_parse_reg_list (&str
, ®
, 0) != 2)
7998 inst
.error
= _("only two consecutive VFP SP registers allowed here");
8000 vfp_sp_encode_reg (reg
, VFP_REG_Sm
);
8006 do_vfp_sp_from_reg (char * str
)
8008 skip_whitespace (str
);
8010 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
8013 if (skip_past_comma (&str
) == FAIL
8014 || reg_required_here (&str
, 12) == FAIL
)
8017 inst
.error
= BAD_ARGS
;
8025 do_vfp_sp2_from_reg2 (char * str
)
8029 skip_whitespace (str
);
8031 /* We require exactly two consecutive SP registers. */
8032 if (vfp_parse_reg_list (&str
, ®
, 0) != 2)
8035 inst
.error
= _("only two consecutive VFP SP registers allowed here");
8037 vfp_sp_encode_reg (reg
, VFP_REG_Sm
);
8039 if (skip_past_comma (&str
) == FAIL
8040 || reg_required_here (&str
, 12) == FAIL
8041 || skip_past_comma (&str
) == FAIL
8042 || reg_required_here (&str
, 16) == FAIL
)
8045 inst
.error
= BAD_ARGS
;
8053 do_vfp_reg_from_dp (char * str
)
8055 skip_whitespace (str
);
8057 if (reg_required_here (&str
, 12) == FAIL
)
8060 if (skip_past_comma (&str
) == FAIL
8061 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
8064 inst
.error
= BAD_ARGS
;
8072 do_vfp_reg2_from_dp (char * str
)
8074 skip_whitespace (str
);
8076 if (reg_required_here (&str
, 12) == FAIL
)
8079 if (skip_past_comma (&str
) == FAIL
8080 || reg_required_here (&str
, 16) == FAIL
8081 || skip_past_comma (&str
) == FAIL
8082 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
8085 inst
.error
= BAD_ARGS
;
8093 do_vfp_dp_from_reg (char * str
)
8095 skip_whitespace (str
);
8097 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
8100 if (skip_past_comma (&str
) == FAIL
8101 || reg_required_here (&str
, 12) == FAIL
)
8104 inst
.error
= BAD_ARGS
;
8112 do_vfp_dp_from_reg2 (char * str
)
8114 skip_whitespace (str
);
8116 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
8119 if (skip_past_comma (&str
) == FAIL
8120 || reg_required_here (&str
, 12) == FAIL
8121 || skip_past_comma (&str
) == FAIL
8122 || reg_required_here (&str
, 16) == FAIL
)
8125 inst
.error
= BAD_ARGS
;
8132 static const struct vfp_reg
*
8133 vfp_psr_parse (char ** str
)
8138 const struct vfp_reg
*vreg
;
8142 /* Find the end of the current token. */
8147 while (ISALPHA (c
));
8152 for (vreg
= vfp_regs
+ 0;
8153 vreg
< vfp_regs
+ sizeof (vfp_regs
) / sizeof (struct vfp_reg
);
8156 if (streq (start
, vreg
->name
))
8169 vfp_psr_required_here (char ** str
)
8172 const struct vfp_reg
*vreg
;
8174 vreg
= vfp_psr_parse (str
);
8178 inst
.instruction
|= vreg
->regno
;
8182 inst
.error
= _("VFP system register expected");
8189 do_vfp_reg_from_ctrl (char * str
)
8191 skip_whitespace (str
);
8193 if (reg_required_here (&str
, 12) == FAIL
)
8196 if (skip_past_comma (&str
) == FAIL
8197 || vfp_psr_required_here (&str
) == FAIL
)
8200 inst
.error
= BAD_ARGS
;
8208 do_vfp_ctrl_from_reg (char * str
)
8210 skip_whitespace (str
);
8212 if (vfp_psr_required_here (&str
) == FAIL
)
8215 if (skip_past_comma (&str
) == FAIL
8216 || reg_required_here (&str
, 12) == FAIL
)
8219 inst
.error
= BAD_ARGS
;
8227 do_vfp_sp_ldst (char * str
)
8229 skip_whitespace (str
);
8231 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8234 inst
.error
= BAD_ARGS
;
8238 if (skip_past_comma (&str
) == FAIL
8239 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
8242 inst
.error
= BAD_ARGS
;
8250 do_vfp_dp_ldst (char * str
)
8252 skip_whitespace (str
);
8254 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8257 inst
.error
= BAD_ARGS
;
8261 if (skip_past_comma (&str
) == FAIL
8262 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
8265 inst
.error
= BAD_ARGS
;
8274 vfp_sp_ldstm (char * str
, enum vfp_ldstm_type ldstm_type
)
8279 skip_whitespace (str
);
8281 if (reg_required_here (&str
, 16) == FAIL
)
8284 skip_whitespace (str
);
8288 inst
.instruction
|= WRITE_BACK
;
8291 else if (ldstm_type
!= VFP_LDSTMIA
)
8293 inst
.error
= _("this addressing mode requires base-register writeback");
8297 if (skip_past_comma (&str
) == FAIL
8298 || (count
= vfp_parse_reg_list (&str
, ®
, 0)) == FAIL
)
8301 inst
.error
= BAD_ARGS
;
8304 vfp_sp_encode_reg (reg
, VFP_REG_Sd
);
8306 inst
.instruction
|= count
;
8311 vfp_dp_ldstm (char * str
, enum vfp_ldstm_type ldstm_type
)
8316 skip_whitespace (str
);
8318 if (reg_required_here (&str
, 16) == FAIL
)
8321 skip_whitespace (str
);
8325 inst
.instruction
|= WRITE_BACK
;
8328 else if (ldstm_type
!= VFP_LDSTMIA
&& ldstm_type
!= VFP_LDSTMIAX
)
8330 inst
.error
= _("this addressing mode requires base-register writeback");
8334 if (skip_past_comma (&str
) == FAIL
8335 || (count
= vfp_parse_reg_list (&str
, ®
, 1)) == FAIL
)
8338 inst
.error
= BAD_ARGS
;
8343 if (ldstm_type
== VFP_LDSTMIAX
|| ldstm_type
== VFP_LDSTMDBX
)
8346 inst
.instruction
|= (reg
<< 12) | count
;
8351 do_vfp_sp_ldstmia (char * str
)
8353 vfp_sp_ldstm (str
, VFP_LDSTMIA
);
8357 do_vfp_sp_ldstmdb (char * str
)
8359 vfp_sp_ldstm (str
, VFP_LDSTMDB
);
8363 do_vfp_dp_ldstmia (char * str
)
8365 vfp_dp_ldstm (str
, VFP_LDSTMIA
);
8369 do_vfp_dp_ldstmdb (char * str
)
8371 vfp_dp_ldstm (str
, VFP_LDSTMDB
);
8375 do_vfp_xp_ldstmia (char *str
)
8377 vfp_dp_ldstm (str
, VFP_LDSTMIAX
);
8381 do_vfp_xp_ldstmdb (char * str
)
8383 vfp_dp_ldstm (str
, VFP_LDSTMDBX
);
8387 do_vfp_sp_compare_z (char * str
)
8389 skip_whitespace (str
);
8391 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8394 inst
.error
= BAD_ARGS
;
8402 do_vfp_dp_compare_z (char * str
)
8404 skip_whitespace (str
);
8406 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8409 inst
.error
= BAD_ARGS
;
8417 do_vfp_dp_sp_cvt (char * str
)
8419 skip_whitespace (str
);
8421 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8424 if (skip_past_comma (&str
) == FAIL
8425 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
8428 inst
.error
= BAD_ARGS
;
8436 do_vfp_sp_dp_cvt (char * str
)
8438 skip_whitespace (str
);
8440 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8443 if (skip_past_comma (&str
) == FAIL
8444 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
8447 inst
.error
= BAD_ARGS
;
8454 /* Thumb specific routines. */
8456 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
8460 thumb_add_sub (char * str
, int subtract
)
8462 int Rd
, Rs
, Rn
= FAIL
;
8464 skip_whitespace (str
);
8466 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
8467 || skip_past_comma (&str
) == FAIL
)
8470 inst
.error
= BAD_ARGS
;
8474 if (is_immediate_prefix (*str
))
8478 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8483 if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8486 if (skip_past_comma (&str
) == FAIL
)
8488 /* Two operand format, shuffle the registers
8489 and pretend there are 3. */
8493 else if (is_immediate_prefix (*str
))
8496 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8499 else if ((Rn
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8503 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8504 for the latter case, EXPR contains the immediate that was found. */
8507 /* All register format. */
8508 if (Rd
> 7 || Rs
> 7 || Rn
> 7)
8512 inst
.error
= _("dest and source1 must be the same register");
8516 /* Can't do this for SUB. */
8519 inst
.error
= _("subtract valid only on lo regs");
8523 inst
.instruction
= (T_OPCODE_ADD_HI
8524 | (Rd
> 7 ? THUMB_H1
: 0)
8525 | (Rn
> 7 ? THUMB_H2
: 0));
8526 inst
.instruction
|= (Rd
& 7) | ((Rn
& 7) << 3);
8530 inst
.instruction
= subtract
? T_OPCODE_SUB_R3
: T_OPCODE_ADD_R3
;
8531 inst
.instruction
|= Rd
| (Rs
<< 3) | (Rn
<< 6);
8536 /* Immediate expression, now things start to get nasty. */
8538 /* First deal with HI regs, only very restricted cases allowed:
8539 Adjusting SP, and using PC or SP to get an address. */
8540 if ((Rd
> 7 && (Rd
!= REG_SP
|| Rs
!= REG_SP
))
8541 || (Rs
> 7 && Rs
!= REG_SP
&& Rs
!= REG_PC
))
8543 inst
.error
= _("invalid Hi register with immediate");
8547 if (inst
.reloc
.exp
.X_op
!= O_constant
)
8549 /* Value isn't known yet, all we can do is store all the fragments
8550 we know about in the instruction and let the reloc hacking
8552 inst
.instruction
= (subtract
? 0x8000 : 0) | (Rd
<< 4) | Rs
;
8553 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
8557 int offset
= inst
.reloc
.exp
.X_add_number
;
8567 /* Quick check, in case offset is MIN_INT. */
8570 inst
.error
= _("immediate value out of range");
8574 /* Note - you cannot convert a subtract of 0 into an
8575 add of 0 because the carry flag is set differently. */
8576 else if (offset
> 0)
8581 if (offset
& ~0x1fc)
8583 inst
.error
= _("invalid immediate value for stack adjust");
8586 inst
.instruction
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
8587 inst
.instruction
|= offset
>> 2;
8589 else if (Rs
== REG_PC
|| Rs
== REG_SP
)
8592 || (offset
& ~0x3fc))
8594 inst
.error
= _("invalid immediate for address calculation");
8597 inst
.instruction
= (Rs
== REG_PC
? T_OPCODE_ADD_PC
8599 inst
.instruction
|= (Rd
<< 8) | (offset
>> 2);
8605 inst
.error
= _("immediate value out of range");
8608 inst
.instruction
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
8609 inst
.instruction
|= (Rd
<< 8) | offset
;
8615 inst
.error
= _("immediate value out of range");
8618 inst
.instruction
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
8619 inst
.instruction
|= Rd
| (Rs
<< 3) | (offset
<< 6);
8628 thumb_shift (char * str
, int shift
)
8630 int Rd
, Rs
, Rn
= FAIL
;
8632 skip_whitespace (str
);
8634 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
8635 || skip_past_comma (&str
) == FAIL
)
8638 inst
.error
= BAD_ARGS
;
8642 if (is_immediate_prefix (*str
))
8644 /* Two operand immediate format, set Rs to Rd. */
8647 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8652 if ((Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8655 if (skip_past_comma (&str
) == FAIL
)
8657 /* Two operand format, shuffle the registers
8658 and pretend there are 3. */
8662 else if (is_immediate_prefix (*str
))
8665 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8668 else if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8672 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8673 for the latter case, EXPR contains the immediate that was found. */
8679 inst
.error
= _("source1 and dest must be same register");
8685 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_R
; break;
8686 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_R
; break;
8687 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_R
; break;
8690 inst
.instruction
|= Rd
| (Rn
<< 3);
8696 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_I
; break;
8697 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_I
; break;
8698 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_I
; break;
8701 if (inst
.reloc
.exp
.X_op
!= O_constant
)
8703 /* Value isn't known yet, create a dummy reloc and let reloc
8704 hacking fix it up. */
8705 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_SHIFT
;
8709 unsigned shift_value
= inst
.reloc
.exp
.X_add_number
;
8711 if (shift_value
> 32 || (shift_value
== 32 && shift
== THUMB_LSL
))
8713 inst
.error
= _("invalid immediate for shift");
8717 /* Shifts of zero are handled by converting to LSL. */
8718 if (shift_value
== 0)
8719 inst
.instruction
= T_OPCODE_LSL_I
;
8721 /* Shifts of 32 are encoded as a shift of zero. */
8722 if (shift_value
== 32)
8725 inst
.instruction
|= shift_value
<< 6;
8728 inst
.instruction
|= Rd
| (Rs
<< 3);
8735 thumb_load_store (char * str
, int load_store
, int size
)
8737 int Rd
, Rb
, Ro
= FAIL
;
8739 skip_whitespace (str
);
8741 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
8742 || skip_past_comma (&str
) == FAIL
)
8745 inst
.error
= BAD_ARGS
;
8752 if ((Rb
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8755 if (skip_past_comma (&str
) != FAIL
)
8757 if (is_immediate_prefix (*str
))
8760 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8763 else if ((Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8768 inst
.reloc
.exp
.X_op
= O_constant
;
8769 inst
.reloc
.exp
.X_add_number
= 0;
8774 inst
.error
= _("expected ']'");
8779 else if (*str
== '=')
8781 if (load_store
!= THUMB_LOAD
)
8783 inst
.error
= _("invalid pseudo operation");
8787 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
8790 skip_whitespace (str
);
8792 if (my_get_expression (& inst
.reloc
.exp
, & str
))
8797 if ( inst
.reloc
.exp
.X_op
!= O_constant
8798 && inst
.reloc
.exp
.X_op
!= O_symbol
)
8800 inst
.error
= "Constant expression expected";
8804 if (inst
.reloc
.exp
.X_op
== O_constant
8805 && ((inst
.reloc
.exp
.X_add_number
& ~0xFF) == 0))
8807 /* This can be done with a mov instruction. */
8809 inst
.instruction
= T_OPCODE_MOV_I8
| (Rd
<< 8);
8810 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
8814 /* Insert into literal pool. */
8815 if (add_to_lit_pool () == FAIL
)
8818 inst
.error
= "literal pool insertion failed";
8822 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8823 inst
.reloc
.pc_rel
= 1;
8824 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
8825 /* Adjust ARM pipeline offset to Thumb. */
8826 inst
.reloc
.exp
.X_add_number
+= 4;
8832 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8835 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
8836 inst
.reloc
.pc_rel
= 1;
8837 inst
.reloc
.exp
.X_add_number
-= 4; /* Pipeline offset. */
8838 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8843 if (Rb
== REG_PC
|| Rb
== REG_SP
)
8845 if (size
!= THUMB_WORD
)
8847 inst
.error
= _("byte or halfword not valid for base register");
8850 else if (Rb
== REG_PC
&& load_store
!= THUMB_LOAD
)
8852 inst
.error
= _("r15 based store not allowed");
8855 else if (Ro
!= FAIL
)
8857 inst
.error
= _("invalid base register for register offset");
8862 inst
.instruction
= T_OPCODE_LDR_PC
;
8863 else if (load_store
== THUMB_LOAD
)
8864 inst
.instruction
= T_OPCODE_LDR_SP
;
8866 inst
.instruction
= T_OPCODE_STR_SP
;
8868 inst
.instruction
|= Rd
<< 8;
8869 if (inst
.reloc
.exp
.X_op
== O_constant
)
8871 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
8873 if (offset
& ~0x3fc)
8875 inst
.error
= _("invalid offset");
8879 inst
.instruction
|= offset
>> 2;
8882 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8886 inst
.error
= _("invalid base register in load/store");
8889 else if (Ro
== FAIL
)
8891 /* Immediate offset. */
8892 if (size
== THUMB_WORD
)
8893 inst
.instruction
= (load_store
== THUMB_LOAD
8894 ? T_OPCODE_LDR_IW
: T_OPCODE_STR_IW
);
8895 else if (size
== THUMB_HALFWORD
)
8896 inst
.instruction
= (load_store
== THUMB_LOAD
8897 ? T_OPCODE_LDR_IH
: T_OPCODE_STR_IH
);
8899 inst
.instruction
= (load_store
== THUMB_LOAD
8900 ? T_OPCODE_LDR_IB
: T_OPCODE_STR_IB
);
8902 inst
.instruction
|= Rd
| (Rb
<< 3);
8904 if (inst
.reloc
.exp
.X_op
== O_constant
)
8906 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
8908 if (offset
& ~(0x1f << size
))
8910 inst
.error
= _("invalid offset");
8913 inst
.instruction
|= (offset
>> size
) << 6;
8916 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8920 /* Register offset. */
8921 if (size
== THUMB_WORD
)
8922 inst
.instruction
= (load_store
== THUMB_LOAD
8923 ? T_OPCODE_LDR_RW
: T_OPCODE_STR_RW
);
8924 else if (size
== THUMB_HALFWORD
)
8925 inst
.instruction
= (load_store
== THUMB_LOAD
8926 ? T_OPCODE_LDR_RH
: T_OPCODE_STR_RH
);
8928 inst
.instruction
= (load_store
== THUMB_LOAD
8929 ? T_OPCODE_LDR_RB
: T_OPCODE_STR_RB
);
8931 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
8937 /* A register must be given at this point.
8939 Shift is the place to put it in inst.instruction.
8941 Restores input start point on err.
8942 Returns the reg#, or FAIL. */
8945 mav_reg_required_here (char ** str
, int shift
, enum arm_reg_type regtype
)
8950 if ((reg
= arm_reg_parse (str
, all_reg_maps
[regtype
].htab
)) != FAIL
)
8953 inst
.instruction
|= reg
<< shift
;
8958 /* Restore the start point. */
8961 /* Try generic coprocessor name if applicable. */
8962 if (regtype
== REG_TYPE_MVF
||
8963 regtype
== REG_TYPE_MVD
||
8964 regtype
== REG_TYPE_MVFX
||
8965 regtype
== REG_TYPE_MVDX
)
8967 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CN
].htab
)) != FAIL
)
8970 inst
.instruction
|= reg
<< shift
;
8975 /* Restore the start point. */
8979 /* In the few cases where we might be able to accept something else
8980 this error can be overridden. */
8981 inst
.error
= _(all_reg_maps
[regtype
].expected
);
8986 /* Cirrus Maverick Instructions. */
8988 /* Isnsn like "foo X,Y". */
8991 do_mav_binops (char * str
,
8993 enum arm_reg_type reg0
,
8994 enum arm_reg_type reg1
)
8998 shift0
= mode
& 0xff;
8999 shift1
= (mode
>> 8) & 0xff;
9001 skip_whitespace (str
);
9003 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
9004 || skip_past_comma (&str
) == FAIL
9005 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
)
9008 inst
.error
= BAD_ARGS
;
9014 /* Isnsn like "foo X,Y,Z". */
9017 do_mav_triple (char * str
,
9019 enum arm_reg_type reg0
,
9020 enum arm_reg_type reg1
,
9021 enum arm_reg_type reg2
)
9023 int shift0
, shift1
, shift2
;
9025 shift0
= mode
& 0xff;
9026 shift1
= (mode
>> 8) & 0xff;
9027 shift2
= (mode
>> 16) & 0xff;
9029 skip_whitespace (str
);
9031 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
9032 || skip_past_comma (&str
) == FAIL
9033 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
9034 || skip_past_comma (&str
) == FAIL
9035 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
)
9038 inst
.error
= BAD_ARGS
;
9044 /* Wrapper functions. */
9047 do_mav_binops_1a (char * str
)
9049 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVF
);
9053 do_mav_binops_1b (char * str
)
9055 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVD
);
9059 do_mav_binops_1c (char * str
)
9061 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVDX
);
9065 do_mav_binops_1d (char * str
)
9067 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVF
);
9071 do_mav_binops_1e (char * str
)
9073 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVD
);
9077 do_mav_binops_1f (char * str
)
9079 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVF
);
9083 do_mav_binops_1g (char * str
)
9085 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVD
);
9089 do_mav_binops_1h (char * str
)
9091 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVFX
);
9095 do_mav_binops_1i (char * str
)
9097 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVFX
);
9101 do_mav_binops_1j (char * str
)
9103 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVDX
);
9107 do_mav_binops_1k (char * str
)
9109 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVDX
);
9113 do_mav_binops_1l (char * str
)
9115 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVF
);
9119 do_mav_binops_1m (char * str
)
9121 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVD
);
9125 do_mav_binops_1n (char * str
)
9127 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
9131 do_mav_binops_1o (char * str
)
9133 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
9137 do_mav_binops_2a (char * str
)
9139 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVF
, REG_TYPE_RN
);
9143 do_mav_binops_2b (char * str
)
9145 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVD
, REG_TYPE_RN
);
9149 do_mav_binops_2c (char * str
)
9151 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVDX
, REG_TYPE_RN
);
9155 do_mav_binops_3a (char * str
)
9157 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVFX
);
9161 do_mav_binops_3b (char * str
)
9163 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVFX
, REG_TYPE_MVAX
);
9167 do_mav_binops_3c (char * str
)
9169 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVDX
);
9173 do_mav_binops_3d (char * str
)
9175 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVDX
, REG_TYPE_MVAX
);
9179 do_mav_triple_4a (char * str
)
9181 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_RN
);
9185 do_mav_triple_4b (char * str
)
9187 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_RN
);
9191 do_mav_triple_5a (char * str
)
9193 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVF
, REG_TYPE_MVF
);
9197 do_mav_triple_5b (char * str
)
9199 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVD
, REG_TYPE_MVD
);
9203 do_mav_triple_5c (char * str
)
9205 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
9209 do_mav_triple_5d (char * str
)
9211 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
9215 do_mav_triple_5e (char * str
)
9217 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVF
, REG_TYPE_MVF
, REG_TYPE_MVF
);
9221 do_mav_triple_5f (char * str
)
9223 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVD
, REG_TYPE_MVD
, REG_TYPE_MVD
);
9227 do_mav_triple_5g (char * str
)
9229 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
9233 do_mav_triple_5h (char * str
)
9235 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
9238 /* Isnsn like "foo W,X,Y,Z".
9239 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
9242 do_mav_quad (char * str
,
9244 enum arm_reg_type reg0
,
9245 enum arm_reg_type reg1
,
9246 enum arm_reg_type reg2
,
9247 enum arm_reg_type reg3
)
9249 int shift0
, shift1
, shift2
, shift3
;
9251 shift0
= mode
& 0xff;
9252 shift1
= (mode
>> 8) & 0xff;
9253 shift2
= (mode
>> 16) & 0xff;
9254 shift3
= (mode
>> 24) & 0xff;
9256 skip_whitespace (str
);
9258 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
9259 || skip_past_comma (&str
) == FAIL
9260 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
9261 || skip_past_comma (&str
) == FAIL
9262 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
9263 || skip_past_comma (&str
) == FAIL
9264 || mav_reg_required_here (&str
, shift3
, reg3
) == FAIL
)
9267 inst
.error
= BAD_ARGS
;
9274 do_mav_quad_6a (char * str
)
9276 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
,
9281 do_mav_quad_6b (char * str
)
9283 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVAX
, REG_TYPE_MVFX
,
9287 /* cfmvsc32<cond> DSPSC,MVDX[15:0]. */
9289 do_mav_dspsc_1 (char * str
)
9291 skip_whitespace (str
);
9294 if (mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
9295 || skip_past_comma (&str
) == FAIL
9296 || mav_reg_required_here (&str
, 12, REG_TYPE_MVDX
) == FAIL
)
9299 inst
.error
= BAD_ARGS
;
9307 /* cfmv32sc<cond> MVDX[15:0],DSPSC. */
9309 do_mav_dspsc_2 (char * str
)
9311 skip_whitespace (str
);
9314 if (mav_reg_required_here (&str
, 12, REG_TYPE_MVDX
) == FAIL
9315 || skip_past_comma (&str
) == FAIL
9316 || mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
)
9319 inst
.error
= BAD_ARGS
;
9327 /* Maverick shift immediate instructions.
9328 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
9329 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
9332 do_mav_shift (char * str
,
9333 enum arm_reg_type reg0
,
9334 enum arm_reg_type reg1
)
9339 skip_whitespace (str
);
9343 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
9344 || skip_past_comma (&str
) == FAIL
9345 || mav_reg_required_here (&str
, 16, reg1
) == FAIL
9346 || skip_past_comma (&str
) == FAIL
)
9349 inst
.error
= BAD_ARGS
;
9353 /* Calculate the immediate operand.
9354 The operand is a 7bit signed number. */
9355 skip_whitespace (str
);
9360 if (!ISDIGIT (*str
) && *str
!= '-')
9362 inst
.error
= _("expecting immediate, 7bit operand");
9372 for (imm
= 0; *str
&& ISDIGIT (*str
); ++str
)
9373 imm
= imm
* 10 + *str
- '0';
9377 inst
.error
= _("immediate out of range");
9381 /* Make negative imm's into 7bit signed numbers. */
9388 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
9389 Bits 5-7 of the insn should have bits 4-6 of the immediate.
9390 Bit 4 should be 0. */
9391 imm
= (imm
& 0xf) | ((imm
& 0x70) << 1);
9393 inst
.instruction
|= imm
;
9398 do_mav_shift_1 (char * str
)
9400 do_mav_shift (str
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
9404 do_mav_shift_2 (char * str
)
9406 do_mav_shift (str
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
9410 mav_parse_offset (char ** str
, int * negative
)
9417 skip_whitespace (p
);
9430 inst
.error
= _("offset expected");
9434 for (offset
= 0; *p
&& ISDIGIT (*p
); ++p
)
9435 offset
= offset
* 10 + *p
- '0';
9439 inst
.error
= _("offset out of range");
9444 inst
.error
= _("offset not a multiple of 4");
9450 return *negative
? -offset
: offset
;
9453 /* Maverick load/store instructions.
9454 <insn><cond> CRd,[Rn,<offset>]{!}.
9455 <insn><cond> CRd,[Rn],<offset>. */
9458 do_mav_ldst (char * str
, enum arm_reg_type reg0
)
9460 int offset
, negative
;
9462 skip_whitespace (str
);
9464 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
9465 || skip_past_comma (&str
) == FAIL
9467 || reg_required_here (&str
, 16) == FAIL
)
9470 if (skip_past_comma (&str
) == SUCCESS
)
9472 /* You are here: "<offset>]{!}". */
9473 inst
.instruction
|= PRE_INDEX
;
9475 offset
= mav_parse_offset (&str
, &negative
);
9482 inst
.error
= _("missing ]");
9488 inst
.instruction
|= WRITE_BACK
;
9494 /* You are here: "], <offset>". */
9497 inst
.error
= _("missing ]");
9501 if (skip_past_comma (&str
) == FAIL
9502 || (offset
= mav_parse_offset (&str
, &negative
), inst
.error
))
9505 inst
.instruction
|= CP_T_WB
; /* Post indexed, set bit W. */
9511 inst
.instruction
|= CP_T_UD
; /* Positive, so set bit U. */
9513 inst
.instruction
|= offset
>> 2;
9519 inst
.error
= BAD_ARGS
;
9523 do_mav_ldst_1 (char * str
)
9525 do_mav_ldst (str
, REG_TYPE_MVF
);
9529 do_mav_ldst_2 (char * str
)
9531 do_mav_ldst (str
, REG_TYPE_MVD
);
9535 do_mav_ldst_3 (char * str
)
9537 do_mav_ldst (str
, REG_TYPE_MVFX
);
9541 do_mav_ldst_4 (char * str
)
9543 do_mav_ldst (str
, REG_TYPE_MVDX
);
9547 do_t_nop (char * str
)
9553 /* Handle the Format 4 instructions that do not have equivalents in other
9554 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
9558 do_t_arit (char * str
)
9562 skip_whitespace (str
);
9564 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9565 || skip_past_comma (&str
) == FAIL
9566 || (Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9568 inst
.error
= BAD_ARGS
;
9572 if (skip_past_comma (&str
) != FAIL
)
9574 /* Three operand format not allowed for TST, CMN, NEG and MVN.
9575 (It isn't allowed for CMP either, but that isn't handled by this
9577 if (inst
.instruction
== T_OPCODE_TST
9578 || inst
.instruction
== T_OPCODE_CMN
9579 || inst
.instruction
== T_OPCODE_NEG
9580 || inst
.instruction
== T_OPCODE_MVN
)
9582 inst
.error
= BAD_ARGS
;
9586 if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9591 inst
.error
= _("dest and source1 must be the same register");
9597 if (inst
.instruction
== T_OPCODE_MUL
9599 as_tsktsk (_("Rs and Rd must be different in MUL"));
9601 inst
.instruction
|= Rd
| (Rs
<< 3);
9606 do_t_add (char * str
)
9608 thumb_add_sub (str
, 0);
9612 do_t_asr (char * str
)
9614 thumb_shift (str
, THUMB_ASR
);
9618 do_t_branch9 (char * str
)
9620 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9622 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH9
;
9623 inst
.reloc
.pc_rel
= 1;
9628 do_t_branch12 (char * str
)
9630 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9632 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH12
;
9633 inst
.reloc
.pc_rel
= 1;
9637 /* Find the real, Thumb encoded start of a Thumb function. */
9640 find_real_start (symbolS
* symbolP
)
9643 const char * name
= S_GET_NAME (symbolP
);
9644 symbolS
* new_target
;
9646 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
9647 #define STUB_NAME ".real_start_of"
9652 /* Names that start with '.' are local labels, not function entry points.
9653 The compiler may generate BL instructions to these labels because it
9654 needs to perform a branch to a far away location. */
9658 real_start
= malloc (strlen (name
) + strlen (STUB_NAME
) + 1);
9659 sprintf (real_start
, "%s%s", STUB_NAME
, name
);
9661 new_target
= symbol_find (real_start
);
9663 if (new_target
== NULL
)
9665 as_warn ("Failed to find real start of function: %s\n", name
);
9666 new_target
= symbolP
;
9675 do_t_branch23 (char * str
)
9677 if (my_get_expression (& inst
.reloc
.exp
, & str
))
9680 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH23
;
9681 inst
.reloc
.pc_rel
= 1;
9684 /* If the destination of the branch is a defined symbol which does not have
9685 the THUMB_FUNC attribute, then we must be calling a function which has
9686 the (interfacearm) attribute. We look for the Thumb entry point to that
9687 function and change the branch to refer to that function instead. */
9688 if ( inst
.reloc
.exp
.X_op
== O_symbol
9689 && inst
.reloc
.exp
.X_add_symbol
!= NULL
9690 && S_IS_DEFINED (inst
.reloc
.exp
.X_add_symbol
)
9691 && ! THUMB_IS_FUNC (inst
.reloc
.exp
.X_add_symbol
))
9692 inst
.reloc
.exp
.X_add_symbol
=
9693 find_real_start (inst
.reloc
.exp
.X_add_symbol
);
9697 do_t_bx (char * str
)
9701 skip_whitespace (str
);
9703 if ((reg
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
9706 /* This sets THUMB_H2 from the top bit of reg. */
9707 inst
.instruction
|= reg
<< 3;
9709 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
9710 should cause the alignment to be checked once it is known. This is
9711 because BX PC only works if the instruction is word aligned. */
9717 do_t_compare (char * str
)
9719 thumb_mov_compare (str
, THUMB_COMPARE
);
9723 do_t_ldmstm (char * str
)
9728 skip_whitespace (str
);
9730 if ((Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9734 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
9738 if (skip_past_comma (&str
) == FAIL
9739 || (range
= reg_list (&str
)) == FAIL
)
9742 inst
.error
= BAD_ARGS
;
9746 if (inst
.reloc
.type
!= BFD_RELOC_UNUSED
)
9748 /* This really doesn't seem worth it. */
9749 inst
.reloc
.type
= BFD_RELOC_UNUSED
;
9750 inst
.error
= _("expression too complex");
9756 inst
.error
= _("only lo-regs valid in load/store multiple");
9760 inst
.instruction
|= (Rb
<< 8) | range
;
9765 do_t_ldr (char * str
)
9767 thumb_load_store (str
, THUMB_LOAD
, THUMB_WORD
);
9771 do_t_ldrb (char * str
)
9773 thumb_load_store (str
, THUMB_LOAD
, THUMB_BYTE
);
9777 do_t_ldrh (char * str
)
9779 thumb_load_store (str
, THUMB_LOAD
, THUMB_HALFWORD
);
9783 do_t_lds (char * str
)
9787 skip_whitespace (str
);
9789 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9790 || skip_past_comma (&str
) == FAIL
9792 || (Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9793 || skip_past_comma (&str
) == FAIL
9794 || (Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9798 inst
.error
= _("syntax: ldrs[b] Rd, [Rb, Ro]");
9802 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
9807 do_t_lsl (char * str
)
9809 thumb_shift (str
, THUMB_LSL
);
9813 do_t_lsr (char * str
)
9815 thumb_shift (str
, THUMB_LSR
);
9819 do_t_mov (char * str
)
9821 thumb_mov_compare (str
, THUMB_MOVE
);
9825 do_t_push_pop (char * str
)
9829 skip_whitespace (str
);
9831 if ((range
= reg_list (&str
)) == FAIL
)
9834 inst
.error
= BAD_ARGS
;
9838 if (inst
.reloc
.type
!= BFD_RELOC_UNUSED
)
9840 /* This really doesn't seem worth it. */
9841 inst
.reloc
.type
= BFD_RELOC_UNUSED
;
9842 inst
.error
= _("expression too complex");
9848 if ((inst
.instruction
== T_OPCODE_PUSH
9849 && (range
& ~0xff) == 1 << REG_LR
)
9850 || (inst
.instruction
== T_OPCODE_POP
9851 && (range
& ~0xff) == 1 << REG_PC
))
9853 inst
.instruction
|= THUMB_PP_PC_LR
;
9858 inst
.error
= _("invalid register list to push/pop instruction");
9863 inst
.instruction
|= range
;
9868 do_t_str (char * str
)
9870 thumb_load_store (str
, THUMB_STORE
, THUMB_WORD
);
9874 do_t_strb (char * str
)
9876 thumb_load_store (str
, THUMB_STORE
, THUMB_BYTE
);
9880 do_t_strh (char * str
)
9882 thumb_load_store (str
, THUMB_STORE
, THUMB_HALFWORD
);
9886 do_t_sub (char * str
)
9888 thumb_add_sub (str
, 1);
9892 do_t_swi (char * str
)
9894 skip_whitespace (str
);
9896 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9899 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
9904 do_t_adr (char * str
)
9908 /* This is a pseudo-op of the form "adr rd, label" to be converted
9909 into a relative address of the form "add rd, pc, #label-.-4". */
9910 skip_whitespace (str
);
9912 /* Store Rd in temporary location inside instruction. */
9913 if ((reg
= reg_required_here (&str
, 4)) == FAIL
9914 || (reg
> 7) /* For Thumb reg must be r0..r7. */
9915 || skip_past_comma (&str
) == FAIL
9916 || my_get_expression (&inst
.reloc
.exp
, &str
))
9919 inst
.error
= BAD_ARGS
;
9923 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
9924 inst
.reloc
.exp
.X_add_number
-= 4; /* PC relative adjust. */
9925 inst
.reloc
.pc_rel
= 1;
9926 inst
.instruction
|= REG_PC
; /* Rd is already placed into the instruction. */
9932 insert_reg (const struct reg_entry
* r
,
9933 struct hash_control
* htab
)
9935 int len
= strlen (r
->name
) + 2;
9936 char * buf
= xmalloc (len
);
9937 char * buf2
= xmalloc (len
);
9940 #ifdef REGISTER_PREFIX
9941 buf
[i
++] = REGISTER_PREFIX
;
9944 strcpy (buf
+ i
, r
->name
);
9946 for (i
= 0; buf
[i
]; i
++)
9947 buf2
[i
] = TOUPPER (buf
[i
]);
9951 hash_insert (htab
, buf
, (PTR
) r
);
9952 hash_insert (htab
, buf2
, (PTR
) r
);
9956 build_reg_hsh (struct reg_map
* map
)
9958 const struct reg_entry
*r
;
9960 if ((map
->htab
= hash_new ()) == NULL
)
9961 as_fatal (_("virtual memory exhausted"));
9963 for (r
= map
->names
; r
->name
!= NULL
; r
++)
9964 insert_reg (r
, map
->htab
);
9968 insert_reg_alias (char * str
,
9970 struct hash_control
*htab
)
9973 struct reg_entry
* new = xmalloc (sizeof (struct reg_entry
));
9974 const char * name
= xmalloc (strlen (str
) + 1);
9976 strcpy ((char *) name
, str
);
9979 new->number
= regnum
;
9980 new->builtin
= FALSE
;
9982 error
= hash_insert (htab
, name
, (PTR
) new);
9985 as_bad (_("failed to create an alias for %s, reason: %s"),
9987 free ((char *) name
);
9992 /* Look for the .req directive. This is of the form:
9994 new_register_name .req existing_register_name
9996 If we find one, or if it looks sufficiently like one that we want to
9997 handle any error here, return non-zero. Otherwise return zero. */
10000 create_register_alias (char * newname
, char * p
)
10006 skip_whitespace (q
);
10011 if (*q
&& !strncmp (q
, ".req ", 5))
10016 #ifndef IGNORE_OPCODE_CASE
10017 newname
= original_case_string
;
10019 copy_of_str
= newname
;
10022 skip_whitespace (q
);
10024 for (r
= q
; *r
!= '\0'; r
++)
10030 enum arm_reg_type new_type
, old_type
;
10035 old_type
= arm_reg_parse_any (q
);
10038 new_type
= arm_reg_parse_any (newname
);
10040 if (new_type
== REG_TYPE_MAX
)
10042 if (old_type
!= REG_TYPE_MAX
)
10044 old_regno
= arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
);
10045 insert_reg_alias (newname
, old_regno
,
10046 all_reg_maps
[old_type
].htab
);
10049 as_warn (_("register '%s' does not exist\n"), q
);
10051 else if (old_type
== REG_TYPE_MAX
)
10053 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
10058 /* Do not warn about redefinitions to the same alias. */
10059 if (new_type
!= old_type
10060 || (arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
)
10061 != arm_reg_parse (&q
, all_reg_maps
[new_type
].htab
)))
10062 as_warn (_("ignoring redefinition of register alias '%s'"),
10068 as_warn (_("ignoring incomplete .req pseuso op"));
10079 set_constant_flonums (void)
10083 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
10084 if (atof_ieee ((char *) fp_const
[i
], 'x', fp_values
[i
]) == NULL
)
10089 static const struct asm_opcode insns
[] =
10091 /* Core ARM Instructions. */
10092 {"and", 0xe0000000, 3, ARM_EXT_V1
, do_arit
},
10093 {"ands", 0xe0100000, 3, ARM_EXT_V1
, do_arit
},
10094 {"eor", 0xe0200000, 3, ARM_EXT_V1
, do_arit
},
10095 {"eors", 0xe0300000, 3, ARM_EXT_V1
, do_arit
},
10096 {"sub", 0xe0400000, 3, ARM_EXT_V1
, do_arit
},
10097 {"subs", 0xe0500000, 3, ARM_EXT_V1
, do_arit
},
10098 {"rsb", 0xe0600000, 3, ARM_EXT_V1
, do_arit
},
10099 {"rsbs", 0xe0700000, 3, ARM_EXT_V1
, do_arit
},
10100 {"add", 0xe0800000, 3, ARM_EXT_V1
, do_arit
},
10101 {"adds", 0xe0900000, 3, ARM_EXT_V1
, do_arit
},
10102 {"adc", 0xe0a00000, 3, ARM_EXT_V1
, do_arit
},
10103 {"adcs", 0xe0b00000, 3, ARM_EXT_V1
, do_arit
},
10104 {"sbc", 0xe0c00000, 3, ARM_EXT_V1
, do_arit
},
10105 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1
, do_arit
},
10106 {"rsc", 0xe0e00000, 3, ARM_EXT_V1
, do_arit
},
10107 {"rscs", 0xe0f00000, 3, ARM_EXT_V1
, do_arit
},
10108 {"orr", 0xe1800000, 3, ARM_EXT_V1
, do_arit
},
10109 {"orrs", 0xe1900000, 3, ARM_EXT_V1
, do_arit
},
10110 {"bic", 0xe1c00000, 3, ARM_EXT_V1
, do_arit
},
10111 {"bics", 0xe1d00000, 3, ARM_EXT_V1
, do_arit
},
10113 {"tst", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
10114 {"tsts", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
10115 {"tstp", 0xe110f000, 3, ARM_EXT_V1
, do_cmp
},
10116 {"teq", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
10117 {"teqs", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
10118 {"teqp", 0xe130f000, 3, ARM_EXT_V1
, do_cmp
},
10119 {"cmp", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
10120 {"cmps", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
10121 {"cmpp", 0xe150f000, 3, ARM_EXT_V1
, do_cmp
},
10122 {"cmn", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
10123 {"cmns", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
10124 {"cmnp", 0xe170f000, 3, ARM_EXT_V1
, do_cmp
},
10126 {"mov", 0xe1a00000, 3, ARM_EXT_V1
, do_mov
},
10127 {"movs", 0xe1b00000, 3, ARM_EXT_V1
, do_mov
},
10128 {"mvn", 0xe1e00000, 3, ARM_EXT_V1
, do_mov
},
10129 {"mvns", 0xe1f00000, 3, ARM_EXT_V1
, do_mov
},
10131 {"ldr", 0xe4100000, 3, ARM_EXT_V1
, do_ldst
},
10132 {"ldrb", 0xe4500000, 3, ARM_EXT_V1
, do_ldst
},
10133 {"ldrt", 0xe4300000, 3, ARM_EXT_V1
, do_ldstt
},
10134 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1
, do_ldstt
},
10135 {"str", 0xe4000000, 3, ARM_EXT_V1
, do_ldst
},
10136 {"strb", 0xe4400000, 3, ARM_EXT_V1
, do_ldst
},
10137 {"strt", 0xe4200000, 3, ARM_EXT_V1
, do_ldstt
},
10138 {"strbt", 0xe4600000, 3, ARM_EXT_V1
, do_ldstt
},
10140 {"stmia", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
10141 {"stmib", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
10142 {"stmda", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
10143 {"stmdb", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
10144 {"stmfd", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
10145 {"stmfa", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
10146 {"stmea", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
10147 {"stmed", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
10149 {"ldmia", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
10150 {"ldmib", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
10151 {"ldmda", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
10152 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
10153 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
10154 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
10155 {"ldmea", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
10156 {"ldmed", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
10158 {"swi", 0xef000000, 3, ARM_EXT_V1
, do_swi
},
10160 /* XXX This is the wrong place to do this. Think multi-arch. */
10161 {"bl", 0xeb000000, 2, ARM_EXT_V1
, do_branch
},
10162 {"b", 0xea000000, 1, ARM_EXT_V1
, do_branch
},
10164 {"bl", 0xebfffffe, 2, ARM_EXT_V1
, do_branch
},
10165 {"b", 0xeafffffe, 1, ARM_EXT_V1
, do_branch
},
10169 {"adr", 0xe28f0000, 3, ARM_EXT_V1
, do_adr
},
10170 {"adrl", 0xe28f0000, 3, ARM_EXT_V1
, do_adrl
},
10171 {"nop", 0xe1a00000, 3, ARM_EXT_V1
, do_nop
},
10173 /* ARM 2 multiplies. */
10174 {"mul", 0xe0000090, 3, ARM_EXT_V2
, do_mul
},
10175 {"muls", 0xe0100090, 3, ARM_EXT_V2
, do_mul
},
10176 {"mla", 0xe0200090, 3, ARM_EXT_V2
, do_mla
},
10177 {"mlas", 0xe0300090, 3, ARM_EXT_V2
, do_mla
},
10179 /* Generic coprocessor instructions. */
10180 {"cdp", 0xee000000, 3, ARM_EXT_V2
, do_cdp
},
10181 {"ldc", 0xec100000, 3, ARM_EXT_V2
, do_lstc
},
10182 {"ldcl", 0xec500000, 3, ARM_EXT_V2
, do_lstc
},
10183 {"stc", 0xec000000, 3, ARM_EXT_V2
, do_lstc
},
10184 {"stcl", 0xec400000, 3, ARM_EXT_V2
, do_lstc
},
10185 {"mcr", 0xee000010, 3, ARM_EXT_V2
, do_co_reg
},
10186 {"mrc", 0xee100010, 3, ARM_EXT_V2
, do_co_reg
},
10188 /* ARM 3 - swp instructions. */
10189 {"swp", 0xe1000090, 3, ARM_EXT_V2S
, do_swap
},
10190 {"swpb", 0xe1400090, 3, ARM_EXT_V2S
, do_swap
},
10192 /* ARM 6 Status register instructions. */
10193 {"mrs", 0xe10f0000, 3, ARM_EXT_V3
, do_mrs
},
10194 {"msr", 0xe120f000, 3, ARM_EXT_V3
, do_msr
},
10195 /* ScottB: our code uses 0xe128f000 for msr.
10196 NickC: but this is wrong because the bits 16 through 19 are
10197 handled by the PSR_xxx defines above. */
10199 /* ARM 7M long multiplies. */
10200 {"smull", 0xe0c00090, 5, ARM_EXT_V3M
, do_mull
},
10201 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M
, do_mull
},
10202 {"umull", 0xe0800090, 5, ARM_EXT_V3M
, do_mull
},
10203 {"umulls", 0xe0900090, 5, ARM_EXT_V3M
, do_mull
},
10204 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M
, do_mull
},
10205 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M
, do_mull
},
10206 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M
, do_mull
},
10207 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M
, do_mull
},
10209 /* ARM Architecture 4. */
10210 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4
, do_ldstv4
},
10211 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4
, do_ldstv4
},
10212 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4
, do_ldstv4
},
10213 {"strh", 0xe00000b0, 3, ARM_EXT_V4
, do_ldstv4
},
10215 /* ARM Architecture 4T. */
10216 /* Note: bx (and blx) are required on V5, even if the processor does
10217 not support Thumb. */
10218 {"bx", 0xe12fff10, 2, ARM_EXT_V4T
| ARM_EXT_V5
, do_bx
},
10220 /* ARM Architecture 5T. */
10221 /* Note: blx has 2 variants, so the .value is set dynamically.
10222 Only one of the variants has conditional execution. */
10223 {"blx", 0xe0000000, 3, ARM_EXT_V5
, do_blx
},
10224 {"clz", 0xe16f0f10, 3, ARM_EXT_V5
, do_clz
},
10225 {"bkpt", 0xe1200070, 0, ARM_EXT_V5
, do_bkpt
},
10226 {"ldc2", 0xfc100000, 0, ARM_EXT_V5
, do_lstc2
},
10227 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5
, do_lstc2
},
10228 {"stc2", 0xfc000000, 0, ARM_EXT_V5
, do_lstc2
},
10229 {"stc2l", 0xfc400000, 0, ARM_EXT_V5
, do_lstc2
},
10230 {"cdp2", 0xfe000000, 0, ARM_EXT_V5
, do_cdp2
},
10231 {"mcr2", 0xfe000010, 0, ARM_EXT_V5
, do_co_reg2
},
10232 {"mrc2", 0xfe100010, 0, ARM_EXT_V5
, do_co_reg2
},
10234 /* ARM Architecture 5TExP. */
10235 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP
, do_smla
},
10236 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP
, do_smla
},
10237 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP
, do_smla
},
10238 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP
, do_smla
},
10240 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP
, do_smla
},
10241 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP
, do_smla
},
10243 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP
, do_smlal
},
10244 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP
, do_smlal
},
10245 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP
, do_smlal
},
10246 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP
, do_smlal
},
10248 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP
, do_smul
},
10249 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP
, do_smul
},
10250 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP
, do_smul
},
10251 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP
, do_smul
},
10253 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP
, do_smul
},
10254 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP
, do_smul
},
10256 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP
, do_qadd
},
10257 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP
, do_qadd
},
10258 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP
, do_qadd
},
10259 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP
, do_qadd
},
10261 /* ARM Architecture 5TE. */
10262 {"pld", 0xf450f000, 0, ARM_EXT_V5E
, do_pld
},
10263 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E
, do_ldrd
},
10264 {"strd", 0xe00000f0, 3, ARM_EXT_V5E
, do_ldrd
},
10266 {"mcrr", 0xec400000, 4, ARM_EXT_V5E
, do_co_reg2c
},
10267 {"mrrc", 0xec500000, 4, ARM_EXT_V5E
, do_co_reg2c
},
10269 /* ARM Architecture 5TEJ. */
10270 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J
, do_bxj
},
10273 { "cps", 0xf1020000, 0, ARM_EXT_V6
, do_cps
},
10274 { "cpsie", 0xf1080000, 0, ARM_EXT_V6
, do_cpsi
},
10275 { "cpsid", 0xf10C0000, 0, ARM_EXT_V6
, do_cpsi
},
10276 { "ldrex", 0xe1900f9f, 5, ARM_EXT_V6
, do_ldrex
},
10277 { "mcrr2", 0xfc400000, 0, ARM_EXT_V6
, do_co_reg2c
},
10278 { "mrrc2", 0xfc500000, 0, ARM_EXT_V6
, do_co_reg2c
},
10279 { "pkhbt", 0xe6800010, 5, ARM_EXT_V6
, do_pkhbt
},
10280 { "pkhtb", 0xe6800050, 5, ARM_EXT_V6
, do_pkhtb
},
10281 { "qadd16", 0xe6200f10, 6, ARM_EXT_V6
, do_qadd16
},
10282 { "qadd8", 0xe6200f90, 5, ARM_EXT_V6
, do_qadd16
},
10283 { "qaddsubx", 0xe6200f30, 8, ARM_EXT_V6
, do_qadd16
},
10284 { "qsub16", 0xe6200f70, 6, ARM_EXT_V6
, do_qadd16
},
10285 { "qsub8", 0xe6200ff0, 5, ARM_EXT_V6
, do_qadd16
},
10286 { "qsubaddx", 0xe6200f50, 8, ARM_EXT_V6
, do_qadd16
},
10287 { "sadd16", 0xe6100f10, 6, ARM_EXT_V6
, do_qadd16
},
10288 { "sadd8", 0xe6100f90, 5, ARM_EXT_V6
, do_qadd16
},
10289 { "saddsubx", 0xe6100f30, 8, ARM_EXT_V6
, do_qadd16
},
10290 { "shadd16", 0xe6300f10, 7, ARM_EXT_V6
, do_qadd16
},
10291 { "shadd8", 0xe6300f90, 6, ARM_EXT_V6
, do_qadd16
},
10292 { "shaddsubx", 0xe6300f30, 9, ARM_EXT_V6
, do_qadd16
},
10293 { "shsub16", 0xe6300f70, 7, ARM_EXT_V6
, do_qadd16
},
10294 { "shsub8", 0xe6300ff0, 6, ARM_EXT_V6
, do_qadd16
},
10295 { "shsubaddx", 0xe6300f50, 9, ARM_EXT_V6
, do_qadd16
},
10296 { "ssub16", 0xe6100f70, 6, ARM_EXT_V6
, do_qadd16
},
10297 { "ssub8", 0xe6100ff0, 5, ARM_EXT_V6
, do_qadd16
},
10298 { "ssubaddx", 0xe6100f50, 8, ARM_EXT_V6
, do_qadd16
},
10299 { "uadd16", 0xe6500f10, 6, ARM_EXT_V6
, do_qadd16
},
10300 { "uadd8", 0xe6500f90, 5, ARM_EXT_V6
, do_qadd16
},
10301 { "uaddsubx", 0xe6500f30, 8, ARM_EXT_V6
, do_qadd16
},
10302 { "uhadd16", 0xe6700f10, 7, ARM_EXT_V6
, do_qadd16
},
10303 { "uhadd8", 0xe6700f90, 6, ARM_EXT_V6
, do_qadd16
},
10304 { "uhaddsubx", 0xe6700f30, 9, ARM_EXT_V6
, do_qadd16
},
10305 { "uhsub16", 0xe6700f70, 7, ARM_EXT_V6
, do_qadd16
},
10306 { "uhsub8", 0xe6700ff0, 6, ARM_EXT_V6
, do_qadd16
},
10307 { "uhsubaddx", 0xe6700f50, 9, ARM_EXT_V6
, do_qadd16
},
10308 { "uqadd16", 0xe6600f10, 7, ARM_EXT_V6
, do_qadd16
},
10309 { "uqadd8", 0xe6600f90, 6, ARM_EXT_V6
, do_qadd16
},
10310 { "uqaddsubx", 0xe6600f30, 9, ARM_EXT_V6
, do_qadd16
},
10311 { "uqsub16", 0xe6600f70, 7, ARM_EXT_V6
, do_qadd16
},
10312 { "uqsub8", 0xe6600ff0, 6, ARM_EXT_V6
, do_qadd16
},
10313 { "uqsubaddx", 0xe6600f50, 9, ARM_EXT_V6
, do_qadd16
},
10314 { "usub16", 0xe6500f70, 6, ARM_EXT_V6
, do_qadd16
},
10315 { "usub8", 0xe6500ff0, 5, ARM_EXT_V6
, do_qadd16
},
10316 { "usubaddx", 0xe6500f50, 8, ARM_EXT_V6
, do_qadd16
},
10317 { "rev", 0xe6bf0f30, 3, ARM_EXT_V6
, do_rev
},
10318 { "rev16", 0xe6bf0fb0, 5, ARM_EXT_V6
, do_rev
},
10319 { "revsh", 0xe6ff0fb0, 5, ARM_EXT_V6
, do_rev
},
10320 { "rfeia", 0xf8900a00, 0, ARM_EXT_V6
, do_rfe
},
10321 { "rfeib", 0xf9900a00, 0, ARM_EXT_V6
, do_rfe
},
10322 { "rfeda", 0xf8100a00, 0, ARM_EXT_V6
, do_rfe
},
10323 { "rfedb", 0xf9100a00, 0, ARM_EXT_V6
, do_rfe
},
10324 { "rfefd", 0xf8900a00, 0, ARM_EXT_V6
, do_rfe
},
10325 { "rfefa", 0xf9900a00, 0, ARM_EXT_V6
, do_rfe
},
10326 { "rfeea", 0xf8100a00, 0, ARM_EXT_V6
, do_rfe
},
10327 { "rfeed", 0xf9100a00, 0, ARM_EXT_V6
, do_rfe
},
10328 { "sxtah", 0xe6b00070, 5, ARM_EXT_V6
, do_sxtah
},
10329 { "sxtab16", 0xe6800070, 7, ARM_EXT_V6
, do_sxtah
},
10330 { "sxtab", 0xe6a00070, 5, ARM_EXT_V6
, do_sxtah
},
10331 { "sxth", 0xe6bf0070, 4, ARM_EXT_V6
, do_sxth
},
10332 { "sxtb16", 0xe68f0070, 6, ARM_EXT_V6
, do_sxth
},
10333 { "sxtb", 0xe6af0070, 4, ARM_EXT_V6
, do_sxth
},
10334 { "uxtah", 0xe6f00070, 5, ARM_EXT_V6
, do_sxtah
},
10335 { "uxtab16", 0xe6c00070, 7, ARM_EXT_V6
, do_sxtah
},
10336 { "uxtab", 0xe6e00070, 5, ARM_EXT_V6
, do_sxtah
},
10337 { "uxth", 0xe6ff0070, 4, ARM_EXT_V6
, do_sxth
},
10338 { "uxtb16", 0xe6cf0070, 6, ARM_EXT_V6
, do_sxth
},
10339 { "uxtb", 0xe6ef0070, 4, ARM_EXT_V6
, do_sxth
},
10340 { "sel", 0xe68000b0, 3, ARM_EXT_V6
, do_qadd16
},
10341 { "setend", 0xf1010000, 0, ARM_EXT_V6
, do_setend
},
10342 { "smlad", 0xe7000010, 5, ARM_EXT_V6
, do_smlad
},
10343 { "smladx", 0xe7000030, 6, ARM_EXT_V6
, do_smlad
},
10344 { "smlald", 0xe7400010, 6, ARM_EXT_V6
, do_smlald
},
10345 { "smlaldx", 0xe7400030, 7, ARM_EXT_V6
, do_smlald
},
10346 { "smlsd", 0xe7000050, 5, ARM_EXT_V6
, do_smlad
},
10347 { "smlsdx", 0xe7000070, 6, ARM_EXT_V6
, do_smlad
},
10348 { "smlsld", 0xe7400050, 6, ARM_EXT_V6
, do_smlald
},
10349 { "smlsldx", 0xe7400070, 7, ARM_EXT_V6
, do_smlald
},
10350 { "smmla", 0xe7500010, 5, ARM_EXT_V6
, do_smlad
},
10351 { "smmlar", 0xe7500030, 6, ARM_EXT_V6
, do_smlad
},
10352 { "smmls", 0xe75000d0, 5, ARM_EXT_V6
, do_smlad
},
10353 { "smmlsr", 0xe75000f0, 6, ARM_EXT_V6
, do_smlad
},
10354 { "smmul", 0xe750f010, 5, ARM_EXT_V6
, do_smmul
},
10355 { "smmulr", 0xe750f030, 6, ARM_EXT_V6
, do_smmul
},
10356 { "smuad", 0xe700f010, 5, ARM_EXT_V6
, do_smmul
},
10357 { "smuadx", 0xe700f030, 6, ARM_EXT_V6
, do_smmul
},
10358 { "smusd", 0xe700f050, 5, ARM_EXT_V6
, do_smmul
},
10359 { "smusdx", 0xe700f070, 6, ARM_EXT_V6
, do_smmul
},
10360 { "srsia", 0xf8cd0500, 0, ARM_EXT_V6
, do_srs
},
10361 { "srsib", 0xf9cd0500, 0, ARM_EXT_V6
, do_srs
},
10362 { "srsda", 0xf84d0500, 0, ARM_EXT_V6
, do_srs
},
10363 { "srsdb", 0xf94d0500, 0, ARM_EXT_V6
, do_srs
},
10364 { "ssat", 0xe6a00010, 4, ARM_EXT_V6
, do_ssat
},
10365 { "ssat16", 0xe6a00f30, 6, ARM_EXT_V6
, do_ssat16
},
10366 { "strex", 0xe1800f90, 5, ARM_EXT_V6
, do_strex
},
10367 { "umaal", 0xe0400090, 5, ARM_EXT_V6
, do_umaal
},
10368 { "usad8", 0xe780f010, 5, ARM_EXT_V6
, do_smmul
},
10369 { "usada8", 0xe7800010, 6, ARM_EXT_V6
, do_smlad
},
10370 { "usat", 0xe6e00010, 4, ARM_EXT_V6
, do_usat
},
10371 { "usat16", 0xe6e00f30, 6, ARM_EXT_V6
, do_usat16
},
10374 { "clrex", 0xf57ff01f, 0, ARM_EXT_V6K
, do_empty
},
10375 { "ldrexb", 0xe1d00f9f, 6, ARM_EXT_V6K
, do_ldrex
},
10376 { "ldrexd", 0xe1b00f9f, 6, ARM_EXT_V6K
, do_ldrex
},
10377 { "ldrexh", 0xe1f00f9f, 6, ARM_EXT_V6K
, do_ldrex
},
10378 { "sev", 0xe320f004, 3, ARM_EXT_V6K
, do_empty
},
10379 { "strexb", 0xe1c00f90, 6, ARM_EXT_V6K
, do_strex
},
10380 { "strexd", 0xe1a00f90, 6, ARM_EXT_V6K
, do_strex
},
10381 { "strexh", 0xe1e00f90, 6, ARM_EXT_V6K
, do_strex
},
10382 { "wfe", 0xe320f002, 3, ARM_EXT_V6K
, do_empty
},
10383 { "wfi", 0xe320f003, 3, ARM_EXT_V6K
, do_empty
},
10384 { "yield", 0xe320f001, 5, ARM_EXT_V6K
, do_empty
},
10387 { "smi", 0xe1600070, 3, ARM_EXT_V6Z
, do_smi
},
10390 { "bfc", 0xe7c0001f, 3, ARM_EXT_V6T2
, do_bfc
},
10391 { "bfi", 0xe7c00010, 3, ARM_EXT_V6T2
, do_bfi
},
10392 { "mls", 0xe0600090, 3, ARM_EXT_V6T2
, do_mls
},
10393 { "movw", 0xe3000000, 4, ARM_EXT_V6T2
, do_mov16
},
10394 { "movt", 0xe3400000, 4, ARM_EXT_V6T2
, do_mov16
},
10395 { "rbit", 0xe3ff0f30, 4, ARM_EXT_V6T2
, do_rbit
},
10396 { "sbfx", 0xe7a00050, 4, ARM_EXT_V6T2
, do_bfx
},
10397 { "ubfx", 0xe7e00050, 4, ARM_EXT_V6T2
, do_bfx
},
10399 { "ldrht", 0xe03000b0, 3, ARM_EXT_V6T2
, do_ldsttv4
},
10400 { "ldrsht", 0xe03000f0, 3, ARM_EXT_V6T2
, do_ldsttv4
},
10401 { "ldrsbt", 0xe03000d0, 3, ARM_EXT_V6T2
, do_ldsttv4
},
10402 { "strht", 0xe02000b0, 3, ARM_EXT_V6T2
, do_ldsttv4
},
10404 /* Core FPA instruction set (V1). */
10405 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
10406 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
10407 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
10408 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
10410 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10411 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10412 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10413 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10415 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10416 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10417 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10418 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10420 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10421 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10422 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10423 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10424 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10425 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10426 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10427 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10428 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10429 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10430 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10431 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10433 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10434 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10435 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10436 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10437 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10438 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10439 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10440 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10441 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10442 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10443 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10444 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10446 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10447 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10448 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10449 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10450 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10451 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10452 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10453 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10454 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10455 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10456 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10457 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10459 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10460 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10461 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10462 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10463 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10464 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10465 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10466 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10467 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10468 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10469 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10470 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10472 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10473 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10474 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10475 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10476 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10477 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10478 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10479 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10480 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10481 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10482 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10483 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10485 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10486 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10487 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10488 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10489 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10490 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10491 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10492 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10493 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10494 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10495 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10496 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10498 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10499 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10500 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10501 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10502 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10503 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10504 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10505 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10506 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10507 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10508 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10509 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10511 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10512 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10513 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10514 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10515 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10516 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10517 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10518 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10519 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10520 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10521 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10522 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10524 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10525 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10526 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10527 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10528 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10529 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10530 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10531 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10532 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10533 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10534 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10535 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10537 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10538 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10539 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10540 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10541 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10542 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10543 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10544 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10545 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10546 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10547 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10548 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10550 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10551 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10552 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10553 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10554 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10555 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10556 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10557 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10558 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10559 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10560 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10561 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10563 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10564 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10565 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10566 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10567 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10568 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10569 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10570 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10571 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10572 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10573 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10574 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10576 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10577 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10578 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10579 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10580 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10581 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10582 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10583 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10584 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10585 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10586 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10587 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10589 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10590 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10591 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10592 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10593 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10594 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10595 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10596 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10597 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10598 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10599 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10600 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10602 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10603 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10604 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10605 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10606 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10607 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10608 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10609 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10610 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10611 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10612 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10613 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10615 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10616 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10617 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10618 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10619 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10620 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10621 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10622 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10623 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10624 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10625 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10626 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10628 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10629 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10630 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10631 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10632 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10633 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10634 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10635 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10636 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10637 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10638 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10639 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10641 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10642 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10643 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10644 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10645 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10646 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10647 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10648 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10649 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10650 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10651 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10652 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10654 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10655 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10656 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10657 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10658 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10659 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10660 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10661 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10662 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10663 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10664 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10665 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10667 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10668 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10669 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10670 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10671 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10672 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10673 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10674 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10675 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10676 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10677 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10678 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10680 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10681 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10682 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10683 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10684 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10685 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10686 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10687 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10688 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10689 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10690 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10691 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10693 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10694 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10695 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10696 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10697 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10698 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10699 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10700 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10701 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10702 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10703 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10704 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10706 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10707 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10708 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10709 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10710 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10711 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10712 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10713 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10714 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10715 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10716 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10717 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10719 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10720 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10721 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10722 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10723 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10724 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10725 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10726 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10727 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10728 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10729 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10730 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10732 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10733 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10734 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10735 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10736 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10737 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10738 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10739 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10740 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10741 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10742 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10743 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10745 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10746 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10747 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10748 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10749 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10750 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10751 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10752 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10753 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10754 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10755 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10756 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10758 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10759 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10760 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10761 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10762 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10763 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10764 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10765 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10766 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10767 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10768 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10769 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10771 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10772 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10773 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10774 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10775 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10776 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10777 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10778 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10779 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10780 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10781 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10782 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10784 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10785 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10786 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10787 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10788 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10789 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10790 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10791 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10792 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10793 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10794 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10795 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10797 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10798 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10799 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10800 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10801 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
10802 not be an optional suffix, but part of the instruction. To be
10803 compatible, we accept either. */
10804 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10805 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10807 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10808 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10809 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10810 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10811 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10812 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10813 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10814 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10815 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10816 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10817 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10818 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10820 /* The implementation of the FIX instruction is broken on some
10821 assemblers, in that it accepts a precision specifier as well as a
10822 rounding specifier, despite the fact that this is meaningless.
10823 To be more compatible, we accept it as well, though of course it
10824 does not set any bits. */
10825 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10826 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10827 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10828 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10829 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10830 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10831 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10832 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10833 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10834 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10835 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10836 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10837 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10839 /* Instructions that were new with the real FPA, call them V2. */
10840 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10841 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10842 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10843 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10844 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10845 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10847 /* VFP V1xD (single precision). */
10848 /* Moves and type conversions. */
10849 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10850 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_reg_from_sp
},
10851 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_from_reg
},
10852 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD
, do_empty
},
10853 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10854 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10855 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10856 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10857 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10858 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10859 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_reg_from_ctrl
},
10860 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_ctrl_from_reg
},
10862 /* Memory operations. */
10863 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldst
},
10864 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldst
},
10865 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
10866 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
10867 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
10868 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
10869 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
10870 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
10871 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
10872 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
10873 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
10874 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
10875 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
10876 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
10877 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
10878 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
10879 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
10880 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
10882 /* Monadic operations. */
10883 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10884 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10885 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10887 /* Dyadic operations. */
10888 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10889 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10890 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10891 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10892 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10893 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10894 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10895 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10896 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10899 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10900 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_compare_z
},
10901 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10902 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_compare_z
},
10904 /* VFP V1 (Double precision). */
10905 /* Moves and type conversions. */
10906 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10907 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
10908 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10909 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1
, do_vfp_dp_from_reg
},
10910 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1
, do_vfp_dp_from_reg
},
10911 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1
, do_vfp_reg_from_dp
},
10912 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1
, do_vfp_reg_from_dp
},
10913 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
10914 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
10915 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10916 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10917 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10918 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10920 /* Memory operations. */
10921 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1
, do_vfp_dp_ldst
},
10922 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1
, do_vfp_dp_ldst
},
10923 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
10924 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
10925 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
10926 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
10927 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
10928 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
10929 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
10930 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
10932 /* Monadic operations. */
10933 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10934 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10935 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10937 /* Dyadic operations. */
10938 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10939 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10940 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10941 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10942 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10943 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10944 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10945 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10946 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10949 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10950 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_compare_z
},
10951 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10952 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1
, do_vfp_dp_compare_z
},
10955 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2
, do_vfp_sp2_from_reg2
},
10956 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2
, do_vfp_reg2_from_sp2
},
10957 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2
, do_vfp_dp_from_reg2
},
10958 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2
, do_vfp_reg2_from_dp
},
10960 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
10961 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE
, do_xsc_mia
},
10962 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10963 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10964 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10965 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10966 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10967 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE
, do_xsc_mar
},
10968 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE
, do_xsc_mra
},
10970 /* Intel Wireless MMX technology instructions. */
10971 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
10972 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
10973 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
10974 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
10975 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
10976 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
10977 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
10978 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
10979 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
10980 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10981 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10982 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10983 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10984 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10985 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10986 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
10987 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
10988 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
10989 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmcr
},
10990 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_tmcrr
},
10991 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10992 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10993 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10994 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10995 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10996 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10997 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
10998 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
10999 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
11000 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmrc
},
11001 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_tmrrc
},
11002 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
11003 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
11004 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
11005 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11006 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11007 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11008 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11009 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11010 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11011 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11012 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11013 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11014 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11015 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11016 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11017 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_waligni
},
11018 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11019 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11020 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11021 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11022 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11023 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11024 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11025 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11026 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11027 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11028 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11029 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11030 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11031 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11032 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11033 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11034 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11035 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11036 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11037 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
11038 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
11039 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
11040 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
11041 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11042 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11043 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11044 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11045 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11046 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11047 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11048 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11049 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11050 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11051 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11052 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11053 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11054 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11055 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11056 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11057 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11058 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11059 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wmov
},
11060 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11061 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11062 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11063 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11064 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11065 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11066 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11067 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11068 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11069 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11070 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11071 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11072 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
11073 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11074 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
11075 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11076 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
11077 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11078 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11079 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11080 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11081 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wshufh
},
11082 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11083 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
11084 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11085 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
11086 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11087 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
11088 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11089 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
11090 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11091 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
11092 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11093 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
11094 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11095 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
11096 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11097 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
11098 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11099 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
11100 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
11101 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
11102 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
11103 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
11104 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11105 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11106 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11107 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11108 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11109 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11110 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11111 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11112 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11113 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11114 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11115 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11116 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11117 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11118 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11119 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11120 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11121 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11122 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11123 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11124 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11125 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11126 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11127 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
11128 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11129 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11130 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11131 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
11132 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wzero
},
11134 /* Cirrus Maverick instructions. */
11135 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_1
},
11136 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_2
},
11137 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_3
},
11138 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_4
},
11139 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_1
},
11140 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_2
},
11141 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_3
},
11142 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_4
},
11143 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK
, do_mav_binops_2a
},
11144 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1a
},
11145 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK
, do_mav_binops_2b
},
11146 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1b
},
11147 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK
, do_mav_binops_2b
},
11148 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1b
},
11149 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK
, do_mav_binops_2c
},
11150 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1c
},
11151 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK
, do_mav_binops_2c
},
11152 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1c
},
11153 {"cfmval32", 0xee200440, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
11154 {"cfmv32al", 0xee100440, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
11155 {"cfmvam32", 0xee200460, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
11156 {"cfmv32am", 0xee100460, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
11157 {"cfmvah32", 0xee200480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
11158 {"cfmv32ah", 0xee100480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
11159 {"cfmva32", 0xee2004a0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
11160 {"cfmv32a", 0xee1004a0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
11161 {"cfmva64", 0xee2004c0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3c
},
11162 {"cfmv64a", 0xee1004c0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3d
},
11163 {"cfmvsc32", 0xee2004e0, 8, ARM_CEXT_MAVERICK
, do_mav_dspsc_1
},
11164 {"cfmv32sc", 0xee1004e0, 8, ARM_CEXT_MAVERICK
, do_mav_dspsc_2
},
11165 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
11166 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
11167 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1f
},
11168 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1g
},
11169 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1h
},
11170 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1i
},
11171 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1j
},
11172 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1k
},
11173 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1l
},
11174 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1m
},
11175 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK
, do_mav_binops_1l
},
11176 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK
, do_mav_binops_1m
},
11177 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK
, do_mav_triple_4a
},
11178 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK
, do_mav_triple_4b
},
11179 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK
, do_mav_shift_1
},
11180 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK
, do_mav_shift_2
},
11181 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5a
},
11182 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5b
},
11183 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5c
},
11184 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5d
},
11185 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
11186 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
11187 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
11188 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
11189 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
11190 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
11191 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
11192 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
11193 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
11194 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
11195 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1n
},
11196 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1o
},
11197 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1n
},
11198 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1o
},
11199 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
11200 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
11201 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
11202 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
11203 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
11204 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
11205 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
11206 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
11207 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK
, do_mav_quad_6a
},
11208 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK
, do_mav_quad_6a
},
11209 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK
, do_mav_quad_6b
},
11210 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK
, do_mav_quad_6b
},
11213 /* Iterate over the base tables to create the instruction patterns. */
11216 build_arm_ops_hsh (void)
11220 static struct obstack insn_obstack
;
11222 obstack_begin (&insn_obstack
, 4000);
11224 for (i
= 0; i
< sizeof (insns
) / sizeof (struct asm_opcode
); i
++)
11226 const struct asm_opcode
*insn
= insns
+ i
;
11228 if (insn
->cond_offset
!= 0)
11230 /* Insn supports conditional execution. Build the varaints
11231 and insert them in the hash table. */
11232 for (j
= 0; j
< sizeof (conds
) / sizeof (struct asm_cond
); j
++)
11234 unsigned len
= strlen (insn
->template);
11235 struct asm_opcode
*new;
11238 new = obstack_alloc (&insn_obstack
, sizeof (struct asm_opcode
));
11239 /* All condition codes are two characters. */
11240 template = obstack_alloc (&insn_obstack
, len
+ 3);
11242 strncpy (template, insn
->template, insn
->cond_offset
);
11243 strcpy (template + insn
->cond_offset
, conds
[j
].template);
11244 if (len
> insn
->cond_offset
)
11245 strcpy (template + insn
->cond_offset
+ 2,
11246 insn
->template + insn
->cond_offset
);
11247 new->template = template;
11248 new->cond_offset
= 0;
11249 new->variant
= insn
->variant
;
11250 new->parms
= insn
->parms
;
11251 new->value
= (insn
->value
& ~COND_MASK
) | conds
[j
].value
;
11253 hash_insert (arm_ops_hsh
, new->template, (PTR
) new);
11256 /* Finally, insert the unconditional insn in the table directly;
11257 no need to build a copy. */
11258 hash_insert (arm_ops_hsh
, insn
->template, (PTR
) insn
);
11263 static const struct thumb_opcode tinsns
[] =
11265 /* Thumb v1 (ARMv4T). */
11266 {"adc", 0x4140, 2, ARM_EXT_V4T
, do_t_arit
},
11267 {"add", 0x0000, 2, ARM_EXT_V4T
, do_t_add
},
11268 {"and", 0x4000, 2, ARM_EXT_V4T
, do_t_arit
},
11269 {"asr", 0x0000, 2, ARM_EXT_V4T
, do_t_asr
},
11270 {"b", T_OPCODE_BRANCH
, 2, ARM_EXT_V4T
, do_t_branch12
},
11271 {"beq", 0xd0fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11272 {"bne", 0xd1fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11273 {"bcs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11274 {"bhs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11275 {"bcc", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11276 {"bul", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11277 {"blo", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11278 {"bmi", 0xd4fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11279 {"bpl", 0xd5fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11280 {"bvs", 0xd6fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11281 {"bvc", 0xd7fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11282 {"bhi", 0xd8fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11283 {"bls", 0xd9fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11284 {"bge", 0xdafe, 2, ARM_EXT_V4T
, do_t_branch9
},
11285 {"blt", 0xdbfe, 2, ARM_EXT_V4T
, do_t_branch9
},
11286 {"bgt", 0xdcfe, 2, ARM_EXT_V4T
, do_t_branch9
},
11287 {"ble", 0xddfe, 2, ARM_EXT_V4T
, do_t_branch9
},
11288 {"bal", 0xdefe, 2, ARM_EXT_V4T
, do_t_branch9
},
11289 {"bic", 0x4380, 2, ARM_EXT_V4T
, do_t_arit
},
11290 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T
, do_t_branch23
},
11291 {"bx", 0x4700, 2, ARM_EXT_V4T
, do_t_bx
},
11292 {"cmn", T_OPCODE_CMN
, 2, ARM_EXT_V4T
, do_t_arit
},
11293 {"cmp", 0x0000, 2, ARM_EXT_V4T
, do_t_compare
},
11294 {"eor", 0x4040, 2, ARM_EXT_V4T
, do_t_arit
},
11295 {"ldmia", 0xc800, 2, ARM_EXT_V4T
, do_t_ldmstm
},
11296 {"ldr", 0x0000, 2, ARM_EXT_V4T
, do_t_ldr
},
11297 {"ldrb", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrb
},
11298 {"ldrh", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrh
},
11299 {"ldrsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
11300 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
11301 {"ldsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
11302 {"ldsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
11303 {"lsl", 0x0000, 2, ARM_EXT_V4T
, do_t_lsl
},
11304 {"lsr", 0x0000, 2, ARM_EXT_V4T
, do_t_lsr
},
11305 {"mov", 0x0000, 2, ARM_EXT_V4T
, do_t_mov
},
11306 {"mul", T_OPCODE_MUL
, 2, ARM_EXT_V4T
, do_t_arit
},
11307 {"mvn", T_OPCODE_MVN
, 2, ARM_EXT_V4T
, do_t_arit
},
11308 {"neg", T_OPCODE_NEG
, 2, ARM_EXT_V4T
, do_t_arit
},
11309 {"orr", 0x4300, 2, ARM_EXT_V4T
, do_t_arit
},
11310 {"pop", 0xbc00, 2, ARM_EXT_V4T
, do_t_push_pop
},
11311 {"push", 0xb400, 2, ARM_EXT_V4T
, do_t_push_pop
},
11312 {"ror", 0x41c0, 2, ARM_EXT_V4T
, do_t_arit
},
11313 {"sbc", 0x4180, 2, ARM_EXT_V4T
, do_t_arit
},
11314 {"stmia", 0xc000, 2, ARM_EXT_V4T
, do_t_ldmstm
},
11315 {"str", 0x0000, 2, ARM_EXT_V4T
, do_t_str
},
11316 {"strb", 0x0000, 2, ARM_EXT_V4T
, do_t_strb
},
11317 {"strh", 0x0000, 2, ARM_EXT_V4T
, do_t_strh
},
11318 {"swi", 0xdf00, 2, ARM_EXT_V4T
, do_t_swi
},
11319 {"sub", 0x0000, 2, ARM_EXT_V4T
, do_t_sub
},
11320 {"tst", T_OPCODE_TST
, 2, ARM_EXT_V4T
, do_t_arit
},
11322 {"adr", 0x0000, 2, ARM_EXT_V4T
, do_t_adr
},
11323 {"nop", 0x46C0, 2, ARM_EXT_V4T
, do_t_nop
}, /* mov r8,r8 */
11324 /* Thumb v2 (ARMv5T). */
11325 {"blx", 0, 0, ARM_EXT_V5T
, do_t_blx
},
11326 {"bkpt", 0xbe00, 2, ARM_EXT_V5T
, do_t_bkpt
},
11329 {"cpsie", 0xb660, 2, ARM_EXT_V6
, do_t_cps
},
11330 {"cpsid", 0xb670, 2, ARM_EXT_V6
, do_t_cps
},
11331 {"cpy", 0x4600, 2, ARM_EXT_V6
, do_t_cpy
},
11332 {"rev", 0xba00, 2, ARM_EXT_V6
, do_t_arit
},
11333 {"rev16", 0xba40, 2, ARM_EXT_V6
, do_t_arit
},
11334 {"revsh", 0xbac0, 2, ARM_EXT_V6
, do_t_arit
},
11335 {"setend", 0xb650, 2, ARM_EXT_V6
, do_t_setend
},
11336 {"sxth", 0xb200, 2, ARM_EXT_V6
, do_t_arit
},
11337 {"sxtb", 0xb240, 2, ARM_EXT_V6
, do_t_arit
},
11338 {"uxth", 0xb280, 2, ARM_EXT_V6
, do_t_arit
},
11339 {"uxtb", 0xb2c0, 2, ARM_EXT_V6
, do_t_arit
},
11342 {"sev", 0xbf40, 2, ARM_EXT_V6K
, do_empty
},
11343 {"wfe", 0xbf20, 2, ARM_EXT_V6K
, do_empty
},
11344 {"wfi", 0xbf30, 2, ARM_EXT_V6K
, do_empty
},
11345 {"yield", 0xbf10, 2, ARM_EXT_V6K
, do_empty
},
11354 if ( (arm_ops_hsh
= hash_new ()) == NULL
11355 || (arm_tops_hsh
= hash_new ()) == NULL
11356 || (arm_cond_hsh
= hash_new ()) == NULL
11357 || (arm_shift_hsh
= hash_new ()) == NULL
11358 || (arm_psr_hsh
= hash_new ()) == NULL
)
11359 as_fatal (_("virtual memory exhausted"));
11361 build_arm_ops_hsh ();
11362 for (i
= 0; i
< sizeof (tinsns
) / sizeof (struct thumb_opcode
); i
++)
11363 hash_insert (arm_tops_hsh
, tinsns
[i
].template, (PTR
) (tinsns
+ i
));
11364 for (i
= 0; i
< sizeof (conds
) / sizeof (struct asm_cond
); i
++)
11365 hash_insert (arm_cond_hsh
, conds
[i
].template, (PTR
) (conds
+ i
));
11366 for (i
= 0; i
< sizeof (shift_names
) / sizeof (struct asm_shift_name
); i
++)
11367 hash_insert (arm_shift_hsh
, shift_names
[i
].name
, (PTR
) (shift_names
+ i
));
11368 for (i
= 0; i
< sizeof (psrs
) / sizeof (struct asm_psr
); i
++)
11369 hash_insert (arm_psr_hsh
, psrs
[i
].template, (PTR
) (psrs
+ i
));
11371 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
11372 build_reg_hsh (all_reg_maps
+ i
);
11374 set_constant_flonums ();
11376 /* Set the cpu variant based on the command-line options. We prefer
11377 -mcpu= over -march= if both are set (as for GCC); and we prefer
11378 -mfpu= over any other way of setting the floating point unit.
11379 Use of legacy options with new options are faulted. */
11380 if (legacy_cpu
!= -1)
11382 if (mcpu_cpu_opt
!= -1 || march_cpu_opt
!= -1)
11383 as_bad (_("use of old and new-style options to set CPU type"));
11385 mcpu_cpu_opt
= legacy_cpu
;
11387 else if (mcpu_cpu_opt
== -1)
11388 mcpu_cpu_opt
= march_cpu_opt
;
11390 if (legacy_fpu
!= -1)
11392 if (mfpu_opt
!= -1)
11393 as_bad (_("use of old and new-style options to set FPU type"));
11395 mfpu_opt
= legacy_fpu
;
11397 else if (mfpu_opt
== -1)
11399 #if !(defined (TE_LINUX) || defined (TE_NetBSD) || defined (TE_VXWORKS))
11400 /* Some environments specify a default FPU. If they don't, infer it
11401 from the processor. */
11402 if (mcpu_fpu_opt
!= -1)
11403 mfpu_opt
= mcpu_fpu_opt
;
11405 mfpu_opt
= march_fpu_opt
;
11407 mfpu_opt
= FPU_DEFAULT
;
11411 if (mfpu_opt
== -1)
11413 if (mcpu_cpu_opt
== -1)
11414 mfpu_opt
= FPU_DEFAULT
;
11415 else if (mcpu_cpu_opt
& ARM_EXT_V5
)
11416 mfpu_opt
= FPU_ARCH_VFP_V2
;
11418 mfpu_opt
= FPU_ARCH_FPA
;
11421 if (mcpu_cpu_opt
== -1)
11422 mcpu_cpu_opt
= CPU_DEFAULT
;
11424 cpu_variant
= mcpu_cpu_opt
| mfpu_opt
;
11426 #if defined OBJ_COFF || defined OBJ_ELF
11428 unsigned int flags
= 0;
11430 #if defined OBJ_ELF
11431 flags
= meabi_flags
;
11433 switch (meabi_flags
)
11435 case EF_ARM_EABI_UNKNOWN
:
11437 /* Set the flags in the private structure. */
11438 if (uses_apcs_26
) flags
|= F_APCS26
;
11439 if (support_interwork
) flags
|= F_INTERWORK
;
11440 if (uses_apcs_float
) flags
|= F_APCS_FLOAT
;
11441 if (pic_code
) flags
|= F_PIC
;
11442 if ((cpu_variant
& FPU_ANY
) == FPU_NONE
11443 || (cpu_variant
& FPU_ANY
) == FPU_ARCH_VFP
) /* VFP layout only. */
11444 flags
|= F_SOFT_FLOAT
;
11446 switch (mfloat_abi_opt
)
11448 case ARM_FLOAT_ABI_SOFT
:
11449 case ARM_FLOAT_ABI_SOFTFP
:
11450 flags
|= F_SOFT_FLOAT
;
11453 case ARM_FLOAT_ABI_HARD
:
11454 if (flags
& F_SOFT_FLOAT
)
11455 as_bad (_("hard-float conflicts with specified fpu"));
11459 /* Using VFP conventions (even if soft-float). */
11460 if (cpu_variant
& FPU_VFP_EXT_NONE
)
11461 flags
|= F_VFP_FLOAT
;
11463 #if defined OBJ_ELF
11464 if (cpu_variant
& FPU_ARCH_MAVERICK
)
11465 flags
|= EF_ARM_MAVERICK_FLOAT
;
11468 case EF_ARM_EABI_VER4
:
11469 /* No additional flags to set. */
11476 bfd_set_private_flags (stdoutput
, flags
);
11478 /* We have run out flags in the COFF header to encode the
11479 status of ATPCS support, so instead we create a dummy,
11480 empty, debug section called .arm.atpcs. */
11485 sec
= bfd_make_section (stdoutput
, ".arm.atpcs");
11489 bfd_set_section_flags
11490 (stdoutput
, sec
, SEC_READONLY
| SEC_DEBUGGING
/* | SEC_HAS_CONTENTS */);
11491 bfd_set_section_size (stdoutput
, sec
, 0);
11492 bfd_set_section_contents (stdoutput
, sec
, NULL
, 0, 0);
11498 /* Record the CPU type as well. */
11499 switch (cpu_variant
& ARM_CPU_MASK
)
11502 mach
= bfd_mach_arm_2
;
11505 case ARM_3
: /* Also ARM_250. */
11506 mach
= bfd_mach_arm_2a
;
11509 case ARM_6
: /* Also ARM_7. */
11510 mach
= bfd_mach_arm_3
;
11514 mach
= bfd_mach_arm_unknown
;
11518 /* Catch special cases. */
11519 if (cpu_variant
& ARM_CEXT_IWMMXT
)
11520 mach
= bfd_mach_arm_iWMMXt
;
11521 else if (cpu_variant
& ARM_CEXT_XSCALE
)
11522 mach
= bfd_mach_arm_XScale
;
11523 else if (cpu_variant
& ARM_CEXT_MAVERICK
)
11524 mach
= bfd_mach_arm_ep9312
;
11525 else if (cpu_variant
& ARM_EXT_V5E
)
11526 mach
= bfd_mach_arm_5TE
;
11527 else if (cpu_variant
& ARM_EXT_V5
)
11529 if (cpu_variant
& ARM_EXT_V4T
)
11530 mach
= bfd_mach_arm_5T
;
11532 mach
= bfd_mach_arm_5
;
11534 else if (cpu_variant
& ARM_EXT_V4
)
11536 if (cpu_variant
& ARM_EXT_V4T
)
11537 mach
= bfd_mach_arm_4T
;
11539 mach
= bfd_mach_arm_4
;
11541 else if (cpu_variant
& ARM_EXT_V3M
)
11542 mach
= bfd_mach_arm_3M
;
11544 bfd_set_arch_mach (stdoutput
, TARGET_ARCH
, mach
);
11547 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11548 for use in the a.out file, and stores them in the array pointed to by buf.
11549 This knows about the endian-ness of the target machine and does
11550 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11551 2 (short) and 4 (long) Floating numbers are put out as a series of
11552 LITTLENUMS (shorts, here at least). */
11555 md_number_to_chars (char * buf
, valueT val
, int n
)
11557 if (target_big_endian
)
11558 number_to_chars_bigendian (buf
, val
, n
);
11560 number_to_chars_littleendian (buf
, val
, n
);
11564 md_chars_to_number (char * buf
, int n
)
11567 unsigned char * where
= (unsigned char *) buf
;
11569 if (target_big_endian
)
11574 result
|= (*where
++ & 255);
11582 result
|= (where
[n
] & 255);
11589 /* Turn a string in input_line_pointer into a floating point constant
11590 of type TYPE, and store the appropriate bytes in *LITP. The number
11591 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11592 returned, or NULL on OK.
11594 Note that fp constants aren't represent in the normal way on the ARM.
11595 In big endian mode, things are as expected. However, in little endian
11596 mode fp constants are big-endian word-wise, and little-endian byte-wise
11597 within the words. For example, (double) 1.1 in big endian mode is
11598 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11599 the byte sequence 99 99 f1 3f 9a 99 99 99.
11601 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11604 md_atof (int type
, char * litP
, int * sizeP
)
11607 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
11639 return _("bad call to MD_ATOF()");
11642 t
= atof_ieee (input_line_pointer
, type
, words
);
11644 input_line_pointer
= t
;
11647 if (target_big_endian
)
11649 for (i
= 0; i
< prec
; i
++)
11651 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
11657 if (cpu_variant
& FPU_ARCH_VFP
)
11658 for (i
= prec
- 1; i
>= 0; i
--)
11660 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
11664 /* For a 4 byte float the order of elements in `words' is 1 0.
11665 For an 8 byte float the order is 1 0 3 2. */
11666 for (i
= 0; i
< prec
; i
+= 2)
11668 md_number_to_chars (litP
, (valueT
) words
[i
+ 1], 2);
11669 md_number_to_chars (litP
+ 2, (valueT
) words
[i
], 2);
11677 /* The knowledge of the PC's pipeline offset is built into the insns
11681 md_pcrel_from (fixS
* fixP
)
11684 && S_GET_SEGMENT (fixP
->fx_addsy
) == undefined_section
11685 && fixP
->fx_subsy
== NULL
)
11688 if (fixP
->fx_pcrel
&& (fixP
->fx_r_type
== BFD_RELOC_ARM_THUMB_ADD
))
11690 /* PC relative addressing on the Thumb is slightly odd
11691 as the bottom two bits of the PC are forced to zero
11692 for the calculation. */
11693 return (fixP
->fx_where
+ fixP
->fx_frag
->fr_address
) & ~3;
11697 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
11698 so we un-adjust here to compensate for the accommodation. */
11699 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
+ 8;
11701 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
11705 /* Round up a section size to the appropriate boundary. */
11708 md_section_align (segT segment ATTRIBUTE_UNUSED
,
11714 /* Round all sects to multiple of 4. */
11715 return (size
+ 3) & ~3;
11719 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
11720 Otherwise we have no need to default values of symbols. */
11723 md_undefined_symbol (char * name ATTRIBUTE_UNUSED
)
11726 if (name
[0] == '_' && name
[1] == 'G'
11727 && streq (name
, GLOBAL_OFFSET_TABLE_NAME
))
11731 if (symbol_find (name
))
11732 as_bad ("GOT already in the symbol table");
11734 GOT_symbol
= symbol_new (name
, undefined_section
,
11735 (valueT
) 0, & zero_address_frag
);
11746 md_apply_fix3 (fixS
* fixP
,
11750 offsetT value
= * valP
;
11752 unsigned int newimm
;
11753 unsigned long temp
;
11755 char * buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
11756 arm_fix_data
* arm_data
= (arm_fix_data
*) fixP
->tc_fix_data
;
11758 assert (fixP
->fx_r_type
<= BFD_RELOC_UNUSED
);
11760 /* Note whether this will delete the relocation. */
11761 if (fixP
->fx_addsy
== 0 && !fixP
->fx_pcrel
)
11764 /* If this symbol is in a different section then we need to leave it for
11765 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
11766 so we have to undo it's effects here. */
11767 if (fixP
->fx_pcrel
)
11769 if (fixP
->fx_addsy
!= NULL
11770 && S_IS_DEFINED (fixP
->fx_addsy
)
11771 && S_GET_SEGMENT (fixP
->fx_addsy
) != seg
)
11772 value
+= md_pcrel_from (fixP
);
11775 /* Remember value for emit_reloc. */
11776 fixP
->fx_addnumber
= value
;
11778 switch (fixP
->fx_r_type
)
11780 case BFD_RELOC_NONE
:
11781 /* This will need to go in the object file. */
11785 case BFD_RELOC_ARM_IMMEDIATE
:
11786 /* We claim that this fixup has been processed here,
11787 even if in fact we generate an error because we do
11788 not have a reloc for it, so tc_gen_reloc will reject it. */
11792 && ! S_IS_DEFINED (fixP
->fx_addsy
))
11794 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11795 _("undefined symbol %s used as an immediate value"),
11796 S_GET_NAME (fixP
->fx_addsy
));
11800 newimm
= validate_immediate (value
);
11801 temp
= md_chars_to_number (buf
, INSN_SIZE
);
11803 /* If the instruction will fail, see if we can fix things up by
11804 changing the opcode. */
11805 if (newimm
== (unsigned int) FAIL
11806 && (newimm
= negate_data_op (&temp
, value
)) == (unsigned int) FAIL
)
11808 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11809 _("invalid constant (%lx) after fixup"),
11810 (unsigned long) value
);
11814 newimm
|= (temp
& 0xfffff000);
11815 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
11818 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
11820 unsigned int highpart
= 0;
11821 unsigned int newinsn
= 0xe1a00000; /* nop. */
11823 newimm
= validate_immediate (value
);
11824 temp
= md_chars_to_number (buf
, INSN_SIZE
);
11826 /* If the instruction will fail, see if we can fix things up by
11827 changing the opcode. */
11828 if (newimm
== (unsigned int) FAIL
11829 && (newimm
= negate_data_op (& temp
, value
)) == (unsigned int) FAIL
)
11831 /* No ? OK - try using two ADD instructions to generate
11833 newimm
= validate_immediate_twopart (value
, & highpart
);
11835 /* Yes - then make sure that the second instruction is
11837 if (newimm
!= (unsigned int) FAIL
)
11839 /* Still No ? Try using a negated value. */
11840 else if ((newimm
= validate_immediate_twopart (- value
, & highpart
)) != (unsigned int) FAIL
)
11841 temp
= newinsn
= (temp
& OPCODE_MASK
) | OPCODE_SUB
<< DATA_OP_SHIFT
;
11842 /* Otherwise - give up. */
11845 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11846 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
11851 /* Replace the first operand in the 2nd instruction (which
11852 is the PC) with the destination register. We have
11853 already added in the PC in the first instruction and we
11854 do not want to do it again. */
11855 newinsn
&= ~ 0xf0000;
11856 newinsn
|= ((newinsn
& 0x0f000) << 4);
11859 newimm
|= (temp
& 0xfffff000);
11860 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
11862 highpart
|= (newinsn
& 0xfffff000);
11863 md_number_to_chars (buf
+ INSN_SIZE
, (valueT
) highpart
, INSN_SIZE
);
11867 case BFD_RELOC_ARM_OFFSET_IMM
:
11873 if (validate_offset_imm (value
, 0) == FAIL
)
11875 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11876 _("bad immediate value for offset (%ld)"),
11881 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11882 newval
&= 0xff7ff000;
11883 newval
|= value
| (sign
? INDEX_UP
: 0);
11884 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11887 case BFD_RELOC_ARM_OFFSET_IMM8
:
11888 case BFD_RELOC_ARM_HWLITERAL
:
11894 if (validate_offset_imm (value
, 1) == FAIL
)
11896 if (fixP
->fx_r_type
== BFD_RELOC_ARM_HWLITERAL
)
11897 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11898 _("invalid literal constant: pool needs to be closer"));
11900 as_bad (_("bad immediate value for half-word offset (%ld)"),
11905 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11906 newval
&= 0xff7ff0f0;
11907 newval
|= ((value
>> 4) << 8) | (value
& 0xf) | (sign
? INDEX_UP
: 0);
11908 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11911 case BFD_RELOC_ARM_LITERAL
:
11917 if (validate_offset_imm (value
, 0) == FAIL
)
11919 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11920 _("invalid literal constant: pool needs to be closer"));
11924 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11925 newval
&= 0xff7ff000;
11926 newval
|= value
| (sign
? INDEX_UP
: 0);
11927 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11930 case BFD_RELOC_ARM_SHIFT_IMM
:
11931 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11932 if (((unsigned long) value
) > 32
11934 && (((newval
& 0x60) == 0) || (newval
& 0x60) == 0x60)))
11936 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11937 _("shift expression is too large"));
11942 /* Shifts of zero must be done as lsl. */
11944 else if (value
== 32)
11946 newval
&= 0xfffff07f;
11947 newval
|= (value
& 0x1f) << 7;
11948 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11951 case BFD_RELOC_ARM_SMI
:
11952 if (((unsigned long) value
) > 0xffff)
11953 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11954 _("invalid smi expression"));
11955 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xfff000f0;
11956 newval
|= (value
& 0xf) | ((value
& 0xfff0) << 4);
11957 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11960 case BFD_RELOC_ARM_SWI
:
11961 if (arm_data
->thumb_mode
)
11963 if (((unsigned long) value
) > 0xff)
11964 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11965 _("invalid swi expression"));
11966 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xff00;
11968 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11972 if (((unsigned long) value
) > 0x00ffffff)
11973 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11974 _("invalid swi expression"));
11975 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff000000;
11977 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11981 case BFD_RELOC_ARM_MULTI
:
11982 if (((unsigned long) value
) > 0xffff)
11983 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11984 _("invalid expression in load/store multiple"));
11985 newval
= value
| md_chars_to_number (buf
, INSN_SIZE
);
11986 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11989 case BFD_RELOC_ARM_PCREL_BRANCH
:
11990 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11992 /* Sign-extend a 24-bit number. */
11993 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
11996 value
= fixP
->fx_offset
;
11999 /* We are going to store value (shifted right by two) in the
12000 instruction, in a 24 bit, signed field. Thus we need to check
12001 that none of the top 8 bits of the shifted value (top 7 bits of
12002 the unshifted, unsigned value) are set, or that they are all set. */
12003 if ((value
& ~ ((offsetT
) 0x1ffffff)) != 0
12004 && ((value
& ~ ((offsetT
) 0x1ffffff)) != ~ ((offsetT
) 0x1ffffff)))
12007 /* Normally we would be stuck at this point, since we cannot store
12008 the absolute address that is the destination of the branch in the
12009 24 bits of the branch instruction. If however, we happen to know
12010 that the destination of the branch is in the same section as the
12011 branch instruction itself, then we can compute the relocation for
12012 ourselves and not have to bother the linker with it.
12014 FIXME: The test for OBJ_ELF is only here because I have not
12015 worked out how to do this for OBJ_COFF. */
12016 if (fixP
->fx_addsy
!= NULL
12017 && S_IS_DEFINED (fixP
->fx_addsy
)
12018 && S_GET_SEGMENT (fixP
->fx_addsy
) == seg
)
12020 /* Get pc relative value to go into the branch. */
12023 /* Permit a backward branch provided that enough bits
12024 are set. Allow a forwards branch, provided that
12025 enough bits are clear. */
12026 if ( (value
& ~ ((offsetT
) 0x1ffffff)) == ~ ((offsetT
) 0x1ffffff)
12027 || (value
& ~ ((offsetT
) 0x1ffffff)) == 0)
12031 if (! fixP
->fx_done
)
12033 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12034 _("GAS can't handle same-section branch dest >= 0x04000000"));
12038 value
+= SEXT24 (newval
);
12040 if ( (value
& ~ ((offsetT
) 0xffffff)) != 0
12041 && ((value
& ~ ((offsetT
) 0xffffff)) != ~ ((offsetT
) 0xffffff)))
12042 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12043 _("out of range branch"));
12045 if (seg
->use_rela_p
&& !fixP
->fx_done
)
12047 /* Must unshift the value before storing it in the addend. */
12050 fixP
->fx_offset
= value
;
12052 fixP
->fx_addnumber
= value
;
12053 newval
= newval
& 0xff000000;
12056 newval
= (value
& 0x00ffffff) | (newval
& 0xff000000);
12057 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12060 case BFD_RELOC_ARM_PCREL_BLX
:
12063 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12066 value
= fixP
->fx_offset
;
12068 hbit
= (value
>> 1) & 1;
12069 value
= (value
>> 2) & 0x00ffffff;
12070 value
= (value
+ (newval
& 0x00ffffff)) & 0x00ffffff;
12072 if (seg
->use_rela_p
&& !fixP
->fx_done
)
12074 /* Must sign-extend and unshift the value before storing
12075 it in the addend. */
12076 value
= SEXT24 (value
);
12077 value
= (value
<< 2) | hbit
;
12079 fixP
->fx_offset
= value
;
12081 fixP
->fx_addnumber
= value
;
12082 newval
= newval
& 0xfe000000;
12085 newval
= value
| (newval
& 0xfe000000) | (hbit
<< 24);
12086 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12090 case BFD_RELOC_THUMB_PCREL_BRANCH9
: /* Conditional branch. */
12091 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12093 addressT diff
= (newval
& 0xff) << 1;
12098 if ((value
& ~0xff) && ((value
& ~0xff) != ~0xff))
12099 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12100 _("branch out of range"));
12101 if (seg
->use_rela_p
&& !fixP
->fx_done
)
12104 fixP
->fx_offset
= value
;
12106 fixP
->fx_addnumber
= value
;
12107 newval
= newval
& 0xff00;
12110 newval
= (newval
& 0xff00) | ((value
& 0x1ff) >> 1);
12112 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12115 case BFD_RELOC_THUMB_PCREL_BRANCH12
: /* Unconditional branch. */
12116 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12118 addressT diff
= (newval
& 0x7ff) << 1;
12123 if ((value
& ~0x7ff) && ((value
& ~0x7ff) != ~0x7ff))
12124 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12125 _("branch out of range"));
12126 if (seg
->use_rela_p
&& !fixP
->fx_done
)
12129 fixP
->fx_offset
= value
;
12131 fixP
->fx_addnumber
= value
;
12132 newval
= newval
& 0xf800;
12135 newval
= (newval
& 0xf800) | ((value
& 0xfff) >> 1);
12137 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12140 case BFD_RELOC_THUMB_PCREL_BLX
:
12141 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
12146 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12147 newval2
= md_chars_to_number (buf
+ THUMB_SIZE
, THUMB_SIZE
);
12148 diff
= ((newval
& 0x7ff) << 12) | ((newval2
& 0x7ff) << 1);
12149 if (diff
& 0x400000)
12152 value
= fixP
->fx_offset
;
12156 if ((value
& ~0x3fffff) && ((value
& ~0x3fffff) != ~0x3fffff))
12157 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12158 _("branch with link out of range"));
12160 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
)
12161 /* For a BLX instruction, make sure that the relocation is rounded up
12162 to a word boundary. This follows the semantics of the instruction
12163 which specifies that bit 1 of the target address will come from bit
12164 1 of the base address. */
12165 value
= (value
+ 1) & ~ 1;
12167 if (seg
->use_rela_p
&& !fixP
->fx_done
)
12170 fixP
->fx_offset
= value
;
12172 fixP
->fx_addnumber
= value
;
12173 newval
= newval
& 0xf800;
12174 newval2
= newval2
& 0xf800;
12178 newval
= (newval
& 0xf800) | ((value
& 0x7fffff) >> 12);
12179 newval2
= (newval2
& 0xf800) | ((value
& 0xfff) >> 1);
12181 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12182 md_number_to_chars (buf
+ THUMB_SIZE
, newval2
, THUMB_SIZE
);
12187 if (seg
->use_rela_p
&& !fixP
->fx_done
)
12189 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
12190 md_number_to_chars (buf
, value
, 1);
12194 value
= fixP
->fx_offset
;
12195 md_number_to_chars (buf
, value
, 1);
12201 if (seg
->use_rela_p
&& !fixP
->fx_done
)
12203 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
12204 md_number_to_chars (buf
, value
, 2);
12208 value
= fixP
->fx_offset
;
12209 md_number_to_chars (buf
, value
, 2);
12215 case BFD_RELOC_ARM_GOT32
:
12216 case BFD_RELOC_ARM_GOTOFF
:
12217 case BFD_RELOC_ARM_TARGET2
:
12218 if (seg
->use_rela_p
&& !fixP
->fx_done
)
12220 md_number_to_chars (buf
, 0, 4);
12224 case BFD_RELOC_RVA
:
12226 case BFD_RELOC_ARM_TARGET1
:
12227 case BFD_RELOC_ARM_ROSEGREL32
:
12228 case BFD_RELOC_ARM_SBREL32
:
12229 case BFD_RELOC_32_PCREL
:
12230 if (seg
->use_rela_p
&& !fixP
->fx_done
)
12232 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
12233 md_number_to_chars (buf
, value
, 4);
12237 value
= fixP
->fx_offset
;
12238 md_number_to_chars (buf
, value
, 4);
12244 case BFD_RELOC_ARM_PREL31
:
12245 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
12247 newval
= md_chars_to_number (buf
, 4) & 0x80000000;
12248 if ((value
^ (value
>> 1)) & 0x40000000)
12250 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12251 _("rel31 relocation overflow"));
12253 newval
|= value
& 0x7fffffff;
12254 md_number_to_chars (buf
, newval
, 4);
12258 case BFD_RELOC_ARM_PLT32
:
12259 /* It appears the instruction is fully prepared at this point. */
12263 case BFD_RELOC_ARM_CP_OFF_IMM
:
12265 if (value
< -1023 || value
> 1023 || (value
& 3))
12266 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12267 _("illegal value for co-processor offset"));
12270 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
12271 newval
|= (value
>> 2) | (sign
? INDEX_UP
: 0);
12272 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12275 case BFD_RELOC_ARM_CP_OFF_IMM_S2
:
12277 if (value
< -255 || value
> 255)
12278 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12279 _("Illegal value for co-processor offset"));
12282 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
12283 newval
|= value
| (sign
? INDEX_UP
: 0);
12284 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12287 case BFD_RELOC_ARM_THUMB_OFFSET
:
12288 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12289 /* Exactly what ranges, and where the offset is inserted depends
12290 on the type of instruction, we can establish this from the
12292 switch (newval
>> 12)
12294 case 4: /* PC load. */
12295 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
12296 forced to zero for these loads, so we will need to round
12297 up the offset if the instruction address is not word
12298 aligned (since the final address produced must be, and
12299 we can only describe word-aligned immediate offsets). */
12301 if ((fixP
->fx_frag
->fr_address
+ fixP
->fx_where
+ value
) & 3)
12302 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12303 _("invalid offset, target not word aligned (0x%08X)"),
12304 (unsigned int) (fixP
->fx_frag
->fr_address
12305 + fixP
->fx_where
+ value
));
12307 if ((value
+ 2) & ~0x3fe)
12308 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12309 _("invalid offset, value too big (0x%08lX)"),
12312 /* Round up, since pc will be rounded down. */
12313 newval
|= (value
+ 2) >> 2;
12316 case 9: /* SP load/store. */
12317 if (value
& ~0x3fc)
12318 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12319 _("invalid offset, value too big (0x%08lX)"),
12321 newval
|= value
>> 2;
12324 case 6: /* Word load/store. */
12326 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12327 _("invalid offset, value too big (0x%08lX)"),
12329 newval
|= value
<< 4; /* 6 - 2. */
12332 case 7: /* Byte load/store. */
12334 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12335 _("invalid offset, value too big (0x%08lX)"),
12337 newval
|= value
<< 6;
12340 case 8: /* Halfword load/store. */
12342 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12343 _("invalid offset, value too big (0x%08lX)"),
12345 newval
|= value
<< 5; /* 6 - 1. */
12349 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12350 "Unable to process relocation for thumb opcode: %lx",
12351 (unsigned long) newval
);
12354 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12357 case BFD_RELOC_ARM_THUMB_ADD
:
12358 /* This is a complicated relocation, since we use it for all of
12359 the following immediate relocations:
12363 9bit ADD/SUB SP word-aligned
12364 10bit ADD PC/SP word-aligned
12366 The type of instruction being processed is encoded in the
12373 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12375 int rd
= (newval
>> 4) & 0xf;
12376 int rs
= newval
& 0xf;
12377 int subtract
= newval
& 0x8000;
12381 if (value
& ~0x1fc)
12382 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12383 _("invalid immediate for stack address calculation"));
12384 newval
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
12385 newval
|= value
>> 2;
12387 else if (rs
== REG_PC
|| rs
== REG_SP
)
12391 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12392 _("invalid immediate for address calculation (value = 0x%08lX)"),
12393 (unsigned long) value
);
12394 newval
= (rs
== REG_PC
? T_OPCODE_ADD_PC
: T_OPCODE_ADD_SP
);
12396 newval
|= value
>> 2;
12401 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12402 _("invalid 8bit immediate"));
12403 newval
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
12404 newval
|= (rd
<< 8) | value
;
12409 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12410 _("invalid 3bit immediate"));
12411 newval
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
12412 newval
|= rd
| (rs
<< 3) | (value
<< 6);
12415 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12418 case BFD_RELOC_ARM_THUMB_IMM
:
12419 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12420 switch (newval
>> 11)
12422 case 0x04: /* 8bit immediate MOV. */
12423 case 0x05: /* 8bit immediate CMP. */
12424 if (value
< 0 || value
> 255)
12425 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12426 _("invalid immediate: %ld is too large"),
12434 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12437 case BFD_RELOC_ARM_THUMB_SHIFT
:
12438 /* 5bit shift value (0..31). */
12439 if (value
< 0 || value
> 31)
12440 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12441 _("illegal Thumb shift value: %ld"), (long) value
);
12442 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xf03f;
12443 newval
|= value
<< 6;
12444 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12447 case BFD_RELOC_VTABLE_INHERIT
:
12448 case BFD_RELOC_VTABLE_ENTRY
:
12452 case BFD_RELOC_UNUSED
:
12454 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12455 _("bad relocation fixup type (%d)"), fixP
->fx_r_type
);
12459 /* Translate internal representation of relocation info to BFD target
12463 tc_gen_reloc (asection
* section ATTRIBUTE_UNUSED
,
12467 bfd_reloc_code_real_type code
;
12469 reloc
= xmalloc (sizeof (arelent
));
12471 reloc
->sym_ptr_ptr
= xmalloc (sizeof (asymbol
*));
12472 *reloc
->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
12473 reloc
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
12475 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12477 if (fixp
->fx_pcrel
== 0)
12478 reloc
->addend
= fixp
->fx_offset
;
12480 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
12481 #else /* OBJ_ELF */
12482 reloc
->addend
= fixp
->fx_offset
;
12485 switch (fixp
->fx_r_type
)
12488 if (fixp
->fx_pcrel
)
12490 code
= BFD_RELOC_8_PCREL
;
12495 if (fixp
->fx_pcrel
)
12497 code
= BFD_RELOC_16_PCREL
;
12502 if (fixp
->fx_pcrel
)
12504 code
= BFD_RELOC_32_PCREL
;
12508 case BFD_RELOC_NONE
:
12509 case BFD_RELOC_ARM_PCREL_BRANCH
:
12510 case BFD_RELOC_ARM_PCREL_BLX
:
12511 case BFD_RELOC_RVA
:
12512 case BFD_RELOC_THUMB_PCREL_BRANCH9
:
12513 case BFD_RELOC_THUMB_PCREL_BRANCH12
:
12514 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
12515 case BFD_RELOC_THUMB_PCREL_BLX
:
12516 case BFD_RELOC_VTABLE_ENTRY
:
12517 case BFD_RELOC_VTABLE_INHERIT
:
12518 code
= fixp
->fx_r_type
;
12521 case BFD_RELOC_ARM_LITERAL
:
12522 case BFD_RELOC_ARM_HWLITERAL
:
12523 /* If this is called then the a literal has
12524 been referenced across a section boundary. */
12525 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12526 _("literal referenced across section boundary"));
12530 case BFD_RELOC_ARM_GOT32
:
12531 case BFD_RELOC_ARM_GOTOFF
:
12532 case BFD_RELOC_ARM_PLT32
:
12533 case BFD_RELOC_ARM_TARGET1
:
12534 case BFD_RELOC_ARM_ROSEGREL32
:
12535 case BFD_RELOC_ARM_SBREL32
:
12536 case BFD_RELOC_ARM_PREL31
:
12537 case BFD_RELOC_ARM_TARGET2
:
12538 code
= fixp
->fx_r_type
;
12542 case BFD_RELOC_ARM_IMMEDIATE
:
12543 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12544 _("internal relocation (type: IMMEDIATE) not fixed up"));
12547 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
12548 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12549 _("ADRL used for a symbol not defined in the same file"));
12552 case BFD_RELOC_ARM_OFFSET_IMM
:
12553 if (fixp
->fx_addsy
!= NULL
12554 && !S_IS_DEFINED (fixp
->fx_addsy
)
12555 && S_IS_LOCAL (fixp
->fx_addsy
))
12557 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12558 _("undefined local label `%s'"),
12559 S_GET_NAME (fixp
->fx_addsy
));
12563 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12564 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
12571 switch (fixp
->fx_r_type
)
12573 case BFD_RELOC_NONE
: type
= "NONE"; break;
12574 case BFD_RELOC_ARM_OFFSET_IMM8
: type
= "OFFSET_IMM8"; break;
12575 case BFD_RELOC_ARM_SHIFT_IMM
: type
= "SHIFT_IMM"; break;
12576 case BFD_RELOC_ARM_SMI
: type
= "SMI"; break;
12577 case BFD_RELOC_ARM_SWI
: type
= "SWI"; break;
12578 case BFD_RELOC_ARM_MULTI
: type
= "MULTI"; break;
12579 case BFD_RELOC_ARM_CP_OFF_IMM
: type
= "CP_OFF_IMM"; break;
12580 case BFD_RELOC_ARM_THUMB_ADD
: type
= "THUMB_ADD"; break;
12581 case BFD_RELOC_ARM_THUMB_SHIFT
: type
= "THUMB_SHIFT"; break;
12582 case BFD_RELOC_ARM_THUMB_IMM
: type
= "THUMB_IMM"; break;
12583 case BFD_RELOC_ARM_THUMB_OFFSET
: type
= "THUMB_OFFSET"; break;
12584 default: type
= _("<unknown>"); break;
12586 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12587 _("cannot represent %s relocation in this object file format"),
12594 if ((code
== BFD_RELOC_32_PCREL
|| code
== BFD_RELOC_32
)
12596 && fixp
->fx_addsy
== GOT_symbol
)
12598 code
= BFD_RELOC_ARM_GOTPC
;
12599 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
12603 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, code
);
12605 if (reloc
->howto
== NULL
)
12607 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12608 _("cannot represent %s relocation in this object file format"),
12609 bfd_get_reloc_code_name (code
));
12613 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12614 vtable entry to be used in the relocation's section offset. */
12615 if (fixp
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
12616 reloc
->address
= fixp
->fx_offset
;
12622 md_estimate_size_before_relax (fragS
* fragP ATTRIBUTE_UNUSED
,
12623 segT segtype ATTRIBUTE_UNUSED
)
12625 as_fatal (_("md_estimate_size_before_relax\n"));
12629 /* We need to be able to fix up arbitrary expressions in some statements.
12630 This is so that we can handle symbols that are an arbitrary distance from
12631 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
12632 which returns part of an address in a form which will be valid for
12633 a data instruction. We do this by pushing the expression into a symbol
12634 in the expr_section, and creating a fix for that. */
12637 fix_new_arm (fragS
* frag
,
12645 arm_fix_data
* arm_data
;
12653 new_fix
= fix_new_exp (frag
, where
, size
, exp
, pc_rel
, reloc
);
12657 new_fix
= fix_new (frag
, where
, size
, make_expr_symbol (exp
), 0,
12662 /* Mark whether the fix is to a THUMB instruction, or an ARM
12664 arm_data
= obstack_alloc (& notes
, sizeof (arm_fix_data
));
12665 new_fix
->tc_fix_data
= (PTR
) arm_data
;
12666 arm_data
->thumb_mode
= thumb_mode
;
12670 output_inst (const char * str
)
12676 as_bad ("%s -- `%s'", inst
.error
, str
);
12680 to
= frag_more (inst
.size
);
12682 if (thumb_mode
&& (inst
.size
> THUMB_SIZE
))
12684 assert (inst
.size
== (2 * THUMB_SIZE
));
12685 md_number_to_chars (to
, inst
.instruction
>> 16, THUMB_SIZE
);
12686 md_number_to_chars (to
+ THUMB_SIZE
, inst
.instruction
, THUMB_SIZE
);
12688 else if (inst
.size
> INSN_SIZE
)
12690 assert (inst
.size
== (2 * INSN_SIZE
));
12691 md_number_to_chars (to
, inst
.instruction
, INSN_SIZE
);
12692 md_number_to_chars (to
+ INSN_SIZE
, inst
.instruction
, INSN_SIZE
);
12695 md_number_to_chars (to
, inst
.instruction
, inst
.size
);
12697 if (inst
.reloc
.type
!= BFD_RELOC_UNUSED
)
12698 fix_new_arm (frag_now
, to
- frag_now
->fr_literal
,
12699 inst
.size
, & inst
.reloc
.exp
, inst
.reloc
.pc_rel
,
12703 dwarf2_emit_insn (inst
.size
);
12708 md_assemble (char * str
)
12714 /* Align the previous label if needed. */
12715 if (last_label_seen
!= NULL
)
12717 symbol_set_frag (last_label_seen
, frag_now
);
12718 S_SET_VALUE (last_label_seen
, (valueT
) frag_now_fix ());
12719 S_SET_SEGMENT (last_label_seen
, now_seg
);
12722 memset (&inst
, '\0', sizeof (inst
));
12723 inst
.reloc
.type
= BFD_RELOC_UNUSED
;
12725 skip_whitespace (str
);
12727 /* Scan up to the end of the op-code, which must end in white space or
12729 for (start
= p
= str
; *p
!= '\0'; p
++)
12735 as_bad (_("no operator -- statement `%s'\n"), str
);
12741 const struct thumb_opcode
* opcode
;
12745 opcode
= (const struct thumb_opcode
*) hash_find (arm_tops_hsh
, str
);
12750 /* Check that this instruction is supported for this CPU. */
12751 if (thumb_mode
== 1 && (opcode
->variant
& cpu_variant
) == 0)
12753 as_bad (_("selected processor does not support `%s'"), str
);
12757 mapping_state (MAP_THUMB
);
12758 inst
.instruction
= opcode
->value
;
12759 inst
.size
= opcode
->size
;
12767 const struct asm_opcode
* opcode
;
12771 opcode
= (const struct asm_opcode
*) hash_find (arm_ops_hsh
, str
);
12776 /* Check that this instruction is supported for this CPU. */
12777 if ((opcode
->variant
& cpu_variant
) == 0)
12779 as_bad (_("selected processor does not support `%s'"), str
);
12783 mapping_state (MAP_ARM
);
12784 inst
.instruction
= opcode
->value
;
12785 inst
.size
= INSN_SIZE
;
12792 /* It wasn't an instruction, but it might be a register alias of the form
12794 if (create_register_alias (str
, p
))
12797 as_bad (_("bad instruction `%s'"), start
);
12801 Invocation line includes a switch not recognized by the base assembler.
12802 See if it's a processor-specific option.
12804 This routine is somewhat complicated by the need for backwards
12805 compatibility (since older releases of gcc can't be changed).
12806 The new options try to make the interface as compatible as
12809 New options (supported) are:
12811 -mcpu=<cpu name> Assemble for selected processor
12812 -march=<architecture name> Assemble for selected architecture
12813 -mfpu=<fpu architecture> Assemble for selected FPU.
12814 -EB/-mbig-endian Big-endian
12815 -EL/-mlittle-endian Little-endian
12816 -k Generate PIC code
12817 -mthumb Start in Thumb mode
12818 -mthumb-interwork Code supports ARM/Thumb interworking
12820 For now we will also provide support for:
12822 -mapcs-32 32-bit Program counter
12823 -mapcs-26 26-bit Program counter
12824 -macps-float Floats passed in FP registers
12825 -mapcs-reentrant Reentrant code
12827 (sometime these will probably be replaced with -mapcs=<list of options>
12828 and -matpcs=<list of options>)
12830 The remaining options are only supported for back-wards compatibility.
12831 Cpu variants, the arm part is optional:
12832 -m[arm]1 Currently not supported.
12833 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
12834 -m[arm]3 Arm 3 processor
12835 -m[arm]6[xx], Arm 6 processors
12836 -m[arm]7[xx][t][[d]m] Arm 7 processors
12837 -m[arm]8[10] Arm 8 processors
12838 -m[arm]9[20][tdmi] Arm 9 processors
12839 -mstrongarm[110[0]] StrongARM processors
12840 -mxscale XScale processors
12841 -m[arm]v[2345[t[e]]] Arm architectures
12842 -mall All (except the ARM1)
12844 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
12845 -mfpe-old (No float load/store multiples)
12846 -mvfpxd VFP Single precision
12848 -mno-fpu Disable all floating point instructions
12850 The following CPU names are recognized:
12851 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
12852 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
12853 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
12854 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
12855 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
12856 arm10t arm10e, arm1020t, arm1020e, arm10200e,
12857 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
12861 const char * md_shortopts
= "m:k";
12863 #ifdef ARM_BI_ENDIAN
12864 #define OPTION_EB (OPTION_MD_BASE + 0)
12865 #define OPTION_EL (OPTION_MD_BASE + 1)
12867 #if TARGET_BYTES_BIG_ENDIAN
12868 #define OPTION_EB (OPTION_MD_BASE + 0)
12870 #define OPTION_EL (OPTION_MD_BASE + 1)
12874 struct option md_longopts
[] =
12877 {"EB", no_argument
, NULL
, OPTION_EB
},
12880 {"EL", no_argument
, NULL
, OPTION_EL
},
12882 {NULL
, no_argument
, NULL
, 0}
12885 size_t md_longopts_size
= sizeof (md_longopts
);
12887 struct arm_option_table
12889 char *option
; /* Option name to match. */
12890 char *help
; /* Help information. */
12891 int *var
; /* Variable to change. */
12892 int value
; /* What to change it to. */
12893 char *deprecated
; /* If non-null, print this message. */
12896 struct arm_option_table arm_opts
[] =
12898 {"k", N_("generate PIC code"), &pic_code
, 1, NULL
},
12899 {"mthumb", N_("assemble Thumb code"), &thumb_mode
, 1, NULL
},
12900 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
12901 &support_interwork
, 1, NULL
},
12902 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26
, 0, NULL
},
12903 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26
, 1, NULL
},
12904 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float
,
12906 {"mapcs-reentrant", N_("re-entrant code"), &pic_code
, 1, NULL
},
12907 {"matpcs", N_("code is ATPCS conformant"), &atpcs
, 1, NULL
},
12908 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian
, 1, NULL
},
12909 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian
, 1,
12912 /* These are recognized by the assembler, but have no affect on code. */
12913 {"mapcs-frame", N_("use frame pointer"), NULL
, 0, NULL
},
12914 {"mapcs-stack-check", N_("use stack size checking"), NULL
, 0, NULL
},
12916 /* DON'T add any new processors to this list -- we want the whole list
12917 to go away... Add them to the processors table instead. */
12918 {"marm1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
12919 {"m1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
12920 {"marm2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
12921 {"m2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
12922 {"marm250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
12923 {"m250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
12924 {"marm3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
12925 {"m3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
12926 {"marm6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
12927 {"m6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
12928 {"marm600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
12929 {"m600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
12930 {"marm610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
12931 {"m610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
12932 {"marm620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
12933 {"m620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
12934 {"marm7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
12935 {"m7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
12936 {"marm70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
12937 {"m70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
12938 {"marm700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
12939 {"m700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
12940 {"marm700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
12941 {"m700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
12942 {"marm710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
12943 {"m710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
12944 {"marm710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
12945 {"m710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
12946 {"marm720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
12947 {"m720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
12948 {"marm7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
12949 {"m7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
12950 {"marm7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
12951 {"m7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
12952 {"marm7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
12953 {"m7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
12954 {"marm7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
12955 {"m7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
12956 {"marm7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
12957 {"m7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
12958 {"marm7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
12959 {"m7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
12960 {"marm7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
12961 {"m7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
12962 {"marm7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
12963 {"m7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
12964 {"marm7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12965 {"m7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12966 {"marm7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12967 {"m7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12968 {"marm710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
12969 {"m710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
12970 {"marm720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
12971 {"m720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
12972 {"marm740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
12973 {"m740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
12974 {"marm8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
12975 {"m8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
12976 {"marm810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
12977 {"m810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
12978 {"marm9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
12979 {"m9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
12980 {"marm9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
12981 {"m9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
12982 {"marm920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
12983 {"m920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
12984 {"marm940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
12985 {"m940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
12986 {"mstrongarm", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=strongarm")},
12987 {"mstrongarm110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
12988 N_("use -mcpu=strongarm110")},
12989 {"mstrongarm1100", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
12990 N_("use -mcpu=strongarm1100")},
12991 {"mstrongarm1110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
12992 N_("use -mcpu=strongarm1110")},
12993 {"mxscale", NULL
, &legacy_cpu
, ARM_ARCH_XSCALE
, N_("use -mcpu=xscale")},
12994 {"miwmmxt", NULL
, &legacy_cpu
, ARM_ARCH_IWMMXT
, N_("use -mcpu=iwmmxt")},
12995 {"mall", NULL
, &legacy_cpu
, ARM_ANY
, N_("use -mcpu=all")},
12997 /* Architecture variants -- don't add any more to this list either. */
12998 {"mv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
12999 {"marmv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
13000 {"mv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
13001 {"marmv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
13002 {"mv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
13003 {"marmv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
13004 {"mv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
13005 {"marmv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
13006 {"mv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
13007 {"marmv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
13008 {"mv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
13009 {"marmv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
13010 {"mv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
13011 {"marmv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
13012 {"mv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
13013 {"marmv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
13014 {"mv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
13015 {"marmv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
13017 /* Floating point variants -- don't add any more to this list either. */
13018 {"mfpe-old", NULL
, &legacy_fpu
, FPU_ARCH_FPE
, N_("use -mfpu=fpe")},
13019 {"mfpa10", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa10")},
13020 {"mfpa11", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa11")},
13021 {"mno-fpu", NULL
, &legacy_fpu
, 0,
13022 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
13024 {NULL
, NULL
, NULL
, 0, NULL
}
13027 struct arm_cpu_option_table
13031 /* For some CPUs we assume an FPU unless the user explicitly sets
13036 /* This list should, at a minimum, contain all the cpu names
13037 recognized by GCC. */
13038 static struct arm_cpu_option_table arm_cpus
[] =
13040 {"all", ARM_ANY
, FPU_ARCH_FPA
},
13041 {"arm1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
13042 {"arm2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
13043 {"arm250", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
13044 {"arm3", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
13045 {"arm6", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13046 {"arm60", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13047 {"arm600", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13048 {"arm610", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13049 {"arm620", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13050 {"arm7", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13051 {"arm7m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
13052 {"arm7d", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13053 {"arm7dm", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
13054 {"arm7di", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13055 {"arm7dmi", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
13056 {"arm70", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13057 {"arm700", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13058 {"arm700i", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13059 {"arm710", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13060 {"arm710t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13061 {"arm720", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13062 {"arm720t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13063 {"arm740t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13064 {"arm710c", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13065 {"arm7100", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13066 {"arm7500", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13067 {"arm7500fe", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13068 {"arm7t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13069 {"arm7tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13070 {"arm7tdmi-s", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13071 {"arm8", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13072 {"arm810", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13073 {"strongarm", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13074 {"strongarm1", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13075 {"strongarm110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13076 {"strongarm1100", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13077 {"strongarm1110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13078 {"arm9", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13079 {"arm920", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13080 {"arm920t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13081 {"arm922t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13082 {"arm940t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13083 {"arm9tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13084 /* For V5 or later processors we default to using VFP; but the user
13085 should really set the FPU type explicitly. */
13086 {"arm9e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
13087 {"arm9e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13088 {"arm926ej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
13089 {"arm926ejs", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
13090 {"arm926ej-s", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
13091 {"arm946e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
13092 {"arm946e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13093 {"arm966e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
13094 {"arm966e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13095 {"arm10t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
13096 {"arm10e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13097 {"arm1020", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13098 {"arm1020t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
13099 {"arm1020e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13100 {"arm1026ejs", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
13101 {"arm1026ej-s", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
13102 {"arm1136js", ARM_ARCH_V6
, FPU_NONE
},
13103 {"arm1136j-s", ARM_ARCH_V6
, FPU_NONE
},
13104 {"arm1136jfs", ARM_ARCH_V6
, FPU_ARCH_VFP_V2
},
13105 {"arm1136jf-s", ARM_ARCH_V6
, FPU_ARCH_VFP_V2
},
13106 {"mpcore", ARM_ARCH_V6K
, FPU_ARCH_VFP_V2
},
13107 {"mpcorenovfp", ARM_ARCH_V6K
, FPU_NONE
},
13108 {"arm1176jz-s", ARM_ARCH_V6ZK
, FPU_NONE
},
13109 {"arm1176jzf-s", ARM_ARCH_V6ZK
, FPU_ARCH_VFP_V2
},
13110 /* ??? XSCALE is really an architecture. */
13111 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
13112 /* ??? iwmmxt is not a processor. */
13113 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP_V2
},
13114 {"i80200", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
13116 {"ep9312", ARM_ARCH_V4T
| ARM_CEXT_MAVERICK
, FPU_ARCH_MAVERICK
},
13120 struct arm_arch_option_table
13127 /* This list should, at a minimum, contain all the architecture names
13128 recognized by GCC. */
13129 static struct arm_arch_option_table arm_archs
[] =
13131 {"all", ARM_ANY
, FPU_ARCH_FPA
},
13132 {"armv1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
13133 {"armv2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
13134 {"armv2a", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
13135 {"armv2s", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
13136 {"armv3", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13137 {"armv3m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
13138 {"armv4", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13139 {"armv4xm", ARM_ARCH_V4xM
, FPU_ARCH_FPA
},
13140 {"armv4t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13141 {"armv4txm", ARM_ARCH_V4TxM
, FPU_ARCH_FPA
},
13142 {"armv5", ARM_ARCH_V5
, FPU_ARCH_VFP
},
13143 {"armv5t", ARM_ARCH_V5T
, FPU_ARCH_VFP
},
13144 {"armv5txm", ARM_ARCH_V5TxM
, FPU_ARCH_VFP
},
13145 {"armv5te", ARM_ARCH_V5TE
, FPU_ARCH_VFP
},
13146 {"armv5texp", ARM_ARCH_V5TExP
, FPU_ARCH_VFP
},
13147 {"armv5tej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP
},
13148 {"armv6", ARM_ARCH_V6
, FPU_ARCH_VFP
},
13149 {"armv6j", ARM_ARCH_V6
, FPU_ARCH_VFP
},
13150 {"armv6k", ARM_ARCH_V6K
, FPU_ARCH_VFP
},
13151 {"armv6z", ARM_ARCH_V6Z
, FPU_ARCH_VFP
},
13152 {"armv6zk", ARM_ARCH_V6ZK
, FPU_ARCH_VFP
},
13153 {"armv6t2", ARM_ARCH_V6T2
, FPU_ARCH_VFP
},
13154 {"armv6kt2", ARM_ARCH_V6KT2
, FPU_ARCH_VFP
},
13155 {"armv6zt2", ARM_ARCH_V6ZT2
, FPU_ARCH_VFP
},
13156 {"armv6zkt2", ARM_ARCH_V6ZKT2
, FPU_ARCH_VFP
},
13157 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP
},
13158 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP
},
13162 /* ISA extensions in the co-processor space. */
13163 struct arm_arch_extension_table
13169 static struct arm_arch_extension_table arm_extensions
[] =
13171 {"maverick", ARM_CEXT_MAVERICK
},
13172 {"xscale", ARM_CEXT_XSCALE
},
13173 {"iwmmxt", ARM_CEXT_IWMMXT
},
13177 struct arm_fpu_option_table
13183 /* This list should, at a minimum, contain all the fpu names
13184 recognized by GCC. */
13185 static struct arm_fpu_option_table arm_fpus
[] =
13187 {"softfpa", FPU_NONE
},
13188 {"fpe", FPU_ARCH_FPE
},
13189 {"fpe2", FPU_ARCH_FPE
},
13190 {"fpe3", FPU_ARCH_FPA
}, /* Third release supports LFM/SFM. */
13191 {"fpa", FPU_ARCH_FPA
},
13192 {"fpa10", FPU_ARCH_FPA
},
13193 {"fpa11", FPU_ARCH_FPA
},
13194 {"arm7500fe", FPU_ARCH_FPA
},
13195 {"softvfp", FPU_ARCH_VFP
},
13196 {"softvfp+vfp", FPU_ARCH_VFP_V2
},
13197 {"vfp", FPU_ARCH_VFP_V2
},
13198 {"vfp9", FPU_ARCH_VFP_V2
},
13199 {"vfp10", FPU_ARCH_VFP_V2
},
13200 {"vfp10-r0", FPU_ARCH_VFP_V1
},
13201 {"vfpxd", FPU_ARCH_VFP_V1xD
},
13202 {"arm1020t", FPU_ARCH_VFP_V1
},
13203 {"arm1020e", FPU_ARCH_VFP_V2
},
13204 {"arm1136jfs", FPU_ARCH_VFP_V2
},
13205 {"arm1136jf-s", FPU_ARCH_VFP_V2
},
13206 {"maverick", FPU_ARCH_MAVERICK
},
13210 struct arm_float_abi_option_table
13216 static struct arm_float_abi_option_table arm_float_abis
[] =
13218 {"hard", ARM_FLOAT_ABI_HARD
},
13219 {"softfp", ARM_FLOAT_ABI_SOFTFP
},
13220 {"soft", ARM_FLOAT_ABI_SOFT
},
13224 struct arm_eabi_option_table
13227 unsigned int value
;
13231 /* We only know how to output GNU and ver 4 (AAELF) formats. */
13232 static struct arm_eabi_option_table arm_eabis
[] =
13234 {"gnu", EF_ARM_EABI_UNKNOWN
},
13235 {"4", EF_ARM_EABI_VER4
},
13240 struct arm_long_option_table
13242 char * option
; /* Substring to match. */
13243 char * help
; /* Help information. */
13244 int (* func
) (char * subopt
); /* Function to decode sub-option. */
13245 char * deprecated
; /* If non-null, print this message. */
13249 arm_parse_extension (char * str
, int * opt_p
)
13251 while (str
!= NULL
&& *str
!= 0)
13253 struct arm_arch_extension_table
* opt
;
13259 as_bad (_("invalid architectural extension"));
13264 ext
= strchr (str
, '+');
13267 optlen
= ext
- str
;
13269 optlen
= strlen (str
);
13273 as_bad (_("missing architectural extension"));
13277 for (opt
= arm_extensions
; opt
->name
!= NULL
; opt
++)
13278 if (strncmp (opt
->name
, str
, optlen
) == 0)
13280 *opt_p
|= opt
->value
;
13284 if (opt
->name
== NULL
)
13286 as_bad (_("unknown architectural extnsion `%s'"), str
);
13297 arm_parse_cpu (char * str
)
13299 struct arm_cpu_option_table
* opt
;
13300 char * ext
= strchr (str
, '+');
13304 optlen
= ext
- str
;
13306 optlen
= strlen (str
);
13310 as_bad (_("missing cpu name `%s'"), str
);
13314 for (opt
= arm_cpus
; opt
->name
!= NULL
; opt
++)
13315 if (strncmp (opt
->name
, str
, optlen
) == 0)
13317 mcpu_cpu_opt
= opt
->value
;
13318 mcpu_fpu_opt
= opt
->default_fpu
;
13321 return arm_parse_extension (ext
, &mcpu_cpu_opt
);
13326 as_bad (_("unknown cpu `%s'"), str
);
13331 arm_parse_arch (char * str
)
13333 struct arm_arch_option_table
*opt
;
13334 char *ext
= strchr (str
, '+');
13338 optlen
= ext
- str
;
13340 optlen
= strlen (str
);
13344 as_bad (_("missing architecture name `%s'"), str
);
13349 for (opt
= arm_archs
; opt
->name
!= NULL
; opt
++)
13350 if (streq (opt
->name
, str
))
13352 march_cpu_opt
= opt
->value
;
13353 march_fpu_opt
= opt
->default_fpu
;
13356 return arm_parse_extension (ext
, &march_cpu_opt
);
13361 as_bad (_("unknown architecture `%s'\n"), str
);
13366 arm_parse_fpu (char * str
)
13368 struct arm_fpu_option_table
* opt
;
13370 for (opt
= arm_fpus
; opt
->name
!= NULL
; opt
++)
13371 if (streq (opt
->name
, str
))
13373 mfpu_opt
= opt
->value
;
13377 as_bad (_("unknown floating point format `%s'\n"), str
);
13382 arm_parse_float_abi (char * str
)
13384 struct arm_float_abi_option_table
* opt
;
13386 for (opt
= arm_float_abis
; opt
->name
!= NULL
; opt
++)
13387 if (streq (opt
->name
, str
))
13389 mfloat_abi_opt
= opt
->value
;
13393 as_bad (_("unknown floating point abi `%s'\n"), str
);
13399 arm_parse_eabi (char * str
)
13401 struct arm_eabi_option_table
*opt
;
13403 for (opt
= arm_eabis
; opt
->name
!= NULL
; opt
++)
13404 if (streq (opt
->name
, str
))
13406 meabi_flags
= opt
->value
;
13409 as_bad (_("unknown EABI `%s'\n"), str
);
13414 struct arm_long_option_table arm_long_opts
[] =
13416 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13417 arm_parse_cpu
, NULL
},
13418 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13419 arm_parse_arch
, NULL
},
13420 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13421 arm_parse_fpu
, NULL
},
13422 {"mfloat-abi=", N_("<abi>\t assemble for floating point ABI <abi>"),
13423 arm_parse_float_abi
, NULL
},
13425 {"meabi=", N_("<ver>\t assemble for eabi version <ver>"),
13426 arm_parse_eabi
, NULL
},
13428 {NULL
, NULL
, 0, NULL
}
13432 md_parse_option (int c
, char * arg
)
13434 struct arm_option_table
*opt
;
13435 struct arm_long_option_table
*lopt
;
13441 target_big_endian
= 1;
13447 target_big_endian
= 0;
13452 /* Listing option. Just ignore these, we don't support additional
13457 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
13459 if (c
== opt
->option
[0]
13460 && ((arg
== NULL
&& opt
->option
[1] == 0)
13461 || streq (arg
, opt
->option
+ 1)))
13463 #if WARN_DEPRECATED
13464 /* If the option is deprecated, tell the user. */
13465 if (opt
->deprecated
!= NULL
)
13466 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
,
13467 arg
? arg
: "", _(opt
->deprecated
));
13470 if (opt
->var
!= NULL
)
13471 *opt
->var
= opt
->value
;
13477 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
13479 /* These options are expected to have an argument. */
13480 if (c
== lopt
->option
[0]
13482 && strncmp (arg
, lopt
->option
+ 1,
13483 strlen (lopt
->option
+ 1)) == 0)
13485 #if WARN_DEPRECATED
13486 /* If the option is deprecated, tell the user. */
13487 if (lopt
->deprecated
!= NULL
)
13488 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
, arg
,
13489 _(lopt
->deprecated
));
13492 /* Call the sup-option parser. */
13493 return lopt
->func (arg
+ strlen (lopt
->option
) - 1);
13504 md_show_usage (FILE * fp
)
13506 struct arm_option_table
*opt
;
13507 struct arm_long_option_table
*lopt
;
13509 fprintf (fp
, _(" ARM-specific assembler options:\n"));
13511 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
13512 if (opt
->help
!= NULL
)
13513 fprintf (fp
, " -%-23s%s\n", opt
->option
, _(opt
->help
));
13515 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
13516 if (lopt
->help
!= NULL
)
13517 fprintf (fp
, " -%s%s\n", lopt
->option
, _(lopt
->help
));
13521 -EB assemble code for a big-endian cpu\n"));
13526 -EL assemble code for a little-endian cpu\n"));
13530 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13533 cons_fix_new_arm (fragS
* frag
,
13538 bfd_reloc_code_real_type type
;
13542 FIXME: @@ Should look at CPU word size. */
13546 type
= BFD_RELOC_8
;
13549 type
= BFD_RELOC_16
;
13553 type
= BFD_RELOC_32
;
13556 type
= BFD_RELOC_64
;
13560 fix_new_exp (frag
, where
, (int) size
, exp
, pcrel
, type
);
13563 /* A good place to do this, although this was probably not intended
13564 for this kind of use. We need to dump the literal pool before
13565 references are made to a null symbol pointer. */
13570 literal_pool
* pool
;
13572 for (pool
= list_of_pools
; pool
; pool
= pool
->next
)
13574 /* Put it at the end of the relevent section. */
13575 subseg_set (pool
->section
, pool
->sub_section
);
13577 arm_elf_change_section ();
13584 arm_start_line_hook (void)
13586 last_label_seen
= NULL
;
13590 arm_frob_label (symbolS
* sym
)
13592 last_label_seen
= sym
;
13594 ARM_SET_THUMB (sym
, thumb_mode
);
13596 #if defined OBJ_COFF || defined OBJ_ELF
13597 ARM_SET_INTERWORK (sym
, support_interwork
);
13600 /* Note - do not allow local symbols (.Lxxx) to be labeled
13601 as Thumb functions. This is because these labels, whilst
13602 they exist inside Thumb code, are not the entry points for
13603 possible ARM->Thumb calls. Also, these labels can be used
13604 as part of a computed goto or switch statement. eg gcc
13605 can generate code that looks like this:
13607 ldr r2, [pc, .Laaa]
13617 The first instruction loads the address of the jump table.
13618 The second instruction converts a table index into a byte offset.
13619 The third instruction gets the jump address out of the table.
13620 The fourth instruction performs the jump.
13622 If the address stored at .Laaa is that of a symbol which has the
13623 Thumb_Func bit set, then the linker will arrange for this address
13624 to have the bottom bit set, which in turn would mean that the
13625 address computation performed by the third instruction would end
13626 up with the bottom bit set. Since the ARM is capable of unaligned
13627 word loads, the instruction would then load the incorrect address
13628 out of the jump table, and chaos would ensue. */
13629 if (label_is_thumb_function_name
13630 && (S_GET_NAME (sym
)[0] != '.' || S_GET_NAME (sym
)[1] != 'L')
13631 && (bfd_get_section_flags (stdoutput
, now_seg
) & SEC_CODE
) != 0)
13633 /* When the address of a Thumb function is taken the bottom
13634 bit of that address should be set. This will allow
13635 interworking between Arm and Thumb functions to work
13638 THUMB_SET_FUNC (sym
, 1);
13640 label_is_thumb_function_name
= FALSE
;
13644 /* Adjust the symbol table. This marks Thumb symbols as distinct from
13648 arm_adjust_symtab (void)
13653 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
13655 if (ARM_IS_THUMB (sym
))
13657 if (THUMB_IS_FUNC (sym
))
13659 /* Mark the symbol as a Thumb function. */
13660 if ( S_GET_STORAGE_CLASS (sym
) == C_STAT
13661 || S_GET_STORAGE_CLASS (sym
) == C_LABEL
) /* This can happen! */
13662 S_SET_STORAGE_CLASS (sym
, C_THUMBSTATFUNC
);
13664 else if (S_GET_STORAGE_CLASS (sym
) == C_EXT
)
13665 S_SET_STORAGE_CLASS (sym
, C_THUMBEXTFUNC
);
13667 as_bad (_("%s: unexpected function type: %d"),
13668 S_GET_NAME (sym
), S_GET_STORAGE_CLASS (sym
));
13670 else switch (S_GET_STORAGE_CLASS (sym
))
13673 S_SET_STORAGE_CLASS (sym
, C_THUMBEXT
);
13676 S_SET_STORAGE_CLASS (sym
, C_THUMBSTAT
);
13679 S_SET_STORAGE_CLASS (sym
, C_THUMBLABEL
);
13687 if (ARM_IS_INTERWORK (sym
))
13688 coffsymbol (symbol_get_bfdsym (sym
))->native
->u
.syment
.n_flags
= 0xFF;
13695 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
13697 if (ARM_IS_THUMB (sym
))
13699 elf_symbol_type
* elf_sym
;
13701 elf_sym
= elf_symbol (symbol_get_bfdsym (sym
));
13702 bind
= ELF_ST_BIND (elf_sym
);
13704 /* If it's a .thumb_func, declare it as so,
13705 otherwise tag label as .code 16. */
13706 if (THUMB_IS_FUNC (sym
))
13707 elf_sym
->internal_elf_sym
.st_info
=
13708 ELF_ST_INFO (bind
, STT_ARM_TFUNC
);
13710 elf_sym
->internal_elf_sym
.st_info
=
13711 ELF_ST_INFO (bind
, STT_ARM_16BIT
);
13718 arm_data_in_code (void)
13720 if (thumb_mode
&& ! strncmp (input_line_pointer
+ 1, "data:", 5))
13722 *input_line_pointer
= '/';
13723 input_line_pointer
+= 5;
13724 *input_line_pointer
= 0;
13732 arm_canonicalize_symbol_name (char * name
)
13736 if (thumb_mode
&& (len
= strlen (name
)) > 5
13737 && streq (name
+ len
- 5, "/data"))
13738 *(name
+ len
- 5) = 0;
13743 #if defined OBJ_COFF || defined OBJ_ELF
13745 arm_validate_fix (fixS
* fixP
)
13747 /* If the destination of the branch is a defined symbol which does not have
13748 the THUMB_FUNC attribute, then we must be calling a function which has
13749 the (interfacearm) attribute. We look for the Thumb entry point to that
13750 function and change the branch to refer to that function instead. */
13751 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
13752 && fixP
->fx_addsy
!= NULL
13753 && S_IS_DEFINED (fixP
->fx_addsy
)
13754 && ! THUMB_IS_FUNC (fixP
->fx_addsy
))
13756 fixP
->fx_addsy
= find_real_start (fixP
->fx_addsy
);
13762 arm_force_relocation (struct fix
* fixp
)
13764 #if defined (OBJ_COFF) && defined (TE_PE)
13765 if (fixp
->fx_r_type
== BFD_RELOC_RVA
)
13769 if (fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
13770 || fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
13771 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
13772 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
)
13776 /* Resolve these relocations even if the symbol is extern or weak. */
13777 if (fixp
->fx_r_type
== BFD_RELOC_ARM_IMMEDIATE
13778 || fixp
->fx_r_type
== BFD_RELOC_ARM_OFFSET_IMM
13779 || fixp
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
13782 return generic_force_reloc (fixp
);
13786 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
13787 local labels from being added to the output symbol table when they
13788 are used with the ADRL pseudo op. The ADRL relocation should always
13789 be resolved before the binbary is emitted, so it is safe to say that
13790 it is adjustable. */
13793 arm_fix_adjustable (fixS
* fixP
)
13795 if (fixP
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
13802 /* Relocations against Thumb function names must be left unadjusted,
13803 so that the linker can use this information to correctly set the
13804 bottom bit of their addresses. The MIPS version of this function
13805 also prevents relocations that are mips-16 specific, but I do not
13806 know why it does this.
13809 There is one other problem that ought to be addressed here, but
13810 which currently is not: Taking the address of a label (rather
13811 than a function) and then later jumping to that address. Such
13812 addresses also ought to have their bottom bit set (assuming that
13813 they reside in Thumb code), but at the moment they will not. */
13816 arm_fix_adjustable (fixS
* fixP
)
13818 if (fixP
->fx_addsy
== NULL
)
13821 if (THUMB_IS_FUNC (fixP
->fx_addsy
)
13822 && fixP
->fx_subsy
== NULL
)
13825 /* We need the symbol name for the VTABLE entries. */
13826 if ( fixP
->fx_r_type
== BFD_RELOC_VTABLE_INHERIT
13827 || fixP
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
13830 /* Don't allow symbols to be discarded on GOT related relocs. */
13831 if (fixP
->fx_r_type
== BFD_RELOC_ARM_PLT32
13832 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOT32
13833 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOTOFF
13834 || fixP
->fx_r_type
== BFD_RELOC_ARM_TARGET2
)
13841 elf32_arm_target_format (void)
13844 return (target_big_endian
13845 ? "elf32-bigarm-symbian"
13846 : "elf32-littlearm-symbian");
13847 #elif defined (TE_VXWORKS)
13848 return (target_big_endian
13849 ? "elf32-bigarm-vxworks"
13850 : "elf32-littlearm-vxworks");
13852 if (target_big_endian
)
13853 return "elf32-bigarm";
13855 return "elf32-littlearm";
13860 armelf_frob_symbol (symbolS
* symp
,
13863 elf_frob_symbol (symp
, puntp
);
13867 s_arm_elf_cons (int nbytes
)
13871 #ifdef md_flush_pending_output
13872 md_flush_pending_output ();
13875 if (is_it_end_of_statement ())
13877 demand_empty_rest_of_line ();
13881 #ifdef md_cons_align
13882 md_cons_align (nbytes
);
13885 mapping_state (MAP_DATA
);
13888 bfd_reloc_code_real_type reloc
;
13890 expression (& exp
);
13892 if (exp
.X_op
== O_symbol
13893 && * input_line_pointer
== '('
13894 && (reloc
= arm_parse_reloc ()) != BFD_RELOC_UNUSED
)
13896 reloc_howto_type
*howto
= bfd_reloc_type_lookup (stdoutput
, reloc
);
13897 int size
= bfd_get_reloc_size (howto
);
13900 as_bad ("%s relocations do not fit in %d bytes",
13901 howto
->name
, nbytes
);
13904 char *p
= frag_more ((int) nbytes
);
13905 int offset
= nbytes
- size
;
13907 fix_new_exp (frag_now
, p
- frag_now
->fr_literal
+ offset
, size
,
13912 emit_expr (&exp
, (unsigned int) nbytes
);
13914 while (*input_line_pointer
++ == ',');
13916 /* Put terminator back into stream. */
13917 input_line_pointer
--;
13918 demand_empty_rest_of_line ();
13922 /* Parse a .rel31 directive. */
13925 s_arm_rel31 (int ignored ATTRIBUTE_UNUSED
)
13931 SKIP_WHITESPACE ();
13934 if (*input_line_pointer
== '1')
13935 highbit
= 0x80000000;
13936 else if (*input_line_pointer
!= '0')
13937 as_bad (_("expected 0 or 1"));
13939 input_line_pointer
++;
13940 SKIP_WHITESPACE ();
13941 if (*input_line_pointer
!= ',')
13942 as_bad (_("missing comma"));
13943 input_line_pointer
++;
13945 #ifdef md_flush_pending_output
13946 md_flush_pending_output ();
13949 #ifdef md_cons_align
13953 mapping_state (MAP_DATA
);
13958 md_number_to_chars (p
, highbit
, 4);
13959 fix_new_arm (frag_now
, p
- frag_now
->fr_literal
, 4, &exp
, 1,
13960 BFD_RELOC_ARM_PREL31
);
13962 demand_empty_rest_of_line ();
13965 /* Code to deal with unwinding tables. */
13967 static void add_unwind_adjustsp (offsetT
);
13969 /* Switch to section NAME and create section if necessary. It's
13970 rather ugly that we have to manipulate input_line_pointer but I
13971 don't see any other way to accomplish the same thing without
13972 changing obj-elf.c (which may be the Right Thing, in the end).
13973 Copied from tc-ia64.c. */
13976 set_section (char *name
)
13978 char *saved_input_line_pointer
;
13980 saved_input_line_pointer
= input_line_pointer
;
13981 input_line_pointer
= name
;
13982 obj_elf_section (0);
13983 input_line_pointer
= saved_input_line_pointer
;
13986 /* Cenerate and deferred unwind frame offset. */
13989 flush_pending_unwind (void)
13993 offset
= unwind
.pending_offset
;
13994 unwind
.pending_offset
= 0;
13996 add_unwind_adjustsp (offset
);
13999 /* Add an opcode to this list for this function. Two-byte opcodes should
14000 be passed as op[0] << 8 | op[1]. The list of opcodes is built in reverse
14004 add_unwind_opcode (valueT op
, int length
)
14006 /* Add any deferred stack adjustment. */
14007 if (unwind
.pending_offset
)
14008 flush_pending_unwind ();
14010 unwind
.sp_restored
= 0;
14012 if (unwind
.opcode_count
+ length
> unwind
.opcode_alloc
)
14014 unwind
.opcode_alloc
+= ARM_OPCODE_CHUNK_SIZE
;
14015 if (unwind
.opcodes
)
14016 unwind
.opcodes
= xrealloc (unwind
.opcodes
,
14017 unwind
.opcode_alloc
);
14019 unwind
.opcodes
= xmalloc (unwind
.opcode_alloc
);
14024 unwind
.opcodes
[unwind
.opcode_count
] = op
& 0xff;
14026 unwind
.opcode_count
++;
14030 /* Add unwind opcodes to adjust the stack pointer. */
14033 add_unwind_adjustsp (offsetT offset
)
14037 if (offset
> 0x200)
14039 /* We need at most 5 bytes to hold a 32-bit value in a uleb128. */
14044 /* Long form: 0xb2, uleb128. */
14045 /* This might not fit in a word so add the individual bytes,
14046 remembering the list is built in reverse order. */
14047 o
= (valueT
) ((offset
- 0x204) >> 2);
14049 add_unwind_opcode (0, 1);
14051 /* Calculate the uleb128 encoding of the offset. */
14055 bytes
[n
] = o
& 0x7f;
14061 /* Add the insn. */
14063 add_unwind_opcode (bytes
[n
- 1], 1);
14064 add_unwind_opcode (0xb2, 1);
14066 else if (offset
> 0x100)
14068 /* Two short opcodes. */
14069 add_unwind_opcode (0x3f, 1);
14070 op
= (offset
- 0x104) >> 2;
14071 add_unwind_opcode (op
, 1);
14073 else if (offset
> 0)
14075 /* Short opcode. */
14076 op
= (offset
- 4) >> 2;
14077 add_unwind_opcode (op
, 1);
14079 else if (offset
< 0)
14082 while (offset
> 0x100)
14084 add_unwind_opcode (0x7f, 1);
14087 op
= ((offset
- 4) >> 2) | 0x40;
14088 add_unwind_opcode (op
, 1);
14092 /* Finish the list of unwind opcodes for this function. */
14094 finish_unwind_opcodes (void)
14098 if (unwind
.fp_used
)
14100 /* Adjust sp as neccessary. */
14101 unwind
.pending_offset
+= unwind
.fp_offset
- unwind
.frame_size
;
14102 flush_pending_unwind ();
14104 /* After restoring sp from the frame pointer. */
14105 op
= 0x90 | unwind
.fp_reg
;
14106 add_unwind_opcode (op
, 1);
14109 flush_pending_unwind ();
14113 /* Start an exception table entry. If idx is nonzero this is an index table
14117 start_unwind_section (const segT text_seg
, int idx
)
14119 const char * text_name
;
14120 const char * prefix
;
14121 const char * prefix_once
;
14125 size_t sec_name_len
;
14129 prefix
= ELF_STRING_ARM_unwind
;
14130 prefix_once
= ELF_STRING_ARM_unwind_once
;
14134 prefix
= ELF_STRING_ARM_unwind_info
;
14135 prefix_once
= ELF_STRING_ARM_unwind_info_once
;
14138 text_name
= segment_name (text_seg
);
14139 if (streq (text_name
, ".text"))
14142 if (strncmp (text_name
, ".gnu.linkonce.t.",
14143 strlen (".gnu.linkonce.t.")) == 0)
14145 prefix
= prefix_once
;
14146 text_name
+= strlen (".gnu.linkonce.t.");
14149 prefix_len
= strlen (prefix
);
14150 text_len
= strlen (text_name
);
14151 sec_name_len
= prefix_len
+ text_len
;
14152 sec_name
= alloca (sec_name_len
+ 1);
14153 memcpy (sec_name
, prefix
, prefix_len
);
14154 memcpy (sec_name
+ prefix_len
, text_name
, text_len
);
14155 sec_name
[prefix_len
+ text_len
] = '\0';
14157 /* Handle COMDAT group. */
14158 if (prefix
!= prefix_once
&& (text_seg
->flags
& SEC_LINK_ONCE
) != 0)
14161 size_t len
, group_name_len
;
14162 const char *group_name
= elf_group_name (text_seg
);
14164 if (group_name
== NULL
)
14166 as_bad ("Group section `%s' has no group signature",
14167 segment_name (text_seg
));
14168 ignore_rest_of_line ();
14171 /* We have to construct a fake section directive. */
14172 group_name_len
= strlen (group_name
);
14178 len
= (sec_name_len
14179 + prefix_len
/* ,"aG",%sectiontype, */
14180 + group_name_len
/* ,group_name */
14181 + 7); /* ,comdat */
14183 section
= alloca (len
+ 1);
14184 memcpy (section
, sec_name
, sec_name_len
);
14186 memcpy (section
+ sec_name_len
, ",\"aG\",%exidx,", 13);
14188 memcpy (section
+ sec_name_len
, ",\"aG\",%progbits,", 16);
14189 memcpy (section
+ sec_name_len
+ prefix_len
, group_name
, group_name_len
);
14190 memcpy (section
+ len
- 7, ",comdat", 7);
14191 section
[len
] = '\0';
14192 set_section (section
);
14196 set_section (sec_name
);
14197 bfd_set_section_flags (stdoutput
, now_seg
,
14198 SEC_LOAD
| SEC_ALLOC
| SEC_READONLY
);
14201 /* Set the setion link for index tables. */
14203 elf_linked_to_section (now_seg
) = text_seg
;
14207 /* Start an unwind table entry. HAVE_DATA is nonzero if we have additional
14208 personality routine data. Returns zero, or the index table value for
14209 and inline entry. */
14212 create_unwind_entry (int have_data
)
14217 /* The current word of data. */
14219 /* The number of bytes left in this word. */
14222 finish_unwind_opcodes ();
14224 /* Remember the current text section. */
14225 unwind
.saved_seg
= now_seg
;
14226 unwind
.saved_subseg
= now_subseg
;
14228 start_unwind_section (now_seg
, 0);
14230 if (unwind
.personality_routine
== NULL
)
14232 if (unwind
.personality_index
== -2)
14235 as_bad (_("handerdata in cantunwind frame"));
14236 return 1; /* EXIDX_CANTUNWIND. */
14239 /* Use a default personality routine if none is specified. */
14240 if (unwind
.personality_index
== -1)
14242 if (unwind
.opcode_count
> 3)
14243 unwind
.personality_index
= 1;
14245 unwind
.personality_index
= 0;
14248 /* Space for the personality routine entry. */
14249 if (unwind
.personality_index
== 0)
14251 if (unwind
.opcode_count
> 3)
14252 as_bad (_("too many unwind opcodes for personality routine 0"));
14256 /* All the data is inline in the index table. */
14259 while (unwind
.opcode_count
> 0)
14261 unwind
.opcode_count
--;
14262 data
= (data
<< 8) | unwind
.opcodes
[unwind
.opcode_count
];
14266 /* Pad with "finish" opcodes. */
14268 data
= (data
<< 8) | 0xb0;
14275 /* We get two opcodes "free" in the first word. */
14276 size
= unwind
.opcode_count
- 2;
14279 /* An extra byte is required for the opcode count. */
14280 size
= unwind
.opcode_count
+ 1;
14282 size
= (size
+ 3) >> 2;
14284 as_bad (_("too many unwind opcodes"));
14286 frag_align (2, 0, 0);
14287 record_alignment (now_seg
, 2);
14288 unwind
.table_entry
= expr_build_dot ();
14290 /* Allocate the table entry. */
14291 ptr
= frag_more ((size
<< 2) + 4);
14292 where
= frag_now_fix () - ((size
<< 2) + 4);
14294 switch (unwind
.personality_index
)
14297 /* ??? Should this be a PLT generating relocation? */
14298 /* Custom personality routine. */
14299 fix_new (frag_now
, where
, 4, unwind
.personality_routine
, 0, 1,
14300 BFD_RELOC_ARM_PREL31
);
14302 /* Indicate dependency to linker. */
14304 char *name
= "__aeabi_unwind_cpp_pr0";
14305 symbolS
*pr
= symbol_find_or_make (name
);
14306 fix_new (frag_now
, where
, 4, pr
, 0, 1, BFD_RELOC_NONE
);
14312 /* Set the first byte to the number of additional words. */
14317 /* ABI defined personality routines. */
14319 /* Three opcodes bytes are packed into the first word. */
14326 /* The size and first two opcode bytes go in the first word. */
14327 data
= ((0x80 + unwind
.personality_index
) << 8) | size
;
14333 /* Indicate dependency to linker. */
14334 char *name
[] = { "__aeabi_unwind_cpp_pr0",
14335 "__aeabi_unwind_cpp_pr1",
14336 "__aeabi_unwind_cpp_pr2" };
14337 symbolS
*pr
= symbol_find_or_make (name
[unwind
.personality_index
]);
14338 fix_new (frag_now
, where
, 4, pr
, 0, 1, BFD_RELOC_NONE
);
14343 /* Should never happen. */
14347 /* Pack the opcodes into words (MSB first), reversing the list at the same
14349 while (unwind
.opcode_count
> 0)
14353 md_number_to_chars (ptr
, data
, 4);
14358 unwind
.opcode_count
--;
14360 data
= (data
<< 8) | unwind
.opcodes
[unwind
.opcode_count
];
14363 /* Finish off the last word. */
14366 /* Pad with "finish" opcodes. */
14368 data
= (data
<< 8) | 0xb0;
14370 md_number_to_chars (ptr
, data
, 4);
14375 /* Add an empty descriptor if there is no user-specified data. */
14376 ptr
= frag_more (4);
14377 md_number_to_chars (ptr
, 0, 4);
14384 /* Parse an unwind_fnstart directive. Simply records the current location. */
14387 s_arm_unwind_fnstart (int ignored ATTRIBUTE_UNUSED
)
14389 demand_empty_rest_of_line ();
14390 /* Mark the start of the function. */
14391 unwind
.proc_start
= expr_build_dot ();
14393 /* Reset the rest of the unwind info. */
14394 unwind
.opcode_count
= 0;
14395 unwind
.table_entry
= NULL
;
14396 unwind
.personality_routine
= NULL
;
14397 unwind
.personality_index
= -1;
14398 unwind
.frame_size
= 0;
14399 unwind
.fp_offset
= 0;
14400 unwind
.fp_reg
= 13;
14401 unwind
.fp_used
= 0;
14402 unwind
.sp_restored
= 0;
14406 /* Parse a handlerdata directive. Creates the exception handling table entry
14407 for the function. */
14410 s_arm_unwind_handlerdata (int ignored ATTRIBUTE_UNUSED
)
14412 demand_empty_rest_of_line ();
14413 if (unwind
.table_entry
)
14414 as_bad (_("dupicate .handlerdata directive"));
14416 create_unwind_entry (1);
14419 /* Parse an unwind_fnend directive. Generates the index table entry. */
14422 s_arm_unwind_fnend (int ignored ATTRIBUTE_UNUSED
)
14428 demand_empty_rest_of_line ();
14430 /* Add eh table entry. */
14431 if (unwind
.table_entry
== NULL
)
14432 val
= create_unwind_entry (0);
14436 /* Add index table entry. This is two words. */
14437 start_unwind_section (unwind
.saved_seg
, 1);
14438 frag_align (2, 0, 0);
14439 record_alignment (now_seg
, 2);
14441 ptr
= frag_more (8);
14442 where
= frag_now_fix () - 8;
14444 /* Self relative offset of the function start. */
14445 fix_new (frag_now
, where
, 4, unwind
.proc_start
, 0, 1,
14446 BFD_RELOC_ARM_PREL31
);
14449 /* Inline exception table entry. */
14450 md_number_to_chars (ptr
+ 4, val
, 4);
14452 /* Self relative offset of the table entry. */
14453 fix_new (frag_now
, where
+ 4, 4, unwind
.table_entry
, 0, 1,
14454 BFD_RELOC_ARM_PREL31
);
14456 /* Restore the original section. */
14457 subseg_set (unwind
.saved_seg
, unwind
.saved_subseg
);
14461 /* Parse an unwind_cantunwind directive. */
14464 s_arm_unwind_cantunwind (int ignored ATTRIBUTE_UNUSED
)
14466 demand_empty_rest_of_line ();
14467 if (unwind
.personality_routine
|| unwind
.personality_index
!= -1)
14468 as_bad (_("personality routine specified for cantunwind frame"));
14470 unwind
.personality_index
= -2;
14474 /* Parse a personalityindex directive. */
14477 s_arm_unwind_personalityindex (int ignored ATTRIBUTE_UNUSED
)
14481 if (unwind
.personality_routine
|| unwind
.personality_index
!= -1)
14482 as_bad (_("duplicate .personalityindex directive"));
14484 SKIP_WHITESPACE ();
14488 if (exp
.X_op
!= O_constant
14489 || exp
.X_add_number
< 0 || exp
.X_add_number
> 15)
14491 as_bad (_("bad personality routine number"));
14492 ignore_rest_of_line ();
14496 unwind
.personality_index
= exp
.X_add_number
;
14498 demand_empty_rest_of_line ();
14502 /* Parse a personality directive. */
14505 s_arm_unwind_personality (int ignored ATTRIBUTE_UNUSED
)
14509 if (unwind
.personality_routine
|| unwind
.personality_index
!= -1)
14510 as_bad (_("duplicate .personality directive"));
14512 SKIP_WHITESPACE ();
14513 name
= input_line_pointer
;
14514 c
= get_symbol_end ();
14515 p
= input_line_pointer
;
14516 unwind
.personality_routine
= symbol_find_or_make (name
);
14518 SKIP_WHITESPACE ();
14519 demand_empty_rest_of_line ();
14523 /* Parse a directive saving core registers. */
14526 s_arm_unwind_save_core (void)
14532 SKIP_WHITESPACE ();
14533 range
= reg_list (&input_line_pointer
);
14536 as_bad (_("expected register list"));
14537 ignore_rest_of_line ();
14541 demand_empty_rest_of_line ();
14543 /* Turn .unwind_movsp ip followed by .unwind_save {..., ip, ...}
14544 into .unwind_save {..., sp...}. We aren't bothered about the value of
14545 ip because it is clobbered by calls. */
14546 if (unwind
.sp_restored
&& unwind
.fp_reg
== 12
14547 && (range
& 0x3000) == 0x1000)
14549 unwind
.opcode_count
--;
14550 unwind
.sp_restored
= 0;
14551 range
= (range
| 0x2000) & ~0x1000;
14552 unwind
.pending_offset
= 0;
14555 /* See if we can use the short opcodes. These pop a block of upto 8
14556 registers starting with r4, plus maybe r14. */
14557 for (n
= 0; n
< 8; n
++)
14559 /* Break at the first non-saved register. */
14560 if ((range
& (1 << (n
+ 4))) == 0)
14563 /* See if there are any other bits set. */
14564 if (n
== 0 || (range
& (0xfff0 << n
) & 0xbff0) != 0)
14566 /* Use the long form. */
14567 op
= 0x8000 | ((range
>> 4) & 0xfff);
14568 add_unwind_opcode (op
, 2);
14572 /* Use the short form. */
14573 if (range
& 0x4000)
14574 op
= 0xa8; /* Pop r14. */
14576 op
= 0xa0; /* Do not pop r14. */
14578 add_unwind_opcode (op
, 1);
14584 op
= 0xb100 | (range
& 0xf);
14585 add_unwind_opcode (op
, 2);
14588 /* Record the number of bytes pushed. */
14589 for (n
= 0; n
< 16; n
++)
14591 if (range
& (1 << n
))
14592 unwind
.frame_size
+= 4;
14597 /* Parse a directive saving FPA registers. */
14600 s_arm_unwind_save_fpa (int reg
)
14606 /* Get Number of registers to transfer. */
14607 if (skip_past_comma (&input_line_pointer
) != FAIL
)
14610 exp
.X_op
= O_illegal
;
14612 if (exp
.X_op
!= O_constant
)
14614 as_bad (_("expected , <constant>"));
14615 ignore_rest_of_line ();
14619 num_regs
= exp
.X_add_number
;
14621 if (num_regs
< 1 || num_regs
> 4)
14623 as_bad (_("number of registers must be in the range [1:4]"));
14624 ignore_rest_of_line ();
14628 demand_empty_rest_of_line ();
14633 op
= 0xb4 | (num_regs
- 1);
14634 add_unwind_opcode (op
, 1);
14639 op
= 0xc800 | (reg
<< 4) | (num_regs
- 1);
14640 add_unwind_opcode (op
, 2);
14642 unwind
.frame_size
+= num_regs
* 12;
14646 /* Parse a directive saving VFP registers. */
14649 s_arm_unwind_save_vfp (void)
14655 count
= vfp_parse_reg_list (&input_line_pointer
, ®
, 1);
14658 as_bad (_("expected register list"));
14659 ignore_rest_of_line ();
14663 demand_empty_rest_of_line ();
14668 op
= 0xb8 | (count
- 1);
14669 add_unwind_opcode (op
, 1);
14674 op
= 0xb300 | (reg
<< 4) | (count
- 1);
14675 add_unwind_opcode (op
, 2);
14677 unwind
.frame_size
+= count
* 8 + 4;
14681 /* Parse a directive saving iWMMXt registers. */
14684 s_arm_unwind_save_wmmx (void)
14693 if (*input_line_pointer
== '{')
14694 input_line_pointer
++;
14700 reg
= arm_reg_parse (&input_line_pointer
,
14701 all_reg_maps
[REG_TYPE_IWMMXT
].htab
);
14703 if (wr_register (reg
))
14705 i
= reg
& ~WR_PREFIX
;
14707 as_tsktsk (_("register list not in ascending order"));
14710 else if (wcg_register (reg
))
14712 i
= (reg
& ~WC_PREFIX
) - 8;
14714 as_tsktsk (_("register list not in ascending order"));
14715 wcg_mask
|= 1 << i
;
14719 as_bad (_("expected wr or wcgr"));
14723 SKIP_WHITESPACE ();
14724 if (*input_line_pointer
== '-')
14726 hi_reg
= arm_reg_parse (&input_line_pointer
,
14727 all_reg_maps
[REG_TYPE_IWMMXT
].htab
);
14728 if (wr_register (reg
) && wr_register (hi_reg
))
14730 for (; reg
< hi_reg
; reg
++)
14731 wr_mask
|= 1 << (reg
& ~WR_PREFIX
);
14733 else if (wcg_register (reg
) && wcg_register (hi_reg
))
14735 for (; reg
< hi_reg
; reg
++)
14736 wcg_mask
|= 1 << ((reg
& ~WC_PREFIX
) - 8);
14740 as_bad (_("bad register range"));
14745 while (skip_past_comma (&input_line_pointer
) != FAIL
);
14747 SKIP_WHITESPACE ();
14748 if (*input_line_pointer
== '}')
14749 input_line_pointer
++;
14751 demand_empty_rest_of_line ();
14753 if (wr_mask
&& wcg_mask
)
14755 as_bad (_("inconsistent register types"));
14759 /* Generate any deferred opcodes becuuse we're going to be looking at
14761 flush_pending_unwind ();
14765 for (i
= 0; i
< 16; i
++)
14767 if (wcg_mask
& (1 << i
))
14768 unwind
.frame_size
+= 4;
14770 op
= 0xc700 | wcg_mask
;
14771 add_unwind_opcode (op
, 2);
14775 for (i
= 0; i
< 16; i
++)
14777 if (wr_mask
& (1 << i
))
14778 unwind
.frame_size
+= 8;
14780 /* Attempt to combine with a previous opcode. We do this because gcc
14781 likes to output separate unwind directives for a single block of
14783 if (unwind
.opcode_count
> 0)
14785 i
= unwind
.opcodes
[unwind
.opcode_count
- 1];
14786 if ((i
& 0xf8) == 0xc0)
14789 /* Only merge if the blocks are contiguous. */
14792 if ((wr_mask
& 0xfe00) == (1 << 9))
14794 wr_mask
|= ((1 << (i
+ 11)) - 1) & 0xfc00;
14795 unwind
.opcode_count
--;
14798 else if (i
== 6 && unwind
.opcode_count
>= 2)
14800 i
= unwind
.opcodes
[unwind
.opcode_count
- 2];
14804 op
= 0xffff << (reg
- 1);
14806 || ((wr_mask
& op
) == (1u << (reg
- 1))))
14808 op
= (1 << (reg
+ i
+ 1)) - 1;
14809 op
&= ~((1 << reg
) - 1);
14811 unwind
.opcode_count
-= 2;
14818 /* We want to generate opcodes in the order the registers have been
14819 saved, ie. descending order. */
14820 for (reg
= 15; reg
>= -1; reg
--)
14822 /* Save registers in blocks. */
14824 || !(wr_mask
& (1 << reg
)))
14826 /* We found an unsaved reg. Generate opcodes to save the
14827 preceeding block. */
14833 op
= 0xc0 | (hi_reg
- 10);
14834 add_unwind_opcode (op
, 1);
14839 op
= 0xc600 | ((reg
+ 1) << 4) | ((hi_reg
- reg
) - 1);
14840 add_unwind_opcode (op
, 2);
14849 ignore_rest_of_line ();
14853 /* Parse an unwind_save directive. */
14856 s_arm_unwind_save (int ignored ATTRIBUTE_UNUSED
)
14861 /* Figure out what sort of save we have. */
14862 SKIP_WHITESPACE ();
14863 saved_ptr
= input_line_pointer
;
14865 reg
= arm_reg_parse (&input_line_pointer
, all_reg_maps
[REG_TYPE_FN
].htab
);
14868 s_arm_unwind_save_fpa (reg
);
14872 if (*input_line_pointer
== '{')
14873 input_line_pointer
++;
14875 SKIP_WHITESPACE ();
14877 reg
= arm_reg_parse (&input_line_pointer
, all_reg_maps
[REG_TYPE_RN
].htab
);
14880 input_line_pointer
= saved_ptr
;
14881 s_arm_unwind_save_core ();
14885 reg
= arm_reg_parse (&input_line_pointer
, all_reg_maps
[REG_TYPE_DN
].htab
);
14888 input_line_pointer
= saved_ptr
;
14889 s_arm_unwind_save_vfp ();
14893 reg
= arm_reg_parse (&input_line_pointer
,
14894 all_reg_maps
[REG_TYPE_IWMMXT
].htab
);
14897 input_line_pointer
= saved_ptr
;
14898 s_arm_unwind_save_wmmx ();
14902 /* TODO: Maverick registers. */
14903 as_bad (_("unrecognised register"));
14907 /* Parse an unwind_movsp directive. */
14910 s_arm_unwind_movsp (int ignored ATTRIBUTE_UNUSED
)
14915 SKIP_WHITESPACE ();
14916 reg
= reg_required_here (&input_line_pointer
, -1);
14919 as_bad (_("ARM register expected"));
14920 ignore_rest_of_line ();
14924 if (reg
== 13 || reg
== 15)
14926 as_bad (_("r%d not permitted in .unwind_movsp directive"), reg
);
14927 ignore_rest_of_line ();
14931 if (unwind
.fp_reg
!= 13)
14932 as_bad (_("unexpected .unwind_movsp directive"));
14934 /* Generate opcode to restore the value. */
14936 add_unwind_opcode (op
, 1);
14938 /* Record the information for later. */
14939 unwind
.fp_reg
= reg
;
14940 unwind
.fp_offset
= unwind
.frame_size
;
14941 unwind
.sp_restored
= 1;
14942 demand_empty_rest_of_line ();
14946 /* Parse #<number>. */
14949 require_hashconst (int * val
)
14953 SKIP_WHITESPACE ();
14954 if (*input_line_pointer
== '#')
14956 input_line_pointer
++;
14960 exp
.X_op
= O_illegal
;
14962 if (exp
.X_op
!= O_constant
)
14964 as_bad (_("expected #constant"));
14965 ignore_rest_of_line ();
14968 *val
= exp
.X_add_number
;
14972 /* Parse an unwind_pad directive. */
14975 s_arm_unwind_pad (int ignored ATTRIBUTE_UNUSED
)
14979 if (require_hashconst (&offset
) == FAIL
)
14984 as_bad (_("stack increment must be multiple of 4"));
14985 ignore_rest_of_line ();
14989 /* Don't generate any opcodes, just record the details for later. */
14990 unwind
.frame_size
+= offset
;
14991 unwind
.pending_offset
+= offset
;
14993 demand_empty_rest_of_line ();
14996 /* Parse an unwind_setfp directive. */
14999 s_arm_unwind_setfp (int ignored ATTRIBUTE_UNUSED
)
15005 fp_reg
= reg_required_here (&input_line_pointer
, -1);
15006 if (skip_past_comma (&input_line_pointer
) == FAIL
)
15009 sp_reg
= reg_required_here (&input_line_pointer
, -1);
15011 if (fp_reg
== FAIL
|| sp_reg
== FAIL
)
15013 as_bad (_("expected <reg>, <reg>"));
15014 ignore_rest_of_line ();
15018 /* Optonal constant. */
15019 if (skip_past_comma (&input_line_pointer
) != FAIL
)
15021 if (require_hashconst (&offset
) == FAIL
)
15027 demand_empty_rest_of_line ();
15029 if (sp_reg
!= 13 && sp_reg
!= unwind
.fp_reg
)
15031 as_bad (_("register must be either sp or set by a previous"
15032 "unwind_movsp directive"));
15036 /* Don't generate any opcodes, just record the information for later. */
15037 unwind
.fp_reg
= fp_reg
;
15038 unwind
.fp_used
= 1;
15040 unwind
.fp_offset
= unwind
.frame_size
- offset
;
15042 unwind
.fp_offset
-= offset
;
15045 /* Parse an unwind_raw directive. */
15048 s_arm_unwind_raw (int ignored ATTRIBUTE_UNUSED
)
15051 /* This is an arbitary limit. */
15052 unsigned char op
[16];
15055 SKIP_WHITESPACE ();
15057 if (exp
.X_op
== O_constant
15058 && skip_past_comma (&input_line_pointer
) != FAIL
)
15060 unwind
.frame_size
+= exp
.X_add_number
;
15064 exp
.X_op
= O_illegal
;
15066 if (exp
.X_op
!= O_constant
)
15068 as_bad (_("expected <offset>, <opcode>"));
15069 ignore_rest_of_line ();
15075 /* Parse the opcode. */
15080 as_bad (_("unwind opcode too long"));
15081 ignore_rest_of_line ();
15083 if (exp
.X_op
!= O_constant
|| exp
.X_add_number
& ~0xff)
15085 as_bad (_("invalid unwind opcode"));
15086 ignore_rest_of_line ();
15089 op
[count
++] = exp
.X_add_number
;
15091 /* Parse the next byte. */
15092 if (skip_past_comma (&input_line_pointer
) == FAIL
)
15098 /* Add the opcode bytes in reverse order. */
15100 add_unwind_opcode (op
[count
], 1);
15102 demand_empty_rest_of_line ();
15105 #endif /* OBJ_ELF */
15107 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
15108 of an rs_align_code fragment. */
15111 arm_handle_align (fragS
* fragP
)
15113 static char const arm_noop
[4] = { 0x00, 0x00, 0xa0, 0xe1 };
15114 static char const thumb_noop
[2] = { 0xc0, 0x46 };
15115 static char const arm_bigend_noop
[4] = { 0xe1, 0xa0, 0x00, 0x00 };
15116 static char const thumb_bigend_noop
[2] = { 0x46, 0xc0 };
15118 int bytes
, fix
, noop_size
;
15122 if (fragP
->fr_type
!= rs_align_code
)
15125 bytes
= fragP
->fr_next
->fr_address
- fragP
->fr_address
- fragP
->fr_fix
;
15126 p
= fragP
->fr_literal
+ fragP
->fr_fix
;
15129 if (bytes
> MAX_MEM_FOR_RS_ALIGN_CODE
)
15130 bytes
&= MAX_MEM_FOR_RS_ALIGN_CODE
;
15132 if (fragP
->tc_frag_data
)
15134 if (target_big_endian
)
15135 noop
= thumb_bigend_noop
;
15138 noop_size
= sizeof (thumb_noop
);
15142 if (target_big_endian
)
15143 noop
= arm_bigend_noop
;
15146 noop_size
= sizeof (arm_noop
);
15149 if (bytes
& (noop_size
- 1))
15151 fix
= bytes
& (noop_size
- 1);
15152 memset (p
, 0, fix
);
15157 while (bytes
>= noop_size
)
15159 memcpy (p
, noop
, noop_size
);
15161 bytes
-= noop_size
;
15165 fragP
->fr_fix
+= fix
;
15166 fragP
->fr_var
= noop_size
;
15169 /* Called from md_do_align. Used to create an alignment
15170 frag in a code section. */
15173 arm_frag_align_code (int n
, int max
)
15177 /* We assume that there will never be a requirement
15178 to support alignments greater than 32 bytes. */
15179 if (max
> MAX_MEM_FOR_RS_ALIGN_CODE
)
15180 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
15182 p
= frag_var (rs_align_code
,
15183 MAX_MEM_FOR_RS_ALIGN_CODE
,
15185 (relax_substateT
) max
,
15192 /* Perform target specific initialisation of a frag. */
15195 arm_init_frag (fragS
* fragP
)
15197 /* Record whether this frag is in an ARM or a THUMB area. */
15198 fragP
->tc_frag_data
= thumb_mode
;
15203 /* Convert REGNAME to a DWARF-2 register number. */
15206 tc_arm_regname_to_dw2regnum (const char *regname
)
15210 for (i
= 0; rn_table
[i
].name
; i
++)
15211 if (streq (regname
, rn_table
[i
].name
))
15212 return rn_table
[i
].number
;
15217 /* Initialize the DWARF-2 unwind information for this procedure. */
15220 tc_arm_frame_initial_instructions (void)
15222 cfi_add_CFA_def_cfa (REG_SP
, 0);
15226 /* This table describes all the machine specific pseudo-ops the assembler
15227 has to support. The fields are:
15228 pseudo-op name without dot
15229 function to call to execute this pseudo-op
15230 Integer arg to pass to the function. */
15232 const pseudo_typeS md_pseudo_table
[] =
15234 /* Never called because '.req' does not start a line. */
15235 { "req", s_req
, 0 },
15236 { "unreq", s_unreq
, 0 },
15237 { "bss", s_bss
, 0 },
15238 { "align", s_align
, 0 },
15239 { "arm", s_arm
, 0 },
15240 { "thumb", s_thumb
, 0 },
15241 { "code", s_code
, 0 },
15242 { "force_thumb", s_force_thumb
, 0 },
15243 { "thumb_func", s_thumb_func
, 0 },
15244 { "thumb_set", s_thumb_set
, 0 },
15245 { "even", s_even
, 0 },
15246 { "ltorg", s_ltorg
, 0 },
15247 { "pool", s_ltorg
, 0 },
15249 { "word", s_arm_elf_cons
, 4 },
15250 { "long", s_arm_elf_cons
, 4 },
15251 { "rel31", s_arm_rel31
, 0 },
15252 { "fnstart", s_arm_unwind_fnstart
, 0 },
15253 { "fnend", s_arm_unwind_fnend
, 0 },
15254 { "cantunwind", s_arm_unwind_cantunwind
, 0 },
15255 { "personality", s_arm_unwind_personality
, 0 },
15256 { "personalityindex", s_arm_unwind_personalityindex
, 0 },
15257 { "handlerdata", s_arm_unwind_handlerdata
, 0 },
15258 { "save", s_arm_unwind_save
, 0 },
15259 { "movsp", s_arm_unwind_movsp
, 0 },
15260 { "pad", s_arm_unwind_pad
, 0 },
15261 { "setfp", s_arm_unwind_setfp
, 0 },
15262 { "unwind_raw", s_arm_unwind_raw
, 0 },
15264 { "word", cons
, 4},
15266 { "extend", float_cons
, 'x' },
15267 { "ldouble", float_cons
, 'x' },
15268 { "packed", float_cons
, 'p' },