1 /* tc-arm.c -- Assemble for the ARM
2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
3 Free Software Foundation, Inc.
4 Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
5 Modified by David Taylor (dtaylor@armltd.co.uk)
6 Cirrus coprocessor mods by Aldy Hernandez (aldyh@redhat.com)
7 Cirrus coprocessor fixes by Petko Manolov (petkan@nucleusys.com)
8 Cirrus coprocessor fixes by Vladimir Ivanov (vladitx@nucleusys.com)
10 This file is part of GAS, the GNU Assembler.
12 GAS is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2, or (at your option)
17 GAS is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with GAS; see the file COPYING. If not, write to the Free
24 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
30 #include "safe-ctype.h"
32 /* Need TARGET_CPU. */
39 #include "opcode/arm.h"
43 #include "dwarf2dbg.h"
46 /* XXX Set this to 1 after the next binutils release */
47 #define WARN_DEPRECATED 0
56 /* Types of processor to assemble for. */
57 #define ARM_1 ARM_ARCH_V1
58 #define ARM_2 ARM_ARCH_V2
59 #define ARM_3 ARM_ARCH_V2S
60 #define ARM_250 ARM_ARCH_V2S
61 #define ARM_6 ARM_ARCH_V3
62 #define ARM_7 ARM_ARCH_V3
63 #define ARM_8 ARM_ARCH_V4
64 #define ARM_9 ARM_ARCH_V4T
65 #define ARM_STRONG ARM_ARCH_V4
66 #define ARM_CPU_MASK 0x0000000f /* XXX? */
69 #if defined __XSCALE__
70 #define CPU_DEFAULT (ARM_ARCH_XSCALE)
73 #define CPU_DEFAULT (ARM_ARCH_V5T)
75 #define CPU_DEFAULT ARM_ANY
81 #define FPU_DEFAULT FPU_ARCH_FPA
86 #define FPU_DEFAULT FPU_ARCH_VFP /* Soft-float, but VFP order. */
88 /* Legacy a.out format. */
89 #define FPU_DEFAULT FPU_ARCH_FPA /* Soft-float, but FPA order. */
93 /* For backwards compatibility we default to the FPA. */
95 #define FPU_DEFAULT FPU_ARCH_FPA
98 #define streq(a, b) (strcmp (a, b) == 0)
99 #define skip_whitespace(str) while (*(str) == ' ') ++(str)
101 static unsigned long cpu_variant
;
102 static int target_oabi
= 0;
104 /* Flags stored in private area of BFD structure. */
105 static int uses_apcs_26
= FALSE
;
106 static int atpcs
= FALSE
;
107 static int support_interwork
= FALSE
;
108 static int uses_apcs_float
= FALSE
;
109 static int pic_code
= FALSE
;
111 /* Variables that we set while parsing command-line options. Once all
112 options have been read we re-process these values to set the real
114 static int legacy_cpu
= -1;
115 static int legacy_fpu
= -1;
117 static int mcpu_cpu_opt
= -1;
118 static int mcpu_fpu_opt
= -1;
119 static int march_cpu_opt
= -1;
120 static int march_fpu_opt
= -1;
121 static int mfpu_opt
= -1;
122 static int mfloat_abi_opt
= -1;
124 static int meabi_flags
= EF_ARM_EABI_UNKNOWN
;
127 /* This array holds the chars that always start a comment. If the
128 pre-processor is disabled, these aren't very useful. */
129 const char comment_chars
[] = "@";
131 /* This array holds the chars that only start a comment at the beginning of
132 a line. If the line seems to have the form '# 123 filename'
133 .line and .file directives will appear in the pre-processed output. */
134 /* Note that input_file.c hand checks for '#' at the beginning of the
135 first line of the input file. This is because the compiler outputs
136 #NO_APP at the beginning of its output. */
137 /* Also note that comments like this one will always work. */
138 const char line_comment_chars
[] = "#";
140 const char line_separator_chars
[] = ";";
142 /* Chars that can be used to separate mant
143 from exp in floating point numbers. */
144 const char EXP_CHARS
[] = "eE";
146 /* Chars that mean this number is a floating point constant. */
150 const char FLT_CHARS
[] = "rRsSfFdDxXeEpP";
152 /* Prefix characters that indicate the start of an immediate
154 #define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
157 /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
158 symbolS
* GOT_symbol
;
161 /* Size of relocation record. */
162 const int md_reloc_size
= 8;
164 /* 0: assemble for ARM,
165 1: assemble for Thumb,
166 2: assemble for Thumb even though target CPU does not support thumb
168 static int thumb_mode
= 0;
170 typedef struct arm_fix
178 unsigned long instruction
;
182 bfd_reloc_code_real_type type
;
199 struct asm_shift_properties
201 enum asm_shift_index index
;
202 unsigned long bit_field
;
203 unsigned int allows_0
: 1;
204 unsigned int allows_32
: 1;
207 static const struct asm_shift_properties shift_properties
[] =
209 { SHIFT_LSL
, 0, 1, 0},
210 { SHIFT_LSR
, 0x20, 0, 1},
211 { SHIFT_ASR
, 0x40, 0, 1},
212 { SHIFT_ROR
, 0x60, 0, 0},
213 { SHIFT_RRX
, 0x60, 0, 0}
216 struct asm_shift_name
219 const struct asm_shift_properties
* properties
;
222 static const struct asm_shift_name shift_names
[] =
224 { "asl", shift_properties
+ SHIFT_LSL
},
225 { "lsl", shift_properties
+ SHIFT_LSL
},
226 { "lsr", shift_properties
+ SHIFT_LSR
},
227 { "asr", shift_properties
+ SHIFT_ASR
},
228 { "ror", shift_properties
+ SHIFT_ROR
},
229 { "rrx", shift_properties
+ SHIFT_RRX
},
230 { "ASL", shift_properties
+ SHIFT_LSL
},
231 { "LSL", shift_properties
+ SHIFT_LSL
},
232 { "LSR", shift_properties
+ SHIFT_LSR
},
233 { "ASR", shift_properties
+ SHIFT_ASR
},
234 { "ROR", shift_properties
+ SHIFT_ROR
},
235 { "RRX", shift_properties
+ SHIFT_RRX
}
238 /* Any kind of shift is accepted. */
239 #define NO_SHIFT_RESTRICT 1
240 /* The shift operand must be an immediate value, not a register. */
241 #define SHIFT_IMMEDIATE 0
242 /* The shift must be LSL or ASR and the operand must be an immediate. */
243 #define SHIFT_LSL_OR_ASR_IMMEDIATE 2
244 /* The shift must be ASR and the operand must be an immediate. */
245 #define SHIFT_ASR_IMMEDIATE 3
246 /* The shift must be LSL and the operand must be an immediate. */
247 #define SHIFT_LSL_IMMEDIATE 4
249 #define NUM_FLOAT_VALS 8
251 const char * fp_const
[] =
253 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
256 /* Number of littlenums required to hold an extended precision number. */
257 #define MAX_LITTLENUMS 6
259 LITTLENUM_TYPE fp_values
[NUM_FLOAT_VALS
][MAX_LITTLENUMS
];
264 /* Whether a Co-processor load/store operation accepts write-back forms. */
273 #define CP_T_X 0x00008000
274 #define CP_T_Y 0x00400000
275 #define CP_T_Pre 0x01000000
276 #define CP_T_UD 0x00800000
277 #define CP_T_WB 0x00200000
279 #define CONDS_BIT 0x00100000
280 #define LOAD_BIT 0x00100000
282 #define DOUBLE_LOAD_FLAG 0x00000001
286 const char * template;
290 #define COND_ALWAYS 0xe0000000
291 #define COND_MASK 0xf0000000
293 static const struct asm_cond conds
[] =
297 {"cs", 0x20000000}, {"hs", 0x20000000},
298 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
315 const char *template;
320 /* The bit that distinguishes CPSR and SPSR. */
321 #define SPSR_BIT (1 << 22)
323 /* How many bits to shift the PSR_xxx bits up by. */
326 #define PSR_c (1 << 0)
327 #define PSR_x (1 << 1)
328 #define PSR_s (1 << 2)
329 #define PSR_f (1 << 3)
331 static const struct asm_psr psrs
[] =
333 {"CPSR", TRUE
, PSR_c
| PSR_f
},
334 {"CPSR_all", TRUE
, PSR_c
| PSR_f
},
335 {"SPSR", FALSE
, PSR_c
| PSR_f
},
336 {"SPSR_all", FALSE
, PSR_c
| PSR_f
},
337 {"CPSR_flg", TRUE
, PSR_f
},
338 {"CPSR_f", TRUE
, PSR_f
},
339 {"SPSR_flg", FALSE
, PSR_f
},
340 {"SPSR_f", FALSE
, PSR_f
},
341 {"CPSR_c", TRUE
, PSR_c
},
342 {"CPSR_ctl", TRUE
, PSR_c
},
343 {"SPSR_c", FALSE
, PSR_c
},
344 {"SPSR_ctl", FALSE
, PSR_c
},
345 {"CPSR_x", TRUE
, PSR_x
},
346 {"CPSR_s", TRUE
, PSR_s
},
347 {"SPSR_x", FALSE
, PSR_x
},
348 {"SPSR_s", FALSE
, PSR_s
},
349 /* Combinations of flags. */
350 {"CPSR_fs", TRUE
, PSR_f
| PSR_s
},
351 {"CPSR_fx", TRUE
, PSR_f
| PSR_x
},
352 {"CPSR_fc", TRUE
, PSR_f
| PSR_c
},
353 {"CPSR_sf", TRUE
, PSR_s
| PSR_f
},
354 {"CPSR_sx", TRUE
, PSR_s
| PSR_x
},
355 {"CPSR_sc", TRUE
, PSR_s
| PSR_c
},
356 {"CPSR_xf", TRUE
, PSR_x
| PSR_f
},
357 {"CPSR_xs", TRUE
, PSR_x
| PSR_s
},
358 {"CPSR_xc", TRUE
, PSR_x
| PSR_c
},
359 {"CPSR_cf", TRUE
, PSR_c
| PSR_f
},
360 {"CPSR_cs", TRUE
, PSR_c
| PSR_s
},
361 {"CPSR_cx", TRUE
, PSR_c
| PSR_x
},
362 {"CPSR_fsx", TRUE
, PSR_f
| PSR_s
| PSR_x
},
363 {"CPSR_fsc", TRUE
, PSR_f
| PSR_s
| PSR_c
},
364 {"CPSR_fxs", TRUE
, PSR_f
| PSR_x
| PSR_s
},
365 {"CPSR_fxc", TRUE
, PSR_f
| PSR_x
| PSR_c
},
366 {"CPSR_fcs", TRUE
, PSR_f
| PSR_c
| PSR_s
},
367 {"CPSR_fcx", TRUE
, PSR_f
| PSR_c
| PSR_x
},
368 {"CPSR_sfx", TRUE
, PSR_s
| PSR_f
| PSR_x
},
369 {"CPSR_sfc", TRUE
, PSR_s
| PSR_f
| PSR_c
},
370 {"CPSR_sxf", TRUE
, PSR_s
| PSR_x
| PSR_f
},
371 {"CPSR_sxc", TRUE
, PSR_s
| PSR_x
| PSR_c
},
372 {"CPSR_scf", TRUE
, PSR_s
| PSR_c
| PSR_f
},
373 {"CPSR_scx", TRUE
, PSR_s
| PSR_c
| PSR_x
},
374 {"CPSR_xfs", TRUE
, PSR_x
| PSR_f
| PSR_s
},
375 {"CPSR_xfc", TRUE
, PSR_x
| PSR_f
| PSR_c
},
376 {"CPSR_xsf", TRUE
, PSR_x
| PSR_s
| PSR_f
},
377 {"CPSR_xsc", TRUE
, PSR_x
| PSR_s
| PSR_c
},
378 {"CPSR_xcf", TRUE
, PSR_x
| PSR_c
| PSR_f
},
379 {"CPSR_xcs", TRUE
, PSR_x
| PSR_c
| PSR_s
},
380 {"CPSR_cfs", TRUE
, PSR_c
| PSR_f
| PSR_s
},
381 {"CPSR_cfx", TRUE
, PSR_c
| PSR_f
| PSR_x
},
382 {"CPSR_csf", TRUE
, PSR_c
| PSR_s
| PSR_f
},
383 {"CPSR_csx", TRUE
, PSR_c
| PSR_s
| PSR_x
},
384 {"CPSR_cxf", TRUE
, PSR_c
| PSR_x
| PSR_f
},
385 {"CPSR_cxs", TRUE
, PSR_c
| PSR_x
| PSR_s
},
386 {"CPSR_fsxc", TRUE
, PSR_f
| PSR_s
| PSR_x
| PSR_c
},
387 {"CPSR_fscx", TRUE
, PSR_f
| PSR_s
| PSR_c
| PSR_x
},
388 {"CPSR_fxsc", TRUE
, PSR_f
| PSR_x
| PSR_s
| PSR_c
},
389 {"CPSR_fxcs", TRUE
, PSR_f
| PSR_x
| PSR_c
| PSR_s
},
390 {"CPSR_fcsx", TRUE
, PSR_f
| PSR_c
| PSR_s
| PSR_x
},
391 {"CPSR_fcxs", TRUE
, PSR_f
| PSR_c
| PSR_x
| PSR_s
},
392 {"CPSR_sfxc", TRUE
, PSR_s
| PSR_f
| PSR_x
| PSR_c
},
393 {"CPSR_sfcx", TRUE
, PSR_s
| PSR_f
| PSR_c
| PSR_x
},
394 {"CPSR_sxfc", TRUE
, PSR_s
| PSR_x
| PSR_f
| PSR_c
},
395 {"CPSR_sxcf", TRUE
, PSR_s
| PSR_x
| PSR_c
| PSR_f
},
396 {"CPSR_scfx", TRUE
, PSR_s
| PSR_c
| PSR_f
| PSR_x
},
397 {"CPSR_scxf", TRUE
, PSR_s
| PSR_c
| PSR_x
| PSR_f
},
398 {"CPSR_xfsc", TRUE
, PSR_x
| PSR_f
| PSR_s
| PSR_c
},
399 {"CPSR_xfcs", TRUE
, PSR_x
| PSR_f
| PSR_c
| PSR_s
},
400 {"CPSR_xsfc", TRUE
, PSR_x
| PSR_s
| PSR_f
| PSR_c
},
401 {"CPSR_xscf", TRUE
, PSR_x
| PSR_s
| PSR_c
| PSR_f
},
402 {"CPSR_xcfs", TRUE
, PSR_x
| PSR_c
| PSR_f
| PSR_s
},
403 {"CPSR_xcsf", TRUE
, PSR_x
| PSR_c
| PSR_s
| PSR_f
},
404 {"CPSR_cfsx", TRUE
, PSR_c
| PSR_f
| PSR_s
| PSR_x
},
405 {"CPSR_cfxs", TRUE
, PSR_c
| PSR_f
| PSR_x
| PSR_s
},
406 {"CPSR_csfx", TRUE
, PSR_c
| PSR_s
| PSR_f
| PSR_x
},
407 {"CPSR_csxf", TRUE
, PSR_c
| PSR_s
| PSR_x
| PSR_f
},
408 {"CPSR_cxfs", TRUE
, PSR_c
| PSR_x
| PSR_f
| PSR_s
},
409 {"CPSR_cxsf", TRUE
, PSR_c
| PSR_x
| PSR_s
| PSR_f
},
410 {"SPSR_fs", FALSE
, PSR_f
| PSR_s
},
411 {"SPSR_fx", FALSE
, PSR_f
| PSR_x
},
412 {"SPSR_fc", FALSE
, PSR_f
| PSR_c
},
413 {"SPSR_sf", FALSE
, PSR_s
| PSR_f
},
414 {"SPSR_sx", FALSE
, PSR_s
| PSR_x
},
415 {"SPSR_sc", FALSE
, PSR_s
| PSR_c
},
416 {"SPSR_xf", FALSE
, PSR_x
| PSR_f
},
417 {"SPSR_xs", FALSE
, PSR_x
| PSR_s
},
418 {"SPSR_xc", FALSE
, PSR_x
| PSR_c
},
419 {"SPSR_cf", FALSE
, PSR_c
| PSR_f
},
420 {"SPSR_cs", FALSE
, PSR_c
| PSR_s
},
421 {"SPSR_cx", FALSE
, PSR_c
| PSR_x
},
422 {"SPSR_fsx", FALSE
, PSR_f
| PSR_s
| PSR_x
},
423 {"SPSR_fsc", FALSE
, PSR_f
| PSR_s
| PSR_c
},
424 {"SPSR_fxs", FALSE
, PSR_f
| PSR_x
| PSR_s
},
425 {"SPSR_fxc", FALSE
, PSR_f
| PSR_x
| PSR_c
},
426 {"SPSR_fcs", FALSE
, PSR_f
| PSR_c
| PSR_s
},
427 {"SPSR_fcx", FALSE
, PSR_f
| PSR_c
| PSR_x
},
428 {"SPSR_sfx", FALSE
, PSR_s
| PSR_f
| PSR_x
},
429 {"SPSR_sfc", FALSE
, PSR_s
| PSR_f
| PSR_c
},
430 {"SPSR_sxf", FALSE
, PSR_s
| PSR_x
| PSR_f
},
431 {"SPSR_sxc", FALSE
, PSR_s
| PSR_x
| PSR_c
},
432 {"SPSR_scf", FALSE
, PSR_s
| PSR_c
| PSR_f
},
433 {"SPSR_scx", FALSE
, PSR_s
| PSR_c
| PSR_x
},
434 {"SPSR_xfs", FALSE
, PSR_x
| PSR_f
| PSR_s
},
435 {"SPSR_xfc", FALSE
, PSR_x
| PSR_f
| PSR_c
},
436 {"SPSR_xsf", FALSE
, PSR_x
| PSR_s
| PSR_f
},
437 {"SPSR_xsc", FALSE
, PSR_x
| PSR_s
| PSR_c
},
438 {"SPSR_xcf", FALSE
, PSR_x
| PSR_c
| PSR_f
},
439 {"SPSR_xcs", FALSE
, PSR_x
| PSR_c
| PSR_s
},
440 {"SPSR_cfs", FALSE
, PSR_c
| PSR_f
| PSR_s
},
441 {"SPSR_cfx", FALSE
, PSR_c
| PSR_f
| PSR_x
},
442 {"SPSR_csf", FALSE
, PSR_c
| PSR_s
| PSR_f
},
443 {"SPSR_csx", FALSE
, PSR_c
| PSR_s
| PSR_x
},
444 {"SPSR_cxf", FALSE
, PSR_c
| PSR_x
| PSR_f
},
445 {"SPSR_cxs", FALSE
, PSR_c
| PSR_x
| PSR_s
},
446 {"SPSR_fsxc", FALSE
, PSR_f
| PSR_s
| PSR_x
| PSR_c
},
447 {"SPSR_fscx", FALSE
, PSR_f
| PSR_s
| PSR_c
| PSR_x
},
448 {"SPSR_fxsc", FALSE
, PSR_f
| PSR_x
| PSR_s
| PSR_c
},
449 {"SPSR_fxcs", FALSE
, PSR_f
| PSR_x
| PSR_c
| PSR_s
},
450 {"SPSR_fcsx", FALSE
, PSR_f
| PSR_c
| PSR_s
| PSR_x
},
451 {"SPSR_fcxs", FALSE
, PSR_f
| PSR_c
| PSR_x
| PSR_s
},
452 {"SPSR_sfxc", FALSE
, PSR_s
| PSR_f
| PSR_x
| PSR_c
},
453 {"SPSR_sfcx", FALSE
, PSR_s
| PSR_f
| PSR_c
| PSR_x
},
454 {"SPSR_sxfc", FALSE
, PSR_s
| PSR_x
| PSR_f
| PSR_c
},
455 {"SPSR_sxcf", FALSE
, PSR_s
| PSR_x
| PSR_c
| PSR_f
},
456 {"SPSR_scfx", FALSE
, PSR_s
| PSR_c
| PSR_f
| PSR_x
},
457 {"SPSR_scxf", FALSE
, PSR_s
| PSR_c
| PSR_x
| PSR_f
},
458 {"SPSR_xfsc", FALSE
, PSR_x
| PSR_f
| PSR_s
| PSR_c
},
459 {"SPSR_xfcs", FALSE
, PSR_x
| PSR_f
| PSR_c
| PSR_s
},
460 {"SPSR_xsfc", FALSE
, PSR_x
| PSR_s
| PSR_f
| PSR_c
},
461 {"SPSR_xscf", FALSE
, PSR_x
| PSR_s
| PSR_c
| PSR_f
},
462 {"SPSR_xcfs", FALSE
, PSR_x
| PSR_c
| PSR_f
| PSR_s
},
463 {"SPSR_xcsf", FALSE
, PSR_x
| PSR_c
| PSR_s
| PSR_f
},
464 {"SPSR_cfsx", FALSE
, PSR_c
| PSR_f
| PSR_s
| PSR_x
},
465 {"SPSR_cfxs", FALSE
, PSR_c
| PSR_f
| PSR_x
| PSR_s
},
466 {"SPSR_csfx", FALSE
, PSR_c
| PSR_s
| PSR_f
| PSR_x
},
467 {"SPSR_csxf", FALSE
, PSR_c
| PSR_s
| PSR_x
| PSR_f
},
468 {"SPSR_cxfs", FALSE
, PSR_c
| PSR_x
| PSR_f
| PSR_s
},
469 {"SPSR_cxsf", FALSE
, PSR_c
| PSR_x
| PSR_s
| PSR_f
},
476 IWMMXT_REG_WR_OR_WC
= 2,
480 enum iwmmxt_insn_type
503 VFP_REG_Dd
, VFP_REG_Dm
, VFP_REG_Dn
508 VFP_REG_Sd
, VFP_REG_Sm
, VFP_REG_Sn
513 VFP_LDSTMIA
, VFP_LDSTMDB
, VFP_LDSTMIAX
, VFP_LDSTMDBX
516 /* VFP system registers. */
523 static const struct vfp_reg vfp_regs
[] =
525 {"fpsid", 0x00000000},
526 {"FPSID", 0x00000000},
527 {"fpscr", 0x00010000},
528 {"FPSCR", 0x00010000},
529 {"fpexc", 0x00080000},
530 {"FPEXC", 0x00080000}
533 /* Structure for a hash table entry for a register. */
541 /* Some well known registers that we refer to directly elsewhere. */
546 #define wr_register(reg) ((reg ^ WR_PREFIX) >= 0 && (reg ^ WR_PREFIX) <= 15)
547 #define wc_register(reg) ((reg ^ WC_PREFIX) >= 0 && (reg ^ WC_PREFIX) <= 15)
548 #define wcg_register(reg) ((reg ^ WC_PREFIX) >= 8 && (reg ^ WC_PREFIX) <= 11)
550 /* These are the standard names. Users can add aliases with .req.
551 and delete them with .unreq. */
553 /* Integer Register Numbers. */
554 static const struct reg_entry rn_table
[] =
556 {"r0", 0, TRUE
}, {"r1", 1, TRUE
}, {"r2", 2, TRUE
}, {"r3", 3, TRUE
},
557 {"r4", 4, TRUE
}, {"r5", 5, TRUE
}, {"r6", 6, TRUE
}, {"r7", 7, TRUE
},
558 {"r8", 8, TRUE
}, {"r9", 9, TRUE
}, {"r10", 10, TRUE
}, {"r11", 11, TRUE
},
559 {"r12", 12, TRUE
}, {"r13", REG_SP
, TRUE
}, {"r14", REG_LR
, TRUE
}, {"r15", REG_PC
, TRUE
},
560 /* ATPCS Synonyms. */
561 {"a1", 0, TRUE
}, {"a2", 1, TRUE
}, {"a3", 2, TRUE
}, {"a4", 3, TRUE
},
562 {"v1", 4, TRUE
}, {"v2", 5, TRUE
}, {"v3", 6, TRUE
}, {"v4", 7, TRUE
},
563 {"v5", 8, TRUE
}, {"v6", 9, TRUE
}, {"v7", 10, TRUE
}, {"v8", 11, TRUE
},
564 /* Well-known aliases. */
565 {"wr", 7, TRUE
}, {"sb", 9, TRUE
}, {"sl", 10, TRUE
}, {"fp", 11, TRUE
},
566 {"ip", 12, TRUE
}, {"sp", REG_SP
, TRUE
}, {"lr", REG_LR
, TRUE
}, {"pc", REG_PC
, TRUE
},
570 #define WR_PREFIX 0x200
571 #define WC_PREFIX 0x400
573 static const struct reg_entry iwmmxt_table
[] =
575 /* Intel Wireless MMX technology register names. */
576 { "wr0", 0x0 | WR_PREFIX
, TRUE
}, {"wr1", 0x1 | WR_PREFIX
, TRUE
},
577 { "wr2", 0x2 | WR_PREFIX
, TRUE
}, {"wr3", 0x3 | WR_PREFIX
, TRUE
},
578 { "wr4", 0x4 | WR_PREFIX
, TRUE
}, {"wr5", 0x5 | WR_PREFIX
, TRUE
},
579 { "wr6", 0x6 | WR_PREFIX
, TRUE
}, {"wr7", 0x7 | WR_PREFIX
, TRUE
},
580 { "wr8", 0x8 | WR_PREFIX
, TRUE
}, {"wr9", 0x9 | WR_PREFIX
, TRUE
},
581 { "wr10", 0xa | WR_PREFIX
, TRUE
}, {"wr11", 0xb | WR_PREFIX
, TRUE
},
582 { "wr12", 0xc | WR_PREFIX
, TRUE
}, {"wr13", 0xd | WR_PREFIX
, TRUE
},
583 { "wr14", 0xe | WR_PREFIX
, TRUE
}, {"wr15", 0xf | WR_PREFIX
, TRUE
},
584 { "wcid", 0x0 | WC_PREFIX
, TRUE
}, {"wcon", 0x1 | WC_PREFIX
, TRUE
},
585 {"wcssf", 0x2 | WC_PREFIX
, TRUE
}, {"wcasf", 0x3 | WC_PREFIX
, TRUE
},
586 {"wcgr0", 0x8 | WC_PREFIX
, TRUE
}, {"wcgr1", 0x9 | WC_PREFIX
, TRUE
},
587 {"wcgr2", 0xa | WC_PREFIX
, TRUE
}, {"wcgr3", 0xb | WC_PREFIX
, TRUE
},
589 { "wR0", 0x0 | WR_PREFIX
, TRUE
}, {"wR1", 0x1 | WR_PREFIX
, TRUE
},
590 { "wR2", 0x2 | WR_PREFIX
, TRUE
}, {"wR3", 0x3 | WR_PREFIX
, TRUE
},
591 { "wR4", 0x4 | WR_PREFIX
, TRUE
}, {"wR5", 0x5 | WR_PREFIX
, TRUE
},
592 { "wR6", 0x6 | WR_PREFIX
, TRUE
}, {"wR7", 0x7 | WR_PREFIX
, TRUE
},
593 { "wR8", 0x8 | WR_PREFIX
, TRUE
}, {"wR9", 0x9 | WR_PREFIX
, TRUE
},
594 { "wR10", 0xa | WR_PREFIX
, TRUE
}, {"wR11", 0xb | WR_PREFIX
, TRUE
},
595 { "wR12", 0xc | WR_PREFIX
, TRUE
}, {"wR13", 0xd | WR_PREFIX
, TRUE
},
596 { "wR14", 0xe | WR_PREFIX
, TRUE
}, {"wR15", 0xf | WR_PREFIX
, TRUE
},
597 { "wCID", 0x0 | WC_PREFIX
, TRUE
}, {"wCon", 0x1 | WC_PREFIX
, TRUE
},
598 {"wCSSF", 0x2 | WC_PREFIX
, TRUE
}, {"wCASF", 0x3 | WC_PREFIX
, TRUE
},
599 {"wCGR0", 0x8 | WC_PREFIX
, TRUE
}, {"wCGR1", 0x9 | WC_PREFIX
, TRUE
},
600 {"wCGR2", 0xa | WC_PREFIX
, TRUE
}, {"wCGR3", 0xb | WC_PREFIX
, TRUE
},
604 /* Co-processor Numbers. */
605 static const struct reg_entry cp_table
[] =
607 {"p0", 0, TRUE
}, {"p1", 1, TRUE
}, {"p2", 2, TRUE
}, {"p3", 3, TRUE
},
608 {"p4", 4, TRUE
}, {"p5", 5, TRUE
}, {"p6", 6, TRUE
}, {"p7", 7, TRUE
},
609 {"p8", 8, TRUE
}, {"p9", 9, TRUE
}, {"p10", 10, TRUE
}, {"p11", 11, TRUE
},
610 {"p12", 12, TRUE
}, {"p13", 13, TRUE
}, {"p14", 14, TRUE
}, {"p15", 15, TRUE
},
614 /* Co-processor Register Numbers. */
615 static const struct reg_entry cn_table
[] =
617 {"c0", 0, TRUE
}, {"c1", 1, TRUE
}, {"c2", 2, TRUE
}, {"c3", 3, TRUE
},
618 {"c4", 4, TRUE
}, {"c5", 5, TRUE
}, {"c6", 6, TRUE
}, {"c7", 7, TRUE
},
619 {"c8", 8, TRUE
}, {"c9", 9, TRUE
}, {"c10", 10, TRUE
}, {"c11", 11, TRUE
},
620 {"c12", 12, TRUE
}, {"c13", 13, TRUE
}, {"c14", 14, TRUE
}, {"c15", 15, TRUE
},
621 /* Not really valid, but kept for back-wards compatibility. */
622 {"cr0", 0, TRUE
}, {"cr1", 1, TRUE
}, {"cr2", 2, TRUE
}, {"cr3", 3, TRUE
},
623 {"cr4", 4, TRUE
}, {"cr5", 5, TRUE
}, {"cr6", 6, TRUE
}, {"cr7", 7, TRUE
},
624 {"cr8", 8, TRUE
}, {"cr9", 9, TRUE
}, {"cr10", 10, TRUE
}, {"cr11", 11, TRUE
},
625 {"cr12", 12, TRUE
}, {"cr13", 13, TRUE
}, {"cr14", 14, TRUE
}, {"cr15", 15, TRUE
},
630 static const struct reg_entry fn_table
[] =
632 {"f0", 0, TRUE
}, {"f1", 1, TRUE
}, {"f2", 2, TRUE
}, {"f3", 3, TRUE
},
633 {"f4", 4, TRUE
}, {"f5", 5, TRUE
}, {"f6", 6, TRUE
}, {"f7", 7, TRUE
},
637 /* VFP SP Registers. */
638 static const struct reg_entry sn_table
[] =
640 {"s0", 0, TRUE
}, {"s1", 1, TRUE
}, {"s2", 2, TRUE
}, {"s3", 3, TRUE
},
641 {"s4", 4, TRUE
}, {"s5", 5, TRUE
}, {"s6", 6, TRUE
}, {"s7", 7, TRUE
},
642 {"s8", 8, TRUE
}, {"s9", 9, TRUE
}, {"s10", 10, TRUE
}, {"s11", 11, TRUE
},
643 {"s12", 12, TRUE
}, {"s13", 13, TRUE
}, {"s14", 14, TRUE
}, {"s15", 15, TRUE
},
644 {"s16", 16, TRUE
}, {"s17", 17, TRUE
}, {"s18", 18, TRUE
}, {"s19", 19, TRUE
},
645 {"s20", 20, TRUE
}, {"s21", 21, TRUE
}, {"s22", 22, TRUE
}, {"s23", 23, TRUE
},
646 {"s24", 24, TRUE
}, {"s25", 25, TRUE
}, {"s26", 26, TRUE
}, {"s27", 27, TRUE
},
647 {"s28", 28, TRUE
}, {"s29", 29, TRUE
}, {"s30", 30, TRUE
}, {"s31", 31, TRUE
},
651 /* VFP DP Registers. */
652 static const struct reg_entry dn_table
[] =
654 {"d0", 0, TRUE
}, {"d1", 1, TRUE
}, {"d2", 2, TRUE
}, {"d3", 3, TRUE
},
655 {"d4", 4, TRUE
}, {"d5", 5, TRUE
}, {"d6", 6, TRUE
}, {"d7", 7, TRUE
},
656 {"d8", 8, TRUE
}, {"d9", 9, TRUE
}, {"d10", 10, TRUE
}, {"d11", 11, TRUE
},
657 {"d12", 12, TRUE
}, {"d13", 13, TRUE
}, {"d14", 14, TRUE
}, {"d15", 15, TRUE
},
661 /* Maverick DSP coprocessor registers. */
662 static const struct reg_entry mav_mvf_table
[] =
664 {"mvf0", 0, TRUE
}, {"mvf1", 1, TRUE
}, {"mvf2", 2, TRUE
}, {"mvf3", 3, TRUE
},
665 {"mvf4", 4, TRUE
}, {"mvf5", 5, TRUE
}, {"mvf6", 6, TRUE
}, {"mvf7", 7, TRUE
},
666 {"mvf8", 8, TRUE
}, {"mvf9", 9, TRUE
}, {"mvf10", 10, TRUE
}, {"mvf11", 11, TRUE
},
667 {"mvf12", 12, TRUE
}, {"mvf13", 13, TRUE
}, {"mvf14", 14, TRUE
}, {"mvf15", 15, TRUE
},
671 static const struct reg_entry mav_mvd_table
[] =
673 {"mvd0", 0, TRUE
}, {"mvd1", 1, TRUE
}, {"mvd2", 2, TRUE
}, {"mvd3", 3, TRUE
},
674 {"mvd4", 4, TRUE
}, {"mvd5", 5, TRUE
}, {"mvd6", 6, TRUE
}, {"mvd7", 7, TRUE
},
675 {"mvd8", 8, TRUE
}, {"mvd9", 9, TRUE
}, {"mvd10", 10, TRUE
}, {"mvd11", 11, TRUE
},
676 {"mvd12", 12, TRUE
}, {"mvd13", 13, TRUE
}, {"mvd14", 14, TRUE
}, {"mvd15", 15, TRUE
},
680 static const struct reg_entry mav_mvfx_table
[] =
682 {"mvfx0", 0, TRUE
}, {"mvfx1", 1, TRUE
}, {"mvfx2", 2, TRUE
}, {"mvfx3", 3, TRUE
},
683 {"mvfx4", 4, TRUE
}, {"mvfx5", 5, TRUE
}, {"mvfx6", 6, TRUE
}, {"mvfx7", 7, TRUE
},
684 {"mvfx8", 8, TRUE
}, {"mvfx9", 9, TRUE
}, {"mvfx10", 10, TRUE
}, {"mvfx11", 11, TRUE
},
685 {"mvfx12", 12, TRUE
}, {"mvfx13", 13, TRUE
}, {"mvfx14", 14, TRUE
}, {"mvfx15", 15, TRUE
},
689 static const struct reg_entry mav_mvdx_table
[] =
691 {"mvdx0", 0, TRUE
}, {"mvdx1", 1, TRUE
}, {"mvdx2", 2, TRUE
}, {"mvdx3", 3, TRUE
},
692 {"mvdx4", 4, TRUE
}, {"mvdx5", 5, TRUE
}, {"mvdx6", 6, TRUE
}, {"mvdx7", 7, TRUE
},
693 {"mvdx8", 8, TRUE
}, {"mvdx9", 9, TRUE
}, {"mvdx10", 10, TRUE
}, {"mvdx11", 11, TRUE
},
694 {"mvdx12", 12, TRUE
}, {"mvdx13", 13, TRUE
}, {"mvdx14", 14, TRUE
}, {"mvdx15", 15, TRUE
},
698 static const struct reg_entry mav_mvax_table
[] =
700 {"mvax0", 0, TRUE
}, {"mvax1", 1, TRUE
}, {"mvax2", 2, TRUE
}, {"mvax3", 3, TRUE
},
704 static const struct reg_entry mav_dspsc_table
[] =
712 const struct reg_entry
* names
;
714 struct hash_control
* htab
;
715 const char * expected
;
718 struct reg_map all_reg_maps
[] =
720 {rn_table
, 15, NULL
, N_("ARM register expected")},
721 {cp_table
, 15, NULL
, N_("bad or missing co-processor number")},
722 {cn_table
, 15, NULL
, N_("co-processor register expected")},
723 {fn_table
, 7, NULL
, N_("FPA register expected")},
724 {sn_table
, 31, NULL
, N_("VFP single precision register expected")},
725 {dn_table
, 15, NULL
, N_("VFP double precision register expected")},
726 {mav_mvf_table
, 15, NULL
, N_("Maverick MVF register expected")},
727 {mav_mvd_table
, 15, NULL
, N_("Maverick MVD register expected")},
728 {mav_mvfx_table
, 15, NULL
, N_("Maverick MVFX register expected")},
729 {mav_mvdx_table
, 15, NULL
, N_("Maverick MVDX register expected")},
730 {mav_mvax_table
, 3, NULL
, N_("Maverick MVAX register expected")},
731 {mav_dspsc_table
, 0, NULL
, N_("Maverick DSPSC register expected")},
732 {iwmmxt_table
, 23, NULL
, N_("Intel Wireless MMX technology register expected")},
735 /* Enumeration matching entries in table above. */
739 #define REG_TYPE_FIRST REG_TYPE_RN
751 REG_TYPE_IWMMXT
= 12,
756 /* ARM instructions take 4bytes in the object file, Thumb instructions
760 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
761 #define MAV_MODE1 0x100c
763 /* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
764 #define MAV_MODE2 0x0c10
766 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
767 #define MAV_MODE3 0x100c
769 /* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
770 #define MAV_MODE4 0x0c0010
772 /* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
773 #define MAV_MODE5 0x00100c
775 /* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
776 #define MAV_MODE6 0x00100c05
780 /* Basic string to match. */
781 const char * template;
783 /* Basic instruction code. */
786 /* Offset into the template where the condition code (if any) will be.
787 If zero, then the instruction is never conditional. */
788 unsigned cond_offset
;
790 /* Which architecture variant provides this instruction. */
791 unsigned long variant
;
793 /* Function to call to parse args. */
794 void (* parms
) (char *);
797 /* Defines for various bits that we will want to toggle. */
798 #define INST_IMMEDIATE 0x02000000
799 #define OFFSET_REG 0x02000000
800 #define HWOFFSET_IMM 0x00400000
801 #define SHIFT_BY_REG 0x00000010
802 #define PRE_INDEX 0x01000000
803 #define INDEX_UP 0x00800000
804 #define WRITE_BACK 0x00200000
805 #define LDM_TYPE_2_OR_3 0x00400000
807 #define LITERAL_MASK 0xf000f000
808 #define OPCODE_MASK 0xfe1fffff
809 #define V4_STR_BIT 0x00000020
811 #define DATA_OP_SHIFT 21
813 /* Codes to distinguish the arithmetic instructions. */
824 #define OPCODE_CMP 10
825 #define OPCODE_CMN 11
826 #define OPCODE_ORR 12
827 #define OPCODE_MOV 13
828 #define OPCODE_BIC 14
829 #define OPCODE_MVN 15
831 #define T_OPCODE_MUL 0x4340
832 #define T_OPCODE_TST 0x4200
833 #define T_OPCODE_CMN 0x42c0
834 #define T_OPCODE_NEG 0x4240
835 #define T_OPCODE_MVN 0x43c0
837 #define T_OPCODE_ADD_R3 0x1800
838 #define T_OPCODE_SUB_R3 0x1a00
839 #define T_OPCODE_ADD_HI 0x4400
840 #define T_OPCODE_ADD_ST 0xb000
841 #define T_OPCODE_SUB_ST 0xb080
842 #define T_OPCODE_ADD_SP 0xa800
843 #define T_OPCODE_ADD_PC 0xa000
844 #define T_OPCODE_ADD_I8 0x3000
845 #define T_OPCODE_SUB_I8 0x3800
846 #define T_OPCODE_ADD_I3 0x1c00
847 #define T_OPCODE_SUB_I3 0x1e00
849 #define T_OPCODE_ASR_R 0x4100
850 #define T_OPCODE_LSL_R 0x4080
851 #define T_OPCODE_LSR_R 0x40c0
852 #define T_OPCODE_ASR_I 0x1000
853 #define T_OPCODE_LSL_I 0x0000
854 #define T_OPCODE_LSR_I 0x0800
856 #define T_OPCODE_MOV_I8 0x2000
857 #define T_OPCODE_CMP_I8 0x2800
858 #define T_OPCODE_CMP_LR 0x4280
859 #define T_OPCODE_MOV_HR 0x4600
860 #define T_OPCODE_CMP_HR 0x4500
862 #define T_OPCODE_LDR_PC 0x4800
863 #define T_OPCODE_LDR_SP 0x9800
864 #define T_OPCODE_STR_SP 0x9000
865 #define T_OPCODE_LDR_IW 0x6800
866 #define T_OPCODE_STR_IW 0x6000
867 #define T_OPCODE_LDR_IH 0x8800
868 #define T_OPCODE_STR_IH 0x8000
869 #define T_OPCODE_LDR_IB 0x7800
870 #define T_OPCODE_STR_IB 0x7000
871 #define T_OPCODE_LDR_RW 0x5800
872 #define T_OPCODE_STR_RW 0x5000
873 #define T_OPCODE_LDR_RH 0x5a00
874 #define T_OPCODE_STR_RH 0x5200
875 #define T_OPCODE_LDR_RB 0x5c00
876 #define T_OPCODE_STR_RB 0x5400
878 #define T_OPCODE_PUSH 0xb400
879 #define T_OPCODE_POP 0xbc00
881 #define T_OPCODE_BRANCH 0xe7fe
883 #define THUMB_SIZE 2 /* Size of thumb instruction. */
884 #define THUMB_REG_LO 0x1
885 #define THUMB_REG_HI 0x2
886 #define THUMB_REG_ANY 0x3
888 #define THUMB_H1 0x0080
889 #define THUMB_H2 0x0040
896 #define THUMB_COMPARE 1
900 #define THUMB_STORE 1
902 #define THUMB_PP_PC_LR 0x0100
904 /* These three are used for immediate shifts, do not alter. */
906 #define THUMB_HALFWORD 1
911 /* Basic string to match. */
912 const char * template;
914 /* Basic instruction code. */
919 /* Which CPU variants this exists for. */
920 unsigned long variant
;
922 /* Function to call to parse args. */
923 void (* parms
) (char *);
926 #define BAD_ARGS _("bad arguments to instruction")
927 #define BAD_PC _("r15 not allowed here")
928 #define BAD_COND _("instruction is not conditional")
929 #define ERR_NO_ACCUM _("acc0 expected")
931 static struct hash_control
* arm_ops_hsh
= NULL
;
932 static struct hash_control
* arm_tops_hsh
= NULL
;
933 static struct hash_control
* arm_cond_hsh
= NULL
;
934 static struct hash_control
* arm_shift_hsh
= NULL
;
935 static struct hash_control
* arm_psr_hsh
= NULL
;
937 /* Stuff needed to resolve the label ambiguity
947 symbolS
* last_label_seen
;
948 static int label_is_thumb_function_name
= FALSE
;
950 /* Literal Pool stuff. */
952 #define MAX_LITERAL_POOL_SIZE 1024
954 /* Literal pool structure. Held on a per-section
955 and per-sub-section basis. */
957 typedef struct literal_pool
959 expressionS literals
[MAX_LITERAL_POOL_SIZE
];
960 unsigned int next_free_entry
;
965 struct literal_pool
* next
;
968 /* Pointer to a linked list of literal pools. */
969 literal_pool
* list_of_pools
= NULL
;
971 static literal_pool
*
972 find_literal_pool (void)
976 for (pool
= list_of_pools
; pool
!= NULL
; pool
= pool
->next
)
978 if (pool
->section
== now_seg
979 && pool
->sub_section
== now_subseg
)
986 static literal_pool
*
987 find_or_make_literal_pool (void)
989 /* Next literal pool ID number. */
990 static unsigned int latest_pool_num
= 1;
993 pool
= find_literal_pool ();
997 /* Create a new pool. */
998 pool
= xmalloc (sizeof (* pool
));
1002 pool
->next_free_entry
= 0;
1003 pool
->section
= now_seg
;
1004 pool
->sub_section
= now_subseg
;
1005 pool
->next
= list_of_pools
;
1006 pool
->symbol
= NULL
;
1008 /* Add it to the list. */
1009 list_of_pools
= pool
;
1012 /* New pools, and emptied pools, will have a NULL symbol. */
1013 if (pool
->symbol
== NULL
)
1015 pool
->symbol
= symbol_create (FAKE_LABEL_NAME
, undefined_section
,
1016 (valueT
) 0, &zero_address_frag
);
1017 pool
->id
= latest_pool_num
++;
1024 /* Add the literal in the global 'inst'
1025 structure to the relevent literal pool. */
1028 add_to_lit_pool (void)
1030 literal_pool
* pool
;
1033 pool
= find_or_make_literal_pool ();
1035 /* Check if this literal value is already in the pool. */
1036 for (entry
= 0; entry
< pool
->next_free_entry
; entry
++)
1038 if ((pool
->literals
[entry
].X_op
== inst
.reloc
.exp
.X_op
)
1039 && (inst
.reloc
.exp
.X_op
== O_constant
)
1040 && (pool
->literals
[entry
].X_add_number
1041 == inst
.reloc
.exp
.X_add_number
)
1042 && (pool
->literals
[entry
].X_unsigned
1043 == inst
.reloc
.exp
.X_unsigned
))
1046 if ((pool
->literals
[entry
].X_op
== inst
.reloc
.exp
.X_op
)
1047 && (inst
.reloc
.exp
.X_op
== O_symbol
)
1048 && (pool
->literals
[entry
].X_add_number
1049 == inst
.reloc
.exp
.X_add_number
)
1050 && (pool
->literals
[entry
].X_add_symbol
1051 == inst
.reloc
.exp
.X_add_symbol
)
1052 && (pool
->literals
[entry
].X_op_symbol
1053 == inst
.reloc
.exp
.X_op_symbol
))
1057 /* Do we need to create a new entry? */
1058 if (entry
== pool
->next_free_entry
)
1060 if (entry
>= MAX_LITERAL_POOL_SIZE
)
1062 inst
.error
= _("literal pool overflow");
1066 pool
->literals
[entry
] = inst
.reloc
.exp
;
1067 pool
->next_free_entry
+= 1;
1070 inst
.reloc
.exp
.X_op
= O_symbol
;
1071 inst
.reloc
.exp
.X_add_number
= ((int) entry
) * 4 - 8;
1072 inst
.reloc
.exp
.X_add_symbol
= pool
->symbol
;
1077 /* Can't use symbol_new here, so have to create a symbol and then at
1078 a later date assign it a value. Thats what these functions do. */
1081 symbol_locate (symbolS
* symbolP
,
1082 const char * name
, /* It is copied, the caller can modify. */
1083 segT segment
, /* Segment identifier (SEG_<something>). */
1084 valueT valu
, /* Symbol value. */
1085 fragS
* frag
) /* Associated fragment. */
1087 unsigned int name_length
;
1088 char * preserved_copy_of_name
;
1090 name_length
= strlen (name
) + 1; /* +1 for \0. */
1091 obstack_grow (¬es
, name
, name_length
);
1092 preserved_copy_of_name
= obstack_finish (¬es
);
1093 #ifdef STRIP_UNDERSCORE
1094 if (preserved_copy_of_name
[0] == '_')
1095 preserved_copy_of_name
++;
1098 #ifdef tc_canonicalize_symbol_name
1099 preserved_copy_of_name
=
1100 tc_canonicalize_symbol_name (preserved_copy_of_name
);
1103 S_SET_NAME (symbolP
, preserved_copy_of_name
);
1105 S_SET_SEGMENT (symbolP
, segment
);
1106 S_SET_VALUE (symbolP
, valu
);
1107 symbol_clear_list_pointers (symbolP
);
1109 symbol_set_frag (symbolP
, frag
);
1111 /* Link to end of symbol chain. */
1113 extern int symbol_table_frozen
;
1115 if (symbol_table_frozen
)
1119 symbol_append (symbolP
, symbol_lastP
, & symbol_rootP
, & symbol_lastP
);
1121 obj_symbol_new_hook (symbolP
);
1123 #ifdef tc_symbol_new_hook
1124 tc_symbol_new_hook (symbolP
);
1128 verify_symbol_chain (symbol_rootP
, symbol_lastP
);
1129 #endif /* DEBUG_SYMS */
1132 /* Check that an immediate is valid.
1133 If so, convert it to the right format. */
1136 validate_immediate (unsigned int val
)
1141 #define rotate_left(v, n) (v << n | v >> (32 - n))
1143 for (i
= 0; i
< 32; i
+= 2)
1144 if ((a
= rotate_left (val
, i
)) <= 0xff)
1145 return a
| (i
<< 7); /* 12-bit pack: [shift-cnt,const]. */
1150 /* Check to see if an immediate can be computed as two separate immediate
1151 values, added together. We already know that this value cannot be
1152 computed by just one ARM instruction. */
1155 validate_immediate_twopart (unsigned int val
,
1156 unsigned int * highpart
)
1161 for (i
= 0; i
< 32; i
+= 2)
1162 if (((a
= rotate_left (val
, i
)) & 0xff) != 0)
1168 * highpart
= (a
>> 8) | ((i
+ 24) << 7);
1170 else if (a
& 0xff0000)
1174 * highpart
= (a
>> 16) | ((i
+ 16) << 7);
1178 assert (a
& 0xff000000);
1179 * highpart
= (a
>> 24) | ((i
+ 8) << 7);
1182 return (a
& 0xff) | (i
<< 7);
1189 validate_offset_imm (unsigned int val
, int hwse
)
1191 if ((hwse
&& val
> 255) || val
> 4095)
1198 /* This code is to handle mapping symbols as defined in the ARM ELF spec.
1199 (This text is taken from version B-02 of the spec):
1201 4.4.7 Mapping and tagging symbols
1203 A section of an ARM ELF file can contain a mixture of ARM code,
1204 Thumb code, and data. There are inline transitions between code
1205 and data at literal pool boundaries. There can also be inline
1206 transitions between ARM code and Thumb code, for example in
1207 ARM-Thumb inter-working veneers. Linkers, machine-level
1208 debuggers, profiling tools, and disassembly tools need to map
1209 images accurately. For example, setting an ARM breakpoint on a
1210 Thumb location, or in a literal pool, can crash the program
1211 being debugged, ruining the debugging session.
1213 ARM ELF entities are mapped (see section 4.4.7.1 below) and
1214 tagged (see section 4.4.7.2 below) using local symbols (with
1215 binding STB_LOCAL). To assist consumers, mapping and tagging
1216 symbols should be collated first in the symbol table, before
1217 other symbols with binding STB_LOCAL.
1219 To allow properly collated mapping and tagging symbols to be
1220 skipped by consumers that have no interest in them, the first
1221 such symbol should have the name $m and its st_value field equal
1222 to the total number of mapping and tagging symbols (including
1223 the $m) in the symbol table.
1225 4.4.7.1 Mapping symbols
1227 $a Labels the first byte of a sequence of ARM instructions.
1228 Its type is STT_FUNC.
1230 $d Labels the first byte of a sequence of data items.
1231 Its type is STT_OBJECT.
1233 $t Labels the first byte of a sequence of Thumb instructions.
1234 Its type is STT_FUNC.
1236 This list of mapping symbols may be extended in the future.
1238 Section-relative mapping symbols
1240 Mapping symbols defined in a section define a sequence of
1241 half-open address intervals that cover the address range of the
1242 section. Each interval starts at the address defined by a
1243 mapping symbol, and continues up to, but not including, the
1244 address defined by the next (in address order) mapping symbol or
1245 the end of the section. A corollary is that there must be a
1246 mapping symbol defined at the beginning of each section.
1247 Consumers can ignore the size of a section-relative mapping
1248 symbol. Producers can set it to 0.
1250 Absolute mapping symbols
1252 Because of the need to crystallize a Thumb address with the
1253 Thumb-bit set, absolute symbol of type STT_FUNC (symbols of type
1254 STT_FUNC defined in section SHN_ABS) need to be mapped with $a
1257 The extent of a mapping symbol defined in SHN_ABS is [st_value,
1258 st_value + st_size), or [st_value, st_value + 1) if st_size = 0,
1259 where [x, y) denotes the half-open address range from x,
1260 inclusive, to y, exclusive.
1262 In the absence of a mapping symbol, a consumer can interpret a
1263 function symbol with an odd value as the Thumb code address
1264 obtained by clearing the least significant bit of the
1265 value. This interpretation is deprecated, and it may not work in
1268 Note - the Tagging symbols ($b, $f, $p $m) have been dropped from
1269 the EABI (which is still under development), so they are not
1270 implemented here. */
1272 static enum mstate mapstate
= MAP_UNDEFINED
;
1275 mapping_state (enum mstate state
)
1278 const char * symname
;
1281 if (mapstate
== state
)
1282 /* The mapping symbol has already been emitted.
1283 There is nothing else to do. */
1296 type
= BSF_FUNCTION
;
1300 type
= BSF_FUNCTION
;
1308 seg_info (now_seg
)->tc_segment_info_data
= state
;
1310 symbolP
= symbol_new (symname
, now_seg
, (valueT
) frag_now_fix (), frag_now
);
1311 symbol_table_insert (symbolP
);
1312 symbol_get_bfdsym (symbolP
)->flags
|= type
| BSF_LOCAL
;
1317 THUMB_SET_FUNC (symbolP
, 0);
1318 ARM_SET_THUMB (symbolP
, 0);
1319 ARM_SET_INTERWORK (symbolP
, support_interwork
);
1323 THUMB_SET_FUNC (symbolP
, 1);
1324 ARM_SET_THUMB (symbolP
, 1);
1325 ARM_SET_INTERWORK (symbolP
, support_interwork
);
1334 /* When we change sections we need to issue a new mapping symbol. */
1337 arm_elf_change_section (void)
1341 if (!SEG_NORMAL (now_seg
))
1344 flags
= bfd_get_section_flags (stdoutput
, now_seg
);
1346 /* We can ignore sections that only contain debug info. */
1347 if ((flags
& SEC_ALLOC
) == 0)
1350 mapstate
= seg_info (now_seg
)->tc_segment_info_data
;
1353 #define mapping_state(a)
1354 #endif /* OBJ_ELF */
1356 /* arm_reg_parse () := if it looks like a register, return its token and
1357 advance the pointer. */
1360 arm_reg_parse (char ** ccp
, struct hash_control
* htab
)
1362 char * start
= * ccp
;
1365 struct reg_entry
* reg
;
1367 #ifdef REGISTER_PREFIX
1368 if (*start
!= REGISTER_PREFIX
)
1373 #ifdef OPTIONAL_REGISTER_PREFIX
1374 if (*p
== OPTIONAL_REGISTER_PREFIX
)
1378 if (!ISALPHA (*p
) || !is_name_beginner (*p
))
1382 while (ISALPHA (c
) || ISDIGIT (c
) || c
== '_')
1386 reg
= (struct reg_entry
*) hash_find (htab
, start
);
1398 /* Search for the following register name in each of the possible reg name
1399 tables. Return the classification if found, or REG_TYPE_MAX if not
1402 static enum arm_reg_type
1403 arm_reg_parse_any (char *cp
)
1407 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
1408 if (arm_reg_parse (&cp
, all_reg_maps
[i
].htab
) != FAIL
)
1409 return (enum arm_reg_type
) i
;
1411 return REG_TYPE_MAX
;
1415 opcode_select (int width
)
1422 if (! (cpu_variant
& ARM_EXT_V4T
))
1423 as_bad (_("selected processor does not support THUMB opcodes"));
1426 /* No need to force the alignment, since we will have been
1427 coming from ARM mode, which is word-aligned. */
1428 record_alignment (now_seg
, 1);
1430 mapping_state (MAP_THUMB
);
1436 if ((cpu_variant
& ARM_ALL
) == ARM_EXT_V4T
)
1437 as_bad (_("selected processor does not support ARM opcodes"));
1442 frag_align (2, 0, 0);
1444 record_alignment (now_seg
, 1);
1446 mapping_state (MAP_ARM
);
1450 as_bad (_("invalid instruction size selected (%d)"), width
);
1455 s_req (int a ATTRIBUTE_UNUSED
)
1457 as_bad (_("invalid syntax for .req directive"));
1460 /* The .unreq directive deletes an alias which was previously defined
1461 by .req. For example:
1467 s_unreq (int a ATTRIBUTE_UNUSED
)
1472 skip_whitespace (input_line_pointer
);
1473 name
= input_line_pointer
;
1475 while (*input_line_pointer
!= 0
1476 && *input_line_pointer
!= ' '
1477 && *input_line_pointer
!= '\n')
1478 ++input_line_pointer
;
1480 saved_char
= *input_line_pointer
;
1481 *input_line_pointer
= 0;
1485 enum arm_reg_type req_type
= arm_reg_parse_any (name
);
1487 if (req_type
!= REG_TYPE_MAX
)
1489 char *temp_name
= name
;
1490 int req_no
= arm_reg_parse (&temp_name
, all_reg_maps
[req_type
].htab
);
1494 struct reg_entry
*req_entry
;
1496 /* Check to see if this alias is a builtin one. */
1497 req_entry
= hash_delete (all_reg_maps
[req_type
].htab
, name
);
1500 as_bad (_("unreq: missing hash entry for \"%s\""), name
);
1501 else if (req_entry
->builtin
)
1502 /* FIXME: We are deleting a built in register alias which
1503 points to a const data structure, so we only need to
1504 free up the memory used by the key in the hash table.
1505 Unfortunately we have not recorded this value, so this
1506 is a memory leak. */
1507 /* FIXME: Should we issue a warning message ? */
1511 /* Deleting a user defined alias. We need to free the
1512 key and the value, but fortunately the key is the same
1513 as the value->name field. */
1514 free ((char *) req_entry
->name
);
1519 as_bad (_(".unreq: unrecognized symbol \"%s\""), name
);
1522 as_bad (_(".unreq: unrecognized symbol \"%s\""), name
);
1525 as_bad (_("invalid syntax for .unreq directive"));
1527 *input_line_pointer
= saved_char
;
1528 demand_empty_rest_of_line ();
1532 s_bss (int ignore ATTRIBUTE_UNUSED
)
1534 /* We don't support putting frags in the BSS segment, we fake it by
1535 marking in_bss, then looking at s_skip for clues. */
1536 subseg_set (bss_section
, 0);
1537 demand_empty_rest_of_line ();
1538 mapping_state (MAP_DATA
);
1542 s_even (int ignore ATTRIBUTE_UNUSED
)
1544 /* Never make frag if expect extra pass. */
1546 frag_align (1, 0, 0);
1548 record_alignment (now_seg
, 1);
1550 demand_empty_rest_of_line ();
1554 s_ltorg (int ignored ATTRIBUTE_UNUSED
)
1557 literal_pool
* pool
;
1560 pool
= find_literal_pool ();
1562 || pool
->symbol
== NULL
1563 || pool
->next_free_entry
== 0)
1566 mapping_state (MAP_DATA
);
1568 /* Align pool as you have word accesses.
1569 Only make a frag if we have to. */
1571 frag_align (2, 0, 0);
1573 record_alignment (now_seg
, 2);
1575 sprintf (sym_name
, "$$lit_\002%x", pool
->id
);
1577 symbol_locate (pool
->symbol
, sym_name
, now_seg
,
1578 (valueT
) frag_now_fix (), frag_now
);
1579 symbol_table_insert (pool
->symbol
);
1581 ARM_SET_THUMB (pool
->symbol
, thumb_mode
);
1583 #if defined OBJ_COFF || defined OBJ_ELF
1584 ARM_SET_INTERWORK (pool
->symbol
, support_interwork
);
1587 for (entry
= 0; entry
< pool
->next_free_entry
; entry
++)
1588 /* First output the expression in the instruction to the pool. */
1589 emit_expr (&(pool
->literals
[entry
]), 4); /* .word */
1591 /* Mark the pool as empty. */
1592 pool
->next_free_entry
= 0;
1593 pool
->symbol
= NULL
;
1596 /* Same as s_align_ptwo but align 0 => align 2. */
1599 s_align (int unused ATTRIBUTE_UNUSED
)
1603 long max_alignment
= 15;
1605 temp
= get_absolute_expression ();
1606 if (temp
> max_alignment
)
1607 as_bad (_("alignment too large: %d assumed"), temp
= max_alignment
);
1610 as_bad (_("alignment negative. 0 assumed."));
1614 if (*input_line_pointer
== ',')
1616 input_line_pointer
++;
1617 temp_fill
= get_absolute_expression ();
1625 /* Only make a frag if we HAVE to. */
1626 if (temp
&& !need_pass_2
)
1627 frag_align (temp
, (int) temp_fill
, 0);
1628 demand_empty_rest_of_line ();
1630 record_alignment (now_seg
, temp
);
1634 s_force_thumb (int ignore ATTRIBUTE_UNUSED
)
1636 /* If we are not already in thumb mode go into it, EVEN if
1637 the target processor does not support thumb instructions.
1638 This is used by gcc/config/arm/lib1funcs.asm for example
1639 to compile interworking support functions even if the
1640 target processor should not support interworking. */
1645 record_alignment (now_seg
, 1);
1648 demand_empty_rest_of_line ();
1652 s_thumb_func (int ignore ATTRIBUTE_UNUSED
)
1657 /* The following label is the name/address of the start of a Thumb function.
1658 We need to know this for the interworking support. */
1659 label_is_thumb_function_name
= TRUE
;
1661 demand_empty_rest_of_line ();
1664 /* Perform a .set directive, but also mark the alias as
1665 being a thumb function. */
1668 s_thumb_set (int equiv
)
1670 /* XXX the following is a duplicate of the code for s_set() in read.c
1671 We cannot just call that code as we need to get at the symbol that
1678 /* Especial apologies for the random logic:
1679 This just grew, and could be parsed much more simply!
1681 name
= input_line_pointer
;
1682 delim
= get_symbol_end ();
1683 end_name
= input_line_pointer
;
1688 if (*input_line_pointer
!= ',')
1691 as_bad (_("expected comma after name \"%s\""), name
);
1693 ignore_rest_of_line ();
1697 input_line_pointer
++;
1700 if (name
[0] == '.' && name
[1] == '\0')
1702 /* XXX - this should not happen to .thumb_set. */
1706 if ((symbolP
= symbol_find (name
)) == NULL
1707 && (symbolP
= md_undefined_symbol (name
)) == NULL
)
1710 /* When doing symbol listings, play games with dummy fragments living
1711 outside the normal fragment chain to record the file and line info
1713 if (listing
& LISTING_SYMBOLS
)
1715 extern struct list_info_struct
* listing_tail
;
1716 fragS
* dummy_frag
= xmalloc (sizeof (fragS
));
1718 memset (dummy_frag
, 0, sizeof (fragS
));
1719 dummy_frag
->fr_type
= rs_fill
;
1720 dummy_frag
->line
= listing_tail
;
1721 symbolP
= symbol_new (name
, undefined_section
, 0, dummy_frag
);
1722 dummy_frag
->fr_symbol
= symbolP
;
1726 symbolP
= symbol_new (name
, undefined_section
, 0, &zero_address_frag
);
1729 /* "set" symbols are local unless otherwise specified. */
1730 SF_SET_LOCAL (symbolP
);
1731 #endif /* OBJ_COFF */
1732 } /* Make a new symbol. */
1734 symbol_table_insert (symbolP
);
1739 && S_IS_DEFINED (symbolP
)
1740 && S_GET_SEGMENT (symbolP
) != reg_section
)
1741 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP
));
1743 pseudo_set (symbolP
);
1745 demand_empty_rest_of_line ();
1747 /* XXX Now we come to the Thumb specific bit of code. */
1749 THUMB_SET_FUNC (symbolP
, 1);
1750 ARM_SET_THUMB (symbolP
, 1);
1751 #if defined OBJ_ELF || defined OBJ_COFF
1752 ARM_SET_INTERWORK (symbolP
, support_interwork
);
1757 s_arm (int ignore ATTRIBUTE_UNUSED
)
1760 demand_empty_rest_of_line ();
1764 s_thumb (int ignore ATTRIBUTE_UNUSED
)
1767 demand_empty_rest_of_line ();
1771 s_code (int unused ATTRIBUTE_UNUSED
)
1775 temp
= get_absolute_expression ();
1780 opcode_select (temp
);
1784 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp
);
1789 end_of_line (char * str
)
1791 skip_whitespace (str
);
1793 if (*str
!= '\0' && !inst
.error
)
1794 inst
.error
= _("garbage following instruction");
1798 skip_past_comma (char ** str
)
1800 char * p
= * str
, c
;
1803 while ((c
= *p
) == ' ' || c
== ',')
1806 if (c
== ',' && comma
++)
1814 return comma
? SUCCESS
: FAIL
;
1817 /* Return TRUE if anything in the expression is a bignum. */
1820 walk_no_bignums (symbolS
* sp
)
1822 if (symbol_get_value_expression (sp
)->X_op
== O_big
)
1825 if (symbol_get_value_expression (sp
)->X_add_symbol
)
1827 return (walk_no_bignums (symbol_get_value_expression (sp
)->X_add_symbol
)
1828 || (symbol_get_value_expression (sp
)->X_op_symbol
1829 && walk_no_bignums (symbol_get_value_expression (sp
)->X_op_symbol
)));
1835 static int in_my_get_expression
= 0;
1838 my_get_expression (expressionS
* ep
, char ** str
)
1843 save_in
= input_line_pointer
;
1844 input_line_pointer
= *str
;
1845 in_my_get_expression
= 1;
1846 seg
= expression (ep
);
1847 in_my_get_expression
= 0;
1849 if (ep
->X_op
== O_illegal
)
1851 /* We found a bad expression in md_operand(). */
1852 *str
= input_line_pointer
;
1853 input_line_pointer
= save_in
;
1858 if (seg
!= absolute_section
1859 && seg
!= text_section
1860 && seg
!= data_section
1861 && seg
!= bss_section
1862 && seg
!= undefined_section
)
1864 inst
.error
= _("bad_segment");
1865 *str
= input_line_pointer
;
1866 input_line_pointer
= save_in
;
1871 /* Get rid of any bignums now, so that we don't generate an error for which
1872 we can't establish a line number later on. Big numbers are never valid
1873 in instructions, which is where this routine is always called. */
1874 if (ep
->X_op
== O_big
1875 || (ep
->X_add_symbol
1876 && (walk_no_bignums (ep
->X_add_symbol
)
1878 && walk_no_bignums (ep
->X_op_symbol
)))))
1880 inst
.error
= _("invalid constant");
1881 *str
= input_line_pointer
;
1882 input_line_pointer
= save_in
;
1886 *str
= input_line_pointer
;
1887 input_line_pointer
= save_in
;
1891 /* A standard register must be given at this point.
1892 SHIFT is the place to put it in inst.instruction.
1893 Restores input start point on error.
1894 Returns the reg#, or FAIL. */
1897 reg_required_here (char ** str
, int shift
)
1899 static char buff
[128]; /* XXX */
1901 char * start
= * str
;
1903 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_RN
].htab
)) != FAIL
)
1906 inst
.instruction
|= reg
<< shift
;
1910 /* Restore the start point, we may have got a reg of the wrong class. */
1913 /* In the few cases where we might be able to accept something else
1914 this error can be overridden. */
1915 sprintf (buff
, _("register expected, not '%.100s'"), start
);
1921 /* A Intel Wireless MMX technology register
1922 must be given at this point.
1923 Shift is the place to put it in inst.instruction.
1924 Restores input start point on err.
1925 Returns the reg#, or FAIL. */
1928 wreg_required_here (char ** str
,
1930 enum wreg_type reg_type
)
1932 static char buff
[128];
1934 char * start
= *str
;
1936 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_IWMMXT
].htab
)) != FAIL
)
1938 if (wr_register (reg
)
1939 && (reg_type
== IWMMXT_REG_WR
|| reg_type
== IWMMXT_REG_WR_OR_WC
))
1942 inst
.instruction
|= (reg
^ WR_PREFIX
) << shift
;
1945 else if (wc_register (reg
)
1946 && (reg_type
== IWMMXT_REG_WC
|| reg_type
== IWMMXT_REG_WR_OR_WC
))
1949 inst
.instruction
|= (reg
^ WC_PREFIX
) << shift
;
1952 else if ((wcg_register (reg
) && reg_type
== IWMMXT_REG_WCG
))
1955 inst
.instruction
|= ((reg
^ WC_PREFIX
) - 8) << shift
;
1960 /* Restore the start point, we may have got a reg of the wrong class. */
1963 /* In the few cases where we might be able to accept
1964 something else this error can be overridden. */
1965 sprintf (buff
, _("Intel Wireless MMX technology register expected, not '%.100s'"), start
);
1971 static const struct asm_psr
*
1972 arm_psr_parse (char ** ccp
)
1974 char * start
= * ccp
;
1977 const struct asm_psr
* psr
;
1981 /* Skip to the end of the next word in the input stream. */
1986 while (ISALPHA (c
) || c
== '_');
1988 /* Terminate the word. */
1991 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
1992 feature for ease of use and backwards compatibility. */
1993 if (!strncmp (start
, "cpsr", 4))
1994 strncpy (start
, "CPSR", 4);
1995 else if (!strncmp (start
, "spsr", 4))
1996 strncpy (start
, "SPSR", 4);
1998 /* Now locate the word in the psr hash table. */
1999 psr
= (const struct asm_psr
*) hash_find (arm_psr_hsh
, start
);
2001 /* Restore the input stream. */
2004 /* If we found a valid match, advance the
2005 stream pointer past the end of the word. */
2011 /* Parse the input looking for a PSR flag. */
2014 psr_required_here (char ** str
)
2016 char * start
= * str
;
2017 const struct asm_psr
* psr
;
2019 psr
= arm_psr_parse (str
);
2023 /* If this is the SPSR that is being modified, set the R bit. */
2025 inst
.instruction
|= SPSR_BIT
;
2027 /* Set the psr flags in the MSR instruction. */
2028 inst
.instruction
|= psr
->field
<< PSR_SHIFT
;
2033 /* In the few cases where we might be able to accept
2034 something else this error can be overridden. */
2035 inst
.error
= _("flag for {c}psr instruction expected");
2037 /* Restore the start point. */
2043 co_proc_number (char ** str
)
2045 int processor
, pchar
;
2048 skip_whitespace (*str
);
2051 /* The data sheet seems to imply that just a number on its own is valid
2052 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
2054 if ((processor
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CP
].htab
))
2060 if (pchar
>= '0' && pchar
<= '9')
2062 processor
= pchar
- '0';
2063 if (**str
>= '0' && **str
<= '9')
2065 processor
= processor
* 10 + *(*str
)++ - '0';
2068 inst
.error
= _("illegal co-processor number");
2075 inst
.error
= all_reg_maps
[REG_TYPE_CP
].expected
;
2080 inst
.instruction
|= processor
<< 8;
2085 cp_opc_expr (char ** str
, int where
, int length
)
2089 skip_whitespace (* str
);
2091 memset (&expr
, '\0', sizeof (expr
));
2093 if (my_get_expression (&expr
, str
))
2095 if (expr
.X_op
!= O_constant
)
2097 inst
.error
= _("bad or missing expression");
2101 if ((expr
.X_add_number
& ((1 << length
) - 1)) != expr
.X_add_number
)
2103 inst
.error
= _("immediate co-processor expression too large");
2107 inst
.instruction
|= expr
.X_add_number
<< where
;
2112 cp_reg_required_here (char ** str
, int where
)
2115 char * start
= *str
;
2117 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CN
].htab
)) != FAIL
)
2119 inst
.instruction
|= reg
<< where
;
2123 /* In the few cases where we might be able to accept something else
2124 this error can be overridden. */
2125 inst
.error
= all_reg_maps
[REG_TYPE_CN
].expected
;
2127 /* Restore the start point. */
2133 fp_reg_required_here (char ** str
, int where
)
2136 char * start
= * str
;
2138 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_FN
].htab
)) != FAIL
)
2140 inst
.instruction
|= reg
<< where
;
2144 /* In the few cases where we might be able to accept something else
2145 this error can be overridden. */
2146 inst
.error
= all_reg_maps
[REG_TYPE_FN
].expected
;
2148 /* Restore the start point. */
2154 cp_address_offset (char ** str
)
2158 skip_whitespace (* str
);
2160 if (! is_immediate_prefix (**str
))
2162 inst
.error
= _("immediate expression expected");
2168 if (my_get_expression (& inst
.reloc
.exp
, str
))
2171 if (inst
.reloc
.exp
.X_op
== O_constant
)
2173 offset
= inst
.reloc
.exp
.X_add_number
;
2177 inst
.error
= _("co-processor address must be word aligned");
2181 if (offset
> 1023 || offset
< -1023)
2183 inst
.error
= _("offset too large");
2188 inst
.instruction
|= INDEX_UP
;
2192 inst
.instruction
|= offset
>> 2;
2195 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
2201 cp_address_required_here (char ** str
, int wb_ok
)
2212 skip_whitespace (p
);
2214 if ((reg
= reg_required_here (& p
, 16)) == FAIL
)
2217 skip_whitespace (p
);
2223 skip_whitespace (p
);
2227 /* As an extension to the official ARM syntax we allow:
2229 as a short hand for:
2231 inst
.instruction
|= PRE_INDEX
| INDEX_UP
;
2236 if (skip_past_comma (& p
) == FAIL
)
2238 inst
.error
= _("comma expected after closing square bracket");
2242 skip_whitespace (p
);
2249 write_back
= WRITE_BACK
;
2253 inst
.error
= _("pc may not be used in post-increment");
2257 if (cp_address_offset (& p
) == FAIL
)
2261 pre_inc
= PRE_INDEX
| INDEX_UP
;
2267 /* [Rn], {<expr>} */
2270 skip_whitespace (p
);
2272 if (my_get_expression (& inst
.reloc
.exp
, & p
))
2275 if (inst
.reloc
.exp
.X_op
== O_constant
)
2277 option
= inst
.reloc
.exp
.X_add_number
;
2279 if (option
> 255 || option
< 0)
2281 inst
.error
= _("'option' field too large");
2285 skip_whitespace (p
);
2289 inst
.error
= _("'}' expected at end of 'option' field");
2295 inst
.instruction
|= option
;
2296 inst
.instruction
|= INDEX_UP
;
2301 inst
.error
= _("non-constant expressions for 'option' field not supported");
2307 inst
.error
= _("# or { expected after comma");
2313 /* '['Rn, #expr']'[!] */
2315 if (skip_past_comma (& p
) == FAIL
)
2317 inst
.error
= _("pre-indexed expression expected");
2321 pre_inc
= PRE_INDEX
;
2323 if (cp_address_offset (& p
) == FAIL
)
2326 skip_whitespace (p
);
2330 inst
.error
= _("missing ]");
2334 skip_whitespace (p
);
2336 if (wb_ok
&& *p
== '!')
2340 inst
.error
= _("pc may not be used with write-back");
2345 write_back
= WRITE_BACK
;
2351 if (my_get_expression (&inst
.reloc
.exp
, &p
))
2354 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
2355 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
2356 inst
.reloc
.pc_rel
= 1;
2357 inst
.instruction
|= (REG_PC
<< 16);
2358 pre_inc
= PRE_INDEX
;
2361 inst
.instruction
|= write_back
| pre_inc
;
2367 cp_byte_address_offset (char ** str
)
2371 skip_whitespace (* str
);
2373 if (! is_immediate_prefix (**str
))
2375 inst
.error
= _("immediate expression expected");
2381 if (my_get_expression (& inst
.reloc
.exp
, str
))
2384 if (inst
.reloc
.exp
.X_op
== O_constant
)
2386 offset
= inst
.reloc
.exp
.X_add_number
;
2388 if (offset
> 255 || offset
< -255)
2390 inst
.error
= _("offset too large");
2395 inst
.instruction
|= INDEX_UP
;
2399 inst
.instruction
|= offset
;
2402 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM_S2
;
2408 cp_byte_address_required_here (char ** str
)
2419 skip_whitespace (p
);
2421 if ((reg
= reg_required_here (& p
, 16)) == FAIL
)
2424 skip_whitespace (p
);
2430 if (skip_past_comma (& p
) == SUCCESS
)
2433 write_back
= WRITE_BACK
;
2437 inst
.error
= _("pc may not be used in post-increment");
2441 if (cp_byte_address_offset (& p
) == FAIL
)
2445 pre_inc
= PRE_INDEX
| INDEX_UP
;
2449 /* '['Rn, #expr']'[!] */
2451 if (skip_past_comma (& p
) == FAIL
)
2453 inst
.error
= _("pre-indexed expression expected");
2457 pre_inc
= PRE_INDEX
;
2459 if (cp_byte_address_offset (& p
) == FAIL
)
2462 skip_whitespace (p
);
2466 inst
.error
= _("missing ]");
2470 skip_whitespace (p
);
2476 inst
.error
= _("pc may not be used with write-back");
2481 write_back
= WRITE_BACK
;
2487 if (my_get_expression (&inst
.reloc
.exp
, &p
))
2490 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM_S2
;
2491 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
2492 inst
.reloc
.pc_rel
= 1;
2493 inst
.instruction
|= (REG_PC
<< 16);
2494 pre_inc
= PRE_INDEX
;
2497 inst
.instruction
|= write_back
| pre_inc
;
2503 do_empty (char * str
)
2505 /* Do nothing really. */
2514 /* Only one syntax. */
2515 skip_whitespace (str
);
2517 if (reg_required_here (&str
, 12) == FAIL
)
2519 inst
.error
= BAD_ARGS
;
2523 if (skip_past_comma (&str
) == FAIL
)
2525 inst
.error
= _("comma expected after register name");
2529 skip_whitespace (str
);
2531 if ( streq (str
, "CPSR")
2532 || streq (str
, "SPSR")
2533 /* Lower case versions for backwards compatibility. */
2534 || streq (str
, "cpsr")
2535 || streq (str
, "spsr"))
2538 /* This is for backwards compatibility with older toolchains. */
2539 else if ( streq (str
, "cpsr_all")
2540 || streq (str
, "spsr_all"))
2544 inst
.error
= _("CPSR or SPSR expected");
2548 if (* str
== 's' || * str
== 'S')
2549 inst
.instruction
|= SPSR_BIT
;
2555 /* Two possible forms:
2556 "{C|S}PSR_<field>, Rm",
2557 "{C|S}PSR_f, #expression". */
2562 skip_whitespace (str
);
2564 if (psr_required_here (& str
) == FAIL
)
2567 if (skip_past_comma (& str
) == FAIL
)
2569 inst
.error
= _("comma missing after psr flags");
2573 skip_whitespace (str
);
2575 if (reg_required_here (& str
, 0) != FAIL
)
2582 if (! is_immediate_prefix (* str
))
2585 _("only a register or immediate value can follow a psr flag");
2592 if (my_get_expression (& inst
.reloc
.exp
, & str
))
2595 _("only a register or immediate value can follow a psr flag");
2599 #if 0 /* The first edition of the ARM architecture manual stated that
2600 writing anything other than the flags with an immediate operation
2601 had UNPREDICTABLE effects. This constraint was removed in the
2602 second edition of the specification. */
2603 if ((cpu_variant
& ARM_EXT_V5
) != ARM_EXT_V5
2604 && inst
.instruction
& ((PSR_c
| PSR_x
| PSR_s
) << PSR_SHIFT
))
2606 inst
.error
= _("immediate value cannot be used to set this field");
2611 inst
.instruction
|= INST_IMMEDIATE
;
2613 if (inst
.reloc
.exp
.X_add_symbol
)
2615 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
2616 inst
.reloc
.pc_rel
= 0;
2620 unsigned value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
2622 if (value
== (unsigned) FAIL
)
2624 inst
.error
= _("invalid constant");
2628 inst
.instruction
|= value
;
2635 /* Long Multiply Parser
2636 UMULL RdLo, RdHi, Rm, Rs
2637 SMULL RdLo, RdHi, Rm, Rs
2638 UMLAL RdLo, RdHi, Rm, Rs
2639 SMLAL RdLo, RdHi, Rm, Rs. */
2642 do_mull (char * str
)
2644 int rdlo
, rdhi
, rm
, rs
;
2646 /* Only one format "rdlo, rdhi, rm, rs". */
2647 skip_whitespace (str
);
2649 if ((rdlo
= reg_required_here (&str
, 12)) == FAIL
)
2651 inst
.error
= BAD_ARGS
;
2655 if (skip_past_comma (&str
) == FAIL
2656 || (rdhi
= reg_required_here (&str
, 16)) == FAIL
)
2658 inst
.error
= BAD_ARGS
;
2662 if (skip_past_comma (&str
) == FAIL
2663 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
2665 inst
.error
= BAD_ARGS
;
2669 /* rdhi, rdlo and rm must all be different. */
2670 if (rdlo
== rdhi
|| rdlo
== rm
|| rdhi
== rm
)
2671 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
2673 if (skip_past_comma (&str
) == FAIL
2674 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
2676 inst
.error
= BAD_ARGS
;
2680 if (rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
)
2682 inst
.error
= BAD_PC
;
2694 /* Only one format "rd, rm, rs". */
2695 skip_whitespace (str
);
2697 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
2699 inst
.error
= BAD_ARGS
;
2705 inst
.error
= BAD_PC
;
2709 if (skip_past_comma (&str
) == FAIL
2710 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
2712 inst
.error
= BAD_ARGS
;
2718 inst
.error
= BAD_PC
;
2723 as_tsktsk (_("rd and rm should be different in mul"));
2725 if (skip_past_comma (&str
) == FAIL
2726 || (rm
= reg_required_here (&str
, 8)) == FAIL
)
2728 inst
.error
= BAD_ARGS
;
2734 inst
.error
= BAD_PC
;
2746 /* Only one format "rd, rm, rs, rn". */
2747 skip_whitespace (str
);
2749 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
2751 inst
.error
= BAD_ARGS
;
2757 inst
.error
= BAD_PC
;
2761 if (skip_past_comma (&str
) == FAIL
2762 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
2764 inst
.error
= BAD_ARGS
;
2770 inst
.error
= BAD_PC
;
2775 as_tsktsk (_("rd and rm should be different in mla"));
2777 if (skip_past_comma (&str
) == FAIL
2778 || (rd
= reg_required_here (&str
, 8)) == FAIL
2779 || skip_past_comma (&str
) == FAIL
2780 || (rm
= reg_required_here (&str
, 12)) == FAIL
)
2782 inst
.error
= BAD_ARGS
;
2786 if (rd
== REG_PC
|| rm
== REG_PC
)
2788 inst
.error
= BAD_PC
;
2795 /* Expects *str -> the characters "acc0", possibly with leading blanks.
2796 Advances *str to the next non-alphanumeric.
2797 Returns 0, or else FAIL (in which case sets inst.error).
2799 (In a future XScale, there may be accumulators other than zero.
2800 At that time this routine and its callers can be upgraded to suit.) */
2803 accum0_required_here (char ** str
)
2805 static char buff
[128]; /* Note the address is taken. Hence, static. */
2808 int result
= 0; /* The accum number. */
2810 skip_whitespace (p
);
2812 *str
= p
; /* Advance caller's string pointer too. */
2817 *--p
= 0; /* Aap nul into input buffer at non-alnum. */
2819 if (! ( streq (*str
, "acc0") || streq (*str
, "ACC0")))
2821 sprintf (buff
, _("acc0 expected, not '%.100s'"), *str
);
2826 *p
= c
; /* Unzap. */
2827 *str
= p
; /* Caller's string pointer to after match. */
2832 ldst_extend_v4 (char ** str
)
2841 if (my_get_expression (& inst
.reloc
.exp
, str
))
2844 if (inst
.reloc
.exp
.X_op
== O_constant
)
2846 int value
= inst
.reloc
.exp
.X_add_number
;
2848 if (value
< -255 || value
> 255)
2850 inst
.error
= _("address offset too large");
2860 /* Halfword and signextension instructions have the
2861 immediate value split across bits 11..8 and bits 3..0. */
2862 inst
.instruction
|= (add
| HWOFFSET_IMM
2863 | ((value
>> 4) << 8) | (value
& 0xF));
2867 inst
.instruction
|= HWOFFSET_IMM
;
2868 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
2869 inst
.reloc
.pc_rel
= 0;
2882 if (reg_required_here (str
, 0) == FAIL
)
2885 inst
.instruction
|= add
;
2890 /* Expects **str -> after a comma. May be leading blanks.
2891 Advances *str, recognizing a load mode, and setting inst.instruction.
2892 Returns rn, or else FAIL (in which case may set inst.error
2893 and not advance str)
2895 Note: doesn't know Rd, so no err checks that require such knowledge. */
2898 ld_mode_required_here (char ** string
)
2900 char * str
= * string
;
2904 skip_whitespace (str
);
2910 skip_whitespace (str
);
2912 if ((rn
= reg_required_here (& str
, 16)) == FAIL
)
2915 skip_whitespace (str
);
2921 if (skip_past_comma (& str
) == SUCCESS
)
2923 /* [Rn],... (post inc) */
2924 if (ldst_extend_v4 (&str
) == FAIL
)
2929 skip_whitespace (str
);
2934 inst
.instruction
|= WRITE_BACK
;
2937 inst
.instruction
|= INDEX_UP
| HWOFFSET_IMM
;
2943 if (skip_past_comma (& str
) == FAIL
)
2945 inst
.error
= _("pre-indexed expression expected");
2951 if (ldst_extend_v4 (&str
) == FAIL
)
2954 skip_whitespace (str
);
2956 if (* str
++ != ']')
2958 inst
.error
= _("missing ]");
2962 skip_whitespace (str
);
2967 inst
.instruction
|= WRITE_BACK
;
2971 else if (* str
== '=') /* ldr's "r,=label" syntax */
2972 /* We should never reach here, because <text> = <expression> is
2973 caught gas/read.c read_a_source_file() as a .set operation. */
2975 else /* PC +- 8 bit immediate offset. */
2977 if (my_get_expression (& inst
.reloc
.exp
, & str
))
2980 inst
.instruction
|= HWOFFSET_IMM
; /* The I bit. */
2981 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
2982 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
2983 inst
.reloc
.pc_rel
= 1;
2984 inst
.instruction
|= (REG_PC
<< 16);
2990 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
2996 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
2997 SMLAxy{cond} Rd,Rm,Rs,Rn
2998 SMLAWy{cond} Rd,Rm,Rs,Rn
2999 Error if any register is R15. */
3002 do_smla (char * str
)
3006 skip_whitespace (str
);
3008 if ((rd
= reg_required_here (& str
, 16)) == FAIL
3009 || skip_past_comma (& str
) == FAIL
3010 || (rm
= reg_required_here (& str
, 0)) == FAIL
3011 || skip_past_comma (& str
) == FAIL
3012 || (rs
= reg_required_here (& str
, 8)) == FAIL
3013 || skip_past_comma (& str
) == FAIL
3014 || (rn
= reg_required_here (& str
, 12)) == FAIL
)
3015 inst
.error
= BAD_ARGS
;
3017 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
|| rn
== REG_PC
)
3018 inst
.error
= BAD_PC
;
3024 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
3025 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
3026 Error if any register is R15.
3027 Warning if Rdlo == Rdhi. */
3030 do_smlal (char * str
)
3032 int rdlo
, rdhi
, rm
, rs
;
3034 skip_whitespace (str
);
3036 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
3037 || skip_past_comma (& str
) == FAIL
3038 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
3039 || skip_past_comma (& str
) == FAIL
3040 || (rm
= reg_required_here (& str
, 0)) == FAIL
3041 || skip_past_comma (& str
) == FAIL
3042 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
3044 inst
.error
= BAD_ARGS
;
3048 if (rdlo
== REG_PC
|| rdhi
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
3050 inst
.error
= BAD_PC
;
3055 as_tsktsk (_("rdhi and rdlo must be different"));
3060 /* ARM V5E (El Segundo) signed-multiply (argument parse)
3061 SMULxy{cond} Rd,Rm,Rs
3062 Error if any register is R15. */
3065 do_smul (char * str
)
3069 skip_whitespace (str
);
3071 if ((rd
= reg_required_here (& str
, 16)) == FAIL
3072 || skip_past_comma (& str
) == FAIL
3073 || (rm
= reg_required_here (& str
, 0)) == FAIL
3074 || skip_past_comma (& str
) == FAIL
3075 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
3076 inst
.error
= BAD_ARGS
;
3078 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
3079 inst
.error
= BAD_PC
;
3085 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
3086 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
3087 Error if any register is R15. */
3090 do_qadd (char * str
)
3094 skip_whitespace (str
);
3096 if ((rd
= reg_required_here (& str
, 12)) == FAIL
3097 || skip_past_comma (& str
) == FAIL
3098 || (rm
= reg_required_here (& str
, 0)) == FAIL
3099 || skip_past_comma (& str
) == FAIL
3100 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
3101 inst
.error
= BAD_ARGS
;
3103 else if (rd
== REG_PC
|| rm
== REG_PC
|| rn
== REG_PC
)
3104 inst
.error
= BAD_PC
;
3110 /* ARM V5E (el Segundo)
3111 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3112 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3114 These are equivalent to the XScale instructions MAR and MRA,
3115 respectively, when coproc == 0, opcode == 0, and CRm == 0.
3117 Result unpredicatable if Rd or Rn is R15. */
3120 do_co_reg2c (char * str
)
3124 skip_whitespace (str
);
3126 if (co_proc_number (& str
) == FAIL
)
3129 inst
.error
= BAD_ARGS
;
3133 if (skip_past_comma (& str
) == FAIL
3134 || cp_opc_expr (& str
, 4, 4) == FAIL
)
3137 inst
.error
= BAD_ARGS
;
3141 if (skip_past_comma (& str
) == FAIL
3142 || (rd
= reg_required_here (& str
, 12)) == FAIL
)
3145 inst
.error
= BAD_ARGS
;
3149 if (skip_past_comma (& str
) == FAIL
3150 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
3153 inst
.error
= BAD_ARGS
;
3157 /* Unpredictable result if rd or rn is R15. */
3158 if (rd
== REG_PC
|| rn
== REG_PC
)
3160 (_("Warning: instruction unpredictable when using r15"));
3162 if (skip_past_comma (& str
) == FAIL
3163 || cp_reg_required_here (& str
, 0) == FAIL
)
3166 inst
.error
= BAD_ARGS
;
3173 /* ARM V5 count-leading-zeroes instruction (argument parse)
3174 CLZ{<cond>} <Rd>, <Rm>
3175 Condition defaults to COND_ALWAYS.
3176 Error if Rd or Rm are R15. */
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 inst
.error
= BAD_ARGS
;
3190 else if (rd
== REG_PC
|| rm
== REG_PC
)
3191 inst
.error
= BAD_PC
;
3197 /* ARM V5 (argument parse)
3198 LDC2{L} <coproc>, <CRd>, <addressing mode>
3199 STC2{L} <coproc>, <CRd>, <addressing mode>
3200 Instruction is not conditional, and has 0xf in the condition field.
3201 Otherwise, it's the same as LDC/STC. */
3204 do_lstc2 (char * str
)
3206 skip_whitespace (str
);
3208 if (co_proc_number (& str
) == FAIL
)
3211 inst
.error
= BAD_ARGS
;
3213 else if (skip_past_comma (& str
) == FAIL
3214 || cp_reg_required_here (& str
, 12) == FAIL
)
3217 inst
.error
= BAD_ARGS
;
3219 else if (skip_past_comma (& str
) == FAIL
3220 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
3223 inst
.error
= BAD_ARGS
;
3229 /* ARM V5 (argument parse)
3230 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
3231 Instruction is not conditional, and has 0xf in the condition field.
3232 Otherwise, it's the same as CDP. */
3235 do_cdp2 (char * str
)
3237 skip_whitespace (str
);
3239 if (co_proc_number (& str
) == FAIL
)
3242 inst
.error
= BAD_ARGS
;
3246 if (skip_past_comma (& str
) == FAIL
3247 || cp_opc_expr (& str
, 20,4) == FAIL
)
3250 inst
.error
= BAD_ARGS
;
3254 if (skip_past_comma (& str
) == FAIL
3255 || cp_reg_required_here (& str
, 12) == FAIL
)
3258 inst
.error
= BAD_ARGS
;
3262 if (skip_past_comma (& str
) == FAIL
3263 || cp_reg_required_here (& str
, 16) == FAIL
)
3266 inst
.error
= BAD_ARGS
;
3270 if (skip_past_comma (& str
) == FAIL
3271 || cp_reg_required_here (& str
, 0) == FAIL
)
3274 inst
.error
= BAD_ARGS
;
3278 if (skip_past_comma (& str
) == SUCCESS
)
3280 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
3283 inst
.error
= BAD_ARGS
;
3291 /* ARM V5 (argument parse)
3292 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3293 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3294 Instruction is not conditional, and has 0xf in the condition field.
3295 Otherwise, it's the same as MCR/MRC. */
3298 do_co_reg2 (char * str
)
3300 skip_whitespace (str
);
3302 if (co_proc_number (& str
) == FAIL
)
3305 inst
.error
= BAD_ARGS
;
3309 if (skip_past_comma (& str
) == FAIL
3310 || cp_opc_expr (& str
, 21, 3) == FAIL
)
3313 inst
.error
= BAD_ARGS
;
3317 if (skip_past_comma (& str
) == FAIL
3318 || reg_required_here (& str
, 12) == FAIL
)
3321 inst
.error
= BAD_ARGS
;
3325 if (skip_past_comma (& str
) == FAIL
3326 || cp_reg_required_here (& str
, 16) == FAIL
)
3329 inst
.error
= BAD_ARGS
;
3333 if (skip_past_comma (& str
) == FAIL
3334 || cp_reg_required_here (& str
, 0) == FAIL
)
3337 inst
.error
= BAD_ARGS
;
3341 if (skip_past_comma (& str
) == SUCCESS
)
3343 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
3346 inst
.error
= BAD_ARGS
;
3359 skip_whitespace (str
);
3361 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
3363 inst
.error
= BAD_ARGS
;
3367 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
3369 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
3374 /* ARM v5TEJ. Jump to Jazelle code. */
3381 skip_whitespace (str
);
3383 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
3385 inst
.error
= BAD_ARGS
;
3389 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
3391 as_tsktsk (_("use of r15 in bxj is not really useful"));
3396 /* ARM V6 umaal (argument parse). */
3399 do_umaal (char * str
)
3401 int rdlo
, rdhi
, rm
, rs
;
3403 skip_whitespace (str
);
3404 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
3405 || skip_past_comma (& str
) == FAIL
3406 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
3407 || skip_past_comma (& str
) == FAIL
3408 || (rm
= reg_required_here (& str
, 0)) == FAIL
3409 || skip_past_comma (& str
) == FAIL
3410 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
3412 inst
.error
= BAD_ARGS
;
3416 if (rdlo
== REG_PC
|| rdhi
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
3418 inst
.error
= BAD_PC
;
3425 /* ARM V6 strex (argument parse). */
3428 do_strex (char * str
)
3432 /* Parse Rd, Rm,. */
3433 skip_whitespace (str
);
3434 if ((rd
= reg_required_here (& str
, 12)) == FAIL
3435 || skip_past_comma (& str
) == FAIL
3436 || (rm
= reg_required_here (& str
, 0)) == FAIL
3437 || skip_past_comma (& str
) == FAIL
)
3439 inst
.error
= BAD_ARGS
;
3442 if (rd
== REG_PC
|| rm
== REG_PC
)
3444 inst
.error
= BAD_PC
;
3449 inst
.error
= _("Rd equal to Rm or Rn yields unpredictable results");
3453 /* Skip past '['. */
3454 if ((strlen (str
) >= 1)
3455 && strncmp (str
, "[", 1) == 0)
3458 skip_whitespace (str
);
3461 if ((rn
= reg_required_here (& str
, 16)) == FAIL
)
3463 inst
.error
= BAD_ARGS
;
3466 else if (rn
== REG_PC
)
3468 inst
.error
= BAD_PC
;
3473 inst
.error
= _("Rd equal to Rm or Rn yields unpredictable results");
3476 skip_whitespace (str
);
3478 /* Skip past ']'. */
3479 if ((strlen (str
) >= 1)
3480 && strncmp (str
, "]", 1) == 0)
3486 /* KIND indicates what kind of shifts are accepted. */
3489 decode_shift (char ** str
, int kind
)
3491 const struct asm_shift_name
* shift
;
3495 skip_whitespace (* str
);
3497 for (p
= * str
; ISALPHA (* p
); p
++)
3502 inst
.error
= _("shift expression expected");
3508 shift
= (const struct asm_shift_name
*) hash_find (arm_shift_hsh
, * str
);
3513 inst
.error
= _("shift expression expected");
3517 assert (shift
->properties
->index
== shift_properties
[shift
->properties
->index
].index
);
3519 if (kind
== SHIFT_LSL_OR_ASR_IMMEDIATE
3520 && shift
->properties
->index
!= SHIFT_LSL
3521 && shift
->properties
->index
!= SHIFT_ASR
)
3523 inst
.error
= _("'LSL' or 'ASR' required");
3526 else if (kind
== SHIFT_LSL_IMMEDIATE
3527 && shift
->properties
->index
!= SHIFT_LSL
)
3529 inst
.error
= _("'LSL' required");
3532 else if (kind
== SHIFT_ASR_IMMEDIATE
3533 && shift
->properties
->index
!= SHIFT_ASR
)
3535 inst
.error
= _("'ASR' required");
3539 if (shift
->properties
->index
== SHIFT_RRX
)
3542 inst
.instruction
|= shift
->properties
->bit_field
;
3546 skip_whitespace (p
);
3548 if (kind
== NO_SHIFT_RESTRICT
&& reg_required_here (& p
, 8) != FAIL
)
3550 inst
.instruction
|= shift
->properties
->bit_field
| SHIFT_BY_REG
;
3554 else if (! is_immediate_prefix (* p
))
3556 inst
.error
= (NO_SHIFT_RESTRICT
3557 ? _("shift requires register or #expression")
3558 : _("shift requires #expression"));
3566 if (my_get_expression (& inst
.reloc
.exp
, & p
))
3569 /* Validate some simple #expressions. */
3570 if (inst
.reloc
.exp
.X_op
== O_constant
)
3572 unsigned num
= inst
.reloc
.exp
.X_add_number
;
3574 /* Reject operations greater than 32. */
3576 /* Reject a shift of 0 unless the mode allows it. */
3577 || (num
== 0 && shift
->properties
->allows_0
== 0)
3578 /* Reject a shift of 32 unless the mode allows it. */
3579 || (num
== 32 && shift
->properties
->allows_32
== 0)
3582 /* As a special case we allow a shift of zero for
3583 modes that do not support it to be recoded as an
3584 logical shift left of zero (ie nothing). We warn
3585 about this though. */
3588 as_warn (_("shift of 0 ignored."));
3589 shift
= & shift_names
[0];
3590 assert (shift
->properties
->index
== SHIFT_LSL
);
3594 inst
.error
= _("invalid immediate shift");
3599 /* Shifts of 32 are encoded as 0, for those shifts that
3604 inst
.instruction
|= (num
<< 7) | shift
->properties
->bit_field
;
3608 inst
.reloc
.type
= BFD_RELOC_ARM_SHIFT_IMM
;
3609 inst
.reloc
.pc_rel
= 0;
3610 inst
.instruction
|= shift
->properties
->bit_field
;
3618 do_sat (char ** str
, int bias
)
3623 skip_whitespace (*str
);
3625 /* Parse <Rd>, field. */
3626 if ((rd
= reg_required_here (str
, 12)) == FAIL
3627 || skip_past_comma (str
) == FAIL
)
3629 inst
.error
= BAD_ARGS
;
3634 inst
.error
= BAD_PC
;
3638 /* Parse #<immed>, field. */
3639 if (is_immediate_prefix (**str
))
3643 inst
.error
= _("immediate expression expected");
3646 if (my_get_expression (&expr
, str
))
3648 inst
.error
= _("bad expression");
3651 if (expr
.X_op
!= O_constant
)
3653 inst
.error
= _("constant expression expected");
3656 if (expr
.X_add_number
+ bias
< 0
3657 || expr
.X_add_number
+ bias
> 31)
3659 inst
.error
= _("immediate value out of range");
3662 inst
.instruction
|= (expr
.X_add_number
+ bias
) << 16;
3663 if (skip_past_comma (str
) == FAIL
)
3665 inst
.error
= BAD_ARGS
;
3669 /* Parse <Rm> field. */
3670 if ((rm
= reg_required_here (str
, 0)) == FAIL
)
3672 inst
.error
= BAD_ARGS
;
3677 inst
.error
= BAD_PC
;
3681 if (skip_past_comma (str
) == SUCCESS
)
3682 decode_shift (str
, SHIFT_LSL_OR_ASR_IMMEDIATE
);
3685 /* ARM V6 ssat (argument parse). */
3688 do_ssat (char * str
)
3690 do_sat (&str
, /*bias=*/-1);
3694 /* ARM V6 usat (argument parse). */
3697 do_usat (char * str
)
3699 do_sat (&str
, /*bias=*/0);
3704 do_sat16 (char ** str
, int bias
)
3709 skip_whitespace (*str
);
3711 /* Parse the <Rd> field. */
3712 if ((rd
= reg_required_here (str
, 12)) == FAIL
3713 || skip_past_comma (str
) == FAIL
)
3715 inst
.error
= BAD_ARGS
;
3720 inst
.error
= BAD_PC
;
3724 /* Parse #<immed>, field. */
3725 if (is_immediate_prefix (**str
))
3729 inst
.error
= _("immediate expression expected");
3732 if (my_get_expression (&expr
, str
))
3734 inst
.error
= _("bad expression");
3737 if (expr
.X_op
!= O_constant
)
3739 inst
.error
= _("constant expression expected");
3742 if (expr
.X_add_number
+ bias
< 0
3743 || expr
.X_add_number
+ bias
> 15)
3745 inst
.error
= _("immediate value out of range");
3748 inst
.instruction
|= (expr
.X_add_number
+ bias
) << 16;
3749 if (skip_past_comma (str
) == FAIL
)
3751 inst
.error
= BAD_ARGS
;
3755 /* Parse <Rm> field. */
3756 if ((rm
= reg_required_here (str
, 0)) == FAIL
)
3758 inst
.error
= BAD_ARGS
;
3763 inst
.error
= BAD_PC
;
3768 /* ARM V6 ssat16 (argument parse). */
3771 do_ssat16 (char * str
)
3773 do_sat16 (&str
, /*bias=*/-1);
3778 do_usat16 (char * str
)
3780 do_sat16 (&str
, /*bias=*/0);
3785 do_cps_mode (char ** str
)
3789 skip_whitespace (*str
);
3791 if (! is_immediate_prefix (**str
))
3793 inst
.error
= _("immediate expression expected");
3797 (*str
)++; /* Strip off the immediate signifier. */
3798 if (my_get_expression (&expr
, str
))
3800 inst
.error
= _("bad expression");
3804 if (expr
.X_op
!= O_constant
)
3806 inst
.error
= _("constant expression expected");
3810 /* The mode is a 5 bit field. Valid values are 0-31. */
3811 if (((unsigned) expr
.X_add_number
) > 31
3812 || (inst
.reloc
.exp
.X_add_number
) < 0)
3814 inst
.error
= _("invalid constant");
3818 inst
.instruction
|= expr
.X_add_number
;
3821 /* ARM V6 srs (argument parse). */
3827 skip_whitespace (str
);
3828 exclam
= strchr (str
, '!');
3836 inst
.instruction
|= WRITE_BACK
;
3842 /* ARM V6 SMMUL (argument parse). */
3845 do_smmul (char * str
)
3849 skip_whitespace (str
);
3850 if ((rd
= reg_required_here (&str
, 16)) == FAIL
3851 || skip_past_comma (&str
) == FAIL
3852 || (rm
= reg_required_here (&str
, 0)) == FAIL
3853 || skip_past_comma (&str
) == FAIL
3854 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
3856 inst
.error
= BAD_ARGS
;
3864 inst
.error
= BAD_PC
;
3871 /* ARM V6 SMLALD (argument parse). */
3874 do_smlald (char * str
)
3876 int rdlo
, rdhi
, rm
, rs
;
3878 skip_whitespace (str
);
3879 if ((rdlo
= reg_required_here (&str
, 12)) == FAIL
3880 || skip_past_comma (&str
) == FAIL
3881 || (rdhi
= reg_required_here (&str
, 16)) == FAIL
3882 || skip_past_comma (&str
) == FAIL
3883 || (rm
= reg_required_here (&str
, 0)) == FAIL
3884 || skip_past_comma (&str
) == FAIL
3885 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
3887 inst
.error
= BAD_ARGS
;
3896 inst
.error
= BAD_PC
;
3903 /* ARM V6 SMLAD (argument parse). Signed multiply accumulate dual.
3904 smlad{x}{<cond>} Rd, Rm, Rs, Rn */
3907 do_smlad (char * str
)
3911 skip_whitespace (str
);
3912 if ((rd
= reg_required_here (&str
, 16)) == FAIL
3913 || skip_past_comma (&str
) == FAIL
3914 || (rm
= reg_required_here (&str
, 0)) == FAIL
3915 || skip_past_comma (&str
) == FAIL
3916 || (rs
= reg_required_here (&str
, 8)) == FAIL
3917 || skip_past_comma (&str
) == FAIL
3918 || (rn
= reg_required_here (&str
, 12)) == FAIL
)
3920 inst
.error
= BAD_ARGS
;
3929 inst
.error
= BAD_PC
;
3936 /* Returns true if the endian-specifier indicates big-endianness. */
3939 do_endian_specifier (char * str
)
3943 skip_whitespace (str
);
3944 if (strlen (str
) < 2)
3945 inst
.error
= _("missing endian specifier");
3946 else if (strncasecmp (str
, "BE", 2) == 0)
3951 else if (strncasecmp (str
, "LE", 2) == 0)
3954 inst
.error
= _("valid endian specifiers are be or le");
3961 /* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
3962 preserving the other bits.
3964 setend <endian_specifier>, where <endian_specifier> is either
3968 do_setend (char * str
)
3970 if (do_endian_specifier (str
))
3971 inst
.instruction
|= 0x200;
3976 SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
3977 Condition defaults to COND_ALWAYS.
3978 Error if any register uses R15. */
3981 do_sxth (char * str
)
3985 int rotation_clear_mask
= 0xfffff3ff;
3986 int rotation_eight_mask
= 0x00000400;
3987 int rotation_sixteen_mask
= 0x00000800;
3988 int rotation_twenty_four_mask
= 0x00000c00;
3990 skip_whitespace (str
);
3991 if ((rd
= reg_required_here (&str
, 12)) == FAIL
3992 || skip_past_comma (&str
) == FAIL
3993 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
3995 inst
.error
= BAD_ARGS
;
3999 else if (rd
== REG_PC
|| rm
== REG_PC
)
4001 inst
.error
= BAD_PC
;
4005 /* Zero out the rotation field. */
4006 inst
.instruction
&= rotation_clear_mask
;
4008 /* Check for lack of optional rotation field. */
4009 if (skip_past_comma (&str
) == FAIL
)
4015 /* Move past 'ROR'. */
4016 skip_whitespace (str
);
4017 if (strncasecmp (str
, "ROR", 3) == 0)
4021 inst
.error
= _("missing rotation field after comma");
4025 /* Get the immediate constant. */
4026 skip_whitespace (str
);
4027 if (is_immediate_prefix (* str
))
4031 inst
.error
= _("immediate expression expected");
4035 if (my_get_expression (&expr
, &str
))
4037 inst
.error
= _("bad expression");
4041 if (expr
.X_op
!= O_constant
)
4043 inst
.error
= _("constant expression expected");
4047 switch (expr
.X_add_number
)
4050 /* Rotation field has already been zeroed. */
4053 inst
.instruction
|= rotation_eight_mask
;
4057 inst
.instruction
|= rotation_sixteen_mask
;
4061 inst
.instruction
|= rotation_twenty_four_mask
;
4065 inst
.error
= _("rotation can be 8, 16, 24 or 0 when field is ommited");
4072 /* ARM V6 SXTAH extracts a 16-bit value from a register, sign
4073 extends it to 32-bits, and adds the result to a value in another
4074 register. You can specify a rotation by 0, 8, 16, or 24 bits
4075 before extracting the 16-bit value.
4076 SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
4077 Condition defaults to COND_ALWAYS.
4078 Error if any register uses R15. */
4081 do_sxtah (char * str
)
4085 int rotation_clear_mask
= 0xfffff3ff;
4086 int rotation_eight_mask
= 0x00000400;
4087 int rotation_sixteen_mask
= 0x00000800;
4088 int rotation_twenty_four_mask
= 0x00000c00;
4090 skip_whitespace (str
);
4091 if ((rd
= reg_required_here (&str
, 12)) == FAIL
4092 || skip_past_comma (&str
) == FAIL
4093 || (rn
= reg_required_here (&str
, 16)) == FAIL
4094 || skip_past_comma (&str
) == FAIL
4095 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4097 inst
.error
= BAD_ARGS
;
4101 else if (rd
== REG_PC
|| rn
== REG_PC
|| rm
== REG_PC
)
4103 inst
.error
= BAD_PC
;
4107 /* Zero out the rotation field. */
4108 inst
.instruction
&= rotation_clear_mask
;
4110 /* Check for lack of optional rotation field. */
4111 if (skip_past_comma (&str
) == FAIL
)
4117 /* Move past 'ROR'. */
4118 skip_whitespace (str
);
4119 if (strncasecmp (str
, "ROR", 3) == 0)
4123 inst
.error
= _("missing rotation field after comma");
4127 /* Get the immediate constant. */
4128 skip_whitespace (str
);
4129 if (is_immediate_prefix (* str
))
4133 inst
.error
= _("immediate expression expected");
4137 if (my_get_expression (&expr
, &str
))
4139 inst
.error
= _("bad expression");
4143 if (expr
.X_op
!= O_constant
)
4145 inst
.error
= _("constant expression expected");
4149 switch (expr
.X_add_number
)
4152 /* Rotation field has already been zeroed. */
4156 inst
.instruction
|= rotation_eight_mask
;
4160 inst
.instruction
|= rotation_sixteen_mask
;
4164 inst
.instruction
|= rotation_twenty_four_mask
;
4168 inst
.error
= _("rotation can be 8, 16, 24 or 0 when field is ommited");
4176 /* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
4177 word at the specified address and the following word
4179 Unconditionally executed.
4180 Error if Rn is R15. */
4187 skip_whitespace (str
);
4189 if ((rn
= reg_required_here (&str
, 16)) == FAIL
)
4194 inst
.error
= BAD_PC
;
4198 skip_whitespace (str
);
4202 inst
.instruction
|= WRITE_BACK
;
4208 /* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
4209 register (argument parse).
4211 Condition defaults to COND_ALWAYS.
4212 Error if Rd or Rm are R15. */
4219 skip_whitespace (str
);
4221 if ((rd
= reg_required_here (&str
, 12)) == FAIL
4222 || skip_past_comma (&str
) == FAIL
4223 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4224 inst
.error
= BAD_ARGS
;
4226 else if (rd
== REG_PC
|| rm
== REG_PC
)
4227 inst
.error
= BAD_PC
;
4233 /* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
4234 QADD16{<cond>} <Rd>, <Rn>, <Rm>
4235 Condition defaults to COND_ALWAYS.
4236 Error if Rd, Rn or Rm are R15. */
4239 do_qadd16 (char * str
)
4243 skip_whitespace (str
);
4245 if ((rd
= reg_required_here (&str
, 12)) == FAIL
4246 || skip_past_comma (&str
) == FAIL
4247 || (rn
= reg_required_here (&str
, 16)) == FAIL
4248 || skip_past_comma (&str
) == FAIL
4249 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4250 inst
.error
= BAD_ARGS
;
4252 else if (rd
== REG_PC
|| rm
== REG_PC
|| rn
== REG_PC
)
4253 inst
.error
= BAD_PC
;
4260 do_pkh_core (char * str
, int shift
)
4264 skip_whitespace (str
);
4265 if (((rd
= reg_required_here (&str
, 12)) == FAIL
)
4266 || (skip_past_comma (&str
) == FAIL
)
4267 || ((rn
= reg_required_here (&str
, 16)) == FAIL
)
4268 || (skip_past_comma (&str
) == FAIL
)
4269 || ((rm
= reg_required_here (&str
, 0)) == FAIL
))
4271 inst
.error
= BAD_ARGS
;
4275 else if (rd
== REG_PC
|| rn
== REG_PC
|| rm
== REG_PC
)
4277 inst
.error
= BAD_PC
;
4281 /* Check for optional shift immediate constant. */
4282 if (skip_past_comma (&str
) == FAIL
)
4284 if (shift
== SHIFT_ASR_IMMEDIATE
)
4286 /* If the shift specifier is ommited, turn the instruction
4287 into pkhbt rd, rm, rn. First, switch the instruction
4288 code, and clear the rn and rm fields. */
4289 inst
.instruction
&= 0xfff0f010;
4290 /* Now, re-encode the registers. */
4291 inst
.instruction
|= (rm
<< 16) | rn
;
4296 decode_shift (&str
, shift
);
4299 /* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
4300 PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
4301 Condition defaults to COND_ALWAYS.
4302 Error if Rd, Rn or Rm are R15. */
4305 do_pkhbt (char * str
)
4307 do_pkh_core (str
, SHIFT_LSL_IMMEDIATE
);
4310 /* ARM V6 PKHTB (Argument Parse). */
4313 do_pkhtb (char * str
)
4315 do_pkh_core (str
, SHIFT_ASR_IMMEDIATE
);
4318 /* ARM V6 Load Register Exclusive instruction (argument parse).
4319 LDREX{<cond>} <Rd, [<Rn>]
4320 Condition defaults to COND_ALWAYS.
4321 Error if Rd or Rn are R15.
4322 See ARMARMv6 A4.1.27: LDREX. */
4325 do_ldrex (char * str
)
4329 skip_whitespace (str
);
4332 if (((rd
= reg_required_here (&str
, 12)) == FAIL
)
4333 || (skip_past_comma (&str
) == FAIL
))
4335 inst
.error
= BAD_ARGS
;
4338 else if (rd
== REG_PC
)
4340 inst
.error
= BAD_PC
;
4343 skip_whitespace (str
);
4345 /* Skip past '['. */
4346 if ((strlen (str
) >= 1)
4347 &&strncmp (str
, "[", 1) == 0)
4349 skip_whitespace (str
);
4352 if ((rn
= reg_required_here (&str
, 16)) == FAIL
)
4354 inst
.error
= BAD_ARGS
;
4357 else if (rn
== REG_PC
)
4359 inst
.error
= BAD_PC
;
4362 skip_whitespace (str
);
4364 /* Skip past ']'. */
4365 if ((strlen (str
) >= 1)
4366 && strncmp (str
, "]", 1) == 0)
4372 /* ARM V6 change processor state instruction (argument parse)
4373 CPS, CPSIE, CSPID . */
4383 do_cps_flags (char ** str
, int thumb_p
)
4388 unsigned long arm_value
;
4389 unsigned long thumb_value
;
4391 static struct cps_flag flag_table
[] =
4400 skip_whitespace (*str
);
4402 /* Get the a, f and i flags. */
4403 while (**str
&& **str
!= ',')
4406 struct cps_flag
*q
= flag_table
+ sizeof (flag_table
)/sizeof (*p
);
4408 for (p
= flag_table
; p
< q
; ++p
)
4409 if (strncasecmp (*str
, &p
->character
, 1) == 0)
4411 inst
.instruction
|= (thumb_p
? p
->thumb_value
: p
->arm_value
);
4417 inst
.error
= _("unrecognized flag");
4424 inst
.error
= _("no 'a', 'i', or 'f' flags for 'cps'");
4428 do_cpsi (char * str
)
4430 do_cps_flags (&str
, /*thumb_p=*/0);
4432 if (skip_past_comma (&str
) == SUCCESS
)
4434 skip_whitespace (str
);
4440 /* THUMB V5 breakpoint instruction (argument parse)
4444 do_t_bkpt (char * str
)
4447 unsigned long number
;
4449 skip_whitespace (str
);
4451 /* Allow optional leading '#'. */
4452 if (is_immediate_prefix (*str
))
4455 memset (& expr
, '\0', sizeof (expr
));
4456 if (my_get_expression (& expr
, & str
)
4457 || (expr
.X_op
!= O_constant
4458 /* As a convenience we allow 'bkpt' without an operand. */
4459 && expr
.X_op
!= O_absent
))
4461 inst
.error
= _("bad expression");
4465 number
= expr
.X_add_number
;
4467 /* Check it fits an 8 bit unsigned. */
4468 if (number
!= (number
& 0xff))
4470 inst
.error
= _("immediate value out of range");
4474 inst
.instruction
|= number
;
4479 static bfd_reloc_code_real_type
4480 arm_parse_reloc (void)
4489 bfd_reloc_code_real_type reloc
;
4493 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
4494 MAP ("(got)", BFD_RELOC_ARM_GOT32
),
4495 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF
),
4496 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
4497 branch instructions generated by GCC for PLT relocs. */
4498 MAP ("(plt)", BFD_RELOC_ARM_PLT32
),
4499 MAP ("(target1)", BFD_RELOC_ARM_TARGET1
),
4500 MAP ("(sbrel)", BFD_RELOC_ARM_SBREL32
),
4501 MAP ("(target2)", BFD_RELOC_ARM_TARGET2
),
4502 { NULL
, 0, BFD_RELOC_UNUSED
}
4506 for (i
= 0, ip
= input_line_pointer
;
4507 i
< sizeof (id
) && (ISALNUM (*ip
) || ISPUNCT (*ip
));
4509 id
[i
] = TOLOWER (*ip
);
4511 for (i
= 0; reloc_map
[i
].str
; i
++)
4512 if (strncmp (id
, reloc_map
[i
].str
, reloc_map
[i
].len
) == 0)
4515 input_line_pointer
+= reloc_map
[i
].len
;
4517 return reloc_map
[i
].reloc
;
4520 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
4521 Expects inst.instruction is set for BLX(1).
4522 Note: this is cloned from do_branch, and the reloc changed to be a
4523 new one that can cope with setting one extra bit (the H bit). */
4526 do_branch25 (char * str
)
4528 if (my_get_expression (& inst
.reloc
.exp
, & str
))
4535 /* ScottB: February 5, 1998 */
4536 /* Check to see of PLT32 reloc required for the instruction. */
4538 /* arm_parse_reloc() works on input_line_pointer.
4539 We actually want to parse the operands to the branch instruction
4540 passed in 'str'. Save the input pointer and restore it later. */
4541 save_in
= input_line_pointer
;
4542 input_line_pointer
= str
;
4544 if (inst
.reloc
.exp
.X_op
== O_symbol
4546 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
4548 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
4549 inst
.reloc
.pc_rel
= 0;
4550 /* Modify str to point to after parsed operands, otherwise
4551 end_of_line() will complain about the (PLT) left in str. */
4552 str
= input_line_pointer
;
4556 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
4557 inst
.reloc
.pc_rel
= 1;
4560 input_line_pointer
= save_in
;
4563 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
4564 inst
.reloc
.pc_rel
= 1;
4565 #endif /* OBJ_ELF */
4570 /* ARM V5 branch-link-exchange instruction (argument parse)
4571 BLX <target_addr> ie BLX(1)
4572 BLX{<condition>} <Rm> ie BLX(2)
4573 Unfortunately, there are two different opcodes for this mnemonic.
4574 So, the insns[].value is not used, and the code here zaps values
4575 into inst.instruction.
4576 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
4584 skip_whitespace (mystr
);
4585 rm
= reg_required_here (& mystr
, 0);
4587 /* The above may set inst.error. Ignore his opinion. */
4592 /* Arg is a register.
4593 Use the condition code our caller put in inst.instruction.
4594 Pass ourselves off as a BX with a funny opcode. */
4595 inst
.instruction
|= 0x012fff30;
4600 /* This must be is BLX <target address>, no condition allowed. */
4601 if (inst
.instruction
!= COND_ALWAYS
)
4603 inst
.error
= BAD_COND
;
4607 inst
.instruction
= 0xfafffffe;
4609 /* Process like a B/BL, but with a different reloc.
4610 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
4615 /* ARM V5 Thumb BLX (argument parse)
4616 BLX <target_addr> which is BLX(1)
4617 BLX <Rm> which is BLX(2)
4618 Unfortunately, there are two different opcodes for this mnemonic.
4619 So, the tinsns[].value is not used, and the code here zaps values
4620 into inst.instruction. */
4623 do_t_blx (char * str
)
4628 skip_whitespace (mystr
);
4629 inst
.instruction
= 0x4780;
4631 /* Note that this call is to the ARM register recognizer. BLX(2)
4632 uses the ARM register space, not the Thumb one, so a call to
4633 thumb_reg() would be wrong. */
4634 rm
= reg_required_here (& mystr
, 3);
4639 /* It's BLX(2). The .instruction was zapped with rm & is final. */
4644 /* No ARM register. This must be BLX(1). Change the .instruction. */
4645 inst
.instruction
= 0xf7ffeffe;
4648 if (my_get_expression (& inst
.reloc
.exp
, & mystr
))
4651 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BLX
;
4652 inst
.reloc
.pc_rel
= 1;
4655 end_of_line (mystr
);
4658 /* ARM V5 breakpoint instruction (argument parse)
4659 BKPT <16 bit unsigned immediate>
4660 Instruction is not conditional.
4661 The bit pattern given in insns[] has the COND_ALWAYS condition,
4662 and it is an error if the caller tried to override that. */
4665 do_bkpt (char * str
)
4668 unsigned long number
;
4670 skip_whitespace (str
);
4672 /* Allow optional leading '#'. */
4673 if (is_immediate_prefix (* str
))
4676 memset (& expr
, '\0', sizeof (expr
));
4678 if (my_get_expression (& expr
, & str
)
4679 || (expr
.X_op
!= O_constant
4680 /* As a convenience we allow 'bkpt' without an operand. */
4681 && expr
.X_op
!= O_absent
))
4683 inst
.error
= _("bad expression");
4687 number
= expr
.X_add_number
;
4689 /* Check it fits a 16 bit unsigned. */
4690 if (number
!= (number
& 0xffff))
4692 inst
.error
= _("immediate value out of range");
4696 /* Top 12 of 16 bits to bits 19:8. */
4697 inst
.instruction
|= (number
& 0xfff0) << 4;
4699 /* Bottom 4 of 16 bits to bits 3:0. */
4700 inst
.instruction
|= number
& 0xf;
4705 /* THUMB CPS instruction (argument parse). */
4708 do_t_cps (char * str
)
4710 do_cps_flags (&str
, /*thumb_p=*/1);
4714 /* Parse and validate that a register is of the right form, this saves
4715 repeated checking of this information in many similar cases.
4716 Unlike the 32-bit case we do not insert the register into the opcode
4717 here, since the position is often unknown until the full instruction
4721 thumb_reg (char ** strp
, int hi_lo
)
4725 if ((reg
= reg_required_here (strp
, -1)) == FAIL
)
4733 inst
.error
= _("lo register required");
4741 inst
.error
= _("hi register required");
4754 thumb_mov_compare (char * str
, int move
)
4758 skip_whitespace (str
);
4760 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
4761 || skip_past_comma (&str
) == FAIL
)
4764 inst
.error
= BAD_ARGS
;
4768 if (move
!= THUMB_CPY
&& is_immediate_prefix (*str
))
4771 if (my_get_expression (&inst
.reloc
.exp
, &str
))
4774 else if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
4779 if (move
!= THUMB_CPY
&& Rs
< 8 && Rd
< 8)
4781 if (move
== THUMB_MOVE
)
4782 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
4783 since a MOV instruction produces unpredictable results. */
4784 inst
.instruction
= T_OPCODE_ADD_I3
;
4786 inst
.instruction
= T_OPCODE_CMP_LR
;
4787 inst
.instruction
|= Rd
| (Rs
<< 3);
4791 if (move
== THUMB_MOVE
)
4792 inst
.instruction
= T_OPCODE_MOV_HR
;
4793 else if (move
!= THUMB_CPY
)
4794 inst
.instruction
= T_OPCODE_CMP_HR
;
4797 inst
.instruction
|= THUMB_H1
;
4800 inst
.instruction
|= THUMB_H2
;
4802 inst
.instruction
|= (Rd
& 7) | ((Rs
& 7) << 3);
4809 inst
.error
= _("only lo regs allowed with immediate");
4813 if (move
== THUMB_MOVE
)
4814 inst
.instruction
= T_OPCODE_MOV_I8
;
4816 inst
.instruction
= T_OPCODE_CMP_I8
;
4818 inst
.instruction
|= Rd
<< 8;
4820 if (inst
.reloc
.exp
.X_op
!= O_constant
)
4821 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_IMM
;
4824 unsigned value
= inst
.reloc
.exp
.X_add_number
;
4828 inst
.error
= _("invalid immediate");
4832 inst
.instruction
|= value
;
4839 /* THUMB CPY instruction (argument parse). */
4842 do_t_cpy (char * str
)
4844 thumb_mov_compare (str
, THUMB_CPY
);
4847 /* THUMB SETEND instruction (argument parse). */
4850 do_t_setend (char * str
)
4852 if (do_endian_specifier (str
))
4853 inst
.instruction
|= 0x8;
4856 /* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
4858 static unsigned long
4859 check_iwmmxt_insn (char * str
,
4860 enum iwmmxt_insn_type insn_type
,
4864 const char * inst_error
;
4866 unsigned long number
;
4868 inst_error
= inst
.error
;
4870 inst
.error
= BAD_ARGS
;
4871 skip_whitespace (str
);
4876 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
4881 if ((wreg_required_here (&str
, 0, IWMMXT_REG_WR
)) == FAIL
)
4886 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
4887 || skip_past_comma (&str
) == FAIL
4888 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
))
4893 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
4894 || skip_past_comma (&str
) == FAIL
4895 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4896 || skip_past_comma (&str
) == FAIL
4897 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
))
4902 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
4903 || skip_past_comma (&str
) == FAIL
4904 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4905 || skip_past_comma (&str
) == FAIL
4906 || wreg_required_here (&str
, 0, IWMMXT_REG_WCG
) == FAIL
))
4911 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4912 || skip_past_comma (&str
) == FAIL
4913 || reg_required_here (&str
, 12) == FAIL
))
4918 if ((reg_required_here (&str
, 12) == FAIL
4919 || skip_past_comma (&str
) == FAIL
4920 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
))
4925 if ((wreg_required_here (&str
, 5, IWMMXT_REG_WR
) == FAIL
4926 || skip_past_comma (&str
) == FAIL
4927 || reg_required_here (&str
, 0) == FAIL
4928 || skip_past_comma (&str
) == FAIL
4929 || reg_required_here (&str
, 12) == FAIL
))
4934 if ((wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
4935 || skip_past_comma (&str
) == FAIL
4936 || reg_required_here (&str
, 12) == FAIL
4937 || skip_past_comma (&str
) == FAIL
4938 || reg_required_here (&str
, 16) == FAIL
))
4943 if ((reg_required_here (&str
, 12) == FAIL
4944 || skip_past_comma (&str
) == FAIL
4945 || reg_required_here (&str
, 16) == FAIL
4946 || skip_past_comma (&str
) == FAIL
4947 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
))
4952 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WC
) == FAIL
4953 || skip_past_comma (&str
) == FAIL
4954 || reg_required_here (&str
, 12) == FAIL
))
4959 if ((reg_required_here (&str
, 12) == FAIL
4960 || skip_past_comma (&str
) == FAIL
4961 || wreg_required_here (&str
, 16, IWMMXT_REG_WC
) == FAIL
))
4966 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4967 || skip_past_comma (&str
) == FAIL
4968 || reg_required_here (&str
, 12) == FAIL
4969 || skip_past_comma (&str
) == FAIL
))
4974 if ((reg_required_here (&str
, 12) == FAIL
4975 || skip_past_comma (&str
) == FAIL
))
4980 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
4981 || skip_past_comma (&str
) == FAIL
4982 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4983 || skip_past_comma (&str
) == FAIL
4984 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
4985 || skip_past_comma (&str
) == FAIL
))
4990 if ((reg_required_here (&str
, 12) == FAIL
4991 || skip_past_comma (&str
) == FAIL
4992 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4993 || skip_past_comma (&str
) == FAIL
))
4998 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
4999 || skip_past_comma (&str
) == FAIL
5000 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5001 || skip_past_comma (&str
) == FAIL
))
5006 if (immediate_size
== 0)
5009 inst
.error
= inst_error
;
5014 skip_whitespace (str
);
5016 /* Allow optional leading '#'. */
5017 if (is_immediate_prefix (* str
))
5020 memset (& expr
, '\0', sizeof (expr
));
5022 if (my_get_expression (& expr
, & str
) || (expr
.X_op
!= O_constant
))
5024 inst
.error
= _("bad or missing expression");
5028 number
= expr
.X_add_number
;
5030 if (number
!= (number
& immediate_size
))
5032 inst
.error
= _("immediate value out of range");
5036 inst
.error
= inst_error
;
5042 do_iwmmxt_byte_addr (char * str
)
5044 int op
= (inst
.instruction
& 0x300) >> 8;
5047 inst
.instruction
&= ~0x300;
5048 inst
.instruction
|= (op
& 1) << 22 | (op
& 2) << 7;
5050 skip_whitespace (str
);
5052 if ((reg
= wreg_required_here (&str
, 12, IWMMXT_REG_WR_OR_WC
)) == FAIL
5053 || skip_past_comma (& str
) == FAIL
5054 || cp_byte_address_required_here (&str
) == FAIL
)
5057 inst
.error
= BAD_ARGS
;
5062 if (wc_register (reg
))
5064 as_bad (_("non-word size not supported with control register"));
5065 inst
.instruction
|= 0xf0000100;
5066 inst
.instruction
&= ~0x00400000;
5071 do_iwmmxt_tandc (char * str
)
5075 reg
= check_iwmmxt_insn (str
, check_rd
, 0);
5077 if (reg
!= REG_PC
&& !inst
.error
)
5078 inst
.error
= _("only r15 allowed here");
5082 do_iwmmxt_tbcst (char * str
)
5084 check_iwmmxt_insn (str
, check_tbcst
, 0);
5088 do_iwmmxt_textrc (char * str
)
5090 unsigned long number
;
5092 if ((number
= check_iwmmxt_insn (str
, check_textrc
, 7)) == (unsigned long) FAIL
)
5095 inst
.instruction
|= number
& 0x7;
5099 do_iwmmxt_textrm (char * str
)
5101 unsigned long number
;
5103 if ((number
= check_iwmmxt_insn (str
, check_textrm
, 7)) == (unsigned long) FAIL
)
5106 inst
.instruction
|= number
& 0x7;
5110 do_iwmmxt_tinsr (char * str
)
5112 unsigned long number
;
5114 if ((number
= check_iwmmxt_insn (str
, check_tinsr
, 7)) == (unsigned long) FAIL
)
5117 inst
.instruction
|= number
& 0x7;
5121 do_iwmmxt_tmcr (char * str
)
5123 check_iwmmxt_insn (str
, check_tmcr
, 0);
5127 do_iwmmxt_tmcrr (char * str
)
5129 check_iwmmxt_insn (str
, check_tmcrr
, 0);
5133 do_iwmmxt_tmia (char * str
)
5135 check_iwmmxt_insn (str
, check_tmia
, 0);
5139 do_iwmmxt_tmovmsk (char * str
)
5141 check_iwmmxt_insn (str
, check_tmovmsk
, 0);
5145 do_iwmmxt_tmrc (char * str
)
5147 check_iwmmxt_insn (str
, check_tmrc
, 0);
5151 do_iwmmxt_tmrrc (char * str
)
5153 check_iwmmxt_insn (str
, check_tmrrc
, 0);
5157 do_iwmmxt_torc (char * str
)
5159 check_iwmmxt_insn (str
, check_rd
, 0);
5163 do_iwmmxt_waligni (char * str
)
5165 unsigned long number
;
5167 if ((number
= check_iwmmxt_insn (str
, check_waligni
, 7)) == (unsigned long) FAIL
)
5170 inst
.instruction
|= ((number
& 0x7) << 20);
5174 do_iwmmxt_wmov (char * str
)
5176 if (check_iwmmxt_insn (str
, check_wrwr
, 0) == (unsigned long) FAIL
)
5179 inst
.instruction
|= ((inst
.instruction
>> 16) & 0xf);
5183 do_iwmmxt_word_addr (char * str
)
5185 int op
= (inst
.instruction
& 0x300) >> 8;
5188 inst
.instruction
&= ~0x300;
5189 inst
.instruction
|= (op
& 1) << 22 | (op
& 2) << 7;
5191 skip_whitespace (str
);
5193 if ((reg
= wreg_required_here (&str
, 12, IWMMXT_REG_WR_OR_WC
)) == FAIL
5194 || skip_past_comma (& str
) == FAIL
5195 || cp_address_required_here (& str
, CP_WB_OK
) == FAIL
)
5198 inst
.error
= BAD_ARGS
;
5203 if (wc_register (reg
))
5205 if ((inst
.instruction
& COND_MASK
) != COND_ALWAYS
)
5206 as_bad (_("conditional execution not supported with control register"));
5208 as_bad (_("non-word size not supported with control register"));
5209 inst
.instruction
|= 0xf0000100;
5210 inst
.instruction
&= ~0x00400000;
5215 do_iwmmxt_wrwr (char * str
)
5217 check_iwmmxt_insn (str
, check_wrwr
, 0);
5221 do_iwmmxt_wrwrwcg (char * str
)
5223 check_iwmmxt_insn (str
, check_wrwrwcg
, 0);
5227 do_iwmmxt_wrwrwr (char * str
)
5229 check_iwmmxt_insn (str
, check_wrwrwr
, 0);
5233 do_iwmmxt_wshufh (char * str
)
5235 unsigned long number
;
5237 if ((number
= check_iwmmxt_insn (str
, check_wshufh
, 0xff)) == (unsigned long) FAIL
)
5240 inst
.instruction
|= ((number
& 0xf0) << 16) | (number
& 0xf);
5244 do_iwmmxt_wzero (char * str
)
5246 if (check_iwmmxt_insn (str
, check_wr
, 0) == (unsigned long) FAIL
)
5249 inst
.instruction
|= ((inst
.instruction
& 0xf) << 12) | ((inst
.instruction
& 0xf) << 16);
5252 /* Xscale multiply-accumulate (argument parse)
5255 MIAxycc acc0,Rm,Rs. */
5258 do_xsc_mia (char * str
)
5263 if (accum0_required_here (& str
) == FAIL
)
5264 inst
.error
= ERR_NO_ACCUM
;
5266 else if (skip_past_comma (& str
) == FAIL
5267 || (rm
= reg_required_here (& str
, 0)) == FAIL
)
5268 inst
.error
= BAD_ARGS
;
5270 else if (skip_past_comma (& str
) == FAIL
5271 || (rs
= reg_required_here (& str
, 12)) == FAIL
)
5272 inst
.error
= BAD_ARGS
;
5274 /* inst.instruction has now been zapped with both rm and rs. */
5275 else if (rm
== REG_PC
|| rs
== REG_PC
)
5276 inst
.error
= BAD_PC
; /* Undefined result if rm or rs is R15. */
5282 /* Xscale move-accumulator-register (argument parse)
5284 MARcc acc0,RdLo,RdHi. */
5287 do_xsc_mar (char * str
)
5291 if (accum0_required_here (& str
) == FAIL
)
5292 inst
.error
= ERR_NO_ACCUM
;
5294 else if (skip_past_comma (& str
) == FAIL
5295 || (rdlo
= reg_required_here (& str
, 12)) == FAIL
)
5296 inst
.error
= BAD_ARGS
;
5298 else if (skip_past_comma (& str
) == FAIL
5299 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
5300 inst
.error
= BAD_ARGS
;
5302 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5303 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
5304 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
5310 /* Xscale move-register-accumulator (argument parse)
5312 MRAcc RdLo,RdHi,acc0. */
5315 do_xsc_mra (char * str
)
5320 skip_whitespace (str
);
5322 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
)
5323 inst
.error
= BAD_ARGS
;
5325 else if (skip_past_comma (& str
) == FAIL
5326 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
5327 inst
.error
= BAD_ARGS
;
5329 else if (skip_past_comma (& str
) == FAIL
5330 || accum0_required_here (& str
) == FAIL
)
5331 inst
.error
= ERR_NO_ACCUM
;
5333 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5334 else if (rdlo
== rdhi
)
5335 inst
.error
= BAD_ARGS
; /* Undefined result if 2 writes to same reg. */
5337 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
5338 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
5344 ldst_extend (char ** str
)
5353 if (my_get_expression (& inst
.reloc
.exp
, str
))
5356 if (inst
.reloc
.exp
.X_op
== O_constant
)
5358 int value
= inst
.reloc
.exp
.X_add_number
;
5360 if (value
< -4095 || value
> 4095)
5362 inst
.error
= _("address offset too large");
5372 inst
.instruction
|= add
| value
;
5376 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
5377 inst
.reloc
.pc_rel
= 0;
5390 if (reg_required_here (str
, 0) == FAIL
)
5393 inst
.instruction
|= add
| OFFSET_REG
;
5394 if (skip_past_comma (str
) == SUCCESS
)
5395 return decode_shift (str
, SHIFT_IMMEDIATE
);
5401 /* ARMv5TE: Preload-Cache
5405 Syntactically, like LDR with B=1, W=0, L=1. */
5412 skip_whitespace (str
);
5416 inst
.error
= _("'[' expected after PLD mnemonic");
5421 skip_whitespace (str
);
5423 if ((rd
= reg_required_here (& str
, 16)) == FAIL
)
5426 skip_whitespace (str
);
5432 skip_whitespace (str
);
5434 /* Post-indexed addressing is not allowed with PLD. */
5435 if (skip_past_comma (&str
) == SUCCESS
)
5438 = _("post-indexed expression used in preload instruction");
5441 else if (*str
== '!') /* [Rn]! */
5443 inst
.error
= _("writeback used in preload instruction");
5447 inst
.instruction
|= INDEX_UP
| PRE_INDEX
;
5449 else /* [Rn, ...] */
5451 if (skip_past_comma (& str
) == FAIL
)
5453 inst
.error
= _("pre-indexed expression expected");
5457 if (ldst_extend (&str
) == FAIL
)
5460 skip_whitespace (str
);
5464 inst
.error
= _("missing ]");
5469 skip_whitespace (str
);
5471 if (* str
== '!') /* [Rn]! */
5473 inst
.error
= _("writeback used in preload instruction");
5477 inst
.instruction
|= PRE_INDEX
;
5483 /* ARMv5TE load-consecutive (argument parse)
5490 do_ldrd (char * str
)
5495 skip_whitespace (str
);
5497 if ((rd
= reg_required_here (& str
, 12)) == FAIL
)
5499 inst
.error
= BAD_ARGS
;
5503 if (skip_past_comma (& str
) == FAIL
5504 || (rn
= ld_mode_required_here (& str
)) == FAIL
)
5507 inst
.error
= BAD_ARGS
;
5511 /* inst.instruction has now been zapped with Rd and the addressing mode. */
5512 if (rd
& 1) /* Unpredictable result if Rd is odd. */
5514 inst
.error
= _("destination register must be even");
5520 inst
.error
= _("r14 not allowed here");
5524 if (((rd
== rn
) || (rd
+ 1 == rn
))
5525 && ((inst
.instruction
& WRITE_BACK
)
5526 || (!(inst
.instruction
& PRE_INDEX
))))
5527 as_warn (_("pre/post-indexing used when modified address register is destination"));
5529 /* For an index-register load, the index register must not overlap the
5530 destination (even if not write-back). */
5531 if ((inst
.instruction
& V4_STR_BIT
) == 0
5532 && (inst
.instruction
& HWOFFSET_IMM
) == 0)
5534 int rm
= inst
.instruction
& 0x0000000f;
5536 if (rm
== rd
|| (rm
== rd
+ 1))
5537 as_warn (_("ldrd destination registers must not overlap index register"));
5543 /* Returns the index into fp_values of a floating point number,
5544 or -1 if not in the table. */
5547 my_get_float_expression (char ** str
)
5549 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
5555 memset (words
, 0, MAX_LITTLENUMS
* sizeof (LITTLENUM_TYPE
));
5557 /* Look for a raw floating point number. */
5558 if ((save_in
= atof_ieee (*str
, 'x', words
)) != NULL
5559 && is_end_of_line
[(unsigned char) *save_in
])
5561 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
5563 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
5565 if (words
[j
] != fp_values
[i
][j
])
5569 if (j
== MAX_LITTLENUMS
)
5577 /* Try and parse a more complex expression, this will probably fail
5578 unless the code uses a floating point prefix (eg "0f"). */
5579 save_in
= input_line_pointer
;
5580 input_line_pointer
= *str
;
5581 if (expression (&exp
) == absolute_section
5582 && exp
.X_op
== O_big
5583 && exp
.X_add_number
< 0)
5585 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
5587 if (gen_to_words (words
, 5, (long) 15) == 0)
5589 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
5591 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
5593 if (words
[j
] != fp_values
[i
][j
])
5597 if (j
== MAX_LITTLENUMS
)
5599 *str
= input_line_pointer
;
5600 input_line_pointer
= save_in
;
5607 *str
= input_line_pointer
;
5608 input_line_pointer
= save_in
;
5612 /* We handle all bad expressions here, so that we can report the faulty
5613 instruction in the error message. */
5615 md_operand (expressionS
* expr
)
5617 if (in_my_get_expression
)
5619 expr
->X_op
= O_illegal
;
5620 if (inst
.error
== NULL
)
5621 inst
.error
= _("bad expression");
5625 /* Do those data_ops which can take a negative immediate constant
5626 by altering the instruction. A bit of a hack really.
5630 by inverting the second operand, and
5633 by negating the second operand. */
5636 negate_data_op (unsigned long * instruction
,
5637 unsigned long value
)
5640 unsigned long negated
, inverted
;
5642 negated
= validate_immediate (-value
);
5643 inverted
= validate_immediate (~value
);
5645 op
= (*instruction
>> DATA_OP_SHIFT
) & 0xf;
5648 /* First negates. */
5649 case OPCODE_SUB
: /* ADD <-> SUB */
5650 new_inst
= OPCODE_ADD
;
5655 new_inst
= OPCODE_SUB
;
5659 case OPCODE_CMP
: /* CMP <-> CMN */
5660 new_inst
= OPCODE_CMN
;
5665 new_inst
= OPCODE_CMP
;
5669 /* Now Inverted ops. */
5670 case OPCODE_MOV
: /* MOV <-> MVN */
5671 new_inst
= OPCODE_MVN
;
5676 new_inst
= OPCODE_MOV
;
5680 case OPCODE_AND
: /* AND <-> BIC */
5681 new_inst
= OPCODE_BIC
;
5686 new_inst
= OPCODE_AND
;
5690 case OPCODE_ADC
: /* ADC <-> SBC */
5691 new_inst
= OPCODE_SBC
;
5696 new_inst
= OPCODE_ADC
;
5700 /* We cannot do anything. */
5705 if (value
== (unsigned) FAIL
)
5708 *instruction
&= OPCODE_MASK
;
5709 *instruction
|= new_inst
<< DATA_OP_SHIFT
;
5714 data_op2 (char ** str
)
5719 skip_whitespace (* str
);
5721 if (reg_required_here (str
, 0) != FAIL
)
5723 if (skip_past_comma (str
) == SUCCESS
)
5724 /* Shift operation on register. */
5725 return decode_shift (str
, NO_SHIFT_RESTRICT
);
5731 /* Immediate expression. */
5732 if (is_immediate_prefix (**str
))
5737 if (my_get_expression (&inst
.reloc
.exp
, str
))
5740 if (inst
.reloc
.exp
.X_add_symbol
)
5742 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
5743 inst
.reloc
.pc_rel
= 0;
5747 if (skip_past_comma (str
) == SUCCESS
)
5749 /* #x, y -- ie explicit rotation by Y. */
5750 if (my_get_expression (&expr
, str
))
5753 if (expr
.X_op
!= O_constant
)
5755 inst
.error
= _("constant expression expected");
5759 /* Rotate must be a multiple of 2. */
5760 if (((unsigned) expr
.X_add_number
) > 30
5761 || (expr
.X_add_number
& 1) != 0
5762 || ((unsigned) inst
.reloc
.exp
.X_add_number
) > 255)
5764 inst
.error
= _("invalid constant");
5767 inst
.instruction
|= INST_IMMEDIATE
;
5768 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
5769 inst
.instruction
|= expr
.X_add_number
<< 7;
5773 /* Implicit rotation, select a suitable one. */
5774 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
5778 /* Can't be done. Perhaps the code reads something like
5779 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
5780 if ((value
= negate_data_op (&inst
.instruction
,
5781 inst
.reloc
.exp
.X_add_number
))
5784 inst
.error
= _("invalid constant");
5789 inst
.instruction
|= value
;
5792 inst
.instruction
|= INST_IMMEDIATE
;
5797 inst
.error
= _("register or shift expression expected");
5803 fp_op2 (char ** str
)
5805 skip_whitespace (* str
);
5807 if (fp_reg_required_here (str
, 0) != FAIL
)
5811 /* Immediate expression. */
5812 if (*((*str
)++) == '#')
5818 skip_whitespace (* str
);
5820 /* First try and match exact strings, this is to guarantee
5821 that some formats will work even for cross assembly. */
5823 for (i
= 0; fp_const
[i
]; i
++)
5825 if (strncmp (*str
, fp_const
[i
], strlen (fp_const
[i
])) == 0)
5829 *str
+= strlen (fp_const
[i
]);
5830 if (is_end_of_line
[(unsigned char) **str
])
5832 inst
.instruction
|= i
+ 8;
5839 /* Just because we didn't get a match doesn't mean that the
5840 constant isn't valid, just that it is in a format that we
5841 don't automatically recognize. Try parsing it with
5842 the standard expression routines. */
5843 if ((i
= my_get_float_expression (str
)) >= 0)
5845 inst
.instruction
|= i
+ 8;
5849 inst
.error
= _("invalid floating point immediate expression");
5853 _("floating point register or immediate expression expected");
5859 do_arit (char * str
)
5861 skip_whitespace (str
);
5863 if (reg_required_here (&str
, 12) == FAIL
5864 || skip_past_comma (&str
) == FAIL
5865 || reg_required_here (&str
, 16) == FAIL
5866 || skip_past_comma (&str
) == FAIL
5867 || data_op2 (&str
) == FAIL
)
5870 inst
.error
= BAD_ARGS
;
5880 /* This is a pseudo-op of the form "adr rd, label" to be converted
5881 into a relative address of the form "add rd, pc, #label-.-8". */
5882 skip_whitespace (str
);
5884 if (reg_required_here (&str
, 12) == FAIL
5885 || skip_past_comma (&str
) == FAIL
5886 || my_get_expression (&inst
.reloc
.exp
, &str
))
5889 inst
.error
= BAD_ARGS
;
5893 /* Frag hacking will turn this into a sub instruction if the offset turns
5894 out to be negative. */
5895 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
5897 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust. */
5899 inst
.reloc
.pc_rel
= 1;
5905 do_adrl (char * str
)
5907 /* This is a pseudo-op of the form "adrl rd, label" to be converted
5908 into a relative address of the form:
5909 add rd, pc, #low(label-.-8)"
5910 add rd, rd, #high(label-.-8)" */
5912 skip_whitespace (str
);
5914 if (reg_required_here (&str
, 12) == FAIL
5915 || skip_past_comma (&str
) == FAIL
5916 || my_get_expression (&inst
.reloc
.exp
, &str
))
5919 inst
.error
= BAD_ARGS
;
5925 /* Frag hacking will turn this into a sub instruction if the offset turns
5926 out to be negative. */
5927 inst
.reloc
.type
= BFD_RELOC_ARM_ADRL_IMMEDIATE
;
5929 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust */
5931 inst
.reloc
.pc_rel
= 1;
5932 inst
.size
= INSN_SIZE
* 2;
5938 skip_whitespace (str
);
5940 if (reg_required_here (&str
, 16) == FAIL
)
5943 inst
.error
= BAD_ARGS
;
5947 if (skip_past_comma (&str
) == FAIL
5948 || data_op2 (&str
) == FAIL
)
5951 inst
.error
= BAD_ARGS
;
5961 skip_whitespace (str
);
5963 if (reg_required_here (&str
, 12) == FAIL
)
5966 inst
.error
= BAD_ARGS
;
5970 if (skip_past_comma (&str
) == FAIL
5971 || data_op2 (&str
) == FAIL
)
5974 inst
.error
= BAD_ARGS
;
5982 do_ldst (char * str
)
5988 skip_whitespace (str
);
5990 if ((conflict_reg
= reg_required_here (&str
, 12)) == FAIL
)
5993 inst
.error
= BAD_ARGS
;
5997 if (skip_past_comma (&str
) == FAIL
)
5999 inst
.error
= _("address expected");
6009 skip_whitespace (str
);
6011 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6014 /* Conflicts can occur on stores as well as loads. */
6015 conflict_reg
= (conflict_reg
== reg
);
6017 skip_whitespace (str
);
6023 if (skip_past_comma (&str
) == SUCCESS
)
6025 /* [Rn],... (post inc) */
6026 if (ldst_extend (&str
) == FAIL
)
6029 as_warn (_("%s register same as write-back base"),
6030 ((inst
.instruction
& LOAD_BIT
)
6031 ? _("destination") : _("source")));
6036 skip_whitespace (str
);
6041 as_warn (_("%s register same as write-back base"),
6042 ((inst
.instruction
& LOAD_BIT
)
6043 ? _("destination") : _("source")));
6045 inst
.instruction
|= WRITE_BACK
;
6048 inst
.instruction
|= INDEX_UP
;
6055 if (skip_past_comma (&str
) == FAIL
)
6057 inst
.error
= _("pre-indexed expression expected");
6062 if (ldst_extend (&str
) == FAIL
)
6065 skip_whitespace (str
);
6069 inst
.error
= _("missing ]");
6073 skip_whitespace (str
);
6078 as_warn (_("%s register same as write-back base"),
6079 ((inst
.instruction
& LOAD_BIT
)
6080 ? _("destination") : _("source")));
6082 inst
.instruction
|= WRITE_BACK
;
6086 else if (*str
== '=')
6088 if ((inst
.instruction
& LOAD_BIT
) == 0)
6090 inst
.error
= _("invalid pseudo operation");
6094 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6097 skip_whitespace (str
);
6099 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6102 if (inst
.reloc
.exp
.X_op
!= O_constant
6103 && inst
.reloc
.exp
.X_op
!= O_symbol
)
6105 inst
.error
= _("constant expression expected");
6109 if (inst
.reloc
.exp
.X_op
== O_constant
)
6111 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
6115 /* This can be done with a mov instruction. */
6116 inst
.instruction
&= LITERAL_MASK
;
6117 inst
.instruction
|= (INST_IMMEDIATE
6118 | (OPCODE_MOV
<< DATA_OP_SHIFT
));
6119 inst
.instruction
|= value
& 0xfff;
6124 value
= validate_immediate (~inst
.reloc
.exp
.X_add_number
);
6128 /* This can be done with a mvn instruction. */
6129 inst
.instruction
&= LITERAL_MASK
;
6130 inst
.instruction
|= (INST_IMMEDIATE
6131 | (OPCODE_MVN
<< DATA_OP_SHIFT
));
6132 inst
.instruction
|= value
& 0xfff;
6138 /* Insert into literal pool. */
6139 if (add_to_lit_pool () == FAIL
)
6142 inst
.error
= _("literal pool insertion failed");
6146 /* Change the instruction exp to point to the pool. */
6147 inst
.reloc
.type
= BFD_RELOC_ARM_LITERAL
;
6148 inst
.reloc
.pc_rel
= 1;
6149 inst
.instruction
|= (REG_PC
<< 16);
6154 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6157 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
6159 /* PC rel adjust. */
6160 inst
.reloc
.exp
.X_add_number
-= 8;
6162 inst
.reloc
.pc_rel
= 1;
6163 inst
.instruction
|= (REG_PC
<< 16);
6167 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
6172 do_ldstt (char * str
)
6176 skip_whitespace (str
);
6178 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
6181 inst
.error
= BAD_ARGS
;
6185 if (skip_past_comma (& str
) == FAIL
)
6187 inst
.error
= _("address expected");
6197 skip_whitespace (str
);
6199 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6202 /* ldrt/strt always use post-indexed addressing, so if the base is
6203 the same as Rd, we warn. */
6204 if (conflict_reg
== reg
)
6205 as_warn (_("%s register same as write-back base"),
6206 ((inst
.instruction
& LOAD_BIT
)
6207 ? _("destination") : _("source")));
6209 skip_whitespace (str
);
6215 if (skip_past_comma (&str
) == SUCCESS
)
6217 /* [Rn],... (post inc) */
6218 if (ldst_extend (&str
) == FAIL
)
6224 skip_whitespace (str
);
6226 /* Skip a write-back '!'. */
6230 inst
.instruction
|= INDEX_UP
;
6235 inst
.error
= _("post-indexed expression expected");
6241 inst
.error
= _("post-indexed expression expected");
6248 /* Halfword and signed-byte load/store operations. */
6251 do_ldstv4 (char * str
)
6257 skip_whitespace (str
);
6259 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
6262 inst
.error
= BAD_ARGS
;
6266 if (skip_past_comma (& str
) == FAIL
)
6268 inst
.error
= _("address expected");
6278 skip_whitespace (str
);
6280 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6283 /* Conflicts can occur on stores as well as loads. */
6284 conflict_reg
= (conflict_reg
== reg
);
6286 skip_whitespace (str
);
6292 if (skip_past_comma (&str
) == SUCCESS
)
6294 /* [Rn],... (post inc) */
6295 if (ldst_extend_v4 (&str
) == FAIL
)
6298 as_warn (_("%s register same as write-back base"),
6299 ((inst
.instruction
& LOAD_BIT
)
6300 ? _("destination") : _("source")));
6305 inst
.instruction
|= HWOFFSET_IMM
;
6307 skip_whitespace (str
);
6312 as_warn (_("%s register same as write-back base"),
6313 ((inst
.instruction
& LOAD_BIT
)
6314 ? _("destination") : _("source")));
6316 inst
.instruction
|= WRITE_BACK
;
6319 inst
.instruction
|= INDEX_UP
;
6326 if (skip_past_comma (&str
) == FAIL
)
6328 inst
.error
= _("pre-indexed expression expected");
6333 if (ldst_extend_v4 (&str
) == FAIL
)
6336 skip_whitespace (str
);
6340 inst
.error
= _("missing ]");
6344 skip_whitespace (str
);
6349 as_warn (_("%s register same as write-back base"),
6350 ((inst
.instruction
& LOAD_BIT
)
6351 ? _("destination") : _("source")));
6353 inst
.instruction
|= WRITE_BACK
;
6357 else if (*str
== '=')
6359 if ((inst
.instruction
& LOAD_BIT
) == 0)
6361 inst
.error
= _("invalid pseudo operation");
6365 /* XXX Does this work correctly for half-word/byte ops? */
6366 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6369 skip_whitespace (str
);
6371 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6374 if (inst
.reloc
.exp
.X_op
!= O_constant
6375 && inst
.reloc
.exp
.X_op
!= O_symbol
)
6377 inst
.error
= _("constant expression expected");
6381 if (inst
.reloc
.exp
.X_op
== O_constant
)
6383 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
6387 /* This can be done with a mov instruction. */
6388 inst
.instruction
&= LITERAL_MASK
;
6389 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MOV
<< DATA_OP_SHIFT
);
6390 inst
.instruction
|= value
& 0xfff;
6395 value
= validate_immediate (~ inst
.reloc
.exp
.X_add_number
);
6399 /* This can be done with a mvn instruction. */
6400 inst
.instruction
&= LITERAL_MASK
;
6401 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MVN
<< DATA_OP_SHIFT
);
6402 inst
.instruction
|= value
& 0xfff;
6408 /* Insert into literal pool. */
6409 if (add_to_lit_pool () == FAIL
)
6412 inst
.error
= _("literal pool insertion failed");
6416 /* Change the instruction exp to point to the pool. */
6417 inst
.instruction
|= HWOFFSET_IMM
;
6418 inst
.reloc
.type
= BFD_RELOC_ARM_HWLITERAL
;
6419 inst
.reloc
.pc_rel
= 1;
6420 inst
.instruction
|= (REG_PC
<< 16);
6425 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6428 inst
.instruction
|= HWOFFSET_IMM
;
6429 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
6431 /* PC rel adjust. */
6432 inst
.reloc
.exp
.X_add_number
-= 8;
6434 inst
.reloc
.pc_rel
= 1;
6435 inst
.instruction
|= (REG_PC
<< 16);
6439 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
6444 reg_list (char ** strp
)
6446 char * str
= * strp
;
6450 /* We come back here if we get ranges concatenated by '+' or '|'. */
6465 skip_whitespace (str
);
6467 if ((reg
= reg_required_here (& str
, -1)) == FAIL
)
6476 inst
.error
= _("bad range in register list");
6480 for (i
= cur_reg
+ 1; i
< reg
; i
++)
6482 if (range
& (1 << i
))
6484 (_("Warning: duplicated register (r%d) in register list"),
6492 if (range
& (1 << reg
))
6493 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
6495 else if (reg
<= cur_reg
)
6496 as_tsktsk (_("Warning: register range not in ascending order"));
6501 while (skip_past_comma (&str
) != FAIL
6502 || (in_range
= 1, *str
++ == '-'));
6504 skip_whitespace (str
);
6508 inst
.error
= _("missing `}'");
6516 if (my_get_expression (&expr
, &str
))
6519 if (expr
.X_op
== O_constant
)
6521 if (expr
.X_add_number
6522 != (expr
.X_add_number
& 0x0000ffff))
6524 inst
.error
= _("invalid register mask");
6528 if ((range
& expr
.X_add_number
) != 0)
6530 int regno
= range
& expr
.X_add_number
;
6533 regno
= (1 << regno
) - 1;
6535 (_("Warning: duplicated register (r%d) in register list"),
6539 range
|= expr
.X_add_number
;
6543 if (inst
.reloc
.type
!= 0)
6545 inst
.error
= _("expression too complex");
6549 memcpy (&inst
.reloc
.exp
, &expr
, sizeof (expressionS
));
6550 inst
.reloc
.type
= BFD_RELOC_ARM_MULTI
;
6551 inst
.reloc
.pc_rel
= 0;
6555 skip_whitespace (str
);
6557 if (*str
== '|' || *str
== '+')
6563 while (another_range
);
6570 do_ldmstm (char * str
)
6575 skip_whitespace (str
);
6577 if ((base_reg
= reg_required_here (&str
, 16)) == FAIL
)
6580 if (base_reg
== REG_PC
)
6582 inst
.error
= _("r15 not allowed as base register");
6586 skip_whitespace (str
);
6590 inst
.instruction
|= WRITE_BACK
;
6594 if (skip_past_comma (&str
) == FAIL
6595 || (range
= reg_list (&str
)) == FAIL
)
6598 inst
.error
= BAD_ARGS
;
6605 inst
.instruction
|= LDM_TYPE_2_OR_3
;
6608 if (inst
.instruction
& WRITE_BACK
)
6610 /* Check for unpredictable uses of writeback. */
6611 if (inst
.instruction
& LOAD_BIT
)
6613 /* Not allowed in LDM type 2. */
6614 if ((inst
.instruction
& LDM_TYPE_2_OR_3
)
6615 && ((range
& (1 << REG_PC
)) == 0))
6616 as_warn (_("writeback of base register is UNPREDICTABLE"));
6617 /* Only allowed if base reg not in list for other types. */
6618 else if (range
& (1 << base_reg
))
6619 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
6623 /* Not allowed for type 2. */
6624 if (inst
.instruction
& LDM_TYPE_2_OR_3
)
6625 as_warn (_("writeback of base register is UNPREDICTABLE"));
6626 /* Only allowed if base reg not in list, or first in list. */
6627 else if ((range
& (1 << base_reg
))
6628 && (range
& ((1 << base_reg
) - 1)))
6629 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
6633 inst
.instruction
|= range
;
6640 skip_whitespace (str
);
6642 /* Allow optional leading '#'. */
6643 if (is_immediate_prefix (*str
))
6646 if (my_get_expression (& inst
.reloc
.exp
, & str
))
6649 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
6650 inst
.reloc
.pc_rel
= 0;
6655 do_swap (char * str
)
6659 skip_whitespace (str
);
6661 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
6666 inst
.error
= _("r15 not allowed in swap");
6670 if (skip_past_comma (&str
) == FAIL
6671 || (reg
= reg_required_here (&str
, 0)) == FAIL
)
6674 inst
.error
= BAD_ARGS
;
6680 inst
.error
= _("r15 not allowed in swap");
6684 if (skip_past_comma (&str
) == FAIL
6687 inst
.error
= BAD_ARGS
;
6691 skip_whitespace (str
);
6693 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6698 inst
.error
= BAD_PC
;
6702 skip_whitespace (str
);
6706 inst
.error
= _("missing ]");
6714 do_branch (char * str
)
6716 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6723 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
6724 required for the instruction. */
6726 /* arm_parse_reloc () works on input_line_pointer.
6727 We actually want to parse the operands to the branch instruction
6728 passed in 'str'. Save the input pointer and restore it later. */
6729 save_in
= input_line_pointer
;
6730 input_line_pointer
= str
;
6731 if (inst
.reloc
.exp
.X_op
== O_symbol
6733 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
6735 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
6736 inst
.reloc
.pc_rel
= 0;
6737 /* Modify str to point to after parsed operands, otherwise
6738 end_of_line() will complain about the (PLT) left in str. */
6739 str
= input_line_pointer
;
6743 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
6744 inst
.reloc
.pc_rel
= 1;
6746 input_line_pointer
= save_in
;
6749 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
6750 inst
.reloc
.pc_rel
= 1;
6751 #endif /* OBJ_ELF */
6759 /* Co-processor data operation.
6760 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
6761 skip_whitespace (str
);
6763 if (co_proc_number (&str
) == FAIL
)
6766 inst
.error
= BAD_ARGS
;
6770 if (skip_past_comma (&str
) == FAIL
6771 || cp_opc_expr (&str
, 20,4) == FAIL
)
6774 inst
.error
= BAD_ARGS
;
6778 if (skip_past_comma (&str
) == FAIL
6779 || cp_reg_required_here (&str
, 12) == FAIL
)
6782 inst
.error
= BAD_ARGS
;
6786 if (skip_past_comma (&str
) == FAIL
6787 || cp_reg_required_here (&str
, 16) == FAIL
)
6790 inst
.error
= BAD_ARGS
;
6794 if (skip_past_comma (&str
) == FAIL
6795 || cp_reg_required_here (&str
, 0) == FAIL
)
6798 inst
.error
= BAD_ARGS
;
6802 if (skip_past_comma (&str
) == SUCCESS
)
6804 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
6807 inst
.error
= BAD_ARGS
;
6816 do_lstc (char * str
)
6818 /* Co-processor register load/store.
6819 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
6821 skip_whitespace (str
);
6823 if (co_proc_number (&str
) == FAIL
)
6826 inst
.error
= BAD_ARGS
;
6830 if (skip_past_comma (&str
) == FAIL
6831 || cp_reg_required_here (&str
, 12) == FAIL
)
6834 inst
.error
= BAD_ARGS
;
6838 if (skip_past_comma (&str
) == FAIL
6839 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
6842 inst
.error
= BAD_ARGS
;
6850 do_co_reg (char * str
)
6852 /* Co-processor register transfer.
6853 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
6855 skip_whitespace (str
);
6857 if (co_proc_number (&str
) == FAIL
)
6860 inst
.error
= BAD_ARGS
;
6864 if (skip_past_comma (&str
) == FAIL
6865 || cp_opc_expr (&str
, 21, 3) == FAIL
)
6868 inst
.error
= BAD_ARGS
;
6872 if (skip_past_comma (&str
) == FAIL
6873 || reg_required_here (&str
, 12) == FAIL
)
6876 inst
.error
= BAD_ARGS
;
6880 if (skip_past_comma (&str
) == FAIL
6881 || cp_reg_required_here (&str
, 16) == FAIL
)
6884 inst
.error
= BAD_ARGS
;
6888 if (skip_past_comma (&str
) == FAIL
6889 || cp_reg_required_here (&str
, 0) == FAIL
)
6892 inst
.error
= BAD_ARGS
;
6896 if (skip_past_comma (&str
) == SUCCESS
)
6898 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
6901 inst
.error
= BAD_ARGS
;
6910 do_fpa_ctrl (char * str
)
6912 /* FP control registers.
6913 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
6915 skip_whitespace (str
);
6917 if (reg_required_here (&str
, 12) == FAIL
)
6920 inst
.error
= BAD_ARGS
;
6928 do_fpa_ldst (char * str
)
6930 skip_whitespace (str
);
6932 if (fp_reg_required_here (&str
, 12) == FAIL
)
6935 inst
.error
= BAD_ARGS
;
6939 if (skip_past_comma (&str
) == FAIL
6940 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
6943 inst
.error
= BAD_ARGS
;
6951 do_fpa_ldmstm (char * str
)
6955 skip_whitespace (str
);
6957 if (fp_reg_required_here (&str
, 12) == FAIL
)
6960 inst
.error
= BAD_ARGS
;
6964 /* Get Number of registers to transfer. */
6965 if (skip_past_comma (&str
) == FAIL
6966 || my_get_expression (&inst
.reloc
.exp
, &str
))
6969 inst
.error
= _("constant expression expected");
6973 if (inst
.reloc
.exp
.X_op
!= O_constant
)
6975 inst
.error
= _("constant value required for number of registers");
6979 num_regs
= inst
.reloc
.exp
.X_add_number
;
6981 if (num_regs
< 1 || num_regs
> 4)
6983 inst
.error
= _("number of registers must be in the range [1:4]");
6990 inst
.instruction
|= CP_T_X
;
6993 inst
.instruction
|= CP_T_Y
;
6996 inst
.instruction
|= CP_T_Y
| CP_T_X
;
7004 if (inst
.instruction
& (CP_T_Pre
| CP_T_UD
)) /* ea/fd format. */
7010 /* The instruction specified "ea" or "fd", so we can only accept
7011 [Rn]{!}. The instruction does not really support stacking or
7012 unstacking, so we have to emulate these by setting appropriate
7013 bits and offsets. */
7014 if (skip_past_comma (&str
) == FAIL
7018 inst
.error
= BAD_ARGS
;
7023 skip_whitespace (str
);
7025 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
7028 skip_whitespace (str
);
7032 inst
.error
= BAD_ARGS
;
7044 _("r15 not allowed as base register with write-back");
7051 if (inst
.instruction
& CP_T_Pre
)
7053 /* Pre-decrement. */
7054 offset
= 3 * num_regs
;
7056 inst
.instruction
|= CP_T_WB
;
7060 /* Post-increment. */
7063 inst
.instruction
|= CP_T_WB
;
7064 offset
= 3 * num_regs
;
7068 /* No write-back, so convert this into a standard pre-increment
7069 instruction -- aesthetically more pleasing. */
7070 inst
.instruction
|= CP_T_Pre
| CP_T_UD
;
7075 inst
.instruction
|= offset
;
7077 else if (skip_past_comma (&str
) == FAIL
7078 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
7081 inst
.error
= BAD_ARGS
;
7089 do_fpa_dyadic (char * str
)
7091 skip_whitespace (str
);
7093 if (fp_reg_required_here (&str
, 12) == FAIL
)
7096 inst
.error
= BAD_ARGS
;
7100 if (skip_past_comma (&str
) == FAIL
7101 || fp_reg_required_here (&str
, 16) == FAIL
)
7104 inst
.error
= BAD_ARGS
;
7108 if (skip_past_comma (&str
) == FAIL
7109 || fp_op2 (&str
) == FAIL
)
7112 inst
.error
= BAD_ARGS
;
7120 do_fpa_monadic (char * str
)
7122 skip_whitespace (str
);
7124 if (fp_reg_required_here (&str
, 12) == FAIL
)
7127 inst
.error
= BAD_ARGS
;
7131 if (skip_past_comma (&str
) == FAIL
7132 || fp_op2 (&str
) == FAIL
)
7135 inst
.error
= BAD_ARGS
;
7143 do_fpa_cmp (char * str
)
7145 skip_whitespace (str
);
7147 if (fp_reg_required_here (&str
, 16) == FAIL
)
7150 inst
.error
= BAD_ARGS
;
7154 if (skip_past_comma (&str
) == FAIL
7155 || fp_op2 (&str
) == FAIL
)
7158 inst
.error
= BAD_ARGS
;
7166 do_fpa_from_reg (char * str
)
7168 skip_whitespace (str
);
7170 if (fp_reg_required_here (&str
, 16) == FAIL
)
7173 inst
.error
= BAD_ARGS
;
7177 if (skip_past_comma (&str
) == FAIL
7178 || reg_required_here (&str
, 12) == FAIL
)
7181 inst
.error
= BAD_ARGS
;
7189 do_fpa_to_reg (char * str
)
7191 skip_whitespace (str
);
7193 if (reg_required_here (&str
, 12) == FAIL
)
7196 if (skip_past_comma (&str
) == FAIL
7197 || fp_reg_required_here (&str
, 0) == FAIL
)
7200 inst
.error
= BAD_ARGS
;
7208 vfp_sp_reg_required_here (char ** str
,
7209 enum vfp_sp_reg_pos pos
)
7214 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_SN
].htab
)) != FAIL
)
7219 inst
.instruction
|= ((reg
>> 1) << 12) | ((reg
& 1) << 22);
7223 inst
.instruction
|= ((reg
>> 1) << 16) | ((reg
& 1) << 7);
7227 inst
.instruction
|= ((reg
>> 1) << 0) | ((reg
& 1) << 5);
7236 /* In the few cases where we might be able to accept something else
7237 this error can be overridden. */
7238 inst
.error
= _(all_reg_maps
[REG_TYPE_SN
].expected
);
7240 /* Restore the start point. */
7246 vfp_dp_reg_required_here (char ** str
,
7247 enum vfp_dp_reg_pos pos
)
7250 char * start
= *str
;
7252 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_DN
].htab
)) != FAIL
)
7257 inst
.instruction
|= reg
<< 12;
7261 inst
.instruction
|= reg
<< 16;
7265 inst
.instruction
|= reg
<< 0;
7274 /* In the few cases where we might be able to accept something else
7275 this error can be overridden. */
7276 inst
.error
= _(all_reg_maps
[REG_TYPE_DN
].expected
);
7278 /* Restore the start point. */
7284 do_vfp_sp_monadic (char * str
)
7286 skip_whitespace (str
);
7288 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7291 if (skip_past_comma (&str
) == FAIL
7292 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
7295 inst
.error
= BAD_ARGS
;
7303 do_vfp_dp_monadic (char * str
)
7305 skip_whitespace (str
);
7307 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7310 if (skip_past_comma (&str
) == FAIL
7311 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7314 inst
.error
= BAD_ARGS
;
7322 do_vfp_sp_dyadic (char * str
)
7324 skip_whitespace (str
);
7326 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7329 if (skip_past_comma (&str
) == FAIL
7330 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
7331 || skip_past_comma (&str
) == FAIL
7332 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
7335 inst
.error
= BAD_ARGS
;
7343 do_vfp_dp_dyadic (char * str
)
7345 skip_whitespace (str
);
7347 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7350 if (skip_past_comma (&str
) == FAIL
7351 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
7352 || skip_past_comma (&str
) == FAIL
7353 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7356 inst
.error
= BAD_ARGS
;
7364 do_vfp_reg_from_sp (char * str
)
7366 skip_whitespace (str
);
7368 if (reg_required_here (&str
, 12) == FAIL
)
7371 if (skip_past_comma (&str
) == FAIL
7372 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
7375 inst
.error
= BAD_ARGS
;
7382 /* Parse and encode a VFP SP register list, storing the initial
7383 register in position POS and returning the range as the result. If
7384 the string is invalid return FAIL (an invalid range). */
7387 vfp_sp_reg_list (char ** str
, enum vfp_sp_reg_pos pos
)
7395 unsigned long mask
= 0;
7402 skip_whitespace (*str
);
7404 tempinst
= inst
.instruction
;
7408 inst
.instruction
= 0;
7410 if ((new_base
= vfp_sp_reg_required_here (str
, pos
)) == FAIL
)
7413 if (count
== 0 || base_reg
> new_base
)
7415 base_reg
= new_base
;
7416 base_bits
= inst
.instruction
;
7419 if (mask
& (1 << new_base
))
7421 inst
.error
= _("invalid register list");
7425 if ((mask
>> new_base
) != 0 && ! warned
)
7427 as_tsktsk (_("register list not in ascending order"));
7431 mask
|= 1 << new_base
;
7434 skip_whitespace (*str
);
7436 if (**str
== '-') /* We have the start of a range expression */
7443 = arm_reg_parse (str
, all_reg_maps
[REG_TYPE_SN
].htab
))
7446 inst
.error
= _(all_reg_maps
[REG_TYPE_SN
].expected
);
7450 if (high_range
<= new_base
)
7452 inst
.error
= _("register range not in ascending order");
7456 for (new_base
++; new_base
<= high_range
; new_base
++)
7458 if (mask
& (1 << new_base
))
7460 inst
.error
= _("invalid register list");
7464 mask
|= 1 << new_base
;
7469 while (skip_past_comma (str
) != FAIL
);
7473 inst
.error
= _("invalid register list");
7481 /* Sanity check -- should have raised a parse error above. */
7482 if (count
== 0 || count
> 32)
7485 /* Final test -- the registers must be consecutive. */
7488 if ((mask
& (1 << base_reg
++)) == 0)
7490 inst
.error
= _("non-contiguous register range");
7495 inst
.instruction
= tempinst
| base_bits
;
7500 do_vfp_reg2_from_sp2 (char * str
)
7502 skip_whitespace (str
);
7504 if (reg_required_here (&str
, 12) == FAIL
7505 || skip_past_comma (&str
) == FAIL
7506 || reg_required_here (&str
, 16) == FAIL
7507 || skip_past_comma (&str
) == FAIL
)
7510 inst
.error
= BAD_ARGS
;
7514 /* We require exactly two consecutive SP registers. */
7515 if (vfp_sp_reg_list (&str
, VFP_REG_Sm
) != 2)
7518 inst
.error
= _("only two consecutive VFP SP registers allowed here");
7525 do_vfp_sp_from_reg (char * str
)
7527 skip_whitespace (str
);
7529 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
7532 if (skip_past_comma (&str
) == FAIL
7533 || reg_required_here (&str
, 12) == FAIL
)
7536 inst
.error
= BAD_ARGS
;
7544 do_vfp_sp2_from_reg2 (char * str
)
7546 skip_whitespace (str
);
7548 /* We require exactly two consecutive SP registers. */
7549 if (vfp_sp_reg_list (&str
, VFP_REG_Sm
) != 2)
7552 inst
.error
= _("only two consecutive VFP SP registers allowed here");
7555 if (skip_past_comma (&str
) == FAIL
7556 || reg_required_here (&str
, 12) == FAIL
7557 || skip_past_comma (&str
) == FAIL
7558 || reg_required_here (&str
, 16) == FAIL
)
7561 inst
.error
= BAD_ARGS
;
7569 do_vfp_reg_from_dp (char * str
)
7571 skip_whitespace (str
);
7573 if (reg_required_here (&str
, 12) == FAIL
)
7576 if (skip_past_comma (&str
) == FAIL
7577 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
7580 inst
.error
= BAD_ARGS
;
7588 do_vfp_reg2_from_dp (char * str
)
7590 skip_whitespace (str
);
7592 if (reg_required_here (&str
, 12) == FAIL
)
7595 if (skip_past_comma (&str
) == FAIL
7596 || reg_required_here (&str
, 16) == FAIL
7597 || skip_past_comma (&str
) == FAIL
7598 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7601 inst
.error
= BAD_ARGS
;
7609 do_vfp_dp_from_reg (char * str
)
7611 skip_whitespace (str
);
7613 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
7616 if (skip_past_comma (&str
) == FAIL
7617 || reg_required_here (&str
, 12) == FAIL
)
7620 inst
.error
= BAD_ARGS
;
7628 do_vfp_dp_from_reg2 (char * str
)
7630 skip_whitespace (str
);
7632 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7635 if (skip_past_comma (&str
) == FAIL
7636 || reg_required_here (&str
, 12) == FAIL
7637 || skip_past_comma (&str
) == FAIL
7638 || reg_required_here (&str
, 16) == FAIL
)
7641 inst
.error
= BAD_ARGS
;
7648 static const struct vfp_reg
*
7649 vfp_psr_parse (char ** str
)
7654 const struct vfp_reg
*vreg
;
7658 /* Find the end of the current token. */
7663 while (ISALPHA (c
));
7668 for (vreg
= vfp_regs
+ 0;
7669 vreg
< vfp_regs
+ sizeof (vfp_regs
) / sizeof (struct vfp_reg
);
7672 if (streq (start
, vreg
->name
))
7685 vfp_psr_required_here (char ** str
)
7688 const struct vfp_reg
*vreg
;
7690 vreg
= vfp_psr_parse (str
);
7694 inst
.instruction
|= vreg
->regno
;
7698 inst
.error
= _("VFP system register expected");
7705 do_vfp_reg_from_ctrl (char * str
)
7707 skip_whitespace (str
);
7709 if (reg_required_here (&str
, 12) == FAIL
)
7712 if (skip_past_comma (&str
) == FAIL
7713 || vfp_psr_required_here (&str
) == FAIL
)
7716 inst
.error
= BAD_ARGS
;
7724 do_vfp_ctrl_from_reg (char * str
)
7726 skip_whitespace (str
);
7728 if (vfp_psr_required_here (&str
) == FAIL
)
7731 if (skip_past_comma (&str
) == FAIL
7732 || reg_required_here (&str
, 12) == FAIL
)
7735 inst
.error
= BAD_ARGS
;
7743 do_vfp_sp_ldst (char * str
)
7745 skip_whitespace (str
);
7747 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7750 inst
.error
= BAD_ARGS
;
7754 if (skip_past_comma (&str
) == FAIL
7755 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
7758 inst
.error
= BAD_ARGS
;
7766 do_vfp_dp_ldst (char * str
)
7768 skip_whitespace (str
);
7770 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7773 inst
.error
= BAD_ARGS
;
7777 if (skip_past_comma (&str
) == FAIL
7778 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
7781 inst
.error
= BAD_ARGS
;
7789 vfp_dp_reg_list (char ** str
)
7796 unsigned long mask
= 0;
7803 skip_whitespace (*str
);
7805 tempinst
= inst
.instruction
;
7809 inst
.instruction
= 0;
7811 if ((new_base
= vfp_dp_reg_required_here (str
, VFP_REG_Dd
)) == FAIL
)
7814 if (count
== 0 || base_reg
> new_base
)
7816 base_reg
= new_base
;
7817 range
= inst
.instruction
;
7820 if (mask
& (1 << new_base
))
7822 inst
.error
= _("invalid register list");
7826 if ((mask
>> new_base
) != 0 && ! warned
)
7828 as_tsktsk (_("register list not in ascending order"));
7832 mask
|= 1 << new_base
;
7835 skip_whitespace (*str
);
7837 if (**str
== '-') /* We have the start of a range expression */
7844 = arm_reg_parse (str
, all_reg_maps
[REG_TYPE_DN
].htab
))
7847 inst
.error
= _(all_reg_maps
[REG_TYPE_DN
].expected
);
7851 if (high_range
<= new_base
)
7853 inst
.error
= _("register range not in ascending order");
7857 for (new_base
++; new_base
<= high_range
; new_base
++)
7859 if (mask
& (1 << new_base
))
7861 inst
.error
= _("invalid register list");
7865 mask
|= 1 << new_base
;
7870 while (skip_past_comma (str
) != FAIL
);
7874 inst
.error
= _("invalid register list");
7882 /* Sanity check -- should have raised a parse error above. */
7883 if (count
== 0 || count
> 16)
7886 /* Final test -- the registers must be consecutive. */
7889 if ((mask
& (1 << base_reg
++)) == 0)
7891 inst
.error
= _("non-contiguous register range");
7896 inst
.instruction
= tempinst
;
7901 vfp_sp_ldstm (char * str
, enum vfp_ldstm_type ldstm_type
)
7905 skip_whitespace (str
);
7907 if (reg_required_here (&str
, 16) == FAIL
)
7910 skip_whitespace (str
);
7914 inst
.instruction
|= WRITE_BACK
;
7917 else if (ldstm_type
!= VFP_LDSTMIA
)
7919 inst
.error
= _("this addressing mode requires base-register writeback");
7923 if (skip_past_comma (&str
) == FAIL
7924 || (range
= vfp_sp_reg_list (&str
, VFP_REG_Sd
)) == FAIL
)
7927 inst
.error
= BAD_ARGS
;
7931 inst
.instruction
|= range
;
7936 vfp_dp_ldstm (char * str
, enum vfp_ldstm_type ldstm_type
)
7940 skip_whitespace (str
);
7942 if (reg_required_here (&str
, 16) == FAIL
)
7945 skip_whitespace (str
);
7949 inst
.instruction
|= WRITE_BACK
;
7952 else if (ldstm_type
!= VFP_LDSTMIA
&& ldstm_type
!= VFP_LDSTMIAX
)
7954 inst
.error
= _("this addressing mode requires base-register writeback");
7958 if (skip_past_comma (&str
) == FAIL
7959 || (range
= vfp_dp_reg_list (&str
)) == FAIL
)
7962 inst
.error
= BAD_ARGS
;
7966 if (ldstm_type
== VFP_LDSTMIAX
|| ldstm_type
== VFP_LDSTMDBX
)
7969 inst
.instruction
|= range
;
7974 do_vfp_sp_ldstmia (char * str
)
7976 vfp_sp_ldstm (str
, VFP_LDSTMIA
);
7980 do_vfp_sp_ldstmdb (char * str
)
7982 vfp_sp_ldstm (str
, VFP_LDSTMDB
);
7986 do_vfp_dp_ldstmia (char * str
)
7988 vfp_dp_ldstm (str
, VFP_LDSTMIA
);
7992 do_vfp_dp_ldstmdb (char * str
)
7994 vfp_dp_ldstm (str
, VFP_LDSTMDB
);
7998 do_vfp_xp_ldstmia (char *str
)
8000 vfp_dp_ldstm (str
, VFP_LDSTMIAX
);
8004 do_vfp_xp_ldstmdb (char * str
)
8006 vfp_dp_ldstm (str
, VFP_LDSTMDBX
);
8010 do_vfp_sp_compare_z (char * str
)
8012 skip_whitespace (str
);
8014 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8017 inst
.error
= BAD_ARGS
;
8025 do_vfp_dp_compare_z (char * str
)
8027 skip_whitespace (str
);
8029 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8032 inst
.error
= BAD_ARGS
;
8040 do_vfp_dp_sp_cvt (char * str
)
8042 skip_whitespace (str
);
8044 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8047 if (skip_past_comma (&str
) == FAIL
8048 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
8051 inst
.error
= BAD_ARGS
;
8059 do_vfp_sp_dp_cvt (char * str
)
8061 skip_whitespace (str
);
8063 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8066 if (skip_past_comma (&str
) == FAIL
8067 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
8070 inst
.error
= BAD_ARGS
;
8077 /* Thumb specific routines. */
8079 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
8083 thumb_add_sub (char * str
, int subtract
)
8085 int Rd
, Rs
, Rn
= FAIL
;
8087 skip_whitespace (str
);
8089 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
8090 || skip_past_comma (&str
) == FAIL
)
8093 inst
.error
= BAD_ARGS
;
8097 if (is_immediate_prefix (*str
))
8101 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8106 if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8109 if (skip_past_comma (&str
) == FAIL
)
8111 /* Two operand format, shuffle the registers
8112 and pretend there are 3. */
8116 else if (is_immediate_prefix (*str
))
8119 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8122 else if ((Rn
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8126 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8127 for the latter case, EXPR contains the immediate that was found. */
8130 /* All register format. */
8131 if (Rd
> 7 || Rs
> 7 || Rn
> 7)
8135 inst
.error
= _("dest and source1 must be the same register");
8139 /* Can't do this for SUB. */
8142 inst
.error
= _("subtract valid only on lo regs");
8146 inst
.instruction
= (T_OPCODE_ADD_HI
8147 | (Rd
> 7 ? THUMB_H1
: 0)
8148 | (Rn
> 7 ? THUMB_H2
: 0));
8149 inst
.instruction
|= (Rd
& 7) | ((Rn
& 7) << 3);
8153 inst
.instruction
= subtract
? T_OPCODE_SUB_R3
: T_OPCODE_ADD_R3
;
8154 inst
.instruction
|= Rd
| (Rs
<< 3) | (Rn
<< 6);
8159 /* Immediate expression, now things start to get nasty. */
8161 /* First deal with HI regs, only very restricted cases allowed:
8162 Adjusting SP, and using PC or SP to get an address. */
8163 if ((Rd
> 7 && (Rd
!= REG_SP
|| Rs
!= REG_SP
))
8164 || (Rs
> 7 && Rs
!= REG_SP
&& Rs
!= REG_PC
))
8166 inst
.error
= _("invalid Hi register with immediate");
8170 if (inst
.reloc
.exp
.X_op
!= O_constant
)
8172 /* Value isn't known yet, all we can do is store all the fragments
8173 we know about in the instruction and let the reloc hacking
8175 inst
.instruction
= (subtract
? 0x8000 : 0) | (Rd
<< 4) | Rs
;
8176 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
8180 int offset
= inst
.reloc
.exp
.X_add_number
;
8190 /* Quick check, in case offset is MIN_INT. */
8193 inst
.error
= _("immediate value out of range");
8197 /* Note - you cannot convert a subtract of 0 into an
8198 add of 0 because the carry flag is set differently. */
8199 else if (offset
> 0)
8204 if (offset
& ~0x1fc)
8206 inst
.error
= _("invalid immediate value for stack adjust");
8209 inst
.instruction
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
8210 inst
.instruction
|= offset
>> 2;
8212 else if (Rs
== REG_PC
|| Rs
== REG_SP
)
8215 || (offset
& ~0x3fc))
8217 inst
.error
= _("invalid immediate for address calculation");
8220 inst
.instruction
= (Rs
== REG_PC
? T_OPCODE_ADD_PC
8222 inst
.instruction
|= (Rd
<< 8) | (offset
>> 2);
8228 inst
.error
= _("immediate value out of range");
8231 inst
.instruction
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
8232 inst
.instruction
|= (Rd
<< 8) | offset
;
8238 inst
.error
= _("immediate value out of range");
8241 inst
.instruction
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
8242 inst
.instruction
|= Rd
| (Rs
<< 3) | (offset
<< 6);
8251 thumb_shift (char * str
, int shift
)
8253 int Rd
, Rs
, Rn
= FAIL
;
8255 skip_whitespace (str
);
8257 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
8258 || skip_past_comma (&str
) == FAIL
)
8261 inst
.error
= BAD_ARGS
;
8265 if (is_immediate_prefix (*str
))
8267 /* Two operand immediate format, set Rs to Rd. */
8270 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8275 if ((Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8278 if (skip_past_comma (&str
) == FAIL
)
8280 /* Two operand format, shuffle the registers
8281 and pretend there are 3. */
8285 else if (is_immediate_prefix (*str
))
8288 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8291 else if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8295 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8296 for the latter case, EXPR contains the immediate that was found. */
8302 inst
.error
= _("source1 and dest must be same register");
8308 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_R
; break;
8309 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_R
; break;
8310 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_R
; break;
8313 inst
.instruction
|= Rd
| (Rn
<< 3);
8319 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_I
; break;
8320 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_I
; break;
8321 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_I
; break;
8324 if (inst
.reloc
.exp
.X_op
!= O_constant
)
8326 /* Value isn't known yet, create a dummy reloc and let reloc
8327 hacking fix it up. */
8328 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_SHIFT
;
8332 unsigned shift_value
= inst
.reloc
.exp
.X_add_number
;
8334 if (shift_value
> 32 || (shift_value
== 32 && shift
== THUMB_LSL
))
8336 inst
.error
= _("invalid immediate for shift");
8340 /* Shifts of zero are handled by converting to LSL. */
8341 if (shift_value
== 0)
8342 inst
.instruction
= T_OPCODE_LSL_I
;
8344 /* Shifts of 32 are encoded as a shift of zero. */
8345 if (shift_value
== 32)
8348 inst
.instruction
|= shift_value
<< 6;
8351 inst
.instruction
|= Rd
| (Rs
<< 3);
8358 thumb_load_store (char * str
, int load_store
, int size
)
8360 int Rd
, Rb
, Ro
= FAIL
;
8362 skip_whitespace (str
);
8364 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
8365 || skip_past_comma (&str
) == FAIL
)
8368 inst
.error
= BAD_ARGS
;
8375 if ((Rb
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8378 if (skip_past_comma (&str
) != FAIL
)
8380 if (is_immediate_prefix (*str
))
8383 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8386 else if ((Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8391 inst
.reloc
.exp
.X_op
= O_constant
;
8392 inst
.reloc
.exp
.X_add_number
= 0;
8397 inst
.error
= _("expected ']'");
8402 else if (*str
== '=')
8404 if (load_store
!= THUMB_LOAD
)
8406 inst
.error
= _("invalid pseudo operation");
8410 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
8413 skip_whitespace (str
);
8415 if (my_get_expression (& inst
.reloc
.exp
, & str
))
8420 if ( inst
.reloc
.exp
.X_op
!= O_constant
8421 && inst
.reloc
.exp
.X_op
!= O_symbol
)
8423 inst
.error
= "Constant expression expected";
8427 if (inst
.reloc
.exp
.X_op
== O_constant
8428 && ((inst
.reloc
.exp
.X_add_number
& ~0xFF) == 0))
8430 /* This can be done with a mov instruction. */
8432 inst
.instruction
= T_OPCODE_MOV_I8
| (Rd
<< 8);
8433 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
8437 /* Insert into literal pool. */
8438 if (add_to_lit_pool () == FAIL
)
8441 inst
.error
= "literal pool insertion failed";
8445 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8446 inst
.reloc
.pc_rel
= 1;
8447 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
8448 /* Adjust ARM pipeline offset to Thumb. */
8449 inst
.reloc
.exp
.X_add_number
+= 4;
8455 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8458 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
8459 inst
.reloc
.pc_rel
= 1;
8460 inst
.reloc
.exp
.X_add_number
-= 4; /* Pipeline offset. */
8461 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8466 if (Rb
== REG_PC
|| Rb
== REG_SP
)
8468 if (size
!= THUMB_WORD
)
8470 inst
.error
= _("byte or halfword not valid for base register");
8473 else if (Rb
== REG_PC
&& load_store
!= THUMB_LOAD
)
8475 inst
.error
= _("r15 based store not allowed");
8478 else if (Ro
!= FAIL
)
8480 inst
.error
= _("invalid base register for register offset");
8485 inst
.instruction
= T_OPCODE_LDR_PC
;
8486 else if (load_store
== THUMB_LOAD
)
8487 inst
.instruction
= T_OPCODE_LDR_SP
;
8489 inst
.instruction
= T_OPCODE_STR_SP
;
8491 inst
.instruction
|= Rd
<< 8;
8492 if (inst
.reloc
.exp
.X_op
== O_constant
)
8494 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
8496 if (offset
& ~0x3fc)
8498 inst
.error
= _("invalid offset");
8502 inst
.instruction
|= offset
>> 2;
8505 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8509 inst
.error
= _("invalid base register in load/store");
8512 else if (Ro
== FAIL
)
8514 /* Immediate offset. */
8515 if (size
== THUMB_WORD
)
8516 inst
.instruction
= (load_store
== THUMB_LOAD
8517 ? T_OPCODE_LDR_IW
: T_OPCODE_STR_IW
);
8518 else if (size
== THUMB_HALFWORD
)
8519 inst
.instruction
= (load_store
== THUMB_LOAD
8520 ? T_OPCODE_LDR_IH
: T_OPCODE_STR_IH
);
8522 inst
.instruction
= (load_store
== THUMB_LOAD
8523 ? T_OPCODE_LDR_IB
: T_OPCODE_STR_IB
);
8525 inst
.instruction
|= Rd
| (Rb
<< 3);
8527 if (inst
.reloc
.exp
.X_op
== O_constant
)
8529 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
8531 if (offset
& ~(0x1f << size
))
8533 inst
.error
= _("invalid offset");
8536 inst
.instruction
|= (offset
>> size
) << 6;
8539 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8543 /* Register offset. */
8544 if (size
== THUMB_WORD
)
8545 inst
.instruction
= (load_store
== THUMB_LOAD
8546 ? T_OPCODE_LDR_RW
: T_OPCODE_STR_RW
);
8547 else if (size
== THUMB_HALFWORD
)
8548 inst
.instruction
= (load_store
== THUMB_LOAD
8549 ? T_OPCODE_LDR_RH
: T_OPCODE_STR_RH
);
8551 inst
.instruction
= (load_store
== THUMB_LOAD
8552 ? T_OPCODE_LDR_RB
: T_OPCODE_STR_RB
);
8554 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
8560 /* A register must be given at this point.
8562 Shift is the place to put it in inst.instruction.
8564 Restores input start point on err.
8565 Returns the reg#, or FAIL. */
8568 mav_reg_required_here (char ** str
, int shift
, enum arm_reg_type regtype
)
8573 if ((reg
= arm_reg_parse (str
, all_reg_maps
[regtype
].htab
)) != FAIL
)
8576 inst
.instruction
|= reg
<< shift
;
8581 /* Restore the start point. */
8584 /* Try generic coprocessor name if applicable. */
8585 if (regtype
== REG_TYPE_MVF
||
8586 regtype
== REG_TYPE_MVD
||
8587 regtype
== REG_TYPE_MVFX
||
8588 regtype
== REG_TYPE_MVDX
)
8590 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CN
].htab
)) != FAIL
)
8593 inst
.instruction
|= reg
<< shift
;
8598 /* Restore the start point. */
8602 /* In the few cases where we might be able to accept something else
8603 this error can be overridden. */
8604 inst
.error
= _(all_reg_maps
[regtype
].expected
);
8609 /* Cirrus Maverick Instructions. */
8611 /* Isnsn like "foo X,Y". */
8614 do_mav_binops (char * str
,
8616 enum arm_reg_type reg0
,
8617 enum arm_reg_type reg1
)
8621 shift0
= mode
& 0xff;
8622 shift1
= (mode
>> 8) & 0xff;
8624 skip_whitespace (str
);
8626 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
8627 || skip_past_comma (&str
) == FAIL
8628 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
)
8631 inst
.error
= BAD_ARGS
;
8637 /* Isnsn like "foo X,Y,Z". */
8640 do_mav_triple (char * str
,
8642 enum arm_reg_type reg0
,
8643 enum arm_reg_type reg1
,
8644 enum arm_reg_type reg2
)
8646 int shift0
, shift1
, shift2
;
8648 shift0
= mode
& 0xff;
8649 shift1
= (mode
>> 8) & 0xff;
8650 shift2
= (mode
>> 16) & 0xff;
8652 skip_whitespace (str
);
8654 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
8655 || skip_past_comma (&str
) == FAIL
8656 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
8657 || skip_past_comma (&str
) == FAIL
8658 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
)
8661 inst
.error
= BAD_ARGS
;
8667 /* Wrapper functions. */
8670 do_mav_binops_1a (char * str
)
8672 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVF
);
8676 do_mav_binops_1b (char * str
)
8678 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVD
);
8682 do_mav_binops_1c (char * str
)
8684 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVDX
);
8688 do_mav_binops_1d (char * str
)
8690 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVF
);
8694 do_mav_binops_1e (char * str
)
8696 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVD
);
8700 do_mav_binops_1f (char * str
)
8702 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVF
);
8706 do_mav_binops_1g (char * str
)
8708 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVD
);
8712 do_mav_binops_1h (char * str
)
8714 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVFX
);
8718 do_mav_binops_1i (char * str
)
8720 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVFX
);
8724 do_mav_binops_1j (char * str
)
8726 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVDX
);
8730 do_mav_binops_1k (char * str
)
8732 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVDX
);
8736 do_mav_binops_1l (char * str
)
8738 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVF
);
8742 do_mav_binops_1m (char * str
)
8744 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVD
);
8748 do_mav_binops_1n (char * str
)
8750 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
8754 do_mav_binops_1o (char * str
)
8756 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
8760 do_mav_binops_2a (char * str
)
8762 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVF
, REG_TYPE_RN
);
8766 do_mav_binops_2b (char * str
)
8768 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVD
, REG_TYPE_RN
);
8772 do_mav_binops_2c (char * str
)
8774 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVDX
, REG_TYPE_RN
);
8778 do_mav_binops_3a (char * str
)
8780 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVFX
);
8784 do_mav_binops_3b (char * str
)
8786 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVFX
, REG_TYPE_MVAX
);
8790 do_mav_binops_3c (char * str
)
8792 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVDX
);
8796 do_mav_binops_3d (char * str
)
8798 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVDX
, REG_TYPE_MVAX
);
8802 do_mav_triple_4a (char * str
)
8804 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_RN
);
8808 do_mav_triple_4b (char * str
)
8810 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_RN
);
8814 do_mav_triple_5a (char * str
)
8816 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVF
, REG_TYPE_MVF
);
8820 do_mav_triple_5b (char * str
)
8822 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVD
, REG_TYPE_MVD
);
8826 do_mav_triple_5c (char * str
)
8828 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
8832 do_mav_triple_5d (char * str
)
8834 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
8838 do_mav_triple_5e (char * str
)
8840 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVF
, REG_TYPE_MVF
, REG_TYPE_MVF
);
8844 do_mav_triple_5f (char * str
)
8846 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVD
, REG_TYPE_MVD
, REG_TYPE_MVD
);
8850 do_mav_triple_5g (char * str
)
8852 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
8856 do_mav_triple_5h (char * str
)
8858 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
8861 /* Isnsn like "foo W,X,Y,Z".
8862 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
8865 do_mav_quad (char * str
,
8867 enum arm_reg_type reg0
,
8868 enum arm_reg_type reg1
,
8869 enum arm_reg_type reg2
,
8870 enum arm_reg_type reg3
)
8872 int shift0
, shift1
, shift2
, shift3
;
8874 shift0
= mode
& 0xff;
8875 shift1
= (mode
>> 8) & 0xff;
8876 shift2
= (mode
>> 16) & 0xff;
8877 shift3
= (mode
>> 24) & 0xff;
8879 skip_whitespace (str
);
8881 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
8882 || skip_past_comma (&str
) == FAIL
8883 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
8884 || skip_past_comma (&str
) == FAIL
8885 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
8886 || skip_past_comma (&str
) == FAIL
8887 || mav_reg_required_here (&str
, shift3
, reg3
) == FAIL
)
8890 inst
.error
= BAD_ARGS
;
8897 do_mav_quad_6a (char * str
)
8899 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
,
8904 do_mav_quad_6b (char * str
)
8906 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVAX
, REG_TYPE_MVFX
,
8910 /* cfmvsc32<cond> DSPSC,MVDX[15:0]. */
8912 do_mav_dspsc_1 (char * str
)
8914 skip_whitespace (str
);
8917 if (mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
8918 || skip_past_comma (&str
) == FAIL
8919 || mav_reg_required_here (&str
, 12, REG_TYPE_MVDX
) == FAIL
)
8922 inst
.error
= BAD_ARGS
;
8930 /* cfmv32sc<cond> MVDX[15:0],DSPSC. */
8932 do_mav_dspsc_2 (char * str
)
8934 skip_whitespace (str
);
8937 if (mav_reg_required_here (&str
, 12, REG_TYPE_MVDX
) == FAIL
8938 || skip_past_comma (&str
) == FAIL
8939 || mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
)
8942 inst
.error
= BAD_ARGS
;
8950 /* Maverick shift immediate instructions.
8951 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
8952 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
8955 do_mav_shift (char * str
,
8956 enum arm_reg_type reg0
,
8957 enum arm_reg_type reg1
)
8962 skip_whitespace (str
);
8966 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
8967 || skip_past_comma (&str
) == FAIL
8968 || mav_reg_required_here (&str
, 16, reg1
) == FAIL
8969 || skip_past_comma (&str
) == FAIL
)
8972 inst
.error
= BAD_ARGS
;
8976 /* Calculate the immediate operand.
8977 The operand is a 7bit signed number. */
8978 skip_whitespace (str
);
8983 if (!ISDIGIT (*str
) && *str
!= '-')
8985 inst
.error
= _("expecting immediate, 7bit operand");
8995 for (imm
= 0; *str
&& ISDIGIT (*str
); ++str
)
8996 imm
= imm
* 10 + *str
- '0';
9000 inst
.error
= _("immediate out of range");
9004 /* Make negative imm's into 7bit signed numbers. */
9011 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
9012 Bits 5-7 of the insn should have bits 4-6 of the immediate.
9013 Bit 4 should be 0. */
9014 imm
= (imm
& 0xf) | ((imm
& 0x70) << 1);
9016 inst
.instruction
|= imm
;
9021 do_mav_shift_1 (char * str
)
9023 do_mav_shift (str
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
9027 do_mav_shift_2 (char * str
)
9029 do_mav_shift (str
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
9033 mav_parse_offset (char ** str
, int * negative
)
9040 skip_whitespace (p
);
9053 inst
.error
= _("offset expected");
9057 for (offset
= 0; *p
&& ISDIGIT (*p
); ++p
)
9058 offset
= offset
* 10 + *p
- '0';
9062 inst
.error
= _("offset out of range");
9067 inst
.error
= _("offset not a multiple of 4");
9073 return *negative
? -offset
: offset
;
9076 /* Maverick load/store instructions.
9077 <insn><cond> CRd,[Rn,<offset>]{!}.
9078 <insn><cond> CRd,[Rn],<offset>. */
9081 do_mav_ldst (char * str
, enum arm_reg_type reg0
)
9083 int offset
, negative
;
9085 skip_whitespace (str
);
9087 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
9088 || skip_past_comma (&str
) == FAIL
9090 || reg_required_here (&str
, 16) == FAIL
)
9093 if (skip_past_comma (&str
) == SUCCESS
)
9095 /* You are here: "<offset>]{!}". */
9096 inst
.instruction
|= PRE_INDEX
;
9098 offset
= mav_parse_offset (&str
, &negative
);
9105 inst
.error
= _("missing ]");
9111 inst
.instruction
|= WRITE_BACK
;
9117 /* You are here: "], <offset>". */
9120 inst
.error
= _("missing ]");
9124 if (skip_past_comma (&str
) == FAIL
9125 || (offset
= mav_parse_offset (&str
, &negative
), inst
.error
))
9128 inst
.instruction
|= CP_T_WB
; /* Post indexed, set bit W. */
9134 inst
.instruction
|= CP_T_UD
; /* Positive, so set bit U. */
9136 inst
.instruction
|= offset
>> 2;
9142 inst
.error
= BAD_ARGS
;
9146 do_mav_ldst_1 (char * str
)
9148 do_mav_ldst (str
, REG_TYPE_MVF
);
9152 do_mav_ldst_2 (char * str
)
9154 do_mav_ldst (str
, REG_TYPE_MVD
);
9158 do_mav_ldst_3 (char * str
)
9160 do_mav_ldst (str
, REG_TYPE_MVFX
);
9164 do_mav_ldst_4 (char * str
)
9166 do_mav_ldst (str
, REG_TYPE_MVDX
);
9170 do_t_nop (char * str
)
9176 /* Handle the Format 4 instructions that do not have equivalents in other
9177 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
9181 do_t_arit (char * str
)
9185 skip_whitespace (str
);
9187 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9188 || skip_past_comma (&str
) == FAIL
9189 || (Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9191 inst
.error
= BAD_ARGS
;
9195 if (skip_past_comma (&str
) != FAIL
)
9197 /* Three operand format not allowed for TST, CMN, NEG and MVN.
9198 (It isn't allowed for CMP either, but that isn't handled by this
9200 if (inst
.instruction
== T_OPCODE_TST
9201 || inst
.instruction
== T_OPCODE_CMN
9202 || inst
.instruction
== T_OPCODE_NEG
9203 || inst
.instruction
== T_OPCODE_MVN
)
9205 inst
.error
= BAD_ARGS
;
9209 if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9214 inst
.error
= _("dest and source1 must be the same register");
9220 if (inst
.instruction
== T_OPCODE_MUL
9222 as_tsktsk (_("Rs and Rd must be different in MUL"));
9224 inst
.instruction
|= Rd
| (Rs
<< 3);
9229 do_t_add (char * str
)
9231 thumb_add_sub (str
, 0);
9235 do_t_asr (char * str
)
9237 thumb_shift (str
, THUMB_ASR
);
9241 do_t_branch9 (char * str
)
9243 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9245 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH9
;
9246 inst
.reloc
.pc_rel
= 1;
9251 do_t_branch12 (char * str
)
9253 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9255 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH12
;
9256 inst
.reloc
.pc_rel
= 1;
9260 /* Find the real, Thumb encoded start of a Thumb function. */
9263 find_real_start (symbolS
* symbolP
)
9266 const char * name
= S_GET_NAME (symbolP
);
9267 symbolS
* new_target
;
9269 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
9270 #define STUB_NAME ".real_start_of"
9275 /* Names that start with '.' are local labels, not function entry points.
9276 The compiler may generate BL instructions to these labels because it
9277 needs to perform a branch to a far away location. */
9281 real_start
= malloc (strlen (name
) + strlen (STUB_NAME
) + 1);
9282 sprintf (real_start
, "%s%s", STUB_NAME
, name
);
9284 new_target
= symbol_find (real_start
);
9286 if (new_target
== NULL
)
9288 as_warn ("Failed to find real start of function: %s\n", name
);
9289 new_target
= symbolP
;
9298 do_t_branch23 (char * str
)
9300 if (my_get_expression (& inst
.reloc
.exp
, & str
))
9303 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH23
;
9304 inst
.reloc
.pc_rel
= 1;
9307 /* If the destination of the branch is a defined symbol which does not have
9308 the THUMB_FUNC attribute, then we must be calling a function which has
9309 the (interfacearm) attribute. We look for the Thumb entry point to that
9310 function and change the branch to refer to that function instead. */
9311 if ( inst
.reloc
.exp
.X_op
== O_symbol
9312 && inst
.reloc
.exp
.X_add_symbol
!= NULL
9313 && S_IS_DEFINED (inst
.reloc
.exp
.X_add_symbol
)
9314 && ! THUMB_IS_FUNC (inst
.reloc
.exp
.X_add_symbol
))
9315 inst
.reloc
.exp
.X_add_symbol
=
9316 find_real_start (inst
.reloc
.exp
.X_add_symbol
);
9320 do_t_bx (char * str
)
9324 skip_whitespace (str
);
9326 if ((reg
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
9329 /* This sets THUMB_H2 from the top bit of reg. */
9330 inst
.instruction
|= reg
<< 3;
9332 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
9333 should cause the alignment to be checked once it is known. This is
9334 because BX PC only works if the instruction is word aligned. */
9340 do_t_compare (char * str
)
9342 thumb_mov_compare (str
, THUMB_COMPARE
);
9346 do_t_ldmstm (char * str
)
9351 skip_whitespace (str
);
9353 if ((Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9357 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
9361 if (skip_past_comma (&str
) == FAIL
9362 || (range
= reg_list (&str
)) == FAIL
)
9365 inst
.error
= BAD_ARGS
;
9369 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
9371 /* This really doesn't seem worth it. */
9372 inst
.reloc
.type
= BFD_RELOC_NONE
;
9373 inst
.error
= _("expression too complex");
9379 inst
.error
= _("only lo-regs valid in load/store multiple");
9383 inst
.instruction
|= (Rb
<< 8) | range
;
9388 do_t_ldr (char * str
)
9390 thumb_load_store (str
, THUMB_LOAD
, THUMB_WORD
);
9394 do_t_ldrb (char * str
)
9396 thumb_load_store (str
, THUMB_LOAD
, THUMB_BYTE
);
9400 do_t_ldrh (char * str
)
9402 thumb_load_store (str
, THUMB_LOAD
, THUMB_HALFWORD
);
9406 do_t_lds (char * str
)
9410 skip_whitespace (str
);
9412 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9413 || skip_past_comma (&str
) == FAIL
9415 || (Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9416 || skip_past_comma (&str
) == FAIL
9417 || (Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9421 inst
.error
= _("syntax: ldrs[b] Rd, [Rb, Ro]");
9425 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
9430 do_t_lsl (char * str
)
9432 thumb_shift (str
, THUMB_LSL
);
9436 do_t_lsr (char * str
)
9438 thumb_shift (str
, THUMB_LSR
);
9442 do_t_mov (char * str
)
9444 thumb_mov_compare (str
, THUMB_MOVE
);
9448 do_t_push_pop (char * str
)
9452 skip_whitespace (str
);
9454 if ((range
= reg_list (&str
)) == FAIL
)
9457 inst
.error
= BAD_ARGS
;
9461 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
9463 /* This really doesn't seem worth it. */
9464 inst
.reloc
.type
= BFD_RELOC_NONE
;
9465 inst
.error
= _("expression too complex");
9471 if ((inst
.instruction
== T_OPCODE_PUSH
9472 && (range
& ~0xff) == 1 << REG_LR
)
9473 || (inst
.instruction
== T_OPCODE_POP
9474 && (range
& ~0xff) == 1 << REG_PC
))
9476 inst
.instruction
|= THUMB_PP_PC_LR
;
9481 inst
.error
= _("invalid register list to push/pop instruction");
9486 inst
.instruction
|= range
;
9491 do_t_str (char * str
)
9493 thumb_load_store (str
, THUMB_STORE
, THUMB_WORD
);
9497 do_t_strb (char * str
)
9499 thumb_load_store (str
, THUMB_STORE
, THUMB_BYTE
);
9503 do_t_strh (char * str
)
9505 thumb_load_store (str
, THUMB_STORE
, THUMB_HALFWORD
);
9509 do_t_sub (char * str
)
9511 thumb_add_sub (str
, 1);
9515 do_t_swi (char * str
)
9517 skip_whitespace (str
);
9519 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9522 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
9527 do_t_adr (char * str
)
9531 /* This is a pseudo-op of the form "adr rd, label" to be converted
9532 into a relative address of the form "add rd, pc, #label-.-4". */
9533 skip_whitespace (str
);
9535 /* Store Rd in temporary location inside instruction. */
9536 if ((reg
= reg_required_here (&str
, 4)) == FAIL
9537 || (reg
> 7) /* For Thumb reg must be r0..r7. */
9538 || skip_past_comma (&str
) == FAIL
9539 || my_get_expression (&inst
.reloc
.exp
, &str
))
9542 inst
.error
= BAD_ARGS
;
9546 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
9547 inst
.reloc
.exp
.X_add_number
-= 4; /* PC relative adjust. */
9548 inst
.reloc
.pc_rel
= 1;
9549 inst
.instruction
|= REG_PC
; /* Rd is already placed into the instruction. */
9555 insert_reg (const struct reg_entry
* r
,
9556 struct hash_control
* htab
)
9558 int len
= strlen (r
->name
) + 2;
9559 char * buf
= xmalloc (len
);
9560 char * buf2
= xmalloc (len
);
9563 #ifdef REGISTER_PREFIX
9564 buf
[i
++] = REGISTER_PREFIX
;
9567 strcpy (buf
+ i
, r
->name
);
9569 for (i
= 0; buf
[i
]; i
++)
9570 buf2
[i
] = TOUPPER (buf
[i
]);
9574 hash_insert (htab
, buf
, (PTR
) r
);
9575 hash_insert (htab
, buf2
, (PTR
) r
);
9579 build_reg_hsh (struct reg_map
* map
)
9581 const struct reg_entry
*r
;
9583 if ((map
->htab
= hash_new ()) == NULL
)
9584 as_fatal (_("virtual memory exhausted"));
9586 for (r
= map
->names
; r
->name
!= NULL
; r
++)
9587 insert_reg (r
, map
->htab
);
9591 insert_reg_alias (char * str
,
9593 struct hash_control
*htab
)
9596 struct reg_entry
* new = xmalloc (sizeof (struct reg_entry
));
9597 const char * name
= xmalloc (strlen (str
) + 1);
9599 strcpy ((char *) name
, str
);
9602 new->number
= regnum
;
9603 new->builtin
= FALSE
;
9605 error
= hash_insert (htab
, name
, (PTR
) new);
9608 as_bad (_("failed to create an alias for %s, reason: %s"),
9610 free ((char *) name
);
9615 /* Look for the .req directive. This is of the form:
9617 new_register_name .req existing_register_name
9619 If we find one, or if it looks sufficiently like one that we want to
9620 handle any error here, return non-zero. Otherwise return zero. */
9623 create_register_alias (char * newname
, char * p
)
9629 skip_whitespace (q
);
9634 if (*q
&& !strncmp (q
, ".req ", 5))
9639 #ifndef IGNORE_OPCODE_CASE
9640 newname
= original_case_string
;
9642 copy_of_str
= newname
;
9645 skip_whitespace (q
);
9647 for (r
= q
; *r
!= '\0'; r
++)
9653 enum arm_reg_type new_type
, old_type
;
9658 old_type
= arm_reg_parse_any (q
);
9661 new_type
= arm_reg_parse_any (newname
);
9663 if (new_type
== REG_TYPE_MAX
)
9665 if (old_type
!= REG_TYPE_MAX
)
9667 old_regno
= arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
);
9668 insert_reg_alias (newname
, old_regno
,
9669 all_reg_maps
[old_type
].htab
);
9672 as_warn (_("register '%s' does not exist\n"), q
);
9674 else if (old_type
== REG_TYPE_MAX
)
9676 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
9681 /* Do not warn about redefinitions to the same alias. */
9682 if (new_type
!= old_type
9683 || (arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
)
9684 != arm_reg_parse (&q
, all_reg_maps
[new_type
].htab
)))
9685 as_warn (_("ignoring redefinition of register alias '%s'"),
9691 as_warn (_("ignoring incomplete .req pseuso op"));
9702 set_constant_flonums (void)
9706 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
9707 if (atof_ieee ((char *) fp_const
[i
], 'x', fp_values
[i
]) == NULL
)
9712 static const struct asm_opcode insns
[] =
9714 /* Core ARM Instructions. */
9715 {"and", 0xe0000000, 3, ARM_EXT_V1
, do_arit
},
9716 {"ands", 0xe0100000, 3, ARM_EXT_V1
, do_arit
},
9717 {"eor", 0xe0200000, 3, ARM_EXT_V1
, do_arit
},
9718 {"eors", 0xe0300000, 3, ARM_EXT_V1
, do_arit
},
9719 {"sub", 0xe0400000, 3, ARM_EXT_V1
, do_arit
},
9720 {"subs", 0xe0500000, 3, ARM_EXT_V1
, do_arit
},
9721 {"rsb", 0xe0600000, 3, ARM_EXT_V1
, do_arit
},
9722 {"rsbs", 0xe0700000, 3, ARM_EXT_V1
, do_arit
},
9723 {"add", 0xe0800000, 3, ARM_EXT_V1
, do_arit
},
9724 {"adds", 0xe0900000, 3, ARM_EXT_V1
, do_arit
},
9725 {"adc", 0xe0a00000, 3, ARM_EXT_V1
, do_arit
},
9726 {"adcs", 0xe0b00000, 3, ARM_EXT_V1
, do_arit
},
9727 {"sbc", 0xe0c00000, 3, ARM_EXT_V1
, do_arit
},
9728 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1
, do_arit
},
9729 {"rsc", 0xe0e00000, 3, ARM_EXT_V1
, do_arit
},
9730 {"rscs", 0xe0f00000, 3, ARM_EXT_V1
, do_arit
},
9731 {"orr", 0xe1800000, 3, ARM_EXT_V1
, do_arit
},
9732 {"orrs", 0xe1900000, 3, ARM_EXT_V1
, do_arit
},
9733 {"bic", 0xe1c00000, 3, ARM_EXT_V1
, do_arit
},
9734 {"bics", 0xe1d00000, 3, ARM_EXT_V1
, do_arit
},
9736 {"tst", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
9737 {"tsts", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
9738 {"tstp", 0xe110f000, 3, ARM_EXT_V1
, do_cmp
},
9739 {"teq", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
9740 {"teqs", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
9741 {"teqp", 0xe130f000, 3, ARM_EXT_V1
, do_cmp
},
9742 {"cmp", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
9743 {"cmps", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
9744 {"cmpp", 0xe150f000, 3, ARM_EXT_V1
, do_cmp
},
9745 {"cmn", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
9746 {"cmns", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
9747 {"cmnp", 0xe170f000, 3, ARM_EXT_V1
, do_cmp
},
9749 {"mov", 0xe1a00000, 3, ARM_EXT_V1
, do_mov
},
9750 {"movs", 0xe1b00000, 3, ARM_EXT_V1
, do_mov
},
9751 {"mvn", 0xe1e00000, 3, ARM_EXT_V1
, do_mov
},
9752 {"mvns", 0xe1f00000, 3, ARM_EXT_V1
, do_mov
},
9754 {"ldr", 0xe4100000, 3, ARM_EXT_V1
, do_ldst
},
9755 {"ldrb", 0xe4500000, 3, ARM_EXT_V1
, do_ldst
},
9756 {"ldrt", 0xe4300000, 3, ARM_EXT_V1
, do_ldstt
},
9757 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1
, do_ldstt
},
9758 {"str", 0xe4000000, 3, ARM_EXT_V1
, do_ldst
},
9759 {"strb", 0xe4400000, 3, ARM_EXT_V1
, do_ldst
},
9760 {"strt", 0xe4200000, 3, ARM_EXT_V1
, do_ldstt
},
9761 {"strbt", 0xe4600000, 3, ARM_EXT_V1
, do_ldstt
},
9763 {"stmia", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
9764 {"stmib", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
9765 {"stmda", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
9766 {"stmdb", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
9767 {"stmfd", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
9768 {"stmfa", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
9769 {"stmea", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
9770 {"stmed", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
9772 {"ldmia", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
9773 {"ldmib", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
9774 {"ldmda", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
9775 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
9776 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
9777 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
9778 {"ldmea", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
9779 {"ldmed", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
9781 {"swi", 0xef000000, 3, ARM_EXT_V1
, do_swi
},
9783 /* XXX This is the wrong place to do this. Think multi-arch. */
9784 {"bl", 0xeb000000, 2, ARM_EXT_V1
, do_branch
},
9785 {"b", 0xea000000, 1, ARM_EXT_V1
, do_branch
},
9787 {"bl", 0xebfffffe, 2, ARM_EXT_V1
, do_branch
},
9788 {"b", 0xeafffffe, 1, ARM_EXT_V1
, do_branch
},
9792 {"adr", 0xe28f0000, 3, ARM_EXT_V1
, do_adr
},
9793 {"adrl", 0xe28f0000, 3, ARM_EXT_V1
, do_adrl
},
9794 {"nop", 0xe1a00000, 3, ARM_EXT_V1
, do_empty
},
9796 /* ARM 2 multiplies. */
9797 {"mul", 0xe0000090, 3, ARM_EXT_V2
, do_mul
},
9798 {"muls", 0xe0100090, 3, ARM_EXT_V2
, do_mul
},
9799 {"mla", 0xe0200090, 3, ARM_EXT_V2
, do_mla
},
9800 {"mlas", 0xe0300090, 3, ARM_EXT_V2
, do_mla
},
9802 /* Generic coprocessor instructions. */
9803 {"cdp", 0xee000000, 3, ARM_EXT_V2
, do_cdp
},
9804 {"ldc", 0xec100000, 3, ARM_EXT_V2
, do_lstc
},
9805 {"ldcl", 0xec500000, 3, ARM_EXT_V2
, do_lstc
},
9806 {"stc", 0xec000000, 3, ARM_EXT_V2
, do_lstc
},
9807 {"stcl", 0xec400000, 3, ARM_EXT_V2
, do_lstc
},
9808 {"mcr", 0xee000010, 3, ARM_EXT_V2
, do_co_reg
},
9809 {"mrc", 0xee100010, 3, ARM_EXT_V2
, do_co_reg
},
9811 /* ARM 3 - swp instructions. */
9812 {"swp", 0xe1000090, 3, ARM_EXT_V2S
, do_swap
},
9813 {"swpb", 0xe1400090, 3, ARM_EXT_V2S
, do_swap
},
9815 /* ARM 6 Status register instructions. */
9816 {"mrs", 0xe10f0000, 3, ARM_EXT_V3
, do_mrs
},
9817 {"msr", 0xe120f000, 3, ARM_EXT_V3
, do_msr
},
9818 /* ScottB: our code uses 0xe128f000 for msr.
9819 NickC: but this is wrong because the bits 16 through 19 are
9820 handled by the PSR_xxx defines above. */
9822 /* ARM 7M long multiplies. */
9823 {"smull", 0xe0c00090, 5, ARM_EXT_V3M
, do_mull
},
9824 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M
, do_mull
},
9825 {"umull", 0xe0800090, 5, ARM_EXT_V3M
, do_mull
},
9826 {"umulls", 0xe0900090, 5, ARM_EXT_V3M
, do_mull
},
9827 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M
, do_mull
},
9828 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M
, do_mull
},
9829 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M
, do_mull
},
9830 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M
, do_mull
},
9832 /* ARM Architecture 4. */
9833 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4
, do_ldstv4
},
9834 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4
, do_ldstv4
},
9835 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4
, do_ldstv4
},
9836 {"strh", 0xe00000b0, 3, ARM_EXT_V4
, do_ldstv4
},
9838 /* ARM Architecture 4T. */
9839 /* Note: bx (and blx) are required on V5, even if the processor does
9840 not support Thumb. */
9841 {"bx", 0xe12fff10, 2, ARM_EXT_V4T
| ARM_EXT_V5
, do_bx
},
9843 /* ARM Architecture 5T. */
9844 /* Note: blx has 2 variants, so the .value is set dynamically.
9845 Only one of the variants has conditional execution. */
9846 {"blx", 0xe0000000, 3, ARM_EXT_V5
, do_blx
},
9847 {"clz", 0xe16f0f10, 3, ARM_EXT_V5
, do_clz
},
9848 {"bkpt", 0xe1200070, 0, ARM_EXT_V5
, do_bkpt
},
9849 {"ldc2", 0xfc100000, 0, ARM_EXT_V5
, do_lstc2
},
9850 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5
, do_lstc2
},
9851 {"stc2", 0xfc000000, 0, ARM_EXT_V5
, do_lstc2
},
9852 {"stc2l", 0xfc400000, 0, ARM_EXT_V5
, do_lstc2
},
9853 {"cdp2", 0xfe000000, 0, ARM_EXT_V5
, do_cdp2
},
9854 {"mcr2", 0xfe000010, 0, ARM_EXT_V5
, do_co_reg2
},
9855 {"mrc2", 0xfe100010, 0, ARM_EXT_V5
, do_co_reg2
},
9857 /* ARM Architecture 5TExP. */
9858 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP
, do_smla
},
9859 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP
, do_smla
},
9860 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP
, do_smla
},
9861 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP
, do_smla
},
9863 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP
, do_smla
},
9864 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP
, do_smla
},
9866 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP
, do_smlal
},
9867 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP
, do_smlal
},
9868 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP
, do_smlal
},
9869 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP
, do_smlal
},
9871 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP
, do_smul
},
9872 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP
, do_smul
},
9873 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP
, do_smul
},
9874 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP
, do_smul
},
9876 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP
, do_smul
},
9877 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP
, do_smul
},
9879 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP
, do_qadd
},
9880 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP
, do_qadd
},
9881 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP
, do_qadd
},
9882 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP
, do_qadd
},
9884 /* ARM Architecture 5TE. */
9885 {"pld", 0xf450f000, 0, ARM_EXT_V5E
, do_pld
},
9886 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E
, do_ldrd
},
9887 {"strd", 0xe00000f0, 3, ARM_EXT_V5E
, do_ldrd
},
9889 {"mcrr", 0xec400000, 4, ARM_EXT_V5E
, do_co_reg2c
},
9890 {"mrrc", 0xec500000, 4, ARM_EXT_V5E
, do_co_reg2c
},
9892 /* ARM Architecture 5TEJ. */
9893 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J
, do_bxj
},
9896 { "cps", 0xf1020000, 0, ARM_EXT_V6
, do_cps
},
9897 { "cpsie", 0xf1080000, 0, ARM_EXT_V6
, do_cpsi
},
9898 { "cpsid", 0xf10C0000, 0, ARM_EXT_V6
, do_cpsi
},
9899 { "ldrex", 0xe1900f9f, 5, ARM_EXT_V6
, do_ldrex
},
9900 { "mcrr2", 0xfc400000, 0, ARM_EXT_V6
, do_co_reg2c
},
9901 { "mrrc2", 0xfc500000, 0, ARM_EXT_V6
, do_co_reg2c
},
9902 { "pkhbt", 0xe6800010, 5, ARM_EXT_V6
, do_pkhbt
},
9903 { "pkhtb", 0xe6800050, 5, ARM_EXT_V6
, do_pkhtb
},
9904 { "qadd16", 0xe6200f10, 6, ARM_EXT_V6
, do_qadd16
},
9905 { "qadd8", 0xe6200f90, 5, ARM_EXT_V6
, do_qadd16
},
9906 { "qaddsubx", 0xe6200f30, 8, ARM_EXT_V6
, do_qadd16
},
9907 { "qsub16", 0xe6200f70, 6, ARM_EXT_V6
, do_qadd16
},
9908 { "qsub8", 0xe6200ff0, 5, ARM_EXT_V6
, do_qadd16
},
9909 { "qsubaddx", 0xe6200f50, 8, ARM_EXT_V6
, do_qadd16
},
9910 { "sadd16", 0xe6100f10, 6, ARM_EXT_V6
, do_qadd16
},
9911 { "sadd8", 0xe6100f90, 5, ARM_EXT_V6
, do_qadd16
},
9912 { "saddsubx", 0xe6100f30, 8, ARM_EXT_V6
, do_qadd16
},
9913 { "shadd16", 0xe6300f10, 7, ARM_EXT_V6
, do_qadd16
},
9914 { "shadd8", 0xe6300f90, 6, ARM_EXT_V6
, do_qadd16
},
9915 { "shaddsubx", 0xe6300f30, 9, ARM_EXT_V6
, do_qadd16
},
9916 { "shsub16", 0xe6300f70, 7, ARM_EXT_V6
, do_qadd16
},
9917 { "shsub8", 0xe6300ff0, 6, ARM_EXT_V6
, do_qadd16
},
9918 { "shsubaddx", 0xe6300f50, 9, ARM_EXT_V6
, do_qadd16
},
9919 { "ssub16", 0xe6100f70, 6, ARM_EXT_V6
, do_qadd16
},
9920 { "ssub8", 0xe6100ff0, 5, ARM_EXT_V6
, do_qadd16
},
9921 { "ssubaddx", 0xe6100f50, 8, ARM_EXT_V6
, do_qadd16
},
9922 { "uadd16", 0xe6500f10, 6, ARM_EXT_V6
, do_qadd16
},
9923 { "uadd8", 0xe6500f90, 5, ARM_EXT_V6
, do_qadd16
},
9924 { "uaddsubx", 0xe6500f30, 8, ARM_EXT_V6
, do_qadd16
},
9925 { "uhadd16", 0xe6700f10, 7, ARM_EXT_V6
, do_qadd16
},
9926 { "uhadd8", 0xe6700f90, 6, ARM_EXT_V6
, do_qadd16
},
9927 { "uhaddsubx", 0xe6700f30, 9, ARM_EXT_V6
, do_qadd16
},
9928 { "uhsub16", 0xe6700f70, 7, ARM_EXT_V6
, do_qadd16
},
9929 { "uhsub8", 0xe6700ff0, 6, ARM_EXT_V6
, do_qadd16
},
9930 { "uhsubaddx", 0xe6700f50, 9, ARM_EXT_V6
, do_qadd16
},
9931 { "uqadd16", 0xe6600f10, 7, ARM_EXT_V6
, do_qadd16
},
9932 { "uqadd8", 0xe6600f90, 6, ARM_EXT_V6
, do_qadd16
},
9933 { "uqaddsubx", 0xe6600f30, 9, ARM_EXT_V6
, do_qadd16
},
9934 { "uqsub16", 0xe6600f70, 7, ARM_EXT_V6
, do_qadd16
},
9935 { "uqsub8", 0xe6600ff0, 6, ARM_EXT_V6
, do_qadd16
},
9936 { "uqsubaddx", 0xe6600f50, 9, ARM_EXT_V6
, do_qadd16
},
9937 { "usub16", 0xe6500f70, 6, ARM_EXT_V6
, do_qadd16
},
9938 { "usub8", 0xe6500ff0, 5, ARM_EXT_V6
, do_qadd16
},
9939 { "usubaddx", 0xe6500f50, 8, ARM_EXT_V6
, do_qadd16
},
9940 { "rev", 0xe6bf0f30, 3, ARM_EXT_V6
, do_rev
},
9941 { "rev16", 0xe6bf0fb0, 5, ARM_EXT_V6
, do_rev
},
9942 { "revsh", 0xe6ff0fb0, 5, ARM_EXT_V6
, do_rev
},
9943 { "rfeia", 0xf8900a00, 0, ARM_EXT_V6
, do_rfe
},
9944 { "rfeib", 0xf9900a00, 0, ARM_EXT_V6
, do_rfe
},
9945 { "rfeda", 0xf8100a00, 0, ARM_EXT_V6
, do_rfe
},
9946 { "rfedb", 0xf9100a00, 0, ARM_EXT_V6
, do_rfe
},
9947 { "rfefd", 0xf8900a00, 0, ARM_EXT_V6
, do_rfe
},
9948 { "rfefa", 0xf9900a00, 0, ARM_EXT_V6
, do_rfe
},
9949 { "rfeea", 0xf8100a00, 0, ARM_EXT_V6
, do_rfe
},
9950 { "rfeed", 0xf9100a00, 0, ARM_EXT_V6
, do_rfe
},
9951 { "sxtah", 0xe6b00070, 5, ARM_EXT_V6
, do_sxtah
},
9952 { "sxtab16", 0xe6800070, 7, ARM_EXT_V6
, do_sxtah
},
9953 { "sxtab", 0xe6a00070, 5, ARM_EXT_V6
, do_sxtah
},
9954 { "sxth", 0xe6bf0070, 4, ARM_EXT_V6
, do_sxth
},
9955 { "sxtb16", 0xe68f0070, 6, ARM_EXT_V6
, do_sxth
},
9956 { "sxtb", 0xe6af0070, 4, ARM_EXT_V6
, do_sxth
},
9957 { "uxtah", 0xe6f00070, 5, ARM_EXT_V6
, do_sxtah
},
9958 { "uxtab16", 0xe6c00070, 7, ARM_EXT_V6
, do_sxtah
},
9959 { "uxtab", 0xe6e00070, 5, ARM_EXT_V6
, do_sxtah
},
9960 { "uxth", 0xe6ff0070, 4, ARM_EXT_V6
, do_sxth
},
9961 { "uxtb16", 0xe6cf0070, 6, ARM_EXT_V6
, do_sxth
},
9962 { "uxtb", 0xe6ef0070, 4, ARM_EXT_V6
, do_sxth
},
9963 { "sel", 0xe68000b0, 3, ARM_EXT_V6
, do_qadd16
},
9964 { "setend", 0xf1010000, 0, ARM_EXT_V6
, do_setend
},
9965 { "smlad", 0xe7000010, 5, ARM_EXT_V6
, do_smlad
},
9966 { "smladx", 0xe7000030, 6, ARM_EXT_V6
, do_smlad
},
9967 { "smlald", 0xe7400010, 6, ARM_EXT_V6
, do_smlald
},
9968 { "smlaldx", 0xe7400030, 7, ARM_EXT_V6
, do_smlald
},
9969 { "smlsd", 0xe7000050, 5, ARM_EXT_V6
, do_smlad
},
9970 { "smlsdx", 0xe7000070, 6, ARM_EXT_V6
, do_smlad
},
9971 { "smlsld", 0xe7400050, 6, ARM_EXT_V6
, do_smlald
},
9972 { "smlsldx", 0xe7400070, 7, ARM_EXT_V6
, do_smlald
},
9973 { "smmla", 0xe7500010, 5, ARM_EXT_V6
, do_smlad
},
9974 { "smmlar", 0xe7500030, 6, ARM_EXT_V6
, do_smlad
},
9975 { "smmls", 0xe75000d0, 5, ARM_EXT_V6
, do_smlad
},
9976 { "smmlsr", 0xe75000f0, 6, ARM_EXT_V6
, do_smlad
},
9977 { "smmul", 0xe750f010, 5, ARM_EXT_V6
, do_smmul
},
9978 { "smmulr", 0xe750f030, 6, ARM_EXT_V6
, do_smmul
},
9979 { "smuad", 0xe700f010, 5, ARM_EXT_V6
, do_smmul
},
9980 { "smuadx", 0xe700f030, 6, ARM_EXT_V6
, do_smmul
},
9981 { "smusd", 0xe700f050, 5, ARM_EXT_V6
, do_smmul
},
9982 { "smusdx", 0xe700f070, 6, ARM_EXT_V6
, do_smmul
},
9983 { "srsia", 0xf8cd0500, 0, ARM_EXT_V6
, do_srs
},
9984 { "srsib", 0xf9cd0500, 0, ARM_EXT_V6
, do_srs
},
9985 { "srsda", 0xf84d0500, 0, ARM_EXT_V6
, do_srs
},
9986 { "srsdb", 0xf94d0500, 0, ARM_EXT_V6
, do_srs
},
9987 { "ssat", 0xe6a00010, 4, ARM_EXT_V6
, do_ssat
},
9988 { "ssat16", 0xe6a00f30, 6, ARM_EXT_V6
, do_ssat16
},
9989 { "strex", 0xe1800f90, 5, ARM_EXT_V6
, do_strex
},
9990 { "umaal", 0xe0400090, 5, ARM_EXT_V6
, do_umaal
},
9991 { "usad8", 0xe780f010, 5, ARM_EXT_V6
, do_smmul
},
9992 { "usada8", 0xe7800010, 6, ARM_EXT_V6
, do_smlad
},
9993 { "usat", 0xe6e00010, 4, ARM_EXT_V6
, do_usat
},
9994 { "usat16", 0xe6e00f30, 6, ARM_EXT_V6
, do_usat16
},
9996 /* Core FPA instruction set (V1). */
9997 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
9998 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
9999 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
10000 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
10002 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10003 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10004 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10005 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10007 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10008 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10009 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10010 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10012 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10013 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10014 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10015 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10016 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10017 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10018 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10019 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10020 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10021 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10022 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10023 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10025 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10026 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10027 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10028 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10029 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10030 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10031 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10032 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10033 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10034 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10035 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10036 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10038 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10039 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10040 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10041 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10042 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10043 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10044 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10045 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10046 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10047 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10048 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10049 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10051 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10052 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10053 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10054 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10055 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10056 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10057 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10058 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10059 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10060 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10061 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10062 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10064 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10065 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10066 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10067 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10068 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10069 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10070 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10071 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10072 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10073 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10074 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10075 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10077 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10078 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10079 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10080 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10081 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10082 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10083 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10084 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10085 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10086 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10087 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10088 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10090 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10091 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10092 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10093 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10094 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10095 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10096 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10097 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10098 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10099 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10100 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10101 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10103 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10104 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10105 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10106 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10107 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10108 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10109 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10110 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10111 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10112 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10113 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10114 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10116 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10117 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10118 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10119 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10120 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10121 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10122 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10123 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10124 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10125 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10126 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10127 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10129 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10130 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10131 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10132 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10133 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10134 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10135 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10136 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10137 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10138 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10139 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10140 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10142 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10143 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10144 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10145 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10146 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10147 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10148 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10149 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10150 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10151 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10152 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10153 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10155 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10156 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10157 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10158 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10159 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10160 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10161 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10162 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10163 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10164 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10165 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10166 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10168 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10169 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10170 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10171 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10172 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10173 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10174 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10175 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10176 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10177 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10178 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10179 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10181 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10182 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10183 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10184 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10185 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10186 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10187 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10188 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10189 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10190 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10191 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10192 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10194 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10195 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10196 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10197 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10198 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10199 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10200 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10201 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10202 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10203 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10204 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10205 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10207 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10208 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10209 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10210 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10211 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10212 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10213 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10214 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10215 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10216 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10217 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10218 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10220 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10221 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10222 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10223 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10224 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10225 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10226 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10227 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10228 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10229 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10230 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10231 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10233 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10234 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10235 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10236 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10237 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10238 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10239 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10240 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10241 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10242 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10243 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10244 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10246 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10247 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10248 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10249 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10250 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10251 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10252 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10253 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10254 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10255 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10256 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10257 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10259 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10260 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10261 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10262 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10263 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10264 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10265 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10266 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10267 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10268 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10269 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10270 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10272 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10273 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10274 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10275 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10276 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10277 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10278 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10279 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10280 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10281 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10282 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10283 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10285 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10286 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10287 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10288 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10289 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10290 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10291 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10292 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10293 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10294 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10295 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10296 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10298 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10299 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10300 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10301 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10302 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10303 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10304 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10305 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10306 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10307 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10308 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10309 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10311 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10312 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10313 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10314 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10315 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10316 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10317 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10318 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10319 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10320 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10321 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10322 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10324 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10325 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10326 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10327 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10328 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10329 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10330 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10331 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10332 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10333 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10334 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10335 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10337 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10338 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10339 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10340 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10341 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10342 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10343 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10344 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10345 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10346 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10347 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10348 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10350 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10351 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10352 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10353 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10354 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10355 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10356 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10357 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10358 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10359 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10360 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10361 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10363 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10364 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10365 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10366 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10367 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10368 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10369 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10370 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10371 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10372 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10373 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10374 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10376 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10377 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10378 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10379 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10380 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10381 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10382 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10383 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10384 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10385 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10386 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10387 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10389 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10390 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10391 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10392 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10393 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
10394 not be an optional suffix, but part of the instruction. To be
10395 compatible, we accept either. */
10396 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10397 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10399 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10400 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10401 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10402 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10403 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10404 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10405 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10406 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10407 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10408 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10409 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10410 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10412 /* The implementation of the FIX instruction is broken on some
10413 assemblers, in that it accepts a precision specifier as well as a
10414 rounding specifier, despite the fact that this is meaningless.
10415 To be more compatible, we accept it as well, though of course it
10416 does not set any bits. */
10417 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10418 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10419 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10420 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10421 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10422 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10423 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10424 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10425 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10426 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10427 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10428 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10429 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10431 /* Instructions that were new with the real FPA, call them V2. */
10432 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10433 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10434 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10435 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10436 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10437 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10439 /* VFP V1xD (single precision). */
10440 /* Moves and type conversions. */
10441 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10442 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_reg_from_sp
},
10443 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_from_reg
},
10444 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD
, do_empty
},
10445 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10446 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10447 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10448 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10449 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10450 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10451 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_reg_from_ctrl
},
10452 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_ctrl_from_reg
},
10454 /* Memory operations. */
10455 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldst
},
10456 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldst
},
10457 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
10458 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
10459 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
10460 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
10461 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
10462 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
10463 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
10464 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
10465 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
10466 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
10467 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
10468 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
10469 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
10470 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
10471 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
10472 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
10474 /* Monadic operations. */
10475 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10476 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10477 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10479 /* Dyadic operations. */
10480 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10481 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10482 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10483 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10484 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10485 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10486 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10487 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10488 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10491 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10492 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_compare_z
},
10493 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10494 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_compare_z
},
10496 /* VFP V1 (Double precision). */
10497 /* Moves and type conversions. */
10498 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10499 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
10500 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10501 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1
, do_vfp_dp_from_reg
},
10502 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1
, do_vfp_dp_from_reg
},
10503 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1
, do_vfp_reg_from_dp
},
10504 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1
, do_vfp_reg_from_dp
},
10505 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
10506 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
10507 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10508 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10509 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10510 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10512 /* Memory operations. */
10513 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1
, do_vfp_dp_ldst
},
10514 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1
, do_vfp_dp_ldst
},
10515 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
10516 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
10517 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
10518 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
10519 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
10520 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
10521 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
10522 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
10524 /* Monadic operations. */
10525 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10526 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10527 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10529 /* Dyadic operations. */
10530 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10531 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10532 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10533 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10534 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10535 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10536 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10537 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10538 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10541 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10542 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_compare_z
},
10543 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10544 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1
, do_vfp_dp_compare_z
},
10547 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2
, do_vfp_sp2_from_reg2
},
10548 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2
, do_vfp_reg2_from_sp2
},
10549 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2
, do_vfp_dp_from_reg2
},
10550 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2
, do_vfp_reg2_from_dp
},
10552 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
10553 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE
, do_xsc_mia
},
10554 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10555 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10556 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10557 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10558 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10559 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE
, do_xsc_mar
},
10560 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE
, do_xsc_mra
},
10562 /* Intel Wireless MMX technology instructions. */
10563 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
10564 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
10565 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
10566 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
10567 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
10568 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
10569 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
10570 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
10571 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
10572 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10573 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10574 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10575 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10576 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10577 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10578 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
10579 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
10580 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
10581 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmcr
},
10582 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_tmcrr
},
10583 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10584 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10585 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10586 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10587 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10588 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10589 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
10590 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
10591 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
10592 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmrc
},
10593 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_tmrrc
},
10594 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
10595 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
10596 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
10597 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10598 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10599 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10600 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10601 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10602 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10603 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10604 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10605 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10606 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10607 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10608 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10609 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_waligni
},
10610 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10611 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10612 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10613 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10614 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10615 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10616 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10617 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10618 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10619 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10620 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10621 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10622 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10623 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10624 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10625 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10626 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10627 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10628 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10629 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
10630 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
10631 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
10632 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
10633 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10634 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10635 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10636 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10637 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10638 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10639 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10640 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10641 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10642 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10643 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10644 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10645 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10646 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10647 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10648 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10649 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10650 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10651 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wmov
},
10652 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10653 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10654 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10655 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10656 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10657 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10658 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10659 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10660 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10661 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10662 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10663 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10664 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10665 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10666 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10667 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10668 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10669 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10670 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10671 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10672 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10673 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wshufh
},
10674 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10675 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10676 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10677 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10678 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10679 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10680 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10681 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10682 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10683 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10684 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10685 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10686 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10687 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10688 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10689 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10690 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10691 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10692 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
10693 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
10694 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
10695 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
10696 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10697 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10698 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10699 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10700 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10701 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10702 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10703 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10704 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10705 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10706 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10707 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10708 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10709 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10710 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10711 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10712 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10713 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10714 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10715 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10716 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10717 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10718 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10719 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10720 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10721 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10722 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10723 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10724 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wzero
},
10726 /* Cirrus Maverick instructions. */
10727 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_1
},
10728 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_2
},
10729 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_3
},
10730 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_4
},
10731 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_1
},
10732 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_2
},
10733 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_3
},
10734 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_4
},
10735 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK
, do_mav_binops_2a
},
10736 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1a
},
10737 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK
, do_mav_binops_2b
},
10738 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1b
},
10739 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK
, do_mav_binops_2b
},
10740 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1b
},
10741 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK
, do_mav_binops_2c
},
10742 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1c
},
10743 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK
, do_mav_binops_2c
},
10744 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1c
},
10745 {"cfmval32", 0xee200440, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
10746 {"cfmv32al", 0xee100440, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
10747 {"cfmvam32", 0xee200460, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
10748 {"cfmv32am", 0xee100460, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
10749 {"cfmvah32", 0xee200480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
10750 {"cfmv32ah", 0xee100480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
10751 {"cfmva32", 0xee2004a0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
10752 {"cfmv32a", 0xee1004a0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
10753 {"cfmva64", 0xee2004c0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3c
},
10754 {"cfmv64a", 0xee1004c0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3d
},
10755 {"cfmvsc32", 0xee2004e0, 8, ARM_CEXT_MAVERICK
, do_mav_dspsc_1
},
10756 {"cfmv32sc", 0xee1004e0, 8, ARM_CEXT_MAVERICK
, do_mav_dspsc_2
},
10757 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
10758 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
10759 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1f
},
10760 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1g
},
10761 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1h
},
10762 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1i
},
10763 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1j
},
10764 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1k
},
10765 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1l
},
10766 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1m
},
10767 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK
, do_mav_binops_1l
},
10768 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK
, do_mav_binops_1m
},
10769 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK
, do_mav_triple_4a
},
10770 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK
, do_mav_triple_4b
},
10771 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK
, do_mav_shift_1
},
10772 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK
, do_mav_shift_2
},
10773 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5a
},
10774 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5b
},
10775 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5c
},
10776 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5d
},
10777 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
10778 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
10779 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
10780 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
10781 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
10782 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
10783 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
10784 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
10785 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
10786 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
10787 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1n
},
10788 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1o
},
10789 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1n
},
10790 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1o
},
10791 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
10792 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
10793 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
10794 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
10795 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
10796 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
10797 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
10798 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
10799 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK
, do_mav_quad_6a
},
10800 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK
, do_mav_quad_6a
},
10801 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK
, do_mav_quad_6b
},
10802 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK
, do_mav_quad_6b
},
10805 /* Iterate over the base tables to create the instruction patterns. */
10808 build_arm_ops_hsh (void)
10812 static struct obstack insn_obstack
;
10814 obstack_begin (&insn_obstack
, 4000);
10816 for (i
= 0; i
< sizeof (insns
) / sizeof (struct asm_opcode
); i
++)
10818 const struct asm_opcode
*insn
= insns
+ i
;
10820 if (insn
->cond_offset
!= 0)
10822 /* Insn supports conditional execution. Build the varaints
10823 and insert them in the hash table. */
10824 for (j
= 0; j
< sizeof (conds
) / sizeof (struct asm_cond
); j
++)
10826 unsigned len
= strlen (insn
->template);
10827 struct asm_opcode
*new;
10830 new = obstack_alloc (&insn_obstack
, sizeof (struct asm_opcode
));
10831 /* All condition codes are two characters. */
10832 template = obstack_alloc (&insn_obstack
, len
+ 3);
10834 strncpy (template, insn
->template, insn
->cond_offset
);
10835 strcpy (template + insn
->cond_offset
, conds
[j
].template);
10836 if (len
> insn
->cond_offset
)
10837 strcpy (template + insn
->cond_offset
+ 2,
10838 insn
->template + insn
->cond_offset
);
10839 new->template = template;
10840 new->cond_offset
= 0;
10841 new->variant
= insn
->variant
;
10842 new->parms
= insn
->parms
;
10843 new->value
= (insn
->value
& ~COND_MASK
) | conds
[j
].value
;
10845 hash_insert (arm_ops_hsh
, new->template, (PTR
) new);
10848 /* Finally, insert the unconditional insn in the table directly;
10849 no need to build a copy. */
10850 hash_insert (arm_ops_hsh
, insn
->template, (PTR
) insn
);
10854 #if 0 /* Suppressed - for now. */
10855 #if defined OBJ_ELF || defined OBJ_COFF
10858 #define arm_Note Elf_External_Note
10862 unsigned char namesz
[4]; /* Size of entry's owner string. */
10863 unsigned char descsz
[4]; /* Size of the note descriptor. */
10864 unsigned char type
[4]; /* Interpretation of the descriptor. */
10865 char name
[1]; /* Start of the name+desc data. */
10869 /* The description is kept to a fix sized in order to make updating
10870 it and merging it easier. */
10871 #define ARM_NOTE_DESCRIPTION_LENGTH 8
10874 arm_add_note (const char * name
,
10875 const char * description
,
10878 arm_Note note ATTRIBUTE_UNUSED
;
10880 unsigned int name_len
;
10882 name_len
= (strlen (name
) + 1 + 3) & ~3;
10884 p
= frag_more (sizeof (note
.namesz
));
10885 md_number_to_chars (p
, (valueT
) name_len
, sizeof (note
.namesz
));
10887 p
= frag_more (sizeof (note
.descsz
));
10888 md_number_to_chars (p
, (valueT
) ARM_NOTE_DESCRIPTION_LENGTH
, sizeof (note
.descsz
));
10890 p
= frag_more (sizeof (note
.type
));
10891 md_number_to_chars (p
, (valueT
) type
, sizeof (note
.type
));
10893 p
= frag_more (name_len
);
10896 p
= frag_more (ARM_NOTE_DESCRIPTION_LENGTH
);
10897 strncpy (p
, description
, ARM_NOTE_DESCRIPTION_LENGTH
);
10898 frag_align (2, 0, 0);
10904 static const struct thumb_opcode tinsns
[] =
10906 /* Thumb v1 (ARMv4T). */
10907 {"adc", 0x4140, 2, ARM_EXT_V4T
, do_t_arit
},
10908 {"add", 0x0000, 2, ARM_EXT_V4T
, do_t_add
},
10909 {"and", 0x4000, 2, ARM_EXT_V4T
, do_t_arit
},
10910 {"asr", 0x0000, 2, ARM_EXT_V4T
, do_t_asr
},
10911 {"b", T_OPCODE_BRANCH
, 2, ARM_EXT_V4T
, do_t_branch12
},
10912 {"beq", 0xd0fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10913 {"bne", 0xd1fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10914 {"bcs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10915 {"bhs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10916 {"bcc", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10917 {"bul", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10918 {"blo", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10919 {"bmi", 0xd4fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10920 {"bpl", 0xd5fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10921 {"bvs", 0xd6fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10922 {"bvc", 0xd7fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10923 {"bhi", 0xd8fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10924 {"bls", 0xd9fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10925 {"bge", 0xdafe, 2, ARM_EXT_V4T
, do_t_branch9
},
10926 {"blt", 0xdbfe, 2, ARM_EXT_V4T
, do_t_branch9
},
10927 {"bgt", 0xdcfe, 2, ARM_EXT_V4T
, do_t_branch9
},
10928 {"ble", 0xddfe, 2, ARM_EXT_V4T
, do_t_branch9
},
10929 {"bal", 0xdefe, 2, ARM_EXT_V4T
, do_t_branch9
},
10930 {"bic", 0x4380, 2, ARM_EXT_V4T
, do_t_arit
},
10931 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T
, do_t_branch23
},
10932 {"bx", 0x4700, 2, ARM_EXT_V4T
, do_t_bx
},
10933 {"cmn", T_OPCODE_CMN
, 2, ARM_EXT_V4T
, do_t_arit
},
10934 {"cmp", 0x0000, 2, ARM_EXT_V4T
, do_t_compare
},
10935 {"eor", 0x4040, 2, ARM_EXT_V4T
, do_t_arit
},
10936 {"ldmia", 0xc800, 2, ARM_EXT_V4T
, do_t_ldmstm
},
10937 {"ldr", 0x0000, 2, ARM_EXT_V4T
, do_t_ldr
},
10938 {"ldrb", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrb
},
10939 {"ldrh", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrh
},
10940 {"ldrsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
10941 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
10942 {"ldsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
10943 {"ldsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
10944 {"lsl", 0x0000, 2, ARM_EXT_V4T
, do_t_lsl
},
10945 {"lsr", 0x0000, 2, ARM_EXT_V4T
, do_t_lsr
},
10946 {"mov", 0x0000, 2, ARM_EXT_V4T
, do_t_mov
},
10947 {"mul", T_OPCODE_MUL
, 2, ARM_EXT_V4T
, do_t_arit
},
10948 {"mvn", T_OPCODE_MVN
, 2, ARM_EXT_V4T
, do_t_arit
},
10949 {"neg", T_OPCODE_NEG
, 2, ARM_EXT_V4T
, do_t_arit
},
10950 {"orr", 0x4300, 2, ARM_EXT_V4T
, do_t_arit
},
10951 {"pop", 0xbc00, 2, ARM_EXT_V4T
, do_t_push_pop
},
10952 {"push", 0xb400, 2, ARM_EXT_V4T
, do_t_push_pop
},
10953 {"ror", 0x41c0, 2, ARM_EXT_V4T
, do_t_arit
},
10954 {"sbc", 0x4180, 2, ARM_EXT_V4T
, do_t_arit
},
10955 {"stmia", 0xc000, 2, ARM_EXT_V4T
, do_t_ldmstm
},
10956 {"str", 0x0000, 2, ARM_EXT_V4T
, do_t_str
},
10957 {"strb", 0x0000, 2, ARM_EXT_V4T
, do_t_strb
},
10958 {"strh", 0x0000, 2, ARM_EXT_V4T
, do_t_strh
},
10959 {"swi", 0xdf00, 2, ARM_EXT_V4T
, do_t_swi
},
10960 {"sub", 0x0000, 2, ARM_EXT_V4T
, do_t_sub
},
10961 {"tst", T_OPCODE_TST
, 2, ARM_EXT_V4T
, do_t_arit
},
10963 {"adr", 0x0000, 2, ARM_EXT_V4T
, do_t_adr
},
10964 {"nop", 0x46C0, 2, ARM_EXT_V4T
, do_t_nop
}, /* mov r8,r8 */
10965 /* Thumb v2 (ARMv5T). */
10966 {"blx", 0, 0, ARM_EXT_V5T
, do_t_blx
},
10967 {"bkpt", 0xbe00, 2, ARM_EXT_V5T
, do_t_bkpt
},
10970 {"cpsie", 0xb660, 2, ARM_EXT_V6
, do_t_cps
},
10971 {"cpsid", 0xb670, 2, ARM_EXT_V6
, do_t_cps
},
10972 {"cpy", 0x4600, 2, ARM_EXT_V6
, do_t_cpy
},
10973 {"rev", 0xba00, 2, ARM_EXT_V6
, do_t_arit
},
10974 {"rev16", 0xba40, 2, ARM_EXT_V6
, do_t_arit
},
10975 {"revsh", 0xbac0, 2, ARM_EXT_V6
, do_t_arit
},
10976 {"setend", 0xb650, 2, ARM_EXT_V6
, do_t_setend
},
10977 {"sxth", 0xb200, 2, ARM_EXT_V6
, do_t_arit
},
10978 {"sxtb", 0xb240, 2, ARM_EXT_V6
, do_t_arit
},
10979 {"uxth", 0xb280, 2, ARM_EXT_V6
, do_t_arit
},
10980 {"uxtb", 0xb2c0, 2, ARM_EXT_V6
, do_t_arit
},
10989 if ( (arm_ops_hsh
= hash_new ()) == NULL
10990 || (arm_tops_hsh
= hash_new ()) == NULL
10991 || (arm_cond_hsh
= hash_new ()) == NULL
10992 || (arm_shift_hsh
= hash_new ()) == NULL
10993 || (arm_psr_hsh
= hash_new ()) == NULL
)
10994 as_fatal (_("virtual memory exhausted"));
10996 build_arm_ops_hsh ();
10997 for (i
= 0; i
< sizeof (tinsns
) / sizeof (struct thumb_opcode
); i
++)
10998 hash_insert (arm_tops_hsh
, tinsns
[i
].template, (PTR
) (tinsns
+ i
));
10999 for (i
= 0; i
< sizeof (conds
) / sizeof (struct asm_cond
); i
++)
11000 hash_insert (arm_cond_hsh
, conds
[i
].template, (PTR
) (conds
+ i
));
11001 for (i
= 0; i
< sizeof (shift_names
) / sizeof (struct asm_shift_name
); i
++)
11002 hash_insert (arm_shift_hsh
, shift_names
[i
].name
, (PTR
) (shift_names
+ i
));
11003 for (i
= 0; i
< sizeof (psrs
) / sizeof (struct asm_psr
); i
++)
11004 hash_insert (arm_psr_hsh
, psrs
[i
].template, (PTR
) (psrs
+ i
));
11006 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
11007 build_reg_hsh (all_reg_maps
+ i
);
11009 set_constant_flonums ();
11011 /* Set the cpu variant based on the command-line options. We prefer
11012 -mcpu= over -march= if both are set (as for GCC); and we prefer
11013 -mfpu= over any other way of setting the floating point unit.
11014 Use of legacy options with new options are faulted. */
11015 if (legacy_cpu
!= -1)
11017 if (mcpu_cpu_opt
!= -1 || march_cpu_opt
!= -1)
11018 as_bad (_("use of old and new-style options to set CPU type"));
11020 mcpu_cpu_opt
= legacy_cpu
;
11022 else if (mcpu_cpu_opt
== -1)
11023 mcpu_cpu_opt
= march_cpu_opt
;
11025 if (legacy_fpu
!= -1)
11027 if (mfpu_opt
!= -1)
11028 as_bad (_("use of old and new-style options to set FPU type"));
11030 mfpu_opt
= legacy_fpu
;
11032 else if (mfpu_opt
== -1)
11034 #if !(defined (TE_LINUX) || defined (TE_NetBSD))
11035 /* Some environments specify a default FPU. If they don't, infer it
11036 from the processor. */
11037 if (mcpu_fpu_opt
!= -1)
11038 mfpu_opt
= mcpu_fpu_opt
;
11040 mfpu_opt
= march_fpu_opt
;
11042 mfpu_opt
= FPU_DEFAULT
;
11046 if (mfpu_opt
== -1)
11048 if (mcpu_cpu_opt
== -1)
11049 mfpu_opt
= FPU_DEFAULT
;
11050 else if (mcpu_cpu_opt
& ARM_EXT_V5
)
11051 mfpu_opt
= FPU_ARCH_VFP_V2
;
11053 mfpu_opt
= FPU_ARCH_FPA
;
11056 if (mcpu_cpu_opt
== -1)
11057 mcpu_cpu_opt
= CPU_DEFAULT
;
11059 cpu_variant
= mcpu_cpu_opt
| mfpu_opt
;
11062 unsigned int flags
= 0;
11064 #if defined OBJ_ELF
11065 flags
= meabi_flags
;
11067 switch (meabi_flags
)
11069 case EF_ARM_EABI_UNKNOWN
:
11071 #if defined OBJ_COFF || defined OBJ_ELF
11072 /* Set the flags in the private structure. */
11073 if (uses_apcs_26
) flags
|= F_APCS26
;
11074 if (support_interwork
) flags
|= F_INTERWORK
;
11075 if (uses_apcs_float
) flags
|= F_APCS_FLOAT
;
11076 if (pic_code
) flags
|= F_PIC
;
11077 if ((cpu_variant
& FPU_ANY
) == FPU_NONE
11078 || (cpu_variant
& FPU_ANY
) == FPU_ARCH_VFP
) /* VFP layout only. */
11079 flags
|= F_SOFT_FLOAT
;
11081 switch (mfloat_abi_opt
)
11083 case ARM_FLOAT_ABI_SOFT
:
11084 case ARM_FLOAT_ABI_SOFTFP
:
11085 flags
|= F_SOFT_FLOAT
;
11088 case ARM_FLOAT_ABI_HARD
:
11089 if (flags
& F_SOFT_FLOAT
)
11090 as_bad (_("hard-float conflicts with specified fpu"));
11094 /* Using VFP conventions (even if soft-float). */
11095 if (cpu_variant
& FPU_VFP_EXT_NONE
)
11096 flags
|= F_VFP_FLOAT
;
11098 #if defined OBJ_ELF
11099 if (cpu_variant
& FPU_ARCH_MAVERICK
)
11100 flags
|= EF_ARM_MAVERICK_FLOAT
;
11103 case EF_ARM_EABI_VER3
:
11104 /* No additional flags to set. */
11111 #if defined OBJ_COFF || defined OBJ_ELF
11112 bfd_set_private_flags (stdoutput
, flags
);
11114 /* We have run out flags in the COFF header to encode the
11115 status of ATPCS support, so instead we create a dummy,
11116 empty, debug section called .arm.atpcs. */
11121 sec
= bfd_make_section (stdoutput
, ".arm.atpcs");
11125 bfd_set_section_flags
11126 (stdoutput
, sec
, SEC_READONLY
| SEC_DEBUGGING
/* | SEC_HAS_CONTENTS */);
11127 bfd_set_section_size (stdoutput
, sec
, 0);
11128 bfd_set_section_contents (stdoutput
, sec
, NULL
, 0, 0);
11134 /* Record the CPU type as well. */
11135 switch (cpu_variant
& ARM_CPU_MASK
)
11138 mach
= bfd_mach_arm_2
;
11141 case ARM_3
: /* Also ARM_250. */
11142 mach
= bfd_mach_arm_2a
;
11145 case ARM_6
: /* Also ARM_7. */
11146 mach
= bfd_mach_arm_3
;
11150 mach
= bfd_mach_arm_unknown
;
11154 /* Catch special cases. */
11155 if (cpu_variant
& ARM_CEXT_IWMMXT
)
11156 mach
= bfd_mach_arm_iWMMXt
;
11157 else if (cpu_variant
& ARM_CEXT_XSCALE
)
11158 mach
= bfd_mach_arm_XScale
;
11159 else if (cpu_variant
& ARM_CEXT_MAVERICK
)
11160 mach
= bfd_mach_arm_ep9312
;
11161 else if (cpu_variant
& ARM_EXT_V5E
)
11162 mach
= bfd_mach_arm_5TE
;
11163 else if (cpu_variant
& ARM_EXT_V5
)
11165 if (cpu_variant
& ARM_EXT_V4T
)
11166 mach
= bfd_mach_arm_5T
;
11168 mach
= bfd_mach_arm_5
;
11170 else if (cpu_variant
& ARM_EXT_V4
)
11172 if (cpu_variant
& ARM_EXT_V4T
)
11173 mach
= bfd_mach_arm_4T
;
11175 mach
= bfd_mach_arm_4
;
11177 else if (cpu_variant
& ARM_EXT_V3M
)
11178 mach
= bfd_mach_arm_3M
;
11180 #if 0 /* Suppressed - for now. */
11181 #if defined (OBJ_ELF) || defined (OBJ_COFF)
11183 /* Create a .note section to fully identify this arm binary. */
11185 #define NOTE_ARCH_STRING "arch: "
11187 #if defined OBJ_COFF && ! defined NT_VERSION
11188 #define NT_VERSION 1
11193 segT current_seg
= now_seg
;
11194 subsegT current_subseg
= now_subseg
;
11195 asection
* arm_arch
;
11196 const char * arch_string
;
11198 arm_arch
= bfd_make_section_old_way (stdoutput
, ARM_NOTE_SECTION
);
11201 bfd_set_section_flags (stdoutput
, arm_arch
,
11202 SEC_DATA
| SEC_ALLOC
| SEC_LOAD
| SEC_LINK_ONCE \
11203 | SEC_HAS_CONTENTS
);
11205 bfd_set_section_flags (stdoutput
, arm_arch
,
11206 SEC_READONLY
| SEC_HAS_CONTENTS
);
11208 arm_arch
->output_section
= arm_arch
;
11209 subseg_set (arm_arch
, 0);
11214 case bfd_mach_arm_unknown
: arch_string
= "unknown"; break;
11215 case bfd_mach_arm_2
: arch_string
= "armv2"; break;
11216 case bfd_mach_arm_2a
: arch_string
= "armv2a"; break;
11217 case bfd_mach_arm_3
: arch_string
= "armv3"; break;
11218 case bfd_mach_arm_3M
: arch_string
= "armv3M"; break;
11219 case bfd_mach_arm_4
: arch_string
= "armv4"; break;
11220 case bfd_mach_arm_4T
: arch_string
= "armv4t"; break;
11221 case bfd_mach_arm_5
: arch_string
= "armv5"; break;
11222 case bfd_mach_arm_5T
: arch_string
= "armv5t"; break;
11223 case bfd_mach_arm_5TE
: arch_string
= "armv5te"; break;
11224 case bfd_mach_arm_XScale
: arch_string
= "XScale"; break;
11225 case bfd_mach_arm_ep9312
: arch_string
= "ep9312"; break;
11226 case bfd_mach_arm_iWMMXt
: arch_string
= "iWMMXt"; break;
11229 arm_add_note (NOTE_ARCH_STRING
, arch_string
, NT_ARCH
);
11231 subseg_set (current_seg
, current_subseg
);
11234 #endif /* Suppressed code. */
11236 bfd_set_arch_mach (stdoutput
, TARGET_ARCH
, mach
);
11239 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11240 for use in the a.out file, and stores them in the array pointed to by buf.
11241 This knows about the endian-ness of the target machine and does
11242 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11243 2 (short) and 4 (long) Floating numbers are put out as a series of
11244 LITTLENUMS (shorts, here at least). */
11247 md_number_to_chars (char * buf
, valueT val
, int n
)
11249 if (target_big_endian
)
11250 number_to_chars_bigendian (buf
, val
, n
);
11252 number_to_chars_littleendian (buf
, val
, n
);
11256 md_chars_to_number (char * buf
, int n
)
11259 unsigned char * where
= (unsigned char *) buf
;
11261 if (target_big_endian
)
11266 result
|= (*where
++ & 255);
11274 result
|= (where
[n
] & 255);
11281 /* Turn a string in input_line_pointer into a floating point constant
11282 of type TYPE, and store the appropriate bytes in *LITP. The number
11283 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11284 returned, or NULL on OK.
11286 Note that fp constants aren't represent in the normal way on the ARM.
11287 In big endian mode, things are as expected. However, in little endian
11288 mode fp constants are big-endian word-wise, and little-endian byte-wise
11289 within the words. For example, (double) 1.1 in big endian mode is
11290 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11291 the byte sequence 99 99 f1 3f 9a 99 99 99.
11293 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11296 md_atof (int type
, char * litP
, int * sizeP
)
11299 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
11331 return _("bad call to MD_ATOF()");
11334 t
= atof_ieee (input_line_pointer
, type
, words
);
11336 input_line_pointer
= t
;
11339 if (target_big_endian
)
11341 for (i
= 0; i
< prec
; i
++)
11343 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
11349 if (cpu_variant
& FPU_ARCH_VFP
)
11350 for (i
= prec
- 1; i
>= 0; i
--)
11352 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
11356 /* For a 4 byte float the order of elements in `words' is 1 0.
11357 For an 8 byte float the order is 1 0 3 2. */
11358 for (i
= 0; i
< prec
; i
+= 2)
11360 md_number_to_chars (litP
, (valueT
) words
[i
+ 1], 2);
11361 md_number_to_chars (litP
+ 2, (valueT
) words
[i
], 2);
11369 /* The knowledge of the PC's pipeline offset is built into the insns
11373 md_pcrel_from (fixS
* fixP
)
11376 && S_GET_SEGMENT (fixP
->fx_addsy
) == undefined_section
11377 && fixP
->fx_subsy
== NULL
)
11380 if (fixP
->fx_pcrel
&& (fixP
->fx_r_type
== BFD_RELOC_ARM_THUMB_ADD
))
11382 /* PC relative addressing on the Thumb is slightly odd
11383 as the bottom two bits of the PC are forced to zero
11384 for the calculation. */
11385 return (fixP
->fx_where
+ fixP
->fx_frag
->fr_address
) & ~3;
11389 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
11390 so we un-adjust here to compensate for the accommodation. */
11391 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
+ 8;
11393 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
11397 /* Round up a section size to the appropriate boundary. */
11400 md_section_align (segT segment ATTRIBUTE_UNUSED
,
11406 /* Round all sects to multiple of 4. */
11407 return (size
+ 3) & ~3;
11411 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
11412 Otherwise we have no need to default values of symbols. */
11415 md_undefined_symbol (char * name ATTRIBUTE_UNUSED
)
11418 if (name
[0] == '_' && name
[1] == 'G'
11419 && streq (name
, GLOBAL_OFFSET_TABLE_NAME
))
11423 if (symbol_find (name
))
11424 as_bad ("GOT already in the symbol table");
11426 GOT_symbol
= symbol_new (name
, undefined_section
,
11427 (valueT
) 0, & zero_address_frag
);
11438 md_apply_fix3 (fixS
* fixP
,
11442 offsetT value
= * valP
;
11444 unsigned int newimm
;
11445 unsigned long temp
;
11447 char * buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
11448 arm_fix_data
* arm_data
= (arm_fix_data
*) fixP
->tc_fix_data
;
11450 assert (fixP
->fx_r_type
< BFD_RELOC_UNUSED
);
11452 /* Note whether this will delete the relocation. */
11454 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
11455 doesn't work fully.) */
11456 if ((fixP
->fx_addsy
== 0 || symbol_constant_p (fixP
->fx_addsy
))
11457 && !fixP
->fx_pcrel
)
11459 if (fixP
->fx_addsy
== 0 && !fixP
->fx_pcrel
)
11463 /* If this symbol is in a different section then we need to leave it for
11464 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
11465 so we have to undo it's effects here. */
11466 if (fixP
->fx_pcrel
)
11468 if (fixP
->fx_addsy
!= NULL
11469 && S_IS_DEFINED (fixP
->fx_addsy
)
11470 && S_GET_SEGMENT (fixP
->fx_addsy
) != seg
)
11473 && (fixP
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
11474 || fixP
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
11478 value
+= md_pcrel_from (fixP
);
11482 /* Remember value for emit_reloc. */
11483 fixP
->fx_addnumber
= value
;
11485 switch (fixP
->fx_r_type
)
11487 case BFD_RELOC_ARM_IMMEDIATE
:
11488 /* We claim that this fixup has been processed here,
11489 even if in fact we generate an error because we do
11490 not have a reloc for it, so tc_gen_reloc will reject it. */
11494 && ! S_IS_DEFINED (fixP
->fx_addsy
))
11496 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11497 _("undefined symbol %s used as an immediate value"),
11498 S_GET_NAME (fixP
->fx_addsy
));
11502 newimm
= validate_immediate (value
);
11503 temp
= md_chars_to_number (buf
, INSN_SIZE
);
11505 /* If the instruction will fail, see if we can fix things up by
11506 changing the opcode. */
11507 if (newimm
== (unsigned int) FAIL
11508 && (newimm
= negate_data_op (&temp
, value
)) == (unsigned int) FAIL
)
11510 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11511 _("invalid constant (%lx) after fixup"),
11512 (unsigned long) value
);
11516 newimm
|= (temp
& 0xfffff000);
11517 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
11520 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
11522 unsigned int highpart
= 0;
11523 unsigned int newinsn
= 0xe1a00000; /* nop. */
11525 newimm
= validate_immediate (value
);
11526 temp
= md_chars_to_number (buf
, INSN_SIZE
);
11528 /* If the instruction will fail, see if we can fix things up by
11529 changing the opcode. */
11530 if (newimm
== (unsigned int) FAIL
11531 && (newimm
= negate_data_op (& temp
, value
)) == (unsigned int) FAIL
)
11533 /* No ? OK - try using two ADD instructions to generate
11535 newimm
= validate_immediate_twopart (value
, & highpart
);
11537 /* Yes - then make sure that the second instruction is
11539 if (newimm
!= (unsigned int) FAIL
)
11541 /* Still No ? Try using a negated value. */
11542 else if ((newimm
= validate_immediate_twopart (- value
, & highpart
)) != (unsigned int) FAIL
)
11543 temp
= newinsn
= (temp
& OPCODE_MASK
) | OPCODE_SUB
<< DATA_OP_SHIFT
;
11544 /* Otherwise - give up. */
11547 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11548 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
11553 /* Replace the first operand in the 2nd instruction (which
11554 is the PC) with the destination register. We have
11555 already added in the PC in the first instruction and we
11556 do not want to do it again. */
11557 newinsn
&= ~ 0xf0000;
11558 newinsn
|= ((newinsn
& 0x0f000) << 4);
11561 newimm
|= (temp
& 0xfffff000);
11562 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
11564 highpart
|= (newinsn
& 0xfffff000);
11565 md_number_to_chars (buf
+ INSN_SIZE
, (valueT
) highpart
, INSN_SIZE
);
11569 case BFD_RELOC_ARM_OFFSET_IMM
:
11575 if (validate_offset_imm (value
, 0) == FAIL
)
11577 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11578 _("bad immediate value for offset (%ld)"),
11583 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11584 newval
&= 0xff7ff000;
11585 newval
|= value
| (sign
? INDEX_UP
: 0);
11586 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11589 case BFD_RELOC_ARM_OFFSET_IMM8
:
11590 case BFD_RELOC_ARM_HWLITERAL
:
11596 if (validate_offset_imm (value
, 1) == FAIL
)
11598 if (fixP
->fx_r_type
== BFD_RELOC_ARM_HWLITERAL
)
11599 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11600 _("invalid literal constant: pool needs to be closer"));
11602 as_bad (_("bad immediate value for half-word offset (%ld)"),
11607 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11608 newval
&= 0xff7ff0f0;
11609 newval
|= ((value
>> 4) << 8) | (value
& 0xf) | (sign
? INDEX_UP
: 0);
11610 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11613 case BFD_RELOC_ARM_LITERAL
:
11619 if (validate_offset_imm (value
, 0) == FAIL
)
11621 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11622 _("invalid literal constant: pool needs to be closer"));
11626 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11627 newval
&= 0xff7ff000;
11628 newval
|= value
| (sign
? INDEX_UP
: 0);
11629 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11632 case BFD_RELOC_ARM_SHIFT_IMM
:
11633 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11634 if (((unsigned long) value
) > 32
11636 && (((newval
& 0x60) == 0) || (newval
& 0x60) == 0x60)))
11638 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11639 _("shift expression is too large"));
11644 /* Shifts of zero must be done as lsl. */
11646 else if (value
== 32)
11648 newval
&= 0xfffff07f;
11649 newval
|= (value
& 0x1f) << 7;
11650 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11653 case BFD_RELOC_ARM_SWI
:
11654 if (arm_data
->thumb_mode
)
11656 if (((unsigned long) value
) > 0xff)
11657 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11658 _("invalid swi expression"));
11659 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xff00;
11661 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11665 if (((unsigned long) value
) > 0x00ffffff)
11666 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11667 _("invalid swi expression"));
11668 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff000000;
11670 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11674 case BFD_RELOC_ARM_MULTI
:
11675 if (((unsigned long) value
) > 0xffff)
11676 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11677 _("invalid expression in load/store multiple"));
11678 newval
= value
| md_chars_to_number (buf
, INSN_SIZE
);
11679 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11682 case BFD_RELOC_ARM_PCREL_BRANCH
:
11683 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11685 /* Sign-extend a 24-bit number. */
11686 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
11690 value
= fixP
->fx_offset
;
11693 /* We are going to store value (shifted right by two) in the
11694 instruction, in a 24 bit, signed field. Thus we need to check
11695 that none of the top 8 bits of the shifted value (top 7 bits of
11696 the unshifted, unsigned value) are set, or that they are all set. */
11697 if ((value
& ~ ((offsetT
) 0x1ffffff)) != 0
11698 && ((value
& ~ ((offsetT
) 0x1ffffff)) != ~ ((offsetT
) 0x1ffffff)))
11701 /* Normally we would be stuck at this point, since we cannot store
11702 the absolute address that is the destination of the branch in the
11703 24 bits of the branch instruction. If however, we happen to know
11704 that the destination of the branch is in the same section as the
11705 branch instruction itself, then we can compute the relocation for
11706 ourselves and not have to bother the linker with it.
11708 FIXME: The tests for OBJ_ELF and ! target_oabi are only here
11709 because I have not worked out how to do this for OBJ_COFF or
11712 && fixP
->fx_addsy
!= NULL
11713 && S_IS_DEFINED (fixP
->fx_addsy
)
11714 && S_GET_SEGMENT (fixP
->fx_addsy
) == seg
)
11716 /* Get pc relative value to go into the branch. */
11719 /* Permit a backward branch provided that enough bits
11720 are set. Allow a forwards branch, provided that
11721 enough bits are clear. */
11722 if ( (value
& ~ ((offsetT
) 0x1ffffff)) == ~ ((offsetT
) 0x1ffffff)
11723 || (value
& ~ ((offsetT
) 0x1ffffff)) == 0)
11727 if (! fixP
->fx_done
)
11729 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11730 _("GAS can't handle same-section branch dest >= 0x04000000"));
11734 value
+= SEXT24 (newval
);
11736 if ( (value
& ~ ((offsetT
) 0xffffff)) != 0
11737 && ((value
& ~ ((offsetT
) 0xffffff)) != ~ ((offsetT
) 0xffffff)))
11738 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11739 _("out of range branch"));
11741 newval
= (value
& 0x00ffffff) | (newval
& 0xff000000);
11742 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11745 case BFD_RELOC_ARM_PCREL_BLX
:
11748 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11752 value
= fixP
->fx_offset
;
11754 hbit
= (value
>> 1) & 1;
11755 value
= (value
>> 2) & 0x00ffffff;
11756 value
= (value
+ (newval
& 0x00ffffff)) & 0x00ffffff;
11757 newval
= value
| (newval
& 0xfe000000) | (hbit
<< 24);
11758 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11762 case BFD_RELOC_THUMB_PCREL_BRANCH9
: /* Conditional branch. */
11763 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11765 addressT diff
= (newval
& 0xff) << 1;
11770 if ((value
& ~0xff) && ((value
& ~0xff) != ~0xff))
11771 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11772 _("branch out of range"));
11773 newval
= (newval
& 0xff00) | ((value
& 0x1ff) >> 1);
11775 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11778 case BFD_RELOC_THUMB_PCREL_BRANCH12
: /* Unconditional branch. */
11779 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11781 addressT diff
= (newval
& 0x7ff) << 1;
11786 if ((value
& ~0x7ff) && ((value
& ~0x7ff) != ~0x7ff))
11787 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11788 _("branch out of range"));
11789 newval
= (newval
& 0xf800) | ((value
& 0xfff) >> 1);
11791 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11794 case BFD_RELOC_THUMB_PCREL_BLX
:
11795 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
11800 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11801 newval2
= md_chars_to_number (buf
+ THUMB_SIZE
, THUMB_SIZE
);
11802 diff
= ((newval
& 0x7ff) << 12) | ((newval2
& 0x7ff) << 1);
11803 if (diff
& 0x400000)
11806 value
= fixP
->fx_offset
;
11810 if ((value
& ~0x3fffff) && ((value
& ~0x3fffff) != ~0x3fffff))
11811 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11812 _("branch with link out of range"));
11814 newval
= (newval
& 0xf800) | ((value
& 0x7fffff) >> 12);
11815 newval2
= (newval2
& 0xf800) | ((value
& 0xfff) >> 1);
11816 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
)
11817 /* For a BLX instruction, make sure that the relocation is rounded up
11818 to a word boundary. This follows the semantics of the instruction
11819 which specifies that bit 1 of the target address will come from bit
11820 1 of the base address. */
11821 newval2
= (newval2
+ 1) & ~ 1;
11822 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11823 md_number_to_chars (buf
+ THUMB_SIZE
, newval2
, THUMB_SIZE
);
11828 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11829 md_number_to_chars (buf
, value
, 1);
11831 else if (!target_oabi
)
11833 value
= fixP
->fx_offset
;
11834 md_number_to_chars (buf
, value
, 1);
11840 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11841 md_number_to_chars (buf
, value
, 2);
11843 else if (!target_oabi
)
11845 value
= fixP
->fx_offset
;
11846 md_number_to_chars (buf
, value
, 2);
11852 case BFD_RELOC_ARM_GOT32
:
11853 case BFD_RELOC_ARM_GOTOFF
:
11854 case BFD_RELOC_ARM_TARGET2
:
11855 md_number_to_chars (buf
, 0, 4);
11859 case BFD_RELOC_RVA
:
11861 case BFD_RELOC_ARM_TARGET1
:
11862 case BFD_RELOC_ARM_ROSEGREL32
:
11863 case BFD_RELOC_ARM_SBREL32
:
11864 case BFD_RELOC_32_PCREL
:
11865 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11866 md_number_to_chars (buf
, value
, 4);
11868 else if (!target_oabi
)
11870 value
= fixP
->fx_offset
;
11871 md_number_to_chars (buf
, value
, 4);
11877 case BFD_RELOC_ARM_PREL31
:
11878 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11880 newval
= md_chars_to_number (buf
, 4) & 0x80000000;
11881 if ((value
^ (value
>> 1)) & 0x40000000)
11883 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11884 _("rel31 relocation overflow"));
11886 newval
|= value
& 0x7fffffff;
11887 md_number_to_chars (buf
, newval
, 4);
11891 case BFD_RELOC_ARM_PLT32
:
11892 /* It appears the instruction is fully prepared at this point. */
11896 case BFD_RELOC_ARM_CP_OFF_IMM
:
11898 if (value
< -1023 || value
> 1023 || (value
& 3))
11899 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11900 _("illegal value for co-processor offset"));
11903 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
11904 newval
|= (value
>> 2) | (sign
? INDEX_UP
: 0);
11905 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11908 case BFD_RELOC_ARM_CP_OFF_IMM_S2
:
11910 if (value
< -255 || value
> 255)
11911 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11912 _("Illegal value for co-processor offset"));
11915 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
11916 newval
|= value
| (sign
? INDEX_UP
: 0);
11917 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11920 case BFD_RELOC_ARM_THUMB_OFFSET
:
11921 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11922 /* Exactly what ranges, and where the offset is inserted depends
11923 on the type of instruction, we can establish this from the
11925 switch (newval
>> 12)
11927 case 4: /* PC load. */
11928 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
11929 forced to zero for these loads, so we will need to round
11930 up the offset if the instruction address is not word
11931 aligned (since the final address produced must be, and
11932 we can only describe word-aligned immediate offsets). */
11934 if ((fixP
->fx_frag
->fr_address
+ fixP
->fx_where
+ value
) & 3)
11935 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11936 _("invalid offset, target not word aligned (0x%08X)"),
11937 (unsigned int) (fixP
->fx_frag
->fr_address
11938 + fixP
->fx_where
+ value
));
11940 if ((value
+ 2) & ~0x3fe)
11941 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11942 _("invalid offset, value too big (0x%08lX)"),
11945 /* Round up, since pc will be rounded down. */
11946 newval
|= (value
+ 2) >> 2;
11949 case 9: /* SP load/store. */
11950 if (value
& ~0x3fc)
11951 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11952 _("invalid offset, value too big (0x%08lX)"),
11954 newval
|= value
>> 2;
11957 case 6: /* Word load/store. */
11959 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11960 _("invalid offset, value too big (0x%08lX)"),
11962 newval
|= value
<< 4; /* 6 - 2. */
11965 case 7: /* Byte load/store. */
11967 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11968 _("invalid offset, value too big (0x%08lX)"),
11970 newval
|= value
<< 6;
11973 case 8: /* Halfword load/store. */
11975 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11976 _("invalid offset, value too big (0x%08lX)"),
11978 newval
|= value
<< 5; /* 6 - 1. */
11982 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11983 "Unable to process relocation for thumb opcode: %lx",
11984 (unsigned long) newval
);
11987 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11990 case BFD_RELOC_ARM_THUMB_ADD
:
11991 /* This is a complicated relocation, since we use it for all of
11992 the following immediate relocations:
11996 9bit ADD/SUB SP word-aligned
11997 10bit ADD PC/SP word-aligned
11999 The type of instruction being processed is encoded in the
12006 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12008 int rd
= (newval
>> 4) & 0xf;
12009 int rs
= newval
& 0xf;
12010 int subtract
= newval
& 0x8000;
12014 if (value
& ~0x1fc)
12015 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12016 _("invalid immediate for stack address calculation"));
12017 newval
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
12018 newval
|= value
>> 2;
12020 else if (rs
== REG_PC
|| rs
== REG_SP
)
12024 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12025 _("invalid immediate for address calculation (value = 0x%08lX)"),
12026 (unsigned long) value
);
12027 newval
= (rs
== REG_PC
? T_OPCODE_ADD_PC
: T_OPCODE_ADD_SP
);
12029 newval
|= value
>> 2;
12034 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12035 _("invalid 8bit immediate"));
12036 newval
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
12037 newval
|= (rd
<< 8) | value
;
12042 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12043 _("invalid 3bit immediate"));
12044 newval
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
12045 newval
|= rd
| (rs
<< 3) | (value
<< 6);
12048 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12051 case BFD_RELOC_ARM_THUMB_IMM
:
12052 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12053 switch (newval
>> 11)
12055 case 0x04: /* 8bit immediate MOV. */
12056 case 0x05: /* 8bit immediate CMP. */
12057 if (value
< 0 || value
> 255)
12058 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12059 _("invalid immediate: %ld is too large"),
12067 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12070 case BFD_RELOC_ARM_THUMB_SHIFT
:
12071 /* 5bit shift value (0..31). */
12072 if (value
< 0 || value
> 31)
12073 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12074 _("illegal Thumb shift value: %ld"), (long) value
);
12075 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xf03f;
12076 newval
|= value
<< 6;
12077 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12080 case BFD_RELOC_VTABLE_INHERIT
:
12081 case BFD_RELOC_VTABLE_ENTRY
:
12085 case BFD_RELOC_NONE
:
12087 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12088 _("bad relocation fixup type (%d)"), fixP
->fx_r_type
);
12092 /* Translate internal representation of relocation info to BFD target
12096 tc_gen_reloc (asection
* section ATTRIBUTE_UNUSED
,
12100 bfd_reloc_code_real_type code
;
12102 reloc
= xmalloc (sizeof (arelent
));
12104 reloc
->sym_ptr_ptr
= xmalloc (sizeof (asymbol
*));
12105 *reloc
->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
12106 reloc
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
12108 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12110 if (fixp
->fx_pcrel
== 0)
12111 reloc
->addend
= fixp
->fx_offset
;
12113 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
12114 #else /* OBJ_ELF */
12115 reloc
->addend
= fixp
->fx_offset
;
12118 switch (fixp
->fx_r_type
)
12121 if (fixp
->fx_pcrel
)
12123 code
= BFD_RELOC_8_PCREL
;
12128 if (fixp
->fx_pcrel
)
12130 code
= BFD_RELOC_16_PCREL
;
12135 if (fixp
->fx_pcrel
)
12137 code
= BFD_RELOC_32_PCREL
;
12141 case BFD_RELOC_ARM_PCREL_BRANCH
:
12142 case BFD_RELOC_ARM_PCREL_BLX
:
12143 case BFD_RELOC_RVA
:
12144 case BFD_RELOC_THUMB_PCREL_BRANCH9
:
12145 case BFD_RELOC_THUMB_PCREL_BRANCH12
:
12146 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
12147 case BFD_RELOC_THUMB_PCREL_BLX
:
12148 case BFD_RELOC_VTABLE_ENTRY
:
12149 case BFD_RELOC_VTABLE_INHERIT
:
12150 code
= fixp
->fx_r_type
;
12153 case BFD_RELOC_ARM_LITERAL
:
12154 case BFD_RELOC_ARM_HWLITERAL
:
12155 /* If this is called then the a literal has
12156 been referenced across a section boundary. */
12157 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12158 _("literal referenced across section boundary"));
12162 case BFD_RELOC_ARM_GOT32
:
12163 case BFD_RELOC_ARM_GOTOFF
:
12164 case BFD_RELOC_ARM_PLT32
:
12165 case BFD_RELOC_ARM_TARGET1
:
12166 case BFD_RELOC_ARM_ROSEGREL32
:
12167 case BFD_RELOC_ARM_SBREL32
:
12168 case BFD_RELOC_ARM_PREL31
:
12169 case BFD_RELOC_ARM_TARGET2
:
12170 code
= fixp
->fx_r_type
;
12174 case BFD_RELOC_ARM_IMMEDIATE
:
12175 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12176 _("internal relocation (type: IMMEDIATE) not fixed up"));
12179 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
12180 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12181 _("ADRL used for a symbol not defined in the same file"));
12184 case BFD_RELOC_ARM_OFFSET_IMM
:
12185 if (fixp
->fx_addsy
!= NULL
12186 && !S_IS_DEFINED (fixp
->fx_addsy
)
12187 && S_IS_LOCAL (fixp
->fx_addsy
))
12189 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12190 _("undefined local label `%s'"),
12191 S_GET_NAME (fixp
->fx_addsy
));
12195 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12196 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
12203 switch (fixp
->fx_r_type
)
12205 case BFD_RELOC_ARM_OFFSET_IMM8
: type
= "OFFSET_IMM8"; break;
12206 case BFD_RELOC_ARM_SHIFT_IMM
: type
= "SHIFT_IMM"; break;
12207 case BFD_RELOC_ARM_SWI
: type
= "SWI"; break;
12208 case BFD_RELOC_ARM_MULTI
: type
= "MULTI"; break;
12209 case BFD_RELOC_ARM_CP_OFF_IMM
: type
= "CP_OFF_IMM"; break;
12210 case BFD_RELOC_ARM_THUMB_ADD
: type
= "THUMB_ADD"; break;
12211 case BFD_RELOC_ARM_THUMB_SHIFT
: type
= "THUMB_SHIFT"; break;
12212 case BFD_RELOC_ARM_THUMB_IMM
: type
= "THUMB_IMM"; break;
12213 case BFD_RELOC_ARM_THUMB_OFFSET
: type
= "THUMB_OFFSET"; break;
12214 default: type
= _("<unknown>"); break;
12216 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12217 _("cannot represent %s relocation in this object file format"),
12224 if ((code
== BFD_RELOC_32_PCREL
|| code
== BFD_RELOC_32
)
12226 && fixp
->fx_addsy
== GOT_symbol
)
12228 code
= BFD_RELOC_ARM_GOTPC
;
12229 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
12233 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, code
);
12235 if (reloc
->howto
== NULL
)
12237 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12238 _("cannot represent %s relocation in this object file format"),
12239 bfd_get_reloc_code_name (code
));
12243 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12244 vtable entry to be used in the relocation's section offset. */
12245 if (fixp
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
12246 reloc
->address
= fixp
->fx_offset
;
12252 md_estimate_size_before_relax (fragS
* fragP ATTRIBUTE_UNUSED
,
12253 segT segtype ATTRIBUTE_UNUSED
)
12255 as_fatal (_("md_estimate_size_before_relax\n"));
12259 /* We need to be able to fix up arbitrary expressions in some statements.
12260 This is so that we can handle symbols that are an arbitrary distance from
12261 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
12262 which returns part of an address in a form which will be valid for
12263 a data instruction. We do this by pushing the expression into a symbol
12264 in the expr_section, and creating a fix for that. */
12267 fix_new_arm (fragS
* frag
,
12275 arm_fix_data
* arm_data
;
12283 new_fix
= fix_new_exp (frag
, where
, size
, exp
, pc_rel
, reloc
);
12287 new_fix
= fix_new (frag
, where
, size
, make_expr_symbol (exp
), 0,
12292 /* Mark whether the fix is to a THUMB instruction, or an ARM
12294 arm_data
= obstack_alloc (& notes
, sizeof (arm_fix_data
));
12295 new_fix
->tc_fix_data
= (PTR
) arm_data
;
12296 arm_data
->thumb_mode
= thumb_mode
;
12300 output_inst (const char * str
)
12306 as_bad ("%s -- `%s'", inst
.error
, str
);
12310 to
= frag_more (inst
.size
);
12312 if (thumb_mode
&& (inst
.size
> THUMB_SIZE
))
12314 assert (inst
.size
== (2 * THUMB_SIZE
));
12315 md_number_to_chars (to
, inst
.instruction
>> 16, THUMB_SIZE
);
12316 md_number_to_chars (to
+ THUMB_SIZE
, inst
.instruction
, THUMB_SIZE
);
12318 else if (inst
.size
> INSN_SIZE
)
12320 assert (inst
.size
== (2 * INSN_SIZE
));
12321 md_number_to_chars (to
, inst
.instruction
, INSN_SIZE
);
12322 md_number_to_chars (to
+ INSN_SIZE
, inst
.instruction
, INSN_SIZE
);
12325 md_number_to_chars (to
, inst
.instruction
, inst
.size
);
12327 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
12328 fix_new_arm (frag_now
, to
- frag_now
->fr_literal
,
12329 inst
.size
, & inst
.reloc
.exp
, inst
.reloc
.pc_rel
,
12333 dwarf2_emit_insn (inst
.size
);
12338 md_assemble (char * str
)
12344 /* Align the instruction.
12345 This may not be the right thing to do but ... */
12350 /* Align the previous label if needed. */
12351 if (last_label_seen
!= NULL
)
12353 symbol_set_frag (last_label_seen
, frag_now
);
12354 S_SET_VALUE (last_label_seen
, (valueT
) frag_now_fix ());
12355 S_SET_SEGMENT (last_label_seen
, now_seg
);
12358 memset (&inst
, '\0', sizeof (inst
));
12359 inst
.reloc
.type
= BFD_RELOC_NONE
;
12361 skip_whitespace (str
);
12363 /* Scan up to the end of the op-code, which must end in white space or
12365 for (start
= p
= str
; *p
!= '\0'; p
++)
12371 as_bad (_("no operator -- statement `%s'\n"), str
);
12377 const struct thumb_opcode
* opcode
;
12381 opcode
= (const struct thumb_opcode
*) hash_find (arm_tops_hsh
, str
);
12386 /* Check that this instruction is supported for this CPU. */
12387 if (thumb_mode
== 1 && (opcode
->variant
& cpu_variant
) == 0)
12389 as_bad (_("selected processor does not support `%s'"), str
);
12393 mapping_state (MAP_THUMB
);
12394 inst
.instruction
= opcode
->value
;
12395 inst
.size
= opcode
->size
;
12403 const struct asm_opcode
* opcode
;
12407 opcode
= (const struct asm_opcode
*) hash_find (arm_ops_hsh
, str
);
12412 /* Check that this instruction is supported for this CPU. */
12413 if ((opcode
->variant
& cpu_variant
) == 0)
12415 as_bad (_("selected processor does not support `%s'"), str
);
12419 mapping_state (MAP_ARM
);
12420 inst
.instruction
= opcode
->value
;
12421 inst
.size
= INSN_SIZE
;
12428 /* It wasn't an instruction, but it might be a register alias of the form
12430 if (create_register_alias (str
, p
))
12433 as_bad (_("bad instruction `%s'"), start
);
12437 Invocation line includes a switch not recognized by the base assembler.
12438 See if it's a processor-specific option.
12440 This routine is somewhat complicated by the need for backwards
12441 compatibility (since older releases of gcc can't be changed).
12442 The new options try to make the interface as compatible as
12445 New options (supported) are:
12447 -mcpu=<cpu name> Assemble for selected processor
12448 -march=<architecture name> Assemble for selected architecture
12449 -mfpu=<fpu architecture> Assemble for selected FPU.
12450 -EB/-mbig-endian Big-endian
12451 -EL/-mlittle-endian Little-endian
12452 -k Generate PIC code
12453 -mthumb Start in Thumb mode
12454 -mthumb-interwork Code supports ARM/Thumb interworking
12456 For now we will also provide support for:
12458 -mapcs-32 32-bit Program counter
12459 -mapcs-26 26-bit Program counter
12460 -macps-float Floats passed in FP registers
12461 -mapcs-reentrant Reentrant code
12463 (sometime these will probably be replaced with -mapcs=<list of options>
12464 and -matpcs=<list of options>)
12466 The remaining options are only supported for back-wards compatibility.
12467 Cpu variants, the arm part is optional:
12468 -m[arm]1 Currently not supported.
12469 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
12470 -m[arm]3 Arm 3 processor
12471 -m[arm]6[xx], Arm 6 processors
12472 -m[arm]7[xx][t][[d]m] Arm 7 processors
12473 -m[arm]8[10] Arm 8 processors
12474 -m[arm]9[20][tdmi] Arm 9 processors
12475 -mstrongarm[110[0]] StrongARM processors
12476 -mxscale XScale processors
12477 -m[arm]v[2345[t[e]]] Arm architectures
12478 -mall All (except the ARM1)
12480 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
12481 -mfpe-old (No float load/store multiples)
12482 -mvfpxd VFP Single precision
12484 -mno-fpu Disable all floating point instructions
12486 The following CPU names are recognized:
12487 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
12488 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
12489 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
12490 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
12491 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
12492 arm10t arm10e, arm1020t, arm1020e, arm10200e,
12493 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
12497 const char * md_shortopts
= "m:k";
12499 #ifdef ARM_BI_ENDIAN
12500 #define OPTION_EB (OPTION_MD_BASE + 0)
12501 #define OPTION_EL (OPTION_MD_BASE + 1)
12503 #if TARGET_BYTES_BIG_ENDIAN
12504 #define OPTION_EB (OPTION_MD_BASE + 0)
12506 #define OPTION_EL (OPTION_MD_BASE + 1)
12510 struct option md_longopts
[] =
12513 {"EB", no_argument
, NULL
, OPTION_EB
},
12516 {"EL", no_argument
, NULL
, OPTION_EL
},
12518 {NULL
, no_argument
, NULL
, 0}
12521 size_t md_longopts_size
= sizeof (md_longopts
);
12523 struct arm_option_table
12525 char *option
; /* Option name to match. */
12526 char *help
; /* Help information. */
12527 int *var
; /* Variable to change. */
12528 int value
; /* What to change it to. */
12529 char *deprecated
; /* If non-null, print this message. */
12532 struct arm_option_table arm_opts
[] =
12534 {"k", N_("generate PIC code"), &pic_code
, 1, NULL
},
12535 {"mthumb", N_("assemble Thumb code"), &thumb_mode
, 1, NULL
},
12536 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
12537 &support_interwork
, 1, NULL
},
12538 {"moabi", N_("use old ABI (ELF only)"), &target_oabi
, 1, NULL
},
12539 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26
, 0, NULL
},
12540 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26
, 1, NULL
},
12541 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float
,
12543 {"mapcs-reentrant", N_("re-entrant code"), &pic_code
, 1, NULL
},
12544 {"matpcs", N_("code is ATPCS conformant"), &atpcs
, 1, NULL
},
12545 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian
, 1, NULL
},
12546 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian
, 1,
12549 /* These are recognized by the assembler, but have no affect on code. */
12550 {"mapcs-frame", N_("use frame pointer"), NULL
, 0, NULL
},
12551 {"mapcs-stack-check", N_("use stack size checking"), NULL
, 0, NULL
},
12553 /* DON'T add any new processors to this list -- we want the whole list
12554 to go away... Add them to the processors table instead. */
12555 {"marm1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
12556 {"m1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
12557 {"marm2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
12558 {"m2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
12559 {"marm250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
12560 {"m250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
12561 {"marm3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
12562 {"m3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
12563 {"marm6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
12564 {"m6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
12565 {"marm600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
12566 {"m600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
12567 {"marm610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
12568 {"m610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
12569 {"marm620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
12570 {"m620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
12571 {"marm7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
12572 {"m7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
12573 {"marm70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
12574 {"m70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
12575 {"marm700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
12576 {"m700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
12577 {"marm700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
12578 {"m700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
12579 {"marm710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
12580 {"m710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
12581 {"marm710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
12582 {"m710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
12583 {"marm720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
12584 {"m720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
12585 {"marm7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
12586 {"m7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
12587 {"marm7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
12588 {"m7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
12589 {"marm7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
12590 {"m7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
12591 {"marm7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
12592 {"m7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
12593 {"marm7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
12594 {"m7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
12595 {"marm7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
12596 {"m7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
12597 {"marm7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
12598 {"m7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
12599 {"marm7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
12600 {"m7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
12601 {"marm7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12602 {"m7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12603 {"marm7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12604 {"m7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12605 {"marm710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
12606 {"m710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
12607 {"marm720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
12608 {"m720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
12609 {"marm740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
12610 {"m740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
12611 {"marm8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
12612 {"m8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
12613 {"marm810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
12614 {"m810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
12615 {"marm9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
12616 {"m9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
12617 {"marm9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
12618 {"m9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
12619 {"marm920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
12620 {"m920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
12621 {"marm940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
12622 {"m940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
12623 {"mstrongarm", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=strongarm")},
12624 {"mstrongarm110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
12625 N_("use -mcpu=strongarm110")},
12626 {"mstrongarm1100", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
12627 N_("use -mcpu=strongarm1100")},
12628 {"mstrongarm1110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
12629 N_("use -mcpu=strongarm1110")},
12630 {"mxscale", NULL
, &legacy_cpu
, ARM_ARCH_XSCALE
, N_("use -mcpu=xscale")},
12631 {"miwmmxt", NULL
, &legacy_cpu
, ARM_ARCH_IWMMXT
, N_("use -mcpu=iwmmxt")},
12632 {"mall", NULL
, &legacy_cpu
, ARM_ANY
, N_("use -mcpu=all")},
12634 /* Architecture variants -- don't add any more to this list either. */
12635 {"mv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
12636 {"marmv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
12637 {"mv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
12638 {"marmv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
12639 {"mv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
12640 {"marmv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
12641 {"mv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
12642 {"marmv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
12643 {"mv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
12644 {"marmv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
12645 {"mv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
12646 {"marmv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
12647 {"mv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
12648 {"marmv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
12649 {"mv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
12650 {"marmv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
12651 {"mv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
12652 {"marmv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
12654 /* Floating point variants -- don't add any more to this list either. */
12655 {"mfpe-old", NULL
, &legacy_fpu
, FPU_ARCH_FPE
, N_("use -mfpu=fpe")},
12656 {"mfpa10", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa10")},
12657 {"mfpa11", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa11")},
12658 {"mno-fpu", NULL
, &legacy_fpu
, 0,
12659 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
12661 {NULL
, NULL
, NULL
, 0, NULL
}
12664 struct arm_cpu_option_table
12668 /* For some CPUs we assume an FPU unless the user explicitly sets
12673 /* This list should, at a minimum, contain all the cpu names
12674 recognized by GCC. */
12675 static struct arm_cpu_option_table arm_cpus
[] =
12677 {"all", ARM_ANY
, FPU_ARCH_FPA
},
12678 {"arm1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
12679 {"arm2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
12680 {"arm250", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
12681 {"arm3", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
12682 {"arm6", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12683 {"arm60", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12684 {"arm600", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12685 {"arm610", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12686 {"arm620", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12687 {"arm7", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12688 {"arm7m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
12689 {"arm7d", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12690 {"arm7dm", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
12691 {"arm7di", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12692 {"arm7dmi", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
12693 {"arm70", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12694 {"arm700", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12695 {"arm700i", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12696 {"arm710", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12697 {"arm710t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12698 {"arm720", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12699 {"arm720t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12700 {"arm740t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12701 {"arm710c", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12702 {"arm7100", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12703 {"arm7500", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12704 {"arm7500fe", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12705 {"arm7t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12706 {"arm7tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12707 {"arm7tdmi-s", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12708 {"arm8", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12709 {"arm810", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12710 {"strongarm", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12711 {"strongarm1", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12712 {"strongarm110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12713 {"strongarm1100", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12714 {"strongarm1110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12715 {"arm9", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12716 {"arm920", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12717 {"arm920t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12718 {"arm922t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12719 {"arm940t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12720 {"arm9tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12721 /* For V5 or later processors we default to using VFP; but the user
12722 should really set the FPU type explicitly. */
12723 {"arm9e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
12724 {"arm9e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12725 {"arm926ej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
12726 {"arm926ejs", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
12727 {"arm926ej-s", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
12728 {"arm946e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
12729 {"arm946e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12730 {"arm966e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
12731 {"arm966e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12732 {"arm10t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
12733 {"arm10e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12734 {"arm1020", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12735 {"arm1020t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
12736 {"arm1020e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12737 {"arm1026ejs", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12738 {"arm1026ej-s", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12739 {"arm1136js", ARM_ARCH_V6
, FPU_NONE
},
12740 {"arm1136j-s", ARM_ARCH_V6
, FPU_NONE
},
12741 {"arm1136jfs", ARM_ARCH_V6
, FPU_ARCH_VFP_V2
},
12742 {"arm1136jf-s", ARM_ARCH_V6
, FPU_ARCH_VFP_V2
},
12743 /* ??? XSCALE is really an architecture. */
12744 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
12745 /* ??? iwmmxt is not a processor. */
12746 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP_V2
},
12747 {"i80200", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
12749 {"ep9312", ARM_ARCH_V4T
| ARM_CEXT_MAVERICK
, FPU_ARCH_MAVERICK
},
12753 struct arm_arch_option_table
12760 /* This list should, at a minimum, contain all the architecture names
12761 recognized by GCC. */
12762 static struct arm_arch_option_table arm_archs
[] =
12764 {"all", ARM_ANY
, FPU_ARCH_FPA
},
12765 {"armv1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
12766 {"armv2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
12767 {"armv2a", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
12768 {"armv2s", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
12769 {"armv3", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12770 {"armv3m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
12771 {"armv4", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12772 {"armv4xm", ARM_ARCH_V4xM
, FPU_ARCH_FPA
},
12773 {"armv4t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12774 {"armv4txm", ARM_ARCH_V4TxM
, FPU_ARCH_FPA
},
12775 {"armv5", ARM_ARCH_V5
, FPU_ARCH_VFP
},
12776 {"armv5t", ARM_ARCH_V5T
, FPU_ARCH_VFP
},
12777 {"armv5txm", ARM_ARCH_V5TxM
, FPU_ARCH_VFP
},
12778 {"armv5te", ARM_ARCH_V5TE
, FPU_ARCH_VFP
},
12779 {"armv5texp", ARM_ARCH_V5TExP
, FPU_ARCH_VFP
},
12780 {"armv5tej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP
},
12781 {"armv6", ARM_ARCH_V6
, FPU_ARCH_VFP
},
12782 {"armv6j", ARM_ARCH_V6
, FPU_ARCH_VFP
},
12783 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP
},
12784 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP
},
12788 /* ISA extensions in the co-processor space. */
12789 struct arm_arch_extension_table
12795 static struct arm_arch_extension_table arm_extensions
[] =
12797 {"maverick", ARM_CEXT_MAVERICK
},
12798 {"xscale", ARM_CEXT_XSCALE
},
12799 {"iwmmxt", ARM_CEXT_IWMMXT
},
12803 struct arm_fpu_option_table
12809 /* This list should, at a minimum, contain all the fpu names
12810 recognized by GCC. */
12811 static struct arm_fpu_option_table arm_fpus
[] =
12813 {"softfpa", FPU_NONE
},
12814 {"fpe", FPU_ARCH_FPE
},
12815 {"fpe2", FPU_ARCH_FPE
},
12816 {"fpe3", FPU_ARCH_FPA
}, /* Third release supports LFM/SFM. */
12817 {"fpa", FPU_ARCH_FPA
},
12818 {"fpa10", FPU_ARCH_FPA
},
12819 {"fpa11", FPU_ARCH_FPA
},
12820 {"arm7500fe", FPU_ARCH_FPA
},
12821 {"softvfp", FPU_ARCH_VFP
},
12822 {"softvfp+vfp", FPU_ARCH_VFP_V2
},
12823 {"vfp", FPU_ARCH_VFP_V2
},
12824 {"vfp9", FPU_ARCH_VFP_V2
},
12825 {"vfp10", FPU_ARCH_VFP_V2
},
12826 {"vfp10-r0", FPU_ARCH_VFP_V1
},
12827 {"vfpxd", FPU_ARCH_VFP_V1xD
},
12828 {"arm1020t", FPU_ARCH_VFP_V1
},
12829 {"arm1020e", FPU_ARCH_VFP_V2
},
12830 {"arm1136jfs", FPU_ARCH_VFP_V2
},
12831 {"arm1136jf-s", FPU_ARCH_VFP_V2
},
12832 {"maverick", FPU_ARCH_MAVERICK
},
12836 struct arm_float_abi_option_table
12842 static struct arm_float_abi_option_table arm_float_abis
[] =
12844 {"hard", ARM_FLOAT_ABI_HARD
},
12845 {"softfp", ARM_FLOAT_ABI_SOFTFP
},
12846 {"soft", ARM_FLOAT_ABI_SOFT
},
12850 struct arm_eabi_option_table
12853 unsigned int value
;
12857 /* We only know hot to output GNU and ver 3 (AAELF) formats. */
12858 static struct arm_eabi_option_table arm_eabis
[] =
12860 {"gnu", EF_ARM_EABI_UNKNOWN
},
12861 {"3", EF_ARM_EABI_VER3
},
12866 struct arm_long_option_table
12868 char * option
; /* Substring to match. */
12869 char * help
; /* Help information. */
12870 int (* func
) (char * subopt
); /* Function to decode sub-option. */
12871 char * deprecated
; /* If non-null, print this message. */
12875 arm_parse_extension (char * str
, int * opt_p
)
12877 while (str
!= NULL
&& *str
!= 0)
12879 struct arm_arch_extension_table
* opt
;
12885 as_bad (_("invalid architectural extension"));
12890 ext
= strchr (str
, '+');
12893 optlen
= ext
- str
;
12895 optlen
= strlen (str
);
12899 as_bad (_("missing architectural extension"));
12903 for (opt
= arm_extensions
; opt
->name
!= NULL
; opt
++)
12904 if (strncmp (opt
->name
, str
, optlen
) == 0)
12906 *opt_p
|= opt
->value
;
12910 if (opt
->name
== NULL
)
12912 as_bad (_("unknown architectural extnsion `%s'"), str
);
12923 arm_parse_cpu (char * str
)
12925 struct arm_cpu_option_table
* opt
;
12926 char * ext
= strchr (str
, '+');
12930 optlen
= ext
- str
;
12932 optlen
= strlen (str
);
12936 as_bad (_("missing cpu name `%s'"), str
);
12940 for (opt
= arm_cpus
; opt
->name
!= NULL
; opt
++)
12941 if (strncmp (opt
->name
, str
, optlen
) == 0)
12943 mcpu_cpu_opt
= opt
->value
;
12944 mcpu_fpu_opt
= opt
->default_fpu
;
12947 return arm_parse_extension (ext
, &mcpu_cpu_opt
);
12952 as_bad (_("unknown cpu `%s'"), str
);
12957 arm_parse_arch (char * str
)
12959 struct arm_arch_option_table
*opt
;
12960 char *ext
= strchr (str
, '+');
12964 optlen
= ext
- str
;
12966 optlen
= strlen (str
);
12970 as_bad (_("missing architecture name `%s'"), str
);
12975 for (opt
= arm_archs
; opt
->name
!= NULL
; opt
++)
12976 if (streq (opt
->name
, str
))
12978 march_cpu_opt
= opt
->value
;
12979 march_fpu_opt
= opt
->default_fpu
;
12982 return arm_parse_extension (ext
, &march_cpu_opt
);
12987 as_bad (_("unknown architecture `%s'\n"), str
);
12992 arm_parse_fpu (char * str
)
12994 struct arm_fpu_option_table
* opt
;
12996 for (opt
= arm_fpus
; opt
->name
!= NULL
; opt
++)
12997 if (streq (opt
->name
, str
))
12999 mfpu_opt
= opt
->value
;
13003 as_bad (_("unknown floating point format `%s'\n"), str
);
13008 arm_parse_float_abi (char * str
)
13010 struct arm_float_abi_option_table
* opt
;
13012 for (opt
= arm_float_abis
; opt
->name
!= NULL
; opt
++)
13013 if (streq (opt
->name
, str
))
13015 mfloat_abi_opt
= opt
->value
;
13019 as_bad (_("unknown floating point abi `%s'\n"), str
);
13025 arm_parse_eabi (char * str
)
13027 struct arm_eabi_option_table
*opt
;
13029 for (opt
= arm_eabis
; opt
->name
!= NULL
; opt
++)
13030 if (streq (opt
->name
, str
))
13032 meabi_flags
= opt
->value
;
13035 as_bad (_("unknown EABI `%s'\n"), str
);
13040 struct arm_long_option_table arm_long_opts
[] =
13042 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13043 arm_parse_cpu
, NULL
},
13044 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13045 arm_parse_arch
, NULL
},
13046 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13047 arm_parse_fpu
, NULL
},
13048 {"mfloat-abi=", N_("<abi>\t assemble for floating point ABI <abi>"),
13049 arm_parse_float_abi
, NULL
},
13051 {"meabi=", N_("<ver>\t assemble for eabi version <ver>"),
13052 arm_parse_eabi
, NULL
},
13054 {NULL
, NULL
, 0, NULL
}
13058 md_parse_option (int c
, char * arg
)
13060 struct arm_option_table
*opt
;
13061 struct arm_long_option_table
*lopt
;
13067 target_big_endian
= 1;
13073 target_big_endian
= 0;
13078 /* Listing option. Just ignore these, we don't support additional
13083 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
13085 if (c
== opt
->option
[0]
13086 && ((arg
== NULL
&& opt
->option
[1] == 0)
13087 || streq (arg
, opt
->option
+ 1)))
13089 #if WARN_DEPRECATED
13090 /* If the option is deprecated, tell the user. */
13091 if (opt
->deprecated
!= NULL
)
13092 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
,
13093 arg
? arg
: "", _(opt
->deprecated
));
13096 if (opt
->var
!= NULL
)
13097 *opt
->var
= opt
->value
;
13103 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
13105 /* These options are expected to have an argument. */
13106 if (c
== lopt
->option
[0]
13108 && strncmp (arg
, lopt
->option
+ 1,
13109 strlen (lopt
->option
+ 1)) == 0)
13111 #if WARN_DEPRECATED
13112 /* If the option is deprecated, tell the user. */
13113 if (lopt
->deprecated
!= NULL
)
13114 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
, arg
,
13115 _(lopt
->deprecated
));
13118 /* Call the sup-option parser. */
13119 return lopt
->func (arg
+ strlen (lopt
->option
) - 1);
13130 md_show_usage (FILE * fp
)
13132 struct arm_option_table
*opt
;
13133 struct arm_long_option_table
*lopt
;
13135 fprintf (fp
, _(" ARM-specific assembler options:\n"));
13137 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
13138 if (opt
->help
!= NULL
)
13139 fprintf (fp
, " -%-23s%s\n", opt
->option
, _(opt
->help
));
13141 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
13142 if (lopt
->help
!= NULL
)
13143 fprintf (fp
, " -%s%s\n", lopt
->option
, _(lopt
->help
));
13147 -EB assemble code for a big-endian cpu\n"));
13152 -EL assemble code for a little-endian cpu\n"));
13156 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13159 cons_fix_new_arm (fragS
* frag
,
13164 bfd_reloc_code_real_type type
;
13168 FIXME: @@ Should look at CPU word size. */
13172 type
= BFD_RELOC_8
;
13175 type
= BFD_RELOC_16
;
13179 type
= BFD_RELOC_32
;
13182 type
= BFD_RELOC_64
;
13186 fix_new_exp (frag
, where
, (int) size
, exp
, pcrel
, type
);
13189 /* A good place to do this, although this was probably not intended
13190 for this kind of use. We need to dump the literal pool before
13191 references are made to a null symbol pointer. */
13196 literal_pool
* pool
;
13198 for (pool
= list_of_pools
; pool
; pool
= pool
->next
)
13200 /* Put it at the end of the relevent section. */
13201 subseg_set (pool
->section
, pool
->sub_section
);
13203 arm_elf_change_section ();
13210 arm_start_line_hook (void)
13212 last_label_seen
= NULL
;
13216 arm_frob_label (symbolS
* sym
)
13218 last_label_seen
= sym
;
13220 ARM_SET_THUMB (sym
, thumb_mode
);
13222 #if defined OBJ_COFF || defined OBJ_ELF
13223 ARM_SET_INTERWORK (sym
, support_interwork
);
13226 /* Note - do not allow local symbols (.Lxxx) to be labeled
13227 as Thumb functions. This is because these labels, whilst
13228 they exist inside Thumb code, are not the entry points for
13229 possible ARM->Thumb calls. Also, these labels can be used
13230 as part of a computed goto or switch statement. eg gcc
13231 can generate code that looks like this:
13233 ldr r2, [pc, .Laaa]
13243 The first instruction loads the address of the jump table.
13244 The second instruction converts a table index into a byte offset.
13245 The third instruction gets the jump address out of the table.
13246 The fourth instruction performs the jump.
13248 If the address stored at .Laaa is that of a symbol which has the
13249 Thumb_Func bit set, then the linker will arrange for this address
13250 to have the bottom bit set, which in turn would mean that the
13251 address computation performed by the third instruction would end
13252 up with the bottom bit set. Since the ARM is capable of unaligned
13253 word loads, the instruction would then load the incorrect address
13254 out of the jump table, and chaos would ensue. */
13255 if (label_is_thumb_function_name
13256 && (S_GET_NAME (sym
)[0] != '.' || S_GET_NAME (sym
)[1] != 'L')
13257 && (bfd_get_section_flags (stdoutput
, now_seg
) & SEC_CODE
) != 0)
13259 /* When the address of a Thumb function is taken the bottom
13260 bit of that address should be set. This will allow
13261 interworking between Arm and Thumb functions to work
13264 THUMB_SET_FUNC (sym
, 1);
13266 label_is_thumb_function_name
= FALSE
;
13270 /* Adjust the symbol table. This marks Thumb symbols as distinct from
13274 arm_adjust_symtab (void)
13279 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
13281 if (ARM_IS_THUMB (sym
))
13283 if (THUMB_IS_FUNC (sym
))
13285 /* Mark the symbol as a Thumb function. */
13286 if ( S_GET_STORAGE_CLASS (sym
) == C_STAT
13287 || S_GET_STORAGE_CLASS (sym
) == C_LABEL
) /* This can happen! */
13288 S_SET_STORAGE_CLASS (sym
, C_THUMBSTATFUNC
);
13290 else if (S_GET_STORAGE_CLASS (sym
) == C_EXT
)
13291 S_SET_STORAGE_CLASS (sym
, C_THUMBEXTFUNC
);
13293 as_bad (_("%s: unexpected function type: %d"),
13294 S_GET_NAME (sym
), S_GET_STORAGE_CLASS (sym
));
13296 else switch (S_GET_STORAGE_CLASS (sym
))
13299 S_SET_STORAGE_CLASS (sym
, C_THUMBEXT
);
13302 S_SET_STORAGE_CLASS (sym
, C_THUMBSTAT
);
13305 S_SET_STORAGE_CLASS (sym
, C_THUMBLABEL
);
13313 if (ARM_IS_INTERWORK (sym
))
13314 coffsymbol (symbol_get_bfdsym (sym
))->native
->u
.syment
.n_flags
= 0xFF;
13321 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
13323 if (ARM_IS_THUMB (sym
))
13325 elf_symbol_type
* elf_sym
;
13327 elf_sym
= elf_symbol (symbol_get_bfdsym (sym
));
13328 bind
= ELF_ST_BIND (elf_sym
);
13330 /* If it's a .thumb_func, declare it as so,
13331 otherwise tag label as .code 16. */
13332 if (THUMB_IS_FUNC (sym
))
13333 elf_sym
->internal_elf_sym
.st_info
=
13334 ELF_ST_INFO (bind
, STT_ARM_TFUNC
);
13336 elf_sym
->internal_elf_sym
.st_info
=
13337 ELF_ST_INFO (bind
, STT_ARM_16BIT
);
13344 arm_data_in_code (void)
13346 if (thumb_mode
&& ! strncmp (input_line_pointer
+ 1, "data:", 5))
13348 *input_line_pointer
= '/';
13349 input_line_pointer
+= 5;
13350 *input_line_pointer
= 0;
13358 arm_canonicalize_symbol_name (char * name
)
13362 if (thumb_mode
&& (len
= strlen (name
)) > 5
13363 && streq (name
+ len
- 5, "/data"))
13364 *(name
+ len
- 5) = 0;
13369 #if defined OBJ_COFF || defined OBJ_ELF
13371 arm_validate_fix (fixS
* fixP
)
13373 /* If the destination of the branch is a defined symbol which does not have
13374 the THUMB_FUNC attribute, then we must be calling a function which has
13375 the (interfacearm) attribute. We look for the Thumb entry point to that
13376 function and change the branch to refer to that function instead. */
13377 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
13378 && fixP
->fx_addsy
!= NULL
13379 && S_IS_DEFINED (fixP
->fx_addsy
)
13380 && ! THUMB_IS_FUNC (fixP
->fx_addsy
))
13382 fixP
->fx_addsy
= find_real_start (fixP
->fx_addsy
);
13388 arm_force_relocation (struct fix
* fixp
)
13390 #if defined (OBJ_COFF) && defined (TE_PE)
13391 if (fixp
->fx_r_type
== BFD_RELOC_RVA
)
13395 if (fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
13396 || fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
13397 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
13398 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
)
13402 /* Resolve these relocations even if the symbol is extern or weak. */
13403 if (fixp
->fx_r_type
== BFD_RELOC_ARM_IMMEDIATE
13404 || fixp
->fx_r_type
== BFD_RELOC_ARM_OFFSET_IMM
13405 || fixp
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
13408 return generic_force_reloc (fixp
);
13412 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
13413 local labels from being added to the output symbol table when they
13414 are used with the ADRL pseudo op. The ADRL relocation should always
13415 be resolved before the binbary is emitted, so it is safe to say that
13416 it is adjustable. */
13419 arm_fix_adjustable (fixS
* fixP
)
13421 if (fixP
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
13428 /* Relocations against Thumb function names must be left unadjusted,
13429 so that the linker can use this information to correctly set the
13430 bottom bit of their addresses. The MIPS version of this function
13431 also prevents relocations that are mips-16 specific, but I do not
13432 know why it does this.
13435 There is one other problem that ought to be addressed here, but
13436 which currently is not: Taking the address of a label (rather
13437 than a function) and then later jumping to that address. Such
13438 addresses also ought to have their bottom bit set (assuming that
13439 they reside in Thumb code), but at the moment they will not. */
13442 arm_fix_adjustable (fixS
* fixP
)
13444 if (fixP
->fx_addsy
== NULL
)
13447 if (THUMB_IS_FUNC (fixP
->fx_addsy
)
13448 && fixP
->fx_subsy
== NULL
)
13451 /* We need the symbol name for the VTABLE entries. */
13452 if ( fixP
->fx_r_type
== BFD_RELOC_VTABLE_INHERIT
13453 || fixP
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
13456 /* Don't allow symbols to be discarded on GOT related relocs. */
13457 if (fixP
->fx_r_type
== BFD_RELOC_ARM_PLT32
13458 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOT32
13459 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOTOFF
13460 || fixP
->fx_r_type
== BFD_RELOC_ARM_TARGET2
)
13467 elf32_arm_target_format (void)
13470 return (target_big_endian
13471 ? "elf32-bigarm-symbian"
13472 : "elf32-littlearm-symbian");
13474 if (target_big_endian
)
13477 return "elf32-bigarm-oabi";
13479 return "elf32-bigarm";
13484 return "elf32-littlearm-oabi";
13486 return "elf32-littlearm";
13492 armelf_frob_symbol (symbolS
* symp
,
13495 elf_frob_symbol (symp
, puntp
);
13499 s_arm_elf_cons (int nbytes
)
13503 #ifdef md_flush_pending_output
13504 md_flush_pending_output ();
13507 if (is_it_end_of_statement ())
13509 demand_empty_rest_of_line ();
13513 #ifdef md_cons_align
13514 md_cons_align (nbytes
);
13517 mapping_state (MAP_DATA
);
13520 bfd_reloc_code_real_type reloc
;
13522 expression (& exp
);
13524 if (exp
.X_op
== O_symbol
13525 && * input_line_pointer
== '('
13526 && (reloc
= arm_parse_reloc ()) != BFD_RELOC_UNUSED
)
13528 reloc_howto_type
*howto
= bfd_reloc_type_lookup (stdoutput
, reloc
);
13529 int size
= bfd_get_reloc_size (howto
);
13532 as_bad ("%s relocations do not fit in %d bytes",
13533 howto
->name
, nbytes
);
13536 char *p
= frag_more ((int) nbytes
);
13537 int offset
= nbytes
- size
;
13539 fix_new_exp (frag_now
, p
- frag_now
->fr_literal
+ offset
, size
,
13544 emit_expr (&exp
, (unsigned int) nbytes
);
13546 while (*input_line_pointer
++ == ',');
13548 /* Put terminator back into stream. */
13549 input_line_pointer
--;
13550 demand_empty_rest_of_line ();
13554 /* Parse a .rel31 directive. */
13557 s_arm_rel31 (int ignored ATTRIBUTE_UNUSED
)
13563 SKIP_WHITESPACE ();
13566 if (*input_line_pointer
== '1')
13567 highbit
= 0x80000000;
13568 else if (*input_line_pointer
!= '0')
13569 as_bad (_("expected 0 or 1"));
13571 input_line_pointer
++;
13572 SKIP_WHITESPACE ();
13573 if (*input_line_pointer
!= ',')
13574 as_bad (_("missing comma"));
13575 input_line_pointer
++;
13577 #ifdef md_flush_pending_output
13578 md_flush_pending_output ();
13581 #ifdef md_cons_align
13585 mapping_state (MAP_DATA
);
13590 md_number_to_chars (p
, highbit
, 4);
13591 fix_new_arm (frag_now
, p
- frag_now
->fr_literal
, 4, &exp
, 1,
13592 BFD_RELOC_ARM_PREL31
);
13594 demand_empty_rest_of_line ();
13597 #endif /* OBJ_ELF */
13599 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
13600 of an rs_align_code fragment. */
13603 arm_handle_align (fragS
* fragP
)
13605 static char const arm_noop
[4] = { 0x00, 0x00, 0xa0, 0xe1 };
13606 static char const thumb_noop
[2] = { 0xc0, 0x46 };
13607 static char const arm_bigend_noop
[4] = { 0xe1, 0xa0, 0x00, 0x00 };
13608 static char const thumb_bigend_noop
[2] = { 0x46, 0xc0 };
13610 int bytes
, fix
, noop_size
;
13614 if (fragP
->fr_type
!= rs_align_code
)
13617 bytes
= fragP
->fr_next
->fr_address
- fragP
->fr_address
- fragP
->fr_fix
;
13618 p
= fragP
->fr_literal
+ fragP
->fr_fix
;
13621 if (bytes
> MAX_MEM_FOR_RS_ALIGN_CODE
)
13622 bytes
&= MAX_MEM_FOR_RS_ALIGN_CODE
;
13624 if (fragP
->tc_frag_data
)
13626 if (target_big_endian
)
13627 noop
= thumb_bigend_noop
;
13630 noop_size
= sizeof (thumb_noop
);
13634 if (target_big_endian
)
13635 noop
= arm_bigend_noop
;
13638 noop_size
= sizeof (arm_noop
);
13641 if (bytes
& (noop_size
- 1))
13643 fix
= bytes
& (noop_size
- 1);
13644 memset (p
, 0, fix
);
13649 while (bytes
>= noop_size
)
13651 memcpy (p
, noop
, noop_size
);
13653 bytes
-= noop_size
;
13657 fragP
->fr_fix
+= fix
;
13658 fragP
->fr_var
= noop_size
;
13661 /* Called from md_do_align. Used to create an alignment
13662 frag in a code section. */
13665 arm_frag_align_code (int n
, int max
)
13669 /* We assume that there will never be a requirement
13670 to support alignments greater than 32 bytes. */
13671 if (max
> MAX_MEM_FOR_RS_ALIGN_CODE
)
13672 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
13674 p
= frag_var (rs_align_code
,
13675 MAX_MEM_FOR_RS_ALIGN_CODE
,
13677 (relax_substateT
) max
,
13684 /* Perform target specific initialisation of a frag. */
13687 arm_init_frag (fragS
* fragP
)
13689 /* Record whether this frag is in an ARM or a THUMB area. */
13690 fragP
->tc_frag_data
= thumb_mode
;
13693 /* This table describes all the machine specific pseudo-ops the assembler
13694 has to support. The fields are:
13695 pseudo-op name without dot
13696 function to call to execute this pseudo-op
13697 Integer arg to pass to the function. */
13699 const pseudo_typeS md_pseudo_table
[] =
13701 /* Never called because '.req' does not start a line. */
13702 { "req", s_req
, 0 },
13703 { "unreq", s_unreq
, 0 },
13704 { "bss", s_bss
, 0 },
13705 { "align", s_align
, 0 },
13706 { "arm", s_arm
, 0 },
13707 { "thumb", s_thumb
, 0 },
13708 { "code", s_code
, 0 },
13709 { "force_thumb", s_force_thumb
, 0 },
13710 { "thumb_func", s_thumb_func
, 0 },
13711 { "thumb_set", s_thumb_set
, 0 },
13712 { "even", s_even
, 0 },
13713 { "ltorg", s_ltorg
, 0 },
13714 { "pool", s_ltorg
, 0 },
13716 { "word", s_arm_elf_cons
, 4 },
13717 { "long", s_arm_elf_cons
, 4 },
13718 { "rel31", s_arm_rel31
, 0 },
13720 { "word", cons
, 4},
13722 { "extend", float_cons
, 'x' },
13723 { "ldouble", float_cons
, 'x' },
13724 { "packed", float_cons
, 'p' },