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));
2450 static int my_get_expression
PARAMS ((expressionS
*, char **));
2452 const pseudo_typeS md_pseudo_table
[] =
2454 /* Never called because '.req' does not start a line. */
2455 { "req", s_req
, 0 },
2456 { "unreq", s_unreq
, 0 },
2457 { "bss", s_bss
, 0 },
2458 { "align", s_align
, 0 },
2459 { "arm", s_arm
, 0 },
2460 { "thumb", s_thumb
, 0 },
2461 { "code", s_code
, 0 },
2462 { "force_thumb", s_force_thumb
, 0 },
2463 { "thumb_func", s_thumb_func
, 0 },
2464 { "thumb_set", s_thumb_set
, 0 },
2465 { "even", s_even
, 0 },
2466 { "ltorg", s_ltorg
, 0 },
2467 { "pool", s_ltorg
, 0 },
2469 { "word", s_arm_elf_cons
, 4 },
2470 { "long", s_arm_elf_cons
, 4 },
2474 { "extend", float_cons
, 'x' },
2475 { "ldouble", float_cons
, 'x' },
2476 { "packed", float_cons
, 'p' },
2480 /* Other internal functions. */
2481 static int arm_parse_extension
PARAMS ((char *, int *));
2482 static int arm_parse_cpu
PARAMS ((char *));
2483 static int arm_parse_arch
PARAMS ((char *));
2484 static int arm_parse_fpu
PARAMS ((char *));
2485 static int arm_parse_float_abi
PARAMS ((char *));
2487 static int arm_parse_eabi
PARAMS ((char *));
2489 #if 0 /* Suppressed - for now. */
2490 #if defined OBJ_COFF || defined OBJ_ELF
2491 static void arm_add_note
PARAMS ((const char *, const char *, unsigned int));
2495 /* Stuff needed to resolve the label ambiguity
2505 symbolS
* last_label_seen
;
2506 static int label_is_thumb_function_name
= FALSE
;
2508 /* Literal Pool stuff. */
2510 #define MAX_LITERAL_POOL_SIZE 1024
2512 /* Literal pool structure. Held on a per-section
2513 and per-sub-section basis. */
2514 typedef struct literal_pool
2516 expressionS literals
[MAX_LITERAL_POOL_SIZE
];
2517 unsigned int next_free_entry
;
2521 subsegT sub_section
;
2522 struct literal_pool
* next
;
2525 /* Pointer to a linked list of literal pools. */
2526 literal_pool
* list_of_pools
= NULL
;
2528 static literal_pool
* find_literal_pool
PARAMS ((void));
2529 static literal_pool
* find_or_make_literal_pool
PARAMS ((void));
2531 static literal_pool
*
2532 find_literal_pool ()
2534 literal_pool
* pool
;
2536 for (pool
= list_of_pools
; pool
!= NULL
; pool
= pool
->next
)
2538 if (pool
->section
== now_seg
2539 && pool
->sub_section
== now_subseg
)
2546 static literal_pool
*
2547 find_or_make_literal_pool ()
2549 /* Next literal pool ID number. */
2550 static unsigned int latest_pool_num
= 1;
2551 literal_pool
* pool
;
2553 pool
= find_literal_pool ();
2557 /* Create a new pool. */
2558 pool
= (literal_pool
*) xmalloc (sizeof (* pool
));
2562 pool
->next_free_entry
= 0;
2563 pool
->section
= now_seg
;
2564 pool
->sub_section
= now_subseg
;
2565 pool
->next
= list_of_pools
;
2566 pool
->symbol
= NULL
;
2568 /* Add it to the list. */
2569 list_of_pools
= pool
;
2572 /* New pools, and emptied pools, will have a NULL symbol. */
2573 if (pool
->symbol
== NULL
)
2575 pool
->symbol
= symbol_create (FAKE_LABEL_NAME
, undefined_section
,
2576 (valueT
) 0, &zero_address_frag
);
2577 pool
->id
= latest_pool_num
++;
2584 /* Add the literal in the global 'inst'
2585 structure to the relevent literal pool. */
2589 literal_pool
* pool
;
2592 pool
= find_or_make_literal_pool ();
2594 /* Check if this literal value is already in the pool. */
2595 for (entry
= 0; entry
< pool
->next_free_entry
; entry
++)
2597 if ((pool
->literals
[entry
].X_op
== inst
.reloc
.exp
.X_op
)
2598 && (inst
.reloc
.exp
.X_op
== O_constant
)
2599 && (pool
->literals
[entry
].X_add_number
2600 == inst
.reloc
.exp
.X_add_number
)
2601 && (pool
->literals
[entry
].X_unsigned
2602 == inst
.reloc
.exp
.X_unsigned
))
2605 if ((pool
->literals
[entry
].X_op
== inst
.reloc
.exp
.X_op
)
2606 && (inst
.reloc
.exp
.X_op
== O_symbol
)
2607 && (pool
->literals
[entry
].X_add_number
2608 == inst
.reloc
.exp
.X_add_number
)
2609 && (pool
->literals
[entry
].X_add_symbol
2610 == inst
.reloc
.exp
.X_add_symbol
)
2611 && (pool
->literals
[entry
].X_op_symbol
2612 == inst
.reloc
.exp
.X_op_symbol
))
2616 /* Do we need to create a new entry? */
2617 if (entry
== pool
->next_free_entry
)
2619 if (entry
>= MAX_LITERAL_POOL_SIZE
)
2621 inst
.error
= _("literal pool overflow");
2625 pool
->literals
[entry
] = inst
.reloc
.exp
;
2626 pool
->next_free_entry
+= 1;
2629 inst
.reloc
.exp
.X_op
= O_symbol
;
2630 inst
.reloc
.exp
.X_add_number
= ((int) entry
) * 4 - 8;
2631 inst
.reloc
.exp
.X_add_symbol
= pool
->symbol
;
2636 /* Can't use symbol_new here, so have to create a symbol and then at
2637 a later date assign it a value. Thats what these functions do. */
2640 symbol_locate (symbolP
, name
, segment
, valu
, frag
)
2642 const char * name
; /* It is copied, the caller can modify. */
2643 segT segment
; /* Segment identifier (SEG_<something>). */
2644 valueT valu
; /* Symbol value. */
2645 fragS
* frag
; /* Associated fragment. */
2647 unsigned int name_length
;
2648 char * preserved_copy_of_name
;
2650 name_length
= strlen (name
) + 1; /* +1 for \0. */
2651 obstack_grow (¬es
, name
, name_length
);
2652 preserved_copy_of_name
= obstack_finish (¬es
);
2653 #ifdef STRIP_UNDERSCORE
2654 if (preserved_copy_of_name
[0] == '_')
2655 preserved_copy_of_name
++;
2658 #ifdef tc_canonicalize_symbol_name
2659 preserved_copy_of_name
=
2660 tc_canonicalize_symbol_name (preserved_copy_of_name
);
2663 S_SET_NAME (symbolP
, preserved_copy_of_name
);
2665 S_SET_SEGMENT (symbolP
, segment
);
2666 S_SET_VALUE (symbolP
, valu
);
2667 symbol_clear_list_pointers (symbolP
);
2669 symbol_set_frag (symbolP
, frag
);
2671 /* Link to end of symbol chain. */
2673 extern int symbol_table_frozen
;
2674 if (symbol_table_frozen
)
2678 symbol_append (symbolP
, symbol_lastP
, & symbol_rootP
, & symbol_lastP
);
2680 obj_symbol_new_hook (symbolP
);
2682 #ifdef tc_symbol_new_hook
2683 tc_symbol_new_hook (symbolP
);
2687 verify_symbol_chain (symbol_rootP
, symbol_lastP
);
2688 #endif /* DEBUG_SYMS */
2691 /* Check that an immediate is valid.
2692 If so, convert it to the right format. */
2695 validate_immediate (val
)
2701 #define rotate_left(v, n) (v << n | v >> (32 - n))
2703 for (i
= 0; i
< 32; i
+= 2)
2704 if ((a
= rotate_left (val
, i
)) <= 0xff)
2705 return a
| (i
<< 7); /* 12-bit pack: [shift-cnt,const]. */
2710 /* Check to see if an immediate can be computed as two separate immediate
2711 values, added together. We already know that this value cannot be
2712 computed by just one ARM instruction. */
2715 validate_immediate_twopart (val
, highpart
)
2717 unsigned int * highpart
;
2722 for (i
= 0; i
< 32; i
+= 2)
2723 if (((a
= rotate_left (val
, i
)) & 0xff) != 0)
2729 * highpart
= (a
>> 8) | ((i
+ 24) << 7);
2731 else if (a
& 0xff0000)
2735 * highpart
= (a
>> 16) | ((i
+ 16) << 7);
2739 assert (a
& 0xff000000);
2740 * highpart
= (a
>> 24) | ((i
+ 8) << 7);
2743 return (a
& 0xff) | (i
<< 7);
2750 validate_offset_imm (val
, hwse
)
2754 if ((hwse
&& val
> 255) || val
> 4095)
2761 /* This code is to handle mapping symbols as defined in the ARM ELF spec.
2762 (This text is taken from version B-02 of the spec):
2764 4.4.7 Mapping and tagging symbols
2766 A section of an ARM ELF file can contain a mixture of ARM code,
2767 Thumb code, and data. There are inline transitions between code
2768 and data at literal pool boundaries. There can also be inline
2769 transitions between ARM code and Thumb code, for example in
2770 ARM-Thumb inter-working veneers. Linkers, machine-level
2771 debuggers, profiling tools, and disassembly tools need to map
2772 images accurately. For example, setting an ARM breakpoint on a
2773 Thumb location, or in a literal pool, can crash the program
2774 being debugged, ruining the debugging session.
2776 ARM ELF entities are mapped (see section 4.4.7.1 below) and
2777 tagged (see section 4.4.7.2 below) using local symbols (with
2778 binding STB_LOCAL). To assist consumers, mapping and tagging
2779 symbols should be collated first in the symbol table, before
2780 other symbols with binding STB_LOCAL.
2782 To allow properly collated mapping and tagging symbols to be
2783 skipped by consumers that have no interest in them, the first
2784 such symbol should have the name $m and its st_value field equal
2785 to the total number of mapping and tagging symbols (including
2786 the $m) in the symbol table.
2788 4.4.7.1 Mapping symbols
2790 $a Labels the first byte of a sequence of ARM instructions.
2791 Its type is STT_FUNC.
2793 $d Labels the first byte of a sequence of data items.
2794 Its type is STT_OBJECT.
2796 $t Labels the first byte of a sequence of Thumb instructions.
2797 Its type is STT_FUNC.
2799 This list of mapping symbols may be extended in the future.
2801 Section-relative mapping symbols
2803 Mapping symbols defined in a section define a sequence of
2804 half-open address intervals that cover the address range of the
2805 section. Each interval starts at the address defined by a
2806 mapping symbol, and continues up to, but not including, the
2807 address defined by the next (in address order) mapping symbol or
2808 the end of the section. A corollary is that there must be a
2809 mapping symbol defined at the beginning of each section.
2810 Consumers can ignore the size of a section-relative mapping
2811 symbol. Producers can set it to 0.
2813 Absolute mapping symbols
2815 Because of the need to crystallize a Thumb address with the
2816 Thumb-bit set, absolute symbol of type STT_FUNC (symbols of type
2817 STT_FUNC defined in section SHN_ABS) need to be mapped with $a
2820 The extent of a mapping symbol defined in SHN_ABS is [st_value,
2821 st_value + st_size), or [st_value, st_value + 1) if st_size = 0,
2822 where [x, y) denotes the half-open address range from x,
2823 inclusive, to y, exclusive.
2825 In the absence of a mapping symbol, a consumer can interpret a
2826 function symbol with an odd value as the Thumb code address
2827 obtained by clearing the least significant bit of the
2828 value. This interpretation is deprecated, and it may not work in
2831 Note - the Tagging symbols ($b, $f, $p $m) have been dropped from
2832 the EABI (which is still under development), so they are not
2833 implemented here. */
2835 static enum mstate mapstate
= MAP_UNDEFINED
;
2838 mapping_state (enum mstate state
)
2841 const char * symname
;
2844 if (mapstate
== state
)
2845 /* The mapping symbol has already been emitted.
2846 There is nothing else to do. */
2859 type
= BSF_FUNCTION
;
2863 type
= BSF_FUNCTION
;
2871 seg_info (now_seg
)->tc_segment_info_data
= state
;
2873 symbolP
= symbol_new (symname
, now_seg
, (valueT
) frag_now_fix (), frag_now
);
2874 symbol_table_insert (symbolP
);
2875 symbol_get_bfdsym (symbolP
)->flags
|= type
| BSF_LOCAL
;
2880 THUMB_SET_FUNC (symbolP
, 0);
2881 ARM_SET_THUMB (symbolP
, 0);
2882 ARM_SET_INTERWORK (symbolP
, support_interwork
);
2886 THUMB_SET_FUNC (symbolP
, 1);
2887 ARM_SET_THUMB (symbolP
, 1);
2888 ARM_SET_INTERWORK (symbolP
, support_interwork
);
2897 /* When we change sections we need to issue a new mapping symbol. */
2900 arm_elf_change_section (void)
2904 if (!SEG_NORMAL (now_seg
))
2907 flags
= bfd_get_section_flags (stdoutput
, now_seg
);
2909 /* We can ignore sections that only contain debug info. */
2910 if ((flags
& SEC_ALLOC
) == 0)
2913 mapstate
= seg_info (now_seg
)->tc_segment_info_data
;
2916 #define mapping_state(a)
2917 #endif /* OBJ_ELF */
2922 int a ATTRIBUTE_UNUSED
;
2924 as_bad (_("invalid syntax for .req directive"));
2927 /* The .unreq directive deletes an alias which was previously defined
2928 by .req. For example:
2934 s_unreq (int a ATTRIBUTE_UNUSED
)
2939 skip_whitespace (input_line_pointer
);
2940 name
= input_line_pointer
;
2942 while (*input_line_pointer
!= 0
2943 && *input_line_pointer
!= ' '
2944 && *input_line_pointer
!= '\n')
2945 ++input_line_pointer
;
2947 saved_char
= *input_line_pointer
;
2948 *input_line_pointer
= 0;
2952 enum arm_reg_type req_type
= arm_reg_parse_any (name
);
2954 if (req_type
!= REG_TYPE_MAX
)
2956 char *temp_name
= name
;
2957 int req_no
= arm_reg_parse (&temp_name
, all_reg_maps
[req_type
].htab
);
2961 struct reg_entry
*req_entry
;
2963 /* Check to see if this alias is a builtin one. */
2964 req_entry
= hash_delete (all_reg_maps
[req_type
].htab
, name
);
2967 as_bad (_("unreq: missing hash entry for \"%s\""), name
);
2968 else if (req_entry
->builtin
)
2969 /* FIXME: We are deleting a built in register alias which
2970 points to a const data structure, so we only need to
2971 free up the memory used by the key in the hash table.
2972 Unfortunately we have not recorded this value, so this
2973 is a memory leak. */
2974 /* FIXME: Should we issue a warning message ? */
2978 /* Deleting a user defined alias. We need to free the
2979 key and the value, but fortunately the key is the same
2980 as the value->name field. */
2981 free ((char *) req_entry
->name
);
2986 as_bad (_(".unreq: unrecognized symbol \"%s\""), name
);
2989 as_bad (_(".unreq: unrecognized symbol \"%s\""), name
);
2992 as_bad (_("invalid syntax for .unreq directive"));
2994 *input_line_pointer
= saved_char
;
2995 demand_empty_rest_of_line ();
3000 int ignore ATTRIBUTE_UNUSED
;
3002 /* We don't support putting frags in the BSS segment, we fake it by
3003 marking in_bss, then looking at s_skip for clues. */
3004 subseg_set (bss_section
, 0);
3005 demand_empty_rest_of_line ();
3006 mapping_state (MAP_DATA
);
3011 int ignore ATTRIBUTE_UNUSED
;
3013 /* Never make frag if expect extra pass. */
3015 frag_align (1, 0, 0);
3017 record_alignment (now_seg
, 1);
3019 demand_empty_rest_of_line ();
3024 int ignored ATTRIBUTE_UNUSED
;
3027 literal_pool
* pool
;
3030 pool
= find_literal_pool ();
3032 || pool
->symbol
== NULL
3033 || pool
->next_free_entry
== 0)
3036 mapping_state (MAP_DATA
);
3038 /* Align pool as you have word accesses.
3039 Only make a frag if we have to. */
3041 frag_align (2, 0, 0);
3043 record_alignment (now_seg
, 2);
3045 sprintf (sym_name
, "$$lit_\002%x", pool
->id
);
3047 symbol_locate (pool
->symbol
, sym_name
, now_seg
,
3048 (valueT
) frag_now_fix (), frag_now
);
3049 symbol_table_insert (pool
->symbol
);
3051 ARM_SET_THUMB (pool
->symbol
, thumb_mode
);
3053 #if defined OBJ_COFF || defined OBJ_ELF
3054 ARM_SET_INTERWORK (pool
->symbol
, support_interwork
);
3057 for (entry
= 0; entry
< pool
->next_free_entry
; entry
++)
3058 /* First output the expression in the instruction to the pool. */
3059 emit_expr (&(pool
->literals
[entry
]), 4); /* .word */
3061 /* Mark the pool as empty. */
3062 pool
->next_free_entry
= 0;
3063 pool
->symbol
= NULL
;
3066 /* Same as s_align_ptwo but align 0 => align 2. */
3070 int unused ATTRIBUTE_UNUSED
;
3073 register long temp_fill
;
3074 long max_alignment
= 15;
3076 temp
= get_absolute_expression ();
3077 if (temp
> max_alignment
)
3078 as_bad (_("alignment too large: %d assumed"), temp
= max_alignment
);
3081 as_bad (_("alignment negative. 0 assumed."));
3085 if (*input_line_pointer
== ',')
3087 input_line_pointer
++;
3088 temp_fill
= get_absolute_expression ();
3096 /* Only make a frag if we HAVE to. */
3097 if (temp
&& !need_pass_2
)
3098 frag_align (temp
, (int) temp_fill
, 0);
3099 demand_empty_rest_of_line ();
3101 record_alignment (now_seg
, temp
);
3105 s_force_thumb (ignore
)
3106 int ignore ATTRIBUTE_UNUSED
;
3108 /* If we are not already in thumb mode go into it, EVEN if
3109 the target processor does not support thumb instructions.
3110 This is used by gcc/config/arm/lib1funcs.asm for example
3111 to compile interworking support functions even if the
3112 target processor should not support interworking. */
3117 record_alignment (now_seg
, 1);
3120 demand_empty_rest_of_line ();
3124 s_thumb_func (ignore
)
3125 int ignore ATTRIBUTE_UNUSED
;
3130 /* The following label is the name/address of the start of a Thumb function.
3131 We need to know this for the interworking support. */
3132 label_is_thumb_function_name
= TRUE
;
3134 demand_empty_rest_of_line ();
3137 /* Perform a .set directive, but also mark the alias as
3138 being a thumb function. */
3144 /* XXX the following is a duplicate of the code for s_set() in read.c
3145 We cannot just call that code as we need to get at the symbol that
3147 register char * name
;
3148 register char delim
;
3149 register char * end_name
;
3150 register symbolS
* symbolP
;
3152 /* Especial apologies for the random logic:
3153 This just grew, and could be parsed much more simply!
3155 name
= input_line_pointer
;
3156 delim
= get_symbol_end ();
3157 end_name
= input_line_pointer
;
3162 if (*input_line_pointer
!= ',')
3165 as_bad (_("expected comma after name \"%s\""), name
);
3167 ignore_rest_of_line ();
3171 input_line_pointer
++;
3174 if (name
[0] == '.' && name
[1] == '\0')
3176 /* XXX - this should not happen to .thumb_set. */
3180 if ((symbolP
= symbol_find (name
)) == NULL
3181 && (symbolP
= md_undefined_symbol (name
)) == NULL
)
3184 /* When doing symbol listings, play games with dummy fragments living
3185 outside the normal fragment chain to record the file and line info
3187 if (listing
& LISTING_SYMBOLS
)
3189 extern struct list_info_struct
* listing_tail
;
3190 fragS
* dummy_frag
= (fragS
*) xmalloc (sizeof (fragS
));
3192 memset (dummy_frag
, 0, sizeof (fragS
));
3193 dummy_frag
->fr_type
= rs_fill
;
3194 dummy_frag
->line
= listing_tail
;
3195 symbolP
= symbol_new (name
, undefined_section
, 0, dummy_frag
);
3196 dummy_frag
->fr_symbol
= symbolP
;
3200 symbolP
= symbol_new (name
, undefined_section
, 0, &zero_address_frag
);
3203 /* "set" symbols are local unless otherwise specified. */
3204 SF_SET_LOCAL (symbolP
);
3205 #endif /* OBJ_COFF */
3206 } /* Make a new symbol. */
3208 symbol_table_insert (symbolP
);
3213 && S_IS_DEFINED (symbolP
)
3214 && S_GET_SEGMENT (symbolP
) != reg_section
)
3215 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP
));
3217 pseudo_set (symbolP
);
3219 demand_empty_rest_of_line ();
3221 /* XXX Now we come to the Thumb specific bit of code. */
3223 THUMB_SET_FUNC (symbolP
, 1);
3224 ARM_SET_THUMB (symbolP
, 1);
3225 #if defined OBJ_ELF || defined OBJ_COFF
3226 ARM_SET_INTERWORK (symbolP
, support_interwork
);
3231 opcode_select (width
)
3239 if (! (cpu_variant
& ARM_EXT_V4T
))
3240 as_bad (_("selected processor does not support THUMB opcodes"));
3243 /* No need to force the alignment, since we will have been
3244 coming from ARM mode, which is word-aligned. */
3245 record_alignment (now_seg
, 1);
3247 mapping_state (MAP_THUMB
);
3253 if ((cpu_variant
& ARM_ALL
) == ARM_EXT_V4T
)
3254 as_bad (_("selected processor does not support ARM opcodes"));
3259 frag_align (2, 0, 0);
3261 record_alignment (now_seg
, 1);
3263 mapping_state (MAP_ARM
);
3267 as_bad (_("invalid instruction size selected (%d)"), width
);
3273 int ignore ATTRIBUTE_UNUSED
;
3276 demand_empty_rest_of_line ();
3281 int ignore ATTRIBUTE_UNUSED
;
3284 demand_empty_rest_of_line ();
3289 int unused ATTRIBUTE_UNUSED
;
3293 temp
= get_absolute_expression ();
3298 opcode_select (temp
);
3302 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp
);
3310 skip_whitespace (str
);
3312 if (*str
!= '\0' && !inst
.error
)
3313 inst
.error
= _("garbage following instruction");
3317 skip_past_comma (str
)
3320 char * p
= * str
, c
;
3323 while ((c
= *p
) == ' ' || c
== ',')
3326 if (c
== ',' && comma
++)
3334 return comma
? SUCCESS
: FAIL
;
3337 /* A standard register must be given at this point.
3338 SHIFT is the place to put it in inst.instruction.
3339 Restores input start point on error.
3340 Returns the reg#, or FAIL. */
3343 reg_required_here (str
, shift
)
3347 static char buff
[128]; /* XXX */
3349 char * start
= * str
;
3351 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_RN
].htab
)) != FAIL
)
3354 inst
.instruction
|= reg
<< shift
;
3358 /* Restore the start point, we may have got a reg of the wrong class. */
3361 /* In the few cases where we might be able to accept something else
3362 this error can be overridden. */
3363 sprintf (buff
, _("register expected, not '%.100s'"), start
);
3369 /* A Intel Wireless MMX technology register
3370 must be given at this point.
3371 Shift is the place to put it in inst.instruction.
3372 Restores input start point on err.
3373 Returns the reg#, or FAIL. */
3376 wreg_required_here (str
, shift
, reg_type
)
3379 enum wreg_type reg_type
;
3381 static char buff
[128];
3383 char * start
= *str
;
3385 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_IWMMXT
].htab
)) != FAIL
)
3387 if (wr_register (reg
)
3388 && (reg_type
== IWMMXT_REG_WR
|| reg_type
== IWMMXT_REG_WR_OR_WC
))
3391 inst
.instruction
|= (reg
^ WR_PREFIX
) << shift
;
3394 else if (wc_register (reg
)
3395 && (reg_type
== IWMMXT_REG_WC
|| reg_type
== IWMMXT_REG_WR_OR_WC
))
3398 inst
.instruction
|= (reg
^ WC_PREFIX
) << shift
;
3401 else if ((wcg_register (reg
) && reg_type
== IWMMXT_REG_WCG
))
3404 inst
.instruction
|= ((reg
^ WC_PREFIX
) - 8) << shift
;
3409 /* Restore the start point, we may have got a reg of the wrong class. */
3412 /* In the few cases where we might be able to accept
3413 something else this error can be overridden. */
3414 sprintf (buff
, _("Intel Wireless MMX technology register expected, not '%.100s'"), start
);
3420 static const struct asm_psr
*
3422 register char ** ccp
;
3424 char * start
= * ccp
;
3427 const struct asm_psr
* psr
;
3431 /* Skip to the end of the next word in the input stream. */
3436 while (ISALPHA (c
) || c
== '_');
3438 /* Terminate the word. */
3441 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
3442 feature for ease of use and backwards compatibility. */
3443 if (!strncmp (start
, "cpsr", 4))
3444 strncpy (start
, "CPSR", 4);
3445 else if (!strncmp (start
, "spsr", 4))
3446 strncpy (start
, "SPSR", 4);
3448 /* Now locate the word in the psr hash table. */
3449 psr
= (const struct asm_psr
*) hash_find (arm_psr_hsh
, start
);
3451 /* Restore the input stream. */
3454 /* If we found a valid match, advance the
3455 stream pointer past the end of the word. */
3461 /* Parse the input looking for a PSR flag. */
3464 psr_required_here (str
)
3467 char * start
= * str
;
3468 const struct asm_psr
* psr
;
3470 psr
= arm_psr_parse (str
);
3474 /* If this is the SPSR that is being modified, set the R bit. */
3476 inst
.instruction
|= SPSR_BIT
;
3478 /* Set the psr flags in the MSR instruction. */
3479 inst
.instruction
|= psr
->field
<< PSR_SHIFT
;
3484 /* In the few cases where we might be able to accept
3485 something else this error can be overridden. */
3486 inst
.error
= _("flag for {c}psr instruction expected");
3488 /* Restore the start point. */
3494 co_proc_number (str
)
3497 int processor
, pchar
;
3500 skip_whitespace (*str
);
3503 /* The data sheet seems to imply that just a number on its own is valid
3504 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
3506 if ((processor
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CP
].htab
))
3512 if (pchar
>= '0' && pchar
<= '9')
3514 processor
= pchar
- '0';
3515 if (**str
>= '0' && **str
<= '9')
3517 processor
= processor
* 10 + *(*str
)++ - '0';
3520 inst
.error
= _("illegal co-processor number");
3527 inst
.error
= all_reg_maps
[REG_TYPE_CP
].expected
;
3532 inst
.instruction
|= processor
<< 8;
3537 cp_opc_expr (str
, where
, length
)
3544 skip_whitespace (* str
);
3546 memset (&expr
, '\0', sizeof (expr
));
3548 if (my_get_expression (&expr
, str
))
3550 if (expr
.X_op
!= O_constant
)
3552 inst
.error
= _("bad or missing expression");
3556 if ((expr
.X_add_number
& ((1 << length
) - 1)) != expr
.X_add_number
)
3558 inst
.error
= _("immediate co-processor expression too large");
3562 inst
.instruction
|= expr
.X_add_number
<< where
;
3567 cp_reg_required_here (str
, where
)
3572 char * start
= *str
;
3574 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CN
].htab
)) != FAIL
)
3576 inst
.instruction
|= reg
<< where
;
3580 /* In the few cases where we might be able to accept something else
3581 this error can be overridden. */
3582 inst
.error
= all_reg_maps
[REG_TYPE_CN
].expected
;
3584 /* Restore the start point. */
3590 fp_reg_required_here (str
, where
)
3595 char * start
= * str
;
3597 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_FN
].htab
)) != FAIL
)
3599 inst
.instruction
|= reg
<< where
;
3603 /* In the few cases where we might be able to accept something else
3604 this error can be overridden. */
3605 inst
.error
= all_reg_maps
[REG_TYPE_FN
].expected
;
3607 /* Restore the start point. */
3613 cp_address_offset (str
)
3618 skip_whitespace (* str
);
3620 if (! is_immediate_prefix (**str
))
3622 inst
.error
= _("immediate expression expected");
3628 if (my_get_expression (& inst
.reloc
.exp
, str
))
3631 if (inst
.reloc
.exp
.X_op
== O_constant
)
3633 offset
= inst
.reloc
.exp
.X_add_number
;
3637 inst
.error
= _("co-processor address must be word aligned");
3641 if (offset
> 1023 || offset
< -1023)
3643 inst
.error
= _("offset too large");
3648 inst
.instruction
|= INDEX_UP
;
3652 inst
.instruction
|= offset
>> 2;
3655 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
3661 cp_address_required_here (str
, wb_ok
)
3674 skip_whitespace (p
);
3676 if ((reg
= reg_required_here (& p
, 16)) == FAIL
)
3679 skip_whitespace (p
);
3685 skip_whitespace (p
);
3689 /* As an extension to the official ARM syntax we allow:
3693 as a short hand for:
3696 inst
.instruction
|= PRE_INDEX
| INDEX_UP
;
3701 if (skip_past_comma (& p
) == FAIL
)
3703 inst
.error
= _("comma expected after closing square bracket");
3707 skip_whitespace (p
);
3714 write_back
= WRITE_BACK
;
3718 inst
.error
= _("pc may not be used in post-increment");
3722 if (cp_address_offset (& p
) == FAIL
)
3726 pre_inc
= PRE_INDEX
| INDEX_UP
;
3732 /* [Rn], {<expr>} */
3735 skip_whitespace (p
);
3737 if (my_get_expression (& inst
.reloc
.exp
, & p
))
3740 if (inst
.reloc
.exp
.X_op
== O_constant
)
3742 option
= inst
.reloc
.exp
.X_add_number
;
3744 if (option
> 255 || option
< 0)
3746 inst
.error
= _("'option' field too large");
3750 skip_whitespace (p
);
3754 inst
.error
= _("'}' expected at end of 'option' field");
3760 inst
.instruction
|= option
;
3761 inst
.instruction
|= INDEX_UP
;
3766 inst
.error
= _("non-constant expressions for 'option' field not supported");
3772 inst
.error
= _("# or { expected after comma");
3778 /* '['Rn, #expr']'[!] */
3780 if (skip_past_comma (& p
) == FAIL
)
3782 inst
.error
= _("pre-indexed expression expected");
3786 pre_inc
= PRE_INDEX
;
3788 if (cp_address_offset (& p
) == FAIL
)
3791 skip_whitespace (p
);
3795 inst
.error
= _("missing ]");
3799 skip_whitespace (p
);
3801 if (wb_ok
&& *p
== '!')
3805 inst
.error
= _("pc may not be used with write-back");
3810 write_back
= WRITE_BACK
;
3816 if (my_get_expression (&inst
.reloc
.exp
, &p
))
3819 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
3820 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
3821 inst
.reloc
.pc_rel
= 1;
3822 inst
.instruction
|= (REG_PC
<< 16);
3823 pre_inc
= PRE_INDEX
;
3826 inst
.instruction
|= write_back
| pre_inc
;
3832 cp_byte_address_offset (str
)
3837 skip_whitespace (* str
);
3839 if (! is_immediate_prefix (**str
))
3841 inst
.error
= _("immediate expression expected");
3847 if (my_get_expression (& inst
.reloc
.exp
, str
))
3850 if (inst
.reloc
.exp
.X_op
== O_constant
)
3852 offset
= inst
.reloc
.exp
.X_add_number
;
3854 if (offset
> 255 || offset
< -255)
3856 inst
.error
= _("offset too large");
3861 inst
.instruction
|= INDEX_UP
;
3865 inst
.instruction
|= offset
;
3868 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM_S2
;
3874 cp_byte_address_required_here (str
)
3886 skip_whitespace (p
);
3888 if ((reg
= reg_required_here (& p
, 16)) == FAIL
)
3891 skip_whitespace (p
);
3897 if (skip_past_comma (& p
) == SUCCESS
)
3900 write_back
= WRITE_BACK
;
3904 inst
.error
= _("pc may not be used in post-increment");
3908 if (cp_byte_address_offset (& p
) == FAIL
)
3912 pre_inc
= PRE_INDEX
| INDEX_UP
;
3916 /* '['Rn, #expr']'[!] */
3918 if (skip_past_comma (& p
) == FAIL
)
3920 inst
.error
= _("pre-indexed expression expected");
3924 pre_inc
= PRE_INDEX
;
3926 if (cp_byte_address_offset (& p
) == FAIL
)
3929 skip_whitespace (p
);
3933 inst
.error
= _("missing ]");
3937 skip_whitespace (p
);
3943 inst
.error
= _("pc may not be used with write-back");
3948 write_back
= WRITE_BACK
;
3954 if (my_get_expression (&inst
.reloc
.exp
, &p
))
3957 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM_S2
;
3958 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
3959 inst
.reloc
.pc_rel
= 1;
3960 inst
.instruction
|= (REG_PC
<< 16);
3961 pre_inc
= PRE_INDEX
;
3964 inst
.instruction
|= write_back
| pre_inc
;
3973 /* Do nothing really. */
3983 /* Only one syntax. */
3984 skip_whitespace (str
);
3986 if (reg_required_here (&str
, 12) == FAIL
)
3988 inst
.error
= BAD_ARGS
;
3992 if (skip_past_comma (&str
) == FAIL
)
3994 inst
.error
= _("comma expected after register name");
3998 skip_whitespace (str
);
4000 if ( strcmp (str
, "CPSR") == 0
4001 || strcmp (str
, "SPSR") == 0
4002 /* Lower case versions for backwards compatibility. */
4003 || strcmp (str
, "cpsr") == 0
4004 || strcmp (str
, "spsr") == 0)
4007 /* This is for backwards compatibility with older toolchains. */
4008 else if ( strcmp (str
, "cpsr_all") == 0
4009 || strcmp (str
, "spsr_all") == 0)
4013 inst
.error
= _("CPSR or SPSR expected");
4017 if (* str
== 's' || * str
== 'S')
4018 inst
.instruction
|= SPSR_BIT
;
4024 /* Two possible forms:
4025 "{C|S}PSR_<field>, Rm",
4026 "{C|S}PSR_f, #expression". */
4032 skip_whitespace (str
);
4034 if (psr_required_here (& str
) == FAIL
)
4037 if (skip_past_comma (& str
) == FAIL
)
4039 inst
.error
= _("comma missing after psr flags");
4043 skip_whitespace (str
);
4045 if (reg_required_here (& str
, 0) != FAIL
)
4052 if (! is_immediate_prefix (* str
))
4055 _("only a register or immediate value can follow a psr flag");
4062 if (my_get_expression (& inst
.reloc
.exp
, & str
))
4065 _("only a register or immediate value can follow a psr flag");
4069 #if 0 /* The first edition of the ARM architecture manual stated that
4070 writing anything other than the flags with an immediate operation
4071 had UNPREDICTABLE effects. This constraint was removed in the
4072 second edition of the specification. */
4073 if ((cpu_variant
& ARM_EXT_V5
) != ARM_EXT_V5
4074 && inst
.instruction
& ((PSR_c
| PSR_x
| PSR_s
) << PSR_SHIFT
))
4076 inst
.error
= _("immediate value cannot be used to set this field");
4081 inst
.instruction
|= INST_IMMEDIATE
;
4083 if (inst
.reloc
.exp
.X_add_symbol
)
4085 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
4086 inst
.reloc
.pc_rel
= 0;
4090 unsigned value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
4092 if (value
== (unsigned) FAIL
)
4094 inst
.error
= _("invalid constant");
4098 inst
.instruction
|= value
;
4105 /* Long Multiply Parser
4106 UMULL RdLo, RdHi, Rm, Rs
4107 SMULL RdLo, RdHi, Rm, Rs
4108 UMLAL RdLo, RdHi, Rm, Rs
4109 SMLAL RdLo, RdHi, Rm, Rs. */
4115 int rdlo
, rdhi
, rm
, rs
;
4117 /* Only one format "rdlo, rdhi, rm, rs". */
4118 skip_whitespace (str
);
4120 if ((rdlo
= reg_required_here (&str
, 12)) == FAIL
)
4122 inst
.error
= BAD_ARGS
;
4126 if (skip_past_comma (&str
) == FAIL
4127 || (rdhi
= reg_required_here (&str
, 16)) == FAIL
)
4129 inst
.error
= BAD_ARGS
;
4133 if (skip_past_comma (&str
) == FAIL
4134 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4136 inst
.error
= BAD_ARGS
;
4140 /* rdhi, rdlo and rm must all be different. */
4141 if (rdlo
== rdhi
|| rdlo
== rm
|| rdhi
== rm
)
4142 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
4144 if (skip_past_comma (&str
) == FAIL
4145 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
4147 inst
.error
= BAD_ARGS
;
4151 if (rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
)
4153 inst
.error
= BAD_PC
;
4166 /* Only one format "rd, rm, rs". */
4167 skip_whitespace (str
);
4169 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
4171 inst
.error
= BAD_ARGS
;
4177 inst
.error
= BAD_PC
;
4181 if (skip_past_comma (&str
) == FAIL
4182 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4184 inst
.error
= BAD_ARGS
;
4190 inst
.error
= BAD_PC
;
4195 as_tsktsk (_("rd and rm should be different in mul"));
4197 if (skip_past_comma (&str
) == FAIL
4198 || (rm
= reg_required_here (&str
, 8)) == FAIL
)
4200 inst
.error
= BAD_ARGS
;
4206 inst
.error
= BAD_PC
;
4219 /* Only one format "rd, rm, rs, rn". */
4220 skip_whitespace (str
);
4222 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
4224 inst
.error
= BAD_ARGS
;
4230 inst
.error
= BAD_PC
;
4234 if (skip_past_comma (&str
) == FAIL
4235 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4237 inst
.error
= BAD_ARGS
;
4243 inst
.error
= BAD_PC
;
4248 as_tsktsk (_("rd and rm should be different in mla"));
4250 if (skip_past_comma (&str
) == FAIL
4251 || (rd
= reg_required_here (&str
, 8)) == FAIL
4252 || skip_past_comma (&str
) == FAIL
4253 || (rm
= reg_required_here (&str
, 12)) == FAIL
)
4255 inst
.error
= BAD_ARGS
;
4259 if (rd
== REG_PC
|| rm
== REG_PC
)
4261 inst
.error
= BAD_PC
;
4268 /* Expects *str -> the characters "acc0", possibly with leading blanks.
4269 Advances *str to the next non-alphanumeric.
4270 Returns 0, or else FAIL (in which case sets inst.error).
4272 (In a future XScale, there may be accumulators other than zero.
4273 At that time this routine and its callers can be upgraded to suit.) */
4276 accum0_required_here (str
)
4279 static char buff
[128]; /* Note the address is taken. Hence, static. */
4282 int result
= 0; /* The accum number. */
4284 skip_whitespace (p
);
4286 *str
= p
; /* Advance caller's string pointer too. */
4291 *--p
= 0; /* Aap nul into input buffer at non-alnum. */
4293 if (! ( streq (*str
, "acc0") || streq (*str
, "ACC0")))
4295 sprintf (buff
, _("acc0 expected, not '%.100s'"), *str
);
4300 *p
= c
; /* Unzap. */
4301 *str
= p
; /* Caller's string pointer to after match. */
4305 /* Expects **str -> after a comma. May be leading blanks.
4306 Advances *str, recognizing a load mode, and setting inst.instruction.
4307 Returns rn, or else FAIL (in which case may set inst.error
4308 and not advance str)
4310 Note: doesn't know Rd, so no err checks that require such knowledge. */
4313 ld_mode_required_here (string
)
4316 char * str
= * string
;
4320 skip_whitespace (str
);
4326 skip_whitespace (str
);
4328 if ((rn
= reg_required_here (& str
, 16)) == FAIL
)
4331 skip_whitespace (str
);
4337 if (skip_past_comma (& str
) == SUCCESS
)
4339 /* [Rn],... (post inc) */
4340 if (ldst_extend_v4 (&str
) == FAIL
)
4345 skip_whitespace (str
);
4350 inst
.instruction
|= WRITE_BACK
;
4353 inst
.instruction
|= INDEX_UP
| HWOFFSET_IMM
;
4359 if (skip_past_comma (& str
) == FAIL
)
4361 inst
.error
= _("pre-indexed expression expected");
4367 if (ldst_extend_v4 (&str
) == FAIL
)
4370 skip_whitespace (str
);
4372 if (* str
++ != ']')
4374 inst
.error
= _("missing ]");
4378 skip_whitespace (str
);
4383 inst
.instruction
|= WRITE_BACK
;
4387 else if (* str
== '=') /* ldr's "r,=label" syntax */
4388 /* We should never reach here, because <text> = <expression> is
4389 caught gas/read.c read_a_source_file() as a .set operation. */
4391 else /* PC +- 8 bit immediate offset. */
4393 if (my_get_expression (& inst
.reloc
.exp
, & str
))
4396 inst
.instruction
|= HWOFFSET_IMM
; /* The I bit. */
4397 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
4398 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
4399 inst
.reloc
.pc_rel
= 1;
4400 inst
.instruction
|= (REG_PC
<< 16);
4406 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
4412 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
4413 SMLAxy{cond} Rd,Rm,Rs,Rn
4414 SMLAWy{cond} Rd,Rm,Rs,Rn
4415 Error if any register is R15. */
4423 skip_whitespace (str
);
4425 if ((rd
= reg_required_here (& str
, 16)) == FAIL
4426 || skip_past_comma (& str
) == FAIL
4427 || (rm
= reg_required_here (& str
, 0)) == FAIL
4428 || skip_past_comma (& str
) == FAIL
4429 || (rs
= reg_required_here (& str
, 8)) == FAIL
4430 || skip_past_comma (& str
) == FAIL
4431 || (rn
= reg_required_here (& str
, 12)) == FAIL
)
4432 inst
.error
= BAD_ARGS
;
4434 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
|| rn
== REG_PC
)
4435 inst
.error
= BAD_PC
;
4441 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
4442 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
4443 Error if any register is R15.
4444 Warning if Rdlo == Rdhi. */
4450 int rdlo
, rdhi
, rm
, rs
;
4452 skip_whitespace (str
);
4454 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
4455 || skip_past_comma (& str
) == FAIL
4456 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
4457 || skip_past_comma (& str
) == FAIL
4458 || (rm
= reg_required_here (& str
, 0)) == FAIL
4459 || skip_past_comma (& str
) == FAIL
4460 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
4462 inst
.error
= BAD_ARGS
;
4466 if (rdlo
== REG_PC
|| rdhi
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
4468 inst
.error
= BAD_PC
;
4473 as_tsktsk (_("rdhi and rdlo must be different"));
4478 /* ARM V5E (El Segundo) signed-multiply (argument parse)
4479 SMULxy{cond} Rd,Rm,Rs
4480 Error if any register is R15. */
4488 skip_whitespace (str
);
4490 if ((rd
= reg_required_here (& str
, 16)) == FAIL
4491 || skip_past_comma (& str
) == FAIL
4492 || (rm
= reg_required_here (& str
, 0)) == FAIL
4493 || skip_past_comma (& str
) == FAIL
4494 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
4495 inst
.error
= BAD_ARGS
;
4497 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
4498 inst
.error
= BAD_PC
;
4504 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
4505 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
4506 Error if any register is R15. */
4514 skip_whitespace (str
);
4516 if ((rd
= reg_required_here (& str
, 12)) == FAIL
4517 || skip_past_comma (& str
) == FAIL
4518 || (rm
= reg_required_here (& str
, 0)) == FAIL
4519 || skip_past_comma (& str
) == FAIL
4520 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
4521 inst
.error
= BAD_ARGS
;
4523 else if (rd
== REG_PC
|| rm
== REG_PC
|| rn
== REG_PC
)
4524 inst
.error
= BAD_PC
;
4530 /* ARM V5E (el Segundo)
4531 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4532 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4534 These are equivalent to the XScale instructions MAR and MRA,
4535 respectively, when coproc == 0, opcode == 0, and CRm == 0.
4537 Result unpredicatable if Rd or Rn is R15. */
4545 skip_whitespace (str
);
4547 if (co_proc_number (& str
) == FAIL
)
4550 inst
.error
= BAD_ARGS
;
4554 if (skip_past_comma (& str
) == FAIL
4555 || cp_opc_expr (& str
, 4, 4) == FAIL
)
4558 inst
.error
= BAD_ARGS
;
4562 if (skip_past_comma (& str
) == FAIL
4563 || (rd
= reg_required_here (& str
, 12)) == FAIL
)
4566 inst
.error
= BAD_ARGS
;
4570 if (skip_past_comma (& str
) == FAIL
4571 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
4574 inst
.error
= BAD_ARGS
;
4578 /* Unpredictable result if rd or rn is R15. */
4579 if (rd
== REG_PC
|| rn
== REG_PC
)
4581 (_("Warning: instruction unpredictable when using r15"));
4583 if (skip_past_comma (& str
) == FAIL
4584 || cp_reg_required_here (& str
, 0) == FAIL
)
4587 inst
.error
= BAD_ARGS
;
4594 /* ARM V5 count-leading-zeroes instruction (argument parse)
4595 CLZ{<cond>} <Rd>, <Rm>
4596 Condition defaults to COND_ALWAYS.
4597 Error if Rd or Rm are R15. */
4605 skip_whitespace (str
);
4607 if (((rd
= reg_required_here (& str
, 12)) == FAIL
)
4608 || (skip_past_comma (& str
) == FAIL
)
4609 || ((rm
= reg_required_here (& str
, 0)) == FAIL
))
4610 inst
.error
= BAD_ARGS
;
4612 else if (rd
== REG_PC
|| rm
== REG_PC
)
4613 inst
.error
= BAD_PC
;
4619 /* ARM V5 (argument parse)
4620 LDC2{L} <coproc>, <CRd>, <addressing mode>
4621 STC2{L} <coproc>, <CRd>, <addressing mode>
4622 Instruction is not conditional, and has 0xf in the condition field.
4623 Otherwise, it's the same as LDC/STC. */
4629 skip_whitespace (str
);
4631 if (co_proc_number (& str
) == FAIL
)
4634 inst
.error
= BAD_ARGS
;
4636 else if (skip_past_comma (& str
) == FAIL
4637 || cp_reg_required_here (& str
, 12) == FAIL
)
4640 inst
.error
= BAD_ARGS
;
4642 else if (skip_past_comma (& str
) == FAIL
4643 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
4646 inst
.error
= BAD_ARGS
;
4652 /* ARM V5 (argument parse)
4653 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
4654 Instruction is not conditional, and has 0xf in the condition field.
4655 Otherwise, it's the same as CDP. */
4661 skip_whitespace (str
);
4663 if (co_proc_number (& str
) == FAIL
)
4666 inst
.error
= BAD_ARGS
;
4670 if (skip_past_comma (& str
) == FAIL
4671 || cp_opc_expr (& str
, 20,4) == FAIL
)
4674 inst
.error
= BAD_ARGS
;
4678 if (skip_past_comma (& str
) == FAIL
4679 || cp_reg_required_here (& str
, 12) == FAIL
)
4682 inst
.error
= BAD_ARGS
;
4686 if (skip_past_comma (& str
) == FAIL
4687 || cp_reg_required_here (& str
, 16) == FAIL
)
4690 inst
.error
= BAD_ARGS
;
4694 if (skip_past_comma (& str
) == FAIL
4695 || cp_reg_required_here (& str
, 0) == FAIL
)
4698 inst
.error
= BAD_ARGS
;
4702 if (skip_past_comma (& str
) == SUCCESS
)
4704 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
4707 inst
.error
= BAD_ARGS
;
4715 /* ARM V5 (argument parse)
4716 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4717 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4718 Instruction is not conditional, and has 0xf in the condition field.
4719 Otherwise, it's the same as MCR/MRC. */
4725 skip_whitespace (str
);
4727 if (co_proc_number (& str
) == FAIL
)
4730 inst
.error
= BAD_ARGS
;
4734 if (skip_past_comma (& str
) == FAIL
4735 || cp_opc_expr (& str
, 21, 3) == FAIL
)
4738 inst
.error
= BAD_ARGS
;
4742 if (skip_past_comma (& str
) == FAIL
4743 || reg_required_here (& str
, 12) == FAIL
)
4746 inst
.error
= BAD_ARGS
;
4750 if (skip_past_comma (& str
) == FAIL
4751 || cp_reg_required_here (& str
, 16) == FAIL
)
4754 inst
.error
= BAD_ARGS
;
4758 if (skip_past_comma (& str
) == FAIL
4759 || cp_reg_required_here (& str
, 0) == FAIL
)
4762 inst
.error
= BAD_ARGS
;
4766 if (skip_past_comma (& str
) == SUCCESS
)
4768 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
4771 inst
.error
= BAD_ARGS
;
4779 /* ARM v5TEJ. Jump to Jazelle code. */
4786 skip_whitespace (str
);
4788 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
4790 inst
.error
= BAD_ARGS
;
4794 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
4796 as_tsktsk (_("use of r15 in bxj is not really useful"));
4801 /* ARM V6 umaal (argument parse). */
4808 int rdlo
, rdhi
, rm
, rs
;
4810 skip_whitespace (str
);
4811 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
4812 || skip_past_comma (& str
) == FAIL
4813 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
4814 || skip_past_comma (& str
) == FAIL
4815 || (rm
= reg_required_here (& str
, 0)) == FAIL
4816 || skip_past_comma (& str
) == FAIL
4817 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
4819 inst
.error
= BAD_ARGS
;
4823 if (rdlo
== REG_PC
|| rdhi
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
4825 inst
.error
= BAD_PC
;
4832 /* ARM V6 strex (argument parse). */
4840 /* Parse Rd, Rm,. */
4841 skip_whitespace (str
);
4842 if ((rd
= reg_required_here (& str
, 12)) == FAIL
4843 || skip_past_comma (& str
) == FAIL
4844 || (rm
= reg_required_here (& str
, 0)) == FAIL
4845 || skip_past_comma (& str
) == FAIL
)
4847 inst
.error
= BAD_ARGS
;
4850 if (rd
== REG_PC
|| rm
== REG_PC
)
4852 inst
.error
= BAD_PC
;
4857 inst
.error
= _("Rd equal to Rm or Rn yields unpredictable results");
4861 /* Skip past '['. */
4862 if ((strlen (str
) >= 1)
4863 && strncmp (str
, "[", 1) == 0)
4865 skip_whitespace (str
);
4868 if ((rn
= reg_required_here (& str
, 16)) == FAIL
)
4870 inst
.error
= BAD_ARGS
;
4873 else if (rn
== REG_PC
)
4875 inst
.error
= BAD_PC
;
4880 inst
.error
= _("Rd equal to Rm or Rn yields unpredictable results");
4883 skip_whitespace (str
);
4885 /* Skip past ']'. */
4886 if ((strlen (str
) >= 1)
4887 && strncmp (str
, "]", 1) == 0)
4893 /* ARM V6 ssat (argument parse). */
4899 do_sat (&str
, /*bias=*/-1);
4903 /* ARM V6 usat (argument parse). */
4909 do_sat (&str
, /*bias=*/0);
4921 skip_whitespace (*str
);
4923 /* Parse <Rd>, field. */
4924 if ((rd
= reg_required_here (str
, 12)) == FAIL
4925 || skip_past_comma (str
) == FAIL
)
4927 inst
.error
= BAD_ARGS
;
4932 inst
.error
= BAD_PC
;
4936 /* Parse #<immed>, field. */
4937 if (is_immediate_prefix (**str
))
4941 inst
.error
= _("immediate expression expected");
4944 if (my_get_expression (&expr
, str
))
4946 inst
.error
= _("bad expression");
4949 if (expr
.X_op
!= O_constant
)
4951 inst
.error
= _("constant expression expected");
4954 if (expr
.X_add_number
+ bias
< 0
4955 || expr
.X_add_number
+ bias
> 31)
4957 inst
.error
= _("immediate value out of range");
4960 inst
.instruction
|= (expr
.X_add_number
+ bias
) << 16;
4961 if (skip_past_comma (str
) == FAIL
)
4963 inst
.error
= BAD_ARGS
;
4967 /* Parse <Rm> field. */
4968 if ((rm
= reg_required_here (str
, 0)) == FAIL
)
4970 inst
.error
= BAD_ARGS
;
4975 inst
.error
= BAD_PC
;
4979 if (skip_past_comma (str
) == SUCCESS
)
4980 decode_shift (str
, SHIFT_LSL_OR_ASR_IMMEDIATE
);
4983 /* ARM V6 ssat16 (argument parse). */
4989 do_sat16 (&str
, /*bias=*/-1);
4997 do_sat16 (&str
, /*bias=*/0);
5002 do_sat16 (str
, bias
)
5009 skip_whitespace (*str
);
5011 /* Parse the <Rd> field. */
5012 if ((rd
= reg_required_here (str
, 12)) == FAIL
5013 || skip_past_comma (str
) == FAIL
)
5015 inst
.error
= BAD_ARGS
;
5020 inst
.error
= BAD_PC
;
5024 /* Parse #<immed>, field. */
5025 if (is_immediate_prefix (**str
))
5029 inst
.error
= _("immediate expression expected");
5032 if (my_get_expression (&expr
, str
))
5034 inst
.error
= _("bad expression");
5037 if (expr
.X_op
!= O_constant
)
5039 inst
.error
= _("constant expression expected");
5042 if (expr
.X_add_number
+ bias
< 0
5043 || expr
.X_add_number
+ bias
> 15)
5045 inst
.error
= _("immediate value out of range");
5048 inst
.instruction
|= (expr
.X_add_number
+ bias
) << 16;
5049 if (skip_past_comma (str
) == FAIL
)
5051 inst
.error
= BAD_ARGS
;
5055 /* Parse <Rm> field. */
5056 if ((rm
= reg_required_here (str
, 0)) == FAIL
)
5058 inst
.error
= BAD_ARGS
;
5063 inst
.error
= BAD_PC
;
5068 /* ARM V6 srs (argument parse). */
5075 skip_whitespace (str
);
5076 exclam
= strchr (str
, '!');
5084 inst
.instruction
|= WRITE_BACK
;
5090 /* ARM V6 SMMUL (argument parse). */
5098 skip_whitespace (str
);
5099 if ((rd
= reg_required_here (&str
, 16)) == FAIL
5100 || skip_past_comma (&str
) == FAIL
5101 || (rm
= reg_required_here (&str
, 0)) == FAIL
5102 || skip_past_comma (&str
) == FAIL
5103 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
5105 inst
.error
= BAD_ARGS
;
5113 inst
.error
= BAD_PC
;
5121 /* ARM V6 SMLALD (argument parse). */
5127 int rdlo
, rdhi
, rm
, rs
;
5128 skip_whitespace (str
);
5129 if ((rdlo
= reg_required_here (&str
, 12)) == FAIL
5130 || skip_past_comma (&str
) == FAIL
5131 || (rdhi
= reg_required_here (&str
, 16)) == FAIL
5132 || skip_past_comma (&str
) == FAIL
5133 || (rm
= reg_required_here (&str
, 0)) == FAIL
5134 || skip_past_comma (&str
) == FAIL
5135 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
5137 inst
.error
= BAD_ARGS
;
5146 inst
.error
= BAD_PC
;
5153 /* ARM V6 SMLAD (argument parse). Signed multiply accumulate dual.
5154 smlad{x}{<cond>} Rd, Rm, Rs, Rn */
5162 skip_whitespace (str
);
5163 if ((rd
= reg_required_here (&str
, 16)) == FAIL
5164 || skip_past_comma (&str
) == FAIL
5165 || (rm
= reg_required_here (&str
, 0)) == FAIL
5166 || skip_past_comma (&str
) == FAIL
5167 || (rs
= reg_required_here (&str
, 8)) == FAIL
5168 || skip_past_comma (&str
) == FAIL
5169 || (rn
= reg_required_here (&str
, 12)) == FAIL
)
5171 inst
.error
= BAD_ARGS
;
5180 inst
.error
= BAD_PC
;
5187 /* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
5188 preserving the other bits.
5190 setend <endian_specifier>, where <endian_specifier> is either
5197 if (do_endian_specifier (str
))
5198 inst
.instruction
|= 0x200;
5201 /* Returns true if the endian-specifier indicates big-endianness. */
5204 do_endian_specifier (str
)
5209 skip_whitespace (str
);
5210 if (strlen (str
) < 2)
5211 inst
.error
= _("missing endian specifier");
5212 else if (strncasecmp (str
, "BE", 2) == 0)
5217 else if (strncasecmp (str
, "LE", 2) == 0)
5220 inst
.error
= _("valid endian specifiers are be or le");
5229 SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
5230 Condition defaults to COND_ALWAYS.
5231 Error if any register uses R15. */
5239 int rotation_clear_mask
= 0xfffff3ff;
5240 int rotation_eight_mask
= 0x00000400;
5241 int rotation_sixteen_mask
= 0x00000800;
5242 int rotation_twenty_four_mask
= 0x00000c00;
5244 skip_whitespace (str
);
5245 if ((rd
= reg_required_here (&str
, 12)) == FAIL
5246 || skip_past_comma (&str
) == FAIL
5247 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
5249 inst
.error
= BAD_ARGS
;
5253 else if (rd
== REG_PC
|| rm
== REG_PC
)
5255 inst
.error
= BAD_PC
;
5259 /* Zero out the rotation field. */
5260 inst
.instruction
&= rotation_clear_mask
;
5262 /* Check for lack of optional rotation field. */
5263 if (skip_past_comma (&str
) == FAIL
)
5269 /* Move past 'ROR'. */
5270 skip_whitespace (str
);
5271 if (strncasecmp (str
, "ROR", 3) == 0)
5275 inst
.error
= _("missing rotation field after comma");
5279 /* Get the immediate constant. */
5280 skip_whitespace (str
);
5281 if (is_immediate_prefix (* str
))
5285 inst
.error
= _("immediate expression expected");
5289 if (my_get_expression (&expr
, &str
))
5291 inst
.error
= _("bad expression");
5295 if (expr
.X_op
!= O_constant
)
5297 inst
.error
= _("constant expression expected");
5301 switch (expr
.X_add_number
)
5304 /* Rotation field has already been zeroed. */
5307 inst
.instruction
|= rotation_eight_mask
;
5311 inst
.instruction
|= rotation_sixteen_mask
;
5315 inst
.instruction
|= rotation_twenty_four_mask
;
5319 inst
.error
= _("rotation can be 8, 16, 24 or 0 when field is ommited");
5327 /* ARM V6 SXTAH extracts a 16-bit value from a register, sign
5328 extends it to 32-bits, and adds the result to a value in another
5329 register. You can specify a rotation by 0, 8, 16, or 24 bits
5330 before extracting the 16-bit value.
5331 SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
5332 Condition defaults to COND_ALWAYS.
5333 Error if any register uses R15. */
5341 int rotation_clear_mask
= 0xfffff3ff;
5342 int rotation_eight_mask
= 0x00000400;
5343 int rotation_sixteen_mask
= 0x00000800;
5344 int rotation_twenty_four_mask
= 0x00000c00;
5346 skip_whitespace (str
);
5347 if ((rd
= reg_required_here (&str
, 12)) == FAIL
5348 || skip_past_comma (&str
) == FAIL
5349 || (rn
= reg_required_here (&str
, 16)) == FAIL
5350 || skip_past_comma (&str
) == FAIL
5351 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
5353 inst
.error
= BAD_ARGS
;
5357 else if (rd
== REG_PC
|| rn
== REG_PC
|| rm
== REG_PC
)
5359 inst
.error
= BAD_PC
;
5363 /* Zero out the rotation field. */
5364 inst
.instruction
&= rotation_clear_mask
;
5366 /* Check for lack of optional rotation field. */
5367 if (skip_past_comma (&str
) == FAIL
)
5373 /* Move past 'ROR'. */
5374 skip_whitespace (str
);
5375 if (strncasecmp (str
, "ROR", 3) == 0)
5379 inst
.error
= _("missing rotation field after comma");
5383 /* Get the immediate constant. */
5384 skip_whitespace (str
);
5385 if (is_immediate_prefix (* str
))
5389 inst
.error
= _("immediate expression expected");
5393 if (my_get_expression (&expr
, &str
))
5395 inst
.error
= _("bad expression");
5399 if (expr
.X_op
!= O_constant
)
5401 inst
.error
= _("constant expression expected");
5405 switch (expr
.X_add_number
)
5408 /* Rotation field has already been zeroed. */
5412 inst
.instruction
|= rotation_eight_mask
;
5416 inst
.instruction
|= rotation_sixteen_mask
;
5420 inst
.instruction
|= rotation_twenty_four_mask
;
5424 inst
.error
= _("rotation can be 8, 16, 24 or 0 when field is ommited");
5433 /* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
5434 word at the specified address and the following word
5436 Unconditionally executed.
5446 skip_whitespace (str
);
5448 if ((rn
= reg_required_here (&str
, 16)) == FAIL
)
5453 inst
.error
= BAD_PC
;
5457 skip_whitespace (str
);
5461 inst
.instruction
|= WRITE_BACK
;
5467 /* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
5468 register (argument parse).
5470 Condition defaults to COND_ALWAYS.
5471 Error if Rd or Rm are R15. */
5479 skip_whitespace (str
);
5481 if ((rd
= reg_required_here (&str
, 12)) == FAIL
5482 || skip_past_comma (&str
) == FAIL
5483 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
5484 inst
.error
= BAD_ARGS
;
5486 else if (rd
== REG_PC
|| rm
== REG_PC
)
5487 inst
.error
= BAD_PC
;
5493 /* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
5494 QADD16{<cond>} <Rd>, <Rn>, <Rm>
5495 Condition defaults to COND_ALWAYS.
5496 Error if Rd, Rn or Rm are R15. */
5504 skip_whitespace (str
);
5506 if ((rd
= reg_required_here (&str
, 12)) == FAIL
5507 || skip_past_comma (&str
) == FAIL
5508 || (rn
= reg_required_here (&str
, 16)) == FAIL
5509 || skip_past_comma (&str
) == FAIL
5510 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
5511 inst
.error
= BAD_ARGS
;
5513 else if (rd
== REG_PC
|| rm
== REG_PC
|| rn
== REG_PC
)
5514 inst
.error
= BAD_PC
;
5520 /* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
5521 PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
5522 Condition defaults to COND_ALWAYS.
5523 Error if Rd, Rn or Rm are R15. */
5529 do_pkh_core (str
, SHIFT_LSL_IMMEDIATE
);
5532 /* ARM V6 PKHTB (Argument Parse). */
5538 do_pkh_core (str
, SHIFT_ASR_IMMEDIATE
);
5542 do_pkh_core (str
, shift
)
5548 skip_whitespace (str
);
5549 if (((rd
= reg_required_here (&str
, 12)) == FAIL
)
5550 || (skip_past_comma (&str
) == FAIL
)
5551 || ((rn
= reg_required_here (&str
, 16)) == FAIL
)
5552 || (skip_past_comma (&str
) == FAIL
)
5553 || ((rm
= reg_required_here (&str
, 0)) == FAIL
))
5555 inst
.error
= BAD_ARGS
;
5559 else if (rd
== REG_PC
|| rn
== REG_PC
|| rm
== REG_PC
)
5561 inst
.error
= BAD_PC
;
5565 /* Check for optional shift immediate constant. */
5566 if (skip_past_comma (&str
) == FAIL
)
5568 if (shift
== SHIFT_ASR_IMMEDIATE
)
5570 /* If the shift specifier is ommited, turn the instruction
5571 into pkhbt rd, rm, rn. First, switch the instruction
5572 code, and clear the rn and rm fields. */
5573 inst
.instruction
&= 0xfff0f010;
5574 /* Now, re-encode the registers. */
5575 inst
.instruction
|= (rm
<< 16) | rn
;
5580 decode_shift (&str
, shift
);
5583 /* ARM V6 Load Register Exclusive instruction (argument parse).
5584 LDREX{<cond>} <Rd, [<Rn>]
5585 Condition defaults to COND_ALWAYS.
5586 Error if Rd or Rn are R15.
5587 See ARMARMv6 A4.1.27: LDREX. */
5596 skip_whitespace (str
);
5599 if (((rd
= reg_required_here (&str
, 12)) == FAIL
)
5600 || (skip_past_comma (&str
) == FAIL
))
5602 inst
.error
= BAD_ARGS
;
5605 else if (rd
== REG_PC
)
5607 inst
.error
= BAD_PC
;
5610 skip_whitespace (str
);
5612 /* Skip past '['. */
5613 if ((strlen (str
) >= 1)
5614 &&strncmp (str
, "[", 1) == 0)
5616 skip_whitespace (str
);
5619 if ((rn
= reg_required_here (&str
, 16)) == FAIL
)
5621 inst
.error
= BAD_ARGS
;
5624 else if (rn
== REG_PC
)
5626 inst
.error
= BAD_PC
;
5629 skip_whitespace (str
);
5631 /* Skip past ']'. */
5632 if ((strlen (str
) >= 1)
5633 && strncmp (str
, "]", 1) == 0)
5639 /* ARM V6 change processor state instruction (argument parse)
5640 CPS, CPSIE, CSPID . */
5654 do_cps_flags (&str
, /*thumb_p=*/0);
5656 if (skip_past_comma (&str
) == SUCCESS
)
5658 skip_whitespace (str
);
5670 skip_whitespace (*str
);
5672 if (! is_immediate_prefix (**str
))
5674 inst
.error
= _("immediate expression expected");
5678 (*str
)++; /* Strip off the immediate signifier. */
5679 if (my_get_expression (&expr
, str
))
5681 inst
.error
= _("bad expression");
5685 if (expr
.X_op
!= O_constant
)
5687 inst
.error
= _("constant expression expected");
5691 /* The mode is a 5 bit field. Valid values are 0-31. */
5692 if (((unsigned) expr
.X_add_number
) > 31
5693 || (inst
.reloc
.exp
.X_add_number
) < 0)
5695 inst
.error
= _("invalid constant");
5699 inst
.instruction
|= expr
.X_add_number
;
5703 do_cps_flags (str
, thumb_p
)
5709 unsigned long arm_value
;
5710 unsigned long thumb_value
;
5712 static struct cps_flag flag_table
[] = {
5720 skip_whitespace (*str
);
5722 /* Get the a, f and i flags. */
5723 while (**str
&& **str
!= ',')
5726 struct cps_flag
*q
= flag_table
+ sizeof (flag_table
)/sizeof (*p
);
5727 for (p
= flag_table
; p
< q
; ++p
)
5728 if (strncasecmp (*str
, &p
->character
, 1) == 0)
5730 inst
.instruction
|= (thumb_p
? p
->thumb_value
: p
->arm_value
);
5736 inst
.error
= _("unrecognized flag");
5742 inst
.error
= _("no 'a', 'i', or 'f' flags for 'cps'");
5745 /* THUMB V5 breakpoint instruction (argument parse)
5753 unsigned long number
;
5755 skip_whitespace (str
);
5757 /* Allow optional leading '#'. */
5758 if (is_immediate_prefix (*str
))
5761 memset (& expr
, '\0', sizeof (expr
));
5762 if (my_get_expression (& expr
, & str
)
5763 || (expr
.X_op
!= O_constant
5764 /* As a convenience we allow 'bkpt' without an operand. */
5765 && expr
.X_op
!= O_absent
))
5767 inst
.error
= _("bad expression");
5771 number
= expr
.X_add_number
;
5773 /* Check it fits an 8 bit unsigned. */
5774 if (number
!= (number
& 0xff))
5776 inst
.error
= _("immediate value out of range");
5780 inst
.instruction
|= number
;
5785 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
5786 Expects inst.instruction is set for BLX(1).
5787 Note: this is cloned from do_branch, and the reloc changed to be a
5788 new one that can cope with setting one extra bit (the H bit). */
5794 if (my_get_expression (& inst
.reloc
.exp
, & str
))
5801 /* ScottB: February 5, 1998 */
5802 /* Check to see of PLT32 reloc required for the instruction. */
5804 /* arm_parse_reloc() works on input_line_pointer.
5805 We actually want to parse the operands to the branch instruction
5806 passed in 'str'. Save the input pointer and restore it later. */
5807 save_in
= input_line_pointer
;
5808 input_line_pointer
= str
;
5810 if (inst
.reloc
.exp
.X_op
== O_symbol
5812 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
5814 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
5815 inst
.reloc
.pc_rel
= 0;
5816 /* Modify str to point to after parsed operands, otherwise
5817 end_of_line() will complain about the (PLT) left in str. */
5818 str
= input_line_pointer
;
5822 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
5823 inst
.reloc
.pc_rel
= 1;
5826 input_line_pointer
= save_in
;
5829 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
5830 inst
.reloc
.pc_rel
= 1;
5831 #endif /* OBJ_ELF */
5836 /* ARM V5 branch-link-exchange instruction (argument parse)
5837 BLX <target_addr> ie BLX(1)
5838 BLX{<condition>} <Rm> ie BLX(2)
5839 Unfortunately, there are two different opcodes for this mnemonic.
5840 So, the insns[].value is not used, and the code here zaps values
5841 into inst.instruction.
5842 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
5851 skip_whitespace (mystr
);
5852 rm
= reg_required_here (& mystr
, 0);
5854 /* The above may set inst.error. Ignore his opinion. */
5859 /* Arg is a register.
5860 Use the condition code our caller put in inst.instruction.
5861 Pass ourselves off as a BX with a funny opcode. */
5862 inst
.instruction
|= 0x012fff30;
5867 /* This must be is BLX <target address>, no condition allowed. */
5868 if (inst
.instruction
!= COND_ALWAYS
)
5870 inst
.error
= BAD_COND
;
5874 inst
.instruction
= 0xfafffffe;
5876 /* Process like a B/BL, but with a different reloc.
5877 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
5882 /* ARM V5 Thumb BLX (argument parse)
5883 BLX <target_addr> which is BLX(1)
5884 BLX <Rm> which is BLX(2)
5885 Unfortunately, there are two different opcodes for this mnemonic.
5886 So, the tinsns[].value is not used, and the code here zaps values
5887 into inst.instruction. */
5896 skip_whitespace (mystr
);
5897 inst
.instruction
= 0x4780;
5899 /* Note that this call is to the ARM register recognizer. BLX(2)
5900 uses the ARM register space, not the Thumb one, so a call to
5901 thumb_reg() would be wrong. */
5902 rm
= reg_required_here (& mystr
, 3);
5907 /* It's BLX(2). The .instruction was zapped with rm & is final. */
5912 /* No ARM register. This must be BLX(1). Change the .instruction. */
5913 inst
.instruction
= 0xf7ffeffe;
5916 if (my_get_expression (& inst
.reloc
.exp
, & mystr
))
5919 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BLX
;
5920 inst
.reloc
.pc_rel
= 1;
5923 end_of_line (mystr
);
5926 /* ARM V5 breakpoint instruction (argument parse)
5927 BKPT <16 bit unsigned immediate>
5928 Instruction is not conditional.
5929 The bit pattern given in insns[] has the COND_ALWAYS condition,
5930 and it is an error if the caller tried to override that. */
5937 unsigned long number
;
5939 skip_whitespace (str
);
5941 /* Allow optional leading '#'. */
5942 if (is_immediate_prefix (* str
))
5945 memset (& expr
, '\0', sizeof (expr
));
5947 if (my_get_expression (& expr
, & str
)
5948 || (expr
.X_op
!= O_constant
5949 /* As a convenience we allow 'bkpt' without an operand. */
5950 && expr
.X_op
!= O_absent
))
5952 inst
.error
= _("bad expression");
5956 number
= expr
.X_add_number
;
5958 /* Check it fits a 16 bit unsigned. */
5959 if (number
!= (number
& 0xffff))
5961 inst
.error
= _("immediate value out of range");
5965 /* Top 12 of 16 bits to bits 19:8. */
5966 inst
.instruction
|= (number
& 0xfff0) << 4;
5968 /* Bottom 4 of 16 bits to bits 3:0. */
5969 inst
.instruction
|= number
& 0xf;
5974 /* THUMB CPS instruction (argument parse). */
5980 do_cps_flags (&str
, /*thumb_p=*/1);
5984 /* THUMB CPY instruction (argument parse). */
5990 thumb_mov_compare (str
, THUMB_CPY
);
5993 /* THUMB SETEND instruction (argument parse). */
5999 if (do_endian_specifier (str
))
6000 inst
.instruction
|= 0x8;
6003 static unsigned long check_iwmmxt_insn
PARAMS ((char *, enum iwmmxt_insn_type
, int));
6005 /* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
6007 static unsigned long
6008 check_iwmmxt_insn (str
, insn_type
, immediate_size
)
6010 enum iwmmxt_insn_type insn_type
;
6014 const char * inst_error
;
6016 unsigned long number
;
6018 inst_error
= inst
.error
;
6020 inst
.error
= BAD_ARGS
;
6021 skip_whitespace (str
);
6026 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
6031 if ((wreg_required_here (&str
, 0, IWMMXT_REG_WR
)) == FAIL
)
6036 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
6037 || skip_past_comma (&str
) == FAIL
6038 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
))
6043 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
6044 || skip_past_comma (&str
) == FAIL
6045 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6046 || skip_past_comma (&str
) == FAIL
6047 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
))
6052 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
6053 || skip_past_comma (&str
) == FAIL
6054 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6055 || skip_past_comma (&str
) == FAIL
6056 || wreg_required_here (&str
, 0, IWMMXT_REG_WCG
) == FAIL
))
6061 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6062 || skip_past_comma (&str
) == FAIL
6063 || reg_required_here (&str
, 12) == FAIL
))
6068 if ((reg_required_here (&str
, 12) == FAIL
6069 || skip_past_comma (&str
) == FAIL
6070 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
))
6075 if ((wreg_required_here (&str
, 5, IWMMXT_REG_WR
) == FAIL
6076 || skip_past_comma (&str
) == FAIL
6077 || reg_required_here (&str
, 0) == FAIL
6078 || skip_past_comma (&str
) == FAIL
6079 || reg_required_here (&str
, 12) == FAIL
))
6084 if ((wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
6085 || skip_past_comma (&str
) == FAIL
6086 || reg_required_here (&str
, 12) == FAIL
6087 || skip_past_comma (&str
) == FAIL
6088 || reg_required_here (&str
, 16) == FAIL
))
6093 if ((reg_required_here (&str
, 12) == FAIL
6094 || skip_past_comma (&str
) == FAIL
6095 || reg_required_here (&str
, 16) == FAIL
6096 || skip_past_comma (&str
) == FAIL
6097 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
))
6102 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WC
) == FAIL
6103 || skip_past_comma (&str
) == FAIL
6104 || reg_required_here (&str
, 12) == FAIL
))
6109 if ((reg_required_here (&str
, 12) == FAIL
6110 || skip_past_comma (&str
) == FAIL
6111 || wreg_required_here (&str
, 16, IWMMXT_REG_WC
) == FAIL
))
6116 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6117 || skip_past_comma (&str
) == FAIL
6118 || reg_required_here (&str
, 12) == FAIL
6119 || skip_past_comma (&str
) == FAIL
))
6124 if ((reg_required_here (&str
, 12) == FAIL
6125 || skip_past_comma (&str
) == FAIL
))
6130 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
6131 || skip_past_comma (&str
) == FAIL
6132 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6133 || skip_past_comma (&str
) == FAIL
6134 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
6135 || skip_past_comma (&str
) == FAIL
))
6140 if ((reg_required_here (&str
, 12) == FAIL
6141 || skip_past_comma (&str
) == FAIL
6142 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6143 || skip_past_comma (&str
) == FAIL
))
6148 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
6149 || skip_past_comma (&str
) == FAIL
6150 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6151 || skip_past_comma (&str
) == FAIL
))
6156 if (immediate_size
== 0)
6159 inst
.error
= inst_error
;
6164 skip_whitespace (str
);
6166 /* Allow optional leading '#'. */
6167 if (is_immediate_prefix (* str
))
6170 memset (& expr
, '\0', sizeof (expr
));
6172 if (my_get_expression (& expr
, & str
) || (expr
.X_op
!= O_constant
))
6174 inst
.error
= _("bad or missing expression");
6178 number
= expr
.X_add_number
;
6180 if (number
!= (number
& immediate_size
))
6182 inst
.error
= _("immediate value out of range");
6186 inst
.error
= inst_error
;
6192 do_iwmmxt_byte_addr (str
)
6195 int op
= (inst
.instruction
& 0x300) >> 8;
6198 inst
.instruction
&= ~0x300;
6199 inst
.instruction
|= (op
& 1) << 22 | (op
& 2) << 7;
6201 skip_whitespace (str
);
6203 if ((reg
= wreg_required_here (&str
, 12, IWMMXT_REG_WR_OR_WC
)) == FAIL
6204 || skip_past_comma (& str
) == FAIL
6205 || cp_byte_address_required_here (&str
) == FAIL
)
6208 inst
.error
= BAD_ARGS
;
6213 if (wc_register (reg
))
6215 as_bad (_("non-word size not supported with control register"));
6216 inst
.instruction
|= 0xf0000100;
6217 inst
.instruction
&= ~0x00400000;
6222 do_iwmmxt_tandc (str
)
6227 reg
= check_iwmmxt_insn (str
, check_rd
, 0);
6229 if (reg
!= REG_PC
&& !inst
.error
)
6230 inst
.error
= _("only r15 allowed here");
6234 do_iwmmxt_tbcst (str
)
6237 check_iwmmxt_insn (str
, check_tbcst
, 0);
6241 do_iwmmxt_textrc (str
)
6244 unsigned long number
;
6246 if ((number
= check_iwmmxt_insn (str
, check_textrc
, 7)) == (unsigned long) FAIL
)
6249 inst
.instruction
|= number
& 0x7;
6253 do_iwmmxt_textrm (str
)
6256 unsigned long number
;
6258 if ((number
= check_iwmmxt_insn (str
, check_textrm
, 7)) == (unsigned long) FAIL
)
6261 inst
.instruction
|= number
& 0x7;
6265 do_iwmmxt_tinsr (str
)
6268 unsigned long number
;
6270 if ((number
= check_iwmmxt_insn (str
, check_tinsr
, 7)) == (unsigned long) FAIL
)
6273 inst
.instruction
|= number
& 0x7;
6277 do_iwmmxt_tmcr (str
)
6280 check_iwmmxt_insn (str
, check_tmcr
, 0);
6284 do_iwmmxt_tmcrr (str
)
6287 check_iwmmxt_insn (str
, check_tmcrr
, 0);
6291 do_iwmmxt_tmia (str
)
6294 check_iwmmxt_insn (str
, check_tmia
, 0);
6298 do_iwmmxt_tmovmsk (str
)
6301 check_iwmmxt_insn (str
, check_tmovmsk
, 0);
6305 do_iwmmxt_tmrc (str
)
6308 check_iwmmxt_insn (str
, check_tmrc
, 0);
6312 do_iwmmxt_tmrrc (str
)
6315 check_iwmmxt_insn (str
, check_tmrrc
, 0);
6319 do_iwmmxt_torc (str
)
6322 check_iwmmxt_insn (str
, check_rd
, 0);
6326 do_iwmmxt_waligni (str
)
6329 unsigned long number
;
6331 if ((number
= check_iwmmxt_insn (str
, check_waligni
, 7)) == (unsigned long) FAIL
)
6334 inst
.instruction
|= ((number
& 0x7) << 20);
6338 do_iwmmxt_wmov (str
)
6341 if (check_iwmmxt_insn (str
, check_wrwr
, 0) == (unsigned long) FAIL
)
6344 inst
.instruction
|= ((inst
.instruction
>> 16) & 0xf);
6348 do_iwmmxt_word_addr (str
)
6351 int op
= (inst
.instruction
& 0x300) >> 8;
6354 inst
.instruction
&= ~0x300;
6355 inst
.instruction
|= (op
& 1) << 22 | (op
& 2) << 7;
6357 skip_whitespace (str
);
6359 if ((reg
= wreg_required_here (&str
, 12, IWMMXT_REG_WR_OR_WC
)) == FAIL
6360 || skip_past_comma (& str
) == FAIL
6361 || cp_address_required_here (& str
, CP_WB_OK
) == FAIL
)
6364 inst
.error
= BAD_ARGS
;
6369 if (wc_register (reg
))
6371 if ((inst
.instruction
& COND_MASK
) != COND_ALWAYS
)
6372 as_bad (_("conditional execution not supported with control register"));
6374 as_bad (_("non-word size not supported with control register"));
6375 inst
.instruction
|= 0xf0000100;
6376 inst
.instruction
&= ~0x00400000;
6381 do_iwmmxt_wrwr (str
)
6384 check_iwmmxt_insn (str
, check_wrwr
, 0);
6388 do_iwmmxt_wrwrwcg (str
)
6391 check_iwmmxt_insn (str
, check_wrwrwcg
, 0);
6395 do_iwmmxt_wrwrwr (str
)
6398 check_iwmmxt_insn (str
, check_wrwrwr
, 0);
6402 do_iwmmxt_wshufh (str
)
6405 unsigned long number
;
6407 if ((number
= check_iwmmxt_insn (str
, check_wshufh
, 0xff)) == (unsigned long) FAIL
)
6410 inst
.instruction
|= ((number
& 0xf0) << 16) | (number
& 0xf);
6414 do_iwmmxt_wzero (str
)
6417 if (check_iwmmxt_insn (str
, check_wr
, 0) == (unsigned long) FAIL
)
6420 inst
.instruction
|= ((inst
.instruction
& 0xf) << 12) | ((inst
.instruction
& 0xf) << 16);
6423 /* Xscale multiply-accumulate (argument parse)
6426 MIAxycc acc0,Rm,Rs. */
6435 if (accum0_required_here (& str
) == FAIL
)
6436 inst
.error
= ERR_NO_ACCUM
;
6438 else if (skip_past_comma (& str
) == FAIL
6439 || (rm
= reg_required_here (& str
, 0)) == FAIL
)
6440 inst
.error
= BAD_ARGS
;
6442 else if (skip_past_comma (& str
) == FAIL
6443 || (rs
= reg_required_here (& str
, 12)) == FAIL
)
6444 inst
.error
= BAD_ARGS
;
6446 /* inst.instruction has now been zapped with both rm and rs. */
6447 else if (rm
== REG_PC
|| rs
== REG_PC
)
6448 inst
.error
= BAD_PC
; /* Undefined result if rm or rs is R15. */
6454 /* Xscale move-accumulator-register (argument parse)
6456 MARcc acc0,RdLo,RdHi. */
6464 if (accum0_required_here (& str
) == FAIL
)
6465 inst
.error
= ERR_NO_ACCUM
;
6467 else if (skip_past_comma (& str
) == FAIL
6468 || (rdlo
= reg_required_here (& str
, 12)) == FAIL
)
6469 inst
.error
= BAD_ARGS
;
6471 else if (skip_past_comma (& str
) == FAIL
6472 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
6473 inst
.error
= BAD_ARGS
;
6475 /* inst.instruction has now been zapped with both rdlo and rdhi. */
6476 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
6477 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
6483 /* Xscale move-register-accumulator (argument parse)
6485 MRAcc RdLo,RdHi,acc0. */
6494 skip_whitespace (str
);
6496 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
)
6497 inst
.error
= BAD_ARGS
;
6499 else if (skip_past_comma (& str
) == FAIL
6500 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
6501 inst
.error
= BAD_ARGS
;
6503 else if (skip_past_comma (& str
) == FAIL
6504 || accum0_required_here (& str
) == FAIL
)
6505 inst
.error
= ERR_NO_ACCUM
;
6507 /* inst.instruction has now been zapped with both rdlo and rdhi. */
6508 else if (rdlo
== rdhi
)
6509 inst
.error
= BAD_ARGS
; /* Undefined result if 2 writes to same reg. */
6511 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
6512 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
6517 /* ARMv5TE: Preload-Cache
6521 Syntactically, like LDR with B=1, W=0, L=1. */
6529 skip_whitespace (str
);
6533 inst
.error
= _("'[' expected after PLD mnemonic");
6538 skip_whitespace (str
);
6540 if ((rd
= reg_required_here (& str
, 16)) == FAIL
)
6543 skip_whitespace (str
);
6549 skip_whitespace (str
);
6551 /* Post-indexed addressing is not allowed with PLD. */
6552 if (skip_past_comma (&str
) == SUCCESS
)
6555 = _("post-indexed expression used in preload instruction");
6558 else if (*str
== '!') /* [Rn]! */
6560 inst
.error
= _("writeback used in preload instruction");
6564 inst
.instruction
|= INDEX_UP
| PRE_INDEX
;
6566 else /* [Rn, ...] */
6568 if (skip_past_comma (& str
) == FAIL
)
6570 inst
.error
= _("pre-indexed expression expected");
6574 if (ldst_extend (&str
) == FAIL
)
6577 skip_whitespace (str
);
6581 inst
.error
= _("missing ]");
6586 skip_whitespace (str
);
6588 if (* str
== '!') /* [Rn]! */
6590 inst
.error
= _("writeback used in preload instruction");
6594 inst
.instruction
|= PRE_INDEX
;
6600 /* ARMv5TE load-consecutive (argument parse)
6613 skip_whitespace (str
);
6615 if ((rd
= reg_required_here (& str
, 12)) == FAIL
)
6617 inst
.error
= BAD_ARGS
;
6621 if (skip_past_comma (& str
) == FAIL
6622 || (rn
= ld_mode_required_here (& str
)) == FAIL
)
6625 inst
.error
= BAD_ARGS
;
6629 /* inst.instruction has now been zapped with Rd and the addressing mode. */
6630 if (rd
& 1) /* Unpredictable result if Rd is odd. */
6632 inst
.error
= _("destination register must be even");
6638 inst
.error
= _("r14 not allowed here");
6642 if (((rd
== rn
) || (rd
+ 1 == rn
))
6643 && ((inst
.instruction
& WRITE_BACK
)
6644 || (!(inst
.instruction
& PRE_INDEX
))))
6645 as_warn (_("pre/post-indexing used when modified address register is destination"));
6647 /* For an index-register load, the index register must not overlap the
6648 destination (even if not write-back). */
6649 if ((inst
.instruction
& V4_STR_BIT
) == 0
6650 && (inst
.instruction
& HWOFFSET_IMM
) == 0)
6652 int rm
= inst
.instruction
& 0x0000000f;
6654 if (rm
== rd
|| (rm
== rd
+ 1))
6655 as_warn (_("ldrd destination registers must not overlap index register"));
6661 /* Returns the index into fp_values of a floating point number,
6662 or -1 if not in the table. */
6665 my_get_float_expression (str
)
6668 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
6674 memset (words
, 0, MAX_LITTLENUMS
* sizeof (LITTLENUM_TYPE
));
6676 /* Look for a raw floating point number. */
6677 if ((save_in
= atof_ieee (*str
, 'x', words
)) != NULL
6678 && is_end_of_line
[(unsigned char) *save_in
])
6680 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
6682 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
6684 if (words
[j
] != fp_values
[i
][j
])
6688 if (j
== MAX_LITTLENUMS
)
6696 /* Try and parse a more complex expression, this will probably fail
6697 unless the code uses a floating point prefix (eg "0f"). */
6698 save_in
= input_line_pointer
;
6699 input_line_pointer
= *str
;
6700 if (expression (&exp
) == absolute_section
6701 && exp
.X_op
== O_big
6702 && exp
.X_add_number
< 0)
6704 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
6706 if (gen_to_words (words
, 5, (long) 15) == 0)
6708 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
6710 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
6712 if (words
[j
] != fp_values
[i
][j
])
6716 if (j
== MAX_LITTLENUMS
)
6718 *str
= input_line_pointer
;
6719 input_line_pointer
= save_in
;
6726 *str
= input_line_pointer
;
6727 input_line_pointer
= save_in
;
6731 /* Return TRUE if anything in the expression is a bignum. */
6734 walk_no_bignums (sp
)
6737 if (symbol_get_value_expression (sp
)->X_op
== O_big
)
6740 if (symbol_get_value_expression (sp
)->X_add_symbol
)
6742 return (walk_no_bignums (symbol_get_value_expression (sp
)->X_add_symbol
)
6743 || (symbol_get_value_expression (sp
)->X_op_symbol
6744 && walk_no_bignums (symbol_get_value_expression (sp
)->X_op_symbol
)));
6750 static int in_my_get_expression
= 0;
6753 my_get_expression (ep
, str
)
6760 save_in
= input_line_pointer
;
6761 input_line_pointer
= *str
;
6762 in_my_get_expression
= 1;
6763 seg
= expression (ep
);
6764 in_my_get_expression
= 0;
6766 if (ep
->X_op
== O_illegal
)
6768 /* We found a bad expression in md_operand(). */
6769 *str
= input_line_pointer
;
6770 input_line_pointer
= save_in
;
6775 if (seg
!= absolute_section
6776 && seg
!= text_section
6777 && seg
!= data_section
6778 && seg
!= bss_section
6779 && seg
!= undefined_section
)
6781 inst
.error
= _("bad_segment");
6782 *str
= input_line_pointer
;
6783 input_line_pointer
= save_in
;
6788 /* Get rid of any bignums now, so that we don't generate an error for which
6789 we can't establish a line number later on. Big numbers are never valid
6790 in instructions, which is where this routine is always called. */
6791 if (ep
->X_op
== O_big
6792 || (ep
->X_add_symbol
6793 && (walk_no_bignums (ep
->X_add_symbol
)
6795 && walk_no_bignums (ep
->X_op_symbol
)))))
6797 inst
.error
= _("invalid constant");
6798 *str
= input_line_pointer
;
6799 input_line_pointer
= save_in
;
6803 *str
= input_line_pointer
;
6804 input_line_pointer
= save_in
;
6808 /* We handle all bad expressions here, so that we can report the faulty
6809 instruction in the error message. */
6814 if (in_my_get_expression
)
6816 expr
->X_op
= O_illegal
;
6817 if (inst
.error
== NULL
)
6818 inst
.error
= _("bad expression");
6822 /* KIND indicates what kind of shifts are accepted. */
6825 decode_shift (str
, kind
)
6829 const struct asm_shift_name
* shift
;
6833 skip_whitespace (* str
);
6835 for (p
= * str
; ISALPHA (* p
); p
++)
6840 inst
.error
= _("shift expression expected");
6846 shift
= (const struct asm_shift_name
*) hash_find (arm_shift_hsh
, * str
);
6851 inst
.error
= _("shift expression expected");
6855 assert (shift
->properties
->index
== shift_properties
[shift
->properties
->index
].index
);
6857 if (kind
== SHIFT_LSL_OR_ASR_IMMEDIATE
6858 && shift
->properties
->index
!= SHIFT_LSL
6859 && shift
->properties
->index
!= SHIFT_ASR
)
6861 inst
.error
= _("'LSL' or 'ASR' required");
6864 else if (kind
== SHIFT_LSL_IMMEDIATE
6865 && shift
->properties
->index
!= SHIFT_LSL
)
6867 inst
.error
= _("'LSL' required");
6870 else if (kind
== SHIFT_ASR_IMMEDIATE
6871 && shift
->properties
->index
!= SHIFT_ASR
)
6873 inst
.error
= _("'ASR' required");
6877 if (shift
->properties
->index
== SHIFT_RRX
)
6880 inst
.instruction
|= shift
->properties
->bit_field
;
6884 skip_whitespace (p
);
6886 if (kind
== NO_SHIFT_RESTRICT
&& reg_required_here (& p
, 8) != FAIL
)
6888 inst
.instruction
|= shift
->properties
->bit_field
| SHIFT_BY_REG
;
6892 else if (! is_immediate_prefix (* p
))
6894 inst
.error
= (NO_SHIFT_RESTRICT
6895 ? _("shift requires register or #expression")
6896 : _("shift requires #expression"));
6904 if (my_get_expression (& inst
.reloc
.exp
, & p
))
6907 /* Validate some simple #expressions. */
6908 if (inst
.reloc
.exp
.X_op
== O_constant
)
6910 unsigned num
= inst
.reloc
.exp
.X_add_number
;
6912 /* Reject operations greater than 32. */
6914 /* Reject a shift of 0 unless the mode allows it. */
6915 || (num
== 0 && shift
->properties
->allows_0
== 0)
6916 /* Reject a shift of 32 unless the mode allows it. */
6917 || (num
== 32 && shift
->properties
->allows_32
== 0)
6920 /* As a special case we allow a shift of zero for
6921 modes that do not support it to be recoded as an
6922 logical shift left of zero (ie nothing). We warn
6923 about this though. */
6926 as_warn (_("shift of 0 ignored."));
6927 shift
= & shift_names
[0];
6928 assert (shift
->properties
->index
== SHIFT_LSL
);
6932 inst
.error
= _("invalid immediate shift");
6937 /* Shifts of 32 are encoded as 0, for those shifts that
6942 inst
.instruction
|= (num
<< 7) | shift
->properties
->bit_field
;
6946 inst
.reloc
.type
= BFD_RELOC_ARM_SHIFT_IMM
;
6947 inst
.reloc
.pc_rel
= 0;
6948 inst
.instruction
|= shift
->properties
->bit_field
;
6955 /* Do those data_ops which can take a negative immediate constant
6956 by altering the instruction. A bit of a hack really.
6960 by inverting the second operand, and
6963 by negating the second operand. */
6966 negate_data_op (instruction
, value
)
6967 unsigned long * instruction
;
6968 unsigned long value
;
6971 unsigned long negated
, inverted
;
6973 negated
= validate_immediate (-value
);
6974 inverted
= validate_immediate (~value
);
6976 op
= (*instruction
>> DATA_OP_SHIFT
) & 0xf;
6979 /* First negates. */
6980 case OPCODE_SUB
: /* ADD <-> SUB */
6981 new_inst
= OPCODE_ADD
;
6986 new_inst
= OPCODE_SUB
;
6990 case OPCODE_CMP
: /* CMP <-> CMN */
6991 new_inst
= OPCODE_CMN
;
6996 new_inst
= OPCODE_CMP
;
7000 /* Now Inverted ops. */
7001 case OPCODE_MOV
: /* MOV <-> MVN */
7002 new_inst
= OPCODE_MVN
;
7007 new_inst
= OPCODE_MOV
;
7011 case OPCODE_AND
: /* AND <-> BIC */
7012 new_inst
= OPCODE_BIC
;
7017 new_inst
= OPCODE_AND
;
7021 case OPCODE_ADC
: /* ADC <-> SBC */
7022 new_inst
= OPCODE_SBC
;
7027 new_inst
= OPCODE_ADC
;
7031 /* We cannot do anything. */
7036 if (value
== (unsigned) FAIL
)
7039 *instruction
&= OPCODE_MASK
;
7040 *instruction
|= new_inst
<< DATA_OP_SHIFT
;
7051 skip_whitespace (* str
);
7053 if (reg_required_here (str
, 0) != FAIL
)
7055 if (skip_past_comma (str
) == SUCCESS
)
7056 /* Shift operation on register. */
7057 return decode_shift (str
, NO_SHIFT_RESTRICT
);
7063 /* Immediate expression. */
7064 if (is_immediate_prefix (**str
))
7069 if (my_get_expression (&inst
.reloc
.exp
, str
))
7072 if (inst
.reloc
.exp
.X_add_symbol
)
7074 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
7075 inst
.reloc
.pc_rel
= 0;
7079 if (skip_past_comma (str
) == SUCCESS
)
7081 /* #x, y -- ie explicit rotation by Y. */
7082 if (my_get_expression (&expr
, str
))
7085 if (expr
.X_op
!= O_constant
)
7087 inst
.error
= _("constant expression expected");
7091 /* Rotate must be a multiple of 2. */
7092 if (((unsigned) expr
.X_add_number
) > 30
7093 || (expr
.X_add_number
& 1) != 0
7094 || ((unsigned) inst
.reloc
.exp
.X_add_number
) > 255)
7096 inst
.error
= _("invalid constant");
7099 inst
.instruction
|= INST_IMMEDIATE
;
7100 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
7101 inst
.instruction
|= expr
.X_add_number
<< 7;
7105 /* Implicit rotation, select a suitable one. */
7106 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
7110 /* Can't be done. Perhaps the code reads something like
7111 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
7112 if ((value
= negate_data_op (&inst
.instruction
,
7113 inst
.reloc
.exp
.X_add_number
))
7116 inst
.error
= _("invalid constant");
7121 inst
.instruction
|= value
;
7124 inst
.instruction
|= INST_IMMEDIATE
;
7129 inst
.error
= _("register or shift expression expected");
7138 skip_whitespace (* str
);
7140 if (fp_reg_required_here (str
, 0) != FAIL
)
7144 /* Immediate expression. */
7145 if (*((*str
)++) == '#')
7151 skip_whitespace (* str
);
7153 /* First try and match exact strings, this is to guarantee
7154 that some formats will work even for cross assembly. */
7156 for (i
= 0; fp_const
[i
]; i
++)
7158 if (strncmp (*str
, fp_const
[i
], strlen (fp_const
[i
])) == 0)
7162 *str
+= strlen (fp_const
[i
]);
7163 if (is_end_of_line
[(unsigned char) **str
])
7165 inst
.instruction
|= i
+ 8;
7172 /* Just because we didn't get a match doesn't mean that the
7173 constant isn't valid, just that it is in a format that we
7174 don't automatically recognize. Try parsing it with
7175 the standard expression routines. */
7176 if ((i
= my_get_float_expression (str
)) >= 0)
7178 inst
.instruction
|= i
+ 8;
7182 inst
.error
= _("invalid floating point immediate expression");
7186 _("floating point register or immediate expression expected");
7195 skip_whitespace (str
);
7197 if (reg_required_here (&str
, 12) == FAIL
7198 || skip_past_comma (&str
) == FAIL
7199 || reg_required_here (&str
, 16) == FAIL
7200 || skip_past_comma (&str
) == FAIL
7201 || data_op2 (&str
) == FAIL
)
7204 inst
.error
= BAD_ARGS
;
7215 /* This is a pseudo-op of the form "adr rd, label" to be converted
7216 into a relative address of the form "add rd, pc, #label-.-8". */
7217 skip_whitespace (str
);
7219 if (reg_required_here (&str
, 12) == FAIL
7220 || skip_past_comma (&str
) == FAIL
7221 || my_get_expression (&inst
.reloc
.exp
, &str
))
7224 inst
.error
= BAD_ARGS
;
7228 /* Frag hacking will turn this into a sub instruction if the offset turns
7229 out to be negative. */
7230 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
7232 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust. */
7234 inst
.reloc
.pc_rel
= 1;
7243 /* This is a pseudo-op of the form "adrl rd, label" to be converted
7244 into a relative address of the form:
7245 add rd, pc, #low(label-.-8)"
7246 add rd, rd, #high(label-.-8)" */
7248 skip_whitespace (str
);
7250 if (reg_required_here (&str
, 12) == FAIL
7251 || skip_past_comma (&str
) == FAIL
7252 || my_get_expression (&inst
.reloc
.exp
, &str
))
7255 inst
.error
= BAD_ARGS
;
7261 /* Frag hacking will turn this into a sub instruction if the offset turns
7262 out to be negative. */
7263 inst
.reloc
.type
= BFD_RELOC_ARM_ADRL_IMMEDIATE
;
7265 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust */
7267 inst
.reloc
.pc_rel
= 1;
7268 inst
.size
= INSN_SIZE
* 2;
7275 skip_whitespace (str
);
7277 if (reg_required_here (&str
, 16) == FAIL
)
7280 inst
.error
= BAD_ARGS
;
7284 if (skip_past_comma (&str
) == FAIL
7285 || data_op2 (&str
) == FAIL
)
7288 inst
.error
= BAD_ARGS
;
7299 skip_whitespace (str
);
7301 if (reg_required_here (&str
, 12) == FAIL
)
7304 inst
.error
= BAD_ARGS
;
7308 if (skip_past_comma (&str
) == FAIL
7309 || data_op2 (&str
) == FAIL
)
7312 inst
.error
= BAD_ARGS
;
7330 if (my_get_expression (& inst
.reloc
.exp
, str
))
7333 if (inst
.reloc
.exp
.X_op
== O_constant
)
7335 int value
= inst
.reloc
.exp
.X_add_number
;
7337 if (value
< -4095 || value
> 4095)
7339 inst
.error
= _("address offset too large");
7349 inst
.instruction
|= add
| value
;
7353 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
7354 inst
.reloc
.pc_rel
= 0;
7367 if (reg_required_here (str
, 0) == FAIL
)
7370 inst
.instruction
|= add
| OFFSET_REG
;
7371 if (skip_past_comma (str
) == SUCCESS
)
7372 return decode_shift (str
, SHIFT_IMMEDIATE
);
7386 skip_whitespace (str
);
7388 if ((conflict_reg
= reg_required_here (&str
, 12)) == FAIL
)
7391 inst
.error
= BAD_ARGS
;
7395 if (skip_past_comma (&str
) == FAIL
)
7397 inst
.error
= _("address expected");
7407 skip_whitespace (str
);
7409 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
7412 /* Conflicts can occur on stores as well as loads. */
7413 conflict_reg
= (conflict_reg
== reg
);
7415 skip_whitespace (str
);
7421 if (skip_past_comma (&str
) == SUCCESS
)
7423 /* [Rn],... (post inc) */
7424 if (ldst_extend (&str
) == FAIL
)
7427 as_warn (_("%s register same as write-back base"),
7428 ((inst
.instruction
& LOAD_BIT
)
7429 ? _("destination") : _("source")));
7434 skip_whitespace (str
);
7439 as_warn (_("%s register same as write-back base"),
7440 ((inst
.instruction
& LOAD_BIT
)
7441 ? _("destination") : _("source")));
7443 inst
.instruction
|= WRITE_BACK
;
7446 inst
.instruction
|= INDEX_UP
;
7453 if (skip_past_comma (&str
) == FAIL
)
7455 inst
.error
= _("pre-indexed expression expected");
7460 if (ldst_extend (&str
) == FAIL
)
7463 skip_whitespace (str
);
7467 inst
.error
= _("missing ]");
7471 skip_whitespace (str
);
7476 as_warn (_("%s register same as write-back base"),
7477 ((inst
.instruction
& LOAD_BIT
)
7478 ? _("destination") : _("source")));
7480 inst
.instruction
|= WRITE_BACK
;
7484 else if (*str
== '=')
7486 if ((inst
.instruction
& LOAD_BIT
) == 0)
7488 inst
.error
= _("invalid pseudo operation");
7492 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
7495 skip_whitespace (str
);
7497 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7500 if (inst
.reloc
.exp
.X_op
!= O_constant
7501 && inst
.reloc
.exp
.X_op
!= O_symbol
)
7503 inst
.error
= _("constant expression expected");
7507 if (inst
.reloc
.exp
.X_op
== O_constant
)
7509 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
7513 /* This can be done with a mov instruction. */
7514 inst
.instruction
&= LITERAL_MASK
;
7515 inst
.instruction
|= (INST_IMMEDIATE
7516 | (OPCODE_MOV
<< DATA_OP_SHIFT
));
7517 inst
.instruction
|= value
& 0xfff;
7522 value
= validate_immediate (~inst
.reloc
.exp
.X_add_number
);
7526 /* This can be done with a mvn instruction. */
7527 inst
.instruction
&= LITERAL_MASK
;
7528 inst
.instruction
|= (INST_IMMEDIATE
7529 | (OPCODE_MVN
<< DATA_OP_SHIFT
));
7530 inst
.instruction
|= value
& 0xfff;
7536 /* Insert into literal pool. */
7537 if (add_to_lit_pool () == FAIL
)
7540 inst
.error
= _("literal pool insertion failed");
7544 /* Change the instruction exp to point to the pool. */
7545 inst
.reloc
.type
= BFD_RELOC_ARM_LITERAL
;
7546 inst
.reloc
.pc_rel
= 1;
7547 inst
.instruction
|= (REG_PC
<< 16);
7552 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7555 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
7557 /* PC rel adjust. */
7558 inst
.reloc
.exp
.X_add_number
-= 8;
7560 inst
.reloc
.pc_rel
= 1;
7561 inst
.instruction
|= (REG_PC
<< 16);
7565 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
7575 skip_whitespace (str
);
7577 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
7580 inst
.error
= BAD_ARGS
;
7584 if (skip_past_comma (& str
) == FAIL
)
7586 inst
.error
= _("address expected");
7596 skip_whitespace (str
);
7598 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
7601 /* ldrt/strt always use post-indexed addressing, so if the base is
7602 the same as Rd, we warn. */
7603 if (conflict_reg
== reg
)
7604 as_warn (_("%s register same as write-back base"),
7605 ((inst
.instruction
& LOAD_BIT
)
7606 ? _("destination") : _("source")));
7608 skip_whitespace (str
);
7614 if (skip_past_comma (&str
) == SUCCESS
)
7616 /* [Rn],... (post inc) */
7617 if (ldst_extend (&str
) == FAIL
)
7623 skip_whitespace (str
);
7625 /* Skip a write-back '!'. */
7629 inst
.instruction
|= INDEX_UP
;
7634 inst
.error
= _("post-indexed expression expected");
7640 inst
.error
= _("post-indexed expression expected");
7648 ldst_extend_v4 (str
)
7658 if (my_get_expression (& inst
.reloc
.exp
, str
))
7661 if (inst
.reloc
.exp
.X_op
== O_constant
)
7663 int value
= inst
.reloc
.exp
.X_add_number
;
7665 if (value
< -255 || value
> 255)
7667 inst
.error
= _("address offset too large");
7677 /* Halfword and signextension instructions have the
7678 immediate value split across bits 11..8 and bits 3..0. */
7679 inst
.instruction
|= (add
| HWOFFSET_IMM
7680 | ((value
>> 4) << 8) | (value
& 0xF));
7684 inst
.instruction
|= HWOFFSET_IMM
;
7685 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
7686 inst
.reloc
.pc_rel
= 0;
7699 if (reg_required_here (str
, 0) == FAIL
)
7702 inst
.instruction
|= add
;
7707 /* Halfword and signed-byte load/store operations. */
7716 skip_whitespace (str
);
7718 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
7721 inst
.error
= BAD_ARGS
;
7725 if (skip_past_comma (& str
) == FAIL
)
7727 inst
.error
= _("address expected");
7737 skip_whitespace (str
);
7739 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
7742 /* Conflicts can occur on stores as well as loads. */
7743 conflict_reg
= (conflict_reg
== reg
);
7745 skip_whitespace (str
);
7751 if (skip_past_comma (&str
) == SUCCESS
)
7753 /* [Rn],... (post inc) */
7754 if (ldst_extend_v4 (&str
) == FAIL
)
7757 as_warn (_("%s register same as write-back base"),
7758 ((inst
.instruction
& LOAD_BIT
)
7759 ? _("destination") : _("source")));
7764 inst
.instruction
|= HWOFFSET_IMM
;
7766 skip_whitespace (str
);
7771 as_warn (_("%s register same as write-back base"),
7772 ((inst
.instruction
& LOAD_BIT
)
7773 ? _("destination") : _("source")));
7775 inst
.instruction
|= WRITE_BACK
;
7778 inst
.instruction
|= INDEX_UP
;
7785 if (skip_past_comma (&str
) == FAIL
)
7787 inst
.error
= _("pre-indexed expression expected");
7792 if (ldst_extend_v4 (&str
) == FAIL
)
7795 skip_whitespace (str
);
7799 inst
.error
= _("missing ]");
7803 skip_whitespace (str
);
7808 as_warn (_("%s register same as write-back base"),
7809 ((inst
.instruction
& LOAD_BIT
)
7810 ? _("destination") : _("source")));
7812 inst
.instruction
|= WRITE_BACK
;
7816 else if (*str
== '=')
7818 if ((inst
.instruction
& LOAD_BIT
) == 0)
7820 inst
.error
= _("invalid pseudo operation");
7824 /* XXX Does this work correctly for half-word/byte ops? */
7825 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
7828 skip_whitespace (str
);
7830 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7833 if (inst
.reloc
.exp
.X_op
!= O_constant
7834 && inst
.reloc
.exp
.X_op
!= O_symbol
)
7836 inst
.error
= _("constant expression expected");
7840 if (inst
.reloc
.exp
.X_op
== O_constant
)
7842 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
7846 /* This can be done with a mov instruction. */
7847 inst
.instruction
&= LITERAL_MASK
;
7848 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MOV
<< DATA_OP_SHIFT
);
7849 inst
.instruction
|= value
& 0xfff;
7854 value
= validate_immediate (~ inst
.reloc
.exp
.X_add_number
);
7858 /* This can be done with a mvn instruction. */
7859 inst
.instruction
&= LITERAL_MASK
;
7860 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MVN
<< DATA_OP_SHIFT
);
7861 inst
.instruction
|= value
& 0xfff;
7867 /* Insert into literal pool. */
7868 if (add_to_lit_pool () == FAIL
)
7871 inst
.error
= _("literal pool insertion failed");
7875 /* Change the instruction exp to point to the pool. */
7876 inst
.instruction
|= HWOFFSET_IMM
;
7877 inst
.reloc
.type
= BFD_RELOC_ARM_HWLITERAL
;
7878 inst
.reloc
.pc_rel
= 1;
7879 inst
.instruction
|= (REG_PC
<< 16);
7884 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7887 inst
.instruction
|= HWOFFSET_IMM
;
7888 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
7890 /* PC rel adjust. */
7891 inst
.reloc
.exp
.X_add_number
-= 8;
7893 inst
.reloc
.pc_rel
= 1;
7894 inst
.instruction
|= (REG_PC
<< 16);
7898 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
7906 char * str
= * strp
;
7910 /* We come back here if we get ranges concatenated by '+' or '|'. */
7925 skip_whitespace (str
);
7927 if ((reg
= reg_required_here (& str
, -1)) == FAIL
)
7936 inst
.error
= _("bad range in register list");
7940 for (i
= cur_reg
+ 1; i
< reg
; i
++)
7942 if (range
& (1 << i
))
7944 (_("Warning: duplicated register (r%d) in register list"),
7952 if (range
& (1 << reg
))
7953 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
7955 else if (reg
<= cur_reg
)
7956 as_tsktsk (_("Warning: register range not in ascending order"));
7961 while (skip_past_comma (&str
) != FAIL
7962 || (in_range
= 1, *str
++ == '-'));
7964 skip_whitespace (str
);
7968 inst
.error
= _("missing `}'");
7976 if (my_get_expression (&expr
, &str
))
7979 if (expr
.X_op
== O_constant
)
7981 if (expr
.X_add_number
7982 != (expr
.X_add_number
& 0x0000ffff))
7984 inst
.error
= _("invalid register mask");
7988 if ((range
& expr
.X_add_number
) != 0)
7990 int regno
= range
& expr
.X_add_number
;
7993 regno
= (1 << regno
) - 1;
7995 (_("Warning: duplicated register (r%d) in register list"),
7999 range
|= expr
.X_add_number
;
8003 if (inst
.reloc
.type
!= 0)
8005 inst
.error
= _("expression too complex");
8009 memcpy (&inst
.reloc
.exp
, &expr
, sizeof (expressionS
));
8010 inst
.reloc
.type
= BFD_RELOC_ARM_MULTI
;
8011 inst
.reloc
.pc_rel
= 0;
8015 skip_whitespace (str
);
8017 if (*str
== '|' || *str
== '+')
8023 while (another_range
);
8036 skip_whitespace (str
);
8038 if ((base_reg
= reg_required_here (&str
, 16)) == FAIL
)
8041 if (base_reg
== REG_PC
)
8043 inst
.error
= _("r15 not allowed as base register");
8047 skip_whitespace (str
);
8051 inst
.instruction
|= WRITE_BACK
;
8055 if (skip_past_comma (&str
) == FAIL
8056 || (range
= reg_list (&str
)) == FAIL
)
8059 inst
.error
= BAD_ARGS
;
8066 inst
.instruction
|= LDM_TYPE_2_OR_3
;
8069 if (inst
.instruction
& WRITE_BACK
)
8071 /* Check for unpredictable uses of writeback. */
8072 if (inst
.instruction
& LOAD_BIT
)
8074 /* Not allowed in LDM type 2. */
8075 if ((inst
.instruction
& LDM_TYPE_2_OR_3
)
8076 && ((range
& (1 << REG_PC
)) == 0))
8077 as_warn (_("writeback of base register is UNPREDICTABLE"));
8078 /* Only allowed if base reg not in list for other types. */
8079 else if (range
& (1 << base_reg
))
8080 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
8084 /* Not allowed for type 2. */
8085 if (inst
.instruction
& LDM_TYPE_2_OR_3
)
8086 as_warn (_("writeback of base register is UNPREDICTABLE"));
8087 /* Only allowed if base reg not in list, or first in list. */
8088 else if ((range
& (1 << base_reg
))
8089 && (range
& ((1 << base_reg
) - 1)))
8090 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
8094 inst
.instruction
|= range
;
8102 skip_whitespace (str
);
8104 /* Allow optional leading '#'. */
8105 if (is_immediate_prefix (*str
))
8108 if (my_get_expression (& inst
.reloc
.exp
, & str
))
8111 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
8112 inst
.reloc
.pc_rel
= 0;
8122 skip_whitespace (str
);
8124 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
8129 inst
.error
= _("r15 not allowed in swap");
8133 if (skip_past_comma (&str
) == FAIL
8134 || (reg
= reg_required_here (&str
, 0)) == FAIL
)
8137 inst
.error
= BAD_ARGS
;
8143 inst
.error
= _("r15 not allowed in swap");
8147 if (skip_past_comma (&str
) == FAIL
8150 inst
.error
= BAD_ARGS
;
8154 skip_whitespace (str
);
8156 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
8161 inst
.error
= BAD_PC
;
8165 skip_whitespace (str
);
8169 inst
.error
= _("missing ]");
8180 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8187 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
8188 required for the instruction. */
8190 /* arm_parse_reloc () works on input_line_pointer.
8191 We actually want to parse the operands to the branch instruction
8192 passed in 'str'. Save the input pointer and restore it later. */
8193 save_in
= input_line_pointer
;
8194 input_line_pointer
= str
;
8195 if (inst
.reloc
.exp
.X_op
== O_symbol
8197 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
8199 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
8200 inst
.reloc
.pc_rel
= 0;
8201 /* Modify str to point to after parsed operands, otherwise
8202 end_of_line() will complain about the (PLT) left in str. */
8203 str
= input_line_pointer
;
8207 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
8208 inst
.reloc
.pc_rel
= 1;
8210 input_line_pointer
= save_in
;
8213 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
8214 inst
.reloc
.pc_rel
= 1;
8215 #endif /* OBJ_ELF */
8226 skip_whitespace (str
);
8228 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
8230 inst
.error
= BAD_ARGS
;
8234 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
8236 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
8245 /* Co-processor data operation.
8246 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
8247 skip_whitespace (str
);
8249 if (co_proc_number (&str
) == FAIL
)
8252 inst
.error
= BAD_ARGS
;
8256 if (skip_past_comma (&str
) == FAIL
8257 || cp_opc_expr (&str
, 20,4) == FAIL
)
8260 inst
.error
= BAD_ARGS
;
8264 if (skip_past_comma (&str
) == FAIL
8265 || cp_reg_required_here (&str
, 12) == FAIL
)
8268 inst
.error
= BAD_ARGS
;
8272 if (skip_past_comma (&str
) == FAIL
8273 || cp_reg_required_here (&str
, 16) == FAIL
)
8276 inst
.error
= BAD_ARGS
;
8280 if (skip_past_comma (&str
) == FAIL
8281 || cp_reg_required_here (&str
, 0) == FAIL
)
8284 inst
.error
= BAD_ARGS
;
8288 if (skip_past_comma (&str
) == SUCCESS
)
8290 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
8293 inst
.error
= BAD_ARGS
;
8305 /* Co-processor register load/store.
8306 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
8308 skip_whitespace (str
);
8310 if (co_proc_number (&str
) == FAIL
)
8313 inst
.error
= BAD_ARGS
;
8317 if (skip_past_comma (&str
) == FAIL
8318 || cp_reg_required_here (&str
, 12) == FAIL
)
8321 inst
.error
= BAD_ARGS
;
8325 if (skip_past_comma (&str
) == FAIL
8326 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
8329 inst
.error
= BAD_ARGS
;
8340 /* Co-processor register transfer.
8341 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
8343 skip_whitespace (str
);
8345 if (co_proc_number (&str
) == FAIL
)
8348 inst
.error
= BAD_ARGS
;
8352 if (skip_past_comma (&str
) == FAIL
8353 || cp_opc_expr (&str
, 21, 3) == FAIL
)
8356 inst
.error
= BAD_ARGS
;
8360 if (skip_past_comma (&str
) == FAIL
8361 || reg_required_here (&str
, 12) == FAIL
)
8364 inst
.error
= BAD_ARGS
;
8368 if (skip_past_comma (&str
) == FAIL
8369 || cp_reg_required_here (&str
, 16) == FAIL
)
8372 inst
.error
= BAD_ARGS
;
8376 if (skip_past_comma (&str
) == FAIL
8377 || cp_reg_required_here (&str
, 0) == FAIL
)
8380 inst
.error
= BAD_ARGS
;
8384 if (skip_past_comma (&str
) == SUCCESS
)
8386 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
8389 inst
.error
= BAD_ARGS
;
8401 /* FP control registers.
8402 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
8404 skip_whitespace (str
);
8406 if (reg_required_here (&str
, 12) == FAIL
)
8409 inst
.error
= BAD_ARGS
;
8420 skip_whitespace (str
);
8422 if (fp_reg_required_here (&str
, 12) == FAIL
)
8425 inst
.error
= BAD_ARGS
;
8429 if (skip_past_comma (&str
) == FAIL
8430 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
8433 inst
.error
= BAD_ARGS
;
8446 skip_whitespace (str
);
8448 if (fp_reg_required_here (&str
, 12) == FAIL
)
8451 inst
.error
= BAD_ARGS
;
8455 /* Get Number of registers to transfer. */
8456 if (skip_past_comma (&str
) == FAIL
8457 || my_get_expression (&inst
.reloc
.exp
, &str
))
8460 inst
.error
= _("constant expression expected");
8464 if (inst
.reloc
.exp
.X_op
!= O_constant
)
8466 inst
.error
= _("constant value required for number of registers");
8470 num_regs
= inst
.reloc
.exp
.X_add_number
;
8472 if (num_regs
< 1 || num_regs
> 4)
8474 inst
.error
= _("number of registers must be in the range [1:4]");
8481 inst
.instruction
|= CP_T_X
;
8484 inst
.instruction
|= CP_T_Y
;
8487 inst
.instruction
|= CP_T_Y
| CP_T_X
;
8495 if (inst
.instruction
& (CP_T_Pre
| CP_T_UD
)) /* ea/fd format. */
8501 /* The instruction specified "ea" or "fd", so we can only accept
8502 [Rn]{!}. The instruction does not really support stacking or
8503 unstacking, so we have to emulate these by setting appropriate
8504 bits and offsets. */
8505 if (skip_past_comma (&str
) == FAIL
8509 inst
.error
= BAD_ARGS
;
8514 skip_whitespace (str
);
8516 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
8519 skip_whitespace (str
);
8523 inst
.error
= BAD_ARGS
;
8535 _("r15 not allowed as base register with write-back");
8542 if (inst
.instruction
& CP_T_Pre
)
8544 /* Pre-decrement. */
8545 offset
= 3 * num_regs
;
8547 inst
.instruction
|= CP_T_WB
;
8551 /* Post-increment. */
8554 inst
.instruction
|= CP_T_WB
;
8555 offset
= 3 * num_regs
;
8559 /* No write-back, so convert this into a standard pre-increment
8560 instruction -- aesthetically more pleasing. */
8561 inst
.instruction
|= CP_T_Pre
| CP_T_UD
;
8566 inst
.instruction
|= offset
;
8568 else if (skip_past_comma (&str
) == FAIL
8569 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
8572 inst
.error
= BAD_ARGS
;
8583 skip_whitespace (str
);
8585 if (fp_reg_required_here (&str
, 12) == FAIL
)
8588 inst
.error
= BAD_ARGS
;
8592 if (skip_past_comma (&str
) == FAIL
8593 || fp_reg_required_here (&str
, 16) == FAIL
)
8596 inst
.error
= BAD_ARGS
;
8600 if (skip_past_comma (&str
) == FAIL
8601 || fp_op2 (&str
) == FAIL
)
8604 inst
.error
= BAD_ARGS
;
8612 do_fpa_monadic (str
)
8615 skip_whitespace (str
);
8617 if (fp_reg_required_here (&str
, 12) == FAIL
)
8620 inst
.error
= BAD_ARGS
;
8624 if (skip_past_comma (&str
) == FAIL
8625 || fp_op2 (&str
) == FAIL
)
8628 inst
.error
= BAD_ARGS
;
8639 skip_whitespace (str
);
8641 if (fp_reg_required_here (&str
, 16) == FAIL
)
8644 inst
.error
= BAD_ARGS
;
8648 if (skip_past_comma (&str
) == FAIL
8649 || fp_op2 (&str
) == FAIL
)
8652 inst
.error
= BAD_ARGS
;
8660 do_fpa_from_reg (str
)
8663 skip_whitespace (str
);
8665 if (fp_reg_required_here (&str
, 16) == FAIL
)
8668 inst
.error
= BAD_ARGS
;
8672 if (skip_past_comma (&str
) == FAIL
8673 || reg_required_here (&str
, 12) == FAIL
)
8676 inst
.error
= BAD_ARGS
;
8687 skip_whitespace (str
);
8689 if (reg_required_here (&str
, 12) == FAIL
)
8692 if (skip_past_comma (&str
) == FAIL
8693 || fp_reg_required_here (&str
, 0) == FAIL
)
8696 inst
.error
= BAD_ARGS
;
8704 vfp_sp_reg_required_here (str
, pos
)
8706 enum vfp_sp_reg_pos pos
;
8711 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_SN
].htab
)) != FAIL
)
8716 inst
.instruction
|= ((reg
>> 1) << 12) | ((reg
& 1) << 22);
8720 inst
.instruction
|= ((reg
>> 1) << 16) | ((reg
& 1) << 7);
8724 inst
.instruction
|= ((reg
>> 1) << 0) | ((reg
& 1) << 5);
8733 /* In the few cases where we might be able to accept something else
8734 this error can be overridden. */
8735 inst
.error
= _(all_reg_maps
[REG_TYPE_SN
].expected
);
8737 /* Restore the start point. */
8743 vfp_dp_reg_required_here (str
, pos
)
8745 enum vfp_dp_reg_pos pos
;
8750 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_DN
].htab
)) != FAIL
)
8755 inst
.instruction
|= reg
<< 12;
8759 inst
.instruction
|= reg
<< 16;
8763 inst
.instruction
|= reg
<< 0;
8772 /* In the few cases where we might be able to accept something else
8773 this error can be overridden. */
8774 inst
.error
= _(all_reg_maps
[REG_TYPE_DN
].expected
);
8776 /* Restore the start point. */
8782 do_vfp_sp_monadic (str
)
8785 skip_whitespace (str
);
8787 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8790 if (skip_past_comma (&str
) == FAIL
8791 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
8794 inst
.error
= BAD_ARGS
;
8802 do_vfp_dp_monadic (str
)
8805 skip_whitespace (str
);
8807 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8810 if (skip_past_comma (&str
) == FAIL
8811 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
8814 inst
.error
= BAD_ARGS
;
8822 do_vfp_sp_dyadic (str
)
8825 skip_whitespace (str
);
8827 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8830 if (skip_past_comma (&str
) == FAIL
8831 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
8832 || skip_past_comma (&str
) == FAIL
8833 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
8836 inst
.error
= BAD_ARGS
;
8844 do_vfp_dp_dyadic (str
)
8847 skip_whitespace (str
);
8849 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8852 if (skip_past_comma (&str
) == FAIL
8853 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
8854 || skip_past_comma (&str
) == FAIL
8855 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
8858 inst
.error
= BAD_ARGS
;
8866 do_vfp_reg_from_sp (str
)
8869 skip_whitespace (str
);
8871 if (reg_required_here (&str
, 12) == FAIL
)
8874 if (skip_past_comma (&str
) == FAIL
8875 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
8878 inst
.error
= BAD_ARGS
;
8886 do_vfp_reg2_from_sp2 (str
)
8889 skip_whitespace (str
);
8891 if (reg_required_here (&str
, 12) == FAIL
8892 || skip_past_comma (&str
) == FAIL
8893 || reg_required_here (&str
, 16) == FAIL
8894 || skip_past_comma (&str
) == FAIL
)
8897 inst
.error
= BAD_ARGS
;
8901 /* We require exactly two consecutive SP registers. */
8902 if (vfp_sp_reg_list (&str
, VFP_REG_Sm
) != 2)
8905 inst
.error
= _("only two consecutive VFP SP registers allowed here");
8912 do_vfp_sp_from_reg (str
)
8915 skip_whitespace (str
);
8917 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
8920 if (skip_past_comma (&str
) == FAIL
8921 || reg_required_here (&str
, 12) == FAIL
)
8924 inst
.error
= BAD_ARGS
;
8932 do_vfp_sp2_from_reg2 (str
)
8935 skip_whitespace (str
);
8937 /* We require exactly two consecutive SP registers. */
8938 if (vfp_sp_reg_list (&str
, VFP_REG_Sm
) != 2)
8941 inst
.error
= _("only two consecutive VFP SP registers allowed here");
8944 if (skip_past_comma (&str
) == FAIL
8945 || reg_required_here (&str
, 12) == FAIL
8946 || skip_past_comma (&str
) == FAIL
8947 || reg_required_here (&str
, 16) == FAIL
)
8950 inst
.error
= BAD_ARGS
;
8958 do_vfp_reg_from_dp (str
)
8961 skip_whitespace (str
);
8963 if (reg_required_here (&str
, 12) == FAIL
)
8966 if (skip_past_comma (&str
) == FAIL
8967 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
8970 inst
.error
= BAD_ARGS
;
8978 do_vfp_reg2_from_dp (str
)
8981 skip_whitespace (str
);
8983 if (reg_required_here (&str
, 12) == FAIL
)
8986 if (skip_past_comma (&str
) == FAIL
8987 || reg_required_here (&str
, 16) == FAIL
8988 || skip_past_comma (&str
) == FAIL
8989 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
8992 inst
.error
= BAD_ARGS
;
9000 do_vfp_dp_from_reg (str
)
9003 skip_whitespace (str
);
9005 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
9008 if (skip_past_comma (&str
) == FAIL
9009 || reg_required_here (&str
, 12) == FAIL
)
9012 inst
.error
= BAD_ARGS
;
9020 do_vfp_dp_from_reg2 (str
)
9023 skip_whitespace (str
);
9025 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
9028 if (skip_past_comma (&str
) == FAIL
9029 || reg_required_here (&str
, 12) == FAIL
9030 || skip_past_comma (&str
) == FAIL
9031 || reg_required_here (&str
, 16) == FAIL
)
9034 inst
.error
= BAD_ARGS
;
9041 static const struct vfp_reg
*
9048 const struct vfp_reg
*vreg
;
9052 /* Find the end of the current token. */
9057 while (ISALPHA (c
));
9062 for (vreg
= vfp_regs
+ 0;
9063 vreg
< vfp_regs
+ sizeof (vfp_regs
) / sizeof (struct vfp_reg
);
9066 if (strcmp (start
, vreg
->name
) == 0)
9079 vfp_psr_required_here (str
)
9083 const struct vfp_reg
*vreg
;
9085 vreg
= vfp_psr_parse (str
);
9089 inst
.instruction
|= vreg
->regno
;
9093 inst
.error
= _("VFP system register expected");
9100 do_vfp_reg_from_ctrl (str
)
9103 skip_whitespace (str
);
9105 if (reg_required_here (&str
, 12) == FAIL
)
9108 if (skip_past_comma (&str
) == FAIL
9109 || vfp_psr_required_here (&str
) == FAIL
)
9112 inst
.error
= BAD_ARGS
;
9120 do_vfp_ctrl_from_reg (str
)
9123 skip_whitespace (str
);
9125 if (vfp_psr_required_here (&str
) == FAIL
)
9128 if (skip_past_comma (&str
) == FAIL
9129 || reg_required_here (&str
, 12) == FAIL
)
9132 inst
.error
= BAD_ARGS
;
9140 do_vfp_sp_ldst (str
)
9143 skip_whitespace (str
);
9145 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
9148 inst
.error
= BAD_ARGS
;
9152 if (skip_past_comma (&str
) == FAIL
9153 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
9156 inst
.error
= BAD_ARGS
;
9164 do_vfp_dp_ldst (str
)
9167 skip_whitespace (str
);
9169 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
9172 inst
.error
= BAD_ARGS
;
9176 if (skip_past_comma (&str
) == FAIL
9177 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
9180 inst
.error
= BAD_ARGS
;
9187 /* Parse and encode a VFP SP register list, storing the initial
9188 register in position POS and returning the range as the result. If
9189 the string is invalid return FAIL (an invalid range). */
9191 vfp_sp_reg_list (str
, pos
)
9193 enum vfp_sp_reg_pos pos
;
9201 unsigned long mask
= 0;
9208 skip_whitespace (*str
);
9210 tempinst
= inst
.instruction
;
9214 inst
.instruction
= 0;
9216 if ((new_base
= vfp_sp_reg_required_here (str
, pos
)) == FAIL
)
9219 if (count
== 0 || base_reg
> new_base
)
9221 base_reg
= new_base
;
9222 base_bits
= inst
.instruction
;
9225 if (mask
& (1 << new_base
))
9227 inst
.error
= _("invalid register list");
9231 if ((mask
>> new_base
) != 0 && ! warned
)
9233 as_tsktsk (_("register list not in ascending order"));
9237 mask
|= 1 << new_base
;
9240 skip_whitespace (*str
);
9242 if (**str
== '-') /* We have the start of a range expression */
9249 = arm_reg_parse (str
, all_reg_maps
[REG_TYPE_SN
].htab
))
9252 inst
.error
= _(all_reg_maps
[REG_TYPE_SN
].expected
);
9256 if (high_range
<= new_base
)
9258 inst
.error
= _("register range not in ascending order");
9262 for (new_base
++; new_base
<= high_range
; new_base
++)
9264 if (mask
& (1 << new_base
))
9266 inst
.error
= _("invalid register list");
9270 mask
|= 1 << new_base
;
9275 while (skip_past_comma (str
) != FAIL
);
9279 inst
.error
= _("invalid register list");
9287 /* Sanity check -- should have raised a parse error above. */
9288 if (count
== 0 || count
> 32)
9291 /* Final test -- the registers must be consecutive. */
9294 if ((mask
& (1 << base_reg
++)) == 0)
9296 inst
.error
= _("non-contiguous register range");
9301 inst
.instruction
= tempinst
| base_bits
;
9306 vfp_dp_reg_list (str
)
9314 unsigned long mask
= 0;
9321 skip_whitespace (*str
);
9323 tempinst
= inst
.instruction
;
9327 inst
.instruction
= 0;
9329 if ((new_base
= vfp_dp_reg_required_here (str
, VFP_REG_Dd
)) == FAIL
)
9332 if (count
== 0 || base_reg
> new_base
)
9334 base_reg
= new_base
;
9335 range
= inst
.instruction
;
9338 if (mask
& (1 << new_base
))
9340 inst
.error
= _("invalid register list");
9344 if ((mask
>> new_base
) != 0 && ! warned
)
9346 as_tsktsk (_("register list not in ascending order"));
9350 mask
|= 1 << new_base
;
9353 skip_whitespace (*str
);
9355 if (**str
== '-') /* We have the start of a range expression */
9362 = arm_reg_parse (str
, all_reg_maps
[REG_TYPE_DN
].htab
))
9365 inst
.error
= _(all_reg_maps
[REG_TYPE_DN
].expected
);
9369 if (high_range
<= new_base
)
9371 inst
.error
= _("register range not in ascending order");
9375 for (new_base
++; new_base
<= high_range
; new_base
++)
9377 if (mask
& (1 << new_base
))
9379 inst
.error
= _("invalid register list");
9383 mask
|= 1 << new_base
;
9388 while (skip_past_comma (str
) != FAIL
);
9392 inst
.error
= _("invalid register list");
9400 /* Sanity check -- should have raised a parse error above. */
9401 if (count
== 0 || count
> 16)
9404 /* Final test -- the registers must be consecutive. */
9407 if ((mask
& (1 << base_reg
++)) == 0)
9409 inst
.error
= _("non-contiguous register range");
9414 inst
.instruction
= tempinst
;
9419 vfp_sp_ldstm (str
, ldstm_type
)
9421 enum vfp_ldstm_type ldstm_type
;
9425 skip_whitespace (str
);
9427 if (reg_required_here (&str
, 16) == FAIL
)
9430 skip_whitespace (str
);
9434 inst
.instruction
|= WRITE_BACK
;
9437 else if (ldstm_type
!= VFP_LDSTMIA
)
9439 inst
.error
= _("this addressing mode requires base-register writeback");
9443 if (skip_past_comma (&str
) == FAIL
9444 || (range
= vfp_sp_reg_list (&str
, VFP_REG_Sd
)) == FAIL
)
9447 inst
.error
= BAD_ARGS
;
9451 inst
.instruction
|= range
;
9456 vfp_dp_ldstm (str
, ldstm_type
)
9458 enum vfp_ldstm_type ldstm_type
;
9462 skip_whitespace (str
);
9464 if (reg_required_here (&str
, 16) == FAIL
)
9467 skip_whitespace (str
);
9471 inst
.instruction
|= WRITE_BACK
;
9474 else if (ldstm_type
!= VFP_LDSTMIA
&& ldstm_type
!= VFP_LDSTMIAX
)
9476 inst
.error
= _("this addressing mode requires base-register writeback");
9480 if (skip_past_comma (&str
) == FAIL
9481 || (range
= vfp_dp_reg_list (&str
)) == FAIL
)
9484 inst
.error
= BAD_ARGS
;
9488 if (ldstm_type
== VFP_LDSTMIAX
|| ldstm_type
== VFP_LDSTMDBX
)
9491 inst
.instruction
|= range
;
9496 do_vfp_sp_ldstmia (str
)
9499 vfp_sp_ldstm (str
, VFP_LDSTMIA
);
9503 do_vfp_sp_ldstmdb (str
)
9506 vfp_sp_ldstm (str
, VFP_LDSTMDB
);
9510 do_vfp_dp_ldstmia (str
)
9513 vfp_dp_ldstm (str
, VFP_LDSTMIA
);
9517 do_vfp_dp_ldstmdb (str
)
9520 vfp_dp_ldstm (str
, VFP_LDSTMDB
);
9524 do_vfp_xp_ldstmia (str
)
9527 vfp_dp_ldstm (str
, VFP_LDSTMIAX
);
9531 do_vfp_xp_ldstmdb (str
)
9534 vfp_dp_ldstm (str
, VFP_LDSTMDBX
);
9538 do_vfp_sp_compare_z (str
)
9541 skip_whitespace (str
);
9543 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
9546 inst
.error
= BAD_ARGS
;
9554 do_vfp_dp_compare_z (str
)
9557 skip_whitespace (str
);
9559 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
9562 inst
.error
= BAD_ARGS
;
9570 do_vfp_dp_sp_cvt (str
)
9573 skip_whitespace (str
);
9575 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
9578 if (skip_past_comma (&str
) == FAIL
9579 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
9582 inst
.error
= BAD_ARGS
;
9590 do_vfp_sp_dp_cvt (str
)
9593 skip_whitespace (str
);
9595 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
9598 if (skip_past_comma (&str
) == FAIL
9599 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
9602 inst
.error
= BAD_ARGS
;
9609 /* Thumb specific routines. */
9611 /* Parse and validate that a register is of the right form, this saves
9612 repeated checking of this information in many similar cases.
9613 Unlike the 32-bit case we do not insert the register into the opcode
9614 here, since the position is often unknown until the full instruction
9618 thumb_reg (strp
, hi_lo
)
9624 if ((reg
= reg_required_here (strp
, -1)) == FAIL
)
9632 inst
.error
= _("lo register required");
9640 inst
.error
= _("hi register required");
9652 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
9656 thumb_add_sub (str
, subtract
)
9660 int Rd
, Rs
, Rn
= FAIL
;
9662 skip_whitespace (str
);
9664 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
9665 || skip_past_comma (&str
) == FAIL
)
9668 inst
.error
= BAD_ARGS
;
9672 if (is_immediate_prefix (*str
))
9676 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9681 if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
9684 if (skip_past_comma (&str
) == FAIL
)
9686 /* Two operand format, shuffle the registers
9687 and pretend there are 3. */
9691 else if (is_immediate_prefix (*str
))
9694 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9697 else if ((Rn
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
9701 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
9702 for the latter case, EXPR contains the immediate that was found. */
9705 /* All register format. */
9706 if (Rd
> 7 || Rs
> 7 || Rn
> 7)
9710 inst
.error
= _("dest and source1 must be the same register");
9714 /* Can't do this for SUB. */
9717 inst
.error
= _("subtract valid only on lo regs");
9721 inst
.instruction
= (T_OPCODE_ADD_HI
9722 | (Rd
> 7 ? THUMB_H1
: 0)
9723 | (Rn
> 7 ? THUMB_H2
: 0));
9724 inst
.instruction
|= (Rd
& 7) | ((Rn
& 7) << 3);
9728 inst
.instruction
= subtract
? T_OPCODE_SUB_R3
: T_OPCODE_ADD_R3
;
9729 inst
.instruction
|= Rd
| (Rs
<< 3) | (Rn
<< 6);
9734 /* Immediate expression, now things start to get nasty. */
9736 /* First deal with HI regs, only very restricted cases allowed:
9737 Adjusting SP, and using PC or SP to get an address. */
9738 if ((Rd
> 7 && (Rd
!= REG_SP
|| Rs
!= REG_SP
))
9739 || (Rs
> 7 && Rs
!= REG_SP
&& Rs
!= REG_PC
))
9741 inst
.error
= _("invalid Hi register with immediate");
9745 if (inst
.reloc
.exp
.X_op
!= O_constant
)
9747 /* Value isn't known yet, all we can do is store all the fragments
9748 we know about in the instruction and let the reloc hacking
9750 inst
.instruction
= (subtract
? 0x8000 : 0) | (Rd
<< 4) | Rs
;
9751 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
9755 int offset
= inst
.reloc
.exp
.X_add_number
;
9765 /* Quick check, in case offset is MIN_INT. */
9768 inst
.error
= _("immediate value out of range");
9772 /* Note - you cannot convert a subtract of 0 into an
9773 add of 0 because the carry flag is set differently. */
9774 else if (offset
> 0)
9779 if (offset
& ~0x1fc)
9781 inst
.error
= _("invalid immediate value for stack adjust");
9784 inst
.instruction
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
9785 inst
.instruction
|= offset
>> 2;
9787 else if (Rs
== REG_PC
|| Rs
== REG_SP
)
9790 || (offset
& ~0x3fc))
9792 inst
.error
= _("invalid immediate for address calculation");
9795 inst
.instruction
= (Rs
== REG_PC
? T_OPCODE_ADD_PC
9797 inst
.instruction
|= (Rd
<< 8) | (offset
>> 2);
9803 inst
.error
= _("immediate value out of range");
9806 inst
.instruction
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
9807 inst
.instruction
|= (Rd
<< 8) | offset
;
9813 inst
.error
= _("immediate value out of range");
9816 inst
.instruction
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
9817 inst
.instruction
|= Rd
| (Rs
<< 3) | (offset
<< 6);
9826 thumb_shift (str
, shift
)
9830 int Rd
, Rs
, Rn
= FAIL
;
9832 skip_whitespace (str
);
9834 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9835 || skip_past_comma (&str
) == FAIL
)
9838 inst
.error
= BAD_ARGS
;
9842 if (is_immediate_prefix (*str
))
9844 /* Two operand immediate format, set Rs to Rd. */
9847 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9852 if ((Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9855 if (skip_past_comma (&str
) == FAIL
)
9857 /* Two operand format, shuffle the registers
9858 and pretend there are 3. */
9862 else if (is_immediate_prefix (*str
))
9865 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9868 else if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9872 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
9873 for the latter case, EXPR contains the immediate that was found. */
9879 inst
.error
= _("source1 and dest must be same register");
9885 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_R
; break;
9886 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_R
; break;
9887 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_R
; break;
9890 inst
.instruction
|= Rd
| (Rn
<< 3);
9896 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_I
; break;
9897 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_I
; break;
9898 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_I
; break;
9901 if (inst
.reloc
.exp
.X_op
!= O_constant
)
9903 /* Value isn't known yet, create a dummy reloc and let reloc
9904 hacking fix it up. */
9905 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_SHIFT
;
9909 unsigned shift_value
= inst
.reloc
.exp
.X_add_number
;
9911 if (shift_value
> 32 || (shift_value
== 32 && shift
== THUMB_LSL
))
9913 inst
.error
= _("invalid immediate for shift");
9917 /* Shifts of zero are handled by converting to LSL. */
9918 if (shift_value
== 0)
9919 inst
.instruction
= T_OPCODE_LSL_I
;
9921 /* Shifts of 32 are encoded as a shift of zero. */
9922 if (shift_value
== 32)
9925 inst
.instruction
|= shift_value
<< 6;
9928 inst
.instruction
|= Rd
| (Rs
<< 3);
9935 thumb_mov_compare (str
, move
)
9941 skip_whitespace (str
);
9943 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
9944 || skip_past_comma (&str
) == FAIL
)
9947 inst
.error
= BAD_ARGS
;
9951 if (move
!= THUMB_CPY
&& is_immediate_prefix (*str
))
9954 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9957 else if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
9962 if (move
!= THUMB_CPY
&& Rs
< 8 && Rd
< 8)
9964 if (move
== THUMB_MOVE
)
9965 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
9966 since a MOV instruction produces unpredictable results. */
9967 inst
.instruction
= T_OPCODE_ADD_I3
;
9969 inst
.instruction
= T_OPCODE_CMP_LR
;
9970 inst
.instruction
|= Rd
| (Rs
<< 3);
9974 if (move
== THUMB_MOVE
)
9975 inst
.instruction
= T_OPCODE_MOV_HR
;
9976 else if (move
!= THUMB_CPY
)
9977 inst
.instruction
= T_OPCODE_CMP_HR
;
9980 inst
.instruction
|= THUMB_H1
;
9983 inst
.instruction
|= THUMB_H2
;
9985 inst
.instruction
|= (Rd
& 7) | ((Rs
& 7) << 3);
9992 inst
.error
= _("only lo regs allowed with immediate");
9996 if (move
== THUMB_MOVE
)
9997 inst
.instruction
= T_OPCODE_MOV_I8
;
9999 inst
.instruction
= T_OPCODE_CMP_I8
;
10001 inst
.instruction
|= Rd
<< 8;
10003 if (inst
.reloc
.exp
.X_op
!= O_constant
)
10004 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_IMM
;
10007 unsigned value
= inst
.reloc
.exp
.X_add_number
;
10011 inst
.error
= _("invalid immediate");
10015 inst
.instruction
|= value
;
10023 thumb_load_store (str
, load_store
, size
)
10028 int Rd
, Rb
, Ro
= FAIL
;
10030 skip_whitespace (str
);
10032 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
10033 || skip_past_comma (&str
) == FAIL
)
10036 inst
.error
= BAD_ARGS
;
10043 if ((Rb
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
10046 if (skip_past_comma (&str
) != FAIL
)
10048 if (is_immediate_prefix (*str
))
10051 if (my_get_expression (&inst
.reloc
.exp
, &str
))
10054 else if ((Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
10059 inst
.reloc
.exp
.X_op
= O_constant
;
10060 inst
.reloc
.exp
.X_add_number
= 0;
10065 inst
.error
= _("expected ']'");
10070 else if (*str
== '=')
10072 if (load_store
!= THUMB_LOAD
)
10074 inst
.error
= _("invalid pseudo operation");
10078 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
10081 skip_whitespace (str
);
10083 if (my_get_expression (& inst
.reloc
.exp
, & str
))
10088 if ( inst
.reloc
.exp
.X_op
!= O_constant
10089 && inst
.reloc
.exp
.X_op
!= O_symbol
)
10091 inst
.error
= "Constant expression expected";
10095 if (inst
.reloc
.exp
.X_op
== O_constant
10096 && ((inst
.reloc
.exp
.X_add_number
& ~0xFF) == 0))
10098 /* This can be done with a mov instruction. */
10100 inst
.instruction
= T_OPCODE_MOV_I8
| (Rd
<< 8);
10101 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
10105 /* Insert into literal pool. */
10106 if (add_to_lit_pool () == FAIL
)
10109 inst
.error
= "literal pool insertion failed";
10113 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
10114 inst
.reloc
.pc_rel
= 1;
10115 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
10116 /* Adjust ARM pipeline offset to Thumb. */
10117 inst
.reloc
.exp
.X_add_number
+= 4;
10123 if (my_get_expression (&inst
.reloc
.exp
, &str
))
10126 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
10127 inst
.reloc
.pc_rel
= 1;
10128 inst
.reloc
.exp
.X_add_number
-= 4; /* Pipeline offset. */
10129 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
10134 if (Rb
== REG_PC
|| Rb
== REG_SP
)
10136 if (size
!= THUMB_WORD
)
10138 inst
.error
= _("byte or halfword not valid for base register");
10141 else if (Rb
== REG_PC
&& load_store
!= THUMB_LOAD
)
10143 inst
.error
= _("r15 based store not allowed");
10146 else if (Ro
!= FAIL
)
10148 inst
.error
= _("invalid base register for register offset");
10153 inst
.instruction
= T_OPCODE_LDR_PC
;
10154 else if (load_store
== THUMB_LOAD
)
10155 inst
.instruction
= T_OPCODE_LDR_SP
;
10157 inst
.instruction
= T_OPCODE_STR_SP
;
10159 inst
.instruction
|= Rd
<< 8;
10160 if (inst
.reloc
.exp
.X_op
== O_constant
)
10162 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
10164 if (offset
& ~0x3fc)
10166 inst
.error
= _("invalid offset");
10170 inst
.instruction
|= offset
>> 2;
10173 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
10177 inst
.error
= _("invalid base register in load/store");
10180 else if (Ro
== FAIL
)
10182 /* Immediate offset. */
10183 if (size
== THUMB_WORD
)
10184 inst
.instruction
= (load_store
== THUMB_LOAD
10185 ? T_OPCODE_LDR_IW
: T_OPCODE_STR_IW
);
10186 else if (size
== THUMB_HALFWORD
)
10187 inst
.instruction
= (load_store
== THUMB_LOAD
10188 ? T_OPCODE_LDR_IH
: T_OPCODE_STR_IH
);
10190 inst
.instruction
= (load_store
== THUMB_LOAD
10191 ? T_OPCODE_LDR_IB
: T_OPCODE_STR_IB
);
10193 inst
.instruction
|= Rd
| (Rb
<< 3);
10195 if (inst
.reloc
.exp
.X_op
== O_constant
)
10197 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
10199 if (offset
& ~(0x1f << size
))
10201 inst
.error
= _("invalid offset");
10204 inst
.instruction
|= (offset
>> size
) << 6;
10207 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
10211 /* Register offset. */
10212 if (size
== THUMB_WORD
)
10213 inst
.instruction
= (load_store
== THUMB_LOAD
10214 ? T_OPCODE_LDR_RW
: T_OPCODE_STR_RW
);
10215 else if (size
== THUMB_HALFWORD
)
10216 inst
.instruction
= (load_store
== THUMB_LOAD
10217 ? T_OPCODE_LDR_RH
: T_OPCODE_STR_RH
);
10219 inst
.instruction
= (load_store
== THUMB_LOAD
10220 ? T_OPCODE_LDR_RB
: T_OPCODE_STR_RB
);
10222 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
10228 /* A register must be given at this point.
10230 Shift is the place to put it in inst.instruction.
10232 Restores input start point on err.
10233 Returns the reg#, or FAIL. */
10236 mav_reg_required_here (str
, shift
, regtype
)
10239 enum arm_reg_type regtype
;
10242 char *start
= *str
;
10244 if ((reg
= arm_reg_parse (str
, all_reg_maps
[regtype
].htab
)) != FAIL
)
10247 inst
.instruction
|= reg
<< shift
;
10252 /* Restore the start point. */
10255 /* In the few cases where we might be able to accept something else
10256 this error can be overridden. */
10257 inst
.error
= _(all_reg_maps
[regtype
].expected
);
10262 /* Cirrus Maverick Instructions. */
10264 /* Wrapper functions. */
10267 do_mav_binops_1a (str
)
10270 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVF
);
10274 do_mav_binops_1b (str
)
10277 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVD
);
10281 do_mav_binops_1c (str
)
10284 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVDX
);
10288 do_mav_binops_1d (str
)
10291 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVF
);
10295 do_mav_binops_1e (str
)
10298 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVD
);
10302 do_mav_binops_1f (str
)
10305 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVF
);
10309 do_mav_binops_1g (str
)
10312 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVD
);
10316 do_mav_binops_1h (str
)
10319 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVFX
);
10323 do_mav_binops_1i (str
)
10326 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVFX
);
10330 do_mav_binops_1j (str
)
10333 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVDX
);
10337 do_mav_binops_1k (str
)
10340 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVDX
);
10344 do_mav_binops_1l (str
)
10347 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVF
);
10351 do_mav_binops_1m (str
)
10354 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVD
);
10358 do_mav_binops_1n (str
)
10361 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
10365 do_mav_binops_1o (str
)
10368 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
10372 do_mav_binops_2a (str
)
10375 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVF
, REG_TYPE_RN
);
10379 do_mav_binops_2b (str
)
10382 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVD
, REG_TYPE_RN
);
10386 do_mav_binops_2c (str
)
10389 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVDX
, REG_TYPE_RN
);
10393 do_mav_binops_3a (str
)
10396 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVFX
);
10400 do_mav_binops_3b (str
)
10403 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVFX
, REG_TYPE_MVAX
);
10407 do_mav_binops_3c (str
)
10410 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVDX
);
10414 do_mav_binops_3d (str
)
10417 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVDX
, REG_TYPE_MVAX
);
10421 do_mav_triple_4a (str
)
10424 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_RN
);
10428 do_mav_triple_4b (str
)
10431 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_RN
);
10435 do_mav_triple_5a (str
)
10438 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVF
, REG_TYPE_MVF
);
10442 do_mav_triple_5b (str
)
10445 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVD
, REG_TYPE_MVD
);
10449 do_mav_triple_5c (str
)
10452 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
10456 do_mav_triple_5d (str
)
10459 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
10463 do_mav_triple_5e (str
)
10466 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVF
, REG_TYPE_MVF
, REG_TYPE_MVF
);
10470 do_mav_triple_5f (str
)
10473 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVD
, REG_TYPE_MVD
, REG_TYPE_MVD
);
10477 do_mav_triple_5g (str
)
10480 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
10484 do_mav_triple_5h (str
)
10487 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
10491 do_mav_quad_6a (str
)
10494 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
,
10499 do_mav_quad_6b (str
)
10502 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVAX
, REG_TYPE_MVFX
,
10506 /* cfmvsc32<cond> DSPSC,MVDX[15:0]. */
10508 do_mav_dspsc_1 (str
)
10511 skip_whitespace (str
);
10514 if (mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
10515 || skip_past_comma (&str
) == FAIL
10516 || mav_reg_required_here (&str
, 12, REG_TYPE_MVDX
) == FAIL
)
10519 inst
.error
= BAD_ARGS
;
10527 /* cfmv32sc<cond> MVDX[15:0],DSPSC. */
10529 do_mav_dspsc_2 (str
)
10532 skip_whitespace (str
);
10535 if (mav_reg_required_here (&str
, 12, REG_TYPE_MVDX
) == FAIL
10536 || skip_past_comma (&str
) == FAIL
10537 || mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
)
10540 inst
.error
= BAD_ARGS
;
10549 do_mav_shift_1 (str
)
10552 do_mav_shift (str
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
10556 do_mav_shift_2 (str
)
10559 do_mav_shift (str
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
10563 do_mav_ldst_1 (str
)
10566 do_mav_ldst (str
, REG_TYPE_MVF
);
10570 do_mav_ldst_2 (str
)
10573 do_mav_ldst (str
, REG_TYPE_MVD
);
10577 do_mav_ldst_3 (str
)
10580 do_mav_ldst (str
, REG_TYPE_MVFX
);
10584 do_mav_ldst_4 (str
)
10587 do_mav_ldst (str
, REG_TYPE_MVDX
);
10590 /* Isnsn like "foo X,Y". */
10593 do_mav_binops (str
, mode
, reg0
, reg1
)
10596 enum arm_reg_type reg0
;
10597 enum arm_reg_type reg1
;
10599 int shift0
, shift1
;
10601 shift0
= mode
& 0xff;
10602 shift1
= (mode
>> 8) & 0xff;
10604 skip_whitespace (str
);
10606 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
10607 || skip_past_comma (&str
) == FAIL
10608 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
)
10611 inst
.error
= BAD_ARGS
;
10617 /* Isnsn like "foo X,Y,Z". */
10620 do_mav_triple (str
, mode
, reg0
, reg1
, reg2
)
10623 enum arm_reg_type reg0
;
10624 enum arm_reg_type reg1
;
10625 enum arm_reg_type reg2
;
10627 int shift0
, shift1
, shift2
;
10629 shift0
= mode
& 0xff;
10630 shift1
= (mode
>> 8) & 0xff;
10631 shift2
= (mode
>> 16) & 0xff;
10633 skip_whitespace (str
);
10635 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
10636 || skip_past_comma (&str
) == FAIL
10637 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
10638 || skip_past_comma (&str
) == FAIL
10639 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
)
10642 inst
.error
= BAD_ARGS
;
10648 /* Isnsn like "foo W,X,Y,Z".
10649 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
10652 do_mav_quad (str
, mode
, reg0
, reg1
, reg2
, reg3
)
10655 enum arm_reg_type reg0
;
10656 enum arm_reg_type reg1
;
10657 enum arm_reg_type reg2
;
10658 enum arm_reg_type reg3
;
10660 int shift0
, shift1
, shift2
, shift3
;
10662 shift0
= mode
& 0xff;
10663 shift1
= (mode
>> 8) & 0xff;
10664 shift2
= (mode
>> 16) & 0xff;
10665 shift3
= (mode
>> 24) & 0xff;
10667 skip_whitespace (str
);
10669 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
10670 || skip_past_comma (&str
) == FAIL
10671 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
10672 || skip_past_comma (&str
) == FAIL
10673 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
10674 || skip_past_comma (&str
) == FAIL
10675 || mav_reg_required_here (&str
, shift3
, reg3
) == FAIL
)
10678 inst
.error
= BAD_ARGS
;
10684 /* Maverick shift immediate instructions.
10685 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
10686 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
10689 do_mav_shift (str
, reg0
, reg1
)
10691 enum arm_reg_type reg0
;
10692 enum arm_reg_type reg1
;
10697 skip_whitespace (str
);
10701 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
10702 || skip_past_comma (&str
) == FAIL
10703 || mav_reg_required_here (&str
, 16, reg1
) == FAIL
10704 || skip_past_comma (&str
) == FAIL
)
10707 inst
.error
= BAD_ARGS
;
10711 /* Calculate the immediate operand.
10712 The operand is a 7bit signed number. */
10713 skip_whitespace (str
);
10718 if (!ISDIGIT (*str
) && *str
!= '-')
10720 inst
.error
= _("expecting immediate, 7bit operand");
10730 for (imm
= 0; *str
&& ISDIGIT (*str
); ++str
)
10731 imm
= imm
* 10 + *str
- '0';
10735 inst
.error
= _("immediate out of range");
10739 /* Make negative imm's into 7bit signed numbers. */
10746 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
10747 Bits 5-7 of the insn should have bits 4-6 of the immediate.
10748 Bit 4 should be 0. */
10749 imm
= (imm
& 0xf) | ((imm
& 0x70) << 1);
10751 inst
.instruction
|= imm
;
10756 mav_parse_offset (str
, negative
)
10765 skip_whitespace (p
);
10778 inst
.error
= _("offset expected");
10782 for (offset
= 0; *p
&& ISDIGIT (*p
); ++p
)
10783 offset
= offset
* 10 + *p
- '0';
10785 if (offset
> 0x3fc)
10787 inst
.error
= _("offset out of range");
10792 inst
.error
= _("offset not a multiple of 4");
10798 return *negative
? -offset
: offset
;
10801 /* Maverick load/store instructions.
10802 <insn><cond> CRd,[Rn,<offset>]{!}.
10803 <insn><cond> CRd,[Rn],<offset>. */
10806 do_mav_ldst (str
, reg0
)
10808 enum arm_reg_type reg0
;
10810 int offset
, negative
;
10812 skip_whitespace (str
);
10814 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
10815 || skip_past_comma (&str
) == FAIL
10817 || reg_required_here (&str
, 16) == FAIL
)
10820 if (skip_past_comma (&str
) == SUCCESS
)
10822 /* You are here: "<offset>]{!}". */
10823 inst
.instruction
|= PRE_INDEX
;
10825 offset
= mav_parse_offset (&str
, &negative
);
10832 inst
.error
= _("missing ]");
10838 inst
.instruction
|= WRITE_BACK
;
10844 /* You are here: "], <offset>". */
10847 inst
.error
= _("missing ]");
10851 if (skip_past_comma (&str
) == FAIL
10852 || (offset
= mav_parse_offset (&str
, &negative
), inst
.error
))
10855 inst
.instruction
|= CP_T_WB
; /* Post indexed, set bit W. */
10861 inst
.instruction
|= CP_T_UD
; /* Positive, so set bit U. */
10863 inst
.instruction
|= offset
>> 2;
10869 inst
.error
= BAD_ARGS
;
10880 /* Handle the Format 4 instructions that do not have equivalents in other
10881 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
10890 skip_whitespace (str
);
10892 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
10893 || skip_past_comma (&str
) == FAIL
10894 || (Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
10896 inst
.error
= BAD_ARGS
;
10900 if (skip_past_comma (&str
) != FAIL
)
10902 /* Three operand format not allowed for TST, CMN, NEG and MVN.
10903 (It isn't allowed for CMP either, but that isn't handled by this
10905 if (inst
.instruction
== T_OPCODE_TST
10906 || inst
.instruction
== T_OPCODE_CMN
10907 || inst
.instruction
== T_OPCODE_NEG
10908 || inst
.instruction
== T_OPCODE_MVN
)
10910 inst
.error
= BAD_ARGS
;
10914 if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
10919 inst
.error
= _("dest and source1 must be the same register");
10925 if (inst
.instruction
== T_OPCODE_MUL
10927 as_tsktsk (_("Rs and Rd must be different in MUL"));
10929 inst
.instruction
|= Rd
| (Rs
<< 3);
10937 thumb_add_sub (str
, 0);
10944 thumb_shift (str
, THUMB_ASR
);
10951 if (my_get_expression (&inst
.reloc
.exp
, &str
))
10953 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH9
;
10954 inst
.reloc
.pc_rel
= 1;
10959 do_t_branch12 (str
)
10962 if (my_get_expression (&inst
.reloc
.exp
, &str
))
10964 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH12
;
10965 inst
.reloc
.pc_rel
= 1;
10969 /* Find the real, Thumb encoded start of a Thumb function. */
10972 find_real_start (symbolP
)
10976 const char * name
= S_GET_NAME (symbolP
);
10977 symbolS
* new_target
;
10979 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
10980 #define STUB_NAME ".real_start_of"
10985 /* Names that start with '.' are local labels, not function entry points.
10986 The compiler may generate BL instructions to these labels because it
10987 needs to perform a branch to a far away location. */
10988 if (name
[0] == '.')
10991 real_start
= malloc (strlen (name
) + strlen (STUB_NAME
) + 1);
10992 sprintf (real_start
, "%s%s", STUB_NAME
, name
);
10994 new_target
= symbol_find (real_start
);
10996 if (new_target
== NULL
)
10998 as_warn ("Failed to find real start of function: %s\n", name
);
10999 new_target
= symbolP
;
11008 do_t_branch23 (str
)
11011 if (my_get_expression (& inst
.reloc
.exp
, & str
))
11014 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH23
;
11015 inst
.reloc
.pc_rel
= 1;
11018 /* If the destination of the branch is a defined symbol which does not have
11019 the THUMB_FUNC attribute, then we must be calling a function which has
11020 the (interfacearm) attribute. We look for the Thumb entry point to that
11021 function and change the branch to refer to that function instead. */
11022 if ( inst
.reloc
.exp
.X_op
== O_symbol
11023 && inst
.reloc
.exp
.X_add_symbol
!= NULL
11024 && S_IS_DEFINED (inst
.reloc
.exp
.X_add_symbol
)
11025 && ! THUMB_IS_FUNC (inst
.reloc
.exp
.X_add_symbol
))
11026 inst
.reloc
.exp
.X_add_symbol
=
11027 find_real_start (inst
.reloc
.exp
.X_add_symbol
);
11036 skip_whitespace (str
);
11038 if ((reg
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
11041 /* This sets THUMB_H2 from the top bit of reg. */
11042 inst
.instruction
|= reg
<< 3;
11044 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
11045 should cause the alignment to be checked once it is known. This is
11046 because BX PC only works if the instruction is word aligned. */
11055 thumb_mov_compare (str
, THUMB_COMPARE
);
11065 skip_whitespace (str
);
11067 if ((Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
11071 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
11075 if (skip_past_comma (&str
) == FAIL
11076 || (range
= reg_list (&str
)) == FAIL
)
11079 inst
.error
= BAD_ARGS
;
11083 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
11085 /* This really doesn't seem worth it. */
11086 inst
.reloc
.type
= BFD_RELOC_NONE
;
11087 inst
.error
= _("expression too complex");
11093 inst
.error
= _("only lo-regs valid in load/store multiple");
11097 inst
.instruction
|= (Rb
<< 8) | range
;
11105 thumb_load_store (str
, THUMB_LOAD
, THUMB_WORD
);
11112 thumb_load_store (str
, THUMB_LOAD
, THUMB_BYTE
);
11119 thumb_load_store (str
, THUMB_LOAD
, THUMB_HALFWORD
);
11128 skip_whitespace (str
);
11130 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
11131 || skip_past_comma (&str
) == FAIL
11133 || (Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
11134 || skip_past_comma (&str
) == FAIL
11135 || (Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
11139 inst
.error
= _("syntax: ldrs[b] Rd, [Rb, Ro]");
11143 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
11151 thumb_shift (str
, THUMB_LSL
);
11158 thumb_shift (str
, THUMB_LSR
);
11165 thumb_mov_compare (str
, THUMB_MOVE
);
11169 do_t_push_pop (str
)
11174 skip_whitespace (str
);
11176 if ((range
= reg_list (&str
)) == FAIL
)
11179 inst
.error
= BAD_ARGS
;
11183 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
11185 /* This really doesn't seem worth it. */
11186 inst
.reloc
.type
= BFD_RELOC_NONE
;
11187 inst
.error
= _("expression too complex");
11193 if ((inst
.instruction
== T_OPCODE_PUSH
11194 && (range
& ~0xff) == 1 << REG_LR
)
11195 || (inst
.instruction
== T_OPCODE_POP
11196 && (range
& ~0xff) == 1 << REG_PC
))
11198 inst
.instruction
|= THUMB_PP_PC_LR
;
11203 inst
.error
= _("invalid register list to push/pop instruction");
11208 inst
.instruction
|= range
;
11216 thumb_load_store (str
, THUMB_STORE
, THUMB_WORD
);
11223 thumb_load_store (str
, THUMB_STORE
, THUMB_BYTE
);
11230 thumb_load_store (str
, THUMB_STORE
, THUMB_HALFWORD
);
11237 thumb_add_sub (str
, 1);
11244 skip_whitespace (str
);
11246 if (my_get_expression (&inst
.reloc
.exp
, &str
))
11249 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
11259 /* This is a pseudo-op of the form "adr rd, label" to be converted
11260 into a relative address of the form "add rd, pc, #label-.-4". */
11261 skip_whitespace (str
);
11263 /* Store Rd in temporary location inside instruction. */
11264 if ((reg
= reg_required_here (&str
, 4)) == FAIL
11265 || (reg
> 7) /* For Thumb reg must be r0..r7. */
11266 || skip_past_comma (&str
) == FAIL
11267 || my_get_expression (&inst
.reloc
.exp
, &str
))
11270 inst
.error
= BAD_ARGS
;
11274 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
11275 inst
.reloc
.exp
.X_add_number
-= 4; /* PC relative adjust. */
11276 inst
.reloc
.pc_rel
= 1;
11277 inst
.instruction
|= REG_PC
; /* Rd is already placed into the instruction. */
11283 insert_reg (r
, htab
)
11284 const struct reg_entry
*r
;
11285 struct hash_control
*htab
;
11287 int len
= strlen (r
->name
) + 2;
11288 char * buf
= (char *) xmalloc (len
);
11289 char * buf2
= (char *) xmalloc (len
);
11292 #ifdef REGISTER_PREFIX
11293 buf
[i
++] = REGISTER_PREFIX
;
11296 strcpy (buf
+ i
, r
->name
);
11298 for (i
= 0; buf
[i
]; i
++)
11299 buf2
[i
] = TOUPPER (buf
[i
]);
11303 hash_insert (htab
, buf
, (PTR
) r
);
11304 hash_insert (htab
, buf2
, (PTR
) r
);
11308 build_reg_hsh (map
)
11309 struct reg_map
*map
;
11311 const struct reg_entry
*r
;
11313 if ((map
->htab
= hash_new ()) == NULL
)
11314 as_fatal (_("virtual memory exhausted"));
11316 for (r
= map
->names
; r
->name
!= NULL
; r
++)
11317 insert_reg (r
, map
->htab
);
11321 insert_reg_alias (str
, regnum
, htab
)
11324 struct hash_control
*htab
;
11327 struct reg_entry
*new = xmalloc (sizeof (struct reg_entry
));
11328 const char *name
= xmalloc (strlen (str
) + 1);
11330 strcpy ((char *) name
, str
);
11333 new->number
= regnum
;
11334 new->builtin
= FALSE
;
11336 error
= hash_insert (htab
, name
, (PTR
) new);
11339 as_bad (_("failed to create an alias for %s, reason: %s"),
11341 free ((char *) name
);
11346 /* Look for the .req directive. This is of the form:
11348 new_register_name .req existing_register_name
11350 If we find one, or if it looks sufficiently like one that we want to
11351 handle any error here, return non-zero. Otherwise return zero. */
11353 create_register_alias (newname
, p
)
11361 skip_whitespace (q
);
11366 if (*q
&& !strncmp (q
, ".req ", 5))
11371 #ifndef IGNORE_OPCODE_CASE
11372 newname
= original_case_string
;
11374 copy_of_str
= newname
;
11377 skip_whitespace (q
);
11379 for (r
= q
; *r
!= '\0'; r
++)
11385 enum arm_reg_type new_type
, old_type
;
11390 old_type
= arm_reg_parse_any (q
);
11393 new_type
= arm_reg_parse_any (newname
);
11395 if (new_type
== REG_TYPE_MAX
)
11397 if (old_type
!= REG_TYPE_MAX
)
11399 old_regno
= arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
);
11400 insert_reg_alias (newname
, old_regno
,
11401 all_reg_maps
[old_type
].htab
);
11404 as_warn (_("register '%s' does not exist\n"), q
);
11406 else if (old_type
== REG_TYPE_MAX
)
11408 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
11413 /* Do not warn about redefinitions to the same alias. */
11414 if (new_type
!= old_type
11415 || (arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
)
11416 != arm_reg_parse (&q
, all_reg_maps
[new_type
].htab
)))
11417 as_warn (_("ignoring redefinition of register alias '%s'"),
11423 as_warn (_("ignoring incomplete .req pseuso op"));
11434 set_constant_flonums ()
11438 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
11439 if (atof_ieee ((char *) fp_const
[i
], 'x', fp_values
[i
]) == NULL
)
11443 /* Iterate over the base tables to create the instruction patterns. */
11445 build_arm_ops_hsh ()
11449 static struct obstack insn_obstack
;
11451 obstack_begin (&insn_obstack
, 4000);
11453 for (i
= 0; i
< sizeof (insns
) / sizeof (struct asm_opcode
); i
++)
11455 const struct asm_opcode
*insn
= insns
+ i
;
11457 if (insn
->cond_offset
!= 0)
11459 /* Insn supports conditional execution. Build the varaints
11460 and insert them in the hash table. */
11461 for (j
= 0; j
< sizeof (conds
) / sizeof (struct asm_cond
); j
++)
11463 unsigned len
= strlen (insn
->template);
11464 struct asm_opcode
*new;
11467 new = obstack_alloc (&insn_obstack
, sizeof (struct asm_opcode
));
11468 /* All condition codes are two characters. */
11469 template = obstack_alloc (&insn_obstack
, len
+ 3);
11471 strncpy (template, insn
->template, insn
->cond_offset
);
11472 strcpy (template + insn
->cond_offset
, conds
[j
].template);
11473 if (len
> insn
->cond_offset
)
11474 strcpy (template + insn
->cond_offset
+ 2,
11475 insn
->template + insn
->cond_offset
);
11476 new->template = template;
11477 new->cond_offset
= 0;
11478 new->variant
= insn
->variant
;
11479 new->parms
= insn
->parms
;
11480 new->value
= (insn
->value
& ~COND_MASK
) | conds
[j
].value
;
11482 hash_insert (arm_ops_hsh
, new->template, (PTR
) new);
11485 /* Finally, insert the unconditional insn in the table directly;
11486 no need to build a copy. */
11487 hash_insert (arm_ops_hsh
, insn
->template, (PTR
) insn
);
11491 #if 0 /* Suppressed - for now. */
11492 #if defined OBJ_ELF || defined OBJ_COFF
11495 #define arm_Note Elf_External_Note
11499 unsigned char namesz
[4]; /* Size of entry's owner string. */
11500 unsigned char descsz
[4]; /* Size of the note descriptor. */
11501 unsigned char type
[4]; /* Interpretation of the descriptor. */
11502 char name
[1]; /* Start of the name+desc data. */
11506 /* The description is kept to a fix sized in order to make updating
11507 it and merging it easier. */
11508 #define ARM_NOTE_DESCRIPTION_LENGTH 8
11511 arm_add_note (name
, description
, type
)
11513 const char * description
;
11516 arm_Note note ATTRIBUTE_UNUSED
;
11518 unsigned int name_len
;
11520 name_len
= (strlen (name
) + 1 + 3) & ~3;
11522 p
= frag_more (sizeof (note
.namesz
));
11523 md_number_to_chars (p
, (valueT
) name_len
, sizeof (note
.namesz
));
11525 p
= frag_more (sizeof (note
.descsz
));
11526 md_number_to_chars (p
, (valueT
) ARM_NOTE_DESCRIPTION_LENGTH
, sizeof (note
.descsz
));
11528 p
= frag_more (sizeof (note
.type
));
11529 md_number_to_chars (p
, (valueT
) type
, sizeof (note
.type
));
11531 p
= frag_more (name_len
);
11534 p
= frag_more (ARM_NOTE_DESCRIPTION_LENGTH
);
11535 strncpy (p
, description
, ARM_NOTE_DESCRIPTION_LENGTH
);
11536 frag_align (2, 0, 0);
11547 if ( (arm_ops_hsh
= hash_new ()) == NULL
11548 || (arm_tops_hsh
= hash_new ()) == NULL
11549 || (arm_cond_hsh
= hash_new ()) == NULL
11550 || (arm_shift_hsh
= hash_new ()) == NULL
11551 || (arm_psr_hsh
= hash_new ()) == NULL
)
11552 as_fatal (_("virtual memory exhausted"));
11554 build_arm_ops_hsh ();
11555 for (i
= 0; i
< sizeof (tinsns
) / sizeof (struct thumb_opcode
); i
++)
11556 hash_insert (arm_tops_hsh
, tinsns
[i
].template, (PTR
) (tinsns
+ i
));
11557 for (i
= 0; i
< sizeof (conds
) / sizeof (struct asm_cond
); i
++)
11558 hash_insert (arm_cond_hsh
, conds
[i
].template, (PTR
) (conds
+ i
));
11559 for (i
= 0; i
< sizeof (shift_names
) / sizeof (struct asm_shift_name
); i
++)
11560 hash_insert (arm_shift_hsh
, shift_names
[i
].name
, (PTR
) (shift_names
+ i
));
11561 for (i
= 0; i
< sizeof (psrs
) / sizeof (struct asm_psr
); i
++)
11562 hash_insert (arm_psr_hsh
, psrs
[i
].template, (PTR
) (psrs
+ i
));
11564 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
11565 build_reg_hsh (all_reg_maps
+ i
);
11567 set_constant_flonums ();
11569 /* Set the cpu variant based on the command-line options. We prefer
11570 -mcpu= over -march= if both are set (as for GCC); and we prefer
11571 -mfpu= over any other way of setting the floating point unit.
11572 Use of legacy options with new options are faulted. */
11573 if (legacy_cpu
!= -1)
11575 if (mcpu_cpu_opt
!= -1 || march_cpu_opt
!= -1)
11576 as_bad (_("use of old and new-style options to set CPU type"));
11578 mcpu_cpu_opt
= legacy_cpu
;
11580 else if (mcpu_cpu_opt
== -1)
11581 mcpu_cpu_opt
= march_cpu_opt
;
11583 if (legacy_fpu
!= -1)
11585 if (mfpu_opt
!= -1)
11586 as_bad (_("use of old and new-style options to set FPU type"));
11588 mfpu_opt
= legacy_fpu
;
11590 else if (mfpu_opt
== -1)
11592 #if !(defined (TE_LINUX) || defined (TE_NetBSD))
11593 /* Some environments specify a default FPU. If they don't, infer it
11594 from the processor. */
11595 if (mcpu_fpu_opt
!= -1)
11596 mfpu_opt
= mcpu_fpu_opt
;
11598 mfpu_opt
= march_fpu_opt
;
11600 mfpu_opt
= FPU_DEFAULT
;
11604 if (mfpu_opt
== -1)
11606 if (mcpu_cpu_opt
== -1)
11607 mfpu_opt
= FPU_DEFAULT
;
11608 else if (mcpu_cpu_opt
& ARM_EXT_V5
)
11609 mfpu_opt
= FPU_ARCH_VFP_V2
;
11611 mfpu_opt
= FPU_ARCH_FPA
;
11614 if (mcpu_cpu_opt
== -1)
11615 mcpu_cpu_opt
= CPU_DEFAULT
;
11617 cpu_variant
= mcpu_cpu_opt
| mfpu_opt
;
11620 unsigned int flags
= 0;
11622 #if defined OBJ_ELF
11623 flags
= meabi_flags
;
11625 switch (meabi_flags
)
11627 case EF_ARM_EABI_UNKNOWN
:
11629 #if defined OBJ_COFF || defined OBJ_ELF
11630 /* Set the flags in the private structure. */
11631 if (uses_apcs_26
) flags
|= F_APCS26
;
11632 if (support_interwork
) flags
|= F_INTERWORK
;
11633 if (uses_apcs_float
) flags
|= F_APCS_FLOAT
;
11634 if (pic_code
) flags
|= F_PIC
;
11635 if ((cpu_variant
& FPU_ANY
) == FPU_NONE
11636 || (cpu_variant
& FPU_ANY
) == FPU_ARCH_VFP
) /* VFP layout only. */
11637 flags
|= F_SOFT_FLOAT
;
11639 switch (mfloat_abi_opt
)
11641 case ARM_FLOAT_ABI_SOFT
:
11642 case ARM_FLOAT_ABI_SOFTFP
:
11643 flags
|= F_SOFT_FLOAT
;
11646 case ARM_FLOAT_ABI_HARD
:
11647 if (flags
& F_SOFT_FLOAT
)
11648 as_bad (_("hard-float conflicts with specified fpu"));
11652 /* Using VFP conventions (even if soft-float). */
11653 if (cpu_variant
& FPU_VFP_EXT_NONE
)
11654 flags
|= F_VFP_FLOAT
;
11656 #if defined OBJ_ELF
11657 if (cpu_variant
& FPU_ARCH_MAVERICK
)
11658 flags
|= EF_ARM_MAVERICK_FLOAT
;
11661 case EF_ARM_EABI_VER3
:
11662 /* No additional flags to set. */
11669 #if defined OBJ_COFF || defined OBJ_ELF
11670 bfd_set_private_flags (stdoutput
, flags
);
11672 /* We have run out flags in the COFF header to encode the
11673 status of ATPCS support, so instead we create a dummy,
11674 empty, debug section called .arm.atpcs. */
11679 sec
= bfd_make_section (stdoutput
, ".arm.atpcs");
11683 bfd_set_section_flags
11684 (stdoutput
, sec
, SEC_READONLY
| SEC_DEBUGGING
/* | SEC_HAS_CONTENTS */);
11685 bfd_set_section_size (stdoutput
, sec
, 0);
11686 bfd_set_section_contents (stdoutput
, sec
, NULL
, 0, 0);
11692 /* Record the CPU type as well. */
11693 switch (cpu_variant
& ARM_CPU_MASK
)
11696 mach
= bfd_mach_arm_2
;
11699 case ARM_3
: /* Also ARM_250. */
11700 mach
= bfd_mach_arm_2a
;
11703 case ARM_6
: /* Also ARM_7. */
11704 mach
= bfd_mach_arm_3
;
11708 mach
= bfd_mach_arm_unknown
;
11712 /* Catch special cases. */
11713 if (cpu_variant
& ARM_CEXT_IWMMXT
)
11714 mach
= bfd_mach_arm_iWMMXt
;
11715 else if (cpu_variant
& ARM_CEXT_XSCALE
)
11716 mach
= bfd_mach_arm_XScale
;
11717 else if (cpu_variant
& ARM_CEXT_MAVERICK
)
11718 mach
= bfd_mach_arm_ep9312
;
11719 else if (cpu_variant
& ARM_EXT_V5E
)
11720 mach
= bfd_mach_arm_5TE
;
11721 else if (cpu_variant
& ARM_EXT_V5
)
11723 if (cpu_variant
& ARM_EXT_V4T
)
11724 mach
= bfd_mach_arm_5T
;
11726 mach
= bfd_mach_arm_5
;
11728 else if (cpu_variant
& ARM_EXT_V4
)
11730 if (cpu_variant
& ARM_EXT_V4T
)
11731 mach
= bfd_mach_arm_4T
;
11733 mach
= bfd_mach_arm_4
;
11735 else if (cpu_variant
& ARM_EXT_V3M
)
11736 mach
= bfd_mach_arm_3M
;
11738 #if 0 /* Suppressed - for now. */
11739 #if defined (OBJ_ELF) || defined (OBJ_COFF)
11741 /* Create a .note section to fully identify this arm binary. */
11743 #define NOTE_ARCH_STRING "arch: "
11745 #if defined OBJ_COFF && ! defined NT_VERSION
11746 #define NT_VERSION 1
11751 segT current_seg
= now_seg
;
11752 subsegT current_subseg
= now_subseg
;
11753 asection
* arm_arch
;
11754 const char * arch_string
;
11756 arm_arch
= bfd_make_section_old_way (stdoutput
, ARM_NOTE_SECTION
);
11759 bfd_set_section_flags (stdoutput
, arm_arch
,
11760 SEC_DATA
| SEC_ALLOC
| SEC_LOAD
| SEC_LINK_ONCE \
11761 | SEC_HAS_CONTENTS
);
11763 bfd_set_section_flags (stdoutput
, arm_arch
,
11764 SEC_READONLY
| SEC_HAS_CONTENTS
);
11766 arm_arch
->output_section
= arm_arch
;
11767 subseg_set (arm_arch
, 0);
11772 case bfd_mach_arm_unknown
: arch_string
= "unknown"; break;
11773 case bfd_mach_arm_2
: arch_string
= "armv2"; break;
11774 case bfd_mach_arm_2a
: arch_string
= "armv2a"; break;
11775 case bfd_mach_arm_3
: arch_string
= "armv3"; break;
11776 case bfd_mach_arm_3M
: arch_string
= "armv3M"; break;
11777 case bfd_mach_arm_4
: arch_string
= "armv4"; break;
11778 case bfd_mach_arm_4T
: arch_string
= "armv4t"; break;
11779 case bfd_mach_arm_5
: arch_string
= "armv5"; break;
11780 case bfd_mach_arm_5T
: arch_string
= "armv5t"; break;
11781 case bfd_mach_arm_5TE
: arch_string
= "armv5te"; break;
11782 case bfd_mach_arm_XScale
: arch_string
= "XScale"; break;
11783 case bfd_mach_arm_ep9312
: arch_string
= "ep9312"; break;
11784 case bfd_mach_arm_iWMMXt
: arch_string
= "iWMMXt"; break;
11787 arm_add_note (NOTE_ARCH_STRING
, arch_string
, NT_ARCH
);
11789 subseg_set (current_seg
, current_subseg
);
11792 #endif /* Suppressed code. */
11794 bfd_set_arch_mach (stdoutput
, TARGET_ARCH
, mach
);
11797 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11798 for use in the a.out file, and stores them in the array pointed to by buf.
11799 This knows about the endian-ness of the target machine and does
11800 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11801 2 (short) and 4 (long) Floating numbers are put out as a series of
11802 LITTLENUMS (shorts, here at least). */
11805 md_number_to_chars (buf
, val
, n
)
11810 if (target_big_endian
)
11811 number_to_chars_bigendian (buf
, val
, n
);
11813 number_to_chars_littleendian (buf
, val
, n
);
11817 md_chars_to_number (buf
, n
)
11822 unsigned char * where
= (unsigned char *) buf
;
11824 if (target_big_endian
)
11829 result
|= (*where
++ & 255);
11837 result
|= (where
[n
] & 255);
11844 /* Turn a string in input_line_pointer into a floating point constant
11845 of type TYPE, and store the appropriate bytes in *LITP. The number
11846 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11847 returned, or NULL on OK.
11849 Note that fp constants aren't represent in the normal way on the ARM.
11850 In big endian mode, things are as expected. However, in little endian
11851 mode fp constants are big-endian word-wise, and little-endian byte-wise
11852 within the words. For example, (double) 1.1 in big endian mode is
11853 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11854 the byte sequence 99 99 f1 3f 9a 99 99 99.
11856 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11859 md_atof (type
, litP
, sizeP
)
11865 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
11897 return _("bad call to MD_ATOF()");
11900 t
= atof_ieee (input_line_pointer
, type
, words
);
11902 input_line_pointer
= t
;
11905 if (target_big_endian
)
11907 for (i
= 0; i
< prec
; i
++)
11909 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
11915 if (cpu_variant
& FPU_ARCH_VFP
)
11916 for (i
= prec
- 1; i
>= 0; i
--)
11918 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
11922 /* For a 4 byte float the order of elements in `words' is 1 0.
11923 For an 8 byte float the order is 1 0 3 2. */
11924 for (i
= 0; i
< prec
; i
+= 2)
11926 md_number_to_chars (litP
, (valueT
) words
[i
+ 1], 2);
11927 md_number_to_chars (litP
+ 2, (valueT
) words
[i
], 2);
11935 /* The knowledge of the PC's pipeline offset is built into the insns
11939 md_pcrel_from (fixP
)
11943 && S_GET_SEGMENT (fixP
->fx_addsy
) == undefined_section
11944 && fixP
->fx_subsy
== NULL
)
11947 if (fixP
->fx_pcrel
&& (fixP
->fx_r_type
== BFD_RELOC_ARM_THUMB_ADD
))
11949 /* PC relative addressing on the Thumb is slightly odd
11950 as the bottom two bits of the PC are forced to zero
11951 for the calculation. */
11952 return (fixP
->fx_where
+ fixP
->fx_frag
->fr_address
) & ~3;
11956 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
11957 so we un-adjust here to compensate for the accommodation. */
11958 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
+ 8;
11960 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
11964 /* Round up a section size to the appropriate boundary. */
11967 md_section_align (segment
, size
)
11968 segT segment ATTRIBUTE_UNUSED
;
11974 /* Round all sects to multiple of 4. */
11975 return (size
+ 3) & ~3;
11979 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
11980 Otherwise we have no need to default values of symbols. */
11983 md_undefined_symbol (name
)
11984 char * name ATTRIBUTE_UNUSED
;
11987 if (name
[0] == '_' && name
[1] == 'G'
11988 && streq (name
, GLOBAL_OFFSET_TABLE_NAME
))
11992 if (symbol_find (name
))
11993 as_bad ("GOT already in the symbol table");
11995 GOT_symbol
= symbol_new (name
, undefined_section
,
11996 (valueT
) 0, & zero_address_frag
);
12006 /* arm_reg_parse () := if it looks like a register, return its token and
12007 advance the pointer. */
12010 arm_reg_parse (ccp
, htab
)
12011 register char ** ccp
;
12012 struct hash_control
*htab
;
12014 char * start
= * ccp
;
12017 struct reg_entry
* reg
;
12019 #ifdef REGISTER_PREFIX
12020 if (*start
!= REGISTER_PREFIX
)
12025 #ifdef OPTIONAL_REGISTER_PREFIX
12026 if (*p
== OPTIONAL_REGISTER_PREFIX
)
12030 if (!ISALPHA (*p
) || !is_name_beginner (*p
))
12034 while (ISALPHA (c
) || ISDIGIT (c
) || c
== '_')
12038 reg
= (struct reg_entry
*) hash_find (htab
, start
);
12044 return reg
->number
;
12050 /* Search for the following register name in each of the possible reg name
12051 tables. Return the classification if found, or REG_TYPE_MAX if not
12053 static enum arm_reg_type
12054 arm_reg_parse_any (cp
)
12059 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
12060 if (arm_reg_parse (&cp
, all_reg_maps
[i
].htab
) != FAIL
)
12061 return (enum arm_reg_type
) i
;
12063 return REG_TYPE_MAX
;
12067 md_apply_fix3 (fixP
, valP
, seg
)
12072 offsetT value
= * valP
;
12074 unsigned int newimm
;
12075 unsigned long temp
;
12077 char * buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
12078 arm_fix_data
* arm_data
= (arm_fix_data
*) fixP
->tc_fix_data
;
12080 assert (fixP
->fx_r_type
< BFD_RELOC_UNUSED
);
12082 /* Note whether this will delete the relocation. */
12084 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
12085 doesn't work fully.) */
12086 if ((fixP
->fx_addsy
== 0 || symbol_constant_p (fixP
->fx_addsy
))
12087 && !fixP
->fx_pcrel
)
12089 if (fixP
->fx_addsy
== 0 && !fixP
->fx_pcrel
)
12093 /* If this symbol is in a different section then we need to leave it for
12094 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
12095 so we have to undo it's effects here. */
12096 if (fixP
->fx_pcrel
)
12098 if (fixP
->fx_addsy
!= NULL
12099 && S_IS_DEFINED (fixP
->fx_addsy
)
12100 && S_GET_SEGMENT (fixP
->fx_addsy
) != seg
)
12103 && (fixP
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
12104 || fixP
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
12108 value
+= md_pcrel_from (fixP
);
12112 /* Remember value for emit_reloc. */
12113 fixP
->fx_addnumber
= value
;
12115 switch (fixP
->fx_r_type
)
12117 case BFD_RELOC_ARM_IMMEDIATE
:
12118 /* We claim that this fixup has been processed here,
12119 even if in fact we generate an error because we do
12120 not have a reloc for it, so tc_gen_reloc will reject it. */
12124 && ! S_IS_DEFINED (fixP
->fx_addsy
))
12126 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12127 _("undefined symbol %s used as an immediate value"),
12128 S_GET_NAME (fixP
->fx_addsy
));
12132 newimm
= validate_immediate (value
);
12133 temp
= md_chars_to_number (buf
, INSN_SIZE
);
12135 /* If the instruction will fail, see if we can fix things up by
12136 changing the opcode. */
12137 if (newimm
== (unsigned int) FAIL
12138 && (newimm
= negate_data_op (&temp
, value
)) == (unsigned int) FAIL
)
12140 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12141 _("invalid constant (%lx) after fixup"),
12142 (unsigned long) value
);
12146 newimm
|= (temp
& 0xfffff000);
12147 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
12150 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
12152 unsigned int highpart
= 0;
12153 unsigned int newinsn
= 0xe1a00000; /* nop. */
12155 newimm
= validate_immediate (value
);
12156 temp
= md_chars_to_number (buf
, INSN_SIZE
);
12158 /* If the instruction will fail, see if we can fix things up by
12159 changing the opcode. */
12160 if (newimm
== (unsigned int) FAIL
12161 && (newimm
= negate_data_op (& temp
, value
)) == (unsigned int) FAIL
)
12163 /* No ? OK - try using two ADD instructions to generate
12165 newimm
= validate_immediate_twopart (value
, & highpart
);
12167 /* Yes - then make sure that the second instruction is
12169 if (newimm
!= (unsigned int) FAIL
)
12171 /* Still No ? Try using a negated value. */
12172 else if ((newimm
= validate_immediate_twopart (- value
, & highpart
)) != (unsigned int) FAIL
)
12173 temp
= newinsn
= (temp
& OPCODE_MASK
) | OPCODE_SUB
<< DATA_OP_SHIFT
;
12174 /* Otherwise - give up. */
12177 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12178 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
12183 /* Replace the first operand in the 2nd instruction (which
12184 is the PC) with the destination register. We have
12185 already added in the PC in the first instruction and we
12186 do not want to do it again. */
12187 newinsn
&= ~ 0xf0000;
12188 newinsn
|= ((newinsn
& 0x0f000) << 4);
12191 newimm
|= (temp
& 0xfffff000);
12192 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
12194 highpart
|= (newinsn
& 0xfffff000);
12195 md_number_to_chars (buf
+ INSN_SIZE
, (valueT
) highpart
, INSN_SIZE
);
12199 case BFD_RELOC_ARM_OFFSET_IMM
:
12205 if (validate_offset_imm (value
, 0) == FAIL
)
12207 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12208 _("bad immediate value for offset (%ld)"),
12213 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12214 newval
&= 0xff7ff000;
12215 newval
|= value
| (sign
? INDEX_UP
: 0);
12216 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12219 case BFD_RELOC_ARM_OFFSET_IMM8
:
12220 case BFD_RELOC_ARM_HWLITERAL
:
12226 if (validate_offset_imm (value
, 1) == FAIL
)
12228 if (fixP
->fx_r_type
== BFD_RELOC_ARM_HWLITERAL
)
12229 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12230 _("invalid literal constant: pool needs to be closer"));
12232 as_bad (_("bad immediate value for half-word offset (%ld)"),
12237 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12238 newval
&= 0xff7ff0f0;
12239 newval
|= ((value
>> 4) << 8) | (value
& 0xf) | (sign
? INDEX_UP
: 0);
12240 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12243 case BFD_RELOC_ARM_LITERAL
:
12249 if (validate_offset_imm (value
, 0) == FAIL
)
12251 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12252 _("invalid literal constant: pool needs to be closer"));
12256 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12257 newval
&= 0xff7ff000;
12258 newval
|= value
| (sign
? INDEX_UP
: 0);
12259 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12262 case BFD_RELOC_ARM_SHIFT_IMM
:
12263 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12264 if (((unsigned long) value
) > 32
12266 && (((newval
& 0x60) == 0) || (newval
& 0x60) == 0x60)))
12268 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12269 _("shift expression is too large"));
12274 /* Shifts of zero must be done as lsl. */
12276 else if (value
== 32)
12278 newval
&= 0xfffff07f;
12279 newval
|= (value
& 0x1f) << 7;
12280 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12283 case BFD_RELOC_ARM_SWI
:
12284 if (arm_data
->thumb_mode
)
12286 if (((unsigned long) value
) > 0xff)
12287 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12288 _("invalid swi expression"));
12289 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xff00;
12291 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12295 if (((unsigned long) value
) > 0x00ffffff)
12296 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12297 _("invalid swi expression"));
12298 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff000000;
12300 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12304 case BFD_RELOC_ARM_MULTI
:
12305 if (((unsigned long) value
) > 0xffff)
12306 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12307 _("invalid expression in load/store multiple"));
12308 newval
= value
| md_chars_to_number (buf
, INSN_SIZE
);
12309 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12312 case BFD_RELOC_ARM_PCREL_BRANCH
:
12313 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12315 /* Sign-extend a 24-bit number. */
12316 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
12320 value
= fixP
->fx_offset
;
12323 /* We are going to store value (shifted right by two) in the
12324 instruction, in a 24 bit, signed field. Thus we need to check
12325 that none of the top 8 bits of the shifted value (top 7 bits of
12326 the unshifted, unsigned value) are set, or that they are all set. */
12327 if ((value
& ~ ((offsetT
) 0x1ffffff)) != 0
12328 && ((value
& ~ ((offsetT
) 0x1ffffff)) != ~ ((offsetT
) 0x1ffffff)))
12331 /* Normally we would be stuck at this point, since we cannot store
12332 the absolute address that is the destination of the branch in the
12333 24 bits of the branch instruction. If however, we happen to know
12334 that the destination of the branch is in the same section as the
12335 branch instruction itself, then we can compute the relocation for
12336 ourselves and not have to bother the linker with it.
12338 FIXME: The tests for OBJ_ELF and ! target_oabi are only here
12339 because I have not worked out how to do this for OBJ_COFF or
12342 && fixP
->fx_addsy
!= NULL
12343 && S_IS_DEFINED (fixP
->fx_addsy
)
12344 && S_GET_SEGMENT (fixP
->fx_addsy
) == seg
)
12346 /* Get pc relative value to go into the branch. */
12349 /* Permit a backward branch provided that enough bits
12350 are set. Allow a forwards branch, provided that
12351 enough bits are clear. */
12352 if ( (value
& ~ ((offsetT
) 0x1ffffff)) == ~ ((offsetT
) 0x1ffffff)
12353 || (value
& ~ ((offsetT
) 0x1ffffff)) == 0)
12357 if (! fixP
->fx_done
)
12359 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12360 _("GAS can't handle same-section branch dest >= 0x04000000"));
12364 value
+= SEXT24 (newval
);
12366 if ( (value
& ~ ((offsetT
) 0xffffff)) != 0
12367 && ((value
& ~ ((offsetT
) 0xffffff)) != ~ ((offsetT
) 0xffffff)))
12368 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12369 _("out of range branch"));
12371 newval
= (value
& 0x00ffffff) | (newval
& 0xff000000);
12372 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12375 case BFD_RELOC_ARM_PCREL_BLX
:
12378 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12382 value
= fixP
->fx_offset
;
12384 hbit
= (value
>> 1) & 1;
12385 value
= (value
>> 2) & 0x00ffffff;
12386 value
= (value
+ (newval
& 0x00ffffff)) & 0x00ffffff;
12387 newval
= value
| (newval
& 0xfe000000) | (hbit
<< 24);
12388 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12392 case BFD_RELOC_THUMB_PCREL_BRANCH9
: /* Conditional branch. */
12393 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12395 addressT diff
= (newval
& 0xff) << 1;
12400 if ((value
& ~0xff) && ((value
& ~0xff) != ~0xff))
12401 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12402 _("branch out of range"));
12403 newval
= (newval
& 0xff00) | ((value
& 0x1ff) >> 1);
12405 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12408 case BFD_RELOC_THUMB_PCREL_BRANCH12
: /* Unconditional branch. */
12409 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12411 addressT diff
= (newval
& 0x7ff) << 1;
12416 if ((value
& ~0x7ff) && ((value
& ~0x7ff) != ~0x7ff))
12417 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12418 _("branch out of range"));
12419 newval
= (newval
& 0xf800) | ((value
& 0xfff) >> 1);
12421 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12424 case BFD_RELOC_THUMB_PCREL_BLX
:
12425 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
12430 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12431 newval2
= md_chars_to_number (buf
+ THUMB_SIZE
, THUMB_SIZE
);
12432 diff
= ((newval
& 0x7ff) << 12) | ((newval2
& 0x7ff) << 1);
12433 if (diff
& 0x400000)
12436 value
= fixP
->fx_offset
;
12440 if ((value
& ~0x3fffff) && ((value
& ~0x3fffff) != ~0x3fffff))
12441 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12442 _("branch with link out of range"));
12444 newval
= (newval
& 0xf800) | ((value
& 0x7fffff) >> 12);
12445 newval2
= (newval2
& 0xf800) | ((value
& 0xfff) >> 1);
12446 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
)
12447 /* For a BLX instruction, make sure that the relocation is rounded up
12448 to a word boundary. This follows the semantics of the instruction
12449 which specifies that bit 1 of the target address will come from bit
12450 1 of the base address. */
12451 newval2
= (newval2
+ 1) & ~ 1;
12452 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12453 md_number_to_chars (buf
+ THUMB_SIZE
, newval2
, THUMB_SIZE
);
12458 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
12459 md_number_to_chars (buf
, value
, 1);
12461 else if (!target_oabi
)
12463 value
= fixP
->fx_offset
;
12464 md_number_to_chars (buf
, value
, 1);
12470 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
12471 md_number_to_chars (buf
, value
, 2);
12473 else if (!target_oabi
)
12475 value
= fixP
->fx_offset
;
12476 md_number_to_chars (buf
, value
, 2);
12482 case BFD_RELOC_ARM_GOT32
:
12483 case BFD_RELOC_ARM_GOTOFF
:
12484 md_number_to_chars (buf
, 0, 4);
12488 case BFD_RELOC_RVA
:
12490 case BFD_RELOC_ARM_RELABS32
:
12491 case BFD_RELOC_ARM_ROSEGREL32
:
12492 case BFD_RELOC_ARM_SBREL32
:
12493 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
12494 md_number_to_chars (buf
, value
, 4);
12496 else if (!target_oabi
)
12498 value
= fixP
->fx_offset
;
12499 md_number_to_chars (buf
, value
, 4);
12505 case BFD_RELOC_ARM_PLT32
:
12506 /* It appears the instruction is fully prepared at this point. */
12510 case BFD_RELOC_ARM_CP_OFF_IMM
:
12512 if (value
< -1023 || value
> 1023 || (value
& 3))
12513 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12514 _("illegal value for co-processor offset"));
12517 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
12518 newval
|= (value
>> 2) | (sign
? INDEX_UP
: 0);
12519 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12522 case BFD_RELOC_ARM_CP_OFF_IMM_S2
:
12524 if (value
< -255 || value
> 255)
12525 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12526 _("Illegal value for co-processor offset"));
12529 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
12530 newval
|= value
| (sign
? INDEX_UP
: 0);
12531 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12534 case BFD_RELOC_ARM_THUMB_OFFSET
:
12535 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12536 /* Exactly what ranges, and where the offset is inserted depends
12537 on the type of instruction, we can establish this from the
12539 switch (newval
>> 12)
12541 case 4: /* PC load. */
12542 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
12543 forced to zero for these loads, so we will need to round
12544 up the offset if the instruction address is not word
12545 aligned (since the final address produced must be, and
12546 we can only describe word-aligned immediate offsets). */
12548 if ((fixP
->fx_frag
->fr_address
+ fixP
->fx_where
+ value
) & 3)
12549 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12550 _("invalid offset, target not word aligned (0x%08X)"),
12551 (unsigned int) (fixP
->fx_frag
->fr_address
12552 + fixP
->fx_where
+ value
));
12554 if ((value
+ 2) & ~0x3fe)
12555 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12556 _("invalid offset, value too big (0x%08lX)"),
12559 /* Round up, since pc will be rounded down. */
12560 newval
|= (value
+ 2) >> 2;
12563 case 9: /* SP load/store. */
12564 if (value
& ~0x3fc)
12565 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12566 _("invalid offset, value too big (0x%08lX)"),
12568 newval
|= value
>> 2;
12571 case 6: /* Word load/store. */
12573 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12574 _("invalid offset, value too big (0x%08lX)"),
12576 newval
|= value
<< 4; /* 6 - 2. */
12579 case 7: /* Byte load/store. */
12581 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12582 _("invalid offset, value too big (0x%08lX)"),
12584 newval
|= value
<< 6;
12587 case 8: /* Halfword load/store. */
12589 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12590 _("invalid offset, value too big (0x%08lX)"),
12592 newval
|= value
<< 5; /* 6 - 1. */
12596 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12597 "Unable to process relocation for thumb opcode: %lx",
12598 (unsigned long) newval
);
12601 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12604 case BFD_RELOC_ARM_THUMB_ADD
:
12605 /* This is a complicated relocation, since we use it for all of
12606 the following immediate relocations:
12610 9bit ADD/SUB SP word-aligned
12611 10bit ADD PC/SP word-aligned
12613 The type of instruction being processed is encoded in the
12620 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12622 int rd
= (newval
>> 4) & 0xf;
12623 int rs
= newval
& 0xf;
12624 int subtract
= newval
& 0x8000;
12628 if (value
& ~0x1fc)
12629 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12630 _("invalid immediate for stack address calculation"));
12631 newval
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
12632 newval
|= value
>> 2;
12634 else if (rs
== REG_PC
|| rs
== REG_SP
)
12638 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12639 _("invalid immediate for address calculation (value = 0x%08lX)"),
12640 (unsigned long) value
);
12641 newval
= (rs
== REG_PC
? T_OPCODE_ADD_PC
: T_OPCODE_ADD_SP
);
12643 newval
|= value
>> 2;
12648 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12649 _("invalid 8bit immediate"));
12650 newval
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
12651 newval
|= (rd
<< 8) | value
;
12656 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12657 _("invalid 3bit immediate"));
12658 newval
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
12659 newval
|= rd
| (rs
<< 3) | (value
<< 6);
12662 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12665 case BFD_RELOC_ARM_THUMB_IMM
:
12666 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12667 switch (newval
>> 11)
12669 case 0x04: /* 8bit immediate MOV. */
12670 case 0x05: /* 8bit immediate CMP. */
12671 if (value
< 0 || value
> 255)
12672 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12673 _("invalid immediate: %ld is too large"),
12681 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12684 case BFD_RELOC_ARM_THUMB_SHIFT
:
12685 /* 5bit shift value (0..31). */
12686 if (value
< 0 || value
> 31)
12687 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12688 _("illegal Thumb shift value: %ld"), (long) value
);
12689 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xf03f;
12690 newval
|= value
<< 6;
12691 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12694 case BFD_RELOC_VTABLE_INHERIT
:
12695 case BFD_RELOC_VTABLE_ENTRY
:
12699 case BFD_RELOC_NONE
:
12701 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12702 _("bad relocation fixup type (%d)"), fixP
->fx_r_type
);
12706 /* Translate internal representation of relocation info to BFD target
12710 tc_gen_reloc (section
, fixp
)
12711 asection
* section ATTRIBUTE_UNUSED
;
12715 bfd_reloc_code_real_type code
;
12717 reloc
= (arelent
*) xmalloc (sizeof (arelent
));
12719 reloc
->sym_ptr_ptr
= (asymbol
**) xmalloc (sizeof (asymbol
*));
12720 *reloc
->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
12721 reloc
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
12723 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12725 if (fixp
->fx_pcrel
== 0)
12726 reloc
->addend
= fixp
->fx_offset
;
12728 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
12729 #else /* OBJ_ELF */
12730 reloc
->addend
= fixp
->fx_offset
;
12733 switch (fixp
->fx_r_type
)
12736 if (fixp
->fx_pcrel
)
12738 code
= BFD_RELOC_8_PCREL
;
12743 if (fixp
->fx_pcrel
)
12745 code
= BFD_RELOC_16_PCREL
;
12750 if (fixp
->fx_pcrel
)
12752 code
= BFD_RELOC_32_PCREL
;
12756 case BFD_RELOC_ARM_PCREL_BRANCH
:
12757 case BFD_RELOC_ARM_PCREL_BLX
:
12758 case BFD_RELOC_RVA
:
12759 case BFD_RELOC_THUMB_PCREL_BRANCH9
:
12760 case BFD_RELOC_THUMB_PCREL_BRANCH12
:
12761 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
12762 case BFD_RELOC_THUMB_PCREL_BLX
:
12763 case BFD_RELOC_VTABLE_ENTRY
:
12764 case BFD_RELOC_VTABLE_INHERIT
:
12765 code
= fixp
->fx_r_type
;
12768 case BFD_RELOC_ARM_LITERAL
:
12769 case BFD_RELOC_ARM_HWLITERAL
:
12770 /* If this is called then the a literal has
12771 been referenced across a section boundary. */
12772 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12773 _("literal referenced across section boundary"));
12777 case BFD_RELOC_ARM_GOT32
:
12778 case BFD_RELOC_ARM_GOTOFF
:
12779 case BFD_RELOC_ARM_PLT32
:
12780 case BFD_RELOC_ARM_RELABS32
:
12781 case BFD_RELOC_ARM_ROSEGREL32
:
12782 case BFD_RELOC_ARM_SBREL32
:
12783 code
= fixp
->fx_r_type
;
12787 case BFD_RELOC_ARM_IMMEDIATE
:
12788 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12789 _("internal relocation (type: IMMEDIATE) not fixed up"));
12792 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
12793 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12794 _("ADRL used for a symbol not defined in the same file"));
12797 case BFD_RELOC_ARM_OFFSET_IMM
:
12798 if (fixp
->fx_addsy
!= NULL
12799 && !S_IS_DEFINED (fixp
->fx_addsy
)
12800 && S_IS_LOCAL (fixp
->fx_addsy
))
12802 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12803 _("undefined local label `%s'"),
12804 S_GET_NAME (fixp
->fx_addsy
));
12808 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12809 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
12816 switch (fixp
->fx_r_type
)
12818 case BFD_RELOC_ARM_OFFSET_IMM8
: type
= "OFFSET_IMM8"; break;
12819 case BFD_RELOC_ARM_SHIFT_IMM
: type
= "SHIFT_IMM"; break;
12820 case BFD_RELOC_ARM_SWI
: type
= "SWI"; break;
12821 case BFD_RELOC_ARM_MULTI
: type
= "MULTI"; break;
12822 case BFD_RELOC_ARM_CP_OFF_IMM
: type
= "CP_OFF_IMM"; break;
12823 case BFD_RELOC_ARM_THUMB_ADD
: type
= "THUMB_ADD"; break;
12824 case BFD_RELOC_ARM_THUMB_SHIFT
: type
= "THUMB_SHIFT"; break;
12825 case BFD_RELOC_ARM_THUMB_IMM
: type
= "THUMB_IMM"; break;
12826 case BFD_RELOC_ARM_THUMB_OFFSET
: type
= "THUMB_OFFSET"; break;
12827 default: type
= _("<unknown>"); break;
12829 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12830 _("cannot represent %s relocation in this object file format"),
12837 if ((code
== BFD_RELOC_32_PCREL
|| code
== BFD_RELOC_32
)
12839 && fixp
->fx_addsy
== GOT_symbol
)
12841 code
= BFD_RELOC_ARM_GOTPC
;
12842 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
12846 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, code
);
12848 if (reloc
->howto
== NULL
)
12850 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12851 _("cannot represent %s relocation in this object file format"),
12852 bfd_get_reloc_code_name (code
));
12856 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12857 vtable entry to be used in the relocation's section offset. */
12858 if (fixp
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
12859 reloc
->address
= fixp
->fx_offset
;
12865 md_estimate_size_before_relax (fragP
, segtype
)
12866 fragS
* fragP ATTRIBUTE_UNUSED
;
12867 segT segtype ATTRIBUTE_UNUSED
;
12869 as_fatal (_("md_estimate_size_before_relax\n"));
12881 as_bad ("%s -- `%s'", inst
.error
, str
);
12885 to
= frag_more (inst
.size
);
12887 if (thumb_mode
&& (inst
.size
> THUMB_SIZE
))
12889 assert (inst
.size
== (2 * THUMB_SIZE
));
12890 md_number_to_chars (to
, inst
.instruction
>> 16, THUMB_SIZE
);
12891 md_number_to_chars (to
+ THUMB_SIZE
, inst
.instruction
, THUMB_SIZE
);
12893 else if (inst
.size
> INSN_SIZE
)
12895 assert (inst
.size
== (2 * INSN_SIZE
));
12896 md_number_to_chars (to
, inst
.instruction
, INSN_SIZE
);
12897 md_number_to_chars (to
+ INSN_SIZE
, inst
.instruction
, INSN_SIZE
);
12900 md_number_to_chars (to
, inst
.instruction
, inst
.size
);
12902 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
12903 fix_new_arm (frag_now
, to
- frag_now
->fr_literal
,
12904 inst
.size
, & inst
.reloc
.exp
, inst
.reloc
.pc_rel
,
12908 dwarf2_emit_insn (inst
.size
);
12920 /* Align the instruction.
12921 This may not be the right thing to do but ... */
12926 /* Align the previous label if needed. */
12927 if (last_label_seen
!= NULL
)
12929 symbol_set_frag (last_label_seen
, frag_now
);
12930 S_SET_VALUE (last_label_seen
, (valueT
) frag_now_fix ());
12931 S_SET_SEGMENT (last_label_seen
, now_seg
);
12934 memset (&inst
, '\0', sizeof (inst
));
12935 inst
.reloc
.type
= BFD_RELOC_NONE
;
12937 skip_whitespace (str
);
12939 /* Scan up to the end of the op-code, which must end in white space or
12941 for (start
= p
= str
; *p
!= '\0'; p
++)
12947 as_bad (_("no operator -- statement `%s'\n"), str
);
12953 const struct thumb_opcode
* opcode
;
12957 opcode
= (const struct thumb_opcode
*) hash_find (arm_tops_hsh
, str
);
12962 /* Check that this instruction is supported for this CPU. */
12963 if (thumb_mode
== 1 && (opcode
->variant
& cpu_variant
) == 0)
12965 as_bad (_("selected processor does not support `%s'"), str
);
12969 mapping_state (MAP_THUMB
);
12970 inst
.instruction
= opcode
->value
;
12971 inst
.size
= opcode
->size
;
12972 (*opcode
->parms
) (p
);
12979 const struct asm_opcode
* opcode
;
12983 opcode
= (const struct asm_opcode
*) hash_find (arm_ops_hsh
, str
);
12988 /* Check that this instruction is supported for this CPU. */
12989 if ((opcode
->variant
& cpu_variant
) == 0)
12991 as_bad (_("selected processor does not support `%s'"), str
);
12995 mapping_state (MAP_ARM
);
12996 inst
.instruction
= opcode
->value
;
12997 inst
.size
= INSN_SIZE
;
12998 (*opcode
->parms
) (p
);
13004 /* It wasn't an instruction, but it might be a register alias of the form
13006 if (create_register_alias (str
, p
))
13009 as_bad (_("bad instruction `%s'"), start
);
13013 Invocation line includes a switch not recognized by the base assembler.
13014 See if it's a processor-specific option.
13016 This routine is somewhat complicated by the need for backwards
13017 compatibility (since older releases of gcc can't be changed).
13018 The new options try to make the interface as compatible as
13021 New options (supported) are:
13023 -mcpu=<cpu name> Assemble for selected processor
13024 -march=<architecture name> Assemble for selected architecture
13025 -mfpu=<fpu architecture> Assemble for selected FPU.
13026 -EB/-mbig-endian Big-endian
13027 -EL/-mlittle-endian Little-endian
13028 -k Generate PIC code
13029 -mthumb Start in Thumb mode
13030 -mthumb-interwork Code supports ARM/Thumb interworking
13032 For now we will also provide support for:
13034 -mapcs-32 32-bit Program counter
13035 -mapcs-26 26-bit Program counter
13036 -macps-float Floats passed in FP registers
13037 -mapcs-reentrant Reentrant code
13039 (sometime these will probably be replaced with -mapcs=<list of options>
13040 and -matpcs=<list of options>)
13042 The remaining options are only supported for back-wards compatibility.
13043 Cpu variants, the arm part is optional:
13044 -m[arm]1 Currently not supported.
13045 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
13046 -m[arm]3 Arm 3 processor
13047 -m[arm]6[xx], Arm 6 processors
13048 -m[arm]7[xx][t][[d]m] Arm 7 processors
13049 -m[arm]8[10] Arm 8 processors
13050 -m[arm]9[20][tdmi] Arm 9 processors
13051 -mstrongarm[110[0]] StrongARM processors
13052 -mxscale XScale processors
13053 -m[arm]v[2345[t[e]]] Arm architectures
13054 -mall All (except the ARM1)
13056 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
13057 -mfpe-old (No float load/store multiples)
13058 -mvfpxd VFP Single precision
13060 -mno-fpu Disable all floating point instructions
13062 The following CPU names are recognized:
13063 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
13064 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
13065 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
13066 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
13067 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
13068 arm10t arm10e, arm1020t, arm1020e, arm10200e,
13069 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
13073 const char * md_shortopts
= "m:k";
13075 #ifdef ARM_BI_ENDIAN
13076 #define OPTION_EB (OPTION_MD_BASE + 0)
13077 #define OPTION_EL (OPTION_MD_BASE + 1)
13079 #if TARGET_BYTES_BIG_ENDIAN
13080 #define OPTION_EB (OPTION_MD_BASE + 0)
13082 #define OPTION_EL (OPTION_MD_BASE + 1)
13086 struct option md_longopts
[] =
13089 {"EB", no_argument
, NULL
, OPTION_EB
},
13092 {"EL", no_argument
, NULL
, OPTION_EL
},
13094 {NULL
, no_argument
, NULL
, 0}
13097 size_t md_longopts_size
= sizeof (md_longopts
);
13099 struct arm_option_table
13101 char *option
; /* Option name to match. */
13102 char *help
; /* Help information. */
13103 int *var
; /* Variable to change. */
13104 int value
; /* What to change it to. */
13105 char *deprecated
; /* If non-null, print this message. */
13108 struct arm_option_table arm_opts
[] =
13110 {"k", N_("generate PIC code"), &pic_code
, 1, NULL
},
13111 {"mthumb", N_("assemble Thumb code"), &thumb_mode
, 1, NULL
},
13112 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
13113 &support_interwork
, 1, NULL
},
13114 {"moabi", N_("use old ABI (ELF only)"), &target_oabi
, 1, NULL
},
13115 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26
, 0, NULL
},
13116 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26
, 1, NULL
},
13117 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float
,
13119 {"mapcs-reentrant", N_("re-entrant code"), &pic_code
, 1, NULL
},
13120 {"matpcs", N_("code is ATPCS conformant"), &atpcs
, 1, NULL
},
13121 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian
, 1, NULL
},
13122 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian
, 1,
13125 /* These are recognized by the assembler, but have no affect on code. */
13126 {"mapcs-frame", N_("use frame pointer"), NULL
, 0, NULL
},
13127 {"mapcs-stack-check", N_("use stack size checking"), NULL
, 0, NULL
},
13129 /* DON'T add any new processors to this list -- we want the whole list
13130 to go away... Add them to the processors table instead. */
13131 {"marm1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
13132 {"m1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
13133 {"marm2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
13134 {"m2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
13135 {"marm250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
13136 {"m250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
13137 {"marm3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
13138 {"m3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
13139 {"marm6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
13140 {"m6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
13141 {"marm600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
13142 {"m600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
13143 {"marm610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
13144 {"m610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
13145 {"marm620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
13146 {"m620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
13147 {"marm7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
13148 {"m7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
13149 {"marm70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
13150 {"m70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
13151 {"marm700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
13152 {"m700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
13153 {"marm700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
13154 {"m700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
13155 {"marm710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
13156 {"m710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
13157 {"marm710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
13158 {"m710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
13159 {"marm720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
13160 {"m720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
13161 {"marm7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
13162 {"m7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
13163 {"marm7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
13164 {"m7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
13165 {"marm7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
13166 {"m7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
13167 {"marm7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
13168 {"m7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
13169 {"marm7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
13170 {"m7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
13171 {"marm7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
13172 {"m7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
13173 {"marm7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
13174 {"m7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
13175 {"marm7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
13176 {"m7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
13177 {"marm7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
13178 {"m7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
13179 {"marm7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
13180 {"m7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
13181 {"marm710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
13182 {"m710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
13183 {"marm720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
13184 {"m720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
13185 {"marm740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
13186 {"m740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
13187 {"marm8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
13188 {"m8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
13189 {"marm810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
13190 {"m810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
13191 {"marm9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
13192 {"m9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
13193 {"marm9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
13194 {"m9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
13195 {"marm920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
13196 {"m920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
13197 {"marm940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
13198 {"m940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
13199 {"mstrongarm", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=strongarm")},
13200 {"mstrongarm110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
13201 N_("use -mcpu=strongarm110")},
13202 {"mstrongarm1100", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
13203 N_("use -mcpu=strongarm1100")},
13204 {"mstrongarm1110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
13205 N_("use -mcpu=strongarm1110")},
13206 {"mxscale", NULL
, &legacy_cpu
, ARM_ARCH_XSCALE
, N_("use -mcpu=xscale")},
13207 {"miwmmxt", NULL
, &legacy_cpu
, ARM_ARCH_IWMMXT
, N_("use -mcpu=iwmmxt")},
13208 {"mall", NULL
, &legacy_cpu
, ARM_ANY
, N_("use -mcpu=all")},
13210 /* Architecture variants -- don't add any more to this list either. */
13211 {"mv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
13212 {"marmv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
13213 {"mv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
13214 {"marmv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
13215 {"mv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
13216 {"marmv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
13217 {"mv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
13218 {"marmv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
13219 {"mv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
13220 {"marmv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
13221 {"mv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
13222 {"marmv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
13223 {"mv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
13224 {"marmv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
13225 {"mv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
13226 {"marmv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
13227 {"mv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
13228 {"marmv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
13230 /* Floating point variants -- don't add any more to this list either. */
13231 {"mfpe-old", NULL
, &legacy_fpu
, FPU_ARCH_FPE
, N_("use -mfpu=fpe")},
13232 {"mfpa10", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa10")},
13233 {"mfpa11", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa11")},
13234 {"mno-fpu", NULL
, &legacy_fpu
, 0,
13235 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
13237 {NULL
, NULL
, NULL
, 0, NULL
}
13240 struct arm_cpu_option_table
13244 /* For some CPUs we assume an FPU unless the user explicitly sets
13249 /* This list should, at a minimum, contain all the cpu names
13250 recognized by GCC. */
13251 static struct arm_cpu_option_table arm_cpus
[] =
13253 {"all", ARM_ANY
, FPU_ARCH_FPA
},
13254 {"arm1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
13255 {"arm2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
13256 {"arm250", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
13257 {"arm3", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
13258 {"arm6", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13259 {"arm60", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13260 {"arm600", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13261 {"arm610", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13262 {"arm620", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13263 {"arm7", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13264 {"arm7m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
13265 {"arm7d", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13266 {"arm7dm", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
13267 {"arm7di", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13268 {"arm7dmi", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
13269 {"arm70", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13270 {"arm700", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13271 {"arm700i", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13272 {"arm710", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13273 {"arm710t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13274 {"arm720", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13275 {"arm720t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13276 {"arm740t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13277 {"arm710c", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13278 {"arm7100", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13279 {"arm7500", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13280 {"arm7500fe", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13281 {"arm7t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13282 {"arm7tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13283 {"arm7tdmi-s", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13284 {"arm8", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13285 {"arm810", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13286 {"strongarm", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13287 {"strongarm1", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13288 {"strongarm110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13289 {"strongarm1100", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13290 {"strongarm1110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13291 {"arm9", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13292 {"arm920", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13293 {"arm920t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13294 {"arm922t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13295 {"arm940t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13296 {"arm9tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13297 /* For V5 or later processors we default to using VFP; but the user
13298 should really set the FPU type explicitly. */
13299 {"arm9e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
13300 {"arm9e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13301 {"arm926ej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
13302 {"arm926ejs", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
13303 {"arm926ej-s", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
13304 {"arm946e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
13305 {"arm946e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13306 {"arm966e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
13307 {"arm966e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13308 {"arm10t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
13309 {"arm10e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13310 {"arm1020", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13311 {"arm1020t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
13312 {"arm1020e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13313 {"arm1026ejs", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13314 {"arm1026ej-s", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13315 {"arm1136js", ARM_ARCH_V6
, FPU_NONE
},
13316 {"arm1136j-s", ARM_ARCH_V6
, FPU_NONE
},
13317 {"arm1136jfs", ARM_ARCH_V6
, FPU_ARCH_VFP_V2
},
13318 {"arm1136jf-s", ARM_ARCH_V6
, FPU_ARCH_VFP_V2
},
13319 /* ??? XSCALE is really an architecture. */
13320 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
13321 /* ??? iwmmxt is not a processor. */
13322 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP_V2
},
13323 {"i80200", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
13325 {"ep9312", ARM_ARCH_V4T
| ARM_CEXT_MAVERICK
, FPU_ARCH_MAVERICK
},
13329 struct arm_arch_option_table
13336 /* This list should, at a minimum, contain all the architecture names
13337 recognized by GCC. */
13338 static struct arm_arch_option_table arm_archs
[] =
13340 {"all", ARM_ANY
, FPU_ARCH_FPA
},
13341 {"armv1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
13342 {"armv2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
13343 {"armv2a", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
13344 {"armv2s", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
13345 {"armv3", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13346 {"armv3m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
13347 {"armv4", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13348 {"armv4xm", ARM_ARCH_V4xM
, FPU_ARCH_FPA
},
13349 {"armv4t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13350 {"armv4txm", ARM_ARCH_V4TxM
, FPU_ARCH_FPA
},
13351 {"armv5", ARM_ARCH_V5
, FPU_ARCH_VFP
},
13352 {"armv5t", ARM_ARCH_V5T
, FPU_ARCH_VFP
},
13353 {"armv5txm", ARM_ARCH_V5TxM
, FPU_ARCH_VFP
},
13354 {"armv5te", ARM_ARCH_V5TE
, FPU_ARCH_VFP
},
13355 {"armv5texp", ARM_ARCH_V5TExP
, FPU_ARCH_VFP
},
13356 {"armv5tej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP
},
13357 {"armv6", ARM_ARCH_V6
, FPU_ARCH_VFP
},
13358 {"armv6j", ARM_ARCH_V6
, FPU_ARCH_VFP
},
13359 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP
},
13360 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP
},
13364 /* ISA extensions in the co-processor space. */
13365 struct arm_arch_extension_table
13371 static struct arm_arch_extension_table arm_extensions
[] =
13373 {"maverick", ARM_CEXT_MAVERICK
},
13374 {"xscale", ARM_CEXT_XSCALE
},
13375 {"iwmmxt", ARM_CEXT_IWMMXT
},
13379 struct arm_fpu_option_table
13385 /* This list should, at a minimum, contain all the fpu names
13386 recognized by GCC. */
13387 static struct arm_fpu_option_table arm_fpus
[] =
13389 {"softfpa", FPU_NONE
},
13390 {"fpe", FPU_ARCH_FPE
},
13391 {"fpe2", FPU_ARCH_FPE
},
13392 {"fpe3", FPU_ARCH_FPA
}, /* Third release supports LFM/SFM. */
13393 {"fpa", FPU_ARCH_FPA
},
13394 {"fpa10", FPU_ARCH_FPA
},
13395 {"fpa11", FPU_ARCH_FPA
},
13396 {"arm7500fe", FPU_ARCH_FPA
},
13397 {"softvfp", FPU_ARCH_VFP
},
13398 {"softvfp+vfp", FPU_ARCH_VFP_V2
},
13399 {"vfp", FPU_ARCH_VFP_V2
},
13400 {"vfp9", FPU_ARCH_VFP_V2
},
13401 {"vfp10", FPU_ARCH_VFP_V2
},
13402 {"vfp10-r0", FPU_ARCH_VFP_V1
},
13403 {"vfpxd", FPU_ARCH_VFP_V1xD
},
13404 {"arm1020t", FPU_ARCH_VFP_V1
},
13405 {"arm1020e", FPU_ARCH_VFP_V2
},
13406 {"arm1136jfs", FPU_ARCH_VFP_V2
},
13407 {"arm1136jf-s", FPU_ARCH_VFP_V2
},
13408 {"maverick", FPU_ARCH_MAVERICK
},
13412 struct arm_float_abi_option_table
13418 static struct arm_float_abi_option_table arm_float_abis
[] =
13420 {"hard", ARM_FLOAT_ABI_HARD
},
13421 {"softfp", ARM_FLOAT_ABI_SOFTFP
},
13422 {"soft", ARM_FLOAT_ABI_SOFT
},
13426 struct arm_eabi_option_table
13429 unsigned int value
;
13433 /* We only know hot to output GNU and ver 3 (AAELF) formats. */
13434 static struct arm_eabi_option_table arm_eabis
[] =
13436 {"gnu", EF_ARM_EABI_UNKNOWN
},
13437 {"3", EF_ARM_EABI_VER3
},
13442 struct arm_long_option_table
13444 char *option
; /* Substring to match. */
13445 char *help
; /* Help information. */
13446 int (*func
) PARAMS ((char *subopt
)); /* Function to decode sub-option. */
13447 char *deprecated
; /* If non-null, print this message. */
13451 arm_parse_extension (str
, opt_p
)
13455 while (str
!= NULL
&& *str
!= 0)
13457 struct arm_arch_extension_table
*opt
;
13463 as_bad (_("invalid architectural extension"));
13468 ext
= strchr (str
, '+');
13471 optlen
= ext
- str
;
13473 optlen
= strlen (str
);
13477 as_bad (_("missing architectural extension"));
13481 for (opt
= arm_extensions
; opt
->name
!= NULL
; opt
++)
13482 if (strncmp (opt
->name
, str
, optlen
) == 0)
13484 *opt_p
|= opt
->value
;
13488 if (opt
->name
== NULL
)
13490 as_bad (_("unknown architectural extnsion `%s'"), str
);
13501 arm_parse_cpu (str
)
13504 struct arm_cpu_option_table
*opt
;
13505 char *ext
= strchr (str
, '+');
13509 optlen
= ext
- str
;
13511 optlen
= strlen (str
);
13515 as_bad (_("missing cpu name `%s'"), str
);
13519 for (opt
= arm_cpus
; opt
->name
!= NULL
; opt
++)
13520 if (strncmp (opt
->name
, str
, optlen
) == 0)
13522 mcpu_cpu_opt
= opt
->value
;
13523 mcpu_fpu_opt
= opt
->default_fpu
;
13526 return arm_parse_extension (ext
, &mcpu_cpu_opt
);
13531 as_bad (_("unknown cpu `%s'"), str
);
13536 arm_parse_arch (str
)
13539 struct arm_arch_option_table
*opt
;
13540 char *ext
= strchr (str
, '+');
13544 optlen
= ext
- str
;
13546 optlen
= strlen (str
);
13550 as_bad (_("missing architecture name `%s'"), str
);
13555 for (opt
= arm_archs
; opt
->name
!= NULL
; opt
++)
13556 if (strcmp (opt
->name
, str
) == 0)
13558 march_cpu_opt
= opt
->value
;
13559 march_fpu_opt
= opt
->default_fpu
;
13562 return arm_parse_extension (ext
, &march_cpu_opt
);
13567 as_bad (_("unknown architecture `%s'\n"), str
);
13572 arm_parse_fpu (str
)
13575 struct arm_fpu_option_table
*opt
;
13577 for (opt
= arm_fpus
; opt
->name
!= NULL
; opt
++)
13578 if (strcmp (opt
->name
, str
) == 0)
13580 mfpu_opt
= opt
->value
;
13584 as_bad (_("unknown floating point format `%s'\n"), str
);
13589 arm_parse_float_abi (str
)
13592 struct arm_float_abi_option_table
*opt
;
13594 for (opt
= arm_float_abis
; opt
->name
!= NULL
; opt
++)
13595 if (strcmp (opt
->name
, str
) == 0)
13597 mfloat_abi_opt
= opt
->value
;
13601 as_bad (_("unknown floating point abi `%s'\n"), str
);
13607 arm_parse_eabi (str
)
13610 struct arm_eabi_option_table
*opt
;
13612 for (opt
= arm_eabis
; opt
->name
!= NULL
; opt
++)
13613 if (strcmp (opt
->name
, str
) == 0)
13615 meabi_flags
= opt
->value
;
13618 as_bad (_("unknown EABI `%s'\n"), str
);
13623 struct arm_long_option_table arm_long_opts
[] =
13625 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13626 arm_parse_cpu
, NULL
},
13627 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13628 arm_parse_arch
, NULL
},
13629 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13630 arm_parse_fpu
, NULL
},
13631 {"mfloat-abi=", N_("<abi>\t assemble for floating point ABI <abi>"),
13632 arm_parse_float_abi
, NULL
},
13634 {"meabi=", N_("<ver>\t assemble for eabi version <ver>"),
13635 arm_parse_eabi
, NULL
},
13637 {NULL
, NULL
, 0, NULL
}
13641 md_parse_option (c
, arg
)
13645 struct arm_option_table
*opt
;
13646 struct arm_long_option_table
*lopt
;
13652 target_big_endian
= 1;
13658 target_big_endian
= 0;
13663 /* Listing option. Just ignore these, we don't support additional
13668 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
13670 if (c
== opt
->option
[0]
13671 && ((arg
== NULL
&& opt
->option
[1] == 0)
13672 || strcmp (arg
, opt
->option
+ 1) == 0))
13674 #if WARN_DEPRECATED
13675 /* If the option is deprecated, tell the user. */
13676 if (opt
->deprecated
!= NULL
)
13677 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
,
13678 arg
? arg
: "", _(opt
->deprecated
));
13681 if (opt
->var
!= NULL
)
13682 *opt
->var
= opt
->value
;
13688 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
13690 /* These options are expected to have an argument. */
13691 if (c
== lopt
->option
[0]
13693 && strncmp (arg
, lopt
->option
+ 1,
13694 strlen (lopt
->option
+ 1)) == 0)
13696 #if WARN_DEPRECATED
13697 /* If the option is deprecated, tell the user. */
13698 if (lopt
->deprecated
!= NULL
)
13699 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
, arg
,
13700 _(lopt
->deprecated
));
13703 /* Call the sup-option parser. */
13704 return (*lopt
->func
)(arg
+ strlen (lopt
->option
) - 1);
13718 struct arm_option_table
*opt
;
13719 struct arm_long_option_table
*lopt
;
13721 fprintf (fp
, _(" ARM-specific assembler options:\n"));
13723 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
13724 if (opt
->help
!= NULL
)
13725 fprintf (fp
, " -%-23s%s\n", opt
->option
, _(opt
->help
));
13727 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
13728 if (lopt
->help
!= NULL
)
13729 fprintf (fp
, " -%s%s\n", lopt
->option
, _(lopt
->help
));
13733 -EB assemble code for a big-endian cpu\n"));
13738 -EL assemble code for a little-endian cpu\n"));
13742 /* We need to be able to fix up arbitrary expressions in some statements.
13743 This is so that we can handle symbols that are an arbitrary distance from
13744 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
13745 which returns part of an address in a form which will be valid for
13746 a data instruction. We do this by pushing the expression into a symbol
13747 in the expr_section, and creating a fix for that. */
13750 fix_new_arm (frag
, where
, size
, exp
, pc_rel
, reloc
)
13759 arm_fix_data
* arm_data
;
13767 new_fix
= fix_new_exp (frag
, where
, size
, exp
, pc_rel
, reloc
);
13771 new_fix
= fix_new (frag
, where
, size
, make_expr_symbol (exp
), 0,
13776 /* Mark whether the fix is to a THUMB instruction, or an ARM
13778 arm_data
= (arm_fix_data
*) obstack_alloc (& notes
, sizeof (arm_fix_data
));
13779 new_fix
->tc_fix_data
= (PTR
) arm_data
;
13780 arm_data
->thumb_mode
= thumb_mode
;
13783 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13786 cons_fix_new_arm (frag
, where
, size
, exp
)
13792 bfd_reloc_code_real_type type
;
13796 FIXME: @@ Should look at CPU word size. */
13800 type
= BFD_RELOC_8
;
13803 type
= BFD_RELOC_16
;
13807 type
= BFD_RELOC_32
;
13810 type
= BFD_RELOC_64
;
13814 fix_new_exp (frag
, where
, (int) size
, exp
, pcrel
, type
);
13817 /* A good place to do this, although this was probably not intended
13818 for this kind of use. We need to dump the literal pool before
13819 references are made to a null symbol pointer. */
13824 literal_pool
* pool
;
13826 for (pool
= list_of_pools
; pool
; pool
= pool
->next
)
13828 /* Put it at the end of the relevent section. */
13829 subseg_set (pool
->section
, pool
->sub_section
);
13831 arm_elf_change_section ();
13838 arm_start_line_hook ()
13840 last_label_seen
= NULL
;
13844 arm_frob_label (sym
)
13847 last_label_seen
= sym
;
13849 ARM_SET_THUMB (sym
, thumb_mode
);
13851 #if defined OBJ_COFF || defined OBJ_ELF
13852 ARM_SET_INTERWORK (sym
, support_interwork
);
13855 /* Note - do not allow local symbols (.Lxxx) to be labeled
13856 as Thumb functions. This is because these labels, whilst
13857 they exist inside Thumb code, are not the entry points for
13858 possible ARM->Thumb calls. Also, these labels can be used
13859 as part of a computed goto or switch statement. eg gcc
13860 can generate code that looks like this:
13862 ldr r2, [pc, .Laaa]
13872 The first instruction loads the address of the jump table.
13873 The second instruction converts a table index into a byte offset.
13874 The third instruction gets the jump address out of the table.
13875 The fourth instruction performs the jump.
13877 If the address stored at .Laaa is that of a symbol which has the
13878 Thumb_Func bit set, then the linker will arrange for this address
13879 to have the bottom bit set, which in turn would mean that the
13880 address computation performed by the third instruction would end
13881 up with the bottom bit set. Since the ARM is capable of unaligned
13882 word loads, the instruction would then load the incorrect address
13883 out of the jump table, and chaos would ensue. */
13884 if (label_is_thumb_function_name
13885 && (S_GET_NAME (sym
)[0] != '.' || S_GET_NAME (sym
)[1] != 'L')
13886 && (bfd_get_section_flags (stdoutput
, now_seg
) & SEC_CODE
) != 0)
13888 /* When the address of a Thumb function is taken the bottom
13889 bit of that address should be set. This will allow
13890 interworking between Arm and Thumb functions to work
13893 THUMB_SET_FUNC (sym
, 1);
13895 label_is_thumb_function_name
= FALSE
;
13899 /* Adjust the symbol table. This marks Thumb symbols as distinct from
13903 arm_adjust_symtab ()
13908 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
13910 if (ARM_IS_THUMB (sym
))
13912 if (THUMB_IS_FUNC (sym
))
13914 /* Mark the symbol as a Thumb function. */
13915 if ( S_GET_STORAGE_CLASS (sym
) == C_STAT
13916 || S_GET_STORAGE_CLASS (sym
) == C_LABEL
) /* This can happen! */
13917 S_SET_STORAGE_CLASS (sym
, C_THUMBSTATFUNC
);
13919 else if (S_GET_STORAGE_CLASS (sym
) == C_EXT
)
13920 S_SET_STORAGE_CLASS (sym
, C_THUMBEXTFUNC
);
13922 as_bad (_("%s: unexpected function type: %d"),
13923 S_GET_NAME (sym
), S_GET_STORAGE_CLASS (sym
));
13925 else switch (S_GET_STORAGE_CLASS (sym
))
13928 S_SET_STORAGE_CLASS (sym
, C_THUMBEXT
);
13931 S_SET_STORAGE_CLASS (sym
, C_THUMBSTAT
);
13934 S_SET_STORAGE_CLASS (sym
, C_THUMBLABEL
);
13942 if (ARM_IS_INTERWORK (sym
))
13943 coffsymbol (symbol_get_bfdsym (sym
))->native
->u
.syment
.n_flags
= 0xFF;
13950 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
13952 if (ARM_IS_THUMB (sym
))
13954 elf_symbol_type
* elf_sym
;
13956 elf_sym
= elf_symbol (symbol_get_bfdsym (sym
));
13957 bind
= ELF_ST_BIND (elf_sym
);
13959 /* If it's a .thumb_func, declare it as so,
13960 otherwise tag label as .code 16. */
13961 if (THUMB_IS_FUNC (sym
))
13962 elf_sym
->internal_elf_sym
.st_info
=
13963 ELF_ST_INFO (bind
, STT_ARM_TFUNC
);
13965 elf_sym
->internal_elf_sym
.st_info
=
13966 ELF_ST_INFO (bind
, STT_ARM_16BIT
);
13973 arm_data_in_code ()
13975 if (thumb_mode
&& ! strncmp (input_line_pointer
+ 1, "data:", 5))
13977 *input_line_pointer
= '/';
13978 input_line_pointer
+= 5;
13979 *input_line_pointer
= 0;
13987 arm_canonicalize_symbol_name (name
)
13992 if (thumb_mode
&& (len
= strlen (name
)) > 5
13993 && streq (name
+ len
- 5, "/data"))
13994 *(name
+ len
- 5) = 0;
13999 #if defined OBJ_COFF || defined OBJ_ELF
14001 arm_validate_fix (fixP
)
14004 /* If the destination of the branch is a defined symbol which does not have
14005 the THUMB_FUNC attribute, then we must be calling a function which has
14006 the (interfacearm) attribute. We look for the Thumb entry point to that
14007 function and change the branch to refer to that function instead. */
14008 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
14009 && fixP
->fx_addsy
!= NULL
14010 && S_IS_DEFINED (fixP
->fx_addsy
)
14011 && ! THUMB_IS_FUNC (fixP
->fx_addsy
))
14013 fixP
->fx_addsy
= find_real_start (fixP
->fx_addsy
);
14019 arm_force_relocation (fixp
)
14022 #if defined (OBJ_COFF) && defined (TE_PE)
14023 if (fixp
->fx_r_type
== BFD_RELOC_RVA
)
14027 if (fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
14028 || fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
14029 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
14030 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
)
14034 /* Resolve these relocations even if the symbol is extern or weak. */
14035 if (fixp
->fx_r_type
== BFD_RELOC_ARM_IMMEDIATE
14036 || fixp
->fx_r_type
== BFD_RELOC_ARM_OFFSET_IMM
14037 || fixp
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
14040 return generic_force_reloc (fixp
);
14044 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
14045 local labels from being added to the output symbol table when they
14046 are used with the ADRL pseudo op. The ADRL relocation should always
14047 be resolved before the binbary is emitted, so it is safe to say that
14048 it is adjustable. */
14051 arm_fix_adjustable (fixP
)
14054 if (fixP
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
14061 /* Relocations against Thumb function names must be left unadjusted,
14062 so that the linker can use this information to correctly set the
14063 bottom bit of their addresses. The MIPS version of this function
14064 also prevents relocations that are mips-16 specific, but I do not
14065 know why it does this.
14068 There is one other problem that ought to be addressed here, but
14069 which currently is not: Taking the address of a label (rather
14070 than a function) and then later jumping to that address. Such
14071 addresses also ought to have their bottom bit set (assuming that
14072 they reside in Thumb code), but at the moment they will not. */
14075 arm_fix_adjustable (fixP
)
14078 if (fixP
->fx_addsy
== NULL
)
14081 if (THUMB_IS_FUNC (fixP
->fx_addsy
)
14082 && fixP
->fx_subsy
== NULL
)
14085 /* We need the symbol name for the VTABLE entries. */
14086 if ( fixP
->fx_r_type
== BFD_RELOC_VTABLE_INHERIT
14087 || fixP
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
14090 /* Don't allow symbols to be discarded on GOT related relocs. */
14091 if (fixP
->fx_r_type
== BFD_RELOC_ARM_PLT32
14092 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOT32
14093 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOTOFF
)
14100 elf32_arm_target_format ()
14103 return (target_big_endian
14104 ? "elf32-bigarm-symbian"
14105 : "elf32-littlearm-symbian");
14107 if (target_big_endian
)
14110 return "elf32-bigarm-oabi";
14112 return "elf32-bigarm";
14117 return "elf32-littlearm-oabi";
14119 return "elf32-littlearm";
14125 armelf_frob_symbol (symp
, puntp
)
14129 elf_frob_symbol (symp
, puntp
);
14132 static bfd_reloc_code_real_type
14142 bfd_reloc_code_real_type reloc
;
14146 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
14147 MAP ("(got)", BFD_RELOC_ARM_GOT32
),
14148 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF
),
14149 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
14150 branch instructions generated by GCC for PLT relocs. */
14151 MAP ("(plt)", BFD_RELOC_ARM_PLT32
),
14152 MAP ("(relabs)", BFD_RELOC_ARM_RELABS32
),
14153 MAP ("(sbrel)", BFD_RELOC_ARM_SBREL32
),
14154 { NULL
, 0, BFD_RELOC_UNUSED
}
14158 for (i
= 0, ip
= input_line_pointer
;
14159 i
< sizeof (id
) && (ISALNUM (*ip
) || ISPUNCT (*ip
));
14161 id
[i
] = TOLOWER (*ip
);
14163 for (i
= 0; reloc_map
[i
].str
; i
++)
14164 if (strncmp (id
, reloc_map
[i
].str
, reloc_map
[i
].len
) == 0)
14167 input_line_pointer
+= reloc_map
[i
].len
;
14169 return reloc_map
[i
].reloc
;
14173 s_arm_elf_cons (nbytes
)
14178 #ifdef md_flush_pending_output
14179 md_flush_pending_output ();
14182 if (is_it_end_of_statement ())
14184 demand_empty_rest_of_line ();
14188 #ifdef md_cons_align
14189 md_cons_align (nbytes
);
14192 mapping_state (MAP_DATA
);
14195 bfd_reloc_code_real_type reloc
;
14197 expression (& exp
);
14199 if (exp
.X_op
== O_symbol
14200 && * input_line_pointer
== '('
14201 && (reloc
= arm_parse_reloc ()) != BFD_RELOC_UNUSED
)
14203 reloc_howto_type
*howto
= bfd_reloc_type_lookup (stdoutput
, reloc
);
14204 int size
= bfd_get_reloc_size (howto
);
14207 as_bad ("%s relocations do not fit in %d bytes",
14208 howto
->name
, nbytes
);
14211 register char *p
= frag_more ((int) nbytes
);
14212 int offset
= nbytes
- size
;
14214 fix_new_exp (frag_now
, p
- frag_now
->fr_literal
+ offset
, size
,
14219 emit_expr (&exp
, (unsigned int) nbytes
);
14221 while (*input_line_pointer
++ == ',');
14223 /* Put terminator back into stream. */
14224 input_line_pointer
--;
14225 demand_empty_rest_of_line ();
14228 #endif /* OBJ_ELF */
14230 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
14231 of an rs_align_code fragment. */
14234 arm_handle_align (fragP
)
14237 static char const arm_noop
[4] = { 0x00, 0x00, 0xa0, 0xe1 };
14238 static char const thumb_noop
[2] = { 0xc0, 0x46 };
14239 static char const arm_bigend_noop
[4] = { 0xe1, 0xa0, 0x00, 0x00 };
14240 static char const thumb_bigend_noop
[2] = { 0x46, 0xc0 };
14242 int bytes
, fix
, noop_size
;
14246 if (fragP
->fr_type
!= rs_align_code
)
14249 bytes
= fragP
->fr_next
->fr_address
- fragP
->fr_address
- fragP
->fr_fix
;
14250 p
= fragP
->fr_literal
+ fragP
->fr_fix
;
14253 if (bytes
> MAX_MEM_FOR_RS_ALIGN_CODE
)
14254 bytes
&= MAX_MEM_FOR_RS_ALIGN_CODE
;
14256 if (fragP
->tc_frag_data
)
14258 if (target_big_endian
)
14259 noop
= thumb_bigend_noop
;
14262 noop_size
= sizeof (thumb_noop
);
14266 if (target_big_endian
)
14267 noop
= arm_bigend_noop
;
14270 noop_size
= sizeof (arm_noop
);
14273 if (bytes
& (noop_size
- 1))
14275 fix
= bytes
& (noop_size
- 1);
14276 memset (p
, 0, fix
);
14281 while (bytes
>= noop_size
)
14283 memcpy (p
, noop
, noop_size
);
14285 bytes
-= noop_size
;
14289 fragP
->fr_fix
+= fix
;
14290 fragP
->fr_var
= noop_size
;
14293 /* Called from md_do_align. Used to create an alignment
14294 frag in a code section. */
14297 arm_frag_align_code (n
, max
)
14303 /* We assume that there will never be a requirement
14304 to support alignments greater than 32 bytes. */
14305 if (max
> MAX_MEM_FOR_RS_ALIGN_CODE
)
14306 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
14308 p
= frag_var (rs_align_code
,
14309 MAX_MEM_FOR_RS_ALIGN_CODE
,
14311 (relax_substateT
) max
,
14319 /* Perform target specific initialisation of a frag. */
14322 arm_init_frag (fragP
)
14325 /* Record whether this frag is in an ARM or a THUMB area. */
14326 fragP
->tc_frag_data
= thumb_mode
;