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 /* Functions called by parser. */
757 /* ARM instructions. */
758 static void do_arit
PARAMS ((char *));
759 static void do_cmp
PARAMS ((char *));
760 static void do_mov
PARAMS ((char *));
761 static void do_ldst
PARAMS ((char *));
762 static void do_ldstt
PARAMS ((char *));
763 static void do_ldmstm
PARAMS ((char *));
764 static void do_branch
PARAMS ((char *));
765 static void do_swi
PARAMS ((char *));
767 /* Pseudo Op codes. */
768 static void do_adr
PARAMS ((char *));
769 static void do_adrl
PARAMS ((char *));
770 static void do_empty
PARAMS ((char *));
773 static void do_mul
PARAMS ((char *));
774 static void do_mla
PARAMS ((char *));
777 static void do_swap
PARAMS ((char *));
780 static void do_msr
PARAMS ((char *));
781 static void do_mrs
PARAMS ((char *));
784 static void do_mull
PARAMS ((char *));
787 static void do_ldstv4
PARAMS ((char *));
790 static void do_bx
PARAMS ((char *));
793 static void do_blx
PARAMS ((char *));
794 static void do_bkpt
PARAMS ((char *));
795 static void do_clz
PARAMS ((char *));
796 static void do_lstc2
PARAMS ((char *));
797 static void do_cdp2
PARAMS ((char *));
798 static void do_co_reg2
PARAMS ((char *));
801 static void do_smla
PARAMS ((char *));
802 static void do_smlal
PARAMS ((char *));
803 static void do_smul
PARAMS ((char *));
804 static void do_qadd
PARAMS ((char *));
807 static void do_pld
PARAMS ((char *));
808 static void do_ldrd
PARAMS ((char *));
809 static void do_co_reg2c
PARAMS ((char *));
812 static void do_bxj
PARAMS ((char *));
815 static void do_cps
PARAMS ((char *));
816 static void do_cpsi
PARAMS ((char *));
817 static void do_ldrex
PARAMS ((char *));
818 static void do_pkhbt
PARAMS ((char *));
819 static void do_pkhtb
PARAMS ((char *));
820 static void do_qadd16
PARAMS ((char *));
821 static void do_rev
PARAMS ((char *));
822 static void do_rfe
PARAMS ((char *));
823 static void do_sxtah
PARAMS ((char *));
824 static void do_sxth
PARAMS ((char *));
825 static void do_setend
PARAMS ((char *));
826 static void do_smlad
PARAMS ((char *));
827 static void do_smlald
PARAMS ((char *));
828 static void do_smmul
PARAMS ((char *));
829 static void do_ssat
PARAMS ((char *));
830 static void do_usat
PARAMS ((char *));
831 static void do_srs
PARAMS ((char *));
832 static void do_ssat16
PARAMS ((char *));
833 static void do_usat16
PARAMS ((char *));
834 static void do_strex
PARAMS ((char *));
835 static void do_umaal
PARAMS ((char *));
837 static void do_cps_mode
PARAMS ((char **));
838 static void do_cps_flags
PARAMS ((char **, int));
839 static int do_endian_specifier
PARAMS ((char *));
840 static void do_pkh_core
PARAMS ((char *, int));
841 static void do_sat
PARAMS ((char **, int));
842 static void do_sat16
PARAMS ((char **, int));
844 /* Coprocessor Instructions. */
845 static void do_cdp
PARAMS ((char *));
846 static void do_lstc
PARAMS ((char *));
847 static void do_co_reg
PARAMS ((char *));
849 /* FPA instructions. */
850 static void do_fpa_ctrl
PARAMS ((char *));
851 static void do_fpa_ldst
PARAMS ((char *));
852 static void do_fpa_ldmstm
PARAMS ((char *));
853 static void do_fpa_dyadic
PARAMS ((char *));
854 static void do_fpa_monadic
PARAMS ((char *));
855 static void do_fpa_cmp
PARAMS ((char *));
856 static void do_fpa_from_reg
PARAMS ((char *));
857 static void do_fpa_to_reg
PARAMS ((char *));
859 /* VFP instructions. */
860 static void do_vfp_sp_monadic
PARAMS ((char *));
861 static void do_vfp_dp_monadic
PARAMS ((char *));
862 static void do_vfp_sp_dyadic
PARAMS ((char *));
863 static void do_vfp_dp_dyadic
PARAMS ((char *));
864 static void do_vfp_reg_from_sp
PARAMS ((char *));
865 static void do_vfp_sp_from_reg
PARAMS ((char *));
866 static void do_vfp_reg2_from_sp2
PARAMS ((char *));
867 static void do_vfp_sp2_from_reg2
PARAMS ((char *));
868 static void do_vfp_reg_from_dp
PARAMS ((char *));
869 static void do_vfp_reg2_from_dp
PARAMS ((char *));
870 static void do_vfp_dp_from_reg
PARAMS ((char *));
871 static void do_vfp_dp_from_reg2
PARAMS ((char *));
872 static void do_vfp_reg_from_ctrl
PARAMS ((char *));
873 static void do_vfp_ctrl_from_reg
PARAMS ((char *));
874 static void do_vfp_sp_ldst
PARAMS ((char *));
875 static void do_vfp_dp_ldst
PARAMS ((char *));
876 static void do_vfp_sp_ldstmia
PARAMS ((char *));
877 static void do_vfp_sp_ldstmdb
PARAMS ((char *));
878 static void do_vfp_dp_ldstmia
PARAMS ((char *));
879 static void do_vfp_dp_ldstmdb
PARAMS ((char *));
880 static void do_vfp_xp_ldstmia
PARAMS ((char *));
881 static void do_vfp_xp_ldstmdb
PARAMS ((char *));
882 static void do_vfp_sp_compare_z
PARAMS ((char *));
883 static void do_vfp_dp_compare_z
PARAMS ((char *));
884 static void do_vfp_dp_sp_cvt
PARAMS ((char *));
885 static void do_vfp_sp_dp_cvt
PARAMS ((char *));
888 static void do_xsc_mia
PARAMS ((char *));
889 static void do_xsc_mar
PARAMS ((char *));
890 static void do_xsc_mra
PARAMS ((char *));
893 static void do_mav_binops
PARAMS ((char *, int, enum arm_reg_type
,
895 static void do_mav_binops_1a
PARAMS ((char *));
896 static void do_mav_binops_1b
PARAMS ((char *));
897 static void do_mav_binops_1c
PARAMS ((char *));
898 static void do_mav_binops_1d
PARAMS ((char *));
899 static void do_mav_binops_1e
PARAMS ((char *));
900 static void do_mav_binops_1f
PARAMS ((char *));
901 static void do_mav_binops_1g
PARAMS ((char *));
902 static void do_mav_binops_1h
PARAMS ((char *));
903 static void do_mav_binops_1i
PARAMS ((char *));
904 static void do_mav_binops_1j
PARAMS ((char *));
905 static void do_mav_binops_1k
PARAMS ((char *));
906 static void do_mav_binops_1l
PARAMS ((char *));
907 static void do_mav_binops_1m
PARAMS ((char *));
908 static void do_mav_binops_1n
PARAMS ((char *));
909 static void do_mav_binops_1o
PARAMS ((char *));
910 static void do_mav_binops_2a
PARAMS ((char *));
911 static void do_mav_binops_2b
PARAMS ((char *));
912 static void do_mav_binops_2c
PARAMS ((char *));
913 static void do_mav_binops_3a
PARAMS ((char *));
914 static void do_mav_binops_3b
PARAMS ((char *));
915 static void do_mav_binops_3c
PARAMS ((char *));
916 static void do_mav_binops_3d
PARAMS ((char *));
917 static void do_mav_triple
PARAMS ((char *, int, enum arm_reg_type
,
920 static void do_mav_triple_4a
PARAMS ((char *));
921 static void do_mav_triple_4b
PARAMS ((char *));
922 static void do_mav_triple_5a
PARAMS ((char *));
923 static void do_mav_triple_5b
PARAMS ((char *));
924 static void do_mav_triple_5c
PARAMS ((char *));
925 static void do_mav_triple_5d
PARAMS ((char *));
926 static void do_mav_triple_5e
PARAMS ((char *));
927 static void do_mav_triple_5f
PARAMS ((char *));
928 static void do_mav_triple_5g
PARAMS ((char *));
929 static void do_mav_triple_5h
PARAMS ((char *));
930 static void do_mav_quad
PARAMS ((char *, int, enum arm_reg_type
,
934 static void do_mav_quad_6a
PARAMS ((char *));
935 static void do_mav_quad_6b
PARAMS ((char *));
936 static void do_mav_dspsc_1
PARAMS ((char *));
937 static void do_mav_dspsc_2
PARAMS ((char *));
938 static void do_mav_shift
PARAMS ((char *, enum arm_reg_type
,
940 static void do_mav_shift_1
PARAMS ((char *));
941 static void do_mav_shift_2
PARAMS ((char *));
942 static void do_mav_ldst
PARAMS ((char *, enum arm_reg_type
));
943 static void do_mav_ldst_1
PARAMS ((char *));
944 static void do_mav_ldst_2
PARAMS ((char *));
945 static void do_mav_ldst_3
PARAMS ((char *));
946 static void do_mav_ldst_4
PARAMS ((char *));
948 static int mav_reg_required_here
PARAMS ((char **, int,
950 static int mav_parse_offset
PARAMS ((char **, int *));
952 static void fix_new_arm
PARAMS ((fragS
*, int, short, expressionS
*,
954 static int arm_reg_parse
PARAMS ((char **, struct hash_control
*));
955 static enum arm_reg_type arm_reg_parse_any
PARAMS ((char *));
956 static const struct asm_psr
* arm_psr_parse
PARAMS ((char **));
957 static void symbol_locate
PARAMS ((symbolS
*, const char *, segT
, valueT
,
959 static int add_to_lit_pool
PARAMS ((void));
960 static unsigned validate_immediate
PARAMS ((unsigned));
961 static unsigned validate_immediate_twopart
PARAMS ((unsigned int,
963 static int validate_offset_imm
PARAMS ((unsigned int, int));
964 static void opcode_select
PARAMS ((int));
965 static void end_of_line
PARAMS ((char *));
966 static int reg_required_here
PARAMS ((char **, int));
967 static int psr_required_here
PARAMS ((char **));
968 static int co_proc_number
PARAMS ((char **));
969 static int cp_opc_expr
PARAMS ((char **, int, int));
970 static int cp_reg_required_here
PARAMS ((char **, int));
971 static int fp_reg_required_here
PARAMS ((char **, int));
972 static int vfp_sp_reg_required_here
PARAMS ((char **, enum vfp_sp_reg_pos
));
973 static int vfp_dp_reg_required_here
PARAMS ((char **, enum vfp_dp_reg_pos
));
974 static void vfp_sp_ldstm
PARAMS ((char *, enum vfp_ldstm_type
));
975 static void vfp_dp_ldstm
PARAMS ((char *, enum vfp_ldstm_type
));
976 static long vfp_sp_reg_list
PARAMS ((char **, enum vfp_sp_reg_pos
));
977 static long vfp_dp_reg_list
PARAMS ((char **));
978 static int vfp_psr_required_here
PARAMS ((char **str
));
979 static const struct vfp_reg
*vfp_psr_parse
PARAMS ((char **str
));
980 static int cp_address_offset
PARAMS ((char **));
981 static int cp_address_required_here
PARAMS ((char **, int));
982 static int my_get_float_expression
PARAMS ((char **));
983 static int skip_past_comma
PARAMS ((char **));
984 static int walk_no_bignums
PARAMS ((symbolS
*));
985 static int negate_data_op
PARAMS ((unsigned long *, unsigned long));
986 static int data_op2
PARAMS ((char **));
987 static int fp_op2
PARAMS ((char **));
988 static long reg_list
PARAMS ((char **));
989 static void thumb_load_store
PARAMS ((char *, int, int));
990 static int decode_shift
PARAMS ((char **, int));
991 static int ldst_extend
PARAMS ((char **));
992 static int ldst_extend_v4
PARAMS ((char **));
993 static void thumb_add_sub
PARAMS ((char *, int));
994 static void insert_reg
PARAMS ((const struct reg_entry
*,
995 struct hash_control
*));
996 static void thumb_shift
PARAMS ((char *, int));
997 static void thumb_mov_compare
PARAMS ((char *, int));
998 static void build_arm_ops_hsh
PARAMS ((void));
999 static void set_constant_flonums
PARAMS ((void));
1000 static valueT md_chars_to_number
PARAMS ((char *, int));
1001 static void build_reg_hsh
PARAMS ((struct reg_map
*));
1002 static void insert_reg_alias
PARAMS ((char *, int, struct hash_control
*));
1003 static int create_register_alias
PARAMS ((char *, char *));
1004 static void output_inst
PARAMS ((const char *));
1005 static int accum0_required_here
PARAMS ((char **));
1006 static int ld_mode_required_here
PARAMS ((char **));
1007 static void do_branch25
PARAMS ((char *));
1008 static symbolS
* find_real_start
PARAMS ((symbolS
*));
1010 static bfd_reloc_code_real_type arm_parse_reloc
PARAMS ((void));
1013 static int wreg_required_here
PARAMS ((char **, int, enum wreg_type
));
1014 static void do_iwmmxt_byte_addr
PARAMS ((char *));
1015 static void do_iwmmxt_tandc
PARAMS ((char *));
1016 static void do_iwmmxt_tbcst
PARAMS ((char *));
1017 static void do_iwmmxt_textrc
PARAMS ((char *));
1018 static void do_iwmmxt_textrm
PARAMS ((char *));
1019 static void do_iwmmxt_tinsr
PARAMS ((char *));
1020 static void do_iwmmxt_tmcr
PARAMS ((char *));
1021 static void do_iwmmxt_tmcrr
PARAMS ((char *));
1022 static void do_iwmmxt_tmia
PARAMS ((char *));
1023 static void do_iwmmxt_tmovmsk
PARAMS ((char *));
1024 static void do_iwmmxt_tmrc
PARAMS ((char *));
1025 static void do_iwmmxt_tmrrc
PARAMS ((char *));
1026 static void do_iwmmxt_torc
PARAMS ((char *));
1027 static void do_iwmmxt_waligni
PARAMS ((char *));
1028 static void do_iwmmxt_wmov
PARAMS ((char *));
1029 static void do_iwmmxt_word_addr
PARAMS ((char *));
1030 static void do_iwmmxt_wrwr
PARAMS ((char *));
1031 static void do_iwmmxt_wrwrwcg
PARAMS ((char *));
1032 static void do_iwmmxt_wrwrwr
PARAMS ((char *));
1033 static void do_iwmmxt_wshufh
PARAMS ((char *));
1034 static void do_iwmmxt_wzero
PARAMS ((char *));
1035 static int cp_byte_address_offset
PARAMS ((char **));
1036 static int cp_byte_address_required_here
PARAMS ((char **));
1038 /* ARM instructions take 4bytes in the object file, Thumb instructions
1042 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
1043 #define MAV_MODE1 0x100c
1045 /* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
1046 #define MAV_MODE2 0x0c10
1048 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
1049 #define MAV_MODE3 0x100c
1051 /* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
1052 #define MAV_MODE4 0x0c0010
1054 /* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
1055 #define MAV_MODE5 0x00100c
1057 /* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
1058 #define MAV_MODE6 0x00100c05
1062 /* Basic string to match. */
1063 const char * template;
1065 /* Basic instruction code. */
1066 unsigned long value
;
1068 /* Offset into the template where the condition code (if any) will be.
1069 If zero, then the instruction is never conditional. */
1070 unsigned cond_offset
;
1072 /* Which architecture variant provides this instruction. */
1073 unsigned long variant
;
1075 /* Function to call to parse args. */
1076 void (* parms
) PARAMS ((char *));
1079 static const struct asm_opcode insns
[] =
1081 /* Core ARM Instructions. */
1082 {"and", 0xe0000000, 3, ARM_EXT_V1
, do_arit
},
1083 {"ands", 0xe0100000, 3, ARM_EXT_V1
, do_arit
},
1084 {"eor", 0xe0200000, 3, ARM_EXT_V1
, do_arit
},
1085 {"eors", 0xe0300000, 3, ARM_EXT_V1
, do_arit
},
1086 {"sub", 0xe0400000, 3, ARM_EXT_V1
, do_arit
},
1087 {"subs", 0xe0500000, 3, ARM_EXT_V1
, do_arit
},
1088 {"rsb", 0xe0600000, 3, ARM_EXT_V1
, do_arit
},
1089 {"rsbs", 0xe0700000, 3, ARM_EXT_V1
, do_arit
},
1090 {"add", 0xe0800000, 3, ARM_EXT_V1
, do_arit
},
1091 {"adds", 0xe0900000, 3, ARM_EXT_V1
, do_arit
},
1092 {"adc", 0xe0a00000, 3, ARM_EXT_V1
, do_arit
},
1093 {"adcs", 0xe0b00000, 3, ARM_EXT_V1
, do_arit
},
1094 {"sbc", 0xe0c00000, 3, ARM_EXT_V1
, do_arit
},
1095 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1
, do_arit
},
1096 {"rsc", 0xe0e00000, 3, ARM_EXT_V1
, do_arit
},
1097 {"rscs", 0xe0f00000, 3, ARM_EXT_V1
, do_arit
},
1098 {"orr", 0xe1800000, 3, ARM_EXT_V1
, do_arit
},
1099 {"orrs", 0xe1900000, 3, ARM_EXT_V1
, do_arit
},
1100 {"bic", 0xe1c00000, 3, ARM_EXT_V1
, do_arit
},
1101 {"bics", 0xe1d00000, 3, ARM_EXT_V1
, do_arit
},
1103 {"tst", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
1104 {"tsts", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
1105 {"tstp", 0xe110f000, 3, ARM_EXT_V1
, do_cmp
},
1106 {"teq", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
1107 {"teqs", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
1108 {"teqp", 0xe130f000, 3, ARM_EXT_V1
, do_cmp
},
1109 {"cmp", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
1110 {"cmps", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
1111 {"cmpp", 0xe150f000, 3, ARM_EXT_V1
, do_cmp
},
1112 {"cmn", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
1113 {"cmns", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
1114 {"cmnp", 0xe170f000, 3, ARM_EXT_V1
, do_cmp
},
1116 {"mov", 0xe1a00000, 3, ARM_EXT_V1
, do_mov
},
1117 {"movs", 0xe1b00000, 3, ARM_EXT_V1
, do_mov
},
1118 {"mvn", 0xe1e00000, 3, ARM_EXT_V1
, do_mov
},
1119 {"mvns", 0xe1f00000, 3, ARM_EXT_V1
, do_mov
},
1121 {"ldr", 0xe4100000, 3, ARM_EXT_V1
, do_ldst
},
1122 {"ldrb", 0xe4500000, 3, ARM_EXT_V1
, do_ldst
},
1123 {"ldrt", 0xe4300000, 3, ARM_EXT_V1
, do_ldstt
},
1124 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1
, do_ldstt
},
1125 {"str", 0xe4000000, 3, ARM_EXT_V1
, do_ldst
},
1126 {"strb", 0xe4400000, 3, ARM_EXT_V1
, do_ldst
},
1127 {"strt", 0xe4200000, 3, ARM_EXT_V1
, do_ldstt
},
1128 {"strbt", 0xe4600000, 3, ARM_EXT_V1
, do_ldstt
},
1130 {"stmia", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
1131 {"stmib", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
1132 {"stmda", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
1133 {"stmdb", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
1134 {"stmfd", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
1135 {"stmfa", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
1136 {"stmea", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
1137 {"stmed", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
1139 {"ldmia", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
1140 {"ldmib", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
1141 {"ldmda", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
1142 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
1143 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
1144 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
1145 {"ldmea", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
1146 {"ldmed", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
1148 {"swi", 0xef000000, 3, ARM_EXT_V1
, do_swi
},
1150 /* XXX This is the wrong place to do this. Think multi-arch. */
1151 {"bl", 0xeb000000, 2, ARM_EXT_V1
, do_branch
},
1152 {"b", 0xea000000, 1, ARM_EXT_V1
, do_branch
},
1154 {"bl", 0xebfffffe, 2, ARM_EXT_V1
, do_branch
},
1155 {"b", 0xeafffffe, 1, ARM_EXT_V1
, do_branch
},
1159 {"adr", 0xe28f0000, 3, ARM_EXT_V1
, do_adr
},
1160 {"adrl", 0xe28f0000, 3, ARM_EXT_V1
, do_adrl
},
1161 {"nop", 0xe1a00000, 3, ARM_EXT_V1
, do_empty
},
1163 /* ARM 2 multiplies. */
1164 {"mul", 0xe0000090, 3, ARM_EXT_V2
, do_mul
},
1165 {"muls", 0xe0100090, 3, ARM_EXT_V2
, do_mul
},
1166 {"mla", 0xe0200090, 3, ARM_EXT_V2
, do_mla
},
1167 {"mlas", 0xe0300090, 3, ARM_EXT_V2
, do_mla
},
1169 /* Generic coprocessor instructions. */
1170 {"cdp", 0xee000000, 3, ARM_EXT_V2
, do_cdp
},
1171 {"ldc", 0xec100000, 3, ARM_EXT_V2
, do_lstc
},
1172 {"ldcl", 0xec500000, 3, ARM_EXT_V2
, do_lstc
},
1173 {"stc", 0xec000000, 3, ARM_EXT_V2
, do_lstc
},
1174 {"stcl", 0xec400000, 3, ARM_EXT_V2
, do_lstc
},
1175 {"mcr", 0xee000010, 3, ARM_EXT_V2
, do_co_reg
},
1176 {"mrc", 0xee100010, 3, ARM_EXT_V2
, do_co_reg
},
1178 /* ARM 3 - swp instructions. */
1179 {"swp", 0xe1000090, 3, ARM_EXT_V2S
, do_swap
},
1180 {"swpb", 0xe1400090, 3, ARM_EXT_V2S
, do_swap
},
1182 /* ARM 6 Status register instructions. */
1183 {"mrs", 0xe10f0000, 3, ARM_EXT_V3
, do_mrs
},
1184 {"msr", 0xe120f000, 3, ARM_EXT_V3
, do_msr
},
1185 /* ScottB: our code uses 0xe128f000 for msr.
1186 NickC: but this is wrong because the bits 16 through 19 are
1187 handled by the PSR_xxx defines above. */
1189 /* ARM 7M long multiplies. */
1190 {"smull", 0xe0c00090, 5, ARM_EXT_V3M
, do_mull
},
1191 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M
, do_mull
},
1192 {"umull", 0xe0800090, 5, ARM_EXT_V3M
, do_mull
},
1193 {"umulls", 0xe0900090, 5, ARM_EXT_V3M
, do_mull
},
1194 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M
, do_mull
},
1195 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M
, do_mull
},
1196 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M
, do_mull
},
1197 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M
, do_mull
},
1199 /* ARM Architecture 4. */
1200 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4
, do_ldstv4
},
1201 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4
, do_ldstv4
},
1202 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4
, do_ldstv4
},
1203 {"strh", 0xe00000b0, 3, ARM_EXT_V4
, do_ldstv4
},
1205 /* ARM Architecture 4T. */
1206 /* Note: bx (and blx) are required on V5, even if the processor does
1207 not support Thumb. */
1208 {"bx", 0xe12fff10, 2, ARM_EXT_V4T
| ARM_EXT_V5
, do_bx
},
1210 /* ARM Architecture 5T. */
1211 /* Note: blx has 2 variants, so the .value is set dynamically.
1212 Only one of the variants has conditional execution. */
1213 {"blx", 0xe0000000, 3, ARM_EXT_V5
, do_blx
},
1214 {"clz", 0xe16f0f10, 3, ARM_EXT_V5
, do_clz
},
1215 {"bkpt", 0xe1200070, 0, ARM_EXT_V5
, do_bkpt
},
1216 {"ldc2", 0xfc100000, 0, ARM_EXT_V5
, do_lstc2
},
1217 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5
, do_lstc2
},
1218 {"stc2", 0xfc000000, 0, ARM_EXT_V5
, do_lstc2
},
1219 {"stc2l", 0xfc400000, 0, ARM_EXT_V5
, do_lstc2
},
1220 {"cdp2", 0xfe000000, 0, ARM_EXT_V5
, do_cdp2
},
1221 {"mcr2", 0xfe000010, 0, ARM_EXT_V5
, do_co_reg2
},
1222 {"mrc2", 0xfe100010, 0, ARM_EXT_V5
, do_co_reg2
},
1224 /* ARM Architecture 5TExP. */
1225 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP
, do_smla
},
1226 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP
, do_smla
},
1227 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP
, do_smla
},
1228 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP
, do_smla
},
1230 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP
, do_smla
},
1231 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP
, do_smla
},
1233 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP
, do_smlal
},
1234 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP
, do_smlal
},
1235 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP
, do_smlal
},
1236 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP
, do_smlal
},
1238 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP
, do_smul
},
1239 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP
, do_smul
},
1240 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP
, do_smul
},
1241 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP
, do_smul
},
1243 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP
, do_smul
},
1244 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP
, do_smul
},
1246 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP
, do_qadd
},
1247 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP
, do_qadd
},
1248 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP
, do_qadd
},
1249 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP
, do_qadd
},
1251 /* ARM Architecture 5TE. */
1252 {"pld", 0xf450f000, 0, ARM_EXT_V5E
, do_pld
},
1253 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E
, do_ldrd
},
1254 {"strd", 0xe00000f0, 3, ARM_EXT_V5E
, do_ldrd
},
1256 {"mcrr", 0xec400000, 4, ARM_EXT_V5E
, do_co_reg2c
},
1257 {"mrrc", 0xec500000, 4, ARM_EXT_V5E
, do_co_reg2c
},
1259 /* ARM Architecture 5TEJ. */
1260 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J
, do_bxj
},
1263 { "cps", 0xf1020000, 0, ARM_EXT_V6
, do_cps
},
1264 { "cpsie", 0xf1080000, 0, ARM_EXT_V6
, do_cpsi
},
1265 { "cpsid", 0xf10C0000, 0, ARM_EXT_V6
, do_cpsi
},
1266 { "ldrex", 0xe1900f9f, 5, ARM_EXT_V6
, do_ldrex
},
1267 { "mcrr2", 0xfc400000, 0, ARM_EXT_V6
, do_co_reg2c
},
1268 { "mrrc2", 0xfc500000, 0, ARM_EXT_V6
, do_co_reg2c
},
1269 { "pkhbt", 0xe6800010, 5, ARM_EXT_V6
, do_pkhbt
},
1270 { "pkhtb", 0xe6800050, 5, ARM_EXT_V6
, do_pkhtb
},
1271 { "qadd16", 0xe6200f10, 6, ARM_EXT_V6
, do_qadd16
},
1272 { "qadd8", 0xe6200f90, 5, ARM_EXT_V6
, do_qadd16
},
1273 { "qaddsubx", 0xe6200f30, 8, ARM_EXT_V6
, do_qadd16
},
1274 { "qsub16", 0xe6200f70, 6, ARM_EXT_V6
, do_qadd16
},
1275 { "qsub8", 0xe6200ff0, 5, ARM_EXT_V6
, do_qadd16
},
1276 { "qsubaddx", 0xe6200f50, 8, ARM_EXT_V6
, do_qadd16
},
1277 { "sadd16", 0xe6100f10, 6, ARM_EXT_V6
, do_qadd16
},
1278 { "sadd8", 0xe6100f90, 5, ARM_EXT_V6
, do_qadd16
},
1279 { "saddsubx", 0xe6100f30, 8, ARM_EXT_V6
, do_qadd16
},
1280 { "shadd16", 0xe6300f10, 7, ARM_EXT_V6
, do_qadd16
},
1281 { "shadd8", 0xe6300f90, 6, ARM_EXT_V6
, do_qadd16
},
1282 { "shaddsubx", 0xe6300f30, 9, ARM_EXT_V6
, do_qadd16
},
1283 { "shsub16", 0xe6300f70, 7, ARM_EXT_V6
, do_qadd16
},
1284 { "shsub8", 0xe6300ff0, 6, ARM_EXT_V6
, do_qadd16
},
1285 { "shsubaddx", 0xe6300f50, 9, ARM_EXT_V6
, do_qadd16
},
1286 { "ssub16", 0xe6100f70, 6, ARM_EXT_V6
, do_qadd16
},
1287 { "ssub8", 0xe6100ff0, 5, ARM_EXT_V6
, do_qadd16
},
1288 { "ssubaddx", 0xe6100f50, 8, ARM_EXT_V6
, do_qadd16
},
1289 { "uadd16", 0xe6500f10, 6, ARM_EXT_V6
, do_qadd16
},
1290 { "uadd8", 0xe6500f90, 5, ARM_EXT_V6
, do_qadd16
},
1291 { "uaddsubx", 0xe6500f30, 8, ARM_EXT_V6
, do_qadd16
},
1292 { "uhadd16", 0xe6700f10, 7, ARM_EXT_V6
, do_qadd16
},
1293 { "uhadd8", 0xe6700f90, 6, ARM_EXT_V6
, do_qadd16
},
1294 { "uhaddsubx", 0xe6700f30, 9, ARM_EXT_V6
, do_qadd16
},
1295 { "uhsub16", 0xe6700f70, 7, ARM_EXT_V6
, do_qadd16
},
1296 { "uhsub8", 0xe6700ff0, 6, ARM_EXT_V6
, do_qadd16
},
1297 { "uhsubaddx", 0xe6700f50, 9, ARM_EXT_V6
, do_qadd16
},
1298 { "uqadd16", 0xe6600f10, 7, ARM_EXT_V6
, do_qadd16
},
1299 { "uqadd8", 0xe6600f90, 6, ARM_EXT_V6
, do_qadd16
},
1300 { "uqaddsubx", 0xe6600f30, 9, ARM_EXT_V6
, do_qadd16
},
1301 { "uqsub16", 0xe6600f70, 7, ARM_EXT_V6
, do_qadd16
},
1302 { "uqsub8", 0xe6600ff0, 6, ARM_EXT_V6
, do_qadd16
},
1303 { "uqsubaddx", 0xe6600f50, 9, ARM_EXT_V6
, do_qadd16
},
1304 { "usub16", 0xe6500f70, 6, ARM_EXT_V6
, do_qadd16
},
1305 { "usub8", 0xe6500ff0, 5, ARM_EXT_V6
, do_qadd16
},
1306 { "usubaddx", 0xe6500f50, 8, ARM_EXT_V6
, do_qadd16
},
1307 { "rev", 0xe6bf0f30, 3, ARM_EXT_V6
, do_rev
},
1308 { "rev16", 0xe6bf0fb0, 5, ARM_EXT_V6
, do_rev
},
1309 { "revsh", 0xe6ff0fb0, 5, ARM_EXT_V6
, do_rev
},
1310 { "rfeia", 0xf8900a00, 0, ARM_EXT_V6
, do_rfe
},
1311 { "rfeib", 0xf9900a00, 0, ARM_EXT_V6
, do_rfe
},
1312 { "rfeda", 0xf8100a00, 0, ARM_EXT_V6
, do_rfe
},
1313 { "rfedb", 0xf9100a00, 0, ARM_EXT_V6
, do_rfe
},
1314 { "rfefd", 0xf8900a00, 0, ARM_EXT_V6
, do_rfe
},
1315 { "rfefa", 0xf9900a00, 0, ARM_EXT_V6
, do_rfe
},
1316 { "rfeea", 0xf8100a00, 0, ARM_EXT_V6
, do_rfe
},
1317 { "rfeed", 0xf9100a00, 0, ARM_EXT_V6
, do_rfe
},
1318 { "sxtah", 0xe6b00070, 5, ARM_EXT_V6
, do_sxtah
},
1319 { "sxtab16", 0xe6800070, 7, ARM_EXT_V6
, do_sxtah
},
1320 { "sxtab", 0xe6a00070, 5, ARM_EXT_V6
, do_sxtah
},
1321 { "sxth", 0xe6bf0070, 4, ARM_EXT_V6
, do_sxth
},
1322 { "sxtb16", 0xe68f0070, 6, ARM_EXT_V6
, do_sxth
},
1323 { "sxtb", 0xe6af0070, 4, ARM_EXT_V6
, do_sxth
},
1324 { "uxtah", 0xe6f00070, 5, ARM_EXT_V6
, do_sxtah
},
1325 { "uxtab16", 0xe6c00070, 7, ARM_EXT_V6
, do_sxtah
},
1326 { "uxtab", 0xe6e00070, 5, ARM_EXT_V6
, do_sxtah
},
1327 { "uxth", 0xe6ff0070, 4, ARM_EXT_V6
, do_sxth
},
1328 { "uxtb16", 0xe6cf0070, 6, ARM_EXT_V6
, do_sxth
},
1329 { "uxtb", 0xe6ef0070, 4, ARM_EXT_V6
, do_sxth
},
1330 { "sel", 0xe68000b0, 3, ARM_EXT_V6
, do_qadd16
},
1331 { "setend", 0xf1010000, 0, ARM_EXT_V6
, do_setend
},
1332 { "smlad", 0xe7000010, 5, ARM_EXT_V6
, do_smlad
},
1333 { "smladx", 0xe7000030, 6, ARM_EXT_V6
, do_smlad
},
1334 { "smlald", 0xe7400010, 6, ARM_EXT_V6
, do_smlald
},
1335 { "smlaldx", 0xe7400030, 7, ARM_EXT_V6
, do_smlald
},
1336 { "smlsd", 0xe7000050, 5, ARM_EXT_V6
, do_smlad
},
1337 { "smlsdx", 0xe7000070, 6, ARM_EXT_V6
, do_smlad
},
1338 { "smlsld", 0xe7400050, 6, ARM_EXT_V6
, do_smlald
},
1339 { "smlsldx", 0xe7400070, 7, ARM_EXT_V6
, do_smlald
},
1340 { "smmla", 0xe7500010, 5, ARM_EXT_V6
, do_smlad
},
1341 { "smmlar", 0xe7500030, 6, ARM_EXT_V6
, do_smlad
},
1342 { "smmls", 0xe75000d0, 5, ARM_EXT_V6
, do_smlad
},
1343 { "smmlsr", 0xe75000f0, 6, ARM_EXT_V6
, do_smlad
},
1344 { "smmul", 0xe750f010, 5, ARM_EXT_V6
, do_smmul
},
1345 { "smmulr", 0xe750f030, 6, ARM_EXT_V6
, do_smmul
},
1346 { "smuad", 0xe700f010, 5, ARM_EXT_V6
, do_smmul
},
1347 { "smuadx", 0xe700f030, 6, ARM_EXT_V6
, do_smmul
},
1348 { "smusd", 0xe700f050, 5, ARM_EXT_V6
, do_smmul
},
1349 { "smusdx", 0xe700f070, 6, ARM_EXT_V6
, do_smmul
},
1350 { "srsia", 0xf8cd0500, 0, ARM_EXT_V6
, do_srs
},
1351 { "srsib", 0xf9cd0500, 0, ARM_EXT_V6
, do_srs
},
1352 { "srsda", 0xf84d0500, 0, ARM_EXT_V6
, do_srs
},
1353 { "srsdb", 0xf94d0500, 0, ARM_EXT_V6
, do_srs
},
1354 { "ssat", 0xe6a00010, 4, ARM_EXT_V6
, do_ssat
},
1355 { "ssat16", 0xe6a00f30, 6, ARM_EXT_V6
, do_ssat16
},
1356 { "strex", 0xe1800f90, 5, ARM_EXT_V6
, do_strex
},
1357 { "umaal", 0xe0400090, 5, ARM_EXT_V6
, do_umaal
},
1358 { "usad8", 0xe780f010, 5, ARM_EXT_V6
, do_smmul
},
1359 { "usada8", 0xe7800010, 6, ARM_EXT_V6
, do_smlad
},
1360 { "usat", 0xe6e00010, 4, ARM_EXT_V6
, do_usat
},
1361 { "usat16", 0xe6e00f30, 6, ARM_EXT_V6
, do_usat16
},
1363 /* Core FPA instruction set (V1). */
1364 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1365 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1366 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1367 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1369 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1370 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1371 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1372 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1374 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1375 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1376 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1377 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1379 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1380 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1381 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1382 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1383 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1384 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1385 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1386 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1387 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1388 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1389 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1390 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1392 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1393 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1394 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1395 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1396 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1397 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1398 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1399 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1400 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1401 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1402 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1403 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1405 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1406 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1407 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1408 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1409 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1410 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1411 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1412 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1413 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1414 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1415 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1416 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1418 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1419 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1420 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1421 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1422 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1423 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1424 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1425 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1426 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1427 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1428 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1429 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1431 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1432 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1433 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1434 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1435 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1436 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1437 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1438 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1439 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1440 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1441 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1442 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1444 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1445 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1446 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1447 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1448 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1449 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1450 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1451 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1452 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1453 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1454 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1455 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1457 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1458 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1459 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1460 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1461 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1462 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1463 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1464 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1465 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1466 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1467 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1468 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1470 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1471 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1472 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1473 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1474 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1475 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1476 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1477 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1478 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1479 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1480 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1481 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1483 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1484 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1485 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1486 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1487 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1488 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1489 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1490 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1491 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1492 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1493 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1494 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1496 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1497 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1498 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1499 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1500 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1501 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1502 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1503 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1504 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1505 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1506 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1507 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1509 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1510 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1511 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1512 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1513 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1514 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1515 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1516 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1517 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1518 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1519 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1520 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1522 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1523 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1524 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1525 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1526 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1527 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1528 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1529 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1530 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1531 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1532 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1533 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1535 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1536 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1537 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1538 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1539 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1540 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1541 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1542 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1543 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1544 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1545 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1546 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1548 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1549 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1550 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1551 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1552 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1553 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1554 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1555 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1556 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1557 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1558 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1559 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1561 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1562 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1563 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1564 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1565 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1566 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1567 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1568 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1569 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1570 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1571 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1572 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1574 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1575 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1576 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1577 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1578 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1579 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1580 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1581 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1582 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1583 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1584 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1585 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1587 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1588 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1589 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1590 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1591 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1592 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1593 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1594 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1595 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1596 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1597 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1598 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1600 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1601 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1602 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1603 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1604 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1605 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1606 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1607 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1608 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1609 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1610 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1611 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1613 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1614 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1615 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1616 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1617 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1618 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1619 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1620 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1621 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1622 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1623 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1624 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1626 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1627 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1628 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1629 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1630 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1631 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1632 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1633 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1634 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1635 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1636 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1637 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1639 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1640 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1641 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1642 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1643 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1644 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1645 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1646 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1647 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1648 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1649 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1650 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1652 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1653 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1654 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1655 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1656 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1657 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1658 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1659 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1660 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1661 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1662 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1663 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1665 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1666 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1667 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1668 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1669 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1670 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1671 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1672 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1673 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1674 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1675 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1676 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1678 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1679 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1680 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1681 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1682 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1683 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1684 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1685 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1686 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1687 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1688 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1689 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1691 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1692 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1693 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1694 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1695 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1696 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1697 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1698 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1699 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1700 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1701 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1702 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1704 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1705 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1706 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1707 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1708 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1709 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1710 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1711 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1712 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1713 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1714 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1715 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1717 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1718 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1719 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1720 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1721 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1722 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1723 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1724 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1725 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1726 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1727 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1728 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1730 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1731 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1732 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1733 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1734 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1735 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1736 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1737 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1738 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1739 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1740 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1741 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1743 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1744 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1745 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1746 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1747 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1748 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1749 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1750 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1751 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1752 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1753 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1754 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1756 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1757 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1758 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1759 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1760 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
1761 not be an optional suffix, but part of the instruction. To be
1762 compatible, we accept either. */
1763 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1764 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1766 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1767 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1768 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1769 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1770 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1771 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1772 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1773 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1774 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1775 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1776 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1777 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1779 /* The implementation of the FIX instruction is broken on some
1780 assemblers, in that it accepts a precision specifier as well as a
1781 rounding specifier, despite the fact that this is meaningless.
1782 To be more compatible, we accept it as well, though of course it
1783 does not set any bits. */
1784 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1785 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1786 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1787 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1788 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1789 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1790 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1791 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1792 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1793 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1794 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1795 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1796 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1798 /* Instructions that were new with the real FPA, call them V2. */
1799 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1800 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1801 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1802 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1803 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1804 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1806 /* VFP V1xD (single precision). */
1807 /* Moves and type conversions. */
1808 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1809 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_reg_from_sp
},
1810 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_from_reg
},
1811 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD
, do_empty
},
1812 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1813 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1814 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1815 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1816 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1817 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1818 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_reg_from_ctrl
},
1819 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_ctrl_from_reg
},
1821 /* Memory operations. */
1822 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldst
},
1823 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldst
},
1824 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1825 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1826 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1827 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1828 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1829 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1830 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1831 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1832 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1833 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1834 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1835 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1836 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1837 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1838 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1839 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1841 /* Monadic operations. */
1842 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1843 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1844 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1846 /* Dyadic operations. */
1847 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1848 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1849 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1850 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1851 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1852 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1853 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1854 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1855 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1858 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1859 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_compare_z
},
1860 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1861 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_compare_z
},
1863 /* VFP V1 (Double precision). */
1864 /* Moves and type conversions. */
1865 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1866 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
1867 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1868 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1
, do_vfp_dp_from_reg
},
1869 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1
, do_vfp_dp_from_reg
},
1870 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1
, do_vfp_reg_from_dp
},
1871 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1
, do_vfp_reg_from_dp
},
1872 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
1873 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
1874 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1875 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1876 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1877 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1879 /* Memory operations. */
1880 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1
, do_vfp_dp_ldst
},
1881 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1
, do_vfp_dp_ldst
},
1882 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1883 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1884 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1885 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1886 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1887 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1888 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1889 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1891 /* Monadic operations. */
1892 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1893 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1894 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1896 /* Dyadic operations. */
1897 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1898 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1899 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1900 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1901 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1902 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1903 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1904 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1905 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1908 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1909 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_compare_z
},
1910 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1911 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1
, do_vfp_dp_compare_z
},
1914 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2
, do_vfp_sp2_from_reg2
},
1915 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2
, do_vfp_reg2_from_sp2
},
1916 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2
, do_vfp_dp_from_reg2
},
1917 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2
, do_vfp_reg2_from_dp
},
1919 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
1920 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE
, do_xsc_mia
},
1921 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1922 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1923 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1924 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1925 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1926 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE
, do_xsc_mar
},
1927 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE
, do_xsc_mra
},
1929 /* Intel Wireless MMX technology instructions. */
1930 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
1931 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
1932 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
1933 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
1934 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
1935 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
1936 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
1937 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
1938 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
1939 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
1940 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
1941 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
1942 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
1943 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
1944 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
1945 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
1946 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
1947 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
1948 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmcr
},
1949 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_tmcrr
},
1950 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
1951 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
1952 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
1953 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
1954 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
1955 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
1956 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
1957 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
1958 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
1959 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmrc
},
1960 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_tmrrc
},
1961 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
1962 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
1963 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
1964 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1965 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1966 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1967 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1968 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1969 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1970 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1971 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1972 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1973 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1974 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1975 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1976 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_waligni
},
1977 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1978 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1979 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1980 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1981 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1982 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1983 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1984 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1985 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1986 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1987 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1988 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1989 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1990 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1991 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1992 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1993 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1994 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1995 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1996 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
1997 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
1998 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
1999 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
2000 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2001 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2002 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2003 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2004 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2005 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2006 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2007 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2008 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2009 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2010 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2011 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2012 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2013 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2014 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2015 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2016 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2017 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2018 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wmov
},
2019 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2020 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2021 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2022 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2023 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2024 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2025 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2026 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2027 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2028 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2029 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2030 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2031 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2032 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2033 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2034 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2035 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2036 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2037 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2038 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2039 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2040 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wshufh
},
2041 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2042 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2043 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2044 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2045 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2046 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2047 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2048 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2049 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2050 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2051 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2052 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2053 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2054 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2055 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2056 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2057 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2058 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2059 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
2060 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
2061 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
2062 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
2063 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2064 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2065 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2066 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2067 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2068 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2069 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2070 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2071 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2072 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2073 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2074 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2075 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2076 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2077 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2078 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2079 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2080 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2081 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2082 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2083 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2084 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2085 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2086 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2087 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2088 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2089 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2090 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2091 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wzero
},
2093 /* Cirrus Maverick instructions. */
2094 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_1
},
2095 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_2
},
2096 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_3
},
2097 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_4
},
2098 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_1
},
2099 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_2
},
2100 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_3
},
2101 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_4
},
2102 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK
, do_mav_binops_2a
},
2103 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1a
},
2104 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK
, do_mav_binops_2b
},
2105 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1b
},
2106 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK
, do_mav_binops_2b
},
2107 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1b
},
2108 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK
, do_mav_binops_2c
},
2109 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1c
},
2110 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK
, do_mav_binops_2c
},
2111 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1c
},
2112 {"cfmval32", 0xee200440, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
2113 {"cfmv32al", 0xee100440, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
2114 {"cfmvam32", 0xee200460, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
2115 {"cfmv32am", 0xee100460, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
2116 {"cfmvah32", 0xee200480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
2117 {"cfmv32ah", 0xee100480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
2118 {"cfmva32", 0xee2004a0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
2119 {"cfmv32a", 0xee1004a0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
2120 {"cfmva64", 0xee2004c0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3c
},
2121 {"cfmv64a", 0xee1004c0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3d
},
2122 {"cfmvsc32", 0xee2004e0, 8, ARM_CEXT_MAVERICK
, do_mav_dspsc_1
},
2123 {"cfmv32sc", 0xee1004e0, 8, ARM_CEXT_MAVERICK
, do_mav_dspsc_2
},
2124 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
2125 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
2126 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1f
},
2127 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1g
},
2128 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1h
},
2129 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1i
},
2130 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1j
},
2131 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1k
},
2132 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1l
},
2133 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1m
},
2134 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK
, do_mav_binops_1l
},
2135 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK
, do_mav_binops_1m
},
2136 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK
, do_mav_triple_4a
},
2137 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK
, do_mav_triple_4b
},
2138 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK
, do_mav_shift_1
},
2139 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK
, do_mav_shift_2
},
2140 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5a
},
2141 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5b
},
2142 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5c
},
2143 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5d
},
2144 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
2145 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
2146 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
2147 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
2148 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
2149 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
2150 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
2151 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
2152 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
2153 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
2154 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1n
},
2155 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1o
},
2156 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1n
},
2157 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1o
},
2158 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2159 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
2160 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2161 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
2162 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2163 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
2164 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2165 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2166 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK
, do_mav_quad_6a
},
2167 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK
, do_mav_quad_6a
},
2168 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK
, do_mav_quad_6b
},
2169 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK
, do_mav_quad_6b
},
2172 /* Defines for various bits that we will want to toggle. */
2173 #define INST_IMMEDIATE 0x02000000
2174 #define OFFSET_REG 0x02000000
2175 #define HWOFFSET_IMM 0x00400000
2176 #define SHIFT_BY_REG 0x00000010
2177 #define PRE_INDEX 0x01000000
2178 #define INDEX_UP 0x00800000
2179 #define WRITE_BACK 0x00200000
2180 #define LDM_TYPE_2_OR_3 0x00400000
2182 #define LITERAL_MASK 0xf000f000
2183 #define OPCODE_MASK 0xfe1fffff
2184 #define V4_STR_BIT 0x00000020
2186 #define DATA_OP_SHIFT 21
2188 /* Codes to distinguish the arithmetic instructions. */
2189 #define OPCODE_AND 0
2190 #define OPCODE_EOR 1
2191 #define OPCODE_SUB 2
2192 #define OPCODE_RSB 3
2193 #define OPCODE_ADD 4
2194 #define OPCODE_ADC 5
2195 #define OPCODE_SBC 6
2196 #define OPCODE_RSC 7
2197 #define OPCODE_TST 8
2198 #define OPCODE_TEQ 9
2199 #define OPCODE_CMP 10
2200 #define OPCODE_CMN 11
2201 #define OPCODE_ORR 12
2202 #define OPCODE_MOV 13
2203 #define OPCODE_BIC 14
2204 #define OPCODE_MVN 15
2206 /* Thumb v1 (ARMv4T). */
2207 static void do_t_nop
PARAMS ((char *));
2208 static void do_t_arit
PARAMS ((char *));
2209 static void do_t_add
PARAMS ((char *));
2210 static void do_t_asr
PARAMS ((char *));
2211 static void do_t_branch9
PARAMS ((char *));
2212 static void do_t_branch12
PARAMS ((char *));
2213 static void do_t_branch23
PARAMS ((char *));
2214 static void do_t_bx
PARAMS ((char *));
2215 static void do_t_compare
PARAMS ((char *));
2216 static void do_t_ldmstm
PARAMS ((char *));
2217 static void do_t_ldr
PARAMS ((char *));
2218 static void do_t_ldrb
PARAMS ((char *));
2219 static void do_t_ldrh
PARAMS ((char *));
2220 static void do_t_lds
PARAMS ((char *));
2221 static void do_t_lsl
PARAMS ((char *));
2222 static void do_t_lsr
PARAMS ((char *));
2223 static void do_t_mov
PARAMS ((char *));
2224 static void do_t_push_pop
PARAMS ((char *));
2225 static void do_t_str
PARAMS ((char *));
2226 static void do_t_strb
PARAMS ((char *));
2227 static void do_t_strh
PARAMS ((char *));
2228 static void do_t_sub
PARAMS ((char *));
2229 static void do_t_swi
PARAMS ((char *));
2230 static void do_t_adr
PARAMS ((char *));
2232 /* Thumb v2 (ARMv5T). */
2233 static void do_t_blx
PARAMS ((char *));
2234 static void do_t_bkpt
PARAMS ((char *));
2237 static void do_t_cps
PARAMS ((char *));
2238 static void do_t_cpy
PARAMS ((char *));
2239 static void do_t_setend
PARAMS ((char *));;
2241 #define T_OPCODE_MUL 0x4340
2242 #define T_OPCODE_TST 0x4200
2243 #define T_OPCODE_CMN 0x42c0
2244 #define T_OPCODE_NEG 0x4240
2245 #define T_OPCODE_MVN 0x43c0
2247 #define T_OPCODE_ADD_R3 0x1800
2248 #define T_OPCODE_SUB_R3 0x1a00
2249 #define T_OPCODE_ADD_HI 0x4400
2250 #define T_OPCODE_ADD_ST 0xb000
2251 #define T_OPCODE_SUB_ST 0xb080
2252 #define T_OPCODE_ADD_SP 0xa800
2253 #define T_OPCODE_ADD_PC 0xa000
2254 #define T_OPCODE_ADD_I8 0x3000
2255 #define T_OPCODE_SUB_I8 0x3800
2256 #define T_OPCODE_ADD_I3 0x1c00
2257 #define T_OPCODE_SUB_I3 0x1e00
2259 #define T_OPCODE_ASR_R 0x4100
2260 #define T_OPCODE_LSL_R 0x4080
2261 #define T_OPCODE_LSR_R 0x40c0
2262 #define T_OPCODE_ASR_I 0x1000
2263 #define T_OPCODE_LSL_I 0x0000
2264 #define T_OPCODE_LSR_I 0x0800
2266 #define T_OPCODE_MOV_I8 0x2000
2267 #define T_OPCODE_CMP_I8 0x2800
2268 #define T_OPCODE_CMP_LR 0x4280
2269 #define T_OPCODE_MOV_HR 0x4600
2270 #define T_OPCODE_CMP_HR 0x4500
2272 #define T_OPCODE_LDR_PC 0x4800
2273 #define T_OPCODE_LDR_SP 0x9800
2274 #define T_OPCODE_STR_SP 0x9000
2275 #define T_OPCODE_LDR_IW 0x6800
2276 #define T_OPCODE_STR_IW 0x6000
2277 #define T_OPCODE_LDR_IH 0x8800
2278 #define T_OPCODE_STR_IH 0x8000
2279 #define T_OPCODE_LDR_IB 0x7800
2280 #define T_OPCODE_STR_IB 0x7000
2281 #define T_OPCODE_LDR_RW 0x5800
2282 #define T_OPCODE_STR_RW 0x5000
2283 #define T_OPCODE_LDR_RH 0x5a00
2284 #define T_OPCODE_STR_RH 0x5200
2285 #define T_OPCODE_LDR_RB 0x5c00
2286 #define T_OPCODE_STR_RB 0x5400
2288 #define T_OPCODE_PUSH 0xb400
2289 #define T_OPCODE_POP 0xbc00
2291 #define T_OPCODE_BRANCH 0xe7fe
2293 static int thumb_reg
PARAMS ((char ** str
, int hi_lo
));
2295 #define THUMB_SIZE 2 /* Size of thumb instruction. */
2296 #define THUMB_REG_LO 0x1
2297 #define THUMB_REG_HI 0x2
2298 #define THUMB_REG_ANY 0x3
2300 #define THUMB_H1 0x0080
2301 #define THUMB_H2 0x0040
2307 #define THUMB_MOVE 0
2308 #define THUMB_COMPARE 1
2311 #define THUMB_LOAD 0
2312 #define THUMB_STORE 1
2314 #define THUMB_PP_PC_LR 0x0100
2316 /* These three are used for immediate shifts, do not alter. */
2317 #define THUMB_WORD 2
2318 #define THUMB_HALFWORD 1
2319 #define THUMB_BYTE 0
2323 /* Basic string to match. */
2324 const char * template;
2326 /* Basic instruction code. */
2327 unsigned long value
;
2331 /* Which CPU variants this exists for. */
2332 unsigned long variant
;
2334 /* Function to call to parse args. */
2335 void (* parms
) PARAMS ((char *));
2338 static const struct thumb_opcode tinsns
[] =
2340 /* Thumb v1 (ARMv4T). */
2341 {"adc", 0x4140, 2, ARM_EXT_V4T
, do_t_arit
},
2342 {"add", 0x0000, 2, ARM_EXT_V4T
, do_t_add
},
2343 {"and", 0x4000, 2, ARM_EXT_V4T
, do_t_arit
},
2344 {"asr", 0x0000, 2, ARM_EXT_V4T
, do_t_asr
},
2345 {"b", T_OPCODE_BRANCH
, 2, ARM_EXT_V4T
, do_t_branch12
},
2346 {"beq", 0xd0fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2347 {"bne", 0xd1fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2348 {"bcs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2349 {"bhs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2350 {"bcc", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2351 {"bul", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2352 {"blo", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2353 {"bmi", 0xd4fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2354 {"bpl", 0xd5fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2355 {"bvs", 0xd6fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2356 {"bvc", 0xd7fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2357 {"bhi", 0xd8fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2358 {"bls", 0xd9fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2359 {"bge", 0xdafe, 2, ARM_EXT_V4T
, do_t_branch9
},
2360 {"blt", 0xdbfe, 2, ARM_EXT_V4T
, do_t_branch9
},
2361 {"bgt", 0xdcfe, 2, ARM_EXT_V4T
, do_t_branch9
},
2362 {"ble", 0xddfe, 2, ARM_EXT_V4T
, do_t_branch9
},
2363 {"bal", 0xdefe, 2, ARM_EXT_V4T
, do_t_branch9
},
2364 {"bic", 0x4380, 2, ARM_EXT_V4T
, do_t_arit
},
2365 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T
, do_t_branch23
},
2366 {"bx", 0x4700, 2, ARM_EXT_V4T
, do_t_bx
},
2367 {"cmn", T_OPCODE_CMN
, 2, ARM_EXT_V4T
, do_t_arit
},
2368 {"cmp", 0x0000, 2, ARM_EXT_V4T
, do_t_compare
},
2369 {"eor", 0x4040, 2, ARM_EXT_V4T
, do_t_arit
},
2370 {"ldmia", 0xc800, 2, ARM_EXT_V4T
, do_t_ldmstm
},
2371 {"ldr", 0x0000, 2, ARM_EXT_V4T
, do_t_ldr
},
2372 {"ldrb", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrb
},
2373 {"ldrh", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrh
},
2374 {"ldrsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
2375 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
2376 {"ldsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
2377 {"ldsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
2378 {"lsl", 0x0000, 2, ARM_EXT_V4T
, do_t_lsl
},
2379 {"lsr", 0x0000, 2, ARM_EXT_V4T
, do_t_lsr
},
2380 {"mov", 0x0000, 2, ARM_EXT_V4T
, do_t_mov
},
2381 {"mul", T_OPCODE_MUL
, 2, ARM_EXT_V4T
, do_t_arit
},
2382 {"mvn", T_OPCODE_MVN
, 2, ARM_EXT_V4T
, do_t_arit
},
2383 {"neg", T_OPCODE_NEG
, 2, ARM_EXT_V4T
, do_t_arit
},
2384 {"orr", 0x4300, 2, ARM_EXT_V4T
, do_t_arit
},
2385 {"pop", 0xbc00, 2, ARM_EXT_V4T
, do_t_push_pop
},
2386 {"push", 0xb400, 2, ARM_EXT_V4T
, do_t_push_pop
},
2387 {"ror", 0x41c0, 2, ARM_EXT_V4T
, do_t_arit
},
2388 {"sbc", 0x4180, 2, ARM_EXT_V4T
, do_t_arit
},
2389 {"stmia", 0xc000, 2, ARM_EXT_V4T
, do_t_ldmstm
},
2390 {"str", 0x0000, 2, ARM_EXT_V4T
, do_t_str
},
2391 {"strb", 0x0000, 2, ARM_EXT_V4T
, do_t_strb
},
2392 {"strh", 0x0000, 2, ARM_EXT_V4T
, do_t_strh
},
2393 {"swi", 0xdf00, 2, ARM_EXT_V4T
, do_t_swi
},
2394 {"sub", 0x0000, 2, ARM_EXT_V4T
, do_t_sub
},
2395 {"tst", T_OPCODE_TST
, 2, ARM_EXT_V4T
, do_t_arit
},
2397 {"adr", 0x0000, 2, ARM_EXT_V4T
, do_t_adr
},
2398 {"nop", 0x46C0, 2, ARM_EXT_V4T
, do_t_nop
}, /* mov r8,r8 */
2399 /* Thumb v2 (ARMv5T). */
2400 {"blx", 0, 0, ARM_EXT_V5T
, do_t_blx
},
2401 {"bkpt", 0xbe00, 2, ARM_EXT_V5T
, do_t_bkpt
},
2404 {"cpsie", 0xb660, 2, ARM_EXT_V6
, do_t_cps
},
2405 {"cpsid", 0xb670, 2, ARM_EXT_V6
, do_t_cps
},
2406 {"cpy", 0x4600, 2, ARM_EXT_V6
, do_t_cpy
},
2407 {"rev", 0xba00, 2, ARM_EXT_V6
, do_t_arit
},
2408 {"rev16", 0xba40, 2, ARM_EXT_V6
, do_t_arit
},
2409 {"revsh", 0xbac0, 2, ARM_EXT_V6
, do_t_arit
},
2410 {"setend", 0xb650, 2, ARM_EXT_V6
, do_t_setend
},
2411 {"sxth", 0xb200, 2, ARM_EXT_V6
, do_t_arit
},
2412 {"sxtb", 0xb240, 2, ARM_EXT_V6
, do_t_arit
},
2413 {"uxth", 0xb280, 2, ARM_EXT_V6
, do_t_arit
},
2414 {"uxtb", 0xb2c0, 2, ARM_EXT_V6
, do_t_arit
},
2417 #define BAD_ARGS _("bad arguments to instruction")
2418 #define BAD_PC _("r15 not allowed here")
2419 #define BAD_COND _("instruction is not conditional")
2420 #define ERR_NO_ACCUM _("acc0 expected")
2422 static struct hash_control
* arm_ops_hsh
= NULL
;
2423 static struct hash_control
* arm_tops_hsh
= NULL
;
2424 static struct hash_control
* arm_cond_hsh
= NULL
;
2425 static struct hash_control
* arm_shift_hsh
= NULL
;
2426 static struct hash_control
* arm_psr_hsh
= NULL
;
2428 /* This table describes all the machine specific pseudo-ops the assembler
2429 has to support. The fields are:
2430 pseudo-op name without dot
2431 function to call to execute this pseudo-op
2432 Integer arg to pass to the function. */
2434 static void s_req
PARAMS ((int));
2435 static void s_unreq
PARAMS ((int));
2436 static void s_align
PARAMS ((int));
2437 static void s_bss
PARAMS ((int));
2438 static void s_even
PARAMS ((int));
2439 static void s_ltorg
PARAMS ((int));
2440 static void s_arm
PARAMS ((int));
2441 static void s_thumb
PARAMS ((int));
2442 static void s_code
PARAMS ((int));
2443 static void s_force_thumb
PARAMS ((int));
2444 static void s_thumb_func
PARAMS ((int));
2445 static void s_thumb_set
PARAMS ((int));
2447 static void s_arm_elf_cons
PARAMS ((int));
2448 static void s_arm_rel31 (int nbytes
);
2451 static int my_get_expression
PARAMS ((expressionS
*, char **));
2453 const pseudo_typeS md_pseudo_table
[] =
2455 /* Never called because '.req' does not start a line. */
2456 { "req", s_req
, 0 },
2457 { "unreq", s_unreq
, 0 },
2458 { "bss", s_bss
, 0 },
2459 { "align", s_align
, 0 },
2460 { "arm", s_arm
, 0 },
2461 { "thumb", s_thumb
, 0 },
2462 { "code", s_code
, 0 },
2463 { "force_thumb", s_force_thumb
, 0 },
2464 { "thumb_func", s_thumb_func
, 0 },
2465 { "thumb_set", s_thumb_set
, 0 },
2466 { "even", s_even
, 0 },
2467 { "ltorg", s_ltorg
, 0 },
2468 { "pool", s_ltorg
, 0 },
2470 { "word", s_arm_elf_cons
, 4 },
2471 { "long", s_arm_elf_cons
, 4 },
2472 { "rel31", s_arm_rel31
, 0 },
2476 { "extend", float_cons
, 'x' },
2477 { "ldouble", float_cons
, 'x' },
2478 { "packed", float_cons
, 'p' },
2482 /* Other internal functions. */
2483 static int arm_parse_extension
PARAMS ((char *, int *));
2484 static int arm_parse_cpu
PARAMS ((char *));
2485 static int arm_parse_arch
PARAMS ((char *));
2486 static int arm_parse_fpu
PARAMS ((char *));
2487 static int arm_parse_float_abi
PARAMS ((char *));
2489 static int arm_parse_eabi
PARAMS ((char *));
2491 #if 0 /* Suppressed - for now. */
2492 #if defined OBJ_COFF || defined OBJ_ELF
2493 static void arm_add_note
PARAMS ((const char *, const char *, unsigned int));
2497 /* Stuff needed to resolve the label ambiguity
2507 symbolS
* last_label_seen
;
2508 static int label_is_thumb_function_name
= FALSE
;
2510 /* Literal Pool stuff. */
2512 #define MAX_LITERAL_POOL_SIZE 1024
2514 /* Literal pool structure. Held on a per-section
2515 and per-sub-section basis. */
2516 typedef struct literal_pool
2518 expressionS literals
[MAX_LITERAL_POOL_SIZE
];
2519 unsigned int next_free_entry
;
2523 subsegT sub_section
;
2524 struct literal_pool
* next
;
2527 /* Pointer to a linked list of literal pools. */
2528 literal_pool
* list_of_pools
= NULL
;
2530 static literal_pool
* find_literal_pool
PARAMS ((void));
2531 static literal_pool
* find_or_make_literal_pool
PARAMS ((void));
2533 static literal_pool
*
2534 find_literal_pool ()
2536 literal_pool
* pool
;
2538 for (pool
= list_of_pools
; pool
!= NULL
; pool
= pool
->next
)
2540 if (pool
->section
== now_seg
2541 && pool
->sub_section
== now_subseg
)
2548 static literal_pool
*
2549 find_or_make_literal_pool ()
2551 /* Next literal pool ID number. */
2552 static unsigned int latest_pool_num
= 1;
2553 literal_pool
* pool
;
2555 pool
= find_literal_pool ();
2559 /* Create a new pool. */
2560 pool
= (literal_pool
*) xmalloc (sizeof (* pool
));
2564 pool
->next_free_entry
= 0;
2565 pool
->section
= now_seg
;
2566 pool
->sub_section
= now_subseg
;
2567 pool
->next
= list_of_pools
;
2568 pool
->symbol
= NULL
;
2570 /* Add it to the list. */
2571 list_of_pools
= pool
;
2574 /* New pools, and emptied pools, will have a NULL symbol. */
2575 if (pool
->symbol
== NULL
)
2577 pool
->symbol
= symbol_create (FAKE_LABEL_NAME
, undefined_section
,
2578 (valueT
) 0, &zero_address_frag
);
2579 pool
->id
= latest_pool_num
++;
2586 /* Add the literal in the global 'inst'
2587 structure to the relevent literal pool. */
2591 literal_pool
* pool
;
2594 pool
= find_or_make_literal_pool ();
2596 /* Check if this literal value is already in the pool. */
2597 for (entry
= 0; entry
< pool
->next_free_entry
; entry
++)
2599 if ((pool
->literals
[entry
].X_op
== inst
.reloc
.exp
.X_op
)
2600 && (inst
.reloc
.exp
.X_op
== O_constant
)
2601 && (pool
->literals
[entry
].X_add_number
2602 == inst
.reloc
.exp
.X_add_number
)
2603 && (pool
->literals
[entry
].X_unsigned
2604 == inst
.reloc
.exp
.X_unsigned
))
2607 if ((pool
->literals
[entry
].X_op
== inst
.reloc
.exp
.X_op
)
2608 && (inst
.reloc
.exp
.X_op
== O_symbol
)
2609 && (pool
->literals
[entry
].X_add_number
2610 == inst
.reloc
.exp
.X_add_number
)
2611 && (pool
->literals
[entry
].X_add_symbol
2612 == inst
.reloc
.exp
.X_add_symbol
)
2613 && (pool
->literals
[entry
].X_op_symbol
2614 == inst
.reloc
.exp
.X_op_symbol
))
2618 /* Do we need to create a new entry? */
2619 if (entry
== pool
->next_free_entry
)
2621 if (entry
>= MAX_LITERAL_POOL_SIZE
)
2623 inst
.error
= _("literal pool overflow");
2627 pool
->literals
[entry
] = inst
.reloc
.exp
;
2628 pool
->next_free_entry
+= 1;
2631 inst
.reloc
.exp
.X_op
= O_symbol
;
2632 inst
.reloc
.exp
.X_add_number
= ((int) entry
) * 4 - 8;
2633 inst
.reloc
.exp
.X_add_symbol
= pool
->symbol
;
2638 /* Can't use symbol_new here, so have to create a symbol and then at
2639 a later date assign it a value. Thats what these functions do. */
2642 symbol_locate (symbolP
, name
, segment
, valu
, frag
)
2644 const char * name
; /* It is copied, the caller can modify. */
2645 segT segment
; /* Segment identifier (SEG_<something>). */
2646 valueT valu
; /* Symbol value. */
2647 fragS
* frag
; /* Associated fragment. */
2649 unsigned int name_length
;
2650 char * preserved_copy_of_name
;
2652 name_length
= strlen (name
) + 1; /* +1 for \0. */
2653 obstack_grow (¬es
, name
, name_length
);
2654 preserved_copy_of_name
= obstack_finish (¬es
);
2655 #ifdef STRIP_UNDERSCORE
2656 if (preserved_copy_of_name
[0] == '_')
2657 preserved_copy_of_name
++;
2660 #ifdef tc_canonicalize_symbol_name
2661 preserved_copy_of_name
=
2662 tc_canonicalize_symbol_name (preserved_copy_of_name
);
2665 S_SET_NAME (symbolP
, preserved_copy_of_name
);
2667 S_SET_SEGMENT (symbolP
, segment
);
2668 S_SET_VALUE (symbolP
, valu
);
2669 symbol_clear_list_pointers (symbolP
);
2671 symbol_set_frag (symbolP
, frag
);
2673 /* Link to end of symbol chain. */
2675 extern int symbol_table_frozen
;
2676 if (symbol_table_frozen
)
2680 symbol_append (symbolP
, symbol_lastP
, & symbol_rootP
, & symbol_lastP
);
2682 obj_symbol_new_hook (symbolP
);
2684 #ifdef tc_symbol_new_hook
2685 tc_symbol_new_hook (symbolP
);
2689 verify_symbol_chain (symbol_rootP
, symbol_lastP
);
2690 #endif /* DEBUG_SYMS */
2693 /* Check that an immediate is valid.
2694 If so, convert it to the right format. */
2697 validate_immediate (val
)
2703 #define rotate_left(v, n) (v << n | v >> (32 - n))
2705 for (i
= 0; i
< 32; i
+= 2)
2706 if ((a
= rotate_left (val
, i
)) <= 0xff)
2707 return a
| (i
<< 7); /* 12-bit pack: [shift-cnt,const]. */
2712 /* Check to see if an immediate can be computed as two separate immediate
2713 values, added together. We already know that this value cannot be
2714 computed by just one ARM instruction. */
2717 validate_immediate_twopart (val
, highpart
)
2719 unsigned int * highpart
;
2724 for (i
= 0; i
< 32; i
+= 2)
2725 if (((a
= rotate_left (val
, i
)) & 0xff) != 0)
2731 * highpart
= (a
>> 8) | ((i
+ 24) << 7);
2733 else if (a
& 0xff0000)
2737 * highpart
= (a
>> 16) | ((i
+ 16) << 7);
2741 assert (a
& 0xff000000);
2742 * highpart
= (a
>> 24) | ((i
+ 8) << 7);
2745 return (a
& 0xff) | (i
<< 7);
2752 validate_offset_imm (val
, hwse
)
2756 if ((hwse
&& val
> 255) || val
> 4095)
2763 /* This code is to handle mapping symbols as defined in the ARM ELF spec.
2764 (This text is taken from version B-02 of the spec):
2766 4.4.7 Mapping and tagging symbols
2768 A section of an ARM ELF file can contain a mixture of ARM code,
2769 Thumb code, and data. There are inline transitions between code
2770 and data at literal pool boundaries. There can also be inline
2771 transitions between ARM code and Thumb code, for example in
2772 ARM-Thumb inter-working veneers. Linkers, machine-level
2773 debuggers, profiling tools, and disassembly tools need to map
2774 images accurately. For example, setting an ARM breakpoint on a
2775 Thumb location, or in a literal pool, can crash the program
2776 being debugged, ruining the debugging session.
2778 ARM ELF entities are mapped (see section 4.4.7.1 below) and
2779 tagged (see section 4.4.7.2 below) using local symbols (with
2780 binding STB_LOCAL). To assist consumers, mapping and tagging
2781 symbols should be collated first in the symbol table, before
2782 other symbols with binding STB_LOCAL.
2784 To allow properly collated mapping and tagging symbols to be
2785 skipped by consumers that have no interest in them, the first
2786 such symbol should have the name $m and its st_value field equal
2787 to the total number of mapping and tagging symbols (including
2788 the $m) in the symbol table.
2790 4.4.7.1 Mapping symbols
2792 $a Labels the first byte of a sequence of ARM instructions.
2793 Its type is STT_FUNC.
2795 $d Labels the first byte of a sequence of data items.
2796 Its type is STT_OBJECT.
2798 $t Labels the first byte of a sequence of Thumb instructions.
2799 Its type is STT_FUNC.
2801 This list of mapping symbols may be extended in the future.
2803 Section-relative mapping symbols
2805 Mapping symbols defined in a section define a sequence of
2806 half-open address intervals that cover the address range of the
2807 section. Each interval starts at the address defined by a
2808 mapping symbol, and continues up to, but not including, the
2809 address defined by the next (in address order) mapping symbol or
2810 the end of the section. A corollary is that there must be a
2811 mapping symbol defined at the beginning of each section.
2812 Consumers can ignore the size of a section-relative mapping
2813 symbol. Producers can set it to 0.
2815 Absolute mapping symbols
2817 Because of the need to crystallize a Thumb address with the
2818 Thumb-bit set, absolute symbol of type STT_FUNC (symbols of type
2819 STT_FUNC defined in section SHN_ABS) need to be mapped with $a
2822 The extent of a mapping symbol defined in SHN_ABS is [st_value,
2823 st_value + st_size), or [st_value, st_value + 1) if st_size = 0,
2824 where [x, y) denotes the half-open address range from x,
2825 inclusive, to y, exclusive.
2827 In the absence of a mapping symbol, a consumer can interpret a
2828 function symbol with an odd value as the Thumb code address
2829 obtained by clearing the least significant bit of the
2830 value. This interpretation is deprecated, and it may not work in
2833 Note - the Tagging symbols ($b, $f, $p $m) have been dropped from
2834 the EABI (which is still under development), so they are not
2835 implemented here. */
2837 static enum mstate mapstate
= MAP_UNDEFINED
;
2840 mapping_state (enum mstate state
)
2843 const char * symname
;
2846 if (mapstate
== state
)
2847 /* The mapping symbol has already been emitted.
2848 There is nothing else to do. */
2861 type
= BSF_FUNCTION
;
2865 type
= BSF_FUNCTION
;
2873 seg_info (now_seg
)->tc_segment_info_data
= state
;
2875 symbolP
= symbol_new (symname
, now_seg
, (valueT
) frag_now_fix (), frag_now
);
2876 symbol_table_insert (symbolP
);
2877 symbol_get_bfdsym (symbolP
)->flags
|= type
| BSF_LOCAL
;
2882 THUMB_SET_FUNC (symbolP
, 0);
2883 ARM_SET_THUMB (symbolP
, 0);
2884 ARM_SET_INTERWORK (symbolP
, support_interwork
);
2888 THUMB_SET_FUNC (symbolP
, 1);
2889 ARM_SET_THUMB (symbolP
, 1);
2890 ARM_SET_INTERWORK (symbolP
, support_interwork
);
2899 /* When we change sections we need to issue a new mapping symbol. */
2902 arm_elf_change_section (void)
2906 if (!SEG_NORMAL (now_seg
))
2909 flags
= bfd_get_section_flags (stdoutput
, now_seg
);
2911 /* We can ignore sections that only contain debug info. */
2912 if ((flags
& SEC_ALLOC
) == 0)
2915 mapstate
= seg_info (now_seg
)->tc_segment_info_data
;
2918 #define mapping_state(a)
2919 #endif /* OBJ_ELF */
2924 int a ATTRIBUTE_UNUSED
;
2926 as_bad (_("invalid syntax for .req directive"));
2929 /* The .unreq directive deletes an alias which was previously defined
2930 by .req. For example:
2936 s_unreq (int a ATTRIBUTE_UNUSED
)
2941 skip_whitespace (input_line_pointer
);
2942 name
= input_line_pointer
;
2944 while (*input_line_pointer
!= 0
2945 && *input_line_pointer
!= ' '
2946 && *input_line_pointer
!= '\n')
2947 ++input_line_pointer
;
2949 saved_char
= *input_line_pointer
;
2950 *input_line_pointer
= 0;
2954 enum arm_reg_type req_type
= arm_reg_parse_any (name
);
2956 if (req_type
!= REG_TYPE_MAX
)
2958 char *temp_name
= name
;
2959 int req_no
= arm_reg_parse (&temp_name
, all_reg_maps
[req_type
].htab
);
2963 struct reg_entry
*req_entry
;
2965 /* Check to see if this alias is a builtin one. */
2966 req_entry
= hash_delete (all_reg_maps
[req_type
].htab
, name
);
2969 as_bad (_("unreq: missing hash entry for \"%s\""), name
);
2970 else if (req_entry
->builtin
)
2971 /* FIXME: We are deleting a built in register alias which
2972 points to a const data structure, so we only need to
2973 free up the memory used by the key in the hash table.
2974 Unfortunately we have not recorded this value, so this
2975 is a memory leak. */
2976 /* FIXME: Should we issue a warning message ? */
2980 /* Deleting a user defined alias. We need to free the
2981 key and the value, but fortunately the key is the same
2982 as the value->name field. */
2983 free ((char *) req_entry
->name
);
2988 as_bad (_(".unreq: unrecognized symbol \"%s\""), name
);
2991 as_bad (_(".unreq: unrecognized symbol \"%s\""), name
);
2994 as_bad (_("invalid syntax for .unreq directive"));
2996 *input_line_pointer
= saved_char
;
2997 demand_empty_rest_of_line ();
3002 int ignore ATTRIBUTE_UNUSED
;
3004 /* We don't support putting frags in the BSS segment, we fake it by
3005 marking in_bss, then looking at s_skip for clues. */
3006 subseg_set (bss_section
, 0);
3007 demand_empty_rest_of_line ();
3008 mapping_state (MAP_DATA
);
3013 int ignore ATTRIBUTE_UNUSED
;
3015 /* Never make frag if expect extra pass. */
3017 frag_align (1, 0, 0);
3019 record_alignment (now_seg
, 1);
3021 demand_empty_rest_of_line ();
3026 int ignored ATTRIBUTE_UNUSED
;
3029 literal_pool
* pool
;
3032 pool
= find_literal_pool ();
3034 || pool
->symbol
== NULL
3035 || pool
->next_free_entry
== 0)
3038 mapping_state (MAP_DATA
);
3040 /* Align pool as you have word accesses.
3041 Only make a frag if we have to. */
3043 frag_align (2, 0, 0);
3045 record_alignment (now_seg
, 2);
3047 sprintf (sym_name
, "$$lit_\002%x", pool
->id
);
3049 symbol_locate (pool
->symbol
, sym_name
, now_seg
,
3050 (valueT
) frag_now_fix (), frag_now
);
3051 symbol_table_insert (pool
->symbol
);
3053 ARM_SET_THUMB (pool
->symbol
, thumb_mode
);
3055 #if defined OBJ_COFF || defined OBJ_ELF
3056 ARM_SET_INTERWORK (pool
->symbol
, support_interwork
);
3059 for (entry
= 0; entry
< pool
->next_free_entry
; entry
++)
3060 /* First output the expression in the instruction to the pool. */
3061 emit_expr (&(pool
->literals
[entry
]), 4); /* .word */
3063 /* Mark the pool as empty. */
3064 pool
->next_free_entry
= 0;
3065 pool
->symbol
= NULL
;
3068 /* Same as s_align_ptwo but align 0 => align 2. */
3072 int unused ATTRIBUTE_UNUSED
;
3075 register long temp_fill
;
3076 long max_alignment
= 15;
3078 temp
= get_absolute_expression ();
3079 if (temp
> max_alignment
)
3080 as_bad (_("alignment too large: %d assumed"), temp
= max_alignment
);
3083 as_bad (_("alignment negative. 0 assumed."));
3087 if (*input_line_pointer
== ',')
3089 input_line_pointer
++;
3090 temp_fill
= get_absolute_expression ();
3098 /* Only make a frag if we HAVE to. */
3099 if (temp
&& !need_pass_2
)
3100 frag_align (temp
, (int) temp_fill
, 0);
3101 demand_empty_rest_of_line ();
3103 record_alignment (now_seg
, temp
);
3107 s_force_thumb (ignore
)
3108 int ignore ATTRIBUTE_UNUSED
;
3110 /* If we are not already in thumb mode go into it, EVEN if
3111 the target processor does not support thumb instructions.
3112 This is used by gcc/config/arm/lib1funcs.asm for example
3113 to compile interworking support functions even if the
3114 target processor should not support interworking. */
3119 record_alignment (now_seg
, 1);
3122 demand_empty_rest_of_line ();
3126 s_thumb_func (ignore
)
3127 int ignore ATTRIBUTE_UNUSED
;
3132 /* The following label is the name/address of the start of a Thumb function.
3133 We need to know this for the interworking support. */
3134 label_is_thumb_function_name
= TRUE
;
3136 demand_empty_rest_of_line ();
3139 /* Perform a .set directive, but also mark the alias as
3140 being a thumb function. */
3146 /* XXX the following is a duplicate of the code for s_set() in read.c
3147 We cannot just call that code as we need to get at the symbol that
3149 register char * name
;
3150 register char delim
;
3151 register char * end_name
;
3152 register symbolS
* symbolP
;
3154 /* Especial apologies for the random logic:
3155 This just grew, and could be parsed much more simply!
3157 name
= input_line_pointer
;
3158 delim
= get_symbol_end ();
3159 end_name
= input_line_pointer
;
3164 if (*input_line_pointer
!= ',')
3167 as_bad (_("expected comma after name \"%s\""), name
);
3169 ignore_rest_of_line ();
3173 input_line_pointer
++;
3176 if (name
[0] == '.' && name
[1] == '\0')
3178 /* XXX - this should not happen to .thumb_set. */
3182 if ((symbolP
= symbol_find (name
)) == NULL
3183 && (symbolP
= md_undefined_symbol (name
)) == NULL
)
3186 /* When doing symbol listings, play games with dummy fragments living
3187 outside the normal fragment chain to record the file and line info
3189 if (listing
& LISTING_SYMBOLS
)
3191 extern struct list_info_struct
* listing_tail
;
3192 fragS
* dummy_frag
= (fragS
*) xmalloc (sizeof (fragS
));
3194 memset (dummy_frag
, 0, sizeof (fragS
));
3195 dummy_frag
->fr_type
= rs_fill
;
3196 dummy_frag
->line
= listing_tail
;
3197 symbolP
= symbol_new (name
, undefined_section
, 0, dummy_frag
);
3198 dummy_frag
->fr_symbol
= symbolP
;
3202 symbolP
= symbol_new (name
, undefined_section
, 0, &zero_address_frag
);
3205 /* "set" symbols are local unless otherwise specified. */
3206 SF_SET_LOCAL (symbolP
);
3207 #endif /* OBJ_COFF */
3208 } /* Make a new symbol. */
3210 symbol_table_insert (symbolP
);
3215 && S_IS_DEFINED (symbolP
)
3216 && S_GET_SEGMENT (symbolP
) != reg_section
)
3217 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP
));
3219 pseudo_set (symbolP
);
3221 demand_empty_rest_of_line ();
3223 /* XXX Now we come to the Thumb specific bit of code. */
3225 THUMB_SET_FUNC (symbolP
, 1);
3226 ARM_SET_THUMB (symbolP
, 1);
3227 #if defined OBJ_ELF || defined OBJ_COFF
3228 ARM_SET_INTERWORK (symbolP
, support_interwork
);
3233 opcode_select (width
)
3241 if (! (cpu_variant
& ARM_EXT_V4T
))
3242 as_bad (_("selected processor does not support THUMB opcodes"));
3245 /* No need to force the alignment, since we will have been
3246 coming from ARM mode, which is word-aligned. */
3247 record_alignment (now_seg
, 1);
3249 mapping_state (MAP_THUMB
);
3255 if ((cpu_variant
& ARM_ALL
) == ARM_EXT_V4T
)
3256 as_bad (_("selected processor does not support ARM opcodes"));
3261 frag_align (2, 0, 0);
3263 record_alignment (now_seg
, 1);
3265 mapping_state (MAP_ARM
);
3269 as_bad (_("invalid instruction size selected (%d)"), width
);
3275 int ignore ATTRIBUTE_UNUSED
;
3278 demand_empty_rest_of_line ();
3283 int ignore ATTRIBUTE_UNUSED
;
3286 demand_empty_rest_of_line ();
3291 int unused ATTRIBUTE_UNUSED
;
3295 temp
= get_absolute_expression ();
3300 opcode_select (temp
);
3304 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp
);
3312 skip_whitespace (str
);
3314 if (*str
!= '\0' && !inst
.error
)
3315 inst
.error
= _("garbage following instruction");
3319 skip_past_comma (str
)
3322 char * p
= * str
, c
;
3325 while ((c
= *p
) == ' ' || c
== ',')
3328 if (c
== ',' && comma
++)
3336 return comma
? SUCCESS
: FAIL
;
3339 /* A standard register must be given at this point.
3340 SHIFT is the place to put it in inst.instruction.
3341 Restores input start point on error.
3342 Returns the reg#, or FAIL. */
3345 reg_required_here (str
, shift
)
3349 static char buff
[128]; /* XXX */
3351 char * start
= * str
;
3353 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_RN
].htab
)) != FAIL
)
3356 inst
.instruction
|= reg
<< shift
;
3360 /* Restore the start point, we may have got a reg of the wrong class. */
3363 /* In the few cases where we might be able to accept something else
3364 this error can be overridden. */
3365 sprintf (buff
, _("register expected, not '%.100s'"), start
);
3371 /* A Intel Wireless MMX technology register
3372 must be given at this point.
3373 Shift is the place to put it in inst.instruction.
3374 Restores input start point on err.
3375 Returns the reg#, or FAIL. */
3378 wreg_required_here (str
, shift
, reg_type
)
3381 enum wreg_type reg_type
;
3383 static char buff
[128];
3385 char * start
= *str
;
3387 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_IWMMXT
].htab
)) != FAIL
)
3389 if (wr_register (reg
)
3390 && (reg_type
== IWMMXT_REG_WR
|| reg_type
== IWMMXT_REG_WR_OR_WC
))
3393 inst
.instruction
|= (reg
^ WR_PREFIX
) << shift
;
3396 else if (wc_register (reg
)
3397 && (reg_type
== IWMMXT_REG_WC
|| reg_type
== IWMMXT_REG_WR_OR_WC
))
3400 inst
.instruction
|= (reg
^ WC_PREFIX
) << shift
;
3403 else if ((wcg_register (reg
) && reg_type
== IWMMXT_REG_WCG
))
3406 inst
.instruction
|= ((reg
^ WC_PREFIX
) - 8) << shift
;
3411 /* Restore the start point, we may have got a reg of the wrong class. */
3414 /* In the few cases where we might be able to accept
3415 something else this error can be overridden. */
3416 sprintf (buff
, _("Intel Wireless MMX technology register expected, not '%.100s'"), start
);
3422 static const struct asm_psr
*
3424 register char ** ccp
;
3426 char * start
= * ccp
;
3429 const struct asm_psr
* psr
;
3433 /* Skip to the end of the next word in the input stream. */
3438 while (ISALPHA (c
) || c
== '_');
3440 /* Terminate the word. */
3443 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
3444 feature for ease of use and backwards compatibility. */
3445 if (!strncmp (start
, "cpsr", 4))
3446 strncpy (start
, "CPSR", 4);
3447 else if (!strncmp (start
, "spsr", 4))
3448 strncpy (start
, "SPSR", 4);
3450 /* Now locate the word in the psr hash table. */
3451 psr
= (const struct asm_psr
*) hash_find (arm_psr_hsh
, start
);
3453 /* Restore the input stream. */
3456 /* If we found a valid match, advance the
3457 stream pointer past the end of the word. */
3463 /* Parse the input looking for a PSR flag. */
3466 psr_required_here (str
)
3469 char * start
= * str
;
3470 const struct asm_psr
* psr
;
3472 psr
= arm_psr_parse (str
);
3476 /* If this is the SPSR that is being modified, set the R bit. */
3478 inst
.instruction
|= SPSR_BIT
;
3480 /* Set the psr flags in the MSR instruction. */
3481 inst
.instruction
|= psr
->field
<< PSR_SHIFT
;
3486 /* In the few cases where we might be able to accept
3487 something else this error can be overridden. */
3488 inst
.error
= _("flag for {c}psr instruction expected");
3490 /* Restore the start point. */
3496 co_proc_number (str
)
3499 int processor
, pchar
;
3502 skip_whitespace (*str
);
3505 /* The data sheet seems to imply that just a number on its own is valid
3506 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
3508 if ((processor
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CP
].htab
))
3514 if (pchar
>= '0' && pchar
<= '9')
3516 processor
= pchar
- '0';
3517 if (**str
>= '0' && **str
<= '9')
3519 processor
= processor
* 10 + *(*str
)++ - '0';
3522 inst
.error
= _("illegal co-processor number");
3529 inst
.error
= all_reg_maps
[REG_TYPE_CP
].expected
;
3534 inst
.instruction
|= processor
<< 8;
3539 cp_opc_expr (str
, where
, length
)
3546 skip_whitespace (* str
);
3548 memset (&expr
, '\0', sizeof (expr
));
3550 if (my_get_expression (&expr
, str
))
3552 if (expr
.X_op
!= O_constant
)
3554 inst
.error
= _("bad or missing expression");
3558 if ((expr
.X_add_number
& ((1 << length
) - 1)) != expr
.X_add_number
)
3560 inst
.error
= _("immediate co-processor expression too large");
3564 inst
.instruction
|= expr
.X_add_number
<< where
;
3569 cp_reg_required_here (str
, where
)
3574 char * start
= *str
;
3576 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CN
].htab
)) != FAIL
)
3578 inst
.instruction
|= reg
<< where
;
3582 /* In the few cases where we might be able to accept something else
3583 this error can be overridden. */
3584 inst
.error
= all_reg_maps
[REG_TYPE_CN
].expected
;
3586 /* Restore the start point. */
3592 fp_reg_required_here (str
, where
)
3597 char * start
= * str
;
3599 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_FN
].htab
)) != FAIL
)
3601 inst
.instruction
|= reg
<< where
;
3605 /* In the few cases where we might be able to accept something else
3606 this error can be overridden. */
3607 inst
.error
= all_reg_maps
[REG_TYPE_FN
].expected
;
3609 /* Restore the start point. */
3615 cp_address_offset (str
)
3620 skip_whitespace (* str
);
3622 if (! is_immediate_prefix (**str
))
3624 inst
.error
= _("immediate expression expected");
3630 if (my_get_expression (& inst
.reloc
.exp
, str
))
3633 if (inst
.reloc
.exp
.X_op
== O_constant
)
3635 offset
= inst
.reloc
.exp
.X_add_number
;
3639 inst
.error
= _("co-processor address must be word aligned");
3643 if (offset
> 1023 || offset
< -1023)
3645 inst
.error
= _("offset too large");
3650 inst
.instruction
|= INDEX_UP
;
3654 inst
.instruction
|= offset
>> 2;
3657 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
3663 cp_address_required_here (str
, wb_ok
)
3676 skip_whitespace (p
);
3678 if ((reg
= reg_required_here (& p
, 16)) == FAIL
)
3681 skip_whitespace (p
);
3687 skip_whitespace (p
);
3691 /* As an extension to the official ARM syntax we allow:
3695 as a short hand for:
3698 inst
.instruction
|= PRE_INDEX
| INDEX_UP
;
3703 if (skip_past_comma (& p
) == FAIL
)
3705 inst
.error
= _("comma expected after closing square bracket");
3709 skip_whitespace (p
);
3716 write_back
= WRITE_BACK
;
3720 inst
.error
= _("pc may not be used in post-increment");
3724 if (cp_address_offset (& p
) == FAIL
)
3728 pre_inc
= PRE_INDEX
| INDEX_UP
;
3734 /* [Rn], {<expr>} */
3737 skip_whitespace (p
);
3739 if (my_get_expression (& inst
.reloc
.exp
, & p
))
3742 if (inst
.reloc
.exp
.X_op
== O_constant
)
3744 option
= inst
.reloc
.exp
.X_add_number
;
3746 if (option
> 255 || option
< 0)
3748 inst
.error
= _("'option' field too large");
3752 skip_whitespace (p
);
3756 inst
.error
= _("'}' expected at end of 'option' field");
3762 inst
.instruction
|= option
;
3763 inst
.instruction
|= INDEX_UP
;
3768 inst
.error
= _("non-constant expressions for 'option' field not supported");
3774 inst
.error
= _("# or { expected after comma");
3780 /* '['Rn, #expr']'[!] */
3782 if (skip_past_comma (& p
) == FAIL
)
3784 inst
.error
= _("pre-indexed expression expected");
3788 pre_inc
= PRE_INDEX
;
3790 if (cp_address_offset (& p
) == FAIL
)
3793 skip_whitespace (p
);
3797 inst
.error
= _("missing ]");
3801 skip_whitespace (p
);
3803 if (wb_ok
&& *p
== '!')
3807 inst
.error
= _("pc may not be used with write-back");
3812 write_back
= WRITE_BACK
;
3818 if (my_get_expression (&inst
.reloc
.exp
, &p
))
3821 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
3822 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
3823 inst
.reloc
.pc_rel
= 1;
3824 inst
.instruction
|= (REG_PC
<< 16);
3825 pre_inc
= PRE_INDEX
;
3828 inst
.instruction
|= write_back
| pre_inc
;
3834 cp_byte_address_offset (str
)
3839 skip_whitespace (* str
);
3841 if (! is_immediate_prefix (**str
))
3843 inst
.error
= _("immediate expression expected");
3849 if (my_get_expression (& inst
.reloc
.exp
, str
))
3852 if (inst
.reloc
.exp
.X_op
== O_constant
)
3854 offset
= inst
.reloc
.exp
.X_add_number
;
3856 if (offset
> 255 || offset
< -255)
3858 inst
.error
= _("offset too large");
3863 inst
.instruction
|= INDEX_UP
;
3867 inst
.instruction
|= offset
;
3870 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM_S2
;
3876 cp_byte_address_required_here (str
)
3888 skip_whitespace (p
);
3890 if ((reg
= reg_required_here (& p
, 16)) == FAIL
)
3893 skip_whitespace (p
);
3899 if (skip_past_comma (& p
) == SUCCESS
)
3902 write_back
= WRITE_BACK
;
3906 inst
.error
= _("pc may not be used in post-increment");
3910 if (cp_byte_address_offset (& p
) == FAIL
)
3914 pre_inc
= PRE_INDEX
| INDEX_UP
;
3918 /* '['Rn, #expr']'[!] */
3920 if (skip_past_comma (& p
) == FAIL
)
3922 inst
.error
= _("pre-indexed expression expected");
3926 pre_inc
= PRE_INDEX
;
3928 if (cp_byte_address_offset (& p
) == FAIL
)
3931 skip_whitespace (p
);
3935 inst
.error
= _("missing ]");
3939 skip_whitespace (p
);
3945 inst
.error
= _("pc may not be used with write-back");
3950 write_back
= WRITE_BACK
;
3956 if (my_get_expression (&inst
.reloc
.exp
, &p
))
3959 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM_S2
;
3960 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
3961 inst
.reloc
.pc_rel
= 1;
3962 inst
.instruction
|= (REG_PC
<< 16);
3963 pre_inc
= PRE_INDEX
;
3966 inst
.instruction
|= write_back
| pre_inc
;
3975 /* Do nothing really. */
3985 /* Only one syntax. */
3986 skip_whitespace (str
);
3988 if (reg_required_here (&str
, 12) == FAIL
)
3990 inst
.error
= BAD_ARGS
;
3994 if (skip_past_comma (&str
) == FAIL
)
3996 inst
.error
= _("comma expected after register name");
4000 skip_whitespace (str
);
4002 if ( strcmp (str
, "CPSR") == 0
4003 || strcmp (str
, "SPSR") == 0
4004 /* Lower case versions for backwards compatibility. */
4005 || strcmp (str
, "cpsr") == 0
4006 || strcmp (str
, "spsr") == 0)
4009 /* This is for backwards compatibility with older toolchains. */
4010 else if ( strcmp (str
, "cpsr_all") == 0
4011 || strcmp (str
, "spsr_all") == 0)
4015 inst
.error
= _("CPSR or SPSR expected");
4019 if (* str
== 's' || * str
== 'S')
4020 inst
.instruction
|= SPSR_BIT
;
4026 /* Two possible forms:
4027 "{C|S}PSR_<field>, Rm",
4028 "{C|S}PSR_f, #expression". */
4034 skip_whitespace (str
);
4036 if (psr_required_here (& str
) == FAIL
)
4039 if (skip_past_comma (& str
) == FAIL
)
4041 inst
.error
= _("comma missing after psr flags");
4045 skip_whitespace (str
);
4047 if (reg_required_here (& str
, 0) != FAIL
)
4054 if (! is_immediate_prefix (* str
))
4057 _("only a register or immediate value can follow a psr flag");
4064 if (my_get_expression (& inst
.reloc
.exp
, & str
))
4067 _("only a register or immediate value can follow a psr flag");
4071 #if 0 /* The first edition of the ARM architecture manual stated that
4072 writing anything other than the flags with an immediate operation
4073 had UNPREDICTABLE effects. This constraint was removed in the
4074 second edition of the specification. */
4075 if ((cpu_variant
& ARM_EXT_V5
) != ARM_EXT_V5
4076 && inst
.instruction
& ((PSR_c
| PSR_x
| PSR_s
) << PSR_SHIFT
))
4078 inst
.error
= _("immediate value cannot be used to set this field");
4083 inst
.instruction
|= INST_IMMEDIATE
;
4085 if (inst
.reloc
.exp
.X_add_symbol
)
4087 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
4088 inst
.reloc
.pc_rel
= 0;
4092 unsigned value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
4094 if (value
== (unsigned) FAIL
)
4096 inst
.error
= _("invalid constant");
4100 inst
.instruction
|= value
;
4107 /* Long Multiply Parser
4108 UMULL RdLo, RdHi, Rm, Rs
4109 SMULL RdLo, RdHi, Rm, Rs
4110 UMLAL RdLo, RdHi, Rm, Rs
4111 SMLAL RdLo, RdHi, Rm, Rs. */
4117 int rdlo
, rdhi
, rm
, rs
;
4119 /* Only one format "rdlo, rdhi, rm, rs". */
4120 skip_whitespace (str
);
4122 if ((rdlo
= reg_required_here (&str
, 12)) == FAIL
)
4124 inst
.error
= BAD_ARGS
;
4128 if (skip_past_comma (&str
) == FAIL
4129 || (rdhi
= reg_required_here (&str
, 16)) == FAIL
)
4131 inst
.error
= BAD_ARGS
;
4135 if (skip_past_comma (&str
) == FAIL
4136 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4138 inst
.error
= BAD_ARGS
;
4142 /* rdhi, rdlo and rm must all be different. */
4143 if (rdlo
== rdhi
|| rdlo
== rm
|| rdhi
== rm
)
4144 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
4146 if (skip_past_comma (&str
) == FAIL
4147 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
4149 inst
.error
= BAD_ARGS
;
4153 if (rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
)
4155 inst
.error
= BAD_PC
;
4168 /* Only one format "rd, rm, rs". */
4169 skip_whitespace (str
);
4171 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
4173 inst
.error
= BAD_ARGS
;
4179 inst
.error
= BAD_PC
;
4183 if (skip_past_comma (&str
) == FAIL
4184 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4186 inst
.error
= BAD_ARGS
;
4192 inst
.error
= BAD_PC
;
4197 as_tsktsk (_("rd and rm should be different in mul"));
4199 if (skip_past_comma (&str
) == FAIL
4200 || (rm
= reg_required_here (&str
, 8)) == FAIL
)
4202 inst
.error
= BAD_ARGS
;
4208 inst
.error
= BAD_PC
;
4221 /* Only one format "rd, rm, rs, rn". */
4222 skip_whitespace (str
);
4224 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
4226 inst
.error
= BAD_ARGS
;
4232 inst
.error
= BAD_PC
;
4236 if (skip_past_comma (&str
) == FAIL
4237 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4239 inst
.error
= BAD_ARGS
;
4245 inst
.error
= BAD_PC
;
4250 as_tsktsk (_("rd and rm should be different in mla"));
4252 if (skip_past_comma (&str
) == FAIL
4253 || (rd
= reg_required_here (&str
, 8)) == FAIL
4254 || skip_past_comma (&str
) == FAIL
4255 || (rm
= reg_required_here (&str
, 12)) == FAIL
)
4257 inst
.error
= BAD_ARGS
;
4261 if (rd
== REG_PC
|| rm
== REG_PC
)
4263 inst
.error
= BAD_PC
;
4270 /* Expects *str -> the characters "acc0", possibly with leading blanks.
4271 Advances *str to the next non-alphanumeric.
4272 Returns 0, or else FAIL (in which case sets inst.error).
4274 (In a future XScale, there may be accumulators other than zero.
4275 At that time this routine and its callers can be upgraded to suit.) */
4278 accum0_required_here (str
)
4281 static char buff
[128]; /* Note the address is taken. Hence, static. */
4284 int result
= 0; /* The accum number. */
4286 skip_whitespace (p
);
4288 *str
= p
; /* Advance caller's string pointer too. */
4293 *--p
= 0; /* Aap nul into input buffer at non-alnum. */
4295 if (! ( streq (*str
, "acc0") || streq (*str
, "ACC0")))
4297 sprintf (buff
, _("acc0 expected, not '%.100s'"), *str
);
4302 *p
= c
; /* Unzap. */
4303 *str
= p
; /* Caller's string pointer to after match. */
4307 /* Expects **str -> after a comma. May be leading blanks.
4308 Advances *str, recognizing a load mode, and setting inst.instruction.
4309 Returns rn, or else FAIL (in which case may set inst.error
4310 and not advance str)
4312 Note: doesn't know Rd, so no err checks that require such knowledge. */
4315 ld_mode_required_here (string
)
4318 char * str
= * string
;
4322 skip_whitespace (str
);
4328 skip_whitespace (str
);
4330 if ((rn
= reg_required_here (& str
, 16)) == FAIL
)
4333 skip_whitespace (str
);
4339 if (skip_past_comma (& str
) == SUCCESS
)
4341 /* [Rn],... (post inc) */
4342 if (ldst_extend_v4 (&str
) == FAIL
)
4347 skip_whitespace (str
);
4352 inst
.instruction
|= WRITE_BACK
;
4355 inst
.instruction
|= INDEX_UP
| HWOFFSET_IMM
;
4361 if (skip_past_comma (& str
) == FAIL
)
4363 inst
.error
= _("pre-indexed expression expected");
4369 if (ldst_extend_v4 (&str
) == FAIL
)
4372 skip_whitespace (str
);
4374 if (* str
++ != ']')
4376 inst
.error
= _("missing ]");
4380 skip_whitespace (str
);
4385 inst
.instruction
|= WRITE_BACK
;
4389 else if (* str
== '=') /* ldr's "r,=label" syntax */
4390 /* We should never reach here, because <text> = <expression> is
4391 caught gas/read.c read_a_source_file() as a .set operation. */
4393 else /* PC +- 8 bit immediate offset. */
4395 if (my_get_expression (& inst
.reloc
.exp
, & str
))
4398 inst
.instruction
|= HWOFFSET_IMM
; /* The I bit. */
4399 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
4400 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
4401 inst
.reloc
.pc_rel
= 1;
4402 inst
.instruction
|= (REG_PC
<< 16);
4408 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
4414 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
4415 SMLAxy{cond} Rd,Rm,Rs,Rn
4416 SMLAWy{cond} Rd,Rm,Rs,Rn
4417 Error if any register is R15. */
4425 skip_whitespace (str
);
4427 if ((rd
= reg_required_here (& str
, 16)) == FAIL
4428 || skip_past_comma (& str
) == FAIL
4429 || (rm
= reg_required_here (& str
, 0)) == FAIL
4430 || skip_past_comma (& str
) == FAIL
4431 || (rs
= reg_required_here (& str
, 8)) == FAIL
4432 || skip_past_comma (& str
) == FAIL
4433 || (rn
= reg_required_here (& str
, 12)) == FAIL
)
4434 inst
.error
= BAD_ARGS
;
4436 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
|| rn
== REG_PC
)
4437 inst
.error
= BAD_PC
;
4443 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
4444 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
4445 Error if any register is R15.
4446 Warning if Rdlo == Rdhi. */
4452 int rdlo
, rdhi
, rm
, rs
;
4454 skip_whitespace (str
);
4456 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
4457 || skip_past_comma (& str
) == FAIL
4458 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
4459 || skip_past_comma (& str
) == FAIL
4460 || (rm
= reg_required_here (& str
, 0)) == FAIL
4461 || skip_past_comma (& str
) == FAIL
4462 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
4464 inst
.error
= BAD_ARGS
;
4468 if (rdlo
== REG_PC
|| rdhi
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
4470 inst
.error
= BAD_PC
;
4475 as_tsktsk (_("rdhi and rdlo must be different"));
4480 /* ARM V5E (El Segundo) signed-multiply (argument parse)
4481 SMULxy{cond} Rd,Rm,Rs
4482 Error if any register is R15. */
4490 skip_whitespace (str
);
4492 if ((rd
= reg_required_here (& str
, 16)) == FAIL
4493 || skip_past_comma (& str
) == FAIL
4494 || (rm
= reg_required_here (& str
, 0)) == FAIL
4495 || skip_past_comma (& str
) == FAIL
4496 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
4497 inst
.error
= BAD_ARGS
;
4499 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
4500 inst
.error
= BAD_PC
;
4506 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
4507 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
4508 Error if any register is R15. */
4516 skip_whitespace (str
);
4518 if ((rd
= reg_required_here (& str
, 12)) == FAIL
4519 || skip_past_comma (& str
) == FAIL
4520 || (rm
= reg_required_here (& str
, 0)) == FAIL
4521 || skip_past_comma (& str
) == FAIL
4522 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
4523 inst
.error
= BAD_ARGS
;
4525 else if (rd
== REG_PC
|| rm
== REG_PC
|| rn
== REG_PC
)
4526 inst
.error
= BAD_PC
;
4532 /* ARM V5E (el Segundo)
4533 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4534 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4536 These are equivalent to the XScale instructions MAR and MRA,
4537 respectively, when coproc == 0, opcode == 0, and CRm == 0.
4539 Result unpredicatable if Rd or Rn is R15. */
4547 skip_whitespace (str
);
4549 if (co_proc_number (& str
) == FAIL
)
4552 inst
.error
= BAD_ARGS
;
4556 if (skip_past_comma (& str
) == FAIL
4557 || cp_opc_expr (& str
, 4, 4) == FAIL
)
4560 inst
.error
= BAD_ARGS
;
4564 if (skip_past_comma (& str
) == FAIL
4565 || (rd
= reg_required_here (& str
, 12)) == FAIL
)
4568 inst
.error
= BAD_ARGS
;
4572 if (skip_past_comma (& str
) == FAIL
4573 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
4576 inst
.error
= BAD_ARGS
;
4580 /* Unpredictable result if rd or rn is R15. */
4581 if (rd
== REG_PC
|| rn
== REG_PC
)
4583 (_("Warning: instruction unpredictable when using r15"));
4585 if (skip_past_comma (& str
) == FAIL
4586 || cp_reg_required_here (& str
, 0) == FAIL
)
4589 inst
.error
= BAD_ARGS
;
4596 /* ARM V5 count-leading-zeroes instruction (argument parse)
4597 CLZ{<cond>} <Rd>, <Rm>
4598 Condition defaults to COND_ALWAYS.
4599 Error if Rd or Rm are R15. */
4607 skip_whitespace (str
);
4609 if (((rd
= reg_required_here (& str
, 12)) == FAIL
)
4610 || (skip_past_comma (& str
) == FAIL
)
4611 || ((rm
= reg_required_here (& str
, 0)) == FAIL
))
4612 inst
.error
= BAD_ARGS
;
4614 else if (rd
== REG_PC
|| rm
== REG_PC
)
4615 inst
.error
= BAD_PC
;
4621 /* ARM V5 (argument parse)
4622 LDC2{L} <coproc>, <CRd>, <addressing mode>
4623 STC2{L} <coproc>, <CRd>, <addressing mode>
4624 Instruction is not conditional, and has 0xf in the condition field.
4625 Otherwise, it's the same as LDC/STC. */
4631 skip_whitespace (str
);
4633 if (co_proc_number (& str
) == FAIL
)
4636 inst
.error
= BAD_ARGS
;
4638 else if (skip_past_comma (& str
) == FAIL
4639 || cp_reg_required_here (& str
, 12) == FAIL
)
4642 inst
.error
= BAD_ARGS
;
4644 else if (skip_past_comma (& str
) == FAIL
4645 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
4648 inst
.error
= BAD_ARGS
;
4654 /* ARM V5 (argument parse)
4655 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
4656 Instruction is not conditional, and has 0xf in the condition field.
4657 Otherwise, it's the same as CDP. */
4663 skip_whitespace (str
);
4665 if (co_proc_number (& str
) == FAIL
)
4668 inst
.error
= BAD_ARGS
;
4672 if (skip_past_comma (& str
) == FAIL
4673 || cp_opc_expr (& str
, 20,4) == FAIL
)
4676 inst
.error
= BAD_ARGS
;
4680 if (skip_past_comma (& str
) == FAIL
4681 || cp_reg_required_here (& str
, 12) == FAIL
)
4684 inst
.error
= BAD_ARGS
;
4688 if (skip_past_comma (& str
) == FAIL
4689 || cp_reg_required_here (& str
, 16) == FAIL
)
4692 inst
.error
= BAD_ARGS
;
4696 if (skip_past_comma (& str
) == FAIL
4697 || cp_reg_required_here (& str
, 0) == FAIL
)
4700 inst
.error
= BAD_ARGS
;
4704 if (skip_past_comma (& str
) == SUCCESS
)
4706 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
4709 inst
.error
= BAD_ARGS
;
4717 /* ARM V5 (argument parse)
4718 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4719 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4720 Instruction is not conditional, and has 0xf in the condition field.
4721 Otherwise, it's the same as MCR/MRC. */
4727 skip_whitespace (str
);
4729 if (co_proc_number (& str
) == FAIL
)
4732 inst
.error
= BAD_ARGS
;
4736 if (skip_past_comma (& str
) == FAIL
4737 || cp_opc_expr (& str
, 21, 3) == FAIL
)
4740 inst
.error
= BAD_ARGS
;
4744 if (skip_past_comma (& str
) == FAIL
4745 || reg_required_here (& str
, 12) == FAIL
)
4748 inst
.error
= BAD_ARGS
;
4752 if (skip_past_comma (& str
) == FAIL
4753 || cp_reg_required_here (& str
, 16) == FAIL
)
4756 inst
.error
= BAD_ARGS
;
4760 if (skip_past_comma (& str
) == FAIL
4761 || cp_reg_required_here (& str
, 0) == FAIL
)
4764 inst
.error
= BAD_ARGS
;
4768 if (skip_past_comma (& str
) == SUCCESS
)
4770 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
4773 inst
.error
= BAD_ARGS
;
4781 /* ARM v5TEJ. Jump to Jazelle code. */
4788 skip_whitespace (str
);
4790 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
4792 inst
.error
= BAD_ARGS
;
4796 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
4798 as_tsktsk (_("use of r15 in bxj is not really useful"));
4803 /* ARM V6 umaal (argument parse). */
4810 int rdlo
, rdhi
, rm
, rs
;
4812 skip_whitespace (str
);
4813 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
4814 || skip_past_comma (& str
) == FAIL
4815 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
4816 || skip_past_comma (& str
) == FAIL
4817 || (rm
= reg_required_here (& str
, 0)) == FAIL
4818 || skip_past_comma (& str
) == FAIL
4819 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
4821 inst
.error
= BAD_ARGS
;
4825 if (rdlo
== REG_PC
|| rdhi
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
4827 inst
.error
= BAD_PC
;
4834 /* ARM V6 strex (argument parse). */
4842 /* Parse Rd, Rm,. */
4843 skip_whitespace (str
);
4844 if ((rd
= reg_required_here (& str
, 12)) == FAIL
4845 || skip_past_comma (& str
) == FAIL
4846 || (rm
= reg_required_here (& str
, 0)) == FAIL
4847 || skip_past_comma (& str
) == FAIL
)
4849 inst
.error
= BAD_ARGS
;
4852 if (rd
== REG_PC
|| rm
== REG_PC
)
4854 inst
.error
= BAD_PC
;
4859 inst
.error
= _("Rd equal to Rm or Rn yields unpredictable results");
4863 /* Skip past '['. */
4864 if ((strlen (str
) >= 1)
4865 && strncmp (str
, "[", 1) == 0)
4867 skip_whitespace (str
);
4870 if ((rn
= reg_required_here (& str
, 16)) == FAIL
)
4872 inst
.error
= BAD_ARGS
;
4875 else if (rn
== REG_PC
)
4877 inst
.error
= BAD_PC
;
4882 inst
.error
= _("Rd equal to Rm or Rn yields unpredictable results");
4885 skip_whitespace (str
);
4887 /* Skip past ']'. */
4888 if ((strlen (str
) >= 1)
4889 && strncmp (str
, "]", 1) == 0)
4895 /* ARM V6 ssat (argument parse). */
4901 do_sat (&str
, /*bias=*/-1);
4905 /* ARM V6 usat (argument parse). */
4911 do_sat (&str
, /*bias=*/0);
4923 skip_whitespace (*str
);
4925 /* Parse <Rd>, field. */
4926 if ((rd
= reg_required_here (str
, 12)) == FAIL
4927 || skip_past_comma (str
) == FAIL
)
4929 inst
.error
= BAD_ARGS
;
4934 inst
.error
= BAD_PC
;
4938 /* Parse #<immed>, field. */
4939 if (is_immediate_prefix (**str
))
4943 inst
.error
= _("immediate expression expected");
4946 if (my_get_expression (&expr
, str
))
4948 inst
.error
= _("bad expression");
4951 if (expr
.X_op
!= O_constant
)
4953 inst
.error
= _("constant expression expected");
4956 if (expr
.X_add_number
+ bias
< 0
4957 || expr
.X_add_number
+ bias
> 31)
4959 inst
.error
= _("immediate value out of range");
4962 inst
.instruction
|= (expr
.X_add_number
+ bias
) << 16;
4963 if (skip_past_comma (str
) == FAIL
)
4965 inst
.error
= BAD_ARGS
;
4969 /* Parse <Rm> field. */
4970 if ((rm
= reg_required_here (str
, 0)) == FAIL
)
4972 inst
.error
= BAD_ARGS
;
4977 inst
.error
= BAD_PC
;
4981 if (skip_past_comma (str
) == SUCCESS
)
4982 decode_shift (str
, SHIFT_LSL_OR_ASR_IMMEDIATE
);
4985 /* ARM V6 ssat16 (argument parse). */
4991 do_sat16 (&str
, /*bias=*/-1);
4999 do_sat16 (&str
, /*bias=*/0);
5004 do_sat16 (str
, bias
)
5011 skip_whitespace (*str
);
5013 /* Parse the <Rd> field. */
5014 if ((rd
= reg_required_here (str
, 12)) == FAIL
5015 || skip_past_comma (str
) == FAIL
)
5017 inst
.error
= BAD_ARGS
;
5022 inst
.error
= BAD_PC
;
5026 /* Parse #<immed>, field. */
5027 if (is_immediate_prefix (**str
))
5031 inst
.error
= _("immediate expression expected");
5034 if (my_get_expression (&expr
, str
))
5036 inst
.error
= _("bad expression");
5039 if (expr
.X_op
!= O_constant
)
5041 inst
.error
= _("constant expression expected");
5044 if (expr
.X_add_number
+ bias
< 0
5045 || expr
.X_add_number
+ bias
> 15)
5047 inst
.error
= _("immediate value out of range");
5050 inst
.instruction
|= (expr
.X_add_number
+ bias
) << 16;
5051 if (skip_past_comma (str
) == FAIL
)
5053 inst
.error
= BAD_ARGS
;
5057 /* Parse <Rm> field. */
5058 if ((rm
= reg_required_here (str
, 0)) == FAIL
)
5060 inst
.error
= BAD_ARGS
;
5065 inst
.error
= BAD_PC
;
5070 /* ARM V6 srs (argument parse). */
5077 skip_whitespace (str
);
5078 exclam
= strchr (str
, '!');
5086 inst
.instruction
|= WRITE_BACK
;
5092 /* ARM V6 SMMUL (argument parse). */
5100 skip_whitespace (str
);
5101 if ((rd
= reg_required_here (&str
, 16)) == FAIL
5102 || skip_past_comma (&str
) == FAIL
5103 || (rm
= reg_required_here (&str
, 0)) == FAIL
5104 || skip_past_comma (&str
) == FAIL
5105 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
5107 inst
.error
= BAD_ARGS
;
5115 inst
.error
= BAD_PC
;
5123 /* ARM V6 SMLALD (argument parse). */
5129 int rdlo
, rdhi
, rm
, rs
;
5130 skip_whitespace (str
);
5131 if ((rdlo
= reg_required_here (&str
, 12)) == FAIL
5132 || skip_past_comma (&str
) == FAIL
5133 || (rdhi
= reg_required_here (&str
, 16)) == FAIL
5134 || skip_past_comma (&str
) == FAIL
5135 || (rm
= reg_required_here (&str
, 0)) == FAIL
5136 || skip_past_comma (&str
) == FAIL
5137 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
5139 inst
.error
= BAD_ARGS
;
5148 inst
.error
= BAD_PC
;
5155 /* ARM V6 SMLAD (argument parse). Signed multiply accumulate dual.
5156 smlad{x}{<cond>} Rd, Rm, Rs, Rn */
5164 skip_whitespace (str
);
5165 if ((rd
= reg_required_here (&str
, 16)) == FAIL
5166 || skip_past_comma (&str
) == FAIL
5167 || (rm
= reg_required_here (&str
, 0)) == FAIL
5168 || skip_past_comma (&str
) == FAIL
5169 || (rs
= reg_required_here (&str
, 8)) == FAIL
5170 || skip_past_comma (&str
) == FAIL
5171 || (rn
= reg_required_here (&str
, 12)) == FAIL
)
5173 inst
.error
= BAD_ARGS
;
5182 inst
.error
= BAD_PC
;
5189 /* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
5190 preserving the other bits.
5192 setend <endian_specifier>, where <endian_specifier> is either
5199 if (do_endian_specifier (str
))
5200 inst
.instruction
|= 0x200;
5203 /* Returns true if the endian-specifier indicates big-endianness. */
5206 do_endian_specifier (str
)
5211 skip_whitespace (str
);
5212 if (strlen (str
) < 2)
5213 inst
.error
= _("missing endian specifier");
5214 else if (strncasecmp (str
, "BE", 2) == 0)
5219 else if (strncasecmp (str
, "LE", 2) == 0)
5222 inst
.error
= _("valid endian specifiers are be or le");
5231 SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
5232 Condition defaults to COND_ALWAYS.
5233 Error if any register uses R15. */
5241 int rotation_clear_mask
= 0xfffff3ff;
5242 int rotation_eight_mask
= 0x00000400;
5243 int rotation_sixteen_mask
= 0x00000800;
5244 int rotation_twenty_four_mask
= 0x00000c00;
5246 skip_whitespace (str
);
5247 if ((rd
= reg_required_here (&str
, 12)) == FAIL
5248 || skip_past_comma (&str
) == FAIL
5249 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
5251 inst
.error
= BAD_ARGS
;
5255 else if (rd
== REG_PC
|| rm
== REG_PC
)
5257 inst
.error
= BAD_PC
;
5261 /* Zero out the rotation field. */
5262 inst
.instruction
&= rotation_clear_mask
;
5264 /* Check for lack of optional rotation field. */
5265 if (skip_past_comma (&str
) == FAIL
)
5271 /* Move past 'ROR'. */
5272 skip_whitespace (str
);
5273 if (strncasecmp (str
, "ROR", 3) == 0)
5277 inst
.error
= _("missing rotation field after comma");
5281 /* Get the immediate constant. */
5282 skip_whitespace (str
);
5283 if (is_immediate_prefix (* str
))
5287 inst
.error
= _("immediate expression expected");
5291 if (my_get_expression (&expr
, &str
))
5293 inst
.error
= _("bad expression");
5297 if (expr
.X_op
!= O_constant
)
5299 inst
.error
= _("constant expression expected");
5303 switch (expr
.X_add_number
)
5306 /* Rotation field has already been zeroed. */
5309 inst
.instruction
|= rotation_eight_mask
;
5313 inst
.instruction
|= rotation_sixteen_mask
;
5317 inst
.instruction
|= rotation_twenty_four_mask
;
5321 inst
.error
= _("rotation can be 8, 16, 24 or 0 when field is ommited");
5329 /* ARM V6 SXTAH extracts a 16-bit value from a register, sign
5330 extends it to 32-bits, and adds the result to a value in another
5331 register. You can specify a rotation by 0, 8, 16, or 24 bits
5332 before extracting the 16-bit value.
5333 SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
5334 Condition defaults to COND_ALWAYS.
5335 Error if any register uses R15. */
5343 int rotation_clear_mask
= 0xfffff3ff;
5344 int rotation_eight_mask
= 0x00000400;
5345 int rotation_sixteen_mask
= 0x00000800;
5346 int rotation_twenty_four_mask
= 0x00000c00;
5348 skip_whitespace (str
);
5349 if ((rd
= reg_required_here (&str
, 12)) == FAIL
5350 || skip_past_comma (&str
) == FAIL
5351 || (rn
= reg_required_here (&str
, 16)) == FAIL
5352 || skip_past_comma (&str
) == FAIL
5353 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
5355 inst
.error
= BAD_ARGS
;
5359 else if (rd
== REG_PC
|| rn
== REG_PC
|| rm
== REG_PC
)
5361 inst
.error
= BAD_PC
;
5365 /* Zero out the rotation field. */
5366 inst
.instruction
&= rotation_clear_mask
;
5368 /* Check for lack of optional rotation field. */
5369 if (skip_past_comma (&str
) == FAIL
)
5375 /* Move past 'ROR'. */
5376 skip_whitespace (str
);
5377 if (strncasecmp (str
, "ROR", 3) == 0)
5381 inst
.error
= _("missing rotation field after comma");
5385 /* Get the immediate constant. */
5386 skip_whitespace (str
);
5387 if (is_immediate_prefix (* str
))
5391 inst
.error
= _("immediate expression expected");
5395 if (my_get_expression (&expr
, &str
))
5397 inst
.error
= _("bad expression");
5401 if (expr
.X_op
!= O_constant
)
5403 inst
.error
= _("constant expression expected");
5407 switch (expr
.X_add_number
)
5410 /* Rotation field has already been zeroed. */
5414 inst
.instruction
|= rotation_eight_mask
;
5418 inst
.instruction
|= rotation_sixteen_mask
;
5422 inst
.instruction
|= rotation_twenty_four_mask
;
5426 inst
.error
= _("rotation can be 8, 16, 24 or 0 when field is ommited");
5435 /* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
5436 word at the specified address and the following word
5438 Unconditionally executed.
5448 skip_whitespace (str
);
5450 if ((rn
= reg_required_here (&str
, 16)) == FAIL
)
5455 inst
.error
= BAD_PC
;
5459 skip_whitespace (str
);
5463 inst
.instruction
|= WRITE_BACK
;
5469 /* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
5470 register (argument parse).
5472 Condition defaults to COND_ALWAYS.
5473 Error if Rd or Rm are R15. */
5481 skip_whitespace (str
);
5483 if ((rd
= reg_required_here (&str
, 12)) == FAIL
5484 || skip_past_comma (&str
) == FAIL
5485 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
5486 inst
.error
= BAD_ARGS
;
5488 else if (rd
== REG_PC
|| rm
== REG_PC
)
5489 inst
.error
= BAD_PC
;
5495 /* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
5496 QADD16{<cond>} <Rd>, <Rn>, <Rm>
5497 Condition defaults to COND_ALWAYS.
5498 Error if Rd, Rn or Rm are R15. */
5506 skip_whitespace (str
);
5508 if ((rd
= reg_required_here (&str
, 12)) == FAIL
5509 || skip_past_comma (&str
) == FAIL
5510 || (rn
= reg_required_here (&str
, 16)) == FAIL
5511 || skip_past_comma (&str
) == FAIL
5512 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
5513 inst
.error
= BAD_ARGS
;
5515 else if (rd
== REG_PC
|| rm
== REG_PC
|| rn
== REG_PC
)
5516 inst
.error
= BAD_PC
;
5522 /* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
5523 PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
5524 Condition defaults to COND_ALWAYS.
5525 Error if Rd, Rn or Rm are R15. */
5531 do_pkh_core (str
, SHIFT_LSL_IMMEDIATE
);
5534 /* ARM V6 PKHTB (Argument Parse). */
5540 do_pkh_core (str
, SHIFT_ASR_IMMEDIATE
);
5544 do_pkh_core (str
, shift
)
5550 skip_whitespace (str
);
5551 if (((rd
= reg_required_here (&str
, 12)) == FAIL
)
5552 || (skip_past_comma (&str
) == FAIL
)
5553 || ((rn
= reg_required_here (&str
, 16)) == FAIL
)
5554 || (skip_past_comma (&str
) == FAIL
)
5555 || ((rm
= reg_required_here (&str
, 0)) == FAIL
))
5557 inst
.error
= BAD_ARGS
;
5561 else if (rd
== REG_PC
|| rn
== REG_PC
|| rm
== REG_PC
)
5563 inst
.error
= BAD_PC
;
5567 /* Check for optional shift immediate constant. */
5568 if (skip_past_comma (&str
) == FAIL
)
5570 if (shift
== SHIFT_ASR_IMMEDIATE
)
5572 /* If the shift specifier is ommited, turn the instruction
5573 into pkhbt rd, rm, rn. First, switch the instruction
5574 code, and clear the rn and rm fields. */
5575 inst
.instruction
&= 0xfff0f010;
5576 /* Now, re-encode the registers. */
5577 inst
.instruction
|= (rm
<< 16) | rn
;
5582 decode_shift (&str
, shift
);
5585 /* ARM V6 Load Register Exclusive instruction (argument parse).
5586 LDREX{<cond>} <Rd, [<Rn>]
5587 Condition defaults to COND_ALWAYS.
5588 Error if Rd or Rn are R15.
5589 See ARMARMv6 A4.1.27: LDREX. */
5598 skip_whitespace (str
);
5601 if (((rd
= reg_required_here (&str
, 12)) == FAIL
)
5602 || (skip_past_comma (&str
) == FAIL
))
5604 inst
.error
= BAD_ARGS
;
5607 else if (rd
== REG_PC
)
5609 inst
.error
= BAD_PC
;
5612 skip_whitespace (str
);
5614 /* Skip past '['. */
5615 if ((strlen (str
) >= 1)
5616 &&strncmp (str
, "[", 1) == 0)
5618 skip_whitespace (str
);
5621 if ((rn
= reg_required_here (&str
, 16)) == FAIL
)
5623 inst
.error
= BAD_ARGS
;
5626 else if (rn
== REG_PC
)
5628 inst
.error
= BAD_PC
;
5631 skip_whitespace (str
);
5633 /* Skip past ']'. */
5634 if ((strlen (str
) >= 1)
5635 && strncmp (str
, "]", 1) == 0)
5641 /* ARM V6 change processor state instruction (argument parse)
5642 CPS, CPSIE, CSPID . */
5656 do_cps_flags (&str
, /*thumb_p=*/0);
5658 if (skip_past_comma (&str
) == SUCCESS
)
5660 skip_whitespace (str
);
5672 skip_whitespace (*str
);
5674 if (! is_immediate_prefix (**str
))
5676 inst
.error
= _("immediate expression expected");
5680 (*str
)++; /* Strip off the immediate signifier. */
5681 if (my_get_expression (&expr
, str
))
5683 inst
.error
= _("bad expression");
5687 if (expr
.X_op
!= O_constant
)
5689 inst
.error
= _("constant expression expected");
5693 /* The mode is a 5 bit field. Valid values are 0-31. */
5694 if (((unsigned) expr
.X_add_number
) > 31
5695 || (inst
.reloc
.exp
.X_add_number
) < 0)
5697 inst
.error
= _("invalid constant");
5701 inst
.instruction
|= expr
.X_add_number
;
5705 do_cps_flags (str
, thumb_p
)
5711 unsigned long arm_value
;
5712 unsigned long thumb_value
;
5714 static struct cps_flag flag_table
[] = {
5722 skip_whitespace (*str
);
5724 /* Get the a, f and i flags. */
5725 while (**str
&& **str
!= ',')
5728 struct cps_flag
*q
= flag_table
+ sizeof (flag_table
)/sizeof (*p
);
5729 for (p
= flag_table
; p
< q
; ++p
)
5730 if (strncasecmp (*str
, &p
->character
, 1) == 0)
5732 inst
.instruction
|= (thumb_p
? p
->thumb_value
: p
->arm_value
);
5738 inst
.error
= _("unrecognized flag");
5744 inst
.error
= _("no 'a', 'i', or 'f' flags for 'cps'");
5747 /* THUMB V5 breakpoint instruction (argument parse)
5755 unsigned long number
;
5757 skip_whitespace (str
);
5759 /* Allow optional leading '#'. */
5760 if (is_immediate_prefix (*str
))
5763 memset (& expr
, '\0', sizeof (expr
));
5764 if (my_get_expression (& expr
, & str
)
5765 || (expr
.X_op
!= O_constant
5766 /* As a convenience we allow 'bkpt' without an operand. */
5767 && expr
.X_op
!= O_absent
))
5769 inst
.error
= _("bad expression");
5773 number
= expr
.X_add_number
;
5775 /* Check it fits an 8 bit unsigned. */
5776 if (number
!= (number
& 0xff))
5778 inst
.error
= _("immediate value out of range");
5782 inst
.instruction
|= number
;
5787 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
5788 Expects inst.instruction is set for BLX(1).
5789 Note: this is cloned from do_branch, and the reloc changed to be a
5790 new one that can cope with setting one extra bit (the H bit). */
5796 if (my_get_expression (& inst
.reloc
.exp
, & str
))
5803 /* ScottB: February 5, 1998 */
5804 /* Check to see of PLT32 reloc required for the instruction. */
5806 /* arm_parse_reloc() works on input_line_pointer.
5807 We actually want to parse the operands to the branch instruction
5808 passed in 'str'. Save the input pointer and restore it later. */
5809 save_in
= input_line_pointer
;
5810 input_line_pointer
= str
;
5812 if (inst
.reloc
.exp
.X_op
== O_symbol
5814 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
5816 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
5817 inst
.reloc
.pc_rel
= 0;
5818 /* Modify str to point to after parsed operands, otherwise
5819 end_of_line() will complain about the (PLT) left in str. */
5820 str
= input_line_pointer
;
5824 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
5825 inst
.reloc
.pc_rel
= 1;
5828 input_line_pointer
= save_in
;
5831 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
5832 inst
.reloc
.pc_rel
= 1;
5833 #endif /* OBJ_ELF */
5838 /* ARM V5 branch-link-exchange instruction (argument parse)
5839 BLX <target_addr> ie BLX(1)
5840 BLX{<condition>} <Rm> ie BLX(2)
5841 Unfortunately, there are two different opcodes for this mnemonic.
5842 So, the insns[].value is not used, and the code here zaps values
5843 into inst.instruction.
5844 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
5853 skip_whitespace (mystr
);
5854 rm
= reg_required_here (& mystr
, 0);
5856 /* The above may set inst.error. Ignore his opinion. */
5861 /* Arg is a register.
5862 Use the condition code our caller put in inst.instruction.
5863 Pass ourselves off as a BX with a funny opcode. */
5864 inst
.instruction
|= 0x012fff30;
5869 /* This must be is BLX <target address>, no condition allowed. */
5870 if (inst
.instruction
!= COND_ALWAYS
)
5872 inst
.error
= BAD_COND
;
5876 inst
.instruction
= 0xfafffffe;
5878 /* Process like a B/BL, but with a different reloc.
5879 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
5884 /* ARM V5 Thumb BLX (argument parse)
5885 BLX <target_addr> which is BLX(1)
5886 BLX <Rm> which is BLX(2)
5887 Unfortunately, there are two different opcodes for this mnemonic.
5888 So, the tinsns[].value is not used, and the code here zaps values
5889 into inst.instruction. */
5898 skip_whitespace (mystr
);
5899 inst
.instruction
= 0x4780;
5901 /* Note that this call is to the ARM register recognizer. BLX(2)
5902 uses the ARM register space, not the Thumb one, so a call to
5903 thumb_reg() would be wrong. */
5904 rm
= reg_required_here (& mystr
, 3);
5909 /* It's BLX(2). The .instruction was zapped with rm & is final. */
5914 /* No ARM register. This must be BLX(1). Change the .instruction. */
5915 inst
.instruction
= 0xf7ffeffe;
5918 if (my_get_expression (& inst
.reloc
.exp
, & mystr
))
5921 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BLX
;
5922 inst
.reloc
.pc_rel
= 1;
5925 end_of_line (mystr
);
5928 /* ARM V5 breakpoint instruction (argument parse)
5929 BKPT <16 bit unsigned immediate>
5930 Instruction is not conditional.
5931 The bit pattern given in insns[] has the COND_ALWAYS condition,
5932 and it is an error if the caller tried to override that. */
5939 unsigned long number
;
5941 skip_whitespace (str
);
5943 /* Allow optional leading '#'. */
5944 if (is_immediate_prefix (* str
))
5947 memset (& expr
, '\0', sizeof (expr
));
5949 if (my_get_expression (& expr
, & str
)
5950 || (expr
.X_op
!= O_constant
5951 /* As a convenience we allow 'bkpt' without an operand. */
5952 && expr
.X_op
!= O_absent
))
5954 inst
.error
= _("bad expression");
5958 number
= expr
.X_add_number
;
5960 /* Check it fits a 16 bit unsigned. */
5961 if (number
!= (number
& 0xffff))
5963 inst
.error
= _("immediate value out of range");
5967 /* Top 12 of 16 bits to bits 19:8. */
5968 inst
.instruction
|= (number
& 0xfff0) << 4;
5970 /* Bottom 4 of 16 bits to bits 3:0. */
5971 inst
.instruction
|= number
& 0xf;
5976 /* THUMB CPS instruction (argument parse). */
5982 do_cps_flags (&str
, /*thumb_p=*/1);
5986 /* THUMB CPY instruction (argument parse). */
5992 thumb_mov_compare (str
, THUMB_CPY
);
5995 /* THUMB SETEND instruction (argument parse). */
6001 if (do_endian_specifier (str
))
6002 inst
.instruction
|= 0x8;
6005 static unsigned long check_iwmmxt_insn
PARAMS ((char *, enum iwmmxt_insn_type
, int));
6007 /* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
6009 static unsigned long
6010 check_iwmmxt_insn (str
, insn_type
, immediate_size
)
6012 enum iwmmxt_insn_type insn_type
;
6016 const char * inst_error
;
6018 unsigned long number
;
6020 inst_error
= inst
.error
;
6022 inst
.error
= BAD_ARGS
;
6023 skip_whitespace (str
);
6028 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
6033 if ((wreg_required_here (&str
, 0, IWMMXT_REG_WR
)) == FAIL
)
6038 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
6039 || skip_past_comma (&str
) == FAIL
6040 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
))
6045 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
6046 || skip_past_comma (&str
) == FAIL
6047 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6048 || skip_past_comma (&str
) == FAIL
6049 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
))
6054 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
6055 || skip_past_comma (&str
) == FAIL
6056 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6057 || skip_past_comma (&str
) == FAIL
6058 || wreg_required_here (&str
, 0, IWMMXT_REG_WCG
) == FAIL
))
6063 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6064 || skip_past_comma (&str
) == FAIL
6065 || reg_required_here (&str
, 12) == FAIL
))
6070 if ((reg_required_here (&str
, 12) == FAIL
6071 || skip_past_comma (&str
) == FAIL
6072 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
))
6077 if ((wreg_required_here (&str
, 5, IWMMXT_REG_WR
) == FAIL
6078 || skip_past_comma (&str
) == FAIL
6079 || reg_required_here (&str
, 0) == FAIL
6080 || skip_past_comma (&str
) == FAIL
6081 || reg_required_here (&str
, 12) == FAIL
))
6086 if ((wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
6087 || skip_past_comma (&str
) == FAIL
6088 || reg_required_here (&str
, 12) == FAIL
6089 || skip_past_comma (&str
) == FAIL
6090 || reg_required_here (&str
, 16) == FAIL
))
6095 if ((reg_required_here (&str
, 12) == FAIL
6096 || skip_past_comma (&str
) == FAIL
6097 || reg_required_here (&str
, 16) == FAIL
6098 || skip_past_comma (&str
) == FAIL
6099 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
))
6104 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WC
) == FAIL
6105 || skip_past_comma (&str
) == FAIL
6106 || reg_required_here (&str
, 12) == FAIL
))
6111 if ((reg_required_here (&str
, 12) == FAIL
6112 || skip_past_comma (&str
) == FAIL
6113 || wreg_required_here (&str
, 16, IWMMXT_REG_WC
) == FAIL
))
6118 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6119 || skip_past_comma (&str
) == FAIL
6120 || reg_required_here (&str
, 12) == FAIL
6121 || skip_past_comma (&str
) == FAIL
))
6126 if ((reg_required_here (&str
, 12) == FAIL
6127 || skip_past_comma (&str
) == FAIL
))
6132 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
6133 || skip_past_comma (&str
) == FAIL
6134 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6135 || skip_past_comma (&str
) == FAIL
6136 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
6137 || skip_past_comma (&str
) == FAIL
))
6142 if ((reg_required_here (&str
, 12) == FAIL
6143 || skip_past_comma (&str
) == FAIL
6144 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6145 || skip_past_comma (&str
) == FAIL
))
6150 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
6151 || skip_past_comma (&str
) == FAIL
6152 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6153 || skip_past_comma (&str
) == FAIL
))
6158 if (immediate_size
== 0)
6161 inst
.error
= inst_error
;
6166 skip_whitespace (str
);
6168 /* Allow optional leading '#'. */
6169 if (is_immediate_prefix (* str
))
6172 memset (& expr
, '\0', sizeof (expr
));
6174 if (my_get_expression (& expr
, & str
) || (expr
.X_op
!= O_constant
))
6176 inst
.error
= _("bad or missing expression");
6180 number
= expr
.X_add_number
;
6182 if (number
!= (number
& immediate_size
))
6184 inst
.error
= _("immediate value out of range");
6188 inst
.error
= inst_error
;
6194 do_iwmmxt_byte_addr (str
)
6197 int op
= (inst
.instruction
& 0x300) >> 8;
6200 inst
.instruction
&= ~0x300;
6201 inst
.instruction
|= (op
& 1) << 22 | (op
& 2) << 7;
6203 skip_whitespace (str
);
6205 if ((reg
= wreg_required_here (&str
, 12, IWMMXT_REG_WR_OR_WC
)) == FAIL
6206 || skip_past_comma (& str
) == FAIL
6207 || cp_byte_address_required_here (&str
) == FAIL
)
6210 inst
.error
= BAD_ARGS
;
6215 if (wc_register (reg
))
6217 as_bad (_("non-word size not supported with control register"));
6218 inst
.instruction
|= 0xf0000100;
6219 inst
.instruction
&= ~0x00400000;
6224 do_iwmmxt_tandc (str
)
6229 reg
= check_iwmmxt_insn (str
, check_rd
, 0);
6231 if (reg
!= REG_PC
&& !inst
.error
)
6232 inst
.error
= _("only r15 allowed here");
6236 do_iwmmxt_tbcst (str
)
6239 check_iwmmxt_insn (str
, check_tbcst
, 0);
6243 do_iwmmxt_textrc (str
)
6246 unsigned long number
;
6248 if ((number
= check_iwmmxt_insn (str
, check_textrc
, 7)) == (unsigned long) FAIL
)
6251 inst
.instruction
|= number
& 0x7;
6255 do_iwmmxt_textrm (str
)
6258 unsigned long number
;
6260 if ((number
= check_iwmmxt_insn (str
, check_textrm
, 7)) == (unsigned long) FAIL
)
6263 inst
.instruction
|= number
& 0x7;
6267 do_iwmmxt_tinsr (str
)
6270 unsigned long number
;
6272 if ((number
= check_iwmmxt_insn (str
, check_tinsr
, 7)) == (unsigned long) FAIL
)
6275 inst
.instruction
|= number
& 0x7;
6279 do_iwmmxt_tmcr (str
)
6282 check_iwmmxt_insn (str
, check_tmcr
, 0);
6286 do_iwmmxt_tmcrr (str
)
6289 check_iwmmxt_insn (str
, check_tmcrr
, 0);
6293 do_iwmmxt_tmia (str
)
6296 check_iwmmxt_insn (str
, check_tmia
, 0);
6300 do_iwmmxt_tmovmsk (str
)
6303 check_iwmmxt_insn (str
, check_tmovmsk
, 0);
6307 do_iwmmxt_tmrc (str
)
6310 check_iwmmxt_insn (str
, check_tmrc
, 0);
6314 do_iwmmxt_tmrrc (str
)
6317 check_iwmmxt_insn (str
, check_tmrrc
, 0);
6321 do_iwmmxt_torc (str
)
6324 check_iwmmxt_insn (str
, check_rd
, 0);
6328 do_iwmmxt_waligni (str
)
6331 unsigned long number
;
6333 if ((number
= check_iwmmxt_insn (str
, check_waligni
, 7)) == (unsigned long) FAIL
)
6336 inst
.instruction
|= ((number
& 0x7) << 20);
6340 do_iwmmxt_wmov (str
)
6343 if (check_iwmmxt_insn (str
, check_wrwr
, 0) == (unsigned long) FAIL
)
6346 inst
.instruction
|= ((inst
.instruction
>> 16) & 0xf);
6350 do_iwmmxt_word_addr (str
)
6353 int op
= (inst
.instruction
& 0x300) >> 8;
6356 inst
.instruction
&= ~0x300;
6357 inst
.instruction
|= (op
& 1) << 22 | (op
& 2) << 7;
6359 skip_whitespace (str
);
6361 if ((reg
= wreg_required_here (&str
, 12, IWMMXT_REG_WR_OR_WC
)) == FAIL
6362 || skip_past_comma (& str
) == FAIL
6363 || cp_address_required_here (& str
, CP_WB_OK
) == FAIL
)
6366 inst
.error
= BAD_ARGS
;
6371 if (wc_register (reg
))
6373 if ((inst
.instruction
& COND_MASK
) != COND_ALWAYS
)
6374 as_bad (_("conditional execution not supported with control register"));
6376 as_bad (_("non-word size not supported with control register"));
6377 inst
.instruction
|= 0xf0000100;
6378 inst
.instruction
&= ~0x00400000;
6383 do_iwmmxt_wrwr (str
)
6386 check_iwmmxt_insn (str
, check_wrwr
, 0);
6390 do_iwmmxt_wrwrwcg (str
)
6393 check_iwmmxt_insn (str
, check_wrwrwcg
, 0);
6397 do_iwmmxt_wrwrwr (str
)
6400 check_iwmmxt_insn (str
, check_wrwrwr
, 0);
6404 do_iwmmxt_wshufh (str
)
6407 unsigned long number
;
6409 if ((number
= check_iwmmxt_insn (str
, check_wshufh
, 0xff)) == (unsigned long) FAIL
)
6412 inst
.instruction
|= ((number
& 0xf0) << 16) | (number
& 0xf);
6416 do_iwmmxt_wzero (str
)
6419 if (check_iwmmxt_insn (str
, check_wr
, 0) == (unsigned long) FAIL
)
6422 inst
.instruction
|= ((inst
.instruction
& 0xf) << 12) | ((inst
.instruction
& 0xf) << 16);
6425 /* Xscale multiply-accumulate (argument parse)
6428 MIAxycc acc0,Rm,Rs. */
6437 if (accum0_required_here (& str
) == FAIL
)
6438 inst
.error
= ERR_NO_ACCUM
;
6440 else if (skip_past_comma (& str
) == FAIL
6441 || (rm
= reg_required_here (& str
, 0)) == FAIL
)
6442 inst
.error
= BAD_ARGS
;
6444 else if (skip_past_comma (& str
) == FAIL
6445 || (rs
= reg_required_here (& str
, 12)) == FAIL
)
6446 inst
.error
= BAD_ARGS
;
6448 /* inst.instruction has now been zapped with both rm and rs. */
6449 else if (rm
== REG_PC
|| rs
== REG_PC
)
6450 inst
.error
= BAD_PC
; /* Undefined result if rm or rs is R15. */
6456 /* Xscale move-accumulator-register (argument parse)
6458 MARcc acc0,RdLo,RdHi. */
6466 if (accum0_required_here (& str
) == FAIL
)
6467 inst
.error
= ERR_NO_ACCUM
;
6469 else if (skip_past_comma (& str
) == FAIL
6470 || (rdlo
= reg_required_here (& str
, 12)) == FAIL
)
6471 inst
.error
= BAD_ARGS
;
6473 else if (skip_past_comma (& str
) == FAIL
6474 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
6475 inst
.error
= BAD_ARGS
;
6477 /* inst.instruction has now been zapped with both rdlo and rdhi. */
6478 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
6479 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
6485 /* Xscale move-register-accumulator (argument parse)
6487 MRAcc RdLo,RdHi,acc0. */
6496 skip_whitespace (str
);
6498 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
)
6499 inst
.error
= BAD_ARGS
;
6501 else if (skip_past_comma (& str
) == FAIL
6502 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
6503 inst
.error
= BAD_ARGS
;
6505 else if (skip_past_comma (& str
) == FAIL
6506 || accum0_required_here (& str
) == FAIL
)
6507 inst
.error
= ERR_NO_ACCUM
;
6509 /* inst.instruction has now been zapped with both rdlo and rdhi. */
6510 else if (rdlo
== rdhi
)
6511 inst
.error
= BAD_ARGS
; /* Undefined result if 2 writes to same reg. */
6513 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
6514 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
6519 /* ARMv5TE: Preload-Cache
6523 Syntactically, like LDR with B=1, W=0, L=1. */
6531 skip_whitespace (str
);
6535 inst
.error
= _("'[' expected after PLD mnemonic");
6540 skip_whitespace (str
);
6542 if ((rd
= reg_required_here (& str
, 16)) == FAIL
)
6545 skip_whitespace (str
);
6551 skip_whitespace (str
);
6553 /* Post-indexed addressing is not allowed with PLD. */
6554 if (skip_past_comma (&str
) == SUCCESS
)
6557 = _("post-indexed expression used in preload instruction");
6560 else if (*str
== '!') /* [Rn]! */
6562 inst
.error
= _("writeback used in preload instruction");
6566 inst
.instruction
|= INDEX_UP
| PRE_INDEX
;
6568 else /* [Rn, ...] */
6570 if (skip_past_comma (& str
) == FAIL
)
6572 inst
.error
= _("pre-indexed expression expected");
6576 if (ldst_extend (&str
) == FAIL
)
6579 skip_whitespace (str
);
6583 inst
.error
= _("missing ]");
6588 skip_whitespace (str
);
6590 if (* str
== '!') /* [Rn]! */
6592 inst
.error
= _("writeback used in preload instruction");
6596 inst
.instruction
|= PRE_INDEX
;
6602 /* ARMv5TE load-consecutive (argument parse)
6615 skip_whitespace (str
);
6617 if ((rd
= reg_required_here (& str
, 12)) == FAIL
)
6619 inst
.error
= BAD_ARGS
;
6623 if (skip_past_comma (& str
) == FAIL
6624 || (rn
= ld_mode_required_here (& str
)) == FAIL
)
6627 inst
.error
= BAD_ARGS
;
6631 /* inst.instruction has now been zapped with Rd and the addressing mode. */
6632 if (rd
& 1) /* Unpredictable result if Rd is odd. */
6634 inst
.error
= _("destination register must be even");
6640 inst
.error
= _("r14 not allowed here");
6644 if (((rd
== rn
) || (rd
+ 1 == rn
))
6645 && ((inst
.instruction
& WRITE_BACK
)
6646 || (!(inst
.instruction
& PRE_INDEX
))))
6647 as_warn (_("pre/post-indexing used when modified address register is destination"));
6649 /* For an index-register load, the index register must not overlap the
6650 destination (even if not write-back). */
6651 if ((inst
.instruction
& V4_STR_BIT
) == 0
6652 && (inst
.instruction
& HWOFFSET_IMM
) == 0)
6654 int rm
= inst
.instruction
& 0x0000000f;
6656 if (rm
== rd
|| (rm
== rd
+ 1))
6657 as_warn (_("ldrd destination registers must not overlap index register"));
6663 /* Returns the index into fp_values of a floating point number,
6664 or -1 if not in the table. */
6667 my_get_float_expression (str
)
6670 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
6676 memset (words
, 0, MAX_LITTLENUMS
* sizeof (LITTLENUM_TYPE
));
6678 /* Look for a raw floating point number. */
6679 if ((save_in
= atof_ieee (*str
, 'x', words
)) != NULL
6680 && is_end_of_line
[(unsigned char) *save_in
])
6682 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
6684 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
6686 if (words
[j
] != fp_values
[i
][j
])
6690 if (j
== MAX_LITTLENUMS
)
6698 /* Try and parse a more complex expression, this will probably fail
6699 unless the code uses a floating point prefix (eg "0f"). */
6700 save_in
= input_line_pointer
;
6701 input_line_pointer
= *str
;
6702 if (expression (&exp
) == absolute_section
6703 && exp
.X_op
== O_big
6704 && exp
.X_add_number
< 0)
6706 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
6708 if (gen_to_words (words
, 5, (long) 15) == 0)
6710 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
6712 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
6714 if (words
[j
] != fp_values
[i
][j
])
6718 if (j
== MAX_LITTLENUMS
)
6720 *str
= input_line_pointer
;
6721 input_line_pointer
= save_in
;
6728 *str
= input_line_pointer
;
6729 input_line_pointer
= save_in
;
6733 /* Return TRUE if anything in the expression is a bignum. */
6736 walk_no_bignums (sp
)
6739 if (symbol_get_value_expression (sp
)->X_op
== O_big
)
6742 if (symbol_get_value_expression (sp
)->X_add_symbol
)
6744 return (walk_no_bignums (symbol_get_value_expression (sp
)->X_add_symbol
)
6745 || (symbol_get_value_expression (sp
)->X_op_symbol
6746 && walk_no_bignums (symbol_get_value_expression (sp
)->X_op_symbol
)));
6752 static int in_my_get_expression
= 0;
6755 my_get_expression (ep
, str
)
6762 save_in
= input_line_pointer
;
6763 input_line_pointer
= *str
;
6764 in_my_get_expression
= 1;
6765 seg
= expression (ep
);
6766 in_my_get_expression
= 0;
6768 if (ep
->X_op
== O_illegal
)
6770 /* We found a bad expression in md_operand(). */
6771 *str
= input_line_pointer
;
6772 input_line_pointer
= save_in
;
6777 if (seg
!= absolute_section
6778 && seg
!= text_section
6779 && seg
!= data_section
6780 && seg
!= bss_section
6781 && seg
!= undefined_section
)
6783 inst
.error
= _("bad_segment");
6784 *str
= input_line_pointer
;
6785 input_line_pointer
= save_in
;
6790 /* Get rid of any bignums now, so that we don't generate an error for which
6791 we can't establish a line number later on. Big numbers are never valid
6792 in instructions, which is where this routine is always called. */
6793 if (ep
->X_op
== O_big
6794 || (ep
->X_add_symbol
6795 && (walk_no_bignums (ep
->X_add_symbol
)
6797 && walk_no_bignums (ep
->X_op_symbol
)))))
6799 inst
.error
= _("invalid constant");
6800 *str
= input_line_pointer
;
6801 input_line_pointer
= save_in
;
6805 *str
= input_line_pointer
;
6806 input_line_pointer
= save_in
;
6810 /* We handle all bad expressions here, so that we can report the faulty
6811 instruction in the error message. */
6816 if (in_my_get_expression
)
6818 expr
->X_op
= O_illegal
;
6819 if (inst
.error
== NULL
)
6820 inst
.error
= _("bad expression");
6824 /* KIND indicates what kind of shifts are accepted. */
6827 decode_shift (str
, kind
)
6831 const struct asm_shift_name
* shift
;
6835 skip_whitespace (* str
);
6837 for (p
= * str
; ISALPHA (* p
); p
++)
6842 inst
.error
= _("shift expression expected");
6848 shift
= (const struct asm_shift_name
*) hash_find (arm_shift_hsh
, * str
);
6853 inst
.error
= _("shift expression expected");
6857 assert (shift
->properties
->index
== shift_properties
[shift
->properties
->index
].index
);
6859 if (kind
== SHIFT_LSL_OR_ASR_IMMEDIATE
6860 && shift
->properties
->index
!= SHIFT_LSL
6861 && shift
->properties
->index
!= SHIFT_ASR
)
6863 inst
.error
= _("'LSL' or 'ASR' required");
6866 else if (kind
== SHIFT_LSL_IMMEDIATE
6867 && shift
->properties
->index
!= SHIFT_LSL
)
6869 inst
.error
= _("'LSL' required");
6872 else if (kind
== SHIFT_ASR_IMMEDIATE
6873 && shift
->properties
->index
!= SHIFT_ASR
)
6875 inst
.error
= _("'ASR' required");
6879 if (shift
->properties
->index
== SHIFT_RRX
)
6882 inst
.instruction
|= shift
->properties
->bit_field
;
6886 skip_whitespace (p
);
6888 if (kind
== NO_SHIFT_RESTRICT
&& reg_required_here (& p
, 8) != FAIL
)
6890 inst
.instruction
|= shift
->properties
->bit_field
| SHIFT_BY_REG
;
6894 else if (! is_immediate_prefix (* p
))
6896 inst
.error
= (NO_SHIFT_RESTRICT
6897 ? _("shift requires register or #expression")
6898 : _("shift requires #expression"));
6906 if (my_get_expression (& inst
.reloc
.exp
, & p
))
6909 /* Validate some simple #expressions. */
6910 if (inst
.reloc
.exp
.X_op
== O_constant
)
6912 unsigned num
= inst
.reloc
.exp
.X_add_number
;
6914 /* Reject operations greater than 32. */
6916 /* Reject a shift of 0 unless the mode allows it. */
6917 || (num
== 0 && shift
->properties
->allows_0
== 0)
6918 /* Reject a shift of 32 unless the mode allows it. */
6919 || (num
== 32 && shift
->properties
->allows_32
== 0)
6922 /* As a special case we allow a shift of zero for
6923 modes that do not support it to be recoded as an
6924 logical shift left of zero (ie nothing). We warn
6925 about this though. */
6928 as_warn (_("shift of 0 ignored."));
6929 shift
= & shift_names
[0];
6930 assert (shift
->properties
->index
== SHIFT_LSL
);
6934 inst
.error
= _("invalid immediate shift");
6939 /* Shifts of 32 are encoded as 0, for those shifts that
6944 inst
.instruction
|= (num
<< 7) | shift
->properties
->bit_field
;
6948 inst
.reloc
.type
= BFD_RELOC_ARM_SHIFT_IMM
;
6949 inst
.reloc
.pc_rel
= 0;
6950 inst
.instruction
|= shift
->properties
->bit_field
;
6957 /* Do those data_ops which can take a negative immediate constant
6958 by altering the instruction. A bit of a hack really.
6962 by inverting the second operand, and
6965 by negating the second operand. */
6968 negate_data_op (instruction
, value
)
6969 unsigned long * instruction
;
6970 unsigned long value
;
6973 unsigned long negated
, inverted
;
6975 negated
= validate_immediate (-value
);
6976 inverted
= validate_immediate (~value
);
6978 op
= (*instruction
>> DATA_OP_SHIFT
) & 0xf;
6981 /* First negates. */
6982 case OPCODE_SUB
: /* ADD <-> SUB */
6983 new_inst
= OPCODE_ADD
;
6988 new_inst
= OPCODE_SUB
;
6992 case OPCODE_CMP
: /* CMP <-> CMN */
6993 new_inst
= OPCODE_CMN
;
6998 new_inst
= OPCODE_CMP
;
7002 /* Now Inverted ops. */
7003 case OPCODE_MOV
: /* MOV <-> MVN */
7004 new_inst
= OPCODE_MVN
;
7009 new_inst
= OPCODE_MOV
;
7013 case OPCODE_AND
: /* AND <-> BIC */
7014 new_inst
= OPCODE_BIC
;
7019 new_inst
= OPCODE_AND
;
7023 case OPCODE_ADC
: /* ADC <-> SBC */
7024 new_inst
= OPCODE_SBC
;
7029 new_inst
= OPCODE_ADC
;
7033 /* We cannot do anything. */
7038 if (value
== (unsigned) FAIL
)
7041 *instruction
&= OPCODE_MASK
;
7042 *instruction
|= new_inst
<< DATA_OP_SHIFT
;
7053 skip_whitespace (* str
);
7055 if (reg_required_here (str
, 0) != FAIL
)
7057 if (skip_past_comma (str
) == SUCCESS
)
7058 /* Shift operation on register. */
7059 return decode_shift (str
, NO_SHIFT_RESTRICT
);
7065 /* Immediate expression. */
7066 if (is_immediate_prefix (**str
))
7071 if (my_get_expression (&inst
.reloc
.exp
, str
))
7074 if (inst
.reloc
.exp
.X_add_symbol
)
7076 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
7077 inst
.reloc
.pc_rel
= 0;
7081 if (skip_past_comma (str
) == SUCCESS
)
7083 /* #x, y -- ie explicit rotation by Y. */
7084 if (my_get_expression (&expr
, str
))
7087 if (expr
.X_op
!= O_constant
)
7089 inst
.error
= _("constant expression expected");
7093 /* Rotate must be a multiple of 2. */
7094 if (((unsigned) expr
.X_add_number
) > 30
7095 || (expr
.X_add_number
& 1) != 0
7096 || ((unsigned) inst
.reloc
.exp
.X_add_number
) > 255)
7098 inst
.error
= _("invalid constant");
7101 inst
.instruction
|= INST_IMMEDIATE
;
7102 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
7103 inst
.instruction
|= expr
.X_add_number
<< 7;
7107 /* Implicit rotation, select a suitable one. */
7108 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
7112 /* Can't be done. Perhaps the code reads something like
7113 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
7114 if ((value
= negate_data_op (&inst
.instruction
,
7115 inst
.reloc
.exp
.X_add_number
))
7118 inst
.error
= _("invalid constant");
7123 inst
.instruction
|= value
;
7126 inst
.instruction
|= INST_IMMEDIATE
;
7131 inst
.error
= _("register or shift expression expected");
7140 skip_whitespace (* str
);
7142 if (fp_reg_required_here (str
, 0) != FAIL
)
7146 /* Immediate expression. */
7147 if (*((*str
)++) == '#')
7153 skip_whitespace (* str
);
7155 /* First try and match exact strings, this is to guarantee
7156 that some formats will work even for cross assembly. */
7158 for (i
= 0; fp_const
[i
]; i
++)
7160 if (strncmp (*str
, fp_const
[i
], strlen (fp_const
[i
])) == 0)
7164 *str
+= strlen (fp_const
[i
]);
7165 if (is_end_of_line
[(unsigned char) **str
])
7167 inst
.instruction
|= i
+ 8;
7174 /* Just because we didn't get a match doesn't mean that the
7175 constant isn't valid, just that it is in a format that we
7176 don't automatically recognize. Try parsing it with
7177 the standard expression routines. */
7178 if ((i
= my_get_float_expression (str
)) >= 0)
7180 inst
.instruction
|= i
+ 8;
7184 inst
.error
= _("invalid floating point immediate expression");
7188 _("floating point register or immediate expression expected");
7197 skip_whitespace (str
);
7199 if (reg_required_here (&str
, 12) == FAIL
7200 || skip_past_comma (&str
) == FAIL
7201 || reg_required_here (&str
, 16) == FAIL
7202 || skip_past_comma (&str
) == FAIL
7203 || data_op2 (&str
) == FAIL
)
7206 inst
.error
= BAD_ARGS
;
7217 /* This is a pseudo-op of the form "adr rd, label" to be converted
7218 into a relative address of the form "add rd, pc, #label-.-8". */
7219 skip_whitespace (str
);
7221 if (reg_required_here (&str
, 12) == FAIL
7222 || skip_past_comma (&str
) == FAIL
7223 || my_get_expression (&inst
.reloc
.exp
, &str
))
7226 inst
.error
= BAD_ARGS
;
7230 /* Frag hacking will turn this into a sub instruction if the offset turns
7231 out to be negative. */
7232 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
7234 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust. */
7236 inst
.reloc
.pc_rel
= 1;
7245 /* This is a pseudo-op of the form "adrl rd, label" to be converted
7246 into a relative address of the form:
7247 add rd, pc, #low(label-.-8)"
7248 add rd, rd, #high(label-.-8)" */
7250 skip_whitespace (str
);
7252 if (reg_required_here (&str
, 12) == FAIL
7253 || skip_past_comma (&str
) == FAIL
7254 || my_get_expression (&inst
.reloc
.exp
, &str
))
7257 inst
.error
= BAD_ARGS
;
7263 /* Frag hacking will turn this into a sub instruction if the offset turns
7264 out to be negative. */
7265 inst
.reloc
.type
= BFD_RELOC_ARM_ADRL_IMMEDIATE
;
7267 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust */
7269 inst
.reloc
.pc_rel
= 1;
7270 inst
.size
= INSN_SIZE
* 2;
7277 skip_whitespace (str
);
7279 if (reg_required_here (&str
, 16) == FAIL
)
7282 inst
.error
= BAD_ARGS
;
7286 if (skip_past_comma (&str
) == FAIL
7287 || data_op2 (&str
) == FAIL
)
7290 inst
.error
= BAD_ARGS
;
7301 skip_whitespace (str
);
7303 if (reg_required_here (&str
, 12) == FAIL
)
7306 inst
.error
= BAD_ARGS
;
7310 if (skip_past_comma (&str
) == FAIL
7311 || data_op2 (&str
) == FAIL
)
7314 inst
.error
= BAD_ARGS
;
7332 if (my_get_expression (& inst
.reloc
.exp
, str
))
7335 if (inst
.reloc
.exp
.X_op
== O_constant
)
7337 int value
= inst
.reloc
.exp
.X_add_number
;
7339 if (value
< -4095 || value
> 4095)
7341 inst
.error
= _("address offset too large");
7351 inst
.instruction
|= add
| value
;
7355 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
7356 inst
.reloc
.pc_rel
= 0;
7369 if (reg_required_here (str
, 0) == FAIL
)
7372 inst
.instruction
|= add
| OFFSET_REG
;
7373 if (skip_past_comma (str
) == SUCCESS
)
7374 return decode_shift (str
, SHIFT_IMMEDIATE
);
7388 skip_whitespace (str
);
7390 if ((conflict_reg
= reg_required_here (&str
, 12)) == FAIL
)
7393 inst
.error
= BAD_ARGS
;
7397 if (skip_past_comma (&str
) == FAIL
)
7399 inst
.error
= _("address expected");
7409 skip_whitespace (str
);
7411 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
7414 /* Conflicts can occur on stores as well as loads. */
7415 conflict_reg
= (conflict_reg
== reg
);
7417 skip_whitespace (str
);
7423 if (skip_past_comma (&str
) == SUCCESS
)
7425 /* [Rn],... (post inc) */
7426 if (ldst_extend (&str
) == FAIL
)
7429 as_warn (_("%s register same as write-back base"),
7430 ((inst
.instruction
& LOAD_BIT
)
7431 ? _("destination") : _("source")));
7436 skip_whitespace (str
);
7441 as_warn (_("%s register same as write-back base"),
7442 ((inst
.instruction
& LOAD_BIT
)
7443 ? _("destination") : _("source")));
7445 inst
.instruction
|= WRITE_BACK
;
7448 inst
.instruction
|= INDEX_UP
;
7455 if (skip_past_comma (&str
) == FAIL
)
7457 inst
.error
= _("pre-indexed expression expected");
7462 if (ldst_extend (&str
) == FAIL
)
7465 skip_whitespace (str
);
7469 inst
.error
= _("missing ]");
7473 skip_whitespace (str
);
7478 as_warn (_("%s register same as write-back base"),
7479 ((inst
.instruction
& LOAD_BIT
)
7480 ? _("destination") : _("source")));
7482 inst
.instruction
|= WRITE_BACK
;
7486 else if (*str
== '=')
7488 if ((inst
.instruction
& LOAD_BIT
) == 0)
7490 inst
.error
= _("invalid pseudo operation");
7494 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
7497 skip_whitespace (str
);
7499 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7502 if (inst
.reloc
.exp
.X_op
!= O_constant
7503 && inst
.reloc
.exp
.X_op
!= O_symbol
)
7505 inst
.error
= _("constant expression expected");
7509 if (inst
.reloc
.exp
.X_op
== O_constant
)
7511 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
7515 /* This can be done with a mov instruction. */
7516 inst
.instruction
&= LITERAL_MASK
;
7517 inst
.instruction
|= (INST_IMMEDIATE
7518 | (OPCODE_MOV
<< DATA_OP_SHIFT
));
7519 inst
.instruction
|= value
& 0xfff;
7524 value
= validate_immediate (~inst
.reloc
.exp
.X_add_number
);
7528 /* This can be done with a mvn instruction. */
7529 inst
.instruction
&= LITERAL_MASK
;
7530 inst
.instruction
|= (INST_IMMEDIATE
7531 | (OPCODE_MVN
<< DATA_OP_SHIFT
));
7532 inst
.instruction
|= value
& 0xfff;
7538 /* Insert into literal pool. */
7539 if (add_to_lit_pool () == FAIL
)
7542 inst
.error
= _("literal pool insertion failed");
7546 /* Change the instruction exp to point to the pool. */
7547 inst
.reloc
.type
= BFD_RELOC_ARM_LITERAL
;
7548 inst
.reloc
.pc_rel
= 1;
7549 inst
.instruction
|= (REG_PC
<< 16);
7554 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7557 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
7559 /* PC rel adjust. */
7560 inst
.reloc
.exp
.X_add_number
-= 8;
7562 inst
.reloc
.pc_rel
= 1;
7563 inst
.instruction
|= (REG_PC
<< 16);
7567 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
7577 skip_whitespace (str
);
7579 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
7582 inst
.error
= BAD_ARGS
;
7586 if (skip_past_comma (& str
) == FAIL
)
7588 inst
.error
= _("address expected");
7598 skip_whitespace (str
);
7600 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
7603 /* ldrt/strt always use post-indexed addressing, so if the base is
7604 the same as Rd, we warn. */
7605 if (conflict_reg
== reg
)
7606 as_warn (_("%s register same as write-back base"),
7607 ((inst
.instruction
& LOAD_BIT
)
7608 ? _("destination") : _("source")));
7610 skip_whitespace (str
);
7616 if (skip_past_comma (&str
) == SUCCESS
)
7618 /* [Rn],... (post inc) */
7619 if (ldst_extend (&str
) == FAIL
)
7625 skip_whitespace (str
);
7627 /* Skip a write-back '!'. */
7631 inst
.instruction
|= INDEX_UP
;
7636 inst
.error
= _("post-indexed expression expected");
7642 inst
.error
= _("post-indexed expression expected");
7650 ldst_extend_v4 (str
)
7660 if (my_get_expression (& inst
.reloc
.exp
, str
))
7663 if (inst
.reloc
.exp
.X_op
== O_constant
)
7665 int value
= inst
.reloc
.exp
.X_add_number
;
7667 if (value
< -255 || value
> 255)
7669 inst
.error
= _("address offset too large");
7679 /* Halfword and signextension instructions have the
7680 immediate value split across bits 11..8 and bits 3..0. */
7681 inst
.instruction
|= (add
| HWOFFSET_IMM
7682 | ((value
>> 4) << 8) | (value
& 0xF));
7686 inst
.instruction
|= HWOFFSET_IMM
;
7687 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
7688 inst
.reloc
.pc_rel
= 0;
7701 if (reg_required_here (str
, 0) == FAIL
)
7704 inst
.instruction
|= add
;
7709 /* Halfword and signed-byte load/store operations. */
7718 skip_whitespace (str
);
7720 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
7723 inst
.error
= BAD_ARGS
;
7727 if (skip_past_comma (& str
) == FAIL
)
7729 inst
.error
= _("address expected");
7739 skip_whitespace (str
);
7741 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
7744 /* Conflicts can occur on stores as well as loads. */
7745 conflict_reg
= (conflict_reg
== reg
);
7747 skip_whitespace (str
);
7753 if (skip_past_comma (&str
) == SUCCESS
)
7755 /* [Rn],... (post inc) */
7756 if (ldst_extend_v4 (&str
) == FAIL
)
7759 as_warn (_("%s register same as write-back base"),
7760 ((inst
.instruction
& LOAD_BIT
)
7761 ? _("destination") : _("source")));
7766 inst
.instruction
|= HWOFFSET_IMM
;
7768 skip_whitespace (str
);
7773 as_warn (_("%s register same as write-back base"),
7774 ((inst
.instruction
& LOAD_BIT
)
7775 ? _("destination") : _("source")));
7777 inst
.instruction
|= WRITE_BACK
;
7780 inst
.instruction
|= INDEX_UP
;
7787 if (skip_past_comma (&str
) == FAIL
)
7789 inst
.error
= _("pre-indexed expression expected");
7794 if (ldst_extend_v4 (&str
) == FAIL
)
7797 skip_whitespace (str
);
7801 inst
.error
= _("missing ]");
7805 skip_whitespace (str
);
7810 as_warn (_("%s register same as write-back base"),
7811 ((inst
.instruction
& LOAD_BIT
)
7812 ? _("destination") : _("source")));
7814 inst
.instruction
|= WRITE_BACK
;
7818 else if (*str
== '=')
7820 if ((inst
.instruction
& LOAD_BIT
) == 0)
7822 inst
.error
= _("invalid pseudo operation");
7826 /* XXX Does this work correctly for half-word/byte ops? */
7827 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
7830 skip_whitespace (str
);
7832 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7835 if (inst
.reloc
.exp
.X_op
!= O_constant
7836 && inst
.reloc
.exp
.X_op
!= O_symbol
)
7838 inst
.error
= _("constant expression expected");
7842 if (inst
.reloc
.exp
.X_op
== O_constant
)
7844 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
7848 /* This can be done with a mov instruction. */
7849 inst
.instruction
&= LITERAL_MASK
;
7850 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MOV
<< DATA_OP_SHIFT
);
7851 inst
.instruction
|= value
& 0xfff;
7856 value
= validate_immediate (~ inst
.reloc
.exp
.X_add_number
);
7860 /* This can be done with a mvn instruction. */
7861 inst
.instruction
&= LITERAL_MASK
;
7862 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MVN
<< DATA_OP_SHIFT
);
7863 inst
.instruction
|= value
& 0xfff;
7869 /* Insert into literal pool. */
7870 if (add_to_lit_pool () == FAIL
)
7873 inst
.error
= _("literal pool insertion failed");
7877 /* Change the instruction exp to point to the pool. */
7878 inst
.instruction
|= HWOFFSET_IMM
;
7879 inst
.reloc
.type
= BFD_RELOC_ARM_HWLITERAL
;
7880 inst
.reloc
.pc_rel
= 1;
7881 inst
.instruction
|= (REG_PC
<< 16);
7886 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7889 inst
.instruction
|= HWOFFSET_IMM
;
7890 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
7892 /* PC rel adjust. */
7893 inst
.reloc
.exp
.X_add_number
-= 8;
7895 inst
.reloc
.pc_rel
= 1;
7896 inst
.instruction
|= (REG_PC
<< 16);
7900 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
7908 char * str
= * strp
;
7912 /* We come back here if we get ranges concatenated by '+' or '|'. */
7927 skip_whitespace (str
);
7929 if ((reg
= reg_required_here (& str
, -1)) == FAIL
)
7938 inst
.error
= _("bad range in register list");
7942 for (i
= cur_reg
+ 1; i
< reg
; i
++)
7944 if (range
& (1 << i
))
7946 (_("Warning: duplicated register (r%d) in register list"),
7954 if (range
& (1 << reg
))
7955 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
7957 else if (reg
<= cur_reg
)
7958 as_tsktsk (_("Warning: register range not in ascending order"));
7963 while (skip_past_comma (&str
) != FAIL
7964 || (in_range
= 1, *str
++ == '-'));
7966 skip_whitespace (str
);
7970 inst
.error
= _("missing `}'");
7978 if (my_get_expression (&expr
, &str
))
7981 if (expr
.X_op
== O_constant
)
7983 if (expr
.X_add_number
7984 != (expr
.X_add_number
& 0x0000ffff))
7986 inst
.error
= _("invalid register mask");
7990 if ((range
& expr
.X_add_number
) != 0)
7992 int regno
= range
& expr
.X_add_number
;
7995 regno
= (1 << regno
) - 1;
7997 (_("Warning: duplicated register (r%d) in register list"),
8001 range
|= expr
.X_add_number
;
8005 if (inst
.reloc
.type
!= 0)
8007 inst
.error
= _("expression too complex");
8011 memcpy (&inst
.reloc
.exp
, &expr
, sizeof (expressionS
));
8012 inst
.reloc
.type
= BFD_RELOC_ARM_MULTI
;
8013 inst
.reloc
.pc_rel
= 0;
8017 skip_whitespace (str
);
8019 if (*str
== '|' || *str
== '+')
8025 while (another_range
);
8038 skip_whitespace (str
);
8040 if ((base_reg
= reg_required_here (&str
, 16)) == FAIL
)
8043 if (base_reg
== REG_PC
)
8045 inst
.error
= _("r15 not allowed as base register");
8049 skip_whitespace (str
);
8053 inst
.instruction
|= WRITE_BACK
;
8057 if (skip_past_comma (&str
) == FAIL
8058 || (range
= reg_list (&str
)) == FAIL
)
8061 inst
.error
= BAD_ARGS
;
8068 inst
.instruction
|= LDM_TYPE_2_OR_3
;
8071 if (inst
.instruction
& WRITE_BACK
)
8073 /* Check for unpredictable uses of writeback. */
8074 if (inst
.instruction
& LOAD_BIT
)
8076 /* Not allowed in LDM type 2. */
8077 if ((inst
.instruction
& LDM_TYPE_2_OR_3
)
8078 && ((range
& (1 << REG_PC
)) == 0))
8079 as_warn (_("writeback of base register is UNPREDICTABLE"));
8080 /* Only allowed if base reg not in list for other types. */
8081 else if (range
& (1 << base_reg
))
8082 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
8086 /* Not allowed for type 2. */
8087 if (inst
.instruction
& LDM_TYPE_2_OR_3
)
8088 as_warn (_("writeback of base register is UNPREDICTABLE"));
8089 /* Only allowed if base reg not in list, or first in list. */
8090 else if ((range
& (1 << base_reg
))
8091 && (range
& ((1 << base_reg
) - 1)))
8092 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
8096 inst
.instruction
|= range
;
8104 skip_whitespace (str
);
8106 /* Allow optional leading '#'. */
8107 if (is_immediate_prefix (*str
))
8110 if (my_get_expression (& inst
.reloc
.exp
, & str
))
8113 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
8114 inst
.reloc
.pc_rel
= 0;
8124 skip_whitespace (str
);
8126 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
8131 inst
.error
= _("r15 not allowed in swap");
8135 if (skip_past_comma (&str
) == FAIL
8136 || (reg
= reg_required_here (&str
, 0)) == FAIL
)
8139 inst
.error
= BAD_ARGS
;
8145 inst
.error
= _("r15 not allowed in swap");
8149 if (skip_past_comma (&str
) == FAIL
8152 inst
.error
= BAD_ARGS
;
8156 skip_whitespace (str
);
8158 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
8163 inst
.error
= BAD_PC
;
8167 skip_whitespace (str
);
8171 inst
.error
= _("missing ]");
8182 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8189 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
8190 required for the instruction. */
8192 /* arm_parse_reloc () works on input_line_pointer.
8193 We actually want to parse the operands to the branch instruction
8194 passed in 'str'. Save the input pointer and restore it later. */
8195 save_in
= input_line_pointer
;
8196 input_line_pointer
= str
;
8197 if (inst
.reloc
.exp
.X_op
== O_symbol
8199 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
8201 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
8202 inst
.reloc
.pc_rel
= 0;
8203 /* Modify str to point to after parsed operands, otherwise
8204 end_of_line() will complain about the (PLT) left in str. */
8205 str
= input_line_pointer
;
8209 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
8210 inst
.reloc
.pc_rel
= 1;
8212 input_line_pointer
= save_in
;
8215 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
8216 inst
.reloc
.pc_rel
= 1;
8217 #endif /* OBJ_ELF */
8228 skip_whitespace (str
);
8230 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
8232 inst
.error
= BAD_ARGS
;
8236 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
8238 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
8247 /* Co-processor data operation.
8248 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
8249 skip_whitespace (str
);
8251 if (co_proc_number (&str
) == FAIL
)
8254 inst
.error
= BAD_ARGS
;
8258 if (skip_past_comma (&str
) == FAIL
8259 || cp_opc_expr (&str
, 20,4) == FAIL
)
8262 inst
.error
= BAD_ARGS
;
8266 if (skip_past_comma (&str
) == FAIL
8267 || cp_reg_required_here (&str
, 12) == FAIL
)
8270 inst
.error
= BAD_ARGS
;
8274 if (skip_past_comma (&str
) == FAIL
8275 || cp_reg_required_here (&str
, 16) == FAIL
)
8278 inst
.error
= BAD_ARGS
;
8282 if (skip_past_comma (&str
) == FAIL
8283 || cp_reg_required_here (&str
, 0) == FAIL
)
8286 inst
.error
= BAD_ARGS
;
8290 if (skip_past_comma (&str
) == SUCCESS
)
8292 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
8295 inst
.error
= BAD_ARGS
;
8307 /* Co-processor register load/store.
8308 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
8310 skip_whitespace (str
);
8312 if (co_proc_number (&str
) == FAIL
)
8315 inst
.error
= BAD_ARGS
;
8319 if (skip_past_comma (&str
) == FAIL
8320 || cp_reg_required_here (&str
, 12) == FAIL
)
8323 inst
.error
= BAD_ARGS
;
8327 if (skip_past_comma (&str
) == FAIL
8328 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
8331 inst
.error
= BAD_ARGS
;
8342 /* Co-processor register transfer.
8343 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
8345 skip_whitespace (str
);
8347 if (co_proc_number (&str
) == FAIL
)
8350 inst
.error
= BAD_ARGS
;
8354 if (skip_past_comma (&str
) == FAIL
8355 || cp_opc_expr (&str
, 21, 3) == FAIL
)
8358 inst
.error
= BAD_ARGS
;
8362 if (skip_past_comma (&str
) == FAIL
8363 || reg_required_here (&str
, 12) == FAIL
)
8366 inst
.error
= BAD_ARGS
;
8370 if (skip_past_comma (&str
) == FAIL
8371 || cp_reg_required_here (&str
, 16) == FAIL
)
8374 inst
.error
= BAD_ARGS
;
8378 if (skip_past_comma (&str
) == FAIL
8379 || cp_reg_required_here (&str
, 0) == FAIL
)
8382 inst
.error
= BAD_ARGS
;
8386 if (skip_past_comma (&str
) == SUCCESS
)
8388 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
8391 inst
.error
= BAD_ARGS
;
8403 /* FP control registers.
8404 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
8406 skip_whitespace (str
);
8408 if (reg_required_here (&str
, 12) == FAIL
)
8411 inst
.error
= BAD_ARGS
;
8422 skip_whitespace (str
);
8424 if (fp_reg_required_here (&str
, 12) == FAIL
)
8427 inst
.error
= BAD_ARGS
;
8431 if (skip_past_comma (&str
) == FAIL
8432 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
8435 inst
.error
= BAD_ARGS
;
8448 skip_whitespace (str
);
8450 if (fp_reg_required_here (&str
, 12) == FAIL
)
8453 inst
.error
= BAD_ARGS
;
8457 /* Get Number of registers to transfer. */
8458 if (skip_past_comma (&str
) == FAIL
8459 || my_get_expression (&inst
.reloc
.exp
, &str
))
8462 inst
.error
= _("constant expression expected");
8466 if (inst
.reloc
.exp
.X_op
!= O_constant
)
8468 inst
.error
= _("constant value required for number of registers");
8472 num_regs
= inst
.reloc
.exp
.X_add_number
;
8474 if (num_regs
< 1 || num_regs
> 4)
8476 inst
.error
= _("number of registers must be in the range [1:4]");
8483 inst
.instruction
|= CP_T_X
;
8486 inst
.instruction
|= CP_T_Y
;
8489 inst
.instruction
|= CP_T_Y
| CP_T_X
;
8497 if (inst
.instruction
& (CP_T_Pre
| CP_T_UD
)) /* ea/fd format. */
8503 /* The instruction specified "ea" or "fd", so we can only accept
8504 [Rn]{!}. The instruction does not really support stacking or
8505 unstacking, so we have to emulate these by setting appropriate
8506 bits and offsets. */
8507 if (skip_past_comma (&str
) == FAIL
8511 inst
.error
= BAD_ARGS
;
8516 skip_whitespace (str
);
8518 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
8521 skip_whitespace (str
);
8525 inst
.error
= BAD_ARGS
;
8537 _("r15 not allowed as base register with write-back");
8544 if (inst
.instruction
& CP_T_Pre
)
8546 /* Pre-decrement. */
8547 offset
= 3 * num_regs
;
8549 inst
.instruction
|= CP_T_WB
;
8553 /* Post-increment. */
8556 inst
.instruction
|= CP_T_WB
;
8557 offset
= 3 * num_regs
;
8561 /* No write-back, so convert this into a standard pre-increment
8562 instruction -- aesthetically more pleasing. */
8563 inst
.instruction
|= CP_T_Pre
| CP_T_UD
;
8568 inst
.instruction
|= offset
;
8570 else if (skip_past_comma (&str
) == FAIL
8571 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
8574 inst
.error
= BAD_ARGS
;
8585 skip_whitespace (str
);
8587 if (fp_reg_required_here (&str
, 12) == FAIL
)
8590 inst
.error
= BAD_ARGS
;
8594 if (skip_past_comma (&str
) == FAIL
8595 || fp_reg_required_here (&str
, 16) == FAIL
)
8598 inst
.error
= BAD_ARGS
;
8602 if (skip_past_comma (&str
) == FAIL
8603 || fp_op2 (&str
) == FAIL
)
8606 inst
.error
= BAD_ARGS
;
8614 do_fpa_monadic (str
)
8617 skip_whitespace (str
);
8619 if (fp_reg_required_here (&str
, 12) == FAIL
)
8622 inst
.error
= BAD_ARGS
;
8626 if (skip_past_comma (&str
) == FAIL
8627 || fp_op2 (&str
) == FAIL
)
8630 inst
.error
= BAD_ARGS
;
8641 skip_whitespace (str
);
8643 if (fp_reg_required_here (&str
, 16) == FAIL
)
8646 inst
.error
= BAD_ARGS
;
8650 if (skip_past_comma (&str
) == FAIL
8651 || fp_op2 (&str
) == FAIL
)
8654 inst
.error
= BAD_ARGS
;
8662 do_fpa_from_reg (str
)
8665 skip_whitespace (str
);
8667 if (fp_reg_required_here (&str
, 16) == FAIL
)
8670 inst
.error
= BAD_ARGS
;
8674 if (skip_past_comma (&str
) == FAIL
8675 || reg_required_here (&str
, 12) == FAIL
)
8678 inst
.error
= BAD_ARGS
;
8689 skip_whitespace (str
);
8691 if (reg_required_here (&str
, 12) == FAIL
)
8694 if (skip_past_comma (&str
) == FAIL
8695 || fp_reg_required_here (&str
, 0) == FAIL
)
8698 inst
.error
= BAD_ARGS
;
8706 vfp_sp_reg_required_here (str
, pos
)
8708 enum vfp_sp_reg_pos pos
;
8713 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_SN
].htab
)) != FAIL
)
8718 inst
.instruction
|= ((reg
>> 1) << 12) | ((reg
& 1) << 22);
8722 inst
.instruction
|= ((reg
>> 1) << 16) | ((reg
& 1) << 7);
8726 inst
.instruction
|= ((reg
>> 1) << 0) | ((reg
& 1) << 5);
8735 /* In the few cases where we might be able to accept something else
8736 this error can be overridden. */
8737 inst
.error
= _(all_reg_maps
[REG_TYPE_SN
].expected
);
8739 /* Restore the start point. */
8745 vfp_dp_reg_required_here (str
, pos
)
8747 enum vfp_dp_reg_pos pos
;
8752 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_DN
].htab
)) != FAIL
)
8757 inst
.instruction
|= reg
<< 12;
8761 inst
.instruction
|= reg
<< 16;
8765 inst
.instruction
|= reg
<< 0;
8774 /* In the few cases where we might be able to accept something else
8775 this error can be overridden. */
8776 inst
.error
= _(all_reg_maps
[REG_TYPE_DN
].expected
);
8778 /* Restore the start point. */
8784 do_vfp_sp_monadic (str
)
8787 skip_whitespace (str
);
8789 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8792 if (skip_past_comma (&str
) == FAIL
8793 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
8796 inst
.error
= BAD_ARGS
;
8804 do_vfp_dp_monadic (str
)
8807 skip_whitespace (str
);
8809 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8812 if (skip_past_comma (&str
) == FAIL
8813 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
8816 inst
.error
= BAD_ARGS
;
8824 do_vfp_sp_dyadic (str
)
8827 skip_whitespace (str
);
8829 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8832 if (skip_past_comma (&str
) == FAIL
8833 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
8834 || skip_past_comma (&str
) == FAIL
8835 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
8838 inst
.error
= BAD_ARGS
;
8846 do_vfp_dp_dyadic (str
)
8849 skip_whitespace (str
);
8851 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8854 if (skip_past_comma (&str
) == FAIL
8855 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
8856 || skip_past_comma (&str
) == FAIL
8857 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
8860 inst
.error
= BAD_ARGS
;
8868 do_vfp_reg_from_sp (str
)
8871 skip_whitespace (str
);
8873 if (reg_required_here (&str
, 12) == FAIL
)
8876 if (skip_past_comma (&str
) == FAIL
8877 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
8880 inst
.error
= BAD_ARGS
;
8888 do_vfp_reg2_from_sp2 (str
)
8891 skip_whitespace (str
);
8893 if (reg_required_here (&str
, 12) == FAIL
8894 || skip_past_comma (&str
) == FAIL
8895 || reg_required_here (&str
, 16) == FAIL
8896 || skip_past_comma (&str
) == FAIL
)
8899 inst
.error
= BAD_ARGS
;
8903 /* We require exactly two consecutive SP registers. */
8904 if (vfp_sp_reg_list (&str
, VFP_REG_Sm
) != 2)
8907 inst
.error
= _("only two consecutive VFP SP registers allowed here");
8914 do_vfp_sp_from_reg (str
)
8917 skip_whitespace (str
);
8919 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
8922 if (skip_past_comma (&str
) == FAIL
8923 || reg_required_here (&str
, 12) == FAIL
)
8926 inst
.error
= BAD_ARGS
;
8934 do_vfp_sp2_from_reg2 (str
)
8937 skip_whitespace (str
);
8939 /* We require exactly two consecutive SP registers. */
8940 if (vfp_sp_reg_list (&str
, VFP_REG_Sm
) != 2)
8943 inst
.error
= _("only two consecutive VFP SP registers allowed here");
8946 if (skip_past_comma (&str
) == FAIL
8947 || reg_required_here (&str
, 12) == FAIL
8948 || skip_past_comma (&str
) == FAIL
8949 || reg_required_here (&str
, 16) == FAIL
)
8952 inst
.error
= BAD_ARGS
;
8960 do_vfp_reg_from_dp (str
)
8963 skip_whitespace (str
);
8965 if (reg_required_here (&str
, 12) == FAIL
)
8968 if (skip_past_comma (&str
) == FAIL
8969 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
8972 inst
.error
= BAD_ARGS
;
8980 do_vfp_reg2_from_dp (str
)
8983 skip_whitespace (str
);
8985 if (reg_required_here (&str
, 12) == FAIL
)
8988 if (skip_past_comma (&str
) == FAIL
8989 || reg_required_here (&str
, 16) == FAIL
8990 || skip_past_comma (&str
) == FAIL
8991 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
8994 inst
.error
= BAD_ARGS
;
9002 do_vfp_dp_from_reg (str
)
9005 skip_whitespace (str
);
9007 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
9010 if (skip_past_comma (&str
) == FAIL
9011 || reg_required_here (&str
, 12) == FAIL
)
9014 inst
.error
= BAD_ARGS
;
9022 do_vfp_dp_from_reg2 (str
)
9025 skip_whitespace (str
);
9027 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
9030 if (skip_past_comma (&str
) == FAIL
9031 || reg_required_here (&str
, 12) == FAIL
9032 || skip_past_comma (&str
) == FAIL
9033 || reg_required_here (&str
, 16) == FAIL
)
9036 inst
.error
= BAD_ARGS
;
9043 static const struct vfp_reg
*
9050 const struct vfp_reg
*vreg
;
9054 /* Find the end of the current token. */
9059 while (ISALPHA (c
));
9064 for (vreg
= vfp_regs
+ 0;
9065 vreg
< vfp_regs
+ sizeof (vfp_regs
) / sizeof (struct vfp_reg
);
9068 if (strcmp (start
, vreg
->name
) == 0)
9081 vfp_psr_required_here (str
)
9085 const struct vfp_reg
*vreg
;
9087 vreg
= vfp_psr_parse (str
);
9091 inst
.instruction
|= vreg
->regno
;
9095 inst
.error
= _("VFP system register expected");
9102 do_vfp_reg_from_ctrl (str
)
9105 skip_whitespace (str
);
9107 if (reg_required_here (&str
, 12) == FAIL
)
9110 if (skip_past_comma (&str
) == FAIL
9111 || vfp_psr_required_here (&str
) == FAIL
)
9114 inst
.error
= BAD_ARGS
;
9122 do_vfp_ctrl_from_reg (str
)
9125 skip_whitespace (str
);
9127 if (vfp_psr_required_here (&str
) == FAIL
)
9130 if (skip_past_comma (&str
) == FAIL
9131 || reg_required_here (&str
, 12) == FAIL
)
9134 inst
.error
= BAD_ARGS
;
9142 do_vfp_sp_ldst (str
)
9145 skip_whitespace (str
);
9147 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
9150 inst
.error
= BAD_ARGS
;
9154 if (skip_past_comma (&str
) == FAIL
9155 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
9158 inst
.error
= BAD_ARGS
;
9166 do_vfp_dp_ldst (str
)
9169 skip_whitespace (str
);
9171 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
9174 inst
.error
= BAD_ARGS
;
9178 if (skip_past_comma (&str
) == FAIL
9179 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
9182 inst
.error
= BAD_ARGS
;
9189 /* Parse and encode a VFP SP register list, storing the initial
9190 register in position POS and returning the range as the result. If
9191 the string is invalid return FAIL (an invalid range). */
9193 vfp_sp_reg_list (str
, pos
)
9195 enum vfp_sp_reg_pos pos
;
9203 unsigned long mask
= 0;
9210 skip_whitespace (*str
);
9212 tempinst
= inst
.instruction
;
9216 inst
.instruction
= 0;
9218 if ((new_base
= vfp_sp_reg_required_here (str
, pos
)) == FAIL
)
9221 if (count
== 0 || base_reg
> new_base
)
9223 base_reg
= new_base
;
9224 base_bits
= inst
.instruction
;
9227 if (mask
& (1 << new_base
))
9229 inst
.error
= _("invalid register list");
9233 if ((mask
>> new_base
) != 0 && ! warned
)
9235 as_tsktsk (_("register list not in ascending order"));
9239 mask
|= 1 << new_base
;
9242 skip_whitespace (*str
);
9244 if (**str
== '-') /* We have the start of a range expression */
9251 = arm_reg_parse (str
, all_reg_maps
[REG_TYPE_SN
].htab
))
9254 inst
.error
= _(all_reg_maps
[REG_TYPE_SN
].expected
);
9258 if (high_range
<= new_base
)
9260 inst
.error
= _("register range not in ascending order");
9264 for (new_base
++; new_base
<= high_range
; new_base
++)
9266 if (mask
& (1 << new_base
))
9268 inst
.error
= _("invalid register list");
9272 mask
|= 1 << new_base
;
9277 while (skip_past_comma (str
) != FAIL
);
9281 inst
.error
= _("invalid register list");
9289 /* Sanity check -- should have raised a parse error above. */
9290 if (count
== 0 || count
> 32)
9293 /* Final test -- the registers must be consecutive. */
9296 if ((mask
& (1 << base_reg
++)) == 0)
9298 inst
.error
= _("non-contiguous register range");
9303 inst
.instruction
= tempinst
| base_bits
;
9308 vfp_dp_reg_list (str
)
9316 unsigned long mask
= 0;
9323 skip_whitespace (*str
);
9325 tempinst
= inst
.instruction
;
9329 inst
.instruction
= 0;
9331 if ((new_base
= vfp_dp_reg_required_here (str
, VFP_REG_Dd
)) == FAIL
)
9334 if (count
== 0 || base_reg
> new_base
)
9336 base_reg
= new_base
;
9337 range
= inst
.instruction
;
9340 if (mask
& (1 << new_base
))
9342 inst
.error
= _("invalid register list");
9346 if ((mask
>> new_base
) != 0 && ! warned
)
9348 as_tsktsk (_("register list not in ascending order"));
9352 mask
|= 1 << new_base
;
9355 skip_whitespace (*str
);
9357 if (**str
== '-') /* We have the start of a range expression */
9364 = arm_reg_parse (str
, all_reg_maps
[REG_TYPE_DN
].htab
))
9367 inst
.error
= _(all_reg_maps
[REG_TYPE_DN
].expected
);
9371 if (high_range
<= new_base
)
9373 inst
.error
= _("register range not in ascending order");
9377 for (new_base
++; new_base
<= high_range
; new_base
++)
9379 if (mask
& (1 << new_base
))
9381 inst
.error
= _("invalid register list");
9385 mask
|= 1 << new_base
;
9390 while (skip_past_comma (str
) != FAIL
);
9394 inst
.error
= _("invalid register list");
9402 /* Sanity check -- should have raised a parse error above. */
9403 if (count
== 0 || count
> 16)
9406 /* Final test -- the registers must be consecutive. */
9409 if ((mask
& (1 << base_reg
++)) == 0)
9411 inst
.error
= _("non-contiguous register range");
9416 inst
.instruction
= tempinst
;
9421 vfp_sp_ldstm (str
, ldstm_type
)
9423 enum vfp_ldstm_type ldstm_type
;
9427 skip_whitespace (str
);
9429 if (reg_required_here (&str
, 16) == FAIL
)
9432 skip_whitespace (str
);
9436 inst
.instruction
|= WRITE_BACK
;
9439 else if (ldstm_type
!= VFP_LDSTMIA
)
9441 inst
.error
= _("this addressing mode requires base-register writeback");
9445 if (skip_past_comma (&str
) == FAIL
9446 || (range
= vfp_sp_reg_list (&str
, VFP_REG_Sd
)) == FAIL
)
9449 inst
.error
= BAD_ARGS
;
9453 inst
.instruction
|= range
;
9458 vfp_dp_ldstm (str
, ldstm_type
)
9460 enum vfp_ldstm_type ldstm_type
;
9464 skip_whitespace (str
);
9466 if (reg_required_here (&str
, 16) == FAIL
)
9469 skip_whitespace (str
);
9473 inst
.instruction
|= WRITE_BACK
;
9476 else if (ldstm_type
!= VFP_LDSTMIA
&& ldstm_type
!= VFP_LDSTMIAX
)
9478 inst
.error
= _("this addressing mode requires base-register writeback");
9482 if (skip_past_comma (&str
) == FAIL
9483 || (range
= vfp_dp_reg_list (&str
)) == FAIL
)
9486 inst
.error
= BAD_ARGS
;
9490 if (ldstm_type
== VFP_LDSTMIAX
|| ldstm_type
== VFP_LDSTMDBX
)
9493 inst
.instruction
|= range
;
9498 do_vfp_sp_ldstmia (str
)
9501 vfp_sp_ldstm (str
, VFP_LDSTMIA
);
9505 do_vfp_sp_ldstmdb (str
)
9508 vfp_sp_ldstm (str
, VFP_LDSTMDB
);
9512 do_vfp_dp_ldstmia (str
)
9515 vfp_dp_ldstm (str
, VFP_LDSTMIA
);
9519 do_vfp_dp_ldstmdb (str
)
9522 vfp_dp_ldstm (str
, VFP_LDSTMDB
);
9526 do_vfp_xp_ldstmia (str
)
9529 vfp_dp_ldstm (str
, VFP_LDSTMIAX
);
9533 do_vfp_xp_ldstmdb (str
)
9536 vfp_dp_ldstm (str
, VFP_LDSTMDBX
);
9540 do_vfp_sp_compare_z (str
)
9543 skip_whitespace (str
);
9545 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
9548 inst
.error
= BAD_ARGS
;
9556 do_vfp_dp_compare_z (str
)
9559 skip_whitespace (str
);
9561 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
9564 inst
.error
= BAD_ARGS
;
9572 do_vfp_dp_sp_cvt (str
)
9575 skip_whitespace (str
);
9577 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
9580 if (skip_past_comma (&str
) == FAIL
9581 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
9584 inst
.error
= BAD_ARGS
;
9592 do_vfp_sp_dp_cvt (str
)
9595 skip_whitespace (str
);
9597 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
9600 if (skip_past_comma (&str
) == FAIL
9601 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
9604 inst
.error
= BAD_ARGS
;
9611 /* Thumb specific routines. */
9613 /* Parse and validate that a register is of the right form, this saves
9614 repeated checking of this information in many similar cases.
9615 Unlike the 32-bit case we do not insert the register into the opcode
9616 here, since the position is often unknown until the full instruction
9620 thumb_reg (strp
, hi_lo
)
9626 if ((reg
= reg_required_here (strp
, -1)) == FAIL
)
9634 inst
.error
= _("lo register required");
9642 inst
.error
= _("hi register required");
9654 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
9658 thumb_add_sub (str
, subtract
)
9662 int Rd
, Rs
, Rn
= FAIL
;
9664 skip_whitespace (str
);
9666 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
9667 || skip_past_comma (&str
) == FAIL
)
9670 inst
.error
= BAD_ARGS
;
9674 if (is_immediate_prefix (*str
))
9678 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9683 if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
9686 if (skip_past_comma (&str
) == FAIL
)
9688 /* Two operand format, shuffle the registers
9689 and pretend there are 3. */
9693 else if (is_immediate_prefix (*str
))
9696 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9699 else if ((Rn
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
9703 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
9704 for the latter case, EXPR contains the immediate that was found. */
9707 /* All register format. */
9708 if (Rd
> 7 || Rs
> 7 || Rn
> 7)
9712 inst
.error
= _("dest and source1 must be the same register");
9716 /* Can't do this for SUB. */
9719 inst
.error
= _("subtract valid only on lo regs");
9723 inst
.instruction
= (T_OPCODE_ADD_HI
9724 | (Rd
> 7 ? THUMB_H1
: 0)
9725 | (Rn
> 7 ? THUMB_H2
: 0));
9726 inst
.instruction
|= (Rd
& 7) | ((Rn
& 7) << 3);
9730 inst
.instruction
= subtract
? T_OPCODE_SUB_R3
: T_OPCODE_ADD_R3
;
9731 inst
.instruction
|= Rd
| (Rs
<< 3) | (Rn
<< 6);
9736 /* Immediate expression, now things start to get nasty. */
9738 /* First deal with HI regs, only very restricted cases allowed:
9739 Adjusting SP, and using PC or SP to get an address. */
9740 if ((Rd
> 7 && (Rd
!= REG_SP
|| Rs
!= REG_SP
))
9741 || (Rs
> 7 && Rs
!= REG_SP
&& Rs
!= REG_PC
))
9743 inst
.error
= _("invalid Hi register with immediate");
9747 if (inst
.reloc
.exp
.X_op
!= O_constant
)
9749 /* Value isn't known yet, all we can do is store all the fragments
9750 we know about in the instruction and let the reloc hacking
9752 inst
.instruction
= (subtract
? 0x8000 : 0) | (Rd
<< 4) | Rs
;
9753 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
9757 int offset
= inst
.reloc
.exp
.X_add_number
;
9767 /* Quick check, in case offset is MIN_INT. */
9770 inst
.error
= _("immediate value out of range");
9774 /* Note - you cannot convert a subtract of 0 into an
9775 add of 0 because the carry flag is set differently. */
9776 else if (offset
> 0)
9781 if (offset
& ~0x1fc)
9783 inst
.error
= _("invalid immediate value for stack adjust");
9786 inst
.instruction
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
9787 inst
.instruction
|= offset
>> 2;
9789 else if (Rs
== REG_PC
|| Rs
== REG_SP
)
9792 || (offset
& ~0x3fc))
9794 inst
.error
= _("invalid immediate for address calculation");
9797 inst
.instruction
= (Rs
== REG_PC
? T_OPCODE_ADD_PC
9799 inst
.instruction
|= (Rd
<< 8) | (offset
>> 2);
9805 inst
.error
= _("immediate value out of range");
9808 inst
.instruction
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
9809 inst
.instruction
|= (Rd
<< 8) | offset
;
9815 inst
.error
= _("immediate value out of range");
9818 inst
.instruction
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
9819 inst
.instruction
|= Rd
| (Rs
<< 3) | (offset
<< 6);
9828 thumb_shift (str
, shift
)
9832 int Rd
, Rs
, Rn
= FAIL
;
9834 skip_whitespace (str
);
9836 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9837 || skip_past_comma (&str
) == FAIL
)
9840 inst
.error
= BAD_ARGS
;
9844 if (is_immediate_prefix (*str
))
9846 /* Two operand immediate format, set Rs to Rd. */
9849 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9854 if ((Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9857 if (skip_past_comma (&str
) == FAIL
)
9859 /* Two operand format, shuffle the registers
9860 and pretend there are 3. */
9864 else if (is_immediate_prefix (*str
))
9867 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9870 else if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9874 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
9875 for the latter case, EXPR contains the immediate that was found. */
9881 inst
.error
= _("source1 and dest must be same register");
9887 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_R
; break;
9888 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_R
; break;
9889 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_R
; break;
9892 inst
.instruction
|= Rd
| (Rn
<< 3);
9898 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_I
; break;
9899 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_I
; break;
9900 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_I
; break;
9903 if (inst
.reloc
.exp
.X_op
!= O_constant
)
9905 /* Value isn't known yet, create a dummy reloc and let reloc
9906 hacking fix it up. */
9907 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_SHIFT
;
9911 unsigned shift_value
= inst
.reloc
.exp
.X_add_number
;
9913 if (shift_value
> 32 || (shift_value
== 32 && shift
== THUMB_LSL
))
9915 inst
.error
= _("invalid immediate for shift");
9919 /* Shifts of zero are handled by converting to LSL. */
9920 if (shift_value
== 0)
9921 inst
.instruction
= T_OPCODE_LSL_I
;
9923 /* Shifts of 32 are encoded as a shift of zero. */
9924 if (shift_value
== 32)
9927 inst
.instruction
|= shift_value
<< 6;
9930 inst
.instruction
|= Rd
| (Rs
<< 3);
9937 thumb_mov_compare (str
, move
)
9943 skip_whitespace (str
);
9945 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
9946 || skip_past_comma (&str
) == FAIL
)
9949 inst
.error
= BAD_ARGS
;
9953 if (move
!= THUMB_CPY
&& is_immediate_prefix (*str
))
9956 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9959 else if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
9964 if (move
!= THUMB_CPY
&& Rs
< 8 && Rd
< 8)
9966 if (move
== THUMB_MOVE
)
9967 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
9968 since a MOV instruction produces unpredictable results. */
9969 inst
.instruction
= T_OPCODE_ADD_I3
;
9971 inst
.instruction
= T_OPCODE_CMP_LR
;
9972 inst
.instruction
|= Rd
| (Rs
<< 3);
9976 if (move
== THUMB_MOVE
)
9977 inst
.instruction
= T_OPCODE_MOV_HR
;
9978 else if (move
!= THUMB_CPY
)
9979 inst
.instruction
= T_OPCODE_CMP_HR
;
9982 inst
.instruction
|= THUMB_H1
;
9985 inst
.instruction
|= THUMB_H2
;
9987 inst
.instruction
|= (Rd
& 7) | ((Rs
& 7) << 3);
9994 inst
.error
= _("only lo regs allowed with immediate");
9998 if (move
== THUMB_MOVE
)
9999 inst
.instruction
= T_OPCODE_MOV_I8
;
10001 inst
.instruction
= T_OPCODE_CMP_I8
;
10003 inst
.instruction
|= Rd
<< 8;
10005 if (inst
.reloc
.exp
.X_op
!= O_constant
)
10006 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_IMM
;
10009 unsigned value
= inst
.reloc
.exp
.X_add_number
;
10013 inst
.error
= _("invalid immediate");
10017 inst
.instruction
|= value
;
10025 thumb_load_store (str
, load_store
, size
)
10030 int Rd
, Rb
, Ro
= FAIL
;
10032 skip_whitespace (str
);
10034 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
10035 || skip_past_comma (&str
) == FAIL
)
10038 inst
.error
= BAD_ARGS
;
10045 if ((Rb
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
10048 if (skip_past_comma (&str
) != FAIL
)
10050 if (is_immediate_prefix (*str
))
10053 if (my_get_expression (&inst
.reloc
.exp
, &str
))
10056 else if ((Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
10061 inst
.reloc
.exp
.X_op
= O_constant
;
10062 inst
.reloc
.exp
.X_add_number
= 0;
10067 inst
.error
= _("expected ']'");
10072 else if (*str
== '=')
10074 if (load_store
!= THUMB_LOAD
)
10076 inst
.error
= _("invalid pseudo operation");
10080 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
10083 skip_whitespace (str
);
10085 if (my_get_expression (& inst
.reloc
.exp
, & str
))
10090 if ( inst
.reloc
.exp
.X_op
!= O_constant
10091 && inst
.reloc
.exp
.X_op
!= O_symbol
)
10093 inst
.error
= "Constant expression expected";
10097 if (inst
.reloc
.exp
.X_op
== O_constant
10098 && ((inst
.reloc
.exp
.X_add_number
& ~0xFF) == 0))
10100 /* This can be done with a mov instruction. */
10102 inst
.instruction
= T_OPCODE_MOV_I8
| (Rd
<< 8);
10103 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
10107 /* Insert into literal pool. */
10108 if (add_to_lit_pool () == FAIL
)
10111 inst
.error
= "literal pool insertion failed";
10115 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
10116 inst
.reloc
.pc_rel
= 1;
10117 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
10118 /* Adjust ARM pipeline offset to Thumb. */
10119 inst
.reloc
.exp
.X_add_number
+= 4;
10125 if (my_get_expression (&inst
.reloc
.exp
, &str
))
10128 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
10129 inst
.reloc
.pc_rel
= 1;
10130 inst
.reloc
.exp
.X_add_number
-= 4; /* Pipeline offset. */
10131 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
10136 if (Rb
== REG_PC
|| Rb
== REG_SP
)
10138 if (size
!= THUMB_WORD
)
10140 inst
.error
= _("byte or halfword not valid for base register");
10143 else if (Rb
== REG_PC
&& load_store
!= THUMB_LOAD
)
10145 inst
.error
= _("r15 based store not allowed");
10148 else if (Ro
!= FAIL
)
10150 inst
.error
= _("invalid base register for register offset");
10155 inst
.instruction
= T_OPCODE_LDR_PC
;
10156 else if (load_store
== THUMB_LOAD
)
10157 inst
.instruction
= T_OPCODE_LDR_SP
;
10159 inst
.instruction
= T_OPCODE_STR_SP
;
10161 inst
.instruction
|= Rd
<< 8;
10162 if (inst
.reloc
.exp
.X_op
== O_constant
)
10164 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
10166 if (offset
& ~0x3fc)
10168 inst
.error
= _("invalid offset");
10172 inst
.instruction
|= offset
>> 2;
10175 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
10179 inst
.error
= _("invalid base register in load/store");
10182 else if (Ro
== FAIL
)
10184 /* Immediate offset. */
10185 if (size
== THUMB_WORD
)
10186 inst
.instruction
= (load_store
== THUMB_LOAD
10187 ? T_OPCODE_LDR_IW
: T_OPCODE_STR_IW
);
10188 else if (size
== THUMB_HALFWORD
)
10189 inst
.instruction
= (load_store
== THUMB_LOAD
10190 ? T_OPCODE_LDR_IH
: T_OPCODE_STR_IH
);
10192 inst
.instruction
= (load_store
== THUMB_LOAD
10193 ? T_OPCODE_LDR_IB
: T_OPCODE_STR_IB
);
10195 inst
.instruction
|= Rd
| (Rb
<< 3);
10197 if (inst
.reloc
.exp
.X_op
== O_constant
)
10199 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
10201 if (offset
& ~(0x1f << size
))
10203 inst
.error
= _("invalid offset");
10206 inst
.instruction
|= (offset
>> size
) << 6;
10209 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
10213 /* Register offset. */
10214 if (size
== THUMB_WORD
)
10215 inst
.instruction
= (load_store
== THUMB_LOAD
10216 ? T_OPCODE_LDR_RW
: T_OPCODE_STR_RW
);
10217 else if (size
== THUMB_HALFWORD
)
10218 inst
.instruction
= (load_store
== THUMB_LOAD
10219 ? T_OPCODE_LDR_RH
: T_OPCODE_STR_RH
);
10221 inst
.instruction
= (load_store
== THUMB_LOAD
10222 ? T_OPCODE_LDR_RB
: T_OPCODE_STR_RB
);
10224 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
10230 /* A register must be given at this point.
10232 Shift is the place to put it in inst.instruction.
10234 Restores input start point on err.
10235 Returns the reg#, or FAIL. */
10238 mav_reg_required_here (str
, shift
, regtype
)
10241 enum arm_reg_type regtype
;
10244 char *start
= *str
;
10246 if ((reg
= arm_reg_parse (str
, all_reg_maps
[regtype
].htab
)) != FAIL
)
10249 inst
.instruction
|= reg
<< shift
;
10254 /* Restore the start point. */
10257 /* In the few cases where we might be able to accept something else
10258 this error can be overridden. */
10259 inst
.error
= _(all_reg_maps
[regtype
].expected
);
10264 /* Cirrus Maverick Instructions. */
10266 /* Wrapper functions. */
10269 do_mav_binops_1a (str
)
10272 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVF
);
10276 do_mav_binops_1b (str
)
10279 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVD
);
10283 do_mav_binops_1c (str
)
10286 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVDX
);
10290 do_mav_binops_1d (str
)
10293 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVF
);
10297 do_mav_binops_1e (str
)
10300 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVD
);
10304 do_mav_binops_1f (str
)
10307 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVF
);
10311 do_mav_binops_1g (str
)
10314 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVD
);
10318 do_mav_binops_1h (str
)
10321 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVFX
);
10325 do_mav_binops_1i (str
)
10328 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVFX
);
10332 do_mav_binops_1j (str
)
10335 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVDX
);
10339 do_mav_binops_1k (str
)
10342 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVDX
);
10346 do_mav_binops_1l (str
)
10349 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVF
);
10353 do_mav_binops_1m (str
)
10356 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVD
);
10360 do_mav_binops_1n (str
)
10363 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
10367 do_mav_binops_1o (str
)
10370 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
10374 do_mav_binops_2a (str
)
10377 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVF
, REG_TYPE_RN
);
10381 do_mav_binops_2b (str
)
10384 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVD
, REG_TYPE_RN
);
10388 do_mav_binops_2c (str
)
10391 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVDX
, REG_TYPE_RN
);
10395 do_mav_binops_3a (str
)
10398 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVFX
);
10402 do_mav_binops_3b (str
)
10405 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVFX
, REG_TYPE_MVAX
);
10409 do_mav_binops_3c (str
)
10412 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVDX
);
10416 do_mav_binops_3d (str
)
10419 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVDX
, REG_TYPE_MVAX
);
10423 do_mav_triple_4a (str
)
10426 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_RN
);
10430 do_mav_triple_4b (str
)
10433 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_RN
);
10437 do_mav_triple_5a (str
)
10440 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVF
, REG_TYPE_MVF
);
10444 do_mav_triple_5b (str
)
10447 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVD
, REG_TYPE_MVD
);
10451 do_mav_triple_5c (str
)
10454 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
10458 do_mav_triple_5d (str
)
10461 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
10465 do_mav_triple_5e (str
)
10468 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVF
, REG_TYPE_MVF
, REG_TYPE_MVF
);
10472 do_mav_triple_5f (str
)
10475 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVD
, REG_TYPE_MVD
, REG_TYPE_MVD
);
10479 do_mav_triple_5g (str
)
10482 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
10486 do_mav_triple_5h (str
)
10489 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
10493 do_mav_quad_6a (str
)
10496 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
,
10501 do_mav_quad_6b (str
)
10504 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVAX
, REG_TYPE_MVFX
,
10508 /* cfmvsc32<cond> DSPSC,MVDX[15:0]. */
10510 do_mav_dspsc_1 (str
)
10513 skip_whitespace (str
);
10516 if (mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
10517 || skip_past_comma (&str
) == FAIL
10518 || mav_reg_required_here (&str
, 12, REG_TYPE_MVDX
) == FAIL
)
10521 inst
.error
= BAD_ARGS
;
10529 /* cfmv32sc<cond> MVDX[15:0],DSPSC. */
10531 do_mav_dspsc_2 (str
)
10534 skip_whitespace (str
);
10537 if (mav_reg_required_here (&str
, 12, REG_TYPE_MVDX
) == FAIL
10538 || skip_past_comma (&str
) == FAIL
10539 || mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
)
10542 inst
.error
= BAD_ARGS
;
10551 do_mav_shift_1 (str
)
10554 do_mav_shift (str
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
10558 do_mav_shift_2 (str
)
10561 do_mav_shift (str
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
10565 do_mav_ldst_1 (str
)
10568 do_mav_ldst (str
, REG_TYPE_MVF
);
10572 do_mav_ldst_2 (str
)
10575 do_mav_ldst (str
, REG_TYPE_MVD
);
10579 do_mav_ldst_3 (str
)
10582 do_mav_ldst (str
, REG_TYPE_MVFX
);
10586 do_mav_ldst_4 (str
)
10589 do_mav_ldst (str
, REG_TYPE_MVDX
);
10592 /* Isnsn like "foo X,Y". */
10595 do_mav_binops (str
, mode
, reg0
, reg1
)
10598 enum arm_reg_type reg0
;
10599 enum arm_reg_type reg1
;
10601 int shift0
, shift1
;
10603 shift0
= mode
& 0xff;
10604 shift1
= (mode
>> 8) & 0xff;
10606 skip_whitespace (str
);
10608 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
10609 || skip_past_comma (&str
) == FAIL
10610 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
)
10613 inst
.error
= BAD_ARGS
;
10619 /* Isnsn like "foo X,Y,Z". */
10622 do_mav_triple (str
, mode
, reg0
, reg1
, reg2
)
10625 enum arm_reg_type reg0
;
10626 enum arm_reg_type reg1
;
10627 enum arm_reg_type reg2
;
10629 int shift0
, shift1
, shift2
;
10631 shift0
= mode
& 0xff;
10632 shift1
= (mode
>> 8) & 0xff;
10633 shift2
= (mode
>> 16) & 0xff;
10635 skip_whitespace (str
);
10637 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
10638 || skip_past_comma (&str
) == FAIL
10639 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
10640 || skip_past_comma (&str
) == FAIL
10641 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
)
10644 inst
.error
= BAD_ARGS
;
10650 /* Isnsn like "foo W,X,Y,Z".
10651 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
10654 do_mav_quad (str
, mode
, reg0
, reg1
, reg2
, reg3
)
10657 enum arm_reg_type reg0
;
10658 enum arm_reg_type reg1
;
10659 enum arm_reg_type reg2
;
10660 enum arm_reg_type reg3
;
10662 int shift0
, shift1
, shift2
, shift3
;
10664 shift0
= mode
& 0xff;
10665 shift1
= (mode
>> 8) & 0xff;
10666 shift2
= (mode
>> 16) & 0xff;
10667 shift3
= (mode
>> 24) & 0xff;
10669 skip_whitespace (str
);
10671 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
10672 || skip_past_comma (&str
) == FAIL
10673 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
10674 || skip_past_comma (&str
) == FAIL
10675 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
10676 || skip_past_comma (&str
) == FAIL
10677 || mav_reg_required_here (&str
, shift3
, reg3
) == FAIL
)
10680 inst
.error
= BAD_ARGS
;
10686 /* Maverick shift immediate instructions.
10687 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
10688 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
10691 do_mav_shift (str
, reg0
, reg1
)
10693 enum arm_reg_type reg0
;
10694 enum arm_reg_type reg1
;
10699 skip_whitespace (str
);
10703 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
10704 || skip_past_comma (&str
) == FAIL
10705 || mav_reg_required_here (&str
, 16, reg1
) == FAIL
10706 || skip_past_comma (&str
) == FAIL
)
10709 inst
.error
= BAD_ARGS
;
10713 /* Calculate the immediate operand.
10714 The operand is a 7bit signed number. */
10715 skip_whitespace (str
);
10720 if (!ISDIGIT (*str
) && *str
!= '-')
10722 inst
.error
= _("expecting immediate, 7bit operand");
10732 for (imm
= 0; *str
&& ISDIGIT (*str
); ++str
)
10733 imm
= imm
* 10 + *str
- '0';
10737 inst
.error
= _("immediate out of range");
10741 /* Make negative imm's into 7bit signed numbers. */
10748 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
10749 Bits 5-7 of the insn should have bits 4-6 of the immediate.
10750 Bit 4 should be 0. */
10751 imm
= (imm
& 0xf) | ((imm
& 0x70) << 1);
10753 inst
.instruction
|= imm
;
10758 mav_parse_offset (str
, negative
)
10767 skip_whitespace (p
);
10780 inst
.error
= _("offset expected");
10784 for (offset
= 0; *p
&& ISDIGIT (*p
); ++p
)
10785 offset
= offset
* 10 + *p
- '0';
10787 if (offset
> 0x3fc)
10789 inst
.error
= _("offset out of range");
10794 inst
.error
= _("offset not a multiple of 4");
10800 return *negative
? -offset
: offset
;
10803 /* Maverick load/store instructions.
10804 <insn><cond> CRd,[Rn,<offset>]{!}.
10805 <insn><cond> CRd,[Rn],<offset>. */
10808 do_mav_ldst (str
, reg0
)
10810 enum arm_reg_type reg0
;
10812 int offset
, negative
;
10814 skip_whitespace (str
);
10816 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
10817 || skip_past_comma (&str
) == FAIL
10819 || reg_required_here (&str
, 16) == FAIL
)
10822 if (skip_past_comma (&str
) == SUCCESS
)
10824 /* You are here: "<offset>]{!}". */
10825 inst
.instruction
|= PRE_INDEX
;
10827 offset
= mav_parse_offset (&str
, &negative
);
10834 inst
.error
= _("missing ]");
10840 inst
.instruction
|= WRITE_BACK
;
10846 /* You are here: "], <offset>". */
10849 inst
.error
= _("missing ]");
10853 if (skip_past_comma (&str
) == FAIL
10854 || (offset
= mav_parse_offset (&str
, &negative
), inst
.error
))
10857 inst
.instruction
|= CP_T_WB
; /* Post indexed, set bit W. */
10863 inst
.instruction
|= CP_T_UD
; /* Positive, so set bit U. */
10865 inst
.instruction
|= offset
>> 2;
10871 inst
.error
= BAD_ARGS
;
10882 /* Handle the Format 4 instructions that do not have equivalents in other
10883 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
10892 skip_whitespace (str
);
10894 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
10895 || skip_past_comma (&str
) == FAIL
10896 || (Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
10898 inst
.error
= BAD_ARGS
;
10902 if (skip_past_comma (&str
) != FAIL
)
10904 /* Three operand format not allowed for TST, CMN, NEG and MVN.
10905 (It isn't allowed for CMP either, but that isn't handled by this
10907 if (inst
.instruction
== T_OPCODE_TST
10908 || inst
.instruction
== T_OPCODE_CMN
10909 || inst
.instruction
== T_OPCODE_NEG
10910 || inst
.instruction
== T_OPCODE_MVN
)
10912 inst
.error
= BAD_ARGS
;
10916 if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
10921 inst
.error
= _("dest and source1 must be the same register");
10927 if (inst
.instruction
== T_OPCODE_MUL
10929 as_tsktsk (_("Rs and Rd must be different in MUL"));
10931 inst
.instruction
|= Rd
| (Rs
<< 3);
10939 thumb_add_sub (str
, 0);
10946 thumb_shift (str
, THUMB_ASR
);
10953 if (my_get_expression (&inst
.reloc
.exp
, &str
))
10955 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH9
;
10956 inst
.reloc
.pc_rel
= 1;
10961 do_t_branch12 (str
)
10964 if (my_get_expression (&inst
.reloc
.exp
, &str
))
10966 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH12
;
10967 inst
.reloc
.pc_rel
= 1;
10971 /* Find the real, Thumb encoded start of a Thumb function. */
10974 find_real_start (symbolP
)
10978 const char * name
= S_GET_NAME (symbolP
);
10979 symbolS
* new_target
;
10981 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
10982 #define STUB_NAME ".real_start_of"
10987 /* Names that start with '.' are local labels, not function entry points.
10988 The compiler may generate BL instructions to these labels because it
10989 needs to perform a branch to a far away location. */
10990 if (name
[0] == '.')
10993 real_start
= malloc (strlen (name
) + strlen (STUB_NAME
) + 1);
10994 sprintf (real_start
, "%s%s", STUB_NAME
, name
);
10996 new_target
= symbol_find (real_start
);
10998 if (new_target
== NULL
)
11000 as_warn ("Failed to find real start of function: %s\n", name
);
11001 new_target
= symbolP
;
11010 do_t_branch23 (str
)
11013 if (my_get_expression (& inst
.reloc
.exp
, & str
))
11016 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH23
;
11017 inst
.reloc
.pc_rel
= 1;
11020 /* If the destination of the branch is a defined symbol which does not have
11021 the THUMB_FUNC attribute, then we must be calling a function which has
11022 the (interfacearm) attribute. We look for the Thumb entry point to that
11023 function and change the branch to refer to that function instead. */
11024 if ( inst
.reloc
.exp
.X_op
== O_symbol
11025 && inst
.reloc
.exp
.X_add_symbol
!= NULL
11026 && S_IS_DEFINED (inst
.reloc
.exp
.X_add_symbol
)
11027 && ! THUMB_IS_FUNC (inst
.reloc
.exp
.X_add_symbol
))
11028 inst
.reloc
.exp
.X_add_symbol
=
11029 find_real_start (inst
.reloc
.exp
.X_add_symbol
);
11038 skip_whitespace (str
);
11040 if ((reg
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
11043 /* This sets THUMB_H2 from the top bit of reg. */
11044 inst
.instruction
|= reg
<< 3;
11046 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
11047 should cause the alignment to be checked once it is known. This is
11048 because BX PC only works if the instruction is word aligned. */
11057 thumb_mov_compare (str
, THUMB_COMPARE
);
11067 skip_whitespace (str
);
11069 if ((Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
11073 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
11077 if (skip_past_comma (&str
) == FAIL
11078 || (range
= reg_list (&str
)) == FAIL
)
11081 inst
.error
= BAD_ARGS
;
11085 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
11087 /* This really doesn't seem worth it. */
11088 inst
.reloc
.type
= BFD_RELOC_NONE
;
11089 inst
.error
= _("expression too complex");
11095 inst
.error
= _("only lo-regs valid in load/store multiple");
11099 inst
.instruction
|= (Rb
<< 8) | range
;
11107 thumb_load_store (str
, THUMB_LOAD
, THUMB_WORD
);
11114 thumb_load_store (str
, THUMB_LOAD
, THUMB_BYTE
);
11121 thumb_load_store (str
, THUMB_LOAD
, THUMB_HALFWORD
);
11130 skip_whitespace (str
);
11132 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
11133 || skip_past_comma (&str
) == FAIL
11135 || (Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
11136 || skip_past_comma (&str
) == FAIL
11137 || (Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
11141 inst
.error
= _("syntax: ldrs[b] Rd, [Rb, Ro]");
11145 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
11153 thumb_shift (str
, THUMB_LSL
);
11160 thumb_shift (str
, THUMB_LSR
);
11167 thumb_mov_compare (str
, THUMB_MOVE
);
11171 do_t_push_pop (str
)
11176 skip_whitespace (str
);
11178 if ((range
= reg_list (&str
)) == FAIL
)
11181 inst
.error
= BAD_ARGS
;
11185 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
11187 /* This really doesn't seem worth it. */
11188 inst
.reloc
.type
= BFD_RELOC_NONE
;
11189 inst
.error
= _("expression too complex");
11195 if ((inst
.instruction
== T_OPCODE_PUSH
11196 && (range
& ~0xff) == 1 << REG_LR
)
11197 || (inst
.instruction
== T_OPCODE_POP
11198 && (range
& ~0xff) == 1 << REG_PC
))
11200 inst
.instruction
|= THUMB_PP_PC_LR
;
11205 inst
.error
= _("invalid register list to push/pop instruction");
11210 inst
.instruction
|= range
;
11218 thumb_load_store (str
, THUMB_STORE
, THUMB_WORD
);
11225 thumb_load_store (str
, THUMB_STORE
, THUMB_BYTE
);
11232 thumb_load_store (str
, THUMB_STORE
, THUMB_HALFWORD
);
11239 thumb_add_sub (str
, 1);
11246 skip_whitespace (str
);
11248 if (my_get_expression (&inst
.reloc
.exp
, &str
))
11251 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
11261 /* This is a pseudo-op of the form "adr rd, label" to be converted
11262 into a relative address of the form "add rd, pc, #label-.-4". */
11263 skip_whitespace (str
);
11265 /* Store Rd in temporary location inside instruction. */
11266 if ((reg
= reg_required_here (&str
, 4)) == FAIL
11267 || (reg
> 7) /* For Thumb reg must be r0..r7. */
11268 || skip_past_comma (&str
) == FAIL
11269 || my_get_expression (&inst
.reloc
.exp
, &str
))
11272 inst
.error
= BAD_ARGS
;
11276 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
11277 inst
.reloc
.exp
.X_add_number
-= 4; /* PC relative adjust. */
11278 inst
.reloc
.pc_rel
= 1;
11279 inst
.instruction
|= REG_PC
; /* Rd is already placed into the instruction. */
11285 insert_reg (r
, htab
)
11286 const struct reg_entry
*r
;
11287 struct hash_control
*htab
;
11289 int len
= strlen (r
->name
) + 2;
11290 char * buf
= (char *) xmalloc (len
);
11291 char * buf2
= (char *) xmalloc (len
);
11294 #ifdef REGISTER_PREFIX
11295 buf
[i
++] = REGISTER_PREFIX
;
11298 strcpy (buf
+ i
, r
->name
);
11300 for (i
= 0; buf
[i
]; i
++)
11301 buf2
[i
] = TOUPPER (buf
[i
]);
11305 hash_insert (htab
, buf
, (PTR
) r
);
11306 hash_insert (htab
, buf2
, (PTR
) r
);
11310 build_reg_hsh (map
)
11311 struct reg_map
*map
;
11313 const struct reg_entry
*r
;
11315 if ((map
->htab
= hash_new ()) == NULL
)
11316 as_fatal (_("virtual memory exhausted"));
11318 for (r
= map
->names
; r
->name
!= NULL
; r
++)
11319 insert_reg (r
, map
->htab
);
11323 insert_reg_alias (str
, regnum
, htab
)
11326 struct hash_control
*htab
;
11329 struct reg_entry
*new = xmalloc (sizeof (struct reg_entry
));
11330 const char *name
= xmalloc (strlen (str
) + 1);
11332 strcpy ((char *) name
, str
);
11335 new->number
= regnum
;
11336 new->builtin
= FALSE
;
11338 error
= hash_insert (htab
, name
, (PTR
) new);
11341 as_bad (_("failed to create an alias for %s, reason: %s"),
11343 free ((char *) name
);
11348 /* Look for the .req directive. This is of the form:
11350 new_register_name .req existing_register_name
11352 If we find one, or if it looks sufficiently like one that we want to
11353 handle any error here, return non-zero. Otherwise return zero. */
11355 create_register_alias (newname
, p
)
11363 skip_whitespace (q
);
11368 if (*q
&& !strncmp (q
, ".req ", 5))
11373 #ifndef IGNORE_OPCODE_CASE
11374 newname
= original_case_string
;
11376 copy_of_str
= newname
;
11379 skip_whitespace (q
);
11381 for (r
= q
; *r
!= '\0'; r
++)
11387 enum arm_reg_type new_type
, old_type
;
11392 old_type
= arm_reg_parse_any (q
);
11395 new_type
= arm_reg_parse_any (newname
);
11397 if (new_type
== REG_TYPE_MAX
)
11399 if (old_type
!= REG_TYPE_MAX
)
11401 old_regno
= arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
);
11402 insert_reg_alias (newname
, old_regno
,
11403 all_reg_maps
[old_type
].htab
);
11406 as_warn (_("register '%s' does not exist\n"), q
);
11408 else if (old_type
== REG_TYPE_MAX
)
11410 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
11415 /* Do not warn about redefinitions to the same alias. */
11416 if (new_type
!= old_type
11417 || (arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
)
11418 != arm_reg_parse (&q
, all_reg_maps
[new_type
].htab
)))
11419 as_warn (_("ignoring redefinition of register alias '%s'"),
11425 as_warn (_("ignoring incomplete .req pseuso op"));
11436 set_constant_flonums ()
11440 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
11441 if (atof_ieee ((char *) fp_const
[i
], 'x', fp_values
[i
]) == NULL
)
11445 /* Iterate over the base tables to create the instruction patterns. */
11447 build_arm_ops_hsh ()
11451 static struct obstack insn_obstack
;
11453 obstack_begin (&insn_obstack
, 4000);
11455 for (i
= 0; i
< sizeof (insns
) / sizeof (struct asm_opcode
); i
++)
11457 const struct asm_opcode
*insn
= insns
+ i
;
11459 if (insn
->cond_offset
!= 0)
11461 /* Insn supports conditional execution. Build the varaints
11462 and insert them in the hash table. */
11463 for (j
= 0; j
< sizeof (conds
) / sizeof (struct asm_cond
); j
++)
11465 unsigned len
= strlen (insn
->template);
11466 struct asm_opcode
*new;
11469 new = obstack_alloc (&insn_obstack
, sizeof (struct asm_opcode
));
11470 /* All condition codes are two characters. */
11471 template = obstack_alloc (&insn_obstack
, len
+ 3);
11473 strncpy (template, insn
->template, insn
->cond_offset
);
11474 strcpy (template + insn
->cond_offset
, conds
[j
].template);
11475 if (len
> insn
->cond_offset
)
11476 strcpy (template + insn
->cond_offset
+ 2,
11477 insn
->template + insn
->cond_offset
);
11478 new->template = template;
11479 new->cond_offset
= 0;
11480 new->variant
= insn
->variant
;
11481 new->parms
= insn
->parms
;
11482 new->value
= (insn
->value
& ~COND_MASK
) | conds
[j
].value
;
11484 hash_insert (arm_ops_hsh
, new->template, (PTR
) new);
11487 /* Finally, insert the unconditional insn in the table directly;
11488 no need to build a copy. */
11489 hash_insert (arm_ops_hsh
, insn
->template, (PTR
) insn
);
11493 #if 0 /* Suppressed - for now. */
11494 #if defined OBJ_ELF || defined OBJ_COFF
11497 #define arm_Note Elf_External_Note
11501 unsigned char namesz
[4]; /* Size of entry's owner string. */
11502 unsigned char descsz
[4]; /* Size of the note descriptor. */
11503 unsigned char type
[4]; /* Interpretation of the descriptor. */
11504 char name
[1]; /* Start of the name+desc data. */
11508 /* The description is kept to a fix sized in order to make updating
11509 it and merging it easier. */
11510 #define ARM_NOTE_DESCRIPTION_LENGTH 8
11513 arm_add_note (name
, description
, type
)
11515 const char * description
;
11518 arm_Note note ATTRIBUTE_UNUSED
;
11520 unsigned int name_len
;
11522 name_len
= (strlen (name
) + 1 + 3) & ~3;
11524 p
= frag_more (sizeof (note
.namesz
));
11525 md_number_to_chars (p
, (valueT
) name_len
, sizeof (note
.namesz
));
11527 p
= frag_more (sizeof (note
.descsz
));
11528 md_number_to_chars (p
, (valueT
) ARM_NOTE_DESCRIPTION_LENGTH
, sizeof (note
.descsz
));
11530 p
= frag_more (sizeof (note
.type
));
11531 md_number_to_chars (p
, (valueT
) type
, sizeof (note
.type
));
11533 p
= frag_more (name_len
);
11536 p
= frag_more (ARM_NOTE_DESCRIPTION_LENGTH
);
11537 strncpy (p
, description
, ARM_NOTE_DESCRIPTION_LENGTH
);
11538 frag_align (2, 0, 0);
11549 if ( (arm_ops_hsh
= hash_new ()) == NULL
11550 || (arm_tops_hsh
= hash_new ()) == NULL
11551 || (arm_cond_hsh
= hash_new ()) == NULL
11552 || (arm_shift_hsh
= hash_new ()) == NULL
11553 || (arm_psr_hsh
= hash_new ()) == NULL
)
11554 as_fatal (_("virtual memory exhausted"));
11556 build_arm_ops_hsh ();
11557 for (i
= 0; i
< sizeof (tinsns
) / sizeof (struct thumb_opcode
); i
++)
11558 hash_insert (arm_tops_hsh
, tinsns
[i
].template, (PTR
) (tinsns
+ i
));
11559 for (i
= 0; i
< sizeof (conds
) / sizeof (struct asm_cond
); i
++)
11560 hash_insert (arm_cond_hsh
, conds
[i
].template, (PTR
) (conds
+ i
));
11561 for (i
= 0; i
< sizeof (shift_names
) / sizeof (struct asm_shift_name
); i
++)
11562 hash_insert (arm_shift_hsh
, shift_names
[i
].name
, (PTR
) (shift_names
+ i
));
11563 for (i
= 0; i
< sizeof (psrs
) / sizeof (struct asm_psr
); i
++)
11564 hash_insert (arm_psr_hsh
, psrs
[i
].template, (PTR
) (psrs
+ i
));
11566 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
11567 build_reg_hsh (all_reg_maps
+ i
);
11569 set_constant_flonums ();
11571 /* Set the cpu variant based on the command-line options. We prefer
11572 -mcpu= over -march= if both are set (as for GCC); and we prefer
11573 -mfpu= over any other way of setting the floating point unit.
11574 Use of legacy options with new options are faulted. */
11575 if (legacy_cpu
!= -1)
11577 if (mcpu_cpu_opt
!= -1 || march_cpu_opt
!= -1)
11578 as_bad (_("use of old and new-style options to set CPU type"));
11580 mcpu_cpu_opt
= legacy_cpu
;
11582 else if (mcpu_cpu_opt
== -1)
11583 mcpu_cpu_opt
= march_cpu_opt
;
11585 if (legacy_fpu
!= -1)
11587 if (mfpu_opt
!= -1)
11588 as_bad (_("use of old and new-style options to set FPU type"));
11590 mfpu_opt
= legacy_fpu
;
11592 else if (mfpu_opt
== -1)
11594 #if !(defined (TE_LINUX) || defined (TE_NetBSD))
11595 /* Some environments specify a default FPU. If they don't, infer it
11596 from the processor. */
11597 if (mcpu_fpu_opt
!= -1)
11598 mfpu_opt
= mcpu_fpu_opt
;
11600 mfpu_opt
= march_fpu_opt
;
11602 mfpu_opt
= FPU_DEFAULT
;
11606 if (mfpu_opt
== -1)
11608 if (mcpu_cpu_opt
== -1)
11609 mfpu_opt
= FPU_DEFAULT
;
11610 else if (mcpu_cpu_opt
& ARM_EXT_V5
)
11611 mfpu_opt
= FPU_ARCH_VFP_V2
;
11613 mfpu_opt
= FPU_ARCH_FPA
;
11616 if (mcpu_cpu_opt
== -1)
11617 mcpu_cpu_opt
= CPU_DEFAULT
;
11619 cpu_variant
= mcpu_cpu_opt
| mfpu_opt
;
11622 unsigned int flags
= 0;
11624 #if defined OBJ_ELF
11625 flags
= meabi_flags
;
11627 switch (meabi_flags
)
11629 case EF_ARM_EABI_UNKNOWN
:
11631 #if defined OBJ_COFF || defined OBJ_ELF
11632 /* Set the flags in the private structure. */
11633 if (uses_apcs_26
) flags
|= F_APCS26
;
11634 if (support_interwork
) flags
|= F_INTERWORK
;
11635 if (uses_apcs_float
) flags
|= F_APCS_FLOAT
;
11636 if (pic_code
) flags
|= F_PIC
;
11637 if ((cpu_variant
& FPU_ANY
) == FPU_NONE
11638 || (cpu_variant
& FPU_ANY
) == FPU_ARCH_VFP
) /* VFP layout only. */
11639 flags
|= F_SOFT_FLOAT
;
11641 switch (mfloat_abi_opt
)
11643 case ARM_FLOAT_ABI_SOFT
:
11644 case ARM_FLOAT_ABI_SOFTFP
:
11645 flags
|= F_SOFT_FLOAT
;
11648 case ARM_FLOAT_ABI_HARD
:
11649 if (flags
& F_SOFT_FLOAT
)
11650 as_bad (_("hard-float conflicts with specified fpu"));
11654 /* Using VFP conventions (even if soft-float). */
11655 if (cpu_variant
& FPU_VFP_EXT_NONE
)
11656 flags
|= F_VFP_FLOAT
;
11658 #if defined OBJ_ELF
11659 if (cpu_variant
& FPU_ARCH_MAVERICK
)
11660 flags
|= EF_ARM_MAVERICK_FLOAT
;
11663 case EF_ARM_EABI_VER3
:
11664 /* No additional flags to set. */
11671 #if defined OBJ_COFF || defined OBJ_ELF
11672 bfd_set_private_flags (stdoutput
, flags
);
11674 /* We have run out flags in the COFF header to encode the
11675 status of ATPCS support, so instead we create a dummy,
11676 empty, debug section called .arm.atpcs. */
11681 sec
= bfd_make_section (stdoutput
, ".arm.atpcs");
11685 bfd_set_section_flags
11686 (stdoutput
, sec
, SEC_READONLY
| SEC_DEBUGGING
/* | SEC_HAS_CONTENTS */);
11687 bfd_set_section_size (stdoutput
, sec
, 0);
11688 bfd_set_section_contents (stdoutput
, sec
, NULL
, 0, 0);
11694 /* Record the CPU type as well. */
11695 switch (cpu_variant
& ARM_CPU_MASK
)
11698 mach
= bfd_mach_arm_2
;
11701 case ARM_3
: /* Also ARM_250. */
11702 mach
= bfd_mach_arm_2a
;
11705 case ARM_6
: /* Also ARM_7. */
11706 mach
= bfd_mach_arm_3
;
11710 mach
= bfd_mach_arm_unknown
;
11714 /* Catch special cases. */
11715 if (cpu_variant
& ARM_CEXT_IWMMXT
)
11716 mach
= bfd_mach_arm_iWMMXt
;
11717 else if (cpu_variant
& ARM_CEXT_XSCALE
)
11718 mach
= bfd_mach_arm_XScale
;
11719 else if (cpu_variant
& ARM_CEXT_MAVERICK
)
11720 mach
= bfd_mach_arm_ep9312
;
11721 else if (cpu_variant
& ARM_EXT_V5E
)
11722 mach
= bfd_mach_arm_5TE
;
11723 else if (cpu_variant
& ARM_EXT_V5
)
11725 if (cpu_variant
& ARM_EXT_V4T
)
11726 mach
= bfd_mach_arm_5T
;
11728 mach
= bfd_mach_arm_5
;
11730 else if (cpu_variant
& ARM_EXT_V4
)
11732 if (cpu_variant
& ARM_EXT_V4T
)
11733 mach
= bfd_mach_arm_4T
;
11735 mach
= bfd_mach_arm_4
;
11737 else if (cpu_variant
& ARM_EXT_V3M
)
11738 mach
= bfd_mach_arm_3M
;
11740 #if 0 /* Suppressed - for now. */
11741 #if defined (OBJ_ELF) || defined (OBJ_COFF)
11743 /* Create a .note section to fully identify this arm binary. */
11745 #define NOTE_ARCH_STRING "arch: "
11747 #if defined OBJ_COFF && ! defined NT_VERSION
11748 #define NT_VERSION 1
11753 segT current_seg
= now_seg
;
11754 subsegT current_subseg
= now_subseg
;
11755 asection
* arm_arch
;
11756 const char * arch_string
;
11758 arm_arch
= bfd_make_section_old_way (stdoutput
, ARM_NOTE_SECTION
);
11761 bfd_set_section_flags (stdoutput
, arm_arch
,
11762 SEC_DATA
| SEC_ALLOC
| SEC_LOAD
| SEC_LINK_ONCE \
11763 | SEC_HAS_CONTENTS
);
11765 bfd_set_section_flags (stdoutput
, arm_arch
,
11766 SEC_READONLY
| SEC_HAS_CONTENTS
);
11768 arm_arch
->output_section
= arm_arch
;
11769 subseg_set (arm_arch
, 0);
11774 case bfd_mach_arm_unknown
: arch_string
= "unknown"; break;
11775 case bfd_mach_arm_2
: arch_string
= "armv2"; break;
11776 case bfd_mach_arm_2a
: arch_string
= "armv2a"; break;
11777 case bfd_mach_arm_3
: arch_string
= "armv3"; break;
11778 case bfd_mach_arm_3M
: arch_string
= "armv3M"; break;
11779 case bfd_mach_arm_4
: arch_string
= "armv4"; break;
11780 case bfd_mach_arm_4T
: arch_string
= "armv4t"; break;
11781 case bfd_mach_arm_5
: arch_string
= "armv5"; break;
11782 case bfd_mach_arm_5T
: arch_string
= "armv5t"; break;
11783 case bfd_mach_arm_5TE
: arch_string
= "armv5te"; break;
11784 case bfd_mach_arm_XScale
: arch_string
= "XScale"; break;
11785 case bfd_mach_arm_ep9312
: arch_string
= "ep9312"; break;
11786 case bfd_mach_arm_iWMMXt
: arch_string
= "iWMMXt"; break;
11789 arm_add_note (NOTE_ARCH_STRING
, arch_string
, NT_ARCH
);
11791 subseg_set (current_seg
, current_subseg
);
11794 #endif /* Suppressed code. */
11796 bfd_set_arch_mach (stdoutput
, TARGET_ARCH
, mach
);
11799 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11800 for use in the a.out file, and stores them in the array pointed to by buf.
11801 This knows about the endian-ness of the target machine and does
11802 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11803 2 (short) and 4 (long) Floating numbers are put out as a series of
11804 LITTLENUMS (shorts, here at least). */
11807 md_number_to_chars (buf
, val
, n
)
11812 if (target_big_endian
)
11813 number_to_chars_bigendian (buf
, val
, n
);
11815 number_to_chars_littleendian (buf
, val
, n
);
11819 md_chars_to_number (buf
, n
)
11824 unsigned char * where
= (unsigned char *) buf
;
11826 if (target_big_endian
)
11831 result
|= (*where
++ & 255);
11839 result
|= (where
[n
] & 255);
11846 /* Turn a string in input_line_pointer into a floating point constant
11847 of type TYPE, and store the appropriate bytes in *LITP. The number
11848 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11849 returned, or NULL on OK.
11851 Note that fp constants aren't represent in the normal way on the ARM.
11852 In big endian mode, things are as expected. However, in little endian
11853 mode fp constants are big-endian word-wise, and little-endian byte-wise
11854 within the words. For example, (double) 1.1 in big endian mode is
11855 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11856 the byte sequence 99 99 f1 3f 9a 99 99 99.
11858 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11861 md_atof (type
, litP
, sizeP
)
11867 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
11899 return _("bad call to MD_ATOF()");
11902 t
= atof_ieee (input_line_pointer
, type
, words
);
11904 input_line_pointer
= t
;
11907 if (target_big_endian
)
11909 for (i
= 0; i
< prec
; i
++)
11911 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
11917 if (cpu_variant
& FPU_ARCH_VFP
)
11918 for (i
= prec
- 1; i
>= 0; i
--)
11920 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
11924 /* For a 4 byte float the order of elements in `words' is 1 0.
11925 For an 8 byte float the order is 1 0 3 2. */
11926 for (i
= 0; i
< prec
; i
+= 2)
11928 md_number_to_chars (litP
, (valueT
) words
[i
+ 1], 2);
11929 md_number_to_chars (litP
+ 2, (valueT
) words
[i
], 2);
11937 /* The knowledge of the PC's pipeline offset is built into the insns
11941 md_pcrel_from (fixP
)
11945 && S_GET_SEGMENT (fixP
->fx_addsy
) == undefined_section
11946 && fixP
->fx_subsy
== NULL
)
11949 if (fixP
->fx_pcrel
&& (fixP
->fx_r_type
== BFD_RELOC_ARM_THUMB_ADD
))
11951 /* PC relative addressing on the Thumb is slightly odd
11952 as the bottom two bits of the PC are forced to zero
11953 for the calculation. */
11954 return (fixP
->fx_where
+ fixP
->fx_frag
->fr_address
) & ~3;
11958 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
11959 so we un-adjust here to compensate for the accommodation. */
11960 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
+ 8;
11962 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
11966 /* Round up a section size to the appropriate boundary. */
11969 md_section_align (segment
, size
)
11970 segT segment ATTRIBUTE_UNUSED
;
11976 /* Round all sects to multiple of 4. */
11977 return (size
+ 3) & ~3;
11981 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
11982 Otherwise we have no need to default values of symbols. */
11985 md_undefined_symbol (name
)
11986 char * name ATTRIBUTE_UNUSED
;
11989 if (name
[0] == '_' && name
[1] == 'G'
11990 && streq (name
, GLOBAL_OFFSET_TABLE_NAME
))
11994 if (symbol_find (name
))
11995 as_bad ("GOT already in the symbol table");
11997 GOT_symbol
= symbol_new (name
, undefined_section
,
11998 (valueT
) 0, & zero_address_frag
);
12008 /* arm_reg_parse () := if it looks like a register, return its token and
12009 advance the pointer. */
12012 arm_reg_parse (ccp
, htab
)
12013 register char ** ccp
;
12014 struct hash_control
*htab
;
12016 char * start
= * ccp
;
12019 struct reg_entry
* reg
;
12021 #ifdef REGISTER_PREFIX
12022 if (*start
!= REGISTER_PREFIX
)
12027 #ifdef OPTIONAL_REGISTER_PREFIX
12028 if (*p
== OPTIONAL_REGISTER_PREFIX
)
12032 if (!ISALPHA (*p
) || !is_name_beginner (*p
))
12036 while (ISALPHA (c
) || ISDIGIT (c
) || c
== '_')
12040 reg
= (struct reg_entry
*) hash_find (htab
, start
);
12046 return reg
->number
;
12052 /* Search for the following register name in each of the possible reg name
12053 tables. Return the classification if found, or REG_TYPE_MAX if not
12055 static enum arm_reg_type
12056 arm_reg_parse_any (cp
)
12061 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
12062 if (arm_reg_parse (&cp
, all_reg_maps
[i
].htab
) != FAIL
)
12063 return (enum arm_reg_type
) i
;
12065 return REG_TYPE_MAX
;
12069 md_apply_fix3 (fixP
, valP
, seg
)
12074 offsetT value
= * valP
;
12076 unsigned int newimm
;
12077 unsigned long temp
;
12079 char * buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
12080 arm_fix_data
* arm_data
= (arm_fix_data
*) fixP
->tc_fix_data
;
12082 assert (fixP
->fx_r_type
< BFD_RELOC_UNUSED
);
12084 /* Note whether this will delete the relocation. */
12086 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
12087 doesn't work fully.) */
12088 if ((fixP
->fx_addsy
== 0 || symbol_constant_p (fixP
->fx_addsy
))
12089 && !fixP
->fx_pcrel
)
12091 if (fixP
->fx_addsy
== 0 && !fixP
->fx_pcrel
)
12095 /* If this symbol is in a different section then we need to leave it for
12096 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
12097 so we have to undo it's effects here. */
12098 if (fixP
->fx_pcrel
)
12100 if (fixP
->fx_addsy
!= NULL
12101 && S_IS_DEFINED (fixP
->fx_addsy
)
12102 && S_GET_SEGMENT (fixP
->fx_addsy
) != seg
)
12105 && (fixP
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
12106 || fixP
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
12110 value
+= md_pcrel_from (fixP
);
12114 /* Remember value for emit_reloc. */
12115 fixP
->fx_addnumber
= value
;
12117 switch (fixP
->fx_r_type
)
12119 case BFD_RELOC_ARM_IMMEDIATE
:
12120 /* We claim that this fixup has been processed here,
12121 even if in fact we generate an error because we do
12122 not have a reloc for it, so tc_gen_reloc will reject it. */
12126 && ! S_IS_DEFINED (fixP
->fx_addsy
))
12128 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12129 _("undefined symbol %s used as an immediate value"),
12130 S_GET_NAME (fixP
->fx_addsy
));
12134 newimm
= validate_immediate (value
);
12135 temp
= md_chars_to_number (buf
, INSN_SIZE
);
12137 /* If the instruction will fail, see if we can fix things up by
12138 changing the opcode. */
12139 if (newimm
== (unsigned int) FAIL
12140 && (newimm
= negate_data_op (&temp
, value
)) == (unsigned int) FAIL
)
12142 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12143 _("invalid constant (%lx) after fixup"),
12144 (unsigned long) value
);
12148 newimm
|= (temp
& 0xfffff000);
12149 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
12152 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
12154 unsigned int highpart
= 0;
12155 unsigned int newinsn
= 0xe1a00000; /* nop. */
12157 newimm
= validate_immediate (value
);
12158 temp
= md_chars_to_number (buf
, INSN_SIZE
);
12160 /* If the instruction will fail, see if we can fix things up by
12161 changing the opcode. */
12162 if (newimm
== (unsigned int) FAIL
12163 && (newimm
= negate_data_op (& temp
, value
)) == (unsigned int) FAIL
)
12165 /* No ? OK - try using two ADD instructions to generate
12167 newimm
= validate_immediate_twopart (value
, & highpart
);
12169 /* Yes - then make sure that the second instruction is
12171 if (newimm
!= (unsigned int) FAIL
)
12173 /* Still No ? Try using a negated value. */
12174 else if ((newimm
= validate_immediate_twopart (- value
, & highpart
)) != (unsigned int) FAIL
)
12175 temp
= newinsn
= (temp
& OPCODE_MASK
) | OPCODE_SUB
<< DATA_OP_SHIFT
;
12176 /* Otherwise - give up. */
12179 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12180 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
12185 /* Replace the first operand in the 2nd instruction (which
12186 is the PC) with the destination register. We have
12187 already added in the PC in the first instruction and we
12188 do not want to do it again. */
12189 newinsn
&= ~ 0xf0000;
12190 newinsn
|= ((newinsn
& 0x0f000) << 4);
12193 newimm
|= (temp
& 0xfffff000);
12194 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
12196 highpart
|= (newinsn
& 0xfffff000);
12197 md_number_to_chars (buf
+ INSN_SIZE
, (valueT
) highpart
, INSN_SIZE
);
12201 case BFD_RELOC_ARM_OFFSET_IMM
:
12207 if (validate_offset_imm (value
, 0) == FAIL
)
12209 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12210 _("bad immediate value for offset (%ld)"),
12215 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12216 newval
&= 0xff7ff000;
12217 newval
|= value
| (sign
? INDEX_UP
: 0);
12218 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12221 case BFD_RELOC_ARM_OFFSET_IMM8
:
12222 case BFD_RELOC_ARM_HWLITERAL
:
12228 if (validate_offset_imm (value
, 1) == FAIL
)
12230 if (fixP
->fx_r_type
== BFD_RELOC_ARM_HWLITERAL
)
12231 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12232 _("invalid literal constant: pool needs to be closer"));
12234 as_bad (_("bad immediate value for half-word offset (%ld)"),
12239 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12240 newval
&= 0xff7ff0f0;
12241 newval
|= ((value
>> 4) << 8) | (value
& 0xf) | (sign
? INDEX_UP
: 0);
12242 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12245 case BFD_RELOC_ARM_LITERAL
:
12251 if (validate_offset_imm (value
, 0) == FAIL
)
12253 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12254 _("invalid literal constant: pool needs to be closer"));
12258 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12259 newval
&= 0xff7ff000;
12260 newval
|= value
| (sign
? INDEX_UP
: 0);
12261 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12264 case BFD_RELOC_ARM_SHIFT_IMM
:
12265 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12266 if (((unsigned long) value
) > 32
12268 && (((newval
& 0x60) == 0) || (newval
& 0x60) == 0x60)))
12270 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12271 _("shift expression is too large"));
12276 /* Shifts of zero must be done as lsl. */
12278 else if (value
== 32)
12280 newval
&= 0xfffff07f;
12281 newval
|= (value
& 0x1f) << 7;
12282 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12285 case BFD_RELOC_ARM_SWI
:
12286 if (arm_data
->thumb_mode
)
12288 if (((unsigned long) value
) > 0xff)
12289 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12290 _("invalid swi expression"));
12291 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xff00;
12293 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12297 if (((unsigned long) value
) > 0x00ffffff)
12298 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12299 _("invalid swi expression"));
12300 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff000000;
12302 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12306 case BFD_RELOC_ARM_MULTI
:
12307 if (((unsigned long) value
) > 0xffff)
12308 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12309 _("invalid expression in load/store multiple"));
12310 newval
= value
| md_chars_to_number (buf
, INSN_SIZE
);
12311 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12314 case BFD_RELOC_ARM_PCREL_BRANCH
:
12315 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12317 /* Sign-extend a 24-bit number. */
12318 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
12322 value
= fixP
->fx_offset
;
12325 /* We are going to store value (shifted right by two) in the
12326 instruction, in a 24 bit, signed field. Thus we need to check
12327 that none of the top 8 bits of the shifted value (top 7 bits of
12328 the unshifted, unsigned value) are set, or that they are all set. */
12329 if ((value
& ~ ((offsetT
) 0x1ffffff)) != 0
12330 && ((value
& ~ ((offsetT
) 0x1ffffff)) != ~ ((offsetT
) 0x1ffffff)))
12333 /* Normally we would be stuck at this point, since we cannot store
12334 the absolute address that is the destination of the branch in the
12335 24 bits of the branch instruction. If however, we happen to know
12336 that the destination of the branch is in the same section as the
12337 branch instruction itself, then we can compute the relocation for
12338 ourselves and not have to bother the linker with it.
12340 FIXME: The tests for OBJ_ELF and ! target_oabi are only here
12341 because I have not worked out how to do this for OBJ_COFF or
12344 && fixP
->fx_addsy
!= NULL
12345 && S_IS_DEFINED (fixP
->fx_addsy
)
12346 && S_GET_SEGMENT (fixP
->fx_addsy
) == seg
)
12348 /* Get pc relative value to go into the branch. */
12351 /* Permit a backward branch provided that enough bits
12352 are set. Allow a forwards branch, provided that
12353 enough bits are clear. */
12354 if ( (value
& ~ ((offsetT
) 0x1ffffff)) == ~ ((offsetT
) 0x1ffffff)
12355 || (value
& ~ ((offsetT
) 0x1ffffff)) == 0)
12359 if (! fixP
->fx_done
)
12361 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12362 _("GAS can't handle same-section branch dest >= 0x04000000"));
12366 value
+= SEXT24 (newval
);
12368 if ( (value
& ~ ((offsetT
) 0xffffff)) != 0
12369 && ((value
& ~ ((offsetT
) 0xffffff)) != ~ ((offsetT
) 0xffffff)))
12370 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12371 _("out of range branch"));
12373 newval
= (value
& 0x00ffffff) | (newval
& 0xff000000);
12374 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12377 case BFD_RELOC_ARM_PCREL_BLX
:
12380 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12384 value
= fixP
->fx_offset
;
12386 hbit
= (value
>> 1) & 1;
12387 value
= (value
>> 2) & 0x00ffffff;
12388 value
= (value
+ (newval
& 0x00ffffff)) & 0x00ffffff;
12389 newval
= value
| (newval
& 0xfe000000) | (hbit
<< 24);
12390 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12394 case BFD_RELOC_THUMB_PCREL_BRANCH9
: /* Conditional branch. */
12395 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12397 addressT diff
= (newval
& 0xff) << 1;
12402 if ((value
& ~0xff) && ((value
& ~0xff) != ~0xff))
12403 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12404 _("branch out of range"));
12405 newval
= (newval
& 0xff00) | ((value
& 0x1ff) >> 1);
12407 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12410 case BFD_RELOC_THUMB_PCREL_BRANCH12
: /* Unconditional branch. */
12411 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12413 addressT diff
= (newval
& 0x7ff) << 1;
12418 if ((value
& ~0x7ff) && ((value
& ~0x7ff) != ~0x7ff))
12419 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12420 _("branch out of range"));
12421 newval
= (newval
& 0xf800) | ((value
& 0xfff) >> 1);
12423 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12426 case BFD_RELOC_THUMB_PCREL_BLX
:
12427 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
12432 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12433 newval2
= md_chars_to_number (buf
+ THUMB_SIZE
, THUMB_SIZE
);
12434 diff
= ((newval
& 0x7ff) << 12) | ((newval2
& 0x7ff) << 1);
12435 if (diff
& 0x400000)
12438 value
= fixP
->fx_offset
;
12442 if ((value
& ~0x3fffff) && ((value
& ~0x3fffff) != ~0x3fffff))
12443 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12444 _("branch with link out of range"));
12446 newval
= (newval
& 0xf800) | ((value
& 0x7fffff) >> 12);
12447 newval2
= (newval2
& 0xf800) | ((value
& 0xfff) >> 1);
12448 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
)
12449 /* For a BLX instruction, make sure that the relocation is rounded up
12450 to a word boundary. This follows the semantics of the instruction
12451 which specifies that bit 1 of the target address will come from bit
12452 1 of the base address. */
12453 newval2
= (newval2
+ 1) & ~ 1;
12454 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12455 md_number_to_chars (buf
+ THUMB_SIZE
, newval2
, THUMB_SIZE
);
12460 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
12461 md_number_to_chars (buf
, value
, 1);
12463 else if (!target_oabi
)
12465 value
= fixP
->fx_offset
;
12466 md_number_to_chars (buf
, value
, 1);
12472 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
12473 md_number_to_chars (buf
, value
, 2);
12475 else if (!target_oabi
)
12477 value
= fixP
->fx_offset
;
12478 md_number_to_chars (buf
, value
, 2);
12484 case BFD_RELOC_ARM_GOT32
:
12485 case BFD_RELOC_ARM_GOTOFF
:
12486 case BFD_RELOC_ARM_TARGET2
:
12487 md_number_to_chars (buf
, 0, 4);
12491 case BFD_RELOC_RVA
:
12493 case BFD_RELOC_ARM_TARGET1
:
12494 case BFD_RELOC_ARM_ROSEGREL32
:
12495 case BFD_RELOC_ARM_SBREL32
:
12496 case BFD_RELOC_32_PCREL
:
12497 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
12498 md_number_to_chars (buf
, value
, 4);
12500 else if (!target_oabi
)
12502 value
= fixP
->fx_offset
;
12503 md_number_to_chars (buf
, value
, 4);
12509 case BFD_RELOC_ARM_PREL31
:
12510 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
12512 newval
= md_chars_to_number (buf
, 4) & 0x80000000;
12513 if ((value
^ (value
>> 1)) & 0x40000000)
12515 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12516 _("rel31 relocation overflow"));
12518 newval
|= value
& 0x7fffffff;
12519 md_number_to_chars (buf
, newval
, 4);
12523 case BFD_RELOC_ARM_PLT32
:
12524 /* It appears the instruction is fully prepared at this point. */
12528 case BFD_RELOC_ARM_CP_OFF_IMM
:
12530 if (value
< -1023 || value
> 1023 || (value
& 3))
12531 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12532 _("illegal value for co-processor offset"));
12535 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
12536 newval
|= (value
>> 2) | (sign
? INDEX_UP
: 0);
12537 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12540 case BFD_RELOC_ARM_CP_OFF_IMM_S2
:
12542 if (value
< -255 || value
> 255)
12543 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12544 _("Illegal value for co-processor offset"));
12547 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
12548 newval
|= value
| (sign
? INDEX_UP
: 0);
12549 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12552 case BFD_RELOC_ARM_THUMB_OFFSET
:
12553 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12554 /* Exactly what ranges, and where the offset is inserted depends
12555 on the type of instruction, we can establish this from the
12557 switch (newval
>> 12)
12559 case 4: /* PC load. */
12560 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
12561 forced to zero for these loads, so we will need to round
12562 up the offset if the instruction address is not word
12563 aligned (since the final address produced must be, and
12564 we can only describe word-aligned immediate offsets). */
12566 if ((fixP
->fx_frag
->fr_address
+ fixP
->fx_where
+ value
) & 3)
12567 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12568 _("invalid offset, target not word aligned (0x%08X)"),
12569 (unsigned int) (fixP
->fx_frag
->fr_address
12570 + fixP
->fx_where
+ value
));
12572 if ((value
+ 2) & ~0x3fe)
12573 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12574 _("invalid offset, value too big (0x%08lX)"),
12577 /* Round up, since pc will be rounded down. */
12578 newval
|= (value
+ 2) >> 2;
12581 case 9: /* SP load/store. */
12582 if (value
& ~0x3fc)
12583 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12584 _("invalid offset, value too big (0x%08lX)"),
12586 newval
|= value
>> 2;
12589 case 6: /* Word load/store. */
12591 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12592 _("invalid offset, value too big (0x%08lX)"),
12594 newval
|= value
<< 4; /* 6 - 2. */
12597 case 7: /* Byte load/store. */
12599 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12600 _("invalid offset, value too big (0x%08lX)"),
12602 newval
|= value
<< 6;
12605 case 8: /* Halfword load/store. */
12607 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12608 _("invalid offset, value too big (0x%08lX)"),
12610 newval
|= value
<< 5; /* 6 - 1. */
12614 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12615 "Unable to process relocation for thumb opcode: %lx",
12616 (unsigned long) newval
);
12619 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12622 case BFD_RELOC_ARM_THUMB_ADD
:
12623 /* This is a complicated relocation, since we use it for all of
12624 the following immediate relocations:
12628 9bit ADD/SUB SP word-aligned
12629 10bit ADD PC/SP word-aligned
12631 The type of instruction being processed is encoded in the
12638 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12640 int rd
= (newval
>> 4) & 0xf;
12641 int rs
= newval
& 0xf;
12642 int subtract
= newval
& 0x8000;
12646 if (value
& ~0x1fc)
12647 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12648 _("invalid immediate for stack address calculation"));
12649 newval
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
12650 newval
|= value
>> 2;
12652 else if (rs
== REG_PC
|| rs
== REG_SP
)
12656 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12657 _("invalid immediate for address calculation (value = 0x%08lX)"),
12658 (unsigned long) value
);
12659 newval
= (rs
== REG_PC
? T_OPCODE_ADD_PC
: T_OPCODE_ADD_SP
);
12661 newval
|= value
>> 2;
12666 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12667 _("invalid 8bit immediate"));
12668 newval
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
12669 newval
|= (rd
<< 8) | value
;
12674 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12675 _("invalid 3bit immediate"));
12676 newval
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
12677 newval
|= rd
| (rs
<< 3) | (value
<< 6);
12680 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12683 case BFD_RELOC_ARM_THUMB_IMM
:
12684 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12685 switch (newval
>> 11)
12687 case 0x04: /* 8bit immediate MOV. */
12688 case 0x05: /* 8bit immediate CMP. */
12689 if (value
< 0 || value
> 255)
12690 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12691 _("invalid immediate: %ld is too large"),
12699 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12702 case BFD_RELOC_ARM_THUMB_SHIFT
:
12703 /* 5bit shift value (0..31). */
12704 if (value
< 0 || value
> 31)
12705 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12706 _("illegal Thumb shift value: %ld"), (long) value
);
12707 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xf03f;
12708 newval
|= value
<< 6;
12709 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12712 case BFD_RELOC_VTABLE_INHERIT
:
12713 case BFD_RELOC_VTABLE_ENTRY
:
12717 case BFD_RELOC_NONE
:
12719 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12720 _("bad relocation fixup type (%d)"), fixP
->fx_r_type
);
12724 /* Translate internal representation of relocation info to BFD target
12728 tc_gen_reloc (section
, fixp
)
12729 asection
* section ATTRIBUTE_UNUSED
;
12733 bfd_reloc_code_real_type code
;
12735 reloc
= (arelent
*) xmalloc (sizeof (arelent
));
12737 reloc
->sym_ptr_ptr
= (asymbol
**) xmalloc (sizeof (asymbol
*));
12738 *reloc
->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
12739 reloc
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
12741 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12743 if (fixp
->fx_pcrel
== 0)
12744 reloc
->addend
= fixp
->fx_offset
;
12746 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
12747 #else /* OBJ_ELF */
12748 reloc
->addend
= fixp
->fx_offset
;
12751 switch (fixp
->fx_r_type
)
12754 if (fixp
->fx_pcrel
)
12756 code
= BFD_RELOC_8_PCREL
;
12761 if (fixp
->fx_pcrel
)
12763 code
= BFD_RELOC_16_PCREL
;
12768 if (fixp
->fx_pcrel
)
12770 code
= BFD_RELOC_32_PCREL
;
12774 case BFD_RELOC_ARM_PCREL_BRANCH
:
12775 case BFD_RELOC_ARM_PCREL_BLX
:
12776 case BFD_RELOC_RVA
:
12777 case BFD_RELOC_THUMB_PCREL_BRANCH9
:
12778 case BFD_RELOC_THUMB_PCREL_BRANCH12
:
12779 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
12780 case BFD_RELOC_THUMB_PCREL_BLX
:
12781 case BFD_RELOC_VTABLE_ENTRY
:
12782 case BFD_RELOC_VTABLE_INHERIT
:
12783 code
= fixp
->fx_r_type
;
12786 case BFD_RELOC_ARM_LITERAL
:
12787 case BFD_RELOC_ARM_HWLITERAL
:
12788 /* If this is called then the a literal has
12789 been referenced across a section boundary. */
12790 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12791 _("literal referenced across section boundary"));
12795 case BFD_RELOC_ARM_GOT32
:
12796 case BFD_RELOC_ARM_GOTOFF
:
12797 case BFD_RELOC_ARM_PLT32
:
12798 case BFD_RELOC_ARM_TARGET1
:
12799 case BFD_RELOC_ARM_ROSEGREL32
:
12800 case BFD_RELOC_ARM_SBREL32
:
12801 case BFD_RELOC_ARM_PREL31
:
12802 case BFD_RELOC_ARM_TARGET2
:
12803 code
= fixp
->fx_r_type
;
12807 case BFD_RELOC_ARM_IMMEDIATE
:
12808 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12809 _("internal relocation (type: IMMEDIATE) not fixed up"));
12812 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
12813 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12814 _("ADRL used for a symbol not defined in the same file"));
12817 case BFD_RELOC_ARM_OFFSET_IMM
:
12818 if (fixp
->fx_addsy
!= NULL
12819 && !S_IS_DEFINED (fixp
->fx_addsy
)
12820 && S_IS_LOCAL (fixp
->fx_addsy
))
12822 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12823 _("undefined local label `%s'"),
12824 S_GET_NAME (fixp
->fx_addsy
));
12828 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12829 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
12836 switch (fixp
->fx_r_type
)
12838 case BFD_RELOC_ARM_OFFSET_IMM8
: type
= "OFFSET_IMM8"; break;
12839 case BFD_RELOC_ARM_SHIFT_IMM
: type
= "SHIFT_IMM"; break;
12840 case BFD_RELOC_ARM_SWI
: type
= "SWI"; break;
12841 case BFD_RELOC_ARM_MULTI
: type
= "MULTI"; break;
12842 case BFD_RELOC_ARM_CP_OFF_IMM
: type
= "CP_OFF_IMM"; break;
12843 case BFD_RELOC_ARM_THUMB_ADD
: type
= "THUMB_ADD"; break;
12844 case BFD_RELOC_ARM_THUMB_SHIFT
: type
= "THUMB_SHIFT"; break;
12845 case BFD_RELOC_ARM_THUMB_IMM
: type
= "THUMB_IMM"; break;
12846 case BFD_RELOC_ARM_THUMB_OFFSET
: type
= "THUMB_OFFSET"; break;
12847 default: type
= _("<unknown>"); break;
12849 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12850 _("cannot represent %s relocation in this object file format"),
12857 if ((code
== BFD_RELOC_32_PCREL
|| code
== BFD_RELOC_32
)
12859 && fixp
->fx_addsy
== GOT_symbol
)
12861 code
= BFD_RELOC_ARM_GOTPC
;
12862 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
12866 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, code
);
12868 if (reloc
->howto
== NULL
)
12870 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12871 _("cannot represent %s relocation in this object file format"),
12872 bfd_get_reloc_code_name (code
));
12876 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12877 vtable entry to be used in the relocation's section offset. */
12878 if (fixp
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
12879 reloc
->address
= fixp
->fx_offset
;
12885 md_estimate_size_before_relax (fragP
, segtype
)
12886 fragS
* fragP ATTRIBUTE_UNUSED
;
12887 segT segtype ATTRIBUTE_UNUSED
;
12889 as_fatal (_("md_estimate_size_before_relax\n"));
12901 as_bad ("%s -- `%s'", inst
.error
, str
);
12905 to
= frag_more (inst
.size
);
12907 if (thumb_mode
&& (inst
.size
> THUMB_SIZE
))
12909 assert (inst
.size
== (2 * THUMB_SIZE
));
12910 md_number_to_chars (to
, inst
.instruction
>> 16, THUMB_SIZE
);
12911 md_number_to_chars (to
+ THUMB_SIZE
, inst
.instruction
, THUMB_SIZE
);
12913 else if (inst
.size
> INSN_SIZE
)
12915 assert (inst
.size
== (2 * INSN_SIZE
));
12916 md_number_to_chars (to
, inst
.instruction
, INSN_SIZE
);
12917 md_number_to_chars (to
+ INSN_SIZE
, inst
.instruction
, INSN_SIZE
);
12920 md_number_to_chars (to
, inst
.instruction
, inst
.size
);
12922 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
12923 fix_new_arm (frag_now
, to
- frag_now
->fr_literal
,
12924 inst
.size
, & inst
.reloc
.exp
, inst
.reloc
.pc_rel
,
12928 dwarf2_emit_insn (inst
.size
);
12940 /* Align the instruction.
12941 This may not be the right thing to do but ... */
12946 /* Align the previous label if needed. */
12947 if (last_label_seen
!= NULL
)
12949 symbol_set_frag (last_label_seen
, frag_now
);
12950 S_SET_VALUE (last_label_seen
, (valueT
) frag_now_fix ());
12951 S_SET_SEGMENT (last_label_seen
, now_seg
);
12954 memset (&inst
, '\0', sizeof (inst
));
12955 inst
.reloc
.type
= BFD_RELOC_NONE
;
12957 skip_whitespace (str
);
12959 /* Scan up to the end of the op-code, which must end in white space or
12961 for (start
= p
= str
; *p
!= '\0'; p
++)
12967 as_bad (_("no operator -- statement `%s'\n"), str
);
12973 const struct thumb_opcode
* opcode
;
12977 opcode
= (const struct thumb_opcode
*) hash_find (arm_tops_hsh
, str
);
12982 /* Check that this instruction is supported for this CPU. */
12983 if (thumb_mode
== 1 && (opcode
->variant
& cpu_variant
) == 0)
12985 as_bad (_("selected processor does not support `%s'"), str
);
12989 mapping_state (MAP_THUMB
);
12990 inst
.instruction
= opcode
->value
;
12991 inst
.size
= opcode
->size
;
12992 (*opcode
->parms
) (p
);
12999 const struct asm_opcode
* opcode
;
13003 opcode
= (const struct asm_opcode
*) hash_find (arm_ops_hsh
, str
);
13008 /* Check that this instruction is supported for this CPU. */
13009 if ((opcode
->variant
& cpu_variant
) == 0)
13011 as_bad (_("selected processor does not support `%s'"), str
);
13015 mapping_state (MAP_ARM
);
13016 inst
.instruction
= opcode
->value
;
13017 inst
.size
= INSN_SIZE
;
13018 (*opcode
->parms
) (p
);
13024 /* It wasn't an instruction, but it might be a register alias of the form
13026 if (create_register_alias (str
, p
))
13029 as_bad (_("bad instruction `%s'"), start
);
13033 Invocation line includes a switch not recognized by the base assembler.
13034 See if it's a processor-specific option.
13036 This routine is somewhat complicated by the need for backwards
13037 compatibility (since older releases of gcc can't be changed).
13038 The new options try to make the interface as compatible as
13041 New options (supported) are:
13043 -mcpu=<cpu name> Assemble for selected processor
13044 -march=<architecture name> Assemble for selected architecture
13045 -mfpu=<fpu architecture> Assemble for selected FPU.
13046 -EB/-mbig-endian Big-endian
13047 -EL/-mlittle-endian Little-endian
13048 -k Generate PIC code
13049 -mthumb Start in Thumb mode
13050 -mthumb-interwork Code supports ARM/Thumb interworking
13052 For now we will also provide support for:
13054 -mapcs-32 32-bit Program counter
13055 -mapcs-26 26-bit Program counter
13056 -macps-float Floats passed in FP registers
13057 -mapcs-reentrant Reentrant code
13059 (sometime these will probably be replaced with -mapcs=<list of options>
13060 and -matpcs=<list of options>)
13062 The remaining options are only supported for back-wards compatibility.
13063 Cpu variants, the arm part is optional:
13064 -m[arm]1 Currently not supported.
13065 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
13066 -m[arm]3 Arm 3 processor
13067 -m[arm]6[xx], Arm 6 processors
13068 -m[arm]7[xx][t][[d]m] Arm 7 processors
13069 -m[arm]8[10] Arm 8 processors
13070 -m[arm]9[20][tdmi] Arm 9 processors
13071 -mstrongarm[110[0]] StrongARM processors
13072 -mxscale XScale processors
13073 -m[arm]v[2345[t[e]]] Arm architectures
13074 -mall All (except the ARM1)
13076 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
13077 -mfpe-old (No float load/store multiples)
13078 -mvfpxd VFP Single precision
13080 -mno-fpu Disable all floating point instructions
13082 The following CPU names are recognized:
13083 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
13084 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
13085 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
13086 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
13087 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
13088 arm10t arm10e, arm1020t, arm1020e, arm10200e,
13089 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
13093 const char * md_shortopts
= "m:k";
13095 #ifdef ARM_BI_ENDIAN
13096 #define OPTION_EB (OPTION_MD_BASE + 0)
13097 #define OPTION_EL (OPTION_MD_BASE + 1)
13099 #if TARGET_BYTES_BIG_ENDIAN
13100 #define OPTION_EB (OPTION_MD_BASE + 0)
13102 #define OPTION_EL (OPTION_MD_BASE + 1)
13106 struct option md_longopts
[] =
13109 {"EB", no_argument
, NULL
, OPTION_EB
},
13112 {"EL", no_argument
, NULL
, OPTION_EL
},
13114 {NULL
, no_argument
, NULL
, 0}
13117 size_t md_longopts_size
= sizeof (md_longopts
);
13119 struct arm_option_table
13121 char *option
; /* Option name to match. */
13122 char *help
; /* Help information. */
13123 int *var
; /* Variable to change. */
13124 int value
; /* What to change it to. */
13125 char *deprecated
; /* If non-null, print this message. */
13128 struct arm_option_table arm_opts
[] =
13130 {"k", N_("generate PIC code"), &pic_code
, 1, NULL
},
13131 {"mthumb", N_("assemble Thumb code"), &thumb_mode
, 1, NULL
},
13132 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
13133 &support_interwork
, 1, NULL
},
13134 {"moabi", N_("use old ABI (ELF only)"), &target_oabi
, 1, NULL
},
13135 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26
, 0, NULL
},
13136 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26
, 1, NULL
},
13137 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float
,
13139 {"mapcs-reentrant", N_("re-entrant code"), &pic_code
, 1, NULL
},
13140 {"matpcs", N_("code is ATPCS conformant"), &atpcs
, 1, NULL
},
13141 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian
, 1, NULL
},
13142 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian
, 1,
13145 /* These are recognized by the assembler, but have no affect on code. */
13146 {"mapcs-frame", N_("use frame pointer"), NULL
, 0, NULL
},
13147 {"mapcs-stack-check", N_("use stack size checking"), NULL
, 0, NULL
},
13149 /* DON'T add any new processors to this list -- we want the whole list
13150 to go away... Add them to the processors table instead. */
13151 {"marm1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
13152 {"m1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
13153 {"marm2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
13154 {"m2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
13155 {"marm250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
13156 {"m250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
13157 {"marm3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
13158 {"m3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
13159 {"marm6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
13160 {"m6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
13161 {"marm600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
13162 {"m600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
13163 {"marm610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
13164 {"m610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
13165 {"marm620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
13166 {"m620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
13167 {"marm7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
13168 {"m7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
13169 {"marm70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
13170 {"m70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
13171 {"marm700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
13172 {"m700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
13173 {"marm700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
13174 {"m700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
13175 {"marm710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
13176 {"m710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
13177 {"marm710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
13178 {"m710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
13179 {"marm720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
13180 {"m720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
13181 {"marm7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
13182 {"m7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
13183 {"marm7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
13184 {"m7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
13185 {"marm7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
13186 {"m7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
13187 {"marm7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
13188 {"m7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
13189 {"marm7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
13190 {"m7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
13191 {"marm7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
13192 {"m7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
13193 {"marm7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
13194 {"m7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
13195 {"marm7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
13196 {"m7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
13197 {"marm7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
13198 {"m7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
13199 {"marm7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
13200 {"m7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
13201 {"marm710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
13202 {"m710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
13203 {"marm720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
13204 {"m720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
13205 {"marm740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
13206 {"m740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
13207 {"marm8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
13208 {"m8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
13209 {"marm810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
13210 {"m810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
13211 {"marm9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
13212 {"m9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
13213 {"marm9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
13214 {"m9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
13215 {"marm920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
13216 {"m920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
13217 {"marm940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
13218 {"m940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
13219 {"mstrongarm", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=strongarm")},
13220 {"mstrongarm110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
13221 N_("use -mcpu=strongarm110")},
13222 {"mstrongarm1100", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
13223 N_("use -mcpu=strongarm1100")},
13224 {"mstrongarm1110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
13225 N_("use -mcpu=strongarm1110")},
13226 {"mxscale", NULL
, &legacy_cpu
, ARM_ARCH_XSCALE
, N_("use -mcpu=xscale")},
13227 {"miwmmxt", NULL
, &legacy_cpu
, ARM_ARCH_IWMMXT
, N_("use -mcpu=iwmmxt")},
13228 {"mall", NULL
, &legacy_cpu
, ARM_ANY
, N_("use -mcpu=all")},
13230 /* Architecture variants -- don't add any more to this list either. */
13231 {"mv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
13232 {"marmv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
13233 {"mv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
13234 {"marmv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
13235 {"mv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
13236 {"marmv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
13237 {"mv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
13238 {"marmv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
13239 {"mv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
13240 {"marmv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
13241 {"mv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
13242 {"marmv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
13243 {"mv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
13244 {"marmv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
13245 {"mv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
13246 {"marmv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
13247 {"mv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
13248 {"marmv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
13250 /* Floating point variants -- don't add any more to this list either. */
13251 {"mfpe-old", NULL
, &legacy_fpu
, FPU_ARCH_FPE
, N_("use -mfpu=fpe")},
13252 {"mfpa10", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa10")},
13253 {"mfpa11", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa11")},
13254 {"mno-fpu", NULL
, &legacy_fpu
, 0,
13255 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
13257 {NULL
, NULL
, NULL
, 0, NULL
}
13260 struct arm_cpu_option_table
13264 /* For some CPUs we assume an FPU unless the user explicitly sets
13269 /* This list should, at a minimum, contain all the cpu names
13270 recognized by GCC. */
13271 static struct arm_cpu_option_table arm_cpus
[] =
13273 {"all", ARM_ANY
, FPU_ARCH_FPA
},
13274 {"arm1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
13275 {"arm2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
13276 {"arm250", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
13277 {"arm3", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
13278 {"arm6", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13279 {"arm60", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13280 {"arm600", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13281 {"arm610", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13282 {"arm620", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13283 {"arm7", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13284 {"arm7m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
13285 {"arm7d", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13286 {"arm7dm", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
13287 {"arm7di", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13288 {"arm7dmi", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
13289 {"arm70", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13290 {"arm700", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13291 {"arm700i", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13292 {"arm710", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13293 {"arm710t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13294 {"arm720", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13295 {"arm720t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13296 {"arm740t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13297 {"arm710c", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13298 {"arm7100", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13299 {"arm7500", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13300 {"arm7500fe", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13301 {"arm7t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13302 {"arm7tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13303 {"arm7tdmi-s", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13304 {"arm8", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13305 {"arm810", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13306 {"strongarm", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13307 {"strongarm1", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13308 {"strongarm110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13309 {"strongarm1100", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13310 {"strongarm1110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13311 {"arm9", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13312 {"arm920", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13313 {"arm920t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13314 {"arm922t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13315 {"arm940t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13316 {"arm9tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13317 /* For V5 or later processors we default to using VFP; but the user
13318 should really set the FPU type explicitly. */
13319 {"arm9e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
13320 {"arm9e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13321 {"arm926ej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
13322 {"arm926ejs", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
13323 {"arm926ej-s", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
13324 {"arm946e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
13325 {"arm946e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13326 {"arm966e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
13327 {"arm966e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13328 {"arm10t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
13329 {"arm10e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13330 {"arm1020", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13331 {"arm1020t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
13332 {"arm1020e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13333 {"arm1026ejs", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13334 {"arm1026ej-s", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13335 {"arm1136js", ARM_ARCH_V6
, FPU_NONE
},
13336 {"arm1136j-s", ARM_ARCH_V6
, FPU_NONE
},
13337 {"arm1136jfs", ARM_ARCH_V6
, FPU_ARCH_VFP_V2
},
13338 {"arm1136jf-s", ARM_ARCH_V6
, FPU_ARCH_VFP_V2
},
13339 /* ??? XSCALE is really an architecture. */
13340 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
13341 /* ??? iwmmxt is not a processor. */
13342 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP_V2
},
13343 {"i80200", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
13345 {"ep9312", ARM_ARCH_V4T
| ARM_CEXT_MAVERICK
, FPU_ARCH_MAVERICK
},
13349 struct arm_arch_option_table
13356 /* This list should, at a minimum, contain all the architecture names
13357 recognized by GCC. */
13358 static struct arm_arch_option_table arm_archs
[] =
13360 {"all", ARM_ANY
, FPU_ARCH_FPA
},
13361 {"armv1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
13362 {"armv2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
13363 {"armv2a", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
13364 {"armv2s", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
13365 {"armv3", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13366 {"armv3m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
13367 {"armv4", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13368 {"armv4xm", ARM_ARCH_V4xM
, FPU_ARCH_FPA
},
13369 {"armv4t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13370 {"armv4txm", ARM_ARCH_V4TxM
, FPU_ARCH_FPA
},
13371 {"armv5", ARM_ARCH_V5
, FPU_ARCH_VFP
},
13372 {"armv5t", ARM_ARCH_V5T
, FPU_ARCH_VFP
},
13373 {"armv5txm", ARM_ARCH_V5TxM
, FPU_ARCH_VFP
},
13374 {"armv5te", ARM_ARCH_V5TE
, FPU_ARCH_VFP
},
13375 {"armv5texp", ARM_ARCH_V5TExP
, FPU_ARCH_VFP
},
13376 {"armv5tej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP
},
13377 {"armv6", ARM_ARCH_V6
, FPU_ARCH_VFP
},
13378 {"armv6j", ARM_ARCH_V6
, FPU_ARCH_VFP
},
13379 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP
},
13380 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP
},
13384 /* ISA extensions in the co-processor space. */
13385 struct arm_arch_extension_table
13391 static struct arm_arch_extension_table arm_extensions
[] =
13393 {"maverick", ARM_CEXT_MAVERICK
},
13394 {"xscale", ARM_CEXT_XSCALE
},
13395 {"iwmmxt", ARM_CEXT_IWMMXT
},
13399 struct arm_fpu_option_table
13405 /* This list should, at a minimum, contain all the fpu names
13406 recognized by GCC. */
13407 static struct arm_fpu_option_table arm_fpus
[] =
13409 {"softfpa", FPU_NONE
},
13410 {"fpe", FPU_ARCH_FPE
},
13411 {"fpe2", FPU_ARCH_FPE
},
13412 {"fpe3", FPU_ARCH_FPA
}, /* Third release supports LFM/SFM. */
13413 {"fpa", FPU_ARCH_FPA
},
13414 {"fpa10", FPU_ARCH_FPA
},
13415 {"fpa11", FPU_ARCH_FPA
},
13416 {"arm7500fe", FPU_ARCH_FPA
},
13417 {"softvfp", FPU_ARCH_VFP
},
13418 {"softvfp+vfp", FPU_ARCH_VFP_V2
},
13419 {"vfp", FPU_ARCH_VFP_V2
},
13420 {"vfp9", FPU_ARCH_VFP_V2
},
13421 {"vfp10", FPU_ARCH_VFP_V2
},
13422 {"vfp10-r0", FPU_ARCH_VFP_V1
},
13423 {"vfpxd", FPU_ARCH_VFP_V1xD
},
13424 {"arm1020t", FPU_ARCH_VFP_V1
},
13425 {"arm1020e", FPU_ARCH_VFP_V2
},
13426 {"arm1136jfs", FPU_ARCH_VFP_V2
},
13427 {"arm1136jf-s", FPU_ARCH_VFP_V2
},
13428 {"maverick", FPU_ARCH_MAVERICK
},
13432 struct arm_float_abi_option_table
13438 static struct arm_float_abi_option_table arm_float_abis
[] =
13440 {"hard", ARM_FLOAT_ABI_HARD
},
13441 {"softfp", ARM_FLOAT_ABI_SOFTFP
},
13442 {"soft", ARM_FLOAT_ABI_SOFT
},
13446 struct arm_eabi_option_table
13449 unsigned int value
;
13453 /* We only know hot to output GNU and ver 3 (AAELF) formats. */
13454 static struct arm_eabi_option_table arm_eabis
[] =
13456 {"gnu", EF_ARM_EABI_UNKNOWN
},
13457 {"3", EF_ARM_EABI_VER3
},
13462 struct arm_long_option_table
13464 char *option
; /* Substring to match. */
13465 char *help
; /* Help information. */
13466 int (*func
) PARAMS ((char *subopt
)); /* Function to decode sub-option. */
13467 char *deprecated
; /* If non-null, print this message. */
13471 arm_parse_extension (str
, opt_p
)
13475 while (str
!= NULL
&& *str
!= 0)
13477 struct arm_arch_extension_table
*opt
;
13483 as_bad (_("invalid architectural extension"));
13488 ext
= strchr (str
, '+');
13491 optlen
= ext
- str
;
13493 optlen
= strlen (str
);
13497 as_bad (_("missing architectural extension"));
13501 for (opt
= arm_extensions
; opt
->name
!= NULL
; opt
++)
13502 if (strncmp (opt
->name
, str
, optlen
) == 0)
13504 *opt_p
|= opt
->value
;
13508 if (opt
->name
== NULL
)
13510 as_bad (_("unknown architectural extnsion `%s'"), str
);
13521 arm_parse_cpu (str
)
13524 struct arm_cpu_option_table
*opt
;
13525 char *ext
= strchr (str
, '+');
13529 optlen
= ext
- str
;
13531 optlen
= strlen (str
);
13535 as_bad (_("missing cpu name `%s'"), str
);
13539 for (opt
= arm_cpus
; opt
->name
!= NULL
; opt
++)
13540 if (strncmp (opt
->name
, str
, optlen
) == 0)
13542 mcpu_cpu_opt
= opt
->value
;
13543 mcpu_fpu_opt
= opt
->default_fpu
;
13546 return arm_parse_extension (ext
, &mcpu_cpu_opt
);
13551 as_bad (_("unknown cpu `%s'"), str
);
13556 arm_parse_arch (str
)
13559 struct arm_arch_option_table
*opt
;
13560 char *ext
= strchr (str
, '+');
13564 optlen
= ext
- str
;
13566 optlen
= strlen (str
);
13570 as_bad (_("missing architecture name `%s'"), str
);
13575 for (opt
= arm_archs
; opt
->name
!= NULL
; opt
++)
13576 if (strcmp (opt
->name
, str
) == 0)
13578 march_cpu_opt
= opt
->value
;
13579 march_fpu_opt
= opt
->default_fpu
;
13582 return arm_parse_extension (ext
, &march_cpu_opt
);
13587 as_bad (_("unknown architecture `%s'\n"), str
);
13592 arm_parse_fpu (str
)
13595 struct arm_fpu_option_table
*opt
;
13597 for (opt
= arm_fpus
; opt
->name
!= NULL
; opt
++)
13598 if (strcmp (opt
->name
, str
) == 0)
13600 mfpu_opt
= opt
->value
;
13604 as_bad (_("unknown floating point format `%s'\n"), str
);
13609 arm_parse_float_abi (str
)
13612 struct arm_float_abi_option_table
*opt
;
13614 for (opt
= arm_float_abis
; opt
->name
!= NULL
; opt
++)
13615 if (strcmp (opt
->name
, str
) == 0)
13617 mfloat_abi_opt
= opt
->value
;
13621 as_bad (_("unknown floating point abi `%s'\n"), str
);
13627 arm_parse_eabi (str
)
13630 struct arm_eabi_option_table
*opt
;
13632 for (opt
= arm_eabis
; opt
->name
!= NULL
; opt
++)
13633 if (strcmp (opt
->name
, str
) == 0)
13635 meabi_flags
= opt
->value
;
13638 as_bad (_("unknown EABI `%s'\n"), str
);
13643 struct arm_long_option_table arm_long_opts
[] =
13645 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13646 arm_parse_cpu
, NULL
},
13647 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13648 arm_parse_arch
, NULL
},
13649 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13650 arm_parse_fpu
, NULL
},
13651 {"mfloat-abi=", N_("<abi>\t assemble for floating point ABI <abi>"),
13652 arm_parse_float_abi
, NULL
},
13654 {"meabi=", N_("<ver>\t assemble for eabi version <ver>"),
13655 arm_parse_eabi
, NULL
},
13657 {NULL
, NULL
, 0, NULL
}
13661 md_parse_option (c
, arg
)
13665 struct arm_option_table
*opt
;
13666 struct arm_long_option_table
*lopt
;
13672 target_big_endian
= 1;
13678 target_big_endian
= 0;
13683 /* Listing option. Just ignore these, we don't support additional
13688 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
13690 if (c
== opt
->option
[0]
13691 && ((arg
== NULL
&& opt
->option
[1] == 0)
13692 || strcmp (arg
, opt
->option
+ 1) == 0))
13694 #if WARN_DEPRECATED
13695 /* If the option is deprecated, tell the user. */
13696 if (opt
->deprecated
!= NULL
)
13697 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
,
13698 arg
? arg
: "", _(opt
->deprecated
));
13701 if (opt
->var
!= NULL
)
13702 *opt
->var
= opt
->value
;
13708 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
13710 /* These options are expected to have an argument. */
13711 if (c
== lopt
->option
[0]
13713 && strncmp (arg
, lopt
->option
+ 1,
13714 strlen (lopt
->option
+ 1)) == 0)
13716 #if WARN_DEPRECATED
13717 /* If the option is deprecated, tell the user. */
13718 if (lopt
->deprecated
!= NULL
)
13719 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
, arg
,
13720 _(lopt
->deprecated
));
13723 /* Call the sup-option parser. */
13724 return (*lopt
->func
)(arg
+ strlen (lopt
->option
) - 1);
13738 struct arm_option_table
*opt
;
13739 struct arm_long_option_table
*lopt
;
13741 fprintf (fp
, _(" ARM-specific assembler options:\n"));
13743 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
13744 if (opt
->help
!= NULL
)
13745 fprintf (fp
, " -%-23s%s\n", opt
->option
, _(opt
->help
));
13747 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
13748 if (lopt
->help
!= NULL
)
13749 fprintf (fp
, " -%s%s\n", lopt
->option
, _(lopt
->help
));
13753 -EB assemble code for a big-endian cpu\n"));
13758 -EL assemble code for a little-endian cpu\n"));
13762 /* We need to be able to fix up arbitrary expressions in some statements.
13763 This is so that we can handle symbols that are an arbitrary distance from
13764 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
13765 which returns part of an address in a form which will be valid for
13766 a data instruction. We do this by pushing the expression into a symbol
13767 in the expr_section, and creating a fix for that. */
13770 fix_new_arm (frag
, where
, size
, exp
, pc_rel
, reloc
)
13779 arm_fix_data
* arm_data
;
13787 new_fix
= fix_new_exp (frag
, where
, size
, exp
, pc_rel
, reloc
);
13791 new_fix
= fix_new (frag
, where
, size
, make_expr_symbol (exp
), 0,
13796 /* Mark whether the fix is to a THUMB instruction, or an ARM
13798 arm_data
= (arm_fix_data
*) obstack_alloc (& notes
, sizeof (arm_fix_data
));
13799 new_fix
->tc_fix_data
= (PTR
) arm_data
;
13800 arm_data
->thumb_mode
= thumb_mode
;
13803 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13806 cons_fix_new_arm (frag
, where
, size
, exp
)
13812 bfd_reloc_code_real_type type
;
13816 FIXME: @@ Should look at CPU word size. */
13820 type
= BFD_RELOC_8
;
13823 type
= BFD_RELOC_16
;
13827 type
= BFD_RELOC_32
;
13830 type
= BFD_RELOC_64
;
13834 fix_new_exp (frag
, where
, (int) size
, exp
, pcrel
, type
);
13837 /* A good place to do this, although this was probably not intended
13838 for this kind of use. We need to dump the literal pool before
13839 references are made to a null symbol pointer. */
13844 literal_pool
* pool
;
13846 for (pool
= list_of_pools
; pool
; pool
= pool
->next
)
13848 /* Put it at the end of the relevent section. */
13849 subseg_set (pool
->section
, pool
->sub_section
);
13851 arm_elf_change_section ();
13858 arm_start_line_hook ()
13860 last_label_seen
= NULL
;
13864 arm_frob_label (sym
)
13867 last_label_seen
= sym
;
13869 ARM_SET_THUMB (sym
, thumb_mode
);
13871 #if defined OBJ_COFF || defined OBJ_ELF
13872 ARM_SET_INTERWORK (sym
, support_interwork
);
13875 /* Note - do not allow local symbols (.Lxxx) to be labeled
13876 as Thumb functions. This is because these labels, whilst
13877 they exist inside Thumb code, are not the entry points for
13878 possible ARM->Thumb calls. Also, these labels can be used
13879 as part of a computed goto or switch statement. eg gcc
13880 can generate code that looks like this:
13882 ldr r2, [pc, .Laaa]
13892 The first instruction loads the address of the jump table.
13893 The second instruction converts a table index into a byte offset.
13894 The third instruction gets the jump address out of the table.
13895 The fourth instruction performs the jump.
13897 If the address stored at .Laaa is that of a symbol which has the
13898 Thumb_Func bit set, then the linker will arrange for this address
13899 to have the bottom bit set, which in turn would mean that the
13900 address computation performed by the third instruction would end
13901 up with the bottom bit set. Since the ARM is capable of unaligned
13902 word loads, the instruction would then load the incorrect address
13903 out of the jump table, and chaos would ensue. */
13904 if (label_is_thumb_function_name
13905 && (S_GET_NAME (sym
)[0] != '.' || S_GET_NAME (sym
)[1] != 'L')
13906 && (bfd_get_section_flags (stdoutput
, now_seg
) & SEC_CODE
) != 0)
13908 /* When the address of a Thumb function is taken the bottom
13909 bit of that address should be set. This will allow
13910 interworking between Arm and Thumb functions to work
13913 THUMB_SET_FUNC (sym
, 1);
13915 label_is_thumb_function_name
= FALSE
;
13919 /* Adjust the symbol table. This marks Thumb symbols as distinct from
13923 arm_adjust_symtab ()
13928 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
13930 if (ARM_IS_THUMB (sym
))
13932 if (THUMB_IS_FUNC (sym
))
13934 /* Mark the symbol as a Thumb function. */
13935 if ( S_GET_STORAGE_CLASS (sym
) == C_STAT
13936 || S_GET_STORAGE_CLASS (sym
) == C_LABEL
) /* This can happen! */
13937 S_SET_STORAGE_CLASS (sym
, C_THUMBSTATFUNC
);
13939 else if (S_GET_STORAGE_CLASS (sym
) == C_EXT
)
13940 S_SET_STORAGE_CLASS (sym
, C_THUMBEXTFUNC
);
13942 as_bad (_("%s: unexpected function type: %d"),
13943 S_GET_NAME (sym
), S_GET_STORAGE_CLASS (sym
));
13945 else switch (S_GET_STORAGE_CLASS (sym
))
13948 S_SET_STORAGE_CLASS (sym
, C_THUMBEXT
);
13951 S_SET_STORAGE_CLASS (sym
, C_THUMBSTAT
);
13954 S_SET_STORAGE_CLASS (sym
, C_THUMBLABEL
);
13962 if (ARM_IS_INTERWORK (sym
))
13963 coffsymbol (symbol_get_bfdsym (sym
))->native
->u
.syment
.n_flags
= 0xFF;
13970 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
13972 if (ARM_IS_THUMB (sym
))
13974 elf_symbol_type
* elf_sym
;
13976 elf_sym
= elf_symbol (symbol_get_bfdsym (sym
));
13977 bind
= ELF_ST_BIND (elf_sym
);
13979 /* If it's a .thumb_func, declare it as so,
13980 otherwise tag label as .code 16. */
13981 if (THUMB_IS_FUNC (sym
))
13982 elf_sym
->internal_elf_sym
.st_info
=
13983 ELF_ST_INFO (bind
, STT_ARM_TFUNC
);
13985 elf_sym
->internal_elf_sym
.st_info
=
13986 ELF_ST_INFO (bind
, STT_ARM_16BIT
);
13993 arm_data_in_code ()
13995 if (thumb_mode
&& ! strncmp (input_line_pointer
+ 1, "data:", 5))
13997 *input_line_pointer
= '/';
13998 input_line_pointer
+= 5;
13999 *input_line_pointer
= 0;
14007 arm_canonicalize_symbol_name (name
)
14012 if (thumb_mode
&& (len
= strlen (name
)) > 5
14013 && streq (name
+ len
- 5, "/data"))
14014 *(name
+ len
- 5) = 0;
14019 #if defined OBJ_COFF || defined OBJ_ELF
14021 arm_validate_fix (fixP
)
14024 /* If the destination of the branch is a defined symbol which does not have
14025 the THUMB_FUNC attribute, then we must be calling a function which has
14026 the (interfacearm) attribute. We look for the Thumb entry point to that
14027 function and change the branch to refer to that function instead. */
14028 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
14029 && fixP
->fx_addsy
!= NULL
14030 && S_IS_DEFINED (fixP
->fx_addsy
)
14031 && ! THUMB_IS_FUNC (fixP
->fx_addsy
))
14033 fixP
->fx_addsy
= find_real_start (fixP
->fx_addsy
);
14039 arm_force_relocation (fixp
)
14042 #if defined (OBJ_COFF) && defined (TE_PE)
14043 if (fixp
->fx_r_type
== BFD_RELOC_RVA
)
14047 if (fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
14048 || fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
14049 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
14050 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
)
14054 /* Resolve these relocations even if the symbol is extern or weak. */
14055 if (fixp
->fx_r_type
== BFD_RELOC_ARM_IMMEDIATE
14056 || fixp
->fx_r_type
== BFD_RELOC_ARM_OFFSET_IMM
14057 || fixp
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
14060 return generic_force_reloc (fixp
);
14064 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
14065 local labels from being added to the output symbol table when they
14066 are used with the ADRL pseudo op. The ADRL relocation should always
14067 be resolved before the binbary is emitted, so it is safe to say that
14068 it is adjustable. */
14071 arm_fix_adjustable (fixP
)
14074 if (fixP
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
14081 /* Relocations against Thumb function names must be left unadjusted,
14082 so that the linker can use this information to correctly set the
14083 bottom bit of their addresses. The MIPS version of this function
14084 also prevents relocations that are mips-16 specific, but I do not
14085 know why it does this.
14088 There is one other problem that ought to be addressed here, but
14089 which currently is not: Taking the address of a label (rather
14090 than a function) and then later jumping to that address. Such
14091 addresses also ought to have their bottom bit set (assuming that
14092 they reside in Thumb code), but at the moment they will not. */
14095 arm_fix_adjustable (fixP
)
14098 if (fixP
->fx_addsy
== NULL
)
14101 if (THUMB_IS_FUNC (fixP
->fx_addsy
)
14102 && fixP
->fx_subsy
== NULL
)
14105 /* We need the symbol name for the VTABLE entries. */
14106 if ( fixP
->fx_r_type
== BFD_RELOC_VTABLE_INHERIT
14107 || fixP
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
14110 /* Don't allow symbols to be discarded on GOT related relocs. */
14111 if (fixP
->fx_r_type
== BFD_RELOC_ARM_PLT32
14112 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOT32
14113 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOTOFF
14114 || fixP
->fx_r_type
== BFD_RELOC_ARM_TARGET2
)
14121 elf32_arm_target_format ()
14124 return (target_big_endian
14125 ? "elf32-bigarm-symbian"
14126 : "elf32-littlearm-symbian");
14128 if (target_big_endian
)
14131 return "elf32-bigarm-oabi";
14133 return "elf32-bigarm";
14138 return "elf32-littlearm-oabi";
14140 return "elf32-littlearm";
14146 armelf_frob_symbol (symp
, puntp
)
14150 elf_frob_symbol (symp
, puntp
);
14153 static bfd_reloc_code_real_type
14163 bfd_reloc_code_real_type reloc
;
14167 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
14168 MAP ("(got)", BFD_RELOC_ARM_GOT32
),
14169 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF
),
14170 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
14171 branch instructions generated by GCC for PLT relocs. */
14172 MAP ("(plt)", BFD_RELOC_ARM_PLT32
),
14173 MAP ("(target1)", BFD_RELOC_ARM_TARGET1
),
14174 MAP ("(sbrel)", BFD_RELOC_ARM_SBREL32
),
14175 MAP ("(target2)", BFD_RELOC_ARM_TARGET2
),
14176 { NULL
, 0, BFD_RELOC_UNUSED
}
14180 for (i
= 0, ip
= input_line_pointer
;
14181 i
< sizeof (id
) && (ISALNUM (*ip
) || ISPUNCT (*ip
));
14183 id
[i
] = TOLOWER (*ip
);
14185 for (i
= 0; reloc_map
[i
].str
; i
++)
14186 if (strncmp (id
, reloc_map
[i
].str
, reloc_map
[i
].len
) == 0)
14189 input_line_pointer
+= reloc_map
[i
].len
;
14191 return reloc_map
[i
].reloc
;
14195 s_arm_elf_cons (nbytes
)
14200 #ifdef md_flush_pending_output
14201 md_flush_pending_output ();
14204 if (is_it_end_of_statement ())
14206 demand_empty_rest_of_line ();
14210 #ifdef md_cons_align
14211 md_cons_align (nbytes
);
14214 mapping_state (MAP_DATA
);
14217 bfd_reloc_code_real_type reloc
;
14219 expression (& exp
);
14221 if (exp
.X_op
== O_symbol
14222 && * input_line_pointer
== '('
14223 && (reloc
= arm_parse_reloc ()) != BFD_RELOC_UNUSED
)
14225 reloc_howto_type
*howto
= bfd_reloc_type_lookup (stdoutput
, reloc
);
14226 int size
= bfd_get_reloc_size (howto
);
14229 as_bad ("%s relocations do not fit in %d bytes",
14230 howto
->name
, nbytes
);
14233 register char *p
= frag_more ((int) nbytes
);
14234 int offset
= nbytes
- size
;
14236 fix_new_exp (frag_now
, p
- frag_now
->fr_literal
+ offset
, size
,
14241 emit_expr (&exp
, (unsigned int) nbytes
);
14243 while (*input_line_pointer
++ == ',');
14245 /* Put terminator back into stream. */
14246 input_line_pointer
--;
14247 demand_empty_rest_of_line ();
14251 /* Parse a .rel31 directive. */
14254 s_arm_rel31 (int ignored ATTRIBUTE_UNUSED
)
14260 SKIP_WHITESPACE ();
14263 if (*input_line_pointer
== '1')
14264 highbit
= 0x80000000;
14265 else if (*input_line_pointer
!= '0')
14266 as_bad (_("expected 0 or 1"));
14268 input_line_pointer
++;
14269 SKIP_WHITESPACE ();
14270 if (*input_line_pointer
!= ',')
14271 as_bad (_("missing comma"));
14272 input_line_pointer
++;
14274 #ifdef md_flush_pending_output
14275 md_flush_pending_output ();
14278 #ifdef md_cons_align
14282 mapping_state (MAP_DATA
);
14287 md_number_to_chars (p
, highbit
, 4);
14288 fix_new_arm (frag_now
, p
- frag_now
->fr_literal
, 4, &exp
, 1,
14289 BFD_RELOC_ARM_PREL31
);
14291 demand_empty_rest_of_line ();
14294 #endif /* OBJ_ELF */
14296 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
14297 of an rs_align_code fragment. */
14300 arm_handle_align (fragP
)
14303 static char const arm_noop
[4] = { 0x00, 0x00, 0xa0, 0xe1 };
14304 static char const thumb_noop
[2] = { 0xc0, 0x46 };
14305 static char const arm_bigend_noop
[4] = { 0xe1, 0xa0, 0x00, 0x00 };
14306 static char const thumb_bigend_noop
[2] = { 0x46, 0xc0 };
14308 int bytes
, fix
, noop_size
;
14312 if (fragP
->fr_type
!= rs_align_code
)
14315 bytes
= fragP
->fr_next
->fr_address
- fragP
->fr_address
- fragP
->fr_fix
;
14316 p
= fragP
->fr_literal
+ fragP
->fr_fix
;
14319 if (bytes
> MAX_MEM_FOR_RS_ALIGN_CODE
)
14320 bytes
&= MAX_MEM_FOR_RS_ALIGN_CODE
;
14322 if (fragP
->tc_frag_data
)
14324 if (target_big_endian
)
14325 noop
= thumb_bigend_noop
;
14328 noop_size
= sizeof (thumb_noop
);
14332 if (target_big_endian
)
14333 noop
= arm_bigend_noop
;
14336 noop_size
= sizeof (arm_noop
);
14339 if (bytes
& (noop_size
- 1))
14341 fix
= bytes
& (noop_size
- 1);
14342 memset (p
, 0, fix
);
14347 while (bytes
>= noop_size
)
14349 memcpy (p
, noop
, noop_size
);
14351 bytes
-= noop_size
;
14355 fragP
->fr_fix
+= fix
;
14356 fragP
->fr_var
= noop_size
;
14359 /* Called from md_do_align. Used to create an alignment
14360 frag in a code section. */
14363 arm_frag_align_code (n
, max
)
14369 /* We assume that there will never be a requirement
14370 to support alignments greater than 32 bytes. */
14371 if (max
> MAX_MEM_FOR_RS_ALIGN_CODE
)
14372 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
14374 p
= frag_var (rs_align_code
,
14375 MAX_MEM_FOR_RS_ALIGN_CODE
,
14377 (relax_substateT
) max
,
14385 /* Perform target specific initialisation of a frag. */
14388 arm_init_frag (fragP
)
14391 /* Record whether this frag is in an ARM or a THUMB area. */
14392 fragP
->tc_frag_data
= thumb_mode
;