1 /* tc-arm.c -- Assemble for the ARM
2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
3 Free Software Foundation, Inc.
4 Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
5 Modified by David Taylor (dtaylor@armltd.co.uk)
6 Cirrus coprocessor mods by Aldy Hernandez (aldyh@redhat.com)
7 Cirrus coprocessor fixes by Petko Manolov (petkan@nucleusys.com)
8 Cirrus coprocessor fixes by Vladimir Ivanov (vladitx@nucleusys.com)
10 This file is part of GAS, the GNU Assembler.
12 GAS is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2, or (at your option)
17 GAS is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with GAS; see the file COPYING. If not, write to the Free
24 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
30 #include "safe-ctype.h"
32 /* Need TARGET_CPU. */
39 #include "opcode/arm.h"
43 #include "dwarf2dbg.h"
46 /* XXX Set this to 1 after the next binutils release */
47 #define WARN_DEPRECATED 0
56 /* Types of processor to assemble for. */
57 #define ARM_1 ARM_ARCH_V1
58 #define ARM_2 ARM_ARCH_V2
59 #define ARM_3 ARM_ARCH_V2S
60 #define ARM_250 ARM_ARCH_V2S
61 #define ARM_6 ARM_ARCH_V3
62 #define ARM_7 ARM_ARCH_V3
63 #define ARM_8 ARM_ARCH_V4
64 #define ARM_9 ARM_ARCH_V4T
65 #define ARM_STRONG ARM_ARCH_V4
66 #define ARM_CPU_MASK 0x0000000f /* XXX? */
69 #if defined __XSCALE__
70 #define CPU_DEFAULT (ARM_ARCH_XSCALE)
73 #define CPU_DEFAULT (ARM_ARCH_V5T)
75 #define CPU_DEFAULT ARM_ANY
81 #define FPU_DEFAULT FPU_ARCH_FPA
86 #define FPU_DEFAULT FPU_ARCH_VFP /* Soft-float, but VFP order. */
88 /* Legacy a.out format. */
89 #define FPU_DEFAULT FPU_ARCH_FPA /* Soft-float, but FPA order. */
93 /* For backwards compatibility we default to the FPA. */
95 #define FPU_DEFAULT FPU_ARCH_FPA
98 #define streq(a, b) (strcmp (a, b) == 0)
99 #define skip_whitespace(str) while (*(str) == ' ') ++(str)
101 static unsigned long cpu_variant
;
102 static int target_oabi
= 0;
104 /* Flags stored in private area of BFD structure. */
105 static int uses_apcs_26
= FALSE
;
106 static int atpcs
= FALSE
;
107 static int support_interwork
= FALSE
;
108 static int uses_apcs_float
= FALSE
;
109 static int pic_code
= FALSE
;
111 /* Variables that we set while parsing command-line options. Once all
112 options have been read we re-process these values to set the real
114 static int legacy_cpu
= -1;
115 static int legacy_fpu
= -1;
117 static int mcpu_cpu_opt
= -1;
118 static int mcpu_fpu_opt
= -1;
119 static int march_cpu_opt
= -1;
120 static int march_fpu_opt
= -1;
121 static int mfpu_opt
= -1;
122 static int mfloat_abi_opt
= -1;
124 static int meabi_flags
= EF_ARM_EABI_UNKNOWN
;
127 /* This array holds the chars that always start a comment. If the
128 pre-processor is disabled, these aren't very useful. */
129 const char comment_chars
[] = "@";
131 /* This array holds the chars that only start a comment at the beginning of
132 a line. If the line seems to have the form '# 123 filename'
133 .line and .file directives will appear in the pre-processed output. */
134 /* Note that input_file.c hand checks for '#' at the beginning of the
135 first line of the input file. This is because the compiler outputs
136 #NO_APP at the beginning of its output. */
137 /* Also note that comments like this one will always work. */
138 const char line_comment_chars
[] = "#";
140 const char line_separator_chars
[] = ";";
142 /* Chars that can be used to separate mant
143 from exp in floating point numbers. */
144 const char EXP_CHARS
[] = "eE";
146 /* Chars that mean this number is a floating point constant. */
150 const char FLT_CHARS
[] = "rRsSfFdDxXeEpP";
152 /* Prefix characters that indicate the start of an immediate
154 #define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
157 /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
158 symbolS
* GOT_symbol
;
161 /* Size of relocation record. */
162 const int md_reloc_size
= 8;
164 /* 0: assemble for ARM,
165 1: assemble for Thumb,
166 2: assemble for Thumb even though target CPU does not support thumb
168 static int thumb_mode
= 0;
170 typedef struct arm_fix
178 unsigned long instruction
;
182 bfd_reloc_code_real_type type
;
199 struct asm_shift_properties
201 enum asm_shift_index index
;
202 unsigned long bit_field
;
203 unsigned int allows_0
: 1;
204 unsigned int allows_32
: 1;
207 static const struct asm_shift_properties shift_properties
[] =
209 { SHIFT_LSL
, 0, 1, 0},
210 { SHIFT_LSR
, 0x20, 0, 1},
211 { SHIFT_ASR
, 0x40, 0, 1},
212 { SHIFT_ROR
, 0x60, 0, 0},
213 { SHIFT_RRX
, 0x60, 0, 0}
216 struct asm_shift_name
219 const struct asm_shift_properties
* properties
;
222 static const struct asm_shift_name shift_names
[] =
224 { "asl", shift_properties
+ SHIFT_LSL
},
225 { "lsl", shift_properties
+ SHIFT_LSL
},
226 { "lsr", shift_properties
+ SHIFT_LSR
},
227 { "asr", shift_properties
+ SHIFT_ASR
},
228 { "ror", shift_properties
+ SHIFT_ROR
},
229 { "rrx", shift_properties
+ SHIFT_RRX
},
230 { "ASL", shift_properties
+ SHIFT_LSL
},
231 { "LSL", shift_properties
+ SHIFT_LSL
},
232 { "LSR", shift_properties
+ SHIFT_LSR
},
233 { "ASR", shift_properties
+ SHIFT_ASR
},
234 { "ROR", shift_properties
+ SHIFT_ROR
},
235 { "RRX", shift_properties
+ SHIFT_RRX
}
238 /* Any kind of shift is accepted. */
239 #define NO_SHIFT_RESTRICT 1
240 /* The shift operand must be an immediate value, not a register. */
241 #define SHIFT_IMMEDIATE 0
242 /* The shift must be LSL or ASR and the operand must be an immediate. */
243 #define SHIFT_LSL_OR_ASR_IMMEDIATE 2
244 /* The shift must be ASR and the operand must be an immediate. */
245 #define SHIFT_ASR_IMMEDIATE 3
246 /* The shift must be LSL and the operand must be an immediate. */
247 #define SHIFT_LSL_IMMEDIATE 4
249 #define NUM_FLOAT_VALS 8
251 const char * fp_const
[] =
253 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
256 /* Number of littlenums required to hold an extended precision number. */
257 #define MAX_LITTLENUMS 6
259 LITTLENUM_TYPE fp_values
[NUM_FLOAT_VALS
][MAX_LITTLENUMS
];
264 /* Whether a Co-processor load/store operation accepts write-back forms. */
273 #define CP_T_X 0x00008000
274 #define CP_T_Y 0x00400000
275 #define CP_T_Pre 0x01000000
276 #define CP_T_UD 0x00800000
277 #define CP_T_WB 0x00200000
279 #define CONDS_BIT 0x00100000
280 #define LOAD_BIT 0x00100000
282 #define DOUBLE_LOAD_FLAG 0x00000001
286 const char * template;
290 #define COND_ALWAYS 0xe0000000
291 #define COND_MASK 0xf0000000
293 static const struct asm_cond conds
[] =
297 {"cs", 0x20000000}, {"hs", 0x20000000},
298 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
315 const char *template;
320 /* The bit that distinguishes CPSR and SPSR. */
321 #define SPSR_BIT (1 << 22)
323 /* How many bits to shift the PSR_xxx bits up by. */
326 #define PSR_c (1 << 0)
327 #define PSR_x (1 << 1)
328 #define PSR_s (1 << 2)
329 #define PSR_f (1 << 3)
331 static const struct asm_psr psrs
[] =
333 {"CPSR", TRUE
, PSR_c
| PSR_f
},
334 {"CPSR_all", TRUE
, PSR_c
| PSR_f
},
335 {"SPSR", FALSE
, PSR_c
| PSR_f
},
336 {"SPSR_all", FALSE
, PSR_c
| PSR_f
},
337 {"CPSR_flg", TRUE
, PSR_f
},
338 {"CPSR_f", TRUE
, PSR_f
},
339 {"SPSR_flg", FALSE
, PSR_f
},
340 {"SPSR_f", FALSE
, PSR_f
},
341 {"CPSR_c", TRUE
, PSR_c
},
342 {"CPSR_ctl", TRUE
, PSR_c
},
343 {"SPSR_c", FALSE
, PSR_c
},
344 {"SPSR_ctl", FALSE
, PSR_c
},
345 {"CPSR_x", TRUE
, PSR_x
},
346 {"CPSR_s", TRUE
, PSR_s
},
347 {"SPSR_x", FALSE
, PSR_x
},
348 {"SPSR_s", FALSE
, PSR_s
},
349 /* Combinations of flags. */
350 {"CPSR_fs", TRUE
, PSR_f
| PSR_s
},
351 {"CPSR_fx", TRUE
, PSR_f
| PSR_x
},
352 {"CPSR_fc", TRUE
, PSR_f
| PSR_c
},
353 {"CPSR_sf", TRUE
, PSR_s
| PSR_f
},
354 {"CPSR_sx", TRUE
, PSR_s
| PSR_x
},
355 {"CPSR_sc", TRUE
, PSR_s
| PSR_c
},
356 {"CPSR_xf", TRUE
, PSR_x
| PSR_f
},
357 {"CPSR_xs", TRUE
, PSR_x
| PSR_s
},
358 {"CPSR_xc", TRUE
, PSR_x
| PSR_c
},
359 {"CPSR_cf", TRUE
, PSR_c
| PSR_f
},
360 {"CPSR_cs", TRUE
, PSR_c
| PSR_s
},
361 {"CPSR_cx", TRUE
, PSR_c
| PSR_x
},
362 {"CPSR_fsx", TRUE
, PSR_f
| PSR_s
| PSR_x
},
363 {"CPSR_fsc", TRUE
, PSR_f
| PSR_s
| PSR_c
},
364 {"CPSR_fxs", TRUE
, PSR_f
| PSR_x
| PSR_s
},
365 {"CPSR_fxc", TRUE
, PSR_f
| PSR_x
| PSR_c
},
366 {"CPSR_fcs", TRUE
, PSR_f
| PSR_c
| PSR_s
},
367 {"CPSR_fcx", TRUE
, PSR_f
| PSR_c
| PSR_x
},
368 {"CPSR_sfx", TRUE
, PSR_s
| PSR_f
| PSR_x
},
369 {"CPSR_sfc", TRUE
, PSR_s
| PSR_f
| PSR_c
},
370 {"CPSR_sxf", TRUE
, PSR_s
| PSR_x
| PSR_f
},
371 {"CPSR_sxc", TRUE
, PSR_s
| PSR_x
| PSR_c
},
372 {"CPSR_scf", TRUE
, PSR_s
| PSR_c
| PSR_f
},
373 {"CPSR_scx", TRUE
, PSR_s
| PSR_c
| PSR_x
},
374 {"CPSR_xfs", TRUE
, PSR_x
| PSR_f
| PSR_s
},
375 {"CPSR_xfc", TRUE
, PSR_x
| PSR_f
| PSR_c
},
376 {"CPSR_xsf", TRUE
, PSR_x
| PSR_s
| PSR_f
},
377 {"CPSR_xsc", TRUE
, PSR_x
| PSR_s
| PSR_c
},
378 {"CPSR_xcf", TRUE
, PSR_x
| PSR_c
| PSR_f
},
379 {"CPSR_xcs", TRUE
, PSR_x
| PSR_c
| PSR_s
},
380 {"CPSR_cfs", TRUE
, PSR_c
| PSR_f
| PSR_s
},
381 {"CPSR_cfx", TRUE
, PSR_c
| PSR_f
| PSR_x
},
382 {"CPSR_csf", TRUE
, PSR_c
| PSR_s
| PSR_f
},
383 {"CPSR_csx", TRUE
, PSR_c
| PSR_s
| PSR_x
},
384 {"CPSR_cxf", TRUE
, PSR_c
| PSR_x
| PSR_f
},
385 {"CPSR_cxs", TRUE
, PSR_c
| PSR_x
| PSR_s
},
386 {"CPSR_fsxc", TRUE
, PSR_f
| PSR_s
| PSR_x
| PSR_c
},
387 {"CPSR_fscx", TRUE
, PSR_f
| PSR_s
| PSR_c
| PSR_x
},
388 {"CPSR_fxsc", TRUE
, PSR_f
| PSR_x
| PSR_s
| PSR_c
},
389 {"CPSR_fxcs", TRUE
, PSR_f
| PSR_x
| PSR_c
| PSR_s
},
390 {"CPSR_fcsx", TRUE
, PSR_f
| PSR_c
| PSR_s
| PSR_x
},
391 {"CPSR_fcxs", TRUE
, PSR_f
| PSR_c
| PSR_x
| PSR_s
},
392 {"CPSR_sfxc", TRUE
, PSR_s
| PSR_f
| PSR_x
| PSR_c
},
393 {"CPSR_sfcx", TRUE
, PSR_s
| PSR_f
| PSR_c
| PSR_x
},
394 {"CPSR_sxfc", TRUE
, PSR_s
| PSR_x
| PSR_f
| PSR_c
},
395 {"CPSR_sxcf", TRUE
, PSR_s
| PSR_x
| PSR_c
| PSR_f
},
396 {"CPSR_scfx", TRUE
, PSR_s
| PSR_c
| PSR_f
| PSR_x
},
397 {"CPSR_scxf", TRUE
, PSR_s
| PSR_c
| PSR_x
| PSR_f
},
398 {"CPSR_xfsc", TRUE
, PSR_x
| PSR_f
| PSR_s
| PSR_c
},
399 {"CPSR_xfcs", TRUE
, PSR_x
| PSR_f
| PSR_c
| PSR_s
},
400 {"CPSR_xsfc", TRUE
, PSR_x
| PSR_s
| PSR_f
| PSR_c
},
401 {"CPSR_xscf", TRUE
, PSR_x
| PSR_s
| PSR_c
| PSR_f
},
402 {"CPSR_xcfs", TRUE
, PSR_x
| PSR_c
| PSR_f
| PSR_s
},
403 {"CPSR_xcsf", TRUE
, PSR_x
| PSR_c
| PSR_s
| PSR_f
},
404 {"CPSR_cfsx", TRUE
, PSR_c
| PSR_f
| PSR_s
| PSR_x
},
405 {"CPSR_cfxs", TRUE
, PSR_c
| PSR_f
| PSR_x
| PSR_s
},
406 {"CPSR_csfx", TRUE
, PSR_c
| PSR_s
| PSR_f
| PSR_x
},
407 {"CPSR_csxf", TRUE
, PSR_c
| PSR_s
| PSR_x
| PSR_f
},
408 {"CPSR_cxfs", TRUE
, PSR_c
| PSR_x
| PSR_f
| PSR_s
},
409 {"CPSR_cxsf", TRUE
, PSR_c
| PSR_x
| PSR_s
| PSR_f
},
410 {"SPSR_fs", FALSE
, PSR_f
| PSR_s
},
411 {"SPSR_fx", FALSE
, PSR_f
| PSR_x
},
412 {"SPSR_fc", FALSE
, PSR_f
| PSR_c
},
413 {"SPSR_sf", FALSE
, PSR_s
| PSR_f
},
414 {"SPSR_sx", FALSE
, PSR_s
| PSR_x
},
415 {"SPSR_sc", FALSE
, PSR_s
| PSR_c
},
416 {"SPSR_xf", FALSE
, PSR_x
| PSR_f
},
417 {"SPSR_xs", FALSE
, PSR_x
| PSR_s
},
418 {"SPSR_xc", FALSE
, PSR_x
| PSR_c
},
419 {"SPSR_cf", FALSE
, PSR_c
| PSR_f
},
420 {"SPSR_cs", FALSE
, PSR_c
| PSR_s
},
421 {"SPSR_cx", FALSE
, PSR_c
| PSR_x
},
422 {"SPSR_fsx", FALSE
, PSR_f
| PSR_s
| PSR_x
},
423 {"SPSR_fsc", FALSE
, PSR_f
| PSR_s
| PSR_c
},
424 {"SPSR_fxs", FALSE
, PSR_f
| PSR_x
| PSR_s
},
425 {"SPSR_fxc", FALSE
, PSR_f
| PSR_x
| PSR_c
},
426 {"SPSR_fcs", FALSE
, PSR_f
| PSR_c
| PSR_s
},
427 {"SPSR_fcx", FALSE
, PSR_f
| PSR_c
| PSR_x
},
428 {"SPSR_sfx", FALSE
, PSR_s
| PSR_f
| PSR_x
},
429 {"SPSR_sfc", FALSE
, PSR_s
| PSR_f
| PSR_c
},
430 {"SPSR_sxf", FALSE
, PSR_s
| PSR_x
| PSR_f
},
431 {"SPSR_sxc", FALSE
, PSR_s
| PSR_x
| PSR_c
},
432 {"SPSR_scf", FALSE
, PSR_s
| PSR_c
| PSR_f
},
433 {"SPSR_scx", FALSE
, PSR_s
| PSR_c
| PSR_x
},
434 {"SPSR_xfs", FALSE
, PSR_x
| PSR_f
| PSR_s
},
435 {"SPSR_xfc", FALSE
, PSR_x
| PSR_f
| PSR_c
},
436 {"SPSR_xsf", FALSE
, PSR_x
| PSR_s
| PSR_f
},
437 {"SPSR_xsc", FALSE
, PSR_x
| PSR_s
| PSR_c
},
438 {"SPSR_xcf", FALSE
, PSR_x
| PSR_c
| PSR_f
},
439 {"SPSR_xcs", FALSE
, PSR_x
| PSR_c
| PSR_s
},
440 {"SPSR_cfs", FALSE
, PSR_c
| PSR_f
| PSR_s
},
441 {"SPSR_cfx", FALSE
, PSR_c
| PSR_f
| PSR_x
},
442 {"SPSR_csf", FALSE
, PSR_c
| PSR_s
| PSR_f
},
443 {"SPSR_csx", FALSE
, PSR_c
| PSR_s
| PSR_x
},
444 {"SPSR_cxf", FALSE
, PSR_c
| PSR_x
| PSR_f
},
445 {"SPSR_cxs", FALSE
, PSR_c
| PSR_x
| PSR_s
},
446 {"SPSR_fsxc", FALSE
, PSR_f
| PSR_s
| PSR_x
| PSR_c
},
447 {"SPSR_fscx", FALSE
, PSR_f
| PSR_s
| PSR_c
| PSR_x
},
448 {"SPSR_fxsc", FALSE
, PSR_f
| PSR_x
| PSR_s
| PSR_c
},
449 {"SPSR_fxcs", FALSE
, PSR_f
| PSR_x
| PSR_c
| PSR_s
},
450 {"SPSR_fcsx", FALSE
, PSR_f
| PSR_c
| PSR_s
| PSR_x
},
451 {"SPSR_fcxs", FALSE
, PSR_f
| PSR_c
| PSR_x
| PSR_s
},
452 {"SPSR_sfxc", FALSE
, PSR_s
| PSR_f
| PSR_x
| PSR_c
},
453 {"SPSR_sfcx", FALSE
, PSR_s
| PSR_f
| PSR_c
| PSR_x
},
454 {"SPSR_sxfc", FALSE
, PSR_s
| PSR_x
| PSR_f
| PSR_c
},
455 {"SPSR_sxcf", FALSE
, PSR_s
| PSR_x
| PSR_c
| PSR_f
},
456 {"SPSR_scfx", FALSE
, PSR_s
| PSR_c
| PSR_f
| PSR_x
},
457 {"SPSR_scxf", FALSE
, PSR_s
| PSR_c
| PSR_x
| PSR_f
},
458 {"SPSR_xfsc", FALSE
, PSR_x
| PSR_f
| PSR_s
| PSR_c
},
459 {"SPSR_xfcs", FALSE
, PSR_x
| PSR_f
| PSR_c
| PSR_s
},
460 {"SPSR_xsfc", FALSE
, PSR_x
| PSR_s
| PSR_f
| PSR_c
},
461 {"SPSR_xscf", FALSE
, PSR_x
| PSR_s
| PSR_c
| PSR_f
},
462 {"SPSR_xcfs", FALSE
, PSR_x
| PSR_c
| PSR_f
| PSR_s
},
463 {"SPSR_xcsf", FALSE
, PSR_x
| PSR_c
| PSR_s
| PSR_f
},
464 {"SPSR_cfsx", FALSE
, PSR_c
| PSR_f
| PSR_s
| PSR_x
},
465 {"SPSR_cfxs", FALSE
, PSR_c
| PSR_f
| PSR_x
| PSR_s
},
466 {"SPSR_csfx", FALSE
, PSR_c
| PSR_s
| PSR_f
| PSR_x
},
467 {"SPSR_csxf", FALSE
, PSR_c
| PSR_s
| PSR_x
| PSR_f
},
468 {"SPSR_cxfs", FALSE
, PSR_c
| PSR_x
| PSR_f
| PSR_s
},
469 {"SPSR_cxsf", FALSE
, PSR_c
| PSR_x
| PSR_s
| PSR_f
},
476 IWMMXT_REG_WR_OR_WC
= 2,
480 enum iwmmxt_insn_type
503 VFP_REG_Dd
, VFP_REG_Dm
, VFP_REG_Dn
508 VFP_REG_Sd
, VFP_REG_Sm
, VFP_REG_Sn
513 VFP_LDSTMIA
, VFP_LDSTMDB
, VFP_LDSTMIAX
, VFP_LDSTMDBX
516 /* VFP system registers. */
523 static const struct vfp_reg vfp_regs
[] =
525 {"fpsid", 0x00000000},
526 {"FPSID", 0x00000000},
527 {"fpscr", 0x00010000},
528 {"FPSCR", 0x00010000},
529 {"fpexc", 0x00080000},
530 {"FPEXC", 0x00080000}
533 /* Structure for a hash table entry for a register. */
541 /* Some well known registers that we refer to directly elsewhere. */
546 #define wr_register(reg) ((reg ^ WR_PREFIX) >= 0 && (reg ^ WR_PREFIX) <= 15)
547 #define wc_register(reg) ((reg ^ WC_PREFIX) >= 0 && (reg ^ WC_PREFIX) <= 15)
548 #define wcg_register(reg) ((reg ^ WC_PREFIX) >= 8 && (reg ^ WC_PREFIX) <= 11)
550 /* These are the standard names. Users can add aliases with .req.
551 and delete them with .unreq. */
553 /* Integer Register Numbers. */
554 static const struct reg_entry rn_table
[] =
556 {"r0", 0, TRUE
}, {"r1", 1, TRUE
}, {"r2", 2, TRUE
}, {"r3", 3, TRUE
},
557 {"r4", 4, TRUE
}, {"r5", 5, TRUE
}, {"r6", 6, TRUE
}, {"r7", 7, TRUE
},
558 {"r8", 8, TRUE
}, {"r9", 9, TRUE
}, {"r10", 10, TRUE
}, {"r11", 11, TRUE
},
559 {"r12", 12, TRUE
}, {"r13", REG_SP
, TRUE
}, {"r14", REG_LR
, TRUE
}, {"r15", REG_PC
, TRUE
},
560 /* ATPCS Synonyms. */
561 {"a1", 0, TRUE
}, {"a2", 1, TRUE
}, {"a3", 2, TRUE
}, {"a4", 3, TRUE
},
562 {"v1", 4, TRUE
}, {"v2", 5, TRUE
}, {"v3", 6, TRUE
}, {"v4", 7, TRUE
},
563 {"v5", 8, TRUE
}, {"v6", 9, TRUE
}, {"v7", 10, TRUE
}, {"v8", 11, TRUE
},
564 /* Well-known aliases. */
565 {"wr", 7, TRUE
}, {"sb", 9, TRUE
}, {"sl", 10, TRUE
}, {"fp", 11, TRUE
},
566 {"ip", 12, TRUE
}, {"sp", REG_SP
, TRUE
}, {"lr", REG_LR
, TRUE
}, {"pc", REG_PC
, TRUE
},
570 #define WR_PREFIX 0x200
571 #define WC_PREFIX 0x400
573 static const struct reg_entry iwmmxt_table
[] =
575 /* Intel Wireless MMX technology register names. */
576 { "wr0", 0x0 | WR_PREFIX
, TRUE
}, {"wr1", 0x1 | WR_PREFIX
, TRUE
},
577 { "wr2", 0x2 | WR_PREFIX
, TRUE
}, {"wr3", 0x3 | WR_PREFIX
, TRUE
},
578 { "wr4", 0x4 | WR_PREFIX
, TRUE
}, {"wr5", 0x5 | WR_PREFIX
, TRUE
},
579 { "wr6", 0x6 | WR_PREFIX
, TRUE
}, {"wr7", 0x7 | WR_PREFIX
, TRUE
},
580 { "wr8", 0x8 | WR_PREFIX
, TRUE
}, {"wr9", 0x9 | WR_PREFIX
, TRUE
},
581 { "wr10", 0xa | WR_PREFIX
, TRUE
}, {"wr11", 0xb | WR_PREFIX
, TRUE
},
582 { "wr12", 0xc | WR_PREFIX
, TRUE
}, {"wr13", 0xd | WR_PREFIX
, TRUE
},
583 { "wr14", 0xe | WR_PREFIX
, TRUE
}, {"wr15", 0xf | WR_PREFIX
, TRUE
},
584 { "wcid", 0x0 | WC_PREFIX
, TRUE
}, {"wcon", 0x1 | WC_PREFIX
, TRUE
},
585 {"wcssf", 0x2 | WC_PREFIX
, TRUE
}, {"wcasf", 0x3 | WC_PREFIX
, TRUE
},
586 {"wcgr0", 0x8 | WC_PREFIX
, TRUE
}, {"wcgr1", 0x9 | WC_PREFIX
, TRUE
},
587 {"wcgr2", 0xa | WC_PREFIX
, TRUE
}, {"wcgr3", 0xb | WC_PREFIX
, TRUE
},
589 { "wR0", 0x0 | WR_PREFIX
, TRUE
}, {"wR1", 0x1 | WR_PREFIX
, TRUE
},
590 { "wR2", 0x2 | WR_PREFIX
, TRUE
}, {"wR3", 0x3 | WR_PREFIX
, TRUE
},
591 { "wR4", 0x4 | WR_PREFIX
, TRUE
}, {"wR5", 0x5 | WR_PREFIX
, TRUE
},
592 { "wR6", 0x6 | WR_PREFIX
, TRUE
}, {"wR7", 0x7 | WR_PREFIX
, TRUE
},
593 { "wR8", 0x8 | WR_PREFIX
, TRUE
}, {"wR9", 0x9 | WR_PREFIX
, TRUE
},
594 { "wR10", 0xa | WR_PREFIX
, TRUE
}, {"wR11", 0xb | WR_PREFIX
, TRUE
},
595 { "wR12", 0xc | WR_PREFIX
, TRUE
}, {"wR13", 0xd | WR_PREFIX
, TRUE
},
596 { "wR14", 0xe | WR_PREFIX
, TRUE
}, {"wR15", 0xf | WR_PREFIX
, TRUE
},
597 { "wCID", 0x0 | WC_PREFIX
, TRUE
}, {"wCon", 0x1 | WC_PREFIX
, TRUE
},
598 {"wCSSF", 0x2 | WC_PREFIX
, TRUE
}, {"wCASF", 0x3 | WC_PREFIX
, TRUE
},
599 {"wCGR0", 0x8 | WC_PREFIX
, TRUE
}, {"wCGR1", 0x9 | WC_PREFIX
, TRUE
},
600 {"wCGR2", 0xa | WC_PREFIX
, TRUE
}, {"wCGR3", 0xb | WC_PREFIX
, TRUE
},
604 /* Co-processor Numbers. */
605 static const struct reg_entry cp_table
[] =
607 {"p0", 0, TRUE
}, {"p1", 1, TRUE
}, {"p2", 2, TRUE
}, {"p3", 3, TRUE
},
608 {"p4", 4, TRUE
}, {"p5", 5, TRUE
}, {"p6", 6, TRUE
}, {"p7", 7, TRUE
},
609 {"p8", 8, TRUE
}, {"p9", 9, TRUE
}, {"p10", 10, TRUE
}, {"p11", 11, TRUE
},
610 {"p12", 12, TRUE
}, {"p13", 13, TRUE
}, {"p14", 14, TRUE
}, {"p15", 15, TRUE
},
614 /* Co-processor Register Numbers. */
615 static const struct reg_entry cn_table
[] =
617 {"c0", 0, TRUE
}, {"c1", 1, TRUE
}, {"c2", 2, TRUE
}, {"c3", 3, TRUE
},
618 {"c4", 4, TRUE
}, {"c5", 5, TRUE
}, {"c6", 6, TRUE
}, {"c7", 7, TRUE
},
619 {"c8", 8, TRUE
}, {"c9", 9, TRUE
}, {"c10", 10, TRUE
}, {"c11", 11, TRUE
},
620 {"c12", 12, TRUE
}, {"c13", 13, TRUE
}, {"c14", 14, TRUE
}, {"c15", 15, TRUE
},
621 /* Not really valid, but kept for back-wards compatibility. */
622 {"cr0", 0, TRUE
}, {"cr1", 1, TRUE
}, {"cr2", 2, TRUE
}, {"cr3", 3, TRUE
},
623 {"cr4", 4, TRUE
}, {"cr5", 5, TRUE
}, {"cr6", 6, TRUE
}, {"cr7", 7, TRUE
},
624 {"cr8", 8, TRUE
}, {"cr9", 9, TRUE
}, {"cr10", 10, TRUE
}, {"cr11", 11, TRUE
},
625 {"cr12", 12, TRUE
}, {"cr13", 13, TRUE
}, {"cr14", 14, TRUE
}, {"cr15", 15, TRUE
},
630 static const struct reg_entry fn_table
[] =
632 {"f0", 0, TRUE
}, {"f1", 1, TRUE
}, {"f2", 2, TRUE
}, {"f3", 3, TRUE
},
633 {"f4", 4, TRUE
}, {"f5", 5, TRUE
}, {"f6", 6, TRUE
}, {"f7", 7, TRUE
},
637 /* VFP SP Registers. */
638 static const struct reg_entry sn_table
[] =
640 {"s0", 0, TRUE
}, {"s1", 1, TRUE
}, {"s2", 2, TRUE
}, {"s3", 3, TRUE
},
641 {"s4", 4, TRUE
}, {"s5", 5, TRUE
}, {"s6", 6, TRUE
}, {"s7", 7, TRUE
},
642 {"s8", 8, TRUE
}, {"s9", 9, TRUE
}, {"s10", 10, TRUE
}, {"s11", 11, TRUE
},
643 {"s12", 12, TRUE
}, {"s13", 13, TRUE
}, {"s14", 14, TRUE
}, {"s15", 15, TRUE
},
644 {"s16", 16, TRUE
}, {"s17", 17, TRUE
}, {"s18", 18, TRUE
}, {"s19", 19, TRUE
},
645 {"s20", 20, TRUE
}, {"s21", 21, TRUE
}, {"s22", 22, TRUE
}, {"s23", 23, TRUE
},
646 {"s24", 24, TRUE
}, {"s25", 25, TRUE
}, {"s26", 26, TRUE
}, {"s27", 27, TRUE
},
647 {"s28", 28, TRUE
}, {"s29", 29, TRUE
}, {"s30", 30, TRUE
}, {"s31", 31, TRUE
},
651 /* VFP DP Registers. */
652 static const struct reg_entry dn_table
[] =
654 {"d0", 0, TRUE
}, {"d1", 1, TRUE
}, {"d2", 2, TRUE
}, {"d3", 3, TRUE
},
655 {"d4", 4, TRUE
}, {"d5", 5, TRUE
}, {"d6", 6, TRUE
}, {"d7", 7, TRUE
},
656 {"d8", 8, TRUE
}, {"d9", 9, TRUE
}, {"d10", 10, TRUE
}, {"d11", 11, TRUE
},
657 {"d12", 12, TRUE
}, {"d13", 13, TRUE
}, {"d14", 14, TRUE
}, {"d15", 15, TRUE
},
661 /* Maverick DSP coprocessor registers. */
662 static const struct reg_entry mav_mvf_table
[] =
664 {"mvf0", 0, TRUE
}, {"mvf1", 1, TRUE
}, {"mvf2", 2, TRUE
}, {"mvf3", 3, TRUE
},
665 {"mvf4", 4, TRUE
}, {"mvf5", 5, TRUE
}, {"mvf6", 6, TRUE
}, {"mvf7", 7, TRUE
},
666 {"mvf8", 8, TRUE
}, {"mvf9", 9, TRUE
}, {"mvf10", 10, TRUE
}, {"mvf11", 11, TRUE
},
667 {"mvf12", 12, TRUE
}, {"mvf13", 13, TRUE
}, {"mvf14", 14, TRUE
}, {"mvf15", 15, TRUE
},
671 static const struct reg_entry mav_mvd_table
[] =
673 {"mvd0", 0, TRUE
}, {"mvd1", 1, TRUE
}, {"mvd2", 2, TRUE
}, {"mvd3", 3, TRUE
},
674 {"mvd4", 4, TRUE
}, {"mvd5", 5, TRUE
}, {"mvd6", 6, TRUE
}, {"mvd7", 7, TRUE
},
675 {"mvd8", 8, TRUE
}, {"mvd9", 9, TRUE
}, {"mvd10", 10, TRUE
}, {"mvd11", 11, TRUE
},
676 {"mvd12", 12, TRUE
}, {"mvd13", 13, TRUE
}, {"mvd14", 14, TRUE
}, {"mvd15", 15, TRUE
},
680 static const struct reg_entry mav_mvfx_table
[] =
682 {"mvfx0", 0, TRUE
}, {"mvfx1", 1, TRUE
}, {"mvfx2", 2, TRUE
}, {"mvfx3", 3, TRUE
},
683 {"mvfx4", 4, TRUE
}, {"mvfx5", 5, TRUE
}, {"mvfx6", 6, TRUE
}, {"mvfx7", 7, TRUE
},
684 {"mvfx8", 8, TRUE
}, {"mvfx9", 9, TRUE
}, {"mvfx10", 10, TRUE
}, {"mvfx11", 11, TRUE
},
685 {"mvfx12", 12, TRUE
}, {"mvfx13", 13, TRUE
}, {"mvfx14", 14, TRUE
}, {"mvfx15", 15, TRUE
},
689 static const struct reg_entry mav_mvdx_table
[] =
691 {"mvdx0", 0, TRUE
}, {"mvdx1", 1, TRUE
}, {"mvdx2", 2, TRUE
}, {"mvdx3", 3, TRUE
},
692 {"mvdx4", 4, TRUE
}, {"mvdx5", 5, TRUE
}, {"mvdx6", 6, TRUE
}, {"mvdx7", 7, TRUE
},
693 {"mvdx8", 8, TRUE
}, {"mvdx9", 9, TRUE
}, {"mvdx10", 10, TRUE
}, {"mvdx11", 11, TRUE
},
694 {"mvdx12", 12, TRUE
}, {"mvdx13", 13, TRUE
}, {"mvdx14", 14, TRUE
}, {"mvdx15", 15, TRUE
},
698 static const struct reg_entry mav_mvax_table
[] =
700 {"mvax0", 0, TRUE
}, {"mvax1", 1, TRUE
}, {"mvax2", 2, TRUE
}, {"mvax3", 3, TRUE
},
704 static const struct reg_entry mav_dspsc_table
[] =
712 const struct reg_entry
* names
;
714 struct hash_control
* htab
;
715 const char * expected
;
718 struct reg_map all_reg_maps
[] =
720 {rn_table
, 15, NULL
, N_("ARM register expected")},
721 {cp_table
, 15, NULL
, N_("bad or missing co-processor number")},
722 {cn_table
, 15, NULL
, N_("co-processor register expected")},
723 {fn_table
, 7, NULL
, N_("FPA register expected")},
724 {sn_table
, 31, NULL
, N_("VFP single precision register expected")},
725 {dn_table
, 15, NULL
, N_("VFP double precision register expected")},
726 {mav_mvf_table
, 15, NULL
, N_("Maverick MVF register expected")},
727 {mav_mvd_table
, 15, NULL
, N_("Maverick MVD register expected")},
728 {mav_mvfx_table
, 15, NULL
, N_("Maverick MVFX register expected")},
729 {mav_mvdx_table
, 15, NULL
, N_("Maverick MVDX register expected")},
730 {mav_mvax_table
, 3, NULL
, N_("Maverick MVAX register expected")},
731 {mav_dspsc_table
, 0, NULL
, N_("Maverick DSPSC register expected")},
732 {iwmmxt_table
, 23, NULL
, N_("Intel Wireless MMX technology register expected")},
735 /* Enumeration matching entries in table above. */
739 #define REG_TYPE_FIRST REG_TYPE_RN
751 REG_TYPE_IWMMXT
= 12,
756 /* ARM instructions take 4bytes in the object file, Thumb instructions
760 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
761 #define MAV_MODE1 0x100c
763 /* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
764 #define MAV_MODE2 0x0c10
766 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
767 #define MAV_MODE3 0x100c
769 /* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
770 #define MAV_MODE4 0x0c0010
772 /* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
773 #define MAV_MODE5 0x00100c
775 /* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
776 #define MAV_MODE6 0x00100c05
780 /* Basic string to match. */
781 const char * template;
783 /* Basic instruction code. */
786 /* Offset into the template where the condition code (if any) will be.
787 If zero, then the instruction is never conditional. */
788 unsigned cond_offset
;
790 /* Which architecture variant provides this instruction. */
791 unsigned long variant
;
793 /* Function to call to parse args. */
794 void (* parms
) (char *);
797 /* Defines for various bits that we will want to toggle. */
798 #define INST_IMMEDIATE 0x02000000
799 #define OFFSET_REG 0x02000000
800 #define HWOFFSET_IMM 0x00400000
801 #define SHIFT_BY_REG 0x00000010
802 #define PRE_INDEX 0x01000000
803 #define INDEX_UP 0x00800000
804 #define WRITE_BACK 0x00200000
805 #define LDM_TYPE_2_OR_3 0x00400000
807 #define LITERAL_MASK 0xf000f000
808 #define OPCODE_MASK 0xfe1fffff
809 #define V4_STR_BIT 0x00000020
811 #define DATA_OP_SHIFT 21
813 /* Codes to distinguish the arithmetic instructions. */
824 #define OPCODE_CMP 10
825 #define OPCODE_CMN 11
826 #define OPCODE_ORR 12
827 #define OPCODE_MOV 13
828 #define OPCODE_BIC 14
829 #define OPCODE_MVN 15
831 #define T_OPCODE_MUL 0x4340
832 #define T_OPCODE_TST 0x4200
833 #define T_OPCODE_CMN 0x42c0
834 #define T_OPCODE_NEG 0x4240
835 #define T_OPCODE_MVN 0x43c0
837 #define T_OPCODE_ADD_R3 0x1800
838 #define T_OPCODE_SUB_R3 0x1a00
839 #define T_OPCODE_ADD_HI 0x4400
840 #define T_OPCODE_ADD_ST 0xb000
841 #define T_OPCODE_SUB_ST 0xb080
842 #define T_OPCODE_ADD_SP 0xa800
843 #define T_OPCODE_ADD_PC 0xa000
844 #define T_OPCODE_ADD_I8 0x3000
845 #define T_OPCODE_SUB_I8 0x3800
846 #define T_OPCODE_ADD_I3 0x1c00
847 #define T_OPCODE_SUB_I3 0x1e00
849 #define T_OPCODE_ASR_R 0x4100
850 #define T_OPCODE_LSL_R 0x4080
851 #define T_OPCODE_LSR_R 0x40c0
852 #define T_OPCODE_ASR_I 0x1000
853 #define T_OPCODE_LSL_I 0x0000
854 #define T_OPCODE_LSR_I 0x0800
856 #define T_OPCODE_MOV_I8 0x2000
857 #define T_OPCODE_CMP_I8 0x2800
858 #define T_OPCODE_CMP_LR 0x4280
859 #define T_OPCODE_MOV_HR 0x4600
860 #define T_OPCODE_CMP_HR 0x4500
862 #define T_OPCODE_LDR_PC 0x4800
863 #define T_OPCODE_LDR_SP 0x9800
864 #define T_OPCODE_STR_SP 0x9000
865 #define T_OPCODE_LDR_IW 0x6800
866 #define T_OPCODE_STR_IW 0x6000
867 #define T_OPCODE_LDR_IH 0x8800
868 #define T_OPCODE_STR_IH 0x8000
869 #define T_OPCODE_LDR_IB 0x7800
870 #define T_OPCODE_STR_IB 0x7000
871 #define T_OPCODE_LDR_RW 0x5800
872 #define T_OPCODE_STR_RW 0x5000
873 #define T_OPCODE_LDR_RH 0x5a00
874 #define T_OPCODE_STR_RH 0x5200
875 #define T_OPCODE_LDR_RB 0x5c00
876 #define T_OPCODE_STR_RB 0x5400
878 #define T_OPCODE_PUSH 0xb400
879 #define T_OPCODE_POP 0xbc00
881 #define T_OPCODE_BRANCH 0xe7fe
883 #define THUMB_SIZE 2 /* Size of thumb instruction. */
884 #define THUMB_REG_LO 0x1
885 #define THUMB_REG_HI 0x2
886 #define THUMB_REG_ANY 0x3
888 #define THUMB_H1 0x0080
889 #define THUMB_H2 0x0040
896 #define THUMB_COMPARE 1
900 #define THUMB_STORE 1
902 #define THUMB_PP_PC_LR 0x0100
904 /* These three are used for immediate shifts, do not alter. */
906 #define THUMB_HALFWORD 1
911 /* Basic string to match. */
912 const char * template;
914 /* Basic instruction code. */
919 /* Which CPU variants this exists for. */
920 unsigned long variant
;
922 /* Function to call to parse args. */
923 void (* parms
) (char *);
926 #define BAD_ARGS _("bad arguments to instruction")
927 #define BAD_PC _("r15 not allowed here")
928 #define BAD_COND _("instruction is not conditional")
929 #define ERR_NO_ACCUM _("acc0 expected")
931 static struct hash_control
* arm_ops_hsh
= NULL
;
932 static struct hash_control
* arm_tops_hsh
= NULL
;
933 static struct hash_control
* arm_cond_hsh
= NULL
;
934 static struct hash_control
* arm_shift_hsh
= NULL
;
935 static struct hash_control
* arm_psr_hsh
= NULL
;
937 /* Stuff needed to resolve the label ambiguity
947 symbolS
* last_label_seen
;
948 static int label_is_thumb_function_name
= FALSE
;
950 /* Literal Pool stuff. */
952 #define MAX_LITERAL_POOL_SIZE 1024
954 /* Literal pool structure. Held on a per-section
955 and per-sub-section basis. */
957 typedef struct literal_pool
959 expressionS literals
[MAX_LITERAL_POOL_SIZE
];
960 unsigned int next_free_entry
;
965 struct literal_pool
* next
;
968 /* Pointer to a linked list of literal pools. */
969 literal_pool
* list_of_pools
= NULL
;
971 static literal_pool
*
972 find_literal_pool (void)
976 for (pool
= list_of_pools
; pool
!= NULL
; pool
= pool
->next
)
978 if (pool
->section
== now_seg
979 && pool
->sub_section
== now_subseg
)
986 static literal_pool
*
987 find_or_make_literal_pool (void)
989 /* Next literal pool ID number. */
990 static unsigned int latest_pool_num
= 1;
993 pool
= find_literal_pool ();
997 /* Create a new pool. */
998 pool
= xmalloc (sizeof (* pool
));
1002 pool
->next_free_entry
= 0;
1003 pool
->section
= now_seg
;
1004 pool
->sub_section
= now_subseg
;
1005 pool
->next
= list_of_pools
;
1006 pool
->symbol
= NULL
;
1008 /* Add it to the list. */
1009 list_of_pools
= pool
;
1012 /* New pools, and emptied pools, will have a NULL symbol. */
1013 if (pool
->symbol
== NULL
)
1015 pool
->symbol
= symbol_create (FAKE_LABEL_NAME
, undefined_section
,
1016 (valueT
) 0, &zero_address_frag
);
1017 pool
->id
= latest_pool_num
++;
1024 /* Add the literal in the global 'inst'
1025 structure to the relevent literal pool. */
1028 add_to_lit_pool (void)
1030 literal_pool
* pool
;
1033 pool
= find_or_make_literal_pool ();
1035 /* Check if this literal value is already in the pool. */
1036 for (entry
= 0; entry
< pool
->next_free_entry
; entry
++)
1038 if ((pool
->literals
[entry
].X_op
== inst
.reloc
.exp
.X_op
)
1039 && (inst
.reloc
.exp
.X_op
== O_constant
)
1040 && (pool
->literals
[entry
].X_add_number
1041 == inst
.reloc
.exp
.X_add_number
)
1042 && (pool
->literals
[entry
].X_unsigned
1043 == inst
.reloc
.exp
.X_unsigned
))
1046 if ((pool
->literals
[entry
].X_op
== inst
.reloc
.exp
.X_op
)
1047 && (inst
.reloc
.exp
.X_op
== O_symbol
)
1048 && (pool
->literals
[entry
].X_add_number
1049 == inst
.reloc
.exp
.X_add_number
)
1050 && (pool
->literals
[entry
].X_add_symbol
1051 == inst
.reloc
.exp
.X_add_symbol
)
1052 && (pool
->literals
[entry
].X_op_symbol
1053 == inst
.reloc
.exp
.X_op_symbol
))
1057 /* Do we need to create a new entry? */
1058 if (entry
== pool
->next_free_entry
)
1060 if (entry
>= MAX_LITERAL_POOL_SIZE
)
1062 inst
.error
= _("literal pool overflow");
1066 pool
->literals
[entry
] = inst
.reloc
.exp
;
1067 pool
->next_free_entry
+= 1;
1070 inst
.reloc
.exp
.X_op
= O_symbol
;
1071 inst
.reloc
.exp
.X_add_number
= ((int) entry
) * 4 - 8;
1072 inst
.reloc
.exp
.X_add_symbol
= pool
->symbol
;
1077 /* Can't use symbol_new here, so have to create a symbol and then at
1078 a later date assign it a value. Thats what these functions do. */
1081 symbol_locate (symbolS
* symbolP
,
1082 const char * name
, /* It is copied, the caller can modify. */
1083 segT segment
, /* Segment identifier (SEG_<something>). */
1084 valueT valu
, /* Symbol value. */
1085 fragS
* frag
) /* Associated fragment. */
1087 unsigned int name_length
;
1088 char * preserved_copy_of_name
;
1090 name_length
= strlen (name
) + 1; /* +1 for \0. */
1091 obstack_grow (¬es
, name
, name_length
);
1092 preserved_copy_of_name
= obstack_finish (¬es
);
1093 #ifdef STRIP_UNDERSCORE
1094 if (preserved_copy_of_name
[0] == '_')
1095 preserved_copy_of_name
++;
1098 #ifdef tc_canonicalize_symbol_name
1099 preserved_copy_of_name
=
1100 tc_canonicalize_symbol_name (preserved_copy_of_name
);
1103 S_SET_NAME (symbolP
, preserved_copy_of_name
);
1105 S_SET_SEGMENT (symbolP
, segment
);
1106 S_SET_VALUE (symbolP
, valu
);
1107 symbol_clear_list_pointers (symbolP
);
1109 symbol_set_frag (symbolP
, frag
);
1111 /* Link to end of symbol chain. */
1113 extern int symbol_table_frozen
;
1115 if (symbol_table_frozen
)
1119 symbol_append (symbolP
, symbol_lastP
, & symbol_rootP
, & symbol_lastP
);
1121 obj_symbol_new_hook (symbolP
);
1123 #ifdef tc_symbol_new_hook
1124 tc_symbol_new_hook (symbolP
);
1128 verify_symbol_chain (symbol_rootP
, symbol_lastP
);
1129 #endif /* DEBUG_SYMS */
1132 /* Check that an immediate is valid.
1133 If so, convert it to the right format. */
1136 validate_immediate (unsigned int val
)
1141 #define rotate_left(v, n) (v << n | v >> (32 - n))
1143 for (i
= 0; i
< 32; i
+= 2)
1144 if ((a
= rotate_left (val
, i
)) <= 0xff)
1145 return a
| (i
<< 7); /* 12-bit pack: [shift-cnt,const]. */
1150 /* Check to see if an immediate can be computed as two separate immediate
1151 values, added together. We already know that this value cannot be
1152 computed by just one ARM instruction. */
1155 validate_immediate_twopart (unsigned int val
,
1156 unsigned int * highpart
)
1161 for (i
= 0; i
< 32; i
+= 2)
1162 if (((a
= rotate_left (val
, i
)) & 0xff) != 0)
1168 * highpart
= (a
>> 8) | ((i
+ 24) << 7);
1170 else if (a
& 0xff0000)
1174 * highpart
= (a
>> 16) | ((i
+ 16) << 7);
1178 assert (a
& 0xff000000);
1179 * highpart
= (a
>> 24) | ((i
+ 8) << 7);
1182 return (a
& 0xff) | (i
<< 7);
1189 validate_offset_imm (unsigned int val
, int hwse
)
1191 if ((hwse
&& val
> 255) || val
> 4095)
1198 /* This code is to handle mapping symbols as defined in the ARM ELF spec.
1199 (This text is taken from version B-02 of the spec):
1201 4.4.7 Mapping and tagging symbols
1203 A section of an ARM ELF file can contain a mixture of ARM code,
1204 Thumb code, and data. There are inline transitions between code
1205 and data at literal pool boundaries. There can also be inline
1206 transitions between ARM code and Thumb code, for example in
1207 ARM-Thumb inter-working veneers. Linkers, machine-level
1208 debuggers, profiling tools, and disassembly tools need to map
1209 images accurately. For example, setting an ARM breakpoint on a
1210 Thumb location, or in a literal pool, can crash the program
1211 being debugged, ruining the debugging session.
1213 ARM ELF entities are mapped (see section 4.4.7.1 below) and
1214 tagged (see section 4.4.7.2 below) using local symbols (with
1215 binding STB_LOCAL). To assist consumers, mapping and tagging
1216 symbols should be collated first in the symbol table, before
1217 other symbols with binding STB_LOCAL.
1219 To allow properly collated mapping and tagging symbols to be
1220 skipped by consumers that have no interest in them, the first
1221 such symbol should have the name $m and its st_value field equal
1222 to the total number of mapping and tagging symbols (including
1223 the $m) in the symbol table.
1225 4.4.7.1 Mapping symbols
1227 $a Labels the first byte of a sequence of ARM instructions.
1228 Its type is STT_FUNC.
1230 $d Labels the first byte of a sequence of data items.
1231 Its type is STT_OBJECT.
1233 $t Labels the first byte of a sequence of Thumb instructions.
1234 Its type is STT_FUNC.
1236 This list of mapping symbols may be extended in the future.
1238 Section-relative mapping symbols
1240 Mapping symbols defined in a section define a sequence of
1241 half-open address intervals that cover the address range of the
1242 section. Each interval starts at the address defined by a
1243 mapping symbol, and continues up to, but not including, the
1244 address defined by the next (in address order) mapping symbol or
1245 the end of the section. A corollary is that there must be a
1246 mapping symbol defined at the beginning of each section.
1247 Consumers can ignore the size of a section-relative mapping
1248 symbol. Producers can set it to 0.
1250 Absolute mapping symbols
1252 Because of the need to crystallize a Thumb address with the
1253 Thumb-bit set, absolute symbol of type STT_FUNC (symbols of type
1254 STT_FUNC defined in section SHN_ABS) need to be mapped with $a
1257 The extent of a mapping symbol defined in SHN_ABS is [st_value,
1258 st_value + st_size), or [st_value, st_value + 1) if st_size = 0,
1259 where [x, y) denotes the half-open address range from x,
1260 inclusive, to y, exclusive.
1262 In the absence of a mapping symbol, a consumer can interpret a
1263 function symbol with an odd value as the Thumb code address
1264 obtained by clearing the least significant bit of the
1265 value. This interpretation is deprecated, and it may not work in
1268 Note - the Tagging symbols ($b, $f, $p $m) have been dropped from
1269 the EABI (which is still under development), so they are not
1270 implemented here. */
1272 static enum mstate mapstate
= MAP_UNDEFINED
;
1275 mapping_state (enum mstate state
)
1278 const char * symname
;
1281 if (mapstate
== state
)
1282 /* The mapping symbol has already been emitted.
1283 There is nothing else to do. */
1296 type
= BSF_FUNCTION
;
1300 type
= BSF_FUNCTION
;
1308 seg_info (now_seg
)->tc_segment_info_data
= state
;
1310 symbolP
= symbol_new (symname
, now_seg
, (valueT
) frag_now_fix (), frag_now
);
1311 symbol_table_insert (symbolP
);
1312 symbol_get_bfdsym (symbolP
)->flags
|= type
| BSF_LOCAL
;
1317 THUMB_SET_FUNC (symbolP
, 0);
1318 ARM_SET_THUMB (symbolP
, 0);
1319 ARM_SET_INTERWORK (symbolP
, support_interwork
);
1323 THUMB_SET_FUNC (symbolP
, 1);
1324 ARM_SET_THUMB (symbolP
, 1);
1325 ARM_SET_INTERWORK (symbolP
, support_interwork
);
1334 /* When we change sections we need to issue a new mapping symbol. */
1337 arm_elf_change_section (void)
1341 /* Link an unlinked unwind index table section to the .text section. */
1342 if (elf_section_type (now_seg
) == SHT_ARM_EXIDX
1343 && elf_linked_to_section (now_seg
) == NULL
)
1344 elf_linked_to_section (now_seg
) = text_section
;
1346 if (!SEG_NORMAL (now_seg
))
1349 flags
= bfd_get_section_flags (stdoutput
, now_seg
);
1351 /* We can ignore sections that only contain debug info. */
1352 if ((flags
& SEC_ALLOC
) == 0)
1355 mapstate
= seg_info (now_seg
)->tc_segment_info_data
;
1359 arm_elf_section_type (const char * str
, size_t len
)
1361 if (len
== 5 && strncmp (str
, "exidx", 5) == 0)
1362 return SHT_ARM_EXIDX
;
1367 #define mapping_state(a)
1368 #endif /* OBJ_ELF */
1370 /* arm_reg_parse () := if it looks like a register, return its token and
1371 advance the pointer. */
1374 arm_reg_parse (char ** ccp
, struct hash_control
* htab
)
1376 char * start
= * ccp
;
1379 struct reg_entry
* reg
;
1381 #ifdef REGISTER_PREFIX
1382 if (*start
!= REGISTER_PREFIX
)
1387 #ifdef OPTIONAL_REGISTER_PREFIX
1388 if (*p
== OPTIONAL_REGISTER_PREFIX
)
1392 if (!ISALPHA (*p
) || !is_name_beginner (*p
))
1396 while (ISALPHA (c
) || ISDIGIT (c
) || c
== '_')
1400 reg
= (struct reg_entry
*) hash_find (htab
, start
);
1412 /* Search for the following register name in each of the possible reg name
1413 tables. Return the classification if found, or REG_TYPE_MAX if not
1416 static enum arm_reg_type
1417 arm_reg_parse_any (char *cp
)
1421 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
1422 if (arm_reg_parse (&cp
, all_reg_maps
[i
].htab
) != FAIL
)
1423 return (enum arm_reg_type
) i
;
1425 return REG_TYPE_MAX
;
1429 opcode_select (int width
)
1436 if (! (cpu_variant
& ARM_EXT_V4T
))
1437 as_bad (_("selected processor does not support THUMB opcodes"));
1440 /* No need to force the alignment, since we will have been
1441 coming from ARM mode, which is word-aligned. */
1442 record_alignment (now_seg
, 1);
1444 mapping_state (MAP_THUMB
);
1450 if ((cpu_variant
& ARM_ALL
) == ARM_EXT_V4T
)
1451 as_bad (_("selected processor does not support ARM opcodes"));
1456 frag_align (2, 0, 0);
1458 record_alignment (now_seg
, 1);
1460 mapping_state (MAP_ARM
);
1464 as_bad (_("invalid instruction size selected (%d)"), width
);
1469 s_req (int a ATTRIBUTE_UNUSED
)
1471 as_bad (_("invalid syntax for .req directive"));
1474 /* The .unreq directive deletes an alias which was previously defined
1475 by .req. For example:
1481 s_unreq (int a ATTRIBUTE_UNUSED
)
1486 skip_whitespace (input_line_pointer
);
1487 name
= input_line_pointer
;
1489 while (*input_line_pointer
!= 0
1490 && *input_line_pointer
!= ' '
1491 && *input_line_pointer
!= '\n')
1492 ++input_line_pointer
;
1494 saved_char
= *input_line_pointer
;
1495 *input_line_pointer
= 0;
1499 enum arm_reg_type req_type
= arm_reg_parse_any (name
);
1501 if (req_type
!= REG_TYPE_MAX
)
1503 char *temp_name
= name
;
1504 int req_no
= arm_reg_parse (&temp_name
, all_reg_maps
[req_type
].htab
);
1508 struct reg_entry
*req_entry
;
1510 /* Check to see if this alias is a builtin one. */
1511 req_entry
= hash_delete (all_reg_maps
[req_type
].htab
, name
);
1514 as_bad (_("unreq: missing hash entry for \"%s\""), name
);
1515 else if (req_entry
->builtin
)
1516 /* FIXME: We are deleting a built in register alias which
1517 points to a const data structure, so we only need to
1518 free up the memory used by the key in the hash table.
1519 Unfortunately we have not recorded this value, so this
1520 is a memory leak. */
1521 /* FIXME: Should we issue a warning message ? */
1525 /* Deleting a user defined alias. We need to free the
1526 key and the value, but fortunately the key is the same
1527 as the value->name field. */
1528 free ((char *) req_entry
->name
);
1533 as_bad (_(".unreq: unrecognized symbol \"%s\""), name
);
1536 as_bad (_(".unreq: unrecognized symbol \"%s\""), name
);
1539 as_bad (_("invalid syntax for .unreq directive"));
1541 *input_line_pointer
= saved_char
;
1542 demand_empty_rest_of_line ();
1546 s_bss (int ignore ATTRIBUTE_UNUSED
)
1548 /* We don't support putting frags in the BSS segment, we fake it by
1549 marking in_bss, then looking at s_skip for clues. */
1550 subseg_set (bss_section
, 0);
1551 demand_empty_rest_of_line ();
1552 mapping_state (MAP_DATA
);
1556 s_even (int ignore ATTRIBUTE_UNUSED
)
1558 /* Never make frag if expect extra pass. */
1560 frag_align (1, 0, 0);
1562 record_alignment (now_seg
, 1);
1564 demand_empty_rest_of_line ();
1568 s_ltorg (int ignored ATTRIBUTE_UNUSED
)
1571 literal_pool
* pool
;
1574 pool
= find_literal_pool ();
1576 || pool
->symbol
== NULL
1577 || pool
->next_free_entry
== 0)
1580 mapping_state (MAP_DATA
);
1582 /* Align pool as you have word accesses.
1583 Only make a frag if we have to. */
1585 frag_align (2, 0, 0);
1587 record_alignment (now_seg
, 2);
1589 sprintf (sym_name
, "$$lit_\002%x", pool
->id
);
1591 symbol_locate (pool
->symbol
, sym_name
, now_seg
,
1592 (valueT
) frag_now_fix (), frag_now
);
1593 symbol_table_insert (pool
->symbol
);
1595 ARM_SET_THUMB (pool
->symbol
, thumb_mode
);
1597 #if defined OBJ_COFF || defined OBJ_ELF
1598 ARM_SET_INTERWORK (pool
->symbol
, support_interwork
);
1601 for (entry
= 0; entry
< pool
->next_free_entry
; entry
++)
1602 /* First output the expression in the instruction to the pool. */
1603 emit_expr (&(pool
->literals
[entry
]), 4); /* .word */
1605 /* Mark the pool as empty. */
1606 pool
->next_free_entry
= 0;
1607 pool
->symbol
= NULL
;
1610 /* Same as s_align_ptwo but align 0 => align 2. */
1613 s_align (int unused ATTRIBUTE_UNUSED
)
1617 long max_alignment
= 15;
1619 temp
= get_absolute_expression ();
1620 if (temp
> max_alignment
)
1621 as_bad (_("alignment too large: %d assumed"), temp
= max_alignment
);
1624 as_bad (_("alignment negative. 0 assumed."));
1628 if (*input_line_pointer
== ',')
1630 input_line_pointer
++;
1631 temp_fill
= get_absolute_expression ();
1639 /* Only make a frag if we HAVE to. */
1640 if (temp
&& !need_pass_2
)
1641 frag_align (temp
, (int) temp_fill
, 0);
1642 demand_empty_rest_of_line ();
1644 record_alignment (now_seg
, temp
);
1648 s_force_thumb (int ignore ATTRIBUTE_UNUSED
)
1650 /* If we are not already in thumb mode go into it, EVEN if
1651 the target processor does not support thumb instructions.
1652 This is used by gcc/config/arm/lib1funcs.asm for example
1653 to compile interworking support functions even if the
1654 target processor should not support interworking. */
1659 record_alignment (now_seg
, 1);
1662 demand_empty_rest_of_line ();
1666 s_thumb_func (int ignore ATTRIBUTE_UNUSED
)
1671 /* The following label is the name/address of the start of a Thumb function.
1672 We need to know this for the interworking support. */
1673 label_is_thumb_function_name
= TRUE
;
1675 demand_empty_rest_of_line ();
1678 /* Perform a .set directive, but also mark the alias as
1679 being a thumb function. */
1682 s_thumb_set (int equiv
)
1684 /* XXX the following is a duplicate of the code for s_set() in read.c
1685 We cannot just call that code as we need to get at the symbol that
1692 /* Especial apologies for the random logic:
1693 This just grew, and could be parsed much more simply!
1695 name
= input_line_pointer
;
1696 delim
= get_symbol_end ();
1697 end_name
= input_line_pointer
;
1702 if (*input_line_pointer
!= ',')
1705 as_bad (_("expected comma after name \"%s\""), name
);
1707 ignore_rest_of_line ();
1711 input_line_pointer
++;
1714 if (name
[0] == '.' && name
[1] == '\0')
1716 /* XXX - this should not happen to .thumb_set. */
1720 if ((symbolP
= symbol_find (name
)) == NULL
1721 && (symbolP
= md_undefined_symbol (name
)) == NULL
)
1724 /* When doing symbol listings, play games with dummy fragments living
1725 outside the normal fragment chain to record the file and line info
1727 if (listing
& LISTING_SYMBOLS
)
1729 extern struct list_info_struct
* listing_tail
;
1730 fragS
* dummy_frag
= xmalloc (sizeof (fragS
));
1732 memset (dummy_frag
, 0, sizeof (fragS
));
1733 dummy_frag
->fr_type
= rs_fill
;
1734 dummy_frag
->line
= listing_tail
;
1735 symbolP
= symbol_new (name
, undefined_section
, 0, dummy_frag
);
1736 dummy_frag
->fr_symbol
= symbolP
;
1740 symbolP
= symbol_new (name
, undefined_section
, 0, &zero_address_frag
);
1743 /* "set" symbols are local unless otherwise specified. */
1744 SF_SET_LOCAL (symbolP
);
1745 #endif /* OBJ_COFF */
1746 } /* Make a new symbol. */
1748 symbol_table_insert (symbolP
);
1753 && S_IS_DEFINED (symbolP
)
1754 && S_GET_SEGMENT (symbolP
) != reg_section
)
1755 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP
));
1757 pseudo_set (symbolP
);
1759 demand_empty_rest_of_line ();
1761 /* XXX Now we come to the Thumb specific bit of code. */
1763 THUMB_SET_FUNC (symbolP
, 1);
1764 ARM_SET_THUMB (symbolP
, 1);
1765 #if defined OBJ_ELF || defined OBJ_COFF
1766 ARM_SET_INTERWORK (symbolP
, support_interwork
);
1771 s_arm (int ignore ATTRIBUTE_UNUSED
)
1774 demand_empty_rest_of_line ();
1778 s_thumb (int ignore ATTRIBUTE_UNUSED
)
1781 demand_empty_rest_of_line ();
1785 s_code (int unused ATTRIBUTE_UNUSED
)
1789 temp
= get_absolute_expression ();
1794 opcode_select (temp
);
1798 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp
);
1803 end_of_line (char * str
)
1805 skip_whitespace (str
);
1807 if (*str
!= '\0' && !inst
.error
)
1808 inst
.error
= _("garbage following instruction");
1812 skip_past_comma (char ** str
)
1814 char * p
= * str
, c
;
1817 while ((c
= *p
) == ' ' || c
== ',')
1820 if (c
== ',' && comma
++)
1828 return comma
? SUCCESS
: FAIL
;
1831 /* Return TRUE if anything in the expression is a bignum. */
1834 walk_no_bignums (symbolS
* sp
)
1836 if (symbol_get_value_expression (sp
)->X_op
== O_big
)
1839 if (symbol_get_value_expression (sp
)->X_add_symbol
)
1841 return (walk_no_bignums (symbol_get_value_expression (sp
)->X_add_symbol
)
1842 || (symbol_get_value_expression (sp
)->X_op_symbol
1843 && walk_no_bignums (symbol_get_value_expression (sp
)->X_op_symbol
)));
1849 static int in_my_get_expression
= 0;
1852 my_get_expression (expressionS
* ep
, char ** str
)
1857 save_in
= input_line_pointer
;
1858 input_line_pointer
= *str
;
1859 in_my_get_expression
= 1;
1860 seg
= expression (ep
);
1861 in_my_get_expression
= 0;
1863 if (ep
->X_op
== O_illegal
)
1865 /* We found a bad expression in md_operand(). */
1866 *str
= input_line_pointer
;
1867 input_line_pointer
= save_in
;
1872 if (seg
!= absolute_section
1873 && seg
!= text_section
1874 && seg
!= data_section
1875 && seg
!= bss_section
1876 && seg
!= undefined_section
)
1878 inst
.error
= _("bad_segment");
1879 *str
= input_line_pointer
;
1880 input_line_pointer
= save_in
;
1885 /* Get rid of any bignums now, so that we don't generate an error for which
1886 we can't establish a line number later on. Big numbers are never valid
1887 in instructions, which is where this routine is always called. */
1888 if (ep
->X_op
== O_big
1889 || (ep
->X_add_symbol
1890 && (walk_no_bignums (ep
->X_add_symbol
)
1892 && walk_no_bignums (ep
->X_op_symbol
)))))
1894 inst
.error
= _("invalid constant");
1895 *str
= input_line_pointer
;
1896 input_line_pointer
= save_in
;
1900 *str
= input_line_pointer
;
1901 input_line_pointer
= save_in
;
1905 /* A standard register must be given at this point.
1906 SHIFT is the place to put it in inst.instruction.
1907 Restores input start point on error.
1908 Returns the reg#, or FAIL. */
1911 reg_required_here (char ** str
, int shift
)
1913 static char buff
[128]; /* XXX */
1915 char * start
= * str
;
1917 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_RN
].htab
)) != FAIL
)
1920 inst
.instruction
|= reg
<< shift
;
1924 /* Restore the start point, we may have got a reg of the wrong class. */
1927 /* In the few cases where we might be able to accept something else
1928 this error can be overridden. */
1929 sprintf (buff
, _("register expected, not '%.100s'"), start
);
1935 /* A Intel Wireless MMX technology register
1936 must be given at this point.
1937 Shift is the place to put it in inst.instruction.
1938 Restores input start point on err.
1939 Returns the reg#, or FAIL. */
1942 wreg_required_here (char ** str
,
1944 enum wreg_type reg_type
)
1946 static char buff
[128];
1948 char * start
= *str
;
1950 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_IWMMXT
].htab
)) != FAIL
)
1952 if (wr_register (reg
)
1953 && (reg_type
== IWMMXT_REG_WR
|| reg_type
== IWMMXT_REG_WR_OR_WC
))
1956 inst
.instruction
|= (reg
^ WR_PREFIX
) << shift
;
1959 else if (wc_register (reg
)
1960 && (reg_type
== IWMMXT_REG_WC
|| reg_type
== IWMMXT_REG_WR_OR_WC
))
1963 inst
.instruction
|= (reg
^ WC_PREFIX
) << shift
;
1966 else if ((wcg_register (reg
) && reg_type
== IWMMXT_REG_WCG
))
1969 inst
.instruction
|= ((reg
^ WC_PREFIX
) - 8) << shift
;
1974 /* Restore the start point, we may have got a reg of the wrong class. */
1977 /* In the few cases where we might be able to accept
1978 something else this error can be overridden. */
1979 sprintf (buff
, _("Intel Wireless MMX technology register expected, not '%.100s'"), start
);
1985 static const struct asm_psr
*
1986 arm_psr_parse (char ** ccp
)
1988 char * start
= * ccp
;
1991 const struct asm_psr
* psr
;
1995 /* Skip to the end of the next word in the input stream. */
2000 while (ISALPHA (c
) || c
== '_');
2002 /* Terminate the word. */
2005 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
2006 feature for ease of use and backwards compatibility. */
2007 if (!strncmp (start
, "cpsr", 4))
2008 strncpy (start
, "CPSR", 4);
2009 else if (!strncmp (start
, "spsr", 4))
2010 strncpy (start
, "SPSR", 4);
2012 /* Now locate the word in the psr hash table. */
2013 psr
= (const struct asm_psr
*) hash_find (arm_psr_hsh
, start
);
2015 /* Restore the input stream. */
2018 /* If we found a valid match, advance the
2019 stream pointer past the end of the word. */
2025 /* Parse the input looking for a PSR flag. */
2028 psr_required_here (char ** str
)
2030 char * start
= * str
;
2031 const struct asm_psr
* psr
;
2033 psr
= arm_psr_parse (str
);
2037 /* If this is the SPSR that is being modified, set the R bit. */
2039 inst
.instruction
|= SPSR_BIT
;
2041 /* Set the psr flags in the MSR instruction. */
2042 inst
.instruction
|= psr
->field
<< PSR_SHIFT
;
2047 /* In the few cases where we might be able to accept
2048 something else this error can be overridden. */
2049 inst
.error
= _("flag for {c}psr instruction expected");
2051 /* Restore the start point. */
2057 co_proc_number (char ** str
)
2059 int processor
, pchar
;
2062 skip_whitespace (*str
);
2065 /* The data sheet seems to imply that just a number on its own is valid
2066 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
2068 if ((processor
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CP
].htab
))
2074 if (pchar
>= '0' && pchar
<= '9')
2076 processor
= pchar
- '0';
2077 if (**str
>= '0' && **str
<= '9')
2079 processor
= processor
* 10 + *(*str
)++ - '0';
2082 inst
.error
= _("illegal co-processor number");
2089 inst
.error
= all_reg_maps
[REG_TYPE_CP
].expected
;
2094 inst
.instruction
|= processor
<< 8;
2099 cp_opc_expr (char ** str
, int where
, int length
)
2103 skip_whitespace (* str
);
2105 memset (&expr
, '\0', sizeof (expr
));
2107 if (my_get_expression (&expr
, str
))
2109 if (expr
.X_op
!= O_constant
)
2111 inst
.error
= _("bad or missing expression");
2115 if ((expr
.X_add_number
& ((1 << length
) - 1)) != expr
.X_add_number
)
2117 inst
.error
= _("immediate co-processor expression too large");
2121 inst
.instruction
|= expr
.X_add_number
<< where
;
2126 cp_reg_required_here (char ** str
, int where
)
2129 char * start
= *str
;
2131 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CN
].htab
)) != FAIL
)
2133 inst
.instruction
|= reg
<< where
;
2137 /* In the few cases where we might be able to accept something else
2138 this error can be overridden. */
2139 inst
.error
= all_reg_maps
[REG_TYPE_CN
].expected
;
2141 /* Restore the start point. */
2147 fp_reg_required_here (char ** str
, int where
)
2150 char * start
= * str
;
2152 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_FN
].htab
)) != FAIL
)
2154 inst
.instruction
|= reg
<< where
;
2158 /* In the few cases where we might be able to accept something else
2159 this error can be overridden. */
2160 inst
.error
= all_reg_maps
[REG_TYPE_FN
].expected
;
2162 /* Restore the start point. */
2168 cp_address_offset (char ** str
)
2172 skip_whitespace (* str
);
2174 if (! is_immediate_prefix (**str
))
2176 inst
.error
= _("immediate expression expected");
2182 if (my_get_expression (& inst
.reloc
.exp
, str
))
2185 if (inst
.reloc
.exp
.X_op
== O_constant
)
2187 offset
= inst
.reloc
.exp
.X_add_number
;
2191 inst
.error
= _("co-processor address must be word aligned");
2195 if (offset
> 1023 || offset
< -1023)
2197 inst
.error
= _("offset too large");
2202 inst
.instruction
|= INDEX_UP
;
2206 inst
.instruction
|= offset
>> 2;
2209 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
2215 cp_address_required_here (char ** str
, int wb_ok
)
2226 skip_whitespace (p
);
2228 if ((reg
= reg_required_here (& p
, 16)) == FAIL
)
2231 skip_whitespace (p
);
2237 skip_whitespace (p
);
2241 /* As an extension to the official ARM syntax we allow:
2243 as a short hand for:
2245 inst
.instruction
|= PRE_INDEX
| INDEX_UP
;
2250 if (skip_past_comma (& p
) == FAIL
)
2252 inst
.error
= _("comma expected after closing square bracket");
2256 skip_whitespace (p
);
2263 write_back
= WRITE_BACK
;
2267 inst
.error
= _("pc may not be used in post-increment");
2271 if (cp_address_offset (& p
) == FAIL
)
2275 pre_inc
= PRE_INDEX
| INDEX_UP
;
2281 /* [Rn], {<expr>} */
2284 skip_whitespace (p
);
2286 if (my_get_expression (& inst
.reloc
.exp
, & p
))
2289 if (inst
.reloc
.exp
.X_op
== O_constant
)
2291 option
= inst
.reloc
.exp
.X_add_number
;
2293 if (option
> 255 || option
< 0)
2295 inst
.error
= _("'option' field too large");
2299 skip_whitespace (p
);
2303 inst
.error
= _("'}' expected at end of 'option' field");
2309 inst
.instruction
|= option
;
2310 inst
.instruction
|= INDEX_UP
;
2315 inst
.error
= _("non-constant expressions for 'option' field not supported");
2321 inst
.error
= _("# or { expected after comma");
2327 /* '['Rn, #expr']'[!] */
2329 if (skip_past_comma (& p
) == FAIL
)
2331 inst
.error
= _("pre-indexed expression expected");
2335 pre_inc
= PRE_INDEX
;
2337 if (cp_address_offset (& p
) == FAIL
)
2340 skip_whitespace (p
);
2344 inst
.error
= _("missing ]");
2348 skip_whitespace (p
);
2350 if (wb_ok
&& *p
== '!')
2354 inst
.error
= _("pc may not be used with write-back");
2359 write_back
= WRITE_BACK
;
2365 if (my_get_expression (&inst
.reloc
.exp
, &p
))
2368 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
2369 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
2370 inst
.reloc
.pc_rel
= 1;
2371 inst
.instruction
|= (REG_PC
<< 16);
2372 pre_inc
= PRE_INDEX
;
2375 inst
.instruction
|= write_back
| pre_inc
;
2381 cp_byte_address_offset (char ** str
)
2385 skip_whitespace (* str
);
2387 if (! is_immediate_prefix (**str
))
2389 inst
.error
= _("immediate expression expected");
2395 if (my_get_expression (& inst
.reloc
.exp
, str
))
2398 if (inst
.reloc
.exp
.X_op
== O_constant
)
2400 offset
= inst
.reloc
.exp
.X_add_number
;
2402 if (offset
> 255 || offset
< -255)
2404 inst
.error
= _("offset too large");
2409 inst
.instruction
|= INDEX_UP
;
2413 inst
.instruction
|= offset
;
2416 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM_S2
;
2422 cp_byte_address_required_here (char ** str
)
2433 skip_whitespace (p
);
2435 if ((reg
= reg_required_here (& p
, 16)) == FAIL
)
2438 skip_whitespace (p
);
2444 if (skip_past_comma (& p
) == SUCCESS
)
2447 write_back
= WRITE_BACK
;
2451 inst
.error
= _("pc may not be used in post-increment");
2455 if (cp_byte_address_offset (& p
) == FAIL
)
2459 pre_inc
= PRE_INDEX
| INDEX_UP
;
2463 /* '['Rn, #expr']'[!] */
2465 if (skip_past_comma (& p
) == FAIL
)
2467 inst
.error
= _("pre-indexed expression expected");
2471 pre_inc
= PRE_INDEX
;
2473 if (cp_byte_address_offset (& p
) == FAIL
)
2476 skip_whitespace (p
);
2480 inst
.error
= _("missing ]");
2484 skip_whitespace (p
);
2490 inst
.error
= _("pc may not be used with write-back");
2495 write_back
= WRITE_BACK
;
2501 if (my_get_expression (&inst
.reloc
.exp
, &p
))
2504 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM_S2
;
2505 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
2506 inst
.reloc
.pc_rel
= 1;
2507 inst
.instruction
|= (REG_PC
<< 16);
2508 pre_inc
= PRE_INDEX
;
2511 inst
.instruction
|= write_back
| pre_inc
;
2519 skip_whitespace (str
);
2524 if (my_get_expression (&inst
.reloc
.exp
, &str
))
2525 inst
.reloc
.exp
.X_op
= O_illegal
;
2528 skip_whitespace (str
);
2532 inst
.reloc
.exp
.X_op
= O_illegal
;
2535 if (inst
.reloc
.exp
.X_op
!= O_constant
2536 || inst
.reloc
.exp
.X_add_number
> 255
2537 || inst
.reloc
.exp
.X_add_number
< 0)
2539 inst
.error
= _("Invalid NOP hint");
2543 /* Arcitectural NOP hints are CPSR sets with no bits selected. */
2544 inst
.instruction
&= 0xf0000000;
2545 inst
.instruction
|= 0x0320f000 + inst
.reloc
.exp
.X_add_number
;
2552 do_empty (char * str
)
2554 /* Do nothing really. */
2563 /* Only one syntax. */
2564 skip_whitespace (str
);
2566 if (reg_required_here (&str
, 12) == FAIL
)
2568 inst
.error
= BAD_ARGS
;
2572 if (skip_past_comma (&str
) == FAIL
)
2574 inst
.error
= _("comma expected after register name");
2578 skip_whitespace (str
);
2580 if ( streq (str
, "CPSR")
2581 || streq (str
, "SPSR")
2582 /* Lower case versions for backwards compatibility. */
2583 || streq (str
, "cpsr")
2584 || streq (str
, "spsr"))
2587 /* This is for backwards compatibility with older toolchains. */
2588 else if ( streq (str
, "cpsr_all")
2589 || streq (str
, "spsr_all"))
2593 inst
.error
= _("CPSR or SPSR expected");
2597 if (* str
== 's' || * str
== 'S')
2598 inst
.instruction
|= SPSR_BIT
;
2604 /* Two possible forms:
2605 "{C|S}PSR_<field>, Rm",
2606 "{C|S}PSR_f, #expression". */
2611 skip_whitespace (str
);
2613 if (psr_required_here (& str
) == FAIL
)
2616 if (skip_past_comma (& str
) == FAIL
)
2618 inst
.error
= _("comma missing after psr flags");
2622 skip_whitespace (str
);
2624 if (reg_required_here (& str
, 0) != FAIL
)
2631 if (! is_immediate_prefix (* str
))
2634 _("only a register or immediate value can follow a psr flag");
2641 if (my_get_expression (& inst
.reloc
.exp
, & str
))
2644 _("only a register or immediate value can follow a psr flag");
2648 #if 0 /* The first edition of the ARM architecture manual stated that
2649 writing anything other than the flags with an immediate operation
2650 had UNPREDICTABLE effects. This constraint was removed in the
2651 second edition of the specification. */
2652 if ((cpu_variant
& ARM_EXT_V5
) != ARM_EXT_V5
2653 && inst
.instruction
& ((PSR_c
| PSR_x
| PSR_s
) << PSR_SHIFT
))
2655 inst
.error
= _("immediate value cannot be used to set this field");
2660 inst
.instruction
|= INST_IMMEDIATE
;
2662 if (inst
.reloc
.exp
.X_add_symbol
)
2664 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
2665 inst
.reloc
.pc_rel
= 0;
2669 unsigned value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
2671 if (value
== (unsigned) FAIL
)
2673 inst
.error
= _("invalid constant");
2677 inst
.instruction
|= value
;
2684 /* Long Multiply Parser
2685 UMULL RdLo, RdHi, Rm, Rs
2686 SMULL RdLo, RdHi, Rm, Rs
2687 UMLAL RdLo, RdHi, Rm, Rs
2688 SMLAL RdLo, RdHi, Rm, Rs. */
2691 do_mull (char * str
)
2693 int rdlo
, rdhi
, rm
, rs
;
2695 /* Only one format "rdlo, rdhi, rm, rs". */
2696 skip_whitespace (str
);
2698 if ((rdlo
= reg_required_here (&str
, 12)) == FAIL
)
2700 inst
.error
= BAD_ARGS
;
2704 if (skip_past_comma (&str
) == FAIL
2705 || (rdhi
= reg_required_here (&str
, 16)) == FAIL
)
2707 inst
.error
= BAD_ARGS
;
2711 if (skip_past_comma (&str
) == FAIL
2712 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
2714 inst
.error
= BAD_ARGS
;
2718 /* rdhi, rdlo and rm must all be different. */
2719 if (rdlo
== rdhi
|| rdlo
== rm
|| rdhi
== rm
)
2720 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
2722 if (skip_past_comma (&str
) == FAIL
2723 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
2725 inst
.error
= BAD_ARGS
;
2729 if (rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
)
2731 inst
.error
= BAD_PC
;
2743 /* Only one format "rd, rm, rs". */
2744 skip_whitespace (str
);
2746 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
2748 inst
.error
= BAD_ARGS
;
2754 inst
.error
= BAD_PC
;
2758 if (skip_past_comma (&str
) == FAIL
2759 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
2761 inst
.error
= BAD_ARGS
;
2767 inst
.error
= BAD_PC
;
2772 as_tsktsk (_("rd and rm should be different in mul"));
2774 if (skip_past_comma (&str
) == FAIL
2775 || (rm
= reg_required_here (&str
, 8)) == FAIL
)
2777 inst
.error
= BAD_ARGS
;
2783 inst
.error
= BAD_PC
;
2795 /* Only one format "rd, rm, rs, rn". */
2796 skip_whitespace (str
);
2798 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
2800 inst
.error
= BAD_ARGS
;
2806 inst
.error
= BAD_PC
;
2810 if (skip_past_comma (&str
) == FAIL
2811 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
2813 inst
.error
= BAD_ARGS
;
2819 inst
.error
= BAD_PC
;
2824 as_tsktsk (_("rd and rm should be different in mla"));
2826 if (skip_past_comma (&str
) == FAIL
2827 || (rd
= reg_required_here (&str
, 8)) == FAIL
2828 || skip_past_comma (&str
) == FAIL
2829 || (rm
= reg_required_here (&str
, 12)) == FAIL
)
2831 inst
.error
= BAD_ARGS
;
2835 if (rd
== REG_PC
|| rm
== REG_PC
)
2837 inst
.error
= BAD_PC
;
2844 /* Expects *str -> the characters "acc0", possibly with leading blanks.
2845 Advances *str to the next non-alphanumeric.
2846 Returns 0, or else FAIL (in which case sets inst.error).
2848 (In a future XScale, there may be accumulators other than zero.
2849 At that time this routine and its callers can be upgraded to suit.) */
2852 accum0_required_here (char ** str
)
2854 static char buff
[128]; /* Note the address is taken. Hence, static. */
2857 int result
= 0; /* The accum number. */
2859 skip_whitespace (p
);
2861 *str
= p
; /* Advance caller's string pointer too. */
2866 *--p
= 0; /* Aap nul into input buffer at non-alnum. */
2868 if (! ( streq (*str
, "acc0") || streq (*str
, "ACC0")))
2870 sprintf (buff
, _("acc0 expected, not '%.100s'"), *str
);
2875 *p
= c
; /* Unzap. */
2876 *str
= p
; /* Caller's string pointer to after match. */
2881 ldst_extend_v4 (char ** str
)
2890 if (my_get_expression (& inst
.reloc
.exp
, str
))
2893 if (inst
.reloc
.exp
.X_op
== O_constant
)
2895 int value
= inst
.reloc
.exp
.X_add_number
;
2897 if (value
< -255 || value
> 255)
2899 inst
.error
= _("address offset too large");
2909 /* Halfword and signextension instructions have the
2910 immediate value split across bits 11..8 and bits 3..0. */
2911 inst
.instruction
|= (add
| HWOFFSET_IMM
2912 | ((value
>> 4) << 8) | (value
& 0xF));
2916 inst
.instruction
|= HWOFFSET_IMM
;
2917 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
2918 inst
.reloc
.pc_rel
= 0;
2931 if (reg_required_here (str
, 0) == FAIL
)
2934 inst
.instruction
|= add
;
2939 /* Expects **str -> after a comma. May be leading blanks.
2940 Advances *str, recognizing a load mode, and setting inst.instruction.
2941 Returns rn, or else FAIL (in which case may set inst.error
2942 and not advance str)
2944 Note: doesn't know Rd, so no err checks that require such knowledge. */
2947 ld_mode_required_here (char ** string
)
2949 char * str
= * string
;
2953 skip_whitespace (str
);
2959 skip_whitespace (str
);
2961 if ((rn
= reg_required_here (& str
, 16)) == FAIL
)
2964 skip_whitespace (str
);
2970 if (skip_past_comma (& str
) == SUCCESS
)
2972 /* [Rn],... (post inc) */
2973 if (ldst_extend_v4 (&str
) == FAIL
)
2978 skip_whitespace (str
);
2983 inst
.instruction
|= WRITE_BACK
;
2986 inst
.instruction
|= INDEX_UP
| HWOFFSET_IMM
;
2992 if (skip_past_comma (& str
) == FAIL
)
2994 inst
.error
= _("pre-indexed expression expected");
3000 if (ldst_extend_v4 (&str
) == FAIL
)
3003 skip_whitespace (str
);
3005 if (* str
++ != ']')
3007 inst
.error
= _("missing ]");
3011 skip_whitespace (str
);
3016 inst
.instruction
|= WRITE_BACK
;
3020 else if (* str
== '=') /* ldr's "r,=label" syntax */
3021 /* We should never reach here, because <text> = <expression> is
3022 caught gas/read.c read_a_source_file() as a .set operation. */
3024 else /* PC +- 8 bit immediate offset. */
3026 if (my_get_expression (& inst
.reloc
.exp
, & str
))
3029 inst
.instruction
|= HWOFFSET_IMM
; /* The I bit. */
3030 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
3031 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
3032 inst
.reloc
.pc_rel
= 1;
3033 inst
.instruction
|= (REG_PC
<< 16);
3039 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
3045 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
3046 SMLAxy{cond} Rd,Rm,Rs,Rn
3047 SMLAWy{cond} Rd,Rm,Rs,Rn
3048 Error if any register is R15. */
3051 do_smla (char * str
)
3055 skip_whitespace (str
);
3057 if ((rd
= reg_required_here (& str
, 16)) == FAIL
3058 || skip_past_comma (& str
) == FAIL
3059 || (rm
= reg_required_here (& str
, 0)) == FAIL
3060 || skip_past_comma (& str
) == FAIL
3061 || (rs
= reg_required_here (& str
, 8)) == FAIL
3062 || skip_past_comma (& str
) == FAIL
3063 || (rn
= reg_required_here (& str
, 12)) == FAIL
)
3064 inst
.error
= BAD_ARGS
;
3066 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
|| rn
== REG_PC
)
3067 inst
.error
= BAD_PC
;
3073 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
3074 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
3075 Error if any register is R15.
3076 Warning if Rdlo == Rdhi. */
3079 do_smlal (char * str
)
3081 int rdlo
, rdhi
, rm
, rs
;
3083 skip_whitespace (str
);
3085 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
3086 || skip_past_comma (& str
) == FAIL
3087 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
3088 || skip_past_comma (& str
) == FAIL
3089 || (rm
= reg_required_here (& str
, 0)) == FAIL
3090 || skip_past_comma (& str
) == FAIL
3091 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
3093 inst
.error
= BAD_ARGS
;
3097 if (rdlo
== REG_PC
|| rdhi
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
3099 inst
.error
= BAD_PC
;
3104 as_tsktsk (_("rdhi and rdlo must be different"));
3109 /* ARM V5E (El Segundo) signed-multiply (argument parse)
3110 SMULxy{cond} Rd,Rm,Rs
3111 Error if any register is R15. */
3114 do_smul (char * str
)
3118 skip_whitespace (str
);
3120 if ((rd
= reg_required_here (& str
, 16)) == FAIL
3121 || skip_past_comma (& str
) == FAIL
3122 || (rm
= reg_required_here (& str
, 0)) == FAIL
3123 || skip_past_comma (& str
) == FAIL
3124 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
3125 inst
.error
= BAD_ARGS
;
3127 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
3128 inst
.error
= BAD_PC
;
3134 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
3135 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
3136 Error if any register is R15. */
3139 do_qadd (char * str
)
3143 skip_whitespace (str
);
3145 if ((rd
= reg_required_here (& str
, 12)) == FAIL
3146 || skip_past_comma (& str
) == FAIL
3147 || (rm
= reg_required_here (& str
, 0)) == FAIL
3148 || skip_past_comma (& str
) == FAIL
3149 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
3150 inst
.error
= BAD_ARGS
;
3152 else if (rd
== REG_PC
|| rm
== REG_PC
|| rn
== REG_PC
)
3153 inst
.error
= BAD_PC
;
3159 /* ARM V5E (el Segundo)
3160 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3161 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3163 These are equivalent to the XScale instructions MAR and MRA,
3164 respectively, when coproc == 0, opcode == 0, and CRm == 0.
3166 Result unpredicatable if Rd or Rn is R15. */
3169 do_co_reg2c (char * str
)
3173 skip_whitespace (str
);
3175 if (co_proc_number (& str
) == FAIL
)
3178 inst
.error
= BAD_ARGS
;
3182 if (skip_past_comma (& str
) == FAIL
3183 || cp_opc_expr (& str
, 4, 4) == FAIL
)
3186 inst
.error
= BAD_ARGS
;
3190 if (skip_past_comma (& str
) == FAIL
3191 || (rd
= reg_required_here (& str
, 12)) == FAIL
)
3194 inst
.error
= BAD_ARGS
;
3198 if (skip_past_comma (& str
) == FAIL
3199 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
3202 inst
.error
= BAD_ARGS
;
3206 /* Unpredictable result if rd or rn is R15. */
3207 if (rd
== REG_PC
|| rn
== REG_PC
)
3209 (_("Warning: instruction unpredictable when using r15"));
3211 if (skip_past_comma (& str
) == FAIL
3212 || cp_reg_required_here (& str
, 0) == FAIL
)
3215 inst
.error
= BAD_ARGS
;
3222 /* ARM V5 count-leading-zeroes instruction (argument parse)
3223 CLZ{<cond>} <Rd>, <Rm>
3224 Condition defaults to COND_ALWAYS.
3225 Error if Rd or Rm are R15. */
3232 skip_whitespace (str
);
3234 if (((rd
= reg_required_here (& str
, 12)) == FAIL
)
3235 || (skip_past_comma (& str
) == FAIL
)
3236 || ((rm
= reg_required_here (& str
, 0)) == FAIL
))
3237 inst
.error
= BAD_ARGS
;
3239 else if (rd
== REG_PC
|| rm
== REG_PC
)
3240 inst
.error
= BAD_PC
;
3246 /* ARM V5 (argument parse)
3247 LDC2{L} <coproc>, <CRd>, <addressing mode>
3248 STC2{L} <coproc>, <CRd>, <addressing mode>
3249 Instruction is not conditional, and has 0xf in the condition field.
3250 Otherwise, it's the same as LDC/STC. */
3253 do_lstc2 (char * str
)
3255 skip_whitespace (str
);
3257 if (co_proc_number (& str
) == FAIL
)
3260 inst
.error
= BAD_ARGS
;
3262 else if (skip_past_comma (& str
) == FAIL
3263 || cp_reg_required_here (& str
, 12) == FAIL
)
3266 inst
.error
= BAD_ARGS
;
3268 else if (skip_past_comma (& str
) == FAIL
3269 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
3272 inst
.error
= BAD_ARGS
;
3278 /* ARM V5 (argument parse)
3279 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
3280 Instruction is not conditional, and has 0xf in the condition field.
3281 Otherwise, it's the same as CDP. */
3284 do_cdp2 (char * str
)
3286 skip_whitespace (str
);
3288 if (co_proc_number (& str
) == FAIL
)
3291 inst
.error
= BAD_ARGS
;
3295 if (skip_past_comma (& str
) == FAIL
3296 || cp_opc_expr (& str
, 20,4) == FAIL
)
3299 inst
.error
= BAD_ARGS
;
3303 if (skip_past_comma (& str
) == FAIL
3304 || cp_reg_required_here (& str
, 12) == FAIL
)
3307 inst
.error
= BAD_ARGS
;
3311 if (skip_past_comma (& str
) == FAIL
3312 || cp_reg_required_here (& str
, 16) == FAIL
)
3315 inst
.error
= BAD_ARGS
;
3319 if (skip_past_comma (& str
) == FAIL
3320 || cp_reg_required_here (& str
, 0) == FAIL
)
3323 inst
.error
= BAD_ARGS
;
3327 if (skip_past_comma (& str
) == SUCCESS
)
3329 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
3332 inst
.error
= BAD_ARGS
;
3340 /* ARM V5 (argument parse)
3341 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3342 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3343 Instruction is not conditional, and has 0xf in the condition field.
3344 Otherwise, it's the same as MCR/MRC. */
3347 do_co_reg2 (char * str
)
3349 skip_whitespace (str
);
3351 if (co_proc_number (& str
) == FAIL
)
3354 inst
.error
= BAD_ARGS
;
3358 if (skip_past_comma (& str
) == FAIL
3359 || cp_opc_expr (& str
, 21, 3) == FAIL
)
3362 inst
.error
= BAD_ARGS
;
3366 if (skip_past_comma (& str
) == FAIL
3367 || reg_required_here (& str
, 12) == FAIL
)
3370 inst
.error
= BAD_ARGS
;
3374 if (skip_past_comma (& str
) == FAIL
3375 || cp_reg_required_here (& str
, 16) == FAIL
)
3378 inst
.error
= BAD_ARGS
;
3382 if (skip_past_comma (& str
) == FAIL
3383 || cp_reg_required_here (& str
, 0) == FAIL
)
3386 inst
.error
= BAD_ARGS
;
3390 if (skip_past_comma (& str
) == SUCCESS
)
3392 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
3395 inst
.error
= BAD_ARGS
;
3408 skip_whitespace (str
);
3410 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
3412 inst
.error
= BAD_ARGS
;
3416 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
3418 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
3423 /* ARM v5TEJ. Jump to Jazelle code. */
3430 skip_whitespace (str
);
3432 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
3434 inst
.error
= BAD_ARGS
;
3438 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
3440 as_tsktsk (_("use of r15 in bxj is not really useful"));
3445 /* ARM V6 umaal (argument parse). */
3448 do_umaal (char * str
)
3450 int rdlo
, rdhi
, rm
, rs
;
3452 skip_whitespace (str
);
3453 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
3454 || skip_past_comma (& str
) == FAIL
3455 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
3456 || skip_past_comma (& str
) == FAIL
3457 || (rm
= reg_required_here (& str
, 0)) == FAIL
3458 || skip_past_comma (& str
) == FAIL
3459 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
3461 inst
.error
= BAD_ARGS
;
3465 if (rdlo
== REG_PC
|| rdhi
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
3467 inst
.error
= BAD_PC
;
3474 /* ARM V6 strex (argument parse). */
3477 do_strex (char * str
)
3481 /* Parse Rd, Rm,. */
3482 skip_whitespace (str
);
3483 if ((rd
= reg_required_here (& str
, 12)) == FAIL
3484 || skip_past_comma (& str
) == FAIL
3485 || (rm
= reg_required_here (& str
, 0)) == FAIL
3486 || skip_past_comma (& str
) == FAIL
)
3488 inst
.error
= BAD_ARGS
;
3491 if (rd
== REG_PC
|| rm
== REG_PC
)
3493 inst
.error
= BAD_PC
;
3498 inst
.error
= _("Rd equal to Rm or Rn yields unpredictable results");
3502 /* Skip past '['. */
3503 if ((strlen (str
) >= 1)
3504 && strncmp (str
, "[", 1) == 0)
3507 skip_whitespace (str
);
3510 if ((rn
= reg_required_here (& str
, 16)) == FAIL
)
3512 inst
.error
= BAD_ARGS
;
3515 else if (rn
== REG_PC
)
3517 inst
.error
= BAD_PC
;
3522 inst
.error
= _("Rd equal to Rm or Rn yields unpredictable results");
3525 skip_whitespace (str
);
3527 /* Skip past ']'. */
3528 if ((strlen (str
) >= 1)
3529 && strncmp (str
, "]", 1) == 0)
3535 /* KIND indicates what kind of shifts are accepted. */
3538 decode_shift (char ** str
, int kind
)
3540 const struct asm_shift_name
* shift
;
3544 skip_whitespace (* str
);
3546 for (p
= * str
; ISALPHA (* p
); p
++)
3551 inst
.error
= _("shift expression expected");
3557 shift
= (const struct asm_shift_name
*) hash_find (arm_shift_hsh
, * str
);
3562 inst
.error
= _("shift expression expected");
3566 assert (shift
->properties
->index
== shift_properties
[shift
->properties
->index
].index
);
3568 if (kind
== SHIFT_LSL_OR_ASR_IMMEDIATE
3569 && shift
->properties
->index
!= SHIFT_LSL
3570 && shift
->properties
->index
!= SHIFT_ASR
)
3572 inst
.error
= _("'LSL' or 'ASR' required");
3575 else if (kind
== SHIFT_LSL_IMMEDIATE
3576 && shift
->properties
->index
!= SHIFT_LSL
)
3578 inst
.error
= _("'LSL' required");
3581 else if (kind
== SHIFT_ASR_IMMEDIATE
3582 && shift
->properties
->index
!= SHIFT_ASR
)
3584 inst
.error
= _("'ASR' required");
3588 if (shift
->properties
->index
== SHIFT_RRX
)
3591 inst
.instruction
|= shift
->properties
->bit_field
;
3595 skip_whitespace (p
);
3597 if (kind
== NO_SHIFT_RESTRICT
&& reg_required_here (& p
, 8) != FAIL
)
3599 inst
.instruction
|= shift
->properties
->bit_field
| SHIFT_BY_REG
;
3603 else if (! is_immediate_prefix (* p
))
3605 inst
.error
= (NO_SHIFT_RESTRICT
3606 ? _("shift requires register or #expression")
3607 : _("shift requires #expression"));
3615 if (my_get_expression (& inst
.reloc
.exp
, & p
))
3618 /* Validate some simple #expressions. */
3619 if (inst
.reloc
.exp
.X_op
== O_constant
)
3621 unsigned num
= inst
.reloc
.exp
.X_add_number
;
3623 /* Reject operations greater than 32. */
3625 /* Reject a shift of 0 unless the mode allows it. */
3626 || (num
== 0 && shift
->properties
->allows_0
== 0)
3627 /* Reject a shift of 32 unless the mode allows it. */
3628 || (num
== 32 && shift
->properties
->allows_32
== 0)
3631 /* As a special case we allow a shift of zero for
3632 modes that do not support it to be recoded as an
3633 logical shift left of zero (ie nothing). We warn
3634 about this though. */
3637 as_warn (_("shift of 0 ignored."));
3638 shift
= & shift_names
[0];
3639 assert (shift
->properties
->index
== SHIFT_LSL
);
3643 inst
.error
= _("invalid immediate shift");
3648 /* Shifts of 32 are encoded as 0, for those shifts that
3653 inst
.instruction
|= (num
<< 7) | shift
->properties
->bit_field
;
3657 inst
.reloc
.type
= BFD_RELOC_ARM_SHIFT_IMM
;
3658 inst
.reloc
.pc_rel
= 0;
3659 inst
.instruction
|= shift
->properties
->bit_field
;
3667 do_sat (char ** str
, int bias
)
3672 skip_whitespace (*str
);
3674 /* Parse <Rd>, field. */
3675 if ((rd
= reg_required_here (str
, 12)) == FAIL
3676 || skip_past_comma (str
) == FAIL
)
3678 inst
.error
= BAD_ARGS
;
3683 inst
.error
= BAD_PC
;
3687 /* Parse #<immed>, field. */
3688 if (is_immediate_prefix (**str
))
3692 inst
.error
= _("immediate expression expected");
3695 if (my_get_expression (&expr
, str
))
3697 inst
.error
= _("bad expression");
3700 if (expr
.X_op
!= O_constant
)
3702 inst
.error
= _("constant expression expected");
3705 if (expr
.X_add_number
+ bias
< 0
3706 || expr
.X_add_number
+ bias
> 31)
3708 inst
.error
= _("immediate value out of range");
3711 inst
.instruction
|= (expr
.X_add_number
+ bias
) << 16;
3712 if (skip_past_comma (str
) == FAIL
)
3714 inst
.error
= BAD_ARGS
;
3718 /* Parse <Rm> field. */
3719 if ((rm
= reg_required_here (str
, 0)) == FAIL
)
3721 inst
.error
= BAD_ARGS
;
3726 inst
.error
= BAD_PC
;
3730 if (skip_past_comma (str
) == SUCCESS
)
3731 decode_shift (str
, SHIFT_LSL_OR_ASR_IMMEDIATE
);
3734 /* ARM V6 ssat (argument parse). */
3737 do_ssat (char * str
)
3739 do_sat (&str
, /*bias=*/-1);
3743 /* ARM V6 usat (argument parse). */
3746 do_usat (char * str
)
3748 do_sat (&str
, /*bias=*/0);
3753 do_sat16 (char ** str
, int bias
)
3758 skip_whitespace (*str
);
3760 /* Parse the <Rd> field. */
3761 if ((rd
= reg_required_here (str
, 12)) == FAIL
3762 || skip_past_comma (str
) == FAIL
)
3764 inst
.error
= BAD_ARGS
;
3769 inst
.error
= BAD_PC
;
3773 /* Parse #<immed>, field. */
3774 if (is_immediate_prefix (**str
))
3778 inst
.error
= _("immediate expression expected");
3781 if (my_get_expression (&expr
, str
))
3783 inst
.error
= _("bad expression");
3786 if (expr
.X_op
!= O_constant
)
3788 inst
.error
= _("constant expression expected");
3791 if (expr
.X_add_number
+ bias
< 0
3792 || expr
.X_add_number
+ bias
> 15)
3794 inst
.error
= _("immediate value out of range");
3797 inst
.instruction
|= (expr
.X_add_number
+ bias
) << 16;
3798 if (skip_past_comma (str
) == FAIL
)
3800 inst
.error
= BAD_ARGS
;
3804 /* Parse <Rm> field. */
3805 if ((rm
= reg_required_here (str
, 0)) == FAIL
)
3807 inst
.error
= BAD_ARGS
;
3812 inst
.error
= BAD_PC
;
3817 /* ARM V6 ssat16 (argument parse). */
3820 do_ssat16 (char * str
)
3822 do_sat16 (&str
, /*bias=*/-1);
3827 do_usat16 (char * str
)
3829 do_sat16 (&str
, /*bias=*/0);
3834 do_cps_mode (char ** str
)
3838 skip_whitespace (*str
);
3840 if (! is_immediate_prefix (**str
))
3842 inst
.error
= _("immediate expression expected");
3846 (*str
)++; /* Strip off the immediate signifier. */
3847 if (my_get_expression (&expr
, str
))
3849 inst
.error
= _("bad expression");
3853 if (expr
.X_op
!= O_constant
)
3855 inst
.error
= _("constant expression expected");
3859 /* The mode is a 5 bit field. Valid values are 0-31. */
3860 if (((unsigned) expr
.X_add_number
) > 31
3861 || (inst
.reloc
.exp
.X_add_number
) < 0)
3863 inst
.error
= _("invalid constant");
3867 inst
.instruction
|= expr
.X_add_number
;
3870 /* ARM V6 srs (argument parse). */
3876 skip_whitespace (str
);
3877 exclam
= strchr (str
, '!');
3885 inst
.instruction
|= WRITE_BACK
;
3891 /* ARM V6 SMMUL (argument parse). */
3894 do_smmul (char * str
)
3898 skip_whitespace (str
);
3899 if ((rd
= reg_required_here (&str
, 16)) == FAIL
3900 || skip_past_comma (&str
) == FAIL
3901 || (rm
= reg_required_here (&str
, 0)) == FAIL
3902 || skip_past_comma (&str
) == FAIL
3903 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
3905 inst
.error
= BAD_ARGS
;
3913 inst
.error
= BAD_PC
;
3920 /* ARM V6 SMLALD (argument parse). */
3923 do_smlald (char * str
)
3925 int rdlo
, rdhi
, rm
, rs
;
3927 skip_whitespace (str
);
3928 if ((rdlo
= reg_required_here (&str
, 12)) == FAIL
3929 || skip_past_comma (&str
) == FAIL
3930 || (rdhi
= reg_required_here (&str
, 16)) == FAIL
3931 || skip_past_comma (&str
) == FAIL
3932 || (rm
= reg_required_here (&str
, 0)) == FAIL
3933 || skip_past_comma (&str
) == FAIL
3934 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
3936 inst
.error
= BAD_ARGS
;
3945 inst
.error
= BAD_PC
;
3952 /* ARM V6 SMLAD (argument parse). Signed multiply accumulate dual.
3953 smlad{x}{<cond>} Rd, Rm, Rs, Rn */
3956 do_smlad (char * str
)
3960 skip_whitespace (str
);
3961 if ((rd
= reg_required_here (&str
, 16)) == FAIL
3962 || skip_past_comma (&str
) == FAIL
3963 || (rm
= reg_required_here (&str
, 0)) == FAIL
3964 || skip_past_comma (&str
) == FAIL
3965 || (rs
= reg_required_here (&str
, 8)) == FAIL
3966 || skip_past_comma (&str
) == FAIL
3967 || (rn
= reg_required_here (&str
, 12)) == FAIL
)
3969 inst
.error
= BAD_ARGS
;
3978 inst
.error
= BAD_PC
;
3985 /* Returns true if the endian-specifier indicates big-endianness. */
3988 do_endian_specifier (char * str
)
3992 skip_whitespace (str
);
3993 if (strlen (str
) < 2)
3994 inst
.error
= _("missing endian specifier");
3995 else if (strncasecmp (str
, "BE", 2) == 0)
4000 else if (strncasecmp (str
, "LE", 2) == 0)
4003 inst
.error
= _("valid endian specifiers are be or le");
4010 /* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
4011 preserving the other bits.
4013 setend <endian_specifier>, where <endian_specifier> is either
4017 do_setend (char * str
)
4019 if (do_endian_specifier (str
))
4020 inst
.instruction
|= 0x200;
4025 SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
4026 Condition defaults to COND_ALWAYS.
4027 Error if any register uses R15. */
4030 do_sxth (char * str
)
4034 int rotation_clear_mask
= 0xfffff3ff;
4035 int rotation_eight_mask
= 0x00000400;
4036 int rotation_sixteen_mask
= 0x00000800;
4037 int rotation_twenty_four_mask
= 0x00000c00;
4039 skip_whitespace (str
);
4040 if ((rd
= reg_required_here (&str
, 12)) == FAIL
4041 || skip_past_comma (&str
) == FAIL
4042 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4044 inst
.error
= BAD_ARGS
;
4048 else if (rd
== REG_PC
|| rm
== REG_PC
)
4050 inst
.error
= BAD_PC
;
4054 /* Zero out the rotation field. */
4055 inst
.instruction
&= rotation_clear_mask
;
4057 /* Check for lack of optional rotation field. */
4058 if (skip_past_comma (&str
) == FAIL
)
4064 /* Move past 'ROR'. */
4065 skip_whitespace (str
);
4066 if (strncasecmp (str
, "ROR", 3) == 0)
4070 inst
.error
= _("missing rotation field after comma");
4074 /* Get the immediate constant. */
4075 skip_whitespace (str
);
4076 if (is_immediate_prefix (* str
))
4080 inst
.error
= _("immediate expression expected");
4084 if (my_get_expression (&expr
, &str
))
4086 inst
.error
= _("bad expression");
4090 if (expr
.X_op
!= O_constant
)
4092 inst
.error
= _("constant expression expected");
4096 switch (expr
.X_add_number
)
4099 /* Rotation field has already been zeroed. */
4102 inst
.instruction
|= rotation_eight_mask
;
4106 inst
.instruction
|= rotation_sixteen_mask
;
4110 inst
.instruction
|= rotation_twenty_four_mask
;
4114 inst
.error
= _("rotation can be 8, 16, 24 or 0 when field is ommited");
4121 /* ARM V6 SXTAH extracts a 16-bit value from a register, sign
4122 extends it to 32-bits, and adds the result to a value in another
4123 register. You can specify a rotation by 0, 8, 16, or 24 bits
4124 before extracting the 16-bit value.
4125 SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
4126 Condition defaults to COND_ALWAYS.
4127 Error if any register uses R15. */
4130 do_sxtah (char * str
)
4134 int rotation_clear_mask
= 0xfffff3ff;
4135 int rotation_eight_mask
= 0x00000400;
4136 int rotation_sixteen_mask
= 0x00000800;
4137 int rotation_twenty_four_mask
= 0x00000c00;
4139 skip_whitespace (str
);
4140 if ((rd
= reg_required_here (&str
, 12)) == FAIL
4141 || skip_past_comma (&str
) == FAIL
4142 || (rn
= reg_required_here (&str
, 16)) == FAIL
4143 || skip_past_comma (&str
) == FAIL
4144 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4146 inst
.error
= BAD_ARGS
;
4150 else if (rd
== REG_PC
|| rn
== REG_PC
|| rm
== REG_PC
)
4152 inst
.error
= BAD_PC
;
4156 /* Zero out the rotation field. */
4157 inst
.instruction
&= rotation_clear_mask
;
4159 /* Check for lack of optional rotation field. */
4160 if (skip_past_comma (&str
) == FAIL
)
4166 /* Move past 'ROR'. */
4167 skip_whitespace (str
);
4168 if (strncasecmp (str
, "ROR", 3) == 0)
4172 inst
.error
= _("missing rotation field after comma");
4176 /* Get the immediate constant. */
4177 skip_whitespace (str
);
4178 if (is_immediate_prefix (* str
))
4182 inst
.error
= _("immediate expression expected");
4186 if (my_get_expression (&expr
, &str
))
4188 inst
.error
= _("bad expression");
4192 if (expr
.X_op
!= O_constant
)
4194 inst
.error
= _("constant expression expected");
4198 switch (expr
.X_add_number
)
4201 /* Rotation field has already been zeroed. */
4205 inst
.instruction
|= rotation_eight_mask
;
4209 inst
.instruction
|= rotation_sixteen_mask
;
4213 inst
.instruction
|= rotation_twenty_four_mask
;
4217 inst
.error
= _("rotation can be 8, 16, 24 or 0 when field is ommited");
4225 /* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
4226 word at the specified address and the following word
4228 Unconditionally executed.
4229 Error if Rn is R15. */
4236 skip_whitespace (str
);
4238 if ((rn
= reg_required_here (&str
, 16)) == FAIL
)
4243 inst
.error
= BAD_PC
;
4247 skip_whitespace (str
);
4251 inst
.instruction
|= WRITE_BACK
;
4257 /* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
4258 register (argument parse).
4260 Condition defaults to COND_ALWAYS.
4261 Error if Rd or Rm are R15. */
4268 skip_whitespace (str
);
4270 if ((rd
= reg_required_here (&str
, 12)) == FAIL
4271 || skip_past_comma (&str
) == FAIL
4272 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4273 inst
.error
= BAD_ARGS
;
4275 else if (rd
== REG_PC
|| rm
== REG_PC
)
4276 inst
.error
= BAD_PC
;
4282 /* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
4283 QADD16{<cond>} <Rd>, <Rn>, <Rm>
4284 Condition defaults to COND_ALWAYS.
4285 Error if Rd, Rn or Rm are R15. */
4288 do_qadd16 (char * str
)
4292 skip_whitespace (str
);
4294 if ((rd
= reg_required_here (&str
, 12)) == FAIL
4295 || skip_past_comma (&str
) == FAIL
4296 || (rn
= reg_required_here (&str
, 16)) == FAIL
4297 || skip_past_comma (&str
) == FAIL
4298 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4299 inst
.error
= BAD_ARGS
;
4301 else if (rd
== REG_PC
|| rm
== REG_PC
|| rn
== REG_PC
)
4302 inst
.error
= BAD_PC
;
4309 do_pkh_core (char * str
, int shift
)
4313 skip_whitespace (str
);
4314 if (((rd
= reg_required_here (&str
, 12)) == FAIL
)
4315 || (skip_past_comma (&str
) == FAIL
)
4316 || ((rn
= reg_required_here (&str
, 16)) == FAIL
)
4317 || (skip_past_comma (&str
) == FAIL
)
4318 || ((rm
= reg_required_here (&str
, 0)) == FAIL
))
4320 inst
.error
= BAD_ARGS
;
4324 else if (rd
== REG_PC
|| rn
== REG_PC
|| rm
== REG_PC
)
4326 inst
.error
= BAD_PC
;
4330 /* Check for optional shift immediate constant. */
4331 if (skip_past_comma (&str
) == FAIL
)
4333 if (shift
== SHIFT_ASR_IMMEDIATE
)
4335 /* If the shift specifier is ommited, turn the instruction
4336 into pkhbt rd, rm, rn. First, switch the instruction
4337 code, and clear the rn and rm fields. */
4338 inst
.instruction
&= 0xfff0f010;
4339 /* Now, re-encode the registers. */
4340 inst
.instruction
|= (rm
<< 16) | rn
;
4345 decode_shift (&str
, shift
);
4348 /* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
4349 PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
4350 Condition defaults to COND_ALWAYS.
4351 Error if Rd, Rn or Rm are R15. */
4354 do_pkhbt (char * str
)
4356 do_pkh_core (str
, SHIFT_LSL_IMMEDIATE
);
4359 /* ARM V6 PKHTB (Argument Parse). */
4362 do_pkhtb (char * str
)
4364 do_pkh_core (str
, SHIFT_ASR_IMMEDIATE
);
4367 /* ARM V6 Load Register Exclusive instruction (argument parse).
4368 LDREX{,B,D,H}{<cond>} <Rd, [<Rn>]
4369 Condition defaults to COND_ALWAYS.
4370 Error if Rd or Rn are R15.
4371 See ARMARMv6 A4.1.27: LDREX. */
4374 do_ldrex (char * str
)
4378 skip_whitespace (str
);
4381 if (((rd
= reg_required_here (&str
, 12)) == FAIL
)
4382 || (skip_past_comma (&str
) == FAIL
))
4384 inst
.error
= BAD_ARGS
;
4387 else if (rd
== REG_PC
)
4389 inst
.error
= BAD_PC
;
4392 skip_whitespace (str
);
4394 /* Skip past '['. */
4395 if ((strlen (str
) >= 1)
4396 &&strncmp (str
, "[", 1) == 0)
4398 skip_whitespace (str
);
4401 if ((rn
= reg_required_here (&str
, 16)) == FAIL
)
4403 inst
.error
= BAD_ARGS
;
4406 else if (rn
== REG_PC
)
4408 inst
.error
= BAD_PC
;
4411 skip_whitespace (str
);
4413 /* Skip past ']'. */
4414 if ((strlen (str
) >= 1)
4415 && strncmp (str
, "]", 1) == 0)
4421 /* ARM V6 change processor state instruction (argument parse)
4422 CPS, CPSIE, CSPID . */
4432 do_cps_flags (char ** str
, int thumb_p
)
4437 unsigned long arm_value
;
4438 unsigned long thumb_value
;
4440 static struct cps_flag flag_table
[] =
4449 skip_whitespace (*str
);
4451 /* Get the a, f and i flags. */
4452 while (**str
&& **str
!= ',')
4455 struct cps_flag
*q
= flag_table
+ sizeof (flag_table
)/sizeof (*p
);
4457 for (p
= flag_table
; p
< q
; ++p
)
4458 if (strncasecmp (*str
, &p
->character
, 1) == 0)
4460 inst
.instruction
|= (thumb_p
? p
->thumb_value
: p
->arm_value
);
4466 inst
.error
= _("unrecognized flag");
4473 inst
.error
= _("no 'a', 'i', or 'f' flags for 'cps'");
4477 do_cpsi (char * str
)
4479 do_cps_flags (&str
, /*thumb_p=*/0);
4481 if (skip_past_comma (&str
) == SUCCESS
)
4483 skip_whitespace (str
);
4489 /* THUMB V5 breakpoint instruction (argument parse)
4493 do_t_bkpt (char * str
)
4496 unsigned long number
;
4498 skip_whitespace (str
);
4500 /* Allow optional leading '#'. */
4501 if (is_immediate_prefix (*str
))
4504 memset (& expr
, '\0', sizeof (expr
));
4505 if (my_get_expression (& expr
, & str
)
4506 || (expr
.X_op
!= O_constant
4507 /* As a convenience we allow 'bkpt' without an operand. */
4508 && expr
.X_op
!= O_absent
))
4510 inst
.error
= _("bad expression");
4514 number
= expr
.X_add_number
;
4516 /* Check it fits an 8 bit unsigned. */
4517 if (number
!= (number
& 0xff))
4519 inst
.error
= _("immediate value out of range");
4523 inst
.instruction
|= number
;
4528 static bfd_reloc_code_real_type
4529 arm_parse_reloc (void)
4538 bfd_reloc_code_real_type reloc
;
4542 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
4543 MAP ("(got)", BFD_RELOC_ARM_GOT32
),
4544 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF
),
4545 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
4546 branch instructions generated by GCC for PLT relocs. */
4547 MAP ("(plt)", BFD_RELOC_ARM_PLT32
),
4548 MAP ("(target1)", BFD_RELOC_ARM_TARGET1
),
4549 MAP ("(sbrel)", BFD_RELOC_ARM_SBREL32
),
4550 MAP ("(target2)", BFD_RELOC_ARM_TARGET2
),
4551 { NULL
, 0, BFD_RELOC_UNUSED
}
4555 for (i
= 0, ip
= input_line_pointer
;
4556 i
< sizeof (id
) && (ISALNUM (*ip
) || ISPUNCT (*ip
));
4558 id
[i
] = TOLOWER (*ip
);
4560 for (i
= 0; reloc_map
[i
].str
; i
++)
4561 if (strncmp (id
, reloc_map
[i
].str
, reloc_map
[i
].len
) == 0)
4564 input_line_pointer
+= reloc_map
[i
].len
;
4566 return reloc_map
[i
].reloc
;
4569 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
4570 Expects inst.instruction is set for BLX(1).
4571 Note: this is cloned from do_branch, and the reloc changed to be a
4572 new one that can cope with setting one extra bit (the H bit). */
4575 do_branch25 (char * str
)
4577 if (my_get_expression (& inst
.reloc
.exp
, & str
))
4584 /* ScottB: February 5, 1998 */
4585 /* Check to see of PLT32 reloc required for the instruction. */
4587 /* arm_parse_reloc() works on input_line_pointer.
4588 We actually want to parse the operands to the branch instruction
4589 passed in 'str'. Save the input pointer and restore it later. */
4590 save_in
= input_line_pointer
;
4591 input_line_pointer
= str
;
4593 if (inst
.reloc
.exp
.X_op
== O_symbol
4595 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
4597 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
4598 inst
.reloc
.pc_rel
= 0;
4599 /* Modify str to point to after parsed operands, otherwise
4600 end_of_line() will complain about the (PLT) left in str. */
4601 str
= input_line_pointer
;
4605 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
4606 inst
.reloc
.pc_rel
= 1;
4609 input_line_pointer
= save_in
;
4612 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
4613 inst
.reloc
.pc_rel
= 1;
4614 #endif /* OBJ_ELF */
4619 /* ARM V5 branch-link-exchange instruction (argument parse)
4620 BLX <target_addr> ie BLX(1)
4621 BLX{<condition>} <Rm> ie BLX(2)
4622 Unfortunately, there are two different opcodes for this mnemonic.
4623 So, the insns[].value is not used, and the code here zaps values
4624 into inst.instruction.
4625 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
4633 skip_whitespace (mystr
);
4634 rm
= reg_required_here (& mystr
, 0);
4636 /* The above may set inst.error. Ignore his opinion. */
4641 /* Arg is a register.
4642 Use the condition code our caller put in inst.instruction.
4643 Pass ourselves off as a BX with a funny opcode. */
4644 inst
.instruction
|= 0x012fff30;
4649 /* This must be is BLX <target address>, no condition allowed. */
4650 if (inst
.instruction
!= COND_ALWAYS
)
4652 inst
.error
= BAD_COND
;
4656 inst
.instruction
= 0xfafffffe;
4658 /* Process like a B/BL, but with a different reloc.
4659 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
4664 /* ARM V5 Thumb BLX (argument parse)
4665 BLX <target_addr> which is BLX(1)
4666 BLX <Rm> which is BLX(2)
4667 Unfortunately, there are two different opcodes for this mnemonic.
4668 So, the tinsns[].value is not used, and the code here zaps values
4669 into inst.instruction. */
4672 do_t_blx (char * str
)
4677 skip_whitespace (mystr
);
4678 inst
.instruction
= 0x4780;
4680 /* Note that this call is to the ARM register recognizer. BLX(2)
4681 uses the ARM register space, not the Thumb one, so a call to
4682 thumb_reg() would be wrong. */
4683 rm
= reg_required_here (& mystr
, 3);
4688 /* It's BLX(2). The .instruction was zapped with rm & is final. */
4693 /* No ARM register. This must be BLX(1). Change the .instruction. */
4694 inst
.instruction
= 0xf7ffeffe;
4697 if (my_get_expression (& inst
.reloc
.exp
, & mystr
))
4700 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BLX
;
4701 inst
.reloc
.pc_rel
= 1;
4704 end_of_line (mystr
);
4707 /* ARM V5 breakpoint instruction (argument parse)
4708 BKPT <16 bit unsigned immediate>
4709 Instruction is not conditional.
4710 The bit pattern given in insns[] has the COND_ALWAYS condition,
4711 and it is an error if the caller tried to override that. */
4714 do_bkpt (char * str
)
4717 unsigned long number
;
4719 skip_whitespace (str
);
4721 /* Allow optional leading '#'. */
4722 if (is_immediate_prefix (* str
))
4725 memset (& expr
, '\0', sizeof (expr
));
4727 if (my_get_expression (& expr
, & str
)
4728 || (expr
.X_op
!= O_constant
4729 /* As a convenience we allow 'bkpt' without an operand. */
4730 && expr
.X_op
!= O_absent
))
4732 inst
.error
= _("bad expression");
4736 number
= expr
.X_add_number
;
4738 /* Check it fits a 16 bit unsigned. */
4739 if (number
!= (number
& 0xffff))
4741 inst
.error
= _("immediate value out of range");
4745 /* Top 12 of 16 bits to bits 19:8. */
4746 inst
.instruction
|= (number
& 0xfff0) << 4;
4748 /* Bottom 4 of 16 bits to bits 3:0. */
4749 inst
.instruction
|= number
& 0xf;
4754 /* THUMB CPS instruction (argument parse). */
4757 do_t_cps (char * str
)
4759 do_cps_flags (&str
, /*thumb_p=*/1);
4763 /* Parse and validate that a register is of the right form, this saves
4764 repeated checking of this information in many similar cases.
4765 Unlike the 32-bit case we do not insert the register into the opcode
4766 here, since the position is often unknown until the full instruction
4770 thumb_reg (char ** strp
, int hi_lo
)
4774 if ((reg
= reg_required_here (strp
, -1)) == FAIL
)
4782 inst
.error
= _("lo register required");
4790 inst
.error
= _("hi register required");
4803 thumb_mov_compare (char * str
, int move
)
4807 skip_whitespace (str
);
4809 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
4810 || skip_past_comma (&str
) == FAIL
)
4813 inst
.error
= BAD_ARGS
;
4817 if (move
!= THUMB_CPY
&& is_immediate_prefix (*str
))
4820 if (my_get_expression (&inst
.reloc
.exp
, &str
))
4823 else if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
4828 if (move
!= THUMB_CPY
&& Rs
< 8 && Rd
< 8)
4830 if (move
== THUMB_MOVE
)
4831 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
4832 since a MOV instruction produces unpredictable results. */
4833 inst
.instruction
= T_OPCODE_ADD_I3
;
4835 inst
.instruction
= T_OPCODE_CMP_LR
;
4836 inst
.instruction
|= Rd
| (Rs
<< 3);
4840 if (move
== THUMB_MOVE
)
4841 inst
.instruction
= T_OPCODE_MOV_HR
;
4842 else if (move
!= THUMB_CPY
)
4843 inst
.instruction
= T_OPCODE_CMP_HR
;
4846 inst
.instruction
|= THUMB_H1
;
4849 inst
.instruction
|= THUMB_H2
;
4851 inst
.instruction
|= (Rd
& 7) | ((Rs
& 7) << 3);
4858 inst
.error
= _("only lo regs allowed with immediate");
4862 if (move
== THUMB_MOVE
)
4863 inst
.instruction
= T_OPCODE_MOV_I8
;
4865 inst
.instruction
= T_OPCODE_CMP_I8
;
4867 inst
.instruction
|= Rd
<< 8;
4869 if (inst
.reloc
.exp
.X_op
!= O_constant
)
4870 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_IMM
;
4873 unsigned value
= inst
.reloc
.exp
.X_add_number
;
4877 inst
.error
= _("invalid immediate");
4881 inst
.instruction
|= value
;
4888 /* THUMB CPY instruction (argument parse). */
4891 do_t_cpy (char * str
)
4893 thumb_mov_compare (str
, THUMB_CPY
);
4896 /* THUMB SETEND instruction (argument parse). */
4899 do_t_setend (char * str
)
4901 if (do_endian_specifier (str
))
4902 inst
.instruction
|= 0x8;
4905 /* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
4907 static unsigned long
4908 check_iwmmxt_insn (char * str
,
4909 enum iwmmxt_insn_type insn_type
,
4913 const char * inst_error
;
4915 unsigned long number
;
4917 inst_error
= inst
.error
;
4919 inst
.error
= BAD_ARGS
;
4920 skip_whitespace (str
);
4925 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
4930 if ((wreg_required_here (&str
, 0, IWMMXT_REG_WR
)) == FAIL
)
4935 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
4936 || skip_past_comma (&str
) == FAIL
4937 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
))
4942 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
4943 || skip_past_comma (&str
) == FAIL
4944 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4945 || skip_past_comma (&str
) == FAIL
4946 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
))
4951 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
4952 || skip_past_comma (&str
) == FAIL
4953 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4954 || skip_past_comma (&str
) == FAIL
4955 || wreg_required_here (&str
, 0, IWMMXT_REG_WCG
) == FAIL
))
4960 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4961 || skip_past_comma (&str
) == FAIL
4962 || reg_required_here (&str
, 12) == FAIL
))
4967 if ((reg_required_here (&str
, 12) == FAIL
4968 || skip_past_comma (&str
) == FAIL
4969 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
))
4974 if ((wreg_required_here (&str
, 5, IWMMXT_REG_WR
) == FAIL
4975 || skip_past_comma (&str
) == FAIL
4976 || reg_required_here (&str
, 0) == FAIL
4977 || skip_past_comma (&str
) == FAIL
4978 || reg_required_here (&str
, 12) == FAIL
))
4983 if ((wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
4984 || skip_past_comma (&str
) == FAIL
4985 || reg_required_here (&str
, 12) == FAIL
4986 || skip_past_comma (&str
) == FAIL
4987 || reg_required_here (&str
, 16) == FAIL
))
4992 if ((reg_required_here (&str
, 12) == FAIL
4993 || skip_past_comma (&str
) == FAIL
4994 || reg_required_here (&str
, 16) == FAIL
4995 || skip_past_comma (&str
) == FAIL
4996 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
))
5001 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WC
) == FAIL
5002 || skip_past_comma (&str
) == FAIL
5003 || reg_required_here (&str
, 12) == FAIL
))
5008 if ((reg_required_here (&str
, 12) == FAIL
5009 || skip_past_comma (&str
) == FAIL
5010 || wreg_required_here (&str
, 16, IWMMXT_REG_WC
) == FAIL
))
5015 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5016 || skip_past_comma (&str
) == FAIL
5017 || reg_required_here (&str
, 12) == FAIL
5018 || skip_past_comma (&str
) == FAIL
))
5023 if ((reg_required_here (&str
, 12) == FAIL
5024 || skip_past_comma (&str
) == FAIL
))
5029 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
5030 || skip_past_comma (&str
) == FAIL
5031 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5032 || skip_past_comma (&str
) == FAIL
5033 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
5034 || skip_past_comma (&str
) == FAIL
))
5039 if ((reg_required_here (&str
, 12) == FAIL
5040 || skip_past_comma (&str
) == FAIL
5041 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5042 || skip_past_comma (&str
) == FAIL
))
5047 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
5048 || skip_past_comma (&str
) == FAIL
5049 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5050 || skip_past_comma (&str
) == FAIL
))
5055 if (immediate_size
== 0)
5058 inst
.error
= inst_error
;
5063 skip_whitespace (str
);
5065 /* Allow optional leading '#'. */
5066 if (is_immediate_prefix (* str
))
5069 memset (& expr
, '\0', sizeof (expr
));
5071 if (my_get_expression (& expr
, & str
) || (expr
.X_op
!= O_constant
))
5073 inst
.error
= _("bad or missing expression");
5077 number
= expr
.X_add_number
;
5079 if (number
!= (number
& immediate_size
))
5081 inst
.error
= _("immediate value out of range");
5085 inst
.error
= inst_error
;
5091 do_iwmmxt_byte_addr (char * str
)
5093 int op
= (inst
.instruction
& 0x300) >> 8;
5096 inst
.instruction
&= ~0x300;
5097 inst
.instruction
|= (op
& 1) << 22 | (op
& 2) << 7;
5099 skip_whitespace (str
);
5101 if ((reg
= wreg_required_here (&str
, 12, IWMMXT_REG_WR_OR_WC
)) == FAIL
5102 || skip_past_comma (& str
) == FAIL
5103 || cp_byte_address_required_here (&str
) == FAIL
)
5106 inst
.error
= BAD_ARGS
;
5111 if (wc_register (reg
))
5113 as_bad (_("non-word size not supported with control register"));
5114 inst
.instruction
|= 0xf0000100;
5115 inst
.instruction
&= ~0x00400000;
5120 do_iwmmxt_tandc (char * str
)
5124 reg
= check_iwmmxt_insn (str
, check_rd
, 0);
5126 if (reg
!= REG_PC
&& !inst
.error
)
5127 inst
.error
= _("only r15 allowed here");
5131 do_iwmmxt_tbcst (char * str
)
5133 check_iwmmxt_insn (str
, check_tbcst
, 0);
5137 do_iwmmxt_textrc (char * str
)
5139 unsigned long number
;
5141 if ((number
= check_iwmmxt_insn (str
, check_textrc
, 7)) == (unsigned long) FAIL
)
5144 inst
.instruction
|= number
& 0x7;
5148 do_iwmmxt_textrm (char * str
)
5150 unsigned long number
;
5152 if ((number
= check_iwmmxt_insn (str
, check_textrm
, 7)) == (unsigned long) FAIL
)
5155 inst
.instruction
|= number
& 0x7;
5159 do_iwmmxt_tinsr (char * str
)
5161 unsigned long number
;
5163 if ((number
= check_iwmmxt_insn (str
, check_tinsr
, 7)) == (unsigned long) FAIL
)
5166 inst
.instruction
|= number
& 0x7;
5170 do_iwmmxt_tmcr (char * str
)
5172 check_iwmmxt_insn (str
, check_tmcr
, 0);
5176 do_iwmmxt_tmcrr (char * str
)
5178 check_iwmmxt_insn (str
, check_tmcrr
, 0);
5182 do_iwmmxt_tmia (char * str
)
5184 check_iwmmxt_insn (str
, check_tmia
, 0);
5188 do_iwmmxt_tmovmsk (char * str
)
5190 check_iwmmxt_insn (str
, check_tmovmsk
, 0);
5194 do_iwmmxt_tmrc (char * str
)
5196 check_iwmmxt_insn (str
, check_tmrc
, 0);
5200 do_iwmmxt_tmrrc (char * str
)
5202 check_iwmmxt_insn (str
, check_tmrrc
, 0);
5206 do_iwmmxt_torc (char * str
)
5208 check_iwmmxt_insn (str
, check_rd
, 0);
5212 do_iwmmxt_waligni (char * str
)
5214 unsigned long number
;
5216 if ((number
= check_iwmmxt_insn (str
, check_waligni
, 7)) == (unsigned long) FAIL
)
5219 inst
.instruction
|= ((number
& 0x7) << 20);
5223 do_iwmmxt_wmov (char * str
)
5225 if (check_iwmmxt_insn (str
, check_wrwr
, 0) == (unsigned long) FAIL
)
5228 inst
.instruction
|= ((inst
.instruction
>> 16) & 0xf);
5232 do_iwmmxt_word_addr (char * str
)
5234 int op
= (inst
.instruction
& 0x300) >> 8;
5237 inst
.instruction
&= ~0x300;
5238 inst
.instruction
|= (op
& 1) << 22 | (op
& 2) << 7;
5240 skip_whitespace (str
);
5242 if ((reg
= wreg_required_here (&str
, 12, IWMMXT_REG_WR_OR_WC
)) == FAIL
5243 || skip_past_comma (& str
) == FAIL
5244 || cp_address_required_here (& str
, CP_WB_OK
) == FAIL
)
5247 inst
.error
= BAD_ARGS
;
5252 if (wc_register (reg
))
5254 if ((inst
.instruction
& COND_MASK
) != COND_ALWAYS
)
5255 as_bad (_("conditional execution not supported with control register"));
5257 as_bad (_("non-word size not supported with control register"));
5258 inst
.instruction
|= 0xf0000100;
5259 inst
.instruction
&= ~0x00400000;
5264 do_iwmmxt_wrwr (char * str
)
5266 check_iwmmxt_insn (str
, check_wrwr
, 0);
5270 do_iwmmxt_wrwrwcg (char * str
)
5272 check_iwmmxt_insn (str
, check_wrwrwcg
, 0);
5276 do_iwmmxt_wrwrwr (char * str
)
5278 check_iwmmxt_insn (str
, check_wrwrwr
, 0);
5282 do_iwmmxt_wshufh (char * str
)
5284 unsigned long number
;
5286 if ((number
= check_iwmmxt_insn (str
, check_wshufh
, 0xff)) == (unsigned long) FAIL
)
5289 inst
.instruction
|= ((number
& 0xf0) << 16) | (number
& 0xf);
5293 do_iwmmxt_wzero (char * str
)
5295 if (check_iwmmxt_insn (str
, check_wr
, 0) == (unsigned long) FAIL
)
5298 inst
.instruction
|= ((inst
.instruction
& 0xf) << 12) | ((inst
.instruction
& 0xf) << 16);
5301 /* Xscale multiply-accumulate (argument parse)
5304 MIAxycc acc0,Rm,Rs. */
5307 do_xsc_mia (char * str
)
5312 if (accum0_required_here (& str
) == FAIL
)
5313 inst
.error
= ERR_NO_ACCUM
;
5315 else if (skip_past_comma (& str
) == FAIL
5316 || (rm
= reg_required_here (& str
, 0)) == FAIL
)
5317 inst
.error
= BAD_ARGS
;
5319 else if (skip_past_comma (& str
) == FAIL
5320 || (rs
= reg_required_here (& str
, 12)) == FAIL
)
5321 inst
.error
= BAD_ARGS
;
5323 /* inst.instruction has now been zapped with both rm and rs. */
5324 else if (rm
== REG_PC
|| rs
== REG_PC
)
5325 inst
.error
= BAD_PC
; /* Undefined result if rm or rs is R15. */
5331 /* Xscale move-accumulator-register (argument parse)
5333 MARcc acc0,RdLo,RdHi. */
5336 do_xsc_mar (char * str
)
5340 if (accum0_required_here (& str
) == FAIL
)
5341 inst
.error
= ERR_NO_ACCUM
;
5343 else if (skip_past_comma (& str
) == FAIL
5344 || (rdlo
= reg_required_here (& str
, 12)) == FAIL
)
5345 inst
.error
= BAD_ARGS
;
5347 else if (skip_past_comma (& str
) == FAIL
5348 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
5349 inst
.error
= BAD_ARGS
;
5351 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5352 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
5353 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
5359 /* Xscale move-register-accumulator (argument parse)
5361 MRAcc RdLo,RdHi,acc0. */
5364 do_xsc_mra (char * str
)
5369 skip_whitespace (str
);
5371 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
)
5372 inst
.error
= BAD_ARGS
;
5374 else if (skip_past_comma (& str
) == FAIL
5375 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
5376 inst
.error
= BAD_ARGS
;
5378 else if (skip_past_comma (& str
) == FAIL
5379 || accum0_required_here (& str
) == FAIL
)
5380 inst
.error
= ERR_NO_ACCUM
;
5382 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5383 else if (rdlo
== rdhi
)
5384 inst
.error
= BAD_ARGS
; /* Undefined result if 2 writes to same reg. */
5386 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
5387 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
5393 ldst_extend (char ** str
)
5402 if (my_get_expression (& inst
.reloc
.exp
, str
))
5405 if (inst
.reloc
.exp
.X_op
== O_constant
)
5407 int value
= inst
.reloc
.exp
.X_add_number
;
5409 if (value
< -4095 || value
> 4095)
5411 inst
.error
= _("address offset too large");
5421 inst
.instruction
|= add
| value
;
5425 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
5426 inst
.reloc
.pc_rel
= 0;
5439 if (reg_required_here (str
, 0) == FAIL
)
5442 inst
.instruction
|= add
| OFFSET_REG
;
5443 if (skip_past_comma (str
) == SUCCESS
)
5444 return decode_shift (str
, SHIFT_IMMEDIATE
);
5450 /* ARMv5TE: Preload-Cache
5454 Syntactically, like LDR with B=1, W=0, L=1. */
5461 skip_whitespace (str
);
5465 inst
.error
= _("'[' expected after PLD mnemonic");
5470 skip_whitespace (str
);
5472 if ((rd
= reg_required_here (& str
, 16)) == FAIL
)
5475 skip_whitespace (str
);
5481 skip_whitespace (str
);
5483 /* Post-indexed addressing is not allowed with PLD. */
5484 if (skip_past_comma (&str
) == SUCCESS
)
5487 = _("post-indexed expression used in preload instruction");
5490 else if (*str
== '!') /* [Rn]! */
5492 inst
.error
= _("writeback used in preload instruction");
5496 inst
.instruction
|= INDEX_UP
| PRE_INDEX
;
5498 else /* [Rn, ...] */
5500 if (skip_past_comma (& str
) == FAIL
)
5502 inst
.error
= _("pre-indexed expression expected");
5506 if (ldst_extend (&str
) == FAIL
)
5509 skip_whitespace (str
);
5513 inst
.error
= _("missing ]");
5518 skip_whitespace (str
);
5520 if (* str
== '!') /* [Rn]! */
5522 inst
.error
= _("writeback used in preload instruction");
5526 inst
.instruction
|= PRE_INDEX
;
5532 /* ARMv5TE load-consecutive (argument parse)
5539 do_ldrd (char * str
)
5544 skip_whitespace (str
);
5546 if ((rd
= reg_required_here (& str
, 12)) == FAIL
)
5548 inst
.error
= BAD_ARGS
;
5552 if (skip_past_comma (& str
) == FAIL
5553 || (rn
= ld_mode_required_here (& str
)) == FAIL
)
5556 inst
.error
= BAD_ARGS
;
5560 /* inst.instruction has now been zapped with Rd and the addressing mode. */
5561 if (rd
& 1) /* Unpredictable result if Rd is odd. */
5563 inst
.error
= _("destination register must be even");
5569 inst
.error
= _("r14 not allowed here");
5573 if (((rd
== rn
) || (rd
+ 1 == rn
))
5574 && ((inst
.instruction
& WRITE_BACK
)
5575 || (!(inst
.instruction
& PRE_INDEX
))))
5576 as_warn (_("pre/post-indexing used when modified address register is destination"));
5578 /* For an index-register load, the index register must not overlap the
5579 destination (even if not write-back). */
5580 if ((inst
.instruction
& V4_STR_BIT
) == 0
5581 && (inst
.instruction
& HWOFFSET_IMM
) == 0)
5583 int rm
= inst
.instruction
& 0x0000000f;
5585 if (rm
== rd
|| (rm
== rd
+ 1))
5586 as_warn (_("ldrd destination registers must not overlap index register"));
5592 /* Returns the index into fp_values of a floating point number,
5593 or -1 if not in the table. */
5596 my_get_float_expression (char ** str
)
5598 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
5604 memset (words
, 0, MAX_LITTLENUMS
* sizeof (LITTLENUM_TYPE
));
5606 /* Look for a raw floating point number. */
5607 if ((save_in
= atof_ieee (*str
, 'x', words
)) != NULL
5608 && is_end_of_line
[(unsigned char) *save_in
])
5610 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
5612 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
5614 if (words
[j
] != fp_values
[i
][j
])
5618 if (j
== MAX_LITTLENUMS
)
5626 /* Try and parse a more complex expression, this will probably fail
5627 unless the code uses a floating point prefix (eg "0f"). */
5628 save_in
= input_line_pointer
;
5629 input_line_pointer
= *str
;
5630 if (expression (&exp
) == absolute_section
5631 && exp
.X_op
== O_big
5632 && exp
.X_add_number
< 0)
5634 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
5636 if (gen_to_words (words
, 5, (long) 15) == 0)
5638 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
5640 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
5642 if (words
[j
] != fp_values
[i
][j
])
5646 if (j
== MAX_LITTLENUMS
)
5648 *str
= input_line_pointer
;
5649 input_line_pointer
= save_in
;
5656 *str
= input_line_pointer
;
5657 input_line_pointer
= save_in
;
5661 /* We handle all bad expressions here, so that we can report the faulty
5662 instruction in the error message. */
5664 md_operand (expressionS
* expr
)
5666 if (in_my_get_expression
)
5668 expr
->X_op
= O_illegal
;
5669 if (inst
.error
== NULL
)
5670 inst
.error
= _("bad expression");
5674 /* Do those data_ops which can take a negative immediate constant
5675 by altering the instruction. A bit of a hack really.
5679 by inverting the second operand, and
5682 by negating the second operand. */
5685 negate_data_op (unsigned long * instruction
,
5686 unsigned long value
)
5689 unsigned long negated
, inverted
;
5691 negated
= validate_immediate (-value
);
5692 inverted
= validate_immediate (~value
);
5694 op
= (*instruction
>> DATA_OP_SHIFT
) & 0xf;
5697 /* First negates. */
5698 case OPCODE_SUB
: /* ADD <-> SUB */
5699 new_inst
= OPCODE_ADD
;
5704 new_inst
= OPCODE_SUB
;
5708 case OPCODE_CMP
: /* CMP <-> CMN */
5709 new_inst
= OPCODE_CMN
;
5714 new_inst
= OPCODE_CMP
;
5718 /* Now Inverted ops. */
5719 case OPCODE_MOV
: /* MOV <-> MVN */
5720 new_inst
= OPCODE_MVN
;
5725 new_inst
= OPCODE_MOV
;
5729 case OPCODE_AND
: /* AND <-> BIC */
5730 new_inst
= OPCODE_BIC
;
5735 new_inst
= OPCODE_AND
;
5739 case OPCODE_ADC
: /* ADC <-> SBC */
5740 new_inst
= OPCODE_SBC
;
5745 new_inst
= OPCODE_ADC
;
5749 /* We cannot do anything. */
5754 if (value
== (unsigned) FAIL
)
5757 *instruction
&= OPCODE_MASK
;
5758 *instruction
|= new_inst
<< DATA_OP_SHIFT
;
5763 data_op2 (char ** str
)
5768 skip_whitespace (* str
);
5770 if (reg_required_here (str
, 0) != FAIL
)
5772 if (skip_past_comma (str
) == SUCCESS
)
5773 /* Shift operation on register. */
5774 return decode_shift (str
, NO_SHIFT_RESTRICT
);
5780 /* Immediate expression. */
5781 if (is_immediate_prefix (**str
))
5786 if (my_get_expression (&inst
.reloc
.exp
, str
))
5789 if (inst
.reloc
.exp
.X_add_symbol
)
5791 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
5792 inst
.reloc
.pc_rel
= 0;
5796 if (skip_past_comma (str
) == SUCCESS
)
5798 /* #x, y -- ie explicit rotation by Y. */
5799 if (my_get_expression (&expr
, str
))
5802 if (expr
.X_op
!= O_constant
)
5804 inst
.error
= _("constant expression expected");
5808 /* Rotate must be a multiple of 2. */
5809 if (((unsigned) expr
.X_add_number
) > 30
5810 || (expr
.X_add_number
& 1) != 0
5811 || ((unsigned) inst
.reloc
.exp
.X_add_number
) > 255)
5813 inst
.error
= _("invalid constant");
5816 inst
.instruction
|= INST_IMMEDIATE
;
5817 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
5818 inst
.instruction
|= expr
.X_add_number
<< 7;
5822 /* Implicit rotation, select a suitable one. */
5823 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
5827 /* Can't be done. Perhaps the code reads something like
5828 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
5829 if ((value
= negate_data_op (&inst
.instruction
,
5830 inst
.reloc
.exp
.X_add_number
))
5833 inst
.error
= _("invalid constant");
5838 inst
.instruction
|= value
;
5841 inst
.instruction
|= INST_IMMEDIATE
;
5846 inst
.error
= _("register or shift expression expected");
5852 fp_op2 (char ** str
)
5854 skip_whitespace (* str
);
5856 if (fp_reg_required_here (str
, 0) != FAIL
)
5860 /* Immediate expression. */
5861 if (*((*str
)++) == '#')
5867 skip_whitespace (* str
);
5869 /* First try and match exact strings, this is to guarantee
5870 that some formats will work even for cross assembly. */
5872 for (i
= 0; fp_const
[i
]; i
++)
5874 if (strncmp (*str
, fp_const
[i
], strlen (fp_const
[i
])) == 0)
5878 *str
+= strlen (fp_const
[i
]);
5879 if (is_end_of_line
[(unsigned char) **str
])
5881 inst
.instruction
|= i
+ 8;
5888 /* Just because we didn't get a match doesn't mean that the
5889 constant isn't valid, just that it is in a format that we
5890 don't automatically recognize. Try parsing it with
5891 the standard expression routines. */
5892 if ((i
= my_get_float_expression (str
)) >= 0)
5894 inst
.instruction
|= i
+ 8;
5898 inst
.error
= _("invalid floating point immediate expression");
5902 _("floating point register or immediate expression expected");
5908 do_arit (char * str
)
5910 skip_whitespace (str
);
5912 if (reg_required_here (&str
, 12) == FAIL
5913 || skip_past_comma (&str
) == FAIL
5914 || reg_required_here (&str
, 16) == FAIL
5915 || skip_past_comma (&str
) == FAIL
5916 || data_op2 (&str
) == FAIL
)
5919 inst
.error
= BAD_ARGS
;
5929 /* This is a pseudo-op of the form "adr rd, label" to be converted
5930 into a relative address of the form "add rd, pc, #label-.-8". */
5931 skip_whitespace (str
);
5933 if (reg_required_here (&str
, 12) == FAIL
5934 || skip_past_comma (&str
) == FAIL
5935 || my_get_expression (&inst
.reloc
.exp
, &str
))
5938 inst
.error
= BAD_ARGS
;
5942 /* Frag hacking will turn this into a sub instruction if the offset turns
5943 out to be negative. */
5944 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
5946 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust. */
5948 inst
.reloc
.pc_rel
= 1;
5954 do_adrl (char * str
)
5956 /* This is a pseudo-op of the form "adrl rd, label" to be converted
5957 into a relative address of the form:
5958 add rd, pc, #low(label-.-8)"
5959 add rd, rd, #high(label-.-8)" */
5961 skip_whitespace (str
);
5963 if (reg_required_here (&str
, 12) == FAIL
5964 || skip_past_comma (&str
) == FAIL
5965 || my_get_expression (&inst
.reloc
.exp
, &str
))
5968 inst
.error
= BAD_ARGS
;
5974 /* Frag hacking will turn this into a sub instruction if the offset turns
5975 out to be negative. */
5976 inst
.reloc
.type
= BFD_RELOC_ARM_ADRL_IMMEDIATE
;
5978 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust */
5980 inst
.reloc
.pc_rel
= 1;
5981 inst
.size
= INSN_SIZE
* 2;
5987 skip_whitespace (str
);
5989 if (reg_required_here (&str
, 16) == FAIL
)
5992 inst
.error
= BAD_ARGS
;
5996 if (skip_past_comma (&str
) == FAIL
5997 || data_op2 (&str
) == FAIL
)
6000 inst
.error
= BAD_ARGS
;
6010 skip_whitespace (str
);
6012 if (reg_required_here (&str
, 12) == FAIL
)
6015 inst
.error
= BAD_ARGS
;
6019 if (skip_past_comma (&str
) == FAIL
6020 || data_op2 (&str
) == FAIL
)
6023 inst
.error
= BAD_ARGS
;
6031 do_ldst (char * str
)
6037 skip_whitespace (str
);
6039 if ((conflict_reg
= reg_required_here (&str
, 12)) == FAIL
)
6042 inst
.error
= BAD_ARGS
;
6046 if (skip_past_comma (&str
) == FAIL
)
6048 inst
.error
= _("address expected");
6058 skip_whitespace (str
);
6060 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6063 /* Conflicts can occur on stores as well as loads. */
6064 conflict_reg
= (conflict_reg
== reg
);
6066 skip_whitespace (str
);
6072 if (skip_past_comma (&str
) == SUCCESS
)
6074 /* [Rn],... (post inc) */
6075 if (ldst_extend (&str
) == FAIL
)
6078 as_warn (_("%s register same as write-back base"),
6079 ((inst
.instruction
& LOAD_BIT
)
6080 ? _("destination") : _("source")));
6085 skip_whitespace (str
);
6090 as_warn (_("%s register same as write-back base"),
6091 ((inst
.instruction
& LOAD_BIT
)
6092 ? _("destination") : _("source")));
6094 inst
.instruction
|= WRITE_BACK
;
6097 inst
.instruction
|= INDEX_UP
;
6104 if (skip_past_comma (&str
) == FAIL
)
6106 inst
.error
= _("pre-indexed expression expected");
6111 if (ldst_extend (&str
) == FAIL
)
6114 skip_whitespace (str
);
6118 inst
.error
= _("missing ]");
6122 skip_whitespace (str
);
6127 as_warn (_("%s register same as write-back base"),
6128 ((inst
.instruction
& LOAD_BIT
)
6129 ? _("destination") : _("source")));
6131 inst
.instruction
|= WRITE_BACK
;
6135 else if (*str
== '=')
6137 if ((inst
.instruction
& LOAD_BIT
) == 0)
6139 inst
.error
= _("invalid pseudo operation");
6143 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6146 skip_whitespace (str
);
6148 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6151 if (inst
.reloc
.exp
.X_op
!= O_constant
6152 && inst
.reloc
.exp
.X_op
!= O_symbol
)
6154 inst
.error
= _("constant expression expected");
6158 if (inst
.reloc
.exp
.X_op
== O_constant
)
6160 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
6164 /* This can be done with a mov instruction. */
6165 inst
.instruction
&= LITERAL_MASK
;
6166 inst
.instruction
|= (INST_IMMEDIATE
6167 | (OPCODE_MOV
<< DATA_OP_SHIFT
));
6168 inst
.instruction
|= value
& 0xfff;
6173 value
= validate_immediate (~inst
.reloc
.exp
.X_add_number
);
6177 /* This can be done with a mvn instruction. */
6178 inst
.instruction
&= LITERAL_MASK
;
6179 inst
.instruction
|= (INST_IMMEDIATE
6180 | (OPCODE_MVN
<< DATA_OP_SHIFT
));
6181 inst
.instruction
|= value
& 0xfff;
6187 /* Insert into literal pool. */
6188 if (add_to_lit_pool () == FAIL
)
6191 inst
.error
= _("literal pool insertion failed");
6195 /* Change the instruction exp to point to the pool. */
6196 inst
.reloc
.type
= BFD_RELOC_ARM_LITERAL
;
6197 inst
.reloc
.pc_rel
= 1;
6198 inst
.instruction
|= (REG_PC
<< 16);
6203 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6206 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
6208 /* PC rel adjust. */
6209 inst
.reloc
.exp
.X_add_number
-= 8;
6211 inst
.reloc
.pc_rel
= 1;
6212 inst
.instruction
|= (REG_PC
<< 16);
6216 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
6221 do_ldstt (char * str
)
6225 skip_whitespace (str
);
6227 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
6230 inst
.error
= BAD_ARGS
;
6234 if (skip_past_comma (& str
) == FAIL
)
6236 inst
.error
= _("address expected");
6246 skip_whitespace (str
);
6248 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6251 /* ldrt/strt always use post-indexed addressing, so if the base is
6252 the same as Rd, we warn. */
6253 if (conflict_reg
== reg
)
6254 as_warn (_("%s register same as write-back base"),
6255 ((inst
.instruction
& LOAD_BIT
)
6256 ? _("destination") : _("source")));
6258 skip_whitespace (str
);
6264 if (skip_past_comma (&str
) == SUCCESS
)
6266 /* [Rn],... (post inc) */
6267 if (ldst_extend (&str
) == FAIL
)
6273 skip_whitespace (str
);
6275 /* Skip a write-back '!'. */
6279 inst
.instruction
|= INDEX_UP
;
6284 inst
.error
= _("post-indexed expression expected");
6290 inst
.error
= _("post-indexed expression expected");
6297 /* Halfword and signed-byte load/store operations. */
6300 do_ldstv4 (char * str
)
6306 skip_whitespace (str
);
6308 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
6311 inst
.error
= BAD_ARGS
;
6315 if (skip_past_comma (& str
) == FAIL
)
6317 inst
.error
= _("address expected");
6327 skip_whitespace (str
);
6329 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6332 /* Conflicts can occur on stores as well as loads. */
6333 conflict_reg
= (conflict_reg
== reg
);
6335 skip_whitespace (str
);
6341 if (skip_past_comma (&str
) == SUCCESS
)
6343 /* [Rn],... (post inc) */
6344 if (ldst_extend_v4 (&str
) == FAIL
)
6347 as_warn (_("%s register same as write-back base"),
6348 ((inst
.instruction
& LOAD_BIT
)
6349 ? _("destination") : _("source")));
6354 inst
.instruction
|= HWOFFSET_IMM
;
6356 skip_whitespace (str
);
6361 as_warn (_("%s register same as write-back base"),
6362 ((inst
.instruction
& LOAD_BIT
)
6363 ? _("destination") : _("source")));
6365 inst
.instruction
|= WRITE_BACK
;
6368 inst
.instruction
|= INDEX_UP
;
6375 if (skip_past_comma (&str
) == FAIL
)
6377 inst
.error
= _("pre-indexed expression expected");
6382 if (ldst_extend_v4 (&str
) == FAIL
)
6385 skip_whitespace (str
);
6389 inst
.error
= _("missing ]");
6393 skip_whitespace (str
);
6398 as_warn (_("%s register same as write-back base"),
6399 ((inst
.instruction
& LOAD_BIT
)
6400 ? _("destination") : _("source")));
6402 inst
.instruction
|= WRITE_BACK
;
6406 else if (*str
== '=')
6408 if ((inst
.instruction
& LOAD_BIT
) == 0)
6410 inst
.error
= _("invalid pseudo operation");
6414 /* XXX Does this work correctly for half-word/byte ops? */
6415 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6418 skip_whitespace (str
);
6420 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6423 if (inst
.reloc
.exp
.X_op
!= O_constant
6424 && inst
.reloc
.exp
.X_op
!= O_symbol
)
6426 inst
.error
= _("constant expression expected");
6430 if (inst
.reloc
.exp
.X_op
== O_constant
)
6432 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
6436 /* This can be done with a mov instruction. */
6437 inst
.instruction
&= LITERAL_MASK
;
6438 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MOV
<< DATA_OP_SHIFT
);
6439 inst
.instruction
|= value
& 0xfff;
6444 value
= validate_immediate (~ inst
.reloc
.exp
.X_add_number
);
6448 /* This can be done with a mvn instruction. */
6449 inst
.instruction
&= LITERAL_MASK
;
6450 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MVN
<< DATA_OP_SHIFT
);
6451 inst
.instruction
|= value
& 0xfff;
6457 /* Insert into literal pool. */
6458 if (add_to_lit_pool () == FAIL
)
6461 inst
.error
= _("literal pool insertion failed");
6465 /* Change the instruction exp to point to the pool. */
6466 inst
.instruction
|= HWOFFSET_IMM
;
6467 inst
.reloc
.type
= BFD_RELOC_ARM_HWLITERAL
;
6468 inst
.reloc
.pc_rel
= 1;
6469 inst
.instruction
|= (REG_PC
<< 16);
6474 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6477 inst
.instruction
|= HWOFFSET_IMM
;
6478 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
6480 /* PC rel adjust. */
6481 inst
.reloc
.exp
.X_add_number
-= 8;
6483 inst
.reloc
.pc_rel
= 1;
6484 inst
.instruction
|= (REG_PC
<< 16);
6488 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
6493 reg_list (char ** strp
)
6495 char * str
= * strp
;
6499 /* We come back here if we get ranges concatenated by '+' or '|'. */
6514 skip_whitespace (str
);
6516 if ((reg
= reg_required_here (& str
, -1)) == FAIL
)
6525 inst
.error
= _("bad range in register list");
6529 for (i
= cur_reg
+ 1; i
< reg
; i
++)
6531 if (range
& (1 << i
))
6533 (_("Warning: duplicated register (r%d) in register list"),
6541 if (range
& (1 << reg
))
6542 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
6544 else if (reg
<= cur_reg
)
6545 as_tsktsk (_("Warning: register range not in ascending order"));
6550 while (skip_past_comma (&str
) != FAIL
6551 || (in_range
= 1, *str
++ == '-'));
6553 skip_whitespace (str
);
6557 inst
.error
= _("missing `}'");
6565 if (my_get_expression (&expr
, &str
))
6568 if (expr
.X_op
== O_constant
)
6570 if (expr
.X_add_number
6571 != (expr
.X_add_number
& 0x0000ffff))
6573 inst
.error
= _("invalid register mask");
6577 if ((range
& expr
.X_add_number
) != 0)
6579 int regno
= range
& expr
.X_add_number
;
6582 regno
= (1 << regno
) - 1;
6584 (_("Warning: duplicated register (r%d) in register list"),
6588 range
|= expr
.X_add_number
;
6592 if (inst
.reloc
.type
!= 0)
6594 inst
.error
= _("expression too complex");
6598 memcpy (&inst
.reloc
.exp
, &expr
, sizeof (expressionS
));
6599 inst
.reloc
.type
= BFD_RELOC_ARM_MULTI
;
6600 inst
.reloc
.pc_rel
= 0;
6604 skip_whitespace (str
);
6606 if (*str
== '|' || *str
== '+')
6612 while (another_range
);
6619 do_ldmstm (char * str
)
6624 skip_whitespace (str
);
6626 if ((base_reg
= reg_required_here (&str
, 16)) == FAIL
)
6629 if (base_reg
== REG_PC
)
6631 inst
.error
= _("r15 not allowed as base register");
6635 skip_whitespace (str
);
6639 inst
.instruction
|= WRITE_BACK
;
6643 if (skip_past_comma (&str
) == FAIL
6644 || (range
= reg_list (&str
)) == FAIL
)
6647 inst
.error
= BAD_ARGS
;
6654 inst
.instruction
|= LDM_TYPE_2_OR_3
;
6657 if (inst
.instruction
& WRITE_BACK
)
6659 /* Check for unpredictable uses of writeback. */
6660 if (inst
.instruction
& LOAD_BIT
)
6662 /* Not allowed in LDM type 2. */
6663 if ((inst
.instruction
& LDM_TYPE_2_OR_3
)
6664 && ((range
& (1 << REG_PC
)) == 0))
6665 as_warn (_("writeback of base register is UNPREDICTABLE"));
6666 /* Only allowed if base reg not in list for other types. */
6667 else if (range
& (1 << base_reg
))
6668 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
6672 /* Not allowed for type 2. */
6673 if (inst
.instruction
& LDM_TYPE_2_OR_3
)
6674 as_warn (_("writeback of base register is UNPREDICTABLE"));
6675 /* Only allowed if base reg not in list, or first in list. */
6676 else if ((range
& (1 << base_reg
))
6677 && (range
& ((1 << base_reg
) - 1)))
6678 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
6682 inst
.instruction
|= range
;
6689 skip_whitespace (str
);
6691 /* Allow optional leading '#'. */
6692 if (is_immediate_prefix (*str
))
6695 if (my_get_expression (& inst
.reloc
.exp
, & str
))
6698 inst
.reloc
.type
= BFD_RELOC_ARM_SMI
;
6699 inst
.reloc
.pc_rel
= 0;
6706 skip_whitespace (str
);
6708 /* Allow optional leading '#'. */
6709 if (is_immediate_prefix (*str
))
6712 if (my_get_expression (& inst
.reloc
.exp
, & str
))
6715 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
6716 inst
.reloc
.pc_rel
= 0;
6721 do_swap (char * str
)
6725 skip_whitespace (str
);
6727 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
6732 inst
.error
= _("r15 not allowed in swap");
6736 if (skip_past_comma (&str
) == FAIL
6737 || (reg
= reg_required_here (&str
, 0)) == FAIL
)
6740 inst
.error
= BAD_ARGS
;
6746 inst
.error
= _("r15 not allowed in swap");
6750 if (skip_past_comma (&str
) == FAIL
6753 inst
.error
= BAD_ARGS
;
6757 skip_whitespace (str
);
6759 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6764 inst
.error
= BAD_PC
;
6768 skip_whitespace (str
);
6772 inst
.error
= _("missing ]");
6780 do_branch (char * str
)
6782 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6789 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
6790 required for the instruction. */
6792 /* arm_parse_reloc () works on input_line_pointer.
6793 We actually want to parse the operands to the branch instruction
6794 passed in 'str'. Save the input pointer and restore it later. */
6795 save_in
= input_line_pointer
;
6796 input_line_pointer
= str
;
6797 if (inst
.reloc
.exp
.X_op
== O_symbol
6799 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
6801 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
6802 inst
.reloc
.pc_rel
= 0;
6803 /* Modify str to point to after parsed operands, otherwise
6804 end_of_line() will complain about the (PLT) left in str. */
6805 str
= input_line_pointer
;
6809 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
6810 inst
.reloc
.pc_rel
= 1;
6812 input_line_pointer
= save_in
;
6815 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
6816 inst
.reloc
.pc_rel
= 1;
6817 #endif /* OBJ_ELF */
6825 /* Co-processor data operation.
6826 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
6827 skip_whitespace (str
);
6829 if (co_proc_number (&str
) == FAIL
)
6832 inst
.error
= BAD_ARGS
;
6836 if (skip_past_comma (&str
) == FAIL
6837 || cp_opc_expr (&str
, 20,4) == FAIL
)
6840 inst
.error
= BAD_ARGS
;
6844 if (skip_past_comma (&str
) == FAIL
6845 || cp_reg_required_here (&str
, 12) == FAIL
)
6848 inst
.error
= BAD_ARGS
;
6852 if (skip_past_comma (&str
) == FAIL
6853 || cp_reg_required_here (&str
, 16) == FAIL
)
6856 inst
.error
= BAD_ARGS
;
6860 if (skip_past_comma (&str
) == FAIL
6861 || cp_reg_required_here (&str
, 0) == FAIL
)
6864 inst
.error
= BAD_ARGS
;
6868 if (skip_past_comma (&str
) == SUCCESS
)
6870 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
6873 inst
.error
= BAD_ARGS
;
6882 do_lstc (char * str
)
6884 /* Co-processor register load/store.
6885 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
6887 skip_whitespace (str
);
6889 if (co_proc_number (&str
) == FAIL
)
6892 inst
.error
= BAD_ARGS
;
6896 if (skip_past_comma (&str
) == FAIL
6897 || cp_reg_required_here (&str
, 12) == FAIL
)
6900 inst
.error
= BAD_ARGS
;
6904 if (skip_past_comma (&str
) == FAIL
6905 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
6908 inst
.error
= BAD_ARGS
;
6916 do_co_reg (char * str
)
6918 /* Co-processor register transfer.
6919 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
6921 skip_whitespace (str
);
6923 if (co_proc_number (&str
) == FAIL
)
6926 inst
.error
= BAD_ARGS
;
6930 if (skip_past_comma (&str
) == FAIL
6931 || cp_opc_expr (&str
, 21, 3) == FAIL
)
6934 inst
.error
= BAD_ARGS
;
6938 if (skip_past_comma (&str
) == FAIL
6939 || reg_required_here (&str
, 12) == FAIL
)
6942 inst
.error
= BAD_ARGS
;
6946 if (skip_past_comma (&str
) == FAIL
6947 || cp_reg_required_here (&str
, 16) == FAIL
)
6950 inst
.error
= BAD_ARGS
;
6954 if (skip_past_comma (&str
) == FAIL
6955 || cp_reg_required_here (&str
, 0) == FAIL
)
6958 inst
.error
= BAD_ARGS
;
6962 if (skip_past_comma (&str
) == SUCCESS
)
6964 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
6967 inst
.error
= BAD_ARGS
;
6976 do_fpa_ctrl (char * str
)
6978 /* FP control registers.
6979 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
6981 skip_whitespace (str
);
6983 if (reg_required_here (&str
, 12) == FAIL
)
6986 inst
.error
= BAD_ARGS
;
6994 do_fpa_ldst (char * str
)
6996 skip_whitespace (str
);
6998 if (fp_reg_required_here (&str
, 12) == FAIL
)
7001 inst
.error
= BAD_ARGS
;
7005 if (skip_past_comma (&str
) == FAIL
7006 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
7009 inst
.error
= BAD_ARGS
;
7017 do_fpa_ldmstm (char * str
)
7021 skip_whitespace (str
);
7023 if (fp_reg_required_here (&str
, 12) == FAIL
)
7026 inst
.error
= BAD_ARGS
;
7030 /* Get Number of registers to transfer. */
7031 if (skip_past_comma (&str
) == FAIL
7032 || my_get_expression (&inst
.reloc
.exp
, &str
))
7035 inst
.error
= _("constant expression expected");
7039 if (inst
.reloc
.exp
.X_op
!= O_constant
)
7041 inst
.error
= _("constant value required for number of registers");
7045 num_regs
= inst
.reloc
.exp
.X_add_number
;
7047 if (num_regs
< 1 || num_regs
> 4)
7049 inst
.error
= _("number of registers must be in the range [1:4]");
7056 inst
.instruction
|= CP_T_X
;
7059 inst
.instruction
|= CP_T_Y
;
7062 inst
.instruction
|= CP_T_Y
| CP_T_X
;
7070 if (inst
.instruction
& (CP_T_Pre
| CP_T_UD
)) /* ea/fd format. */
7076 /* The instruction specified "ea" or "fd", so we can only accept
7077 [Rn]{!}. The instruction does not really support stacking or
7078 unstacking, so we have to emulate these by setting appropriate
7079 bits and offsets. */
7080 if (skip_past_comma (&str
) == FAIL
7084 inst
.error
= BAD_ARGS
;
7089 skip_whitespace (str
);
7091 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
7094 skip_whitespace (str
);
7098 inst
.error
= BAD_ARGS
;
7110 _("r15 not allowed as base register with write-back");
7117 if (inst
.instruction
& CP_T_Pre
)
7119 /* Pre-decrement. */
7120 offset
= 3 * num_regs
;
7122 inst
.instruction
|= CP_T_WB
;
7126 /* Post-increment. */
7129 inst
.instruction
|= CP_T_WB
;
7130 offset
= 3 * num_regs
;
7134 /* No write-back, so convert this into a standard pre-increment
7135 instruction -- aesthetically more pleasing. */
7136 inst
.instruction
|= CP_T_Pre
| CP_T_UD
;
7141 inst
.instruction
|= offset
;
7143 else if (skip_past_comma (&str
) == FAIL
7144 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
7147 inst
.error
= BAD_ARGS
;
7155 do_fpa_dyadic (char * str
)
7157 skip_whitespace (str
);
7159 if (fp_reg_required_here (&str
, 12) == FAIL
)
7162 inst
.error
= BAD_ARGS
;
7166 if (skip_past_comma (&str
) == FAIL
7167 || fp_reg_required_here (&str
, 16) == FAIL
)
7170 inst
.error
= BAD_ARGS
;
7174 if (skip_past_comma (&str
) == FAIL
7175 || fp_op2 (&str
) == FAIL
)
7178 inst
.error
= BAD_ARGS
;
7186 do_fpa_monadic (char * str
)
7188 skip_whitespace (str
);
7190 if (fp_reg_required_here (&str
, 12) == FAIL
)
7193 inst
.error
= BAD_ARGS
;
7197 if (skip_past_comma (&str
) == FAIL
7198 || fp_op2 (&str
) == FAIL
)
7201 inst
.error
= BAD_ARGS
;
7209 do_fpa_cmp (char * str
)
7211 skip_whitespace (str
);
7213 if (fp_reg_required_here (&str
, 16) == FAIL
)
7216 inst
.error
= BAD_ARGS
;
7220 if (skip_past_comma (&str
) == FAIL
7221 || fp_op2 (&str
) == FAIL
)
7224 inst
.error
= BAD_ARGS
;
7232 do_fpa_from_reg (char * str
)
7234 skip_whitespace (str
);
7236 if (fp_reg_required_here (&str
, 16) == FAIL
)
7239 inst
.error
= BAD_ARGS
;
7243 if (skip_past_comma (&str
) == FAIL
7244 || reg_required_here (&str
, 12) == FAIL
)
7247 inst
.error
= BAD_ARGS
;
7255 do_fpa_to_reg (char * str
)
7257 skip_whitespace (str
);
7259 if (reg_required_here (&str
, 12) == FAIL
)
7262 if (skip_past_comma (&str
) == FAIL
7263 || fp_reg_required_here (&str
, 0) == FAIL
)
7266 inst
.error
= BAD_ARGS
;
7274 vfp_sp_reg_required_here (char ** str
,
7275 enum vfp_sp_reg_pos pos
)
7280 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_SN
].htab
)) != FAIL
)
7285 inst
.instruction
|= ((reg
>> 1) << 12) | ((reg
& 1) << 22);
7289 inst
.instruction
|= ((reg
>> 1) << 16) | ((reg
& 1) << 7);
7293 inst
.instruction
|= ((reg
>> 1) << 0) | ((reg
& 1) << 5);
7302 /* In the few cases where we might be able to accept something else
7303 this error can be overridden. */
7304 inst
.error
= _(all_reg_maps
[REG_TYPE_SN
].expected
);
7306 /* Restore the start point. */
7312 vfp_dp_reg_required_here (char ** str
,
7313 enum vfp_dp_reg_pos pos
)
7316 char * start
= *str
;
7318 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_DN
].htab
)) != FAIL
)
7323 inst
.instruction
|= reg
<< 12;
7327 inst
.instruction
|= reg
<< 16;
7331 inst
.instruction
|= reg
<< 0;
7340 /* In the few cases where we might be able to accept something else
7341 this error can be overridden. */
7342 inst
.error
= _(all_reg_maps
[REG_TYPE_DN
].expected
);
7344 /* Restore the start point. */
7350 do_vfp_sp_monadic (char * str
)
7352 skip_whitespace (str
);
7354 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7357 if (skip_past_comma (&str
) == FAIL
7358 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
7361 inst
.error
= BAD_ARGS
;
7369 do_vfp_dp_monadic (char * str
)
7371 skip_whitespace (str
);
7373 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7376 if (skip_past_comma (&str
) == FAIL
7377 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7380 inst
.error
= BAD_ARGS
;
7388 do_vfp_sp_dyadic (char * str
)
7390 skip_whitespace (str
);
7392 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7395 if (skip_past_comma (&str
) == FAIL
7396 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
7397 || skip_past_comma (&str
) == FAIL
7398 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
7401 inst
.error
= BAD_ARGS
;
7409 do_vfp_dp_dyadic (char * str
)
7411 skip_whitespace (str
);
7413 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7416 if (skip_past_comma (&str
) == FAIL
7417 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
7418 || skip_past_comma (&str
) == FAIL
7419 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7422 inst
.error
= BAD_ARGS
;
7430 do_vfp_reg_from_sp (char * str
)
7432 skip_whitespace (str
);
7434 if (reg_required_here (&str
, 12) == FAIL
)
7437 if (skip_past_comma (&str
) == FAIL
7438 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
7441 inst
.error
= BAD_ARGS
;
7448 /* Parse and encode a VFP SP register list, storing the initial
7449 register in position POS and returning the range as the result. If
7450 the string is invalid return FAIL (an invalid range). */
7453 vfp_sp_reg_list (char ** str
, enum vfp_sp_reg_pos pos
)
7461 unsigned long mask
= 0;
7468 skip_whitespace (*str
);
7470 tempinst
= inst
.instruction
;
7474 inst
.instruction
= 0;
7476 if ((new_base
= vfp_sp_reg_required_here (str
, pos
)) == FAIL
)
7479 if (count
== 0 || base_reg
> new_base
)
7481 base_reg
= new_base
;
7482 base_bits
= inst
.instruction
;
7485 if (mask
& (1 << new_base
))
7487 inst
.error
= _("invalid register list");
7491 if ((mask
>> new_base
) != 0 && ! warned
)
7493 as_tsktsk (_("register list not in ascending order"));
7497 mask
|= 1 << new_base
;
7500 skip_whitespace (*str
);
7502 if (**str
== '-') /* We have the start of a range expression */
7509 = arm_reg_parse (str
, all_reg_maps
[REG_TYPE_SN
].htab
))
7512 inst
.error
= _(all_reg_maps
[REG_TYPE_SN
].expected
);
7516 if (high_range
<= new_base
)
7518 inst
.error
= _("register range not in ascending order");
7522 for (new_base
++; new_base
<= high_range
; new_base
++)
7524 if (mask
& (1 << new_base
))
7526 inst
.error
= _("invalid register list");
7530 mask
|= 1 << new_base
;
7535 while (skip_past_comma (str
) != FAIL
);
7539 inst
.error
= _("invalid register list");
7547 /* Sanity check -- should have raised a parse error above. */
7548 if (count
== 0 || count
> 32)
7551 /* Final test -- the registers must be consecutive. */
7554 if ((mask
& (1 << base_reg
++)) == 0)
7556 inst
.error
= _("non-contiguous register range");
7561 inst
.instruction
= tempinst
| base_bits
;
7566 do_vfp_reg2_from_sp2 (char * str
)
7568 skip_whitespace (str
);
7570 if (reg_required_here (&str
, 12) == FAIL
7571 || skip_past_comma (&str
) == FAIL
7572 || reg_required_here (&str
, 16) == FAIL
7573 || skip_past_comma (&str
) == FAIL
)
7576 inst
.error
= BAD_ARGS
;
7580 /* We require exactly two consecutive SP registers. */
7581 if (vfp_sp_reg_list (&str
, VFP_REG_Sm
) != 2)
7584 inst
.error
= _("only two consecutive VFP SP registers allowed here");
7591 do_vfp_sp_from_reg (char * str
)
7593 skip_whitespace (str
);
7595 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
7598 if (skip_past_comma (&str
) == FAIL
7599 || reg_required_here (&str
, 12) == FAIL
)
7602 inst
.error
= BAD_ARGS
;
7610 do_vfp_sp2_from_reg2 (char * str
)
7612 skip_whitespace (str
);
7614 /* We require exactly two consecutive SP registers. */
7615 if (vfp_sp_reg_list (&str
, VFP_REG_Sm
) != 2)
7618 inst
.error
= _("only two consecutive VFP SP registers allowed here");
7621 if (skip_past_comma (&str
) == FAIL
7622 || reg_required_here (&str
, 12) == FAIL
7623 || skip_past_comma (&str
) == FAIL
7624 || reg_required_here (&str
, 16) == FAIL
)
7627 inst
.error
= BAD_ARGS
;
7635 do_vfp_reg_from_dp (char * str
)
7637 skip_whitespace (str
);
7639 if (reg_required_here (&str
, 12) == FAIL
)
7642 if (skip_past_comma (&str
) == FAIL
7643 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
7646 inst
.error
= BAD_ARGS
;
7654 do_vfp_reg2_from_dp (char * str
)
7656 skip_whitespace (str
);
7658 if (reg_required_here (&str
, 12) == FAIL
)
7661 if (skip_past_comma (&str
) == FAIL
7662 || reg_required_here (&str
, 16) == FAIL
7663 || skip_past_comma (&str
) == FAIL
7664 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7667 inst
.error
= BAD_ARGS
;
7675 do_vfp_dp_from_reg (char * str
)
7677 skip_whitespace (str
);
7679 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
7682 if (skip_past_comma (&str
) == FAIL
7683 || reg_required_here (&str
, 12) == FAIL
)
7686 inst
.error
= BAD_ARGS
;
7694 do_vfp_dp_from_reg2 (char * str
)
7696 skip_whitespace (str
);
7698 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7701 if (skip_past_comma (&str
) == FAIL
7702 || reg_required_here (&str
, 12) == FAIL
7703 || skip_past_comma (&str
) == FAIL
7704 || reg_required_here (&str
, 16) == FAIL
)
7707 inst
.error
= BAD_ARGS
;
7714 static const struct vfp_reg
*
7715 vfp_psr_parse (char ** str
)
7720 const struct vfp_reg
*vreg
;
7724 /* Find the end of the current token. */
7729 while (ISALPHA (c
));
7734 for (vreg
= vfp_regs
+ 0;
7735 vreg
< vfp_regs
+ sizeof (vfp_regs
) / sizeof (struct vfp_reg
);
7738 if (streq (start
, vreg
->name
))
7751 vfp_psr_required_here (char ** str
)
7754 const struct vfp_reg
*vreg
;
7756 vreg
= vfp_psr_parse (str
);
7760 inst
.instruction
|= vreg
->regno
;
7764 inst
.error
= _("VFP system register expected");
7771 do_vfp_reg_from_ctrl (char * str
)
7773 skip_whitespace (str
);
7775 if (reg_required_here (&str
, 12) == FAIL
)
7778 if (skip_past_comma (&str
) == FAIL
7779 || vfp_psr_required_here (&str
) == FAIL
)
7782 inst
.error
= BAD_ARGS
;
7790 do_vfp_ctrl_from_reg (char * str
)
7792 skip_whitespace (str
);
7794 if (vfp_psr_required_here (&str
) == FAIL
)
7797 if (skip_past_comma (&str
) == FAIL
7798 || reg_required_here (&str
, 12) == FAIL
)
7801 inst
.error
= BAD_ARGS
;
7809 do_vfp_sp_ldst (char * str
)
7811 skip_whitespace (str
);
7813 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7816 inst
.error
= BAD_ARGS
;
7820 if (skip_past_comma (&str
) == FAIL
7821 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
7824 inst
.error
= BAD_ARGS
;
7832 do_vfp_dp_ldst (char * str
)
7834 skip_whitespace (str
);
7836 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7839 inst
.error
= BAD_ARGS
;
7843 if (skip_past_comma (&str
) == FAIL
7844 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
7847 inst
.error
= BAD_ARGS
;
7855 vfp_dp_reg_list (char ** str
)
7862 unsigned long mask
= 0;
7869 skip_whitespace (*str
);
7871 tempinst
= inst
.instruction
;
7875 inst
.instruction
= 0;
7877 if ((new_base
= vfp_dp_reg_required_here (str
, VFP_REG_Dd
)) == FAIL
)
7880 if (count
== 0 || base_reg
> new_base
)
7882 base_reg
= new_base
;
7883 range
= inst
.instruction
;
7886 if (mask
& (1 << new_base
))
7888 inst
.error
= _("invalid register list");
7892 if ((mask
>> new_base
) != 0 && ! warned
)
7894 as_tsktsk (_("register list not in ascending order"));
7898 mask
|= 1 << new_base
;
7901 skip_whitespace (*str
);
7903 if (**str
== '-') /* We have the start of a range expression */
7910 = arm_reg_parse (str
, all_reg_maps
[REG_TYPE_DN
].htab
))
7913 inst
.error
= _(all_reg_maps
[REG_TYPE_DN
].expected
);
7917 if (high_range
<= new_base
)
7919 inst
.error
= _("register range not in ascending order");
7923 for (new_base
++; new_base
<= high_range
; new_base
++)
7925 if (mask
& (1 << new_base
))
7927 inst
.error
= _("invalid register list");
7931 mask
|= 1 << new_base
;
7936 while (skip_past_comma (str
) != FAIL
);
7940 inst
.error
= _("invalid register list");
7948 /* Sanity check -- should have raised a parse error above. */
7949 if (count
== 0 || count
> 16)
7952 /* Final test -- the registers must be consecutive. */
7955 if ((mask
& (1 << base_reg
++)) == 0)
7957 inst
.error
= _("non-contiguous register range");
7962 inst
.instruction
= tempinst
;
7967 vfp_sp_ldstm (char * str
, enum vfp_ldstm_type ldstm_type
)
7971 skip_whitespace (str
);
7973 if (reg_required_here (&str
, 16) == FAIL
)
7976 skip_whitespace (str
);
7980 inst
.instruction
|= WRITE_BACK
;
7983 else if (ldstm_type
!= VFP_LDSTMIA
)
7985 inst
.error
= _("this addressing mode requires base-register writeback");
7989 if (skip_past_comma (&str
) == FAIL
7990 || (range
= vfp_sp_reg_list (&str
, VFP_REG_Sd
)) == FAIL
)
7993 inst
.error
= BAD_ARGS
;
7997 inst
.instruction
|= range
;
8002 vfp_dp_ldstm (char * str
, enum vfp_ldstm_type ldstm_type
)
8006 skip_whitespace (str
);
8008 if (reg_required_here (&str
, 16) == FAIL
)
8011 skip_whitespace (str
);
8015 inst
.instruction
|= WRITE_BACK
;
8018 else if (ldstm_type
!= VFP_LDSTMIA
&& ldstm_type
!= VFP_LDSTMIAX
)
8020 inst
.error
= _("this addressing mode requires base-register writeback");
8024 if (skip_past_comma (&str
) == FAIL
8025 || (range
= vfp_dp_reg_list (&str
)) == FAIL
)
8028 inst
.error
= BAD_ARGS
;
8032 if (ldstm_type
== VFP_LDSTMIAX
|| ldstm_type
== VFP_LDSTMDBX
)
8035 inst
.instruction
|= range
;
8040 do_vfp_sp_ldstmia (char * str
)
8042 vfp_sp_ldstm (str
, VFP_LDSTMIA
);
8046 do_vfp_sp_ldstmdb (char * str
)
8048 vfp_sp_ldstm (str
, VFP_LDSTMDB
);
8052 do_vfp_dp_ldstmia (char * str
)
8054 vfp_dp_ldstm (str
, VFP_LDSTMIA
);
8058 do_vfp_dp_ldstmdb (char * str
)
8060 vfp_dp_ldstm (str
, VFP_LDSTMDB
);
8064 do_vfp_xp_ldstmia (char *str
)
8066 vfp_dp_ldstm (str
, VFP_LDSTMIAX
);
8070 do_vfp_xp_ldstmdb (char * str
)
8072 vfp_dp_ldstm (str
, VFP_LDSTMDBX
);
8076 do_vfp_sp_compare_z (char * str
)
8078 skip_whitespace (str
);
8080 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8083 inst
.error
= BAD_ARGS
;
8091 do_vfp_dp_compare_z (char * str
)
8093 skip_whitespace (str
);
8095 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8098 inst
.error
= BAD_ARGS
;
8106 do_vfp_dp_sp_cvt (char * str
)
8108 skip_whitespace (str
);
8110 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8113 if (skip_past_comma (&str
) == FAIL
8114 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
8117 inst
.error
= BAD_ARGS
;
8125 do_vfp_sp_dp_cvt (char * str
)
8127 skip_whitespace (str
);
8129 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8132 if (skip_past_comma (&str
) == FAIL
8133 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
8136 inst
.error
= BAD_ARGS
;
8143 /* Thumb specific routines. */
8145 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
8149 thumb_add_sub (char * str
, int subtract
)
8151 int Rd
, Rs
, Rn
= FAIL
;
8153 skip_whitespace (str
);
8155 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
8156 || skip_past_comma (&str
) == FAIL
)
8159 inst
.error
= BAD_ARGS
;
8163 if (is_immediate_prefix (*str
))
8167 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8172 if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8175 if (skip_past_comma (&str
) == FAIL
)
8177 /* Two operand format, shuffle the registers
8178 and pretend there are 3. */
8182 else if (is_immediate_prefix (*str
))
8185 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8188 else if ((Rn
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8192 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8193 for the latter case, EXPR contains the immediate that was found. */
8196 /* All register format. */
8197 if (Rd
> 7 || Rs
> 7 || Rn
> 7)
8201 inst
.error
= _("dest and source1 must be the same register");
8205 /* Can't do this for SUB. */
8208 inst
.error
= _("subtract valid only on lo regs");
8212 inst
.instruction
= (T_OPCODE_ADD_HI
8213 | (Rd
> 7 ? THUMB_H1
: 0)
8214 | (Rn
> 7 ? THUMB_H2
: 0));
8215 inst
.instruction
|= (Rd
& 7) | ((Rn
& 7) << 3);
8219 inst
.instruction
= subtract
? T_OPCODE_SUB_R3
: T_OPCODE_ADD_R3
;
8220 inst
.instruction
|= Rd
| (Rs
<< 3) | (Rn
<< 6);
8225 /* Immediate expression, now things start to get nasty. */
8227 /* First deal with HI regs, only very restricted cases allowed:
8228 Adjusting SP, and using PC or SP to get an address. */
8229 if ((Rd
> 7 && (Rd
!= REG_SP
|| Rs
!= REG_SP
))
8230 || (Rs
> 7 && Rs
!= REG_SP
&& Rs
!= REG_PC
))
8232 inst
.error
= _("invalid Hi register with immediate");
8236 if (inst
.reloc
.exp
.X_op
!= O_constant
)
8238 /* Value isn't known yet, all we can do is store all the fragments
8239 we know about in the instruction and let the reloc hacking
8241 inst
.instruction
= (subtract
? 0x8000 : 0) | (Rd
<< 4) | Rs
;
8242 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
8246 int offset
= inst
.reloc
.exp
.X_add_number
;
8256 /* Quick check, in case offset is MIN_INT. */
8259 inst
.error
= _("immediate value out of range");
8263 /* Note - you cannot convert a subtract of 0 into an
8264 add of 0 because the carry flag is set differently. */
8265 else if (offset
> 0)
8270 if (offset
& ~0x1fc)
8272 inst
.error
= _("invalid immediate value for stack adjust");
8275 inst
.instruction
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
8276 inst
.instruction
|= offset
>> 2;
8278 else if (Rs
== REG_PC
|| Rs
== REG_SP
)
8281 || (offset
& ~0x3fc))
8283 inst
.error
= _("invalid immediate for address calculation");
8286 inst
.instruction
= (Rs
== REG_PC
? T_OPCODE_ADD_PC
8288 inst
.instruction
|= (Rd
<< 8) | (offset
>> 2);
8294 inst
.error
= _("immediate value out of range");
8297 inst
.instruction
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
8298 inst
.instruction
|= (Rd
<< 8) | offset
;
8304 inst
.error
= _("immediate value out of range");
8307 inst
.instruction
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
8308 inst
.instruction
|= Rd
| (Rs
<< 3) | (offset
<< 6);
8317 thumb_shift (char * str
, int shift
)
8319 int Rd
, Rs
, Rn
= FAIL
;
8321 skip_whitespace (str
);
8323 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
8324 || skip_past_comma (&str
) == FAIL
)
8327 inst
.error
= BAD_ARGS
;
8331 if (is_immediate_prefix (*str
))
8333 /* Two operand immediate format, set Rs to Rd. */
8336 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8341 if ((Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8344 if (skip_past_comma (&str
) == FAIL
)
8346 /* Two operand format, shuffle the registers
8347 and pretend there are 3. */
8351 else if (is_immediate_prefix (*str
))
8354 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8357 else if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8361 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8362 for the latter case, EXPR contains the immediate that was found. */
8368 inst
.error
= _("source1 and dest must be same register");
8374 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_R
; break;
8375 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_R
; break;
8376 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_R
; break;
8379 inst
.instruction
|= Rd
| (Rn
<< 3);
8385 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_I
; break;
8386 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_I
; break;
8387 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_I
; break;
8390 if (inst
.reloc
.exp
.X_op
!= O_constant
)
8392 /* Value isn't known yet, create a dummy reloc and let reloc
8393 hacking fix it up. */
8394 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_SHIFT
;
8398 unsigned shift_value
= inst
.reloc
.exp
.X_add_number
;
8400 if (shift_value
> 32 || (shift_value
== 32 && shift
== THUMB_LSL
))
8402 inst
.error
= _("invalid immediate for shift");
8406 /* Shifts of zero are handled by converting to LSL. */
8407 if (shift_value
== 0)
8408 inst
.instruction
= T_OPCODE_LSL_I
;
8410 /* Shifts of 32 are encoded as a shift of zero. */
8411 if (shift_value
== 32)
8414 inst
.instruction
|= shift_value
<< 6;
8417 inst
.instruction
|= Rd
| (Rs
<< 3);
8424 thumb_load_store (char * str
, int load_store
, int size
)
8426 int Rd
, Rb
, Ro
= FAIL
;
8428 skip_whitespace (str
);
8430 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
8431 || skip_past_comma (&str
) == FAIL
)
8434 inst
.error
= BAD_ARGS
;
8441 if ((Rb
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8444 if (skip_past_comma (&str
) != FAIL
)
8446 if (is_immediate_prefix (*str
))
8449 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8452 else if ((Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8457 inst
.reloc
.exp
.X_op
= O_constant
;
8458 inst
.reloc
.exp
.X_add_number
= 0;
8463 inst
.error
= _("expected ']'");
8468 else if (*str
== '=')
8470 if (load_store
!= THUMB_LOAD
)
8472 inst
.error
= _("invalid pseudo operation");
8476 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
8479 skip_whitespace (str
);
8481 if (my_get_expression (& inst
.reloc
.exp
, & str
))
8486 if ( inst
.reloc
.exp
.X_op
!= O_constant
8487 && inst
.reloc
.exp
.X_op
!= O_symbol
)
8489 inst
.error
= "Constant expression expected";
8493 if (inst
.reloc
.exp
.X_op
== O_constant
8494 && ((inst
.reloc
.exp
.X_add_number
& ~0xFF) == 0))
8496 /* This can be done with a mov instruction. */
8498 inst
.instruction
= T_OPCODE_MOV_I8
| (Rd
<< 8);
8499 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
8503 /* Insert into literal pool. */
8504 if (add_to_lit_pool () == FAIL
)
8507 inst
.error
= "literal pool insertion failed";
8511 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8512 inst
.reloc
.pc_rel
= 1;
8513 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
8514 /* Adjust ARM pipeline offset to Thumb. */
8515 inst
.reloc
.exp
.X_add_number
+= 4;
8521 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8524 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
8525 inst
.reloc
.pc_rel
= 1;
8526 inst
.reloc
.exp
.X_add_number
-= 4; /* Pipeline offset. */
8527 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8532 if (Rb
== REG_PC
|| Rb
== REG_SP
)
8534 if (size
!= THUMB_WORD
)
8536 inst
.error
= _("byte or halfword not valid for base register");
8539 else if (Rb
== REG_PC
&& load_store
!= THUMB_LOAD
)
8541 inst
.error
= _("r15 based store not allowed");
8544 else if (Ro
!= FAIL
)
8546 inst
.error
= _("invalid base register for register offset");
8551 inst
.instruction
= T_OPCODE_LDR_PC
;
8552 else if (load_store
== THUMB_LOAD
)
8553 inst
.instruction
= T_OPCODE_LDR_SP
;
8555 inst
.instruction
= T_OPCODE_STR_SP
;
8557 inst
.instruction
|= Rd
<< 8;
8558 if (inst
.reloc
.exp
.X_op
== O_constant
)
8560 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
8562 if (offset
& ~0x3fc)
8564 inst
.error
= _("invalid offset");
8568 inst
.instruction
|= offset
>> 2;
8571 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8575 inst
.error
= _("invalid base register in load/store");
8578 else if (Ro
== FAIL
)
8580 /* Immediate offset. */
8581 if (size
== THUMB_WORD
)
8582 inst
.instruction
= (load_store
== THUMB_LOAD
8583 ? T_OPCODE_LDR_IW
: T_OPCODE_STR_IW
);
8584 else if (size
== THUMB_HALFWORD
)
8585 inst
.instruction
= (load_store
== THUMB_LOAD
8586 ? T_OPCODE_LDR_IH
: T_OPCODE_STR_IH
);
8588 inst
.instruction
= (load_store
== THUMB_LOAD
8589 ? T_OPCODE_LDR_IB
: T_OPCODE_STR_IB
);
8591 inst
.instruction
|= Rd
| (Rb
<< 3);
8593 if (inst
.reloc
.exp
.X_op
== O_constant
)
8595 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
8597 if (offset
& ~(0x1f << size
))
8599 inst
.error
= _("invalid offset");
8602 inst
.instruction
|= (offset
>> size
) << 6;
8605 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8609 /* Register offset. */
8610 if (size
== THUMB_WORD
)
8611 inst
.instruction
= (load_store
== THUMB_LOAD
8612 ? T_OPCODE_LDR_RW
: T_OPCODE_STR_RW
);
8613 else if (size
== THUMB_HALFWORD
)
8614 inst
.instruction
= (load_store
== THUMB_LOAD
8615 ? T_OPCODE_LDR_RH
: T_OPCODE_STR_RH
);
8617 inst
.instruction
= (load_store
== THUMB_LOAD
8618 ? T_OPCODE_LDR_RB
: T_OPCODE_STR_RB
);
8620 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
8626 /* A register must be given at this point.
8628 Shift is the place to put it in inst.instruction.
8630 Restores input start point on err.
8631 Returns the reg#, or FAIL. */
8634 mav_reg_required_here (char ** str
, int shift
, enum arm_reg_type regtype
)
8639 if ((reg
= arm_reg_parse (str
, all_reg_maps
[regtype
].htab
)) != FAIL
)
8642 inst
.instruction
|= reg
<< shift
;
8647 /* Restore the start point. */
8650 /* Try generic coprocessor name if applicable. */
8651 if (regtype
== REG_TYPE_MVF
||
8652 regtype
== REG_TYPE_MVD
||
8653 regtype
== REG_TYPE_MVFX
||
8654 regtype
== REG_TYPE_MVDX
)
8656 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CN
].htab
)) != FAIL
)
8659 inst
.instruction
|= reg
<< shift
;
8664 /* Restore the start point. */
8668 /* In the few cases where we might be able to accept something else
8669 this error can be overridden. */
8670 inst
.error
= _(all_reg_maps
[regtype
].expected
);
8675 /* Cirrus Maverick Instructions. */
8677 /* Isnsn like "foo X,Y". */
8680 do_mav_binops (char * str
,
8682 enum arm_reg_type reg0
,
8683 enum arm_reg_type reg1
)
8687 shift0
= mode
& 0xff;
8688 shift1
= (mode
>> 8) & 0xff;
8690 skip_whitespace (str
);
8692 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
8693 || skip_past_comma (&str
) == FAIL
8694 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
)
8697 inst
.error
= BAD_ARGS
;
8703 /* Isnsn like "foo X,Y,Z". */
8706 do_mav_triple (char * str
,
8708 enum arm_reg_type reg0
,
8709 enum arm_reg_type reg1
,
8710 enum arm_reg_type reg2
)
8712 int shift0
, shift1
, shift2
;
8714 shift0
= mode
& 0xff;
8715 shift1
= (mode
>> 8) & 0xff;
8716 shift2
= (mode
>> 16) & 0xff;
8718 skip_whitespace (str
);
8720 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
8721 || skip_past_comma (&str
) == FAIL
8722 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
8723 || skip_past_comma (&str
) == FAIL
8724 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
)
8727 inst
.error
= BAD_ARGS
;
8733 /* Wrapper functions. */
8736 do_mav_binops_1a (char * str
)
8738 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVF
);
8742 do_mav_binops_1b (char * str
)
8744 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVD
);
8748 do_mav_binops_1c (char * str
)
8750 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVDX
);
8754 do_mav_binops_1d (char * str
)
8756 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVF
);
8760 do_mav_binops_1e (char * str
)
8762 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVD
);
8766 do_mav_binops_1f (char * str
)
8768 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVF
);
8772 do_mav_binops_1g (char * str
)
8774 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVD
);
8778 do_mav_binops_1h (char * str
)
8780 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVFX
);
8784 do_mav_binops_1i (char * str
)
8786 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVFX
);
8790 do_mav_binops_1j (char * str
)
8792 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVDX
);
8796 do_mav_binops_1k (char * str
)
8798 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVDX
);
8802 do_mav_binops_1l (char * str
)
8804 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVF
);
8808 do_mav_binops_1m (char * str
)
8810 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVD
);
8814 do_mav_binops_1n (char * str
)
8816 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
8820 do_mav_binops_1o (char * str
)
8822 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
8826 do_mav_binops_2a (char * str
)
8828 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVF
, REG_TYPE_RN
);
8832 do_mav_binops_2b (char * str
)
8834 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVD
, REG_TYPE_RN
);
8838 do_mav_binops_2c (char * str
)
8840 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVDX
, REG_TYPE_RN
);
8844 do_mav_binops_3a (char * str
)
8846 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVFX
);
8850 do_mav_binops_3b (char * str
)
8852 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVFX
, REG_TYPE_MVAX
);
8856 do_mav_binops_3c (char * str
)
8858 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVDX
);
8862 do_mav_binops_3d (char * str
)
8864 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVDX
, REG_TYPE_MVAX
);
8868 do_mav_triple_4a (char * str
)
8870 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_RN
);
8874 do_mav_triple_4b (char * str
)
8876 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_RN
);
8880 do_mav_triple_5a (char * str
)
8882 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVF
, REG_TYPE_MVF
);
8886 do_mav_triple_5b (char * str
)
8888 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVD
, REG_TYPE_MVD
);
8892 do_mav_triple_5c (char * str
)
8894 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
8898 do_mav_triple_5d (char * str
)
8900 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
8904 do_mav_triple_5e (char * str
)
8906 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVF
, REG_TYPE_MVF
, REG_TYPE_MVF
);
8910 do_mav_triple_5f (char * str
)
8912 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVD
, REG_TYPE_MVD
, REG_TYPE_MVD
);
8916 do_mav_triple_5g (char * str
)
8918 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
8922 do_mav_triple_5h (char * str
)
8924 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
8927 /* Isnsn like "foo W,X,Y,Z".
8928 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
8931 do_mav_quad (char * str
,
8933 enum arm_reg_type reg0
,
8934 enum arm_reg_type reg1
,
8935 enum arm_reg_type reg2
,
8936 enum arm_reg_type reg3
)
8938 int shift0
, shift1
, shift2
, shift3
;
8940 shift0
= mode
& 0xff;
8941 shift1
= (mode
>> 8) & 0xff;
8942 shift2
= (mode
>> 16) & 0xff;
8943 shift3
= (mode
>> 24) & 0xff;
8945 skip_whitespace (str
);
8947 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
8948 || skip_past_comma (&str
) == FAIL
8949 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
8950 || skip_past_comma (&str
) == FAIL
8951 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
8952 || skip_past_comma (&str
) == FAIL
8953 || mav_reg_required_here (&str
, shift3
, reg3
) == FAIL
)
8956 inst
.error
= BAD_ARGS
;
8963 do_mav_quad_6a (char * str
)
8965 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
,
8970 do_mav_quad_6b (char * str
)
8972 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVAX
, REG_TYPE_MVFX
,
8976 /* cfmvsc32<cond> DSPSC,MVDX[15:0]. */
8978 do_mav_dspsc_1 (char * str
)
8980 skip_whitespace (str
);
8983 if (mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
8984 || skip_past_comma (&str
) == FAIL
8985 || mav_reg_required_here (&str
, 12, REG_TYPE_MVDX
) == FAIL
)
8988 inst
.error
= BAD_ARGS
;
8996 /* cfmv32sc<cond> MVDX[15:0],DSPSC. */
8998 do_mav_dspsc_2 (char * str
)
9000 skip_whitespace (str
);
9003 if (mav_reg_required_here (&str
, 12, REG_TYPE_MVDX
) == FAIL
9004 || skip_past_comma (&str
) == FAIL
9005 || mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
)
9008 inst
.error
= BAD_ARGS
;
9016 /* Maverick shift immediate instructions.
9017 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
9018 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
9021 do_mav_shift (char * str
,
9022 enum arm_reg_type reg0
,
9023 enum arm_reg_type reg1
)
9028 skip_whitespace (str
);
9032 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
9033 || skip_past_comma (&str
) == FAIL
9034 || mav_reg_required_here (&str
, 16, reg1
) == FAIL
9035 || skip_past_comma (&str
) == FAIL
)
9038 inst
.error
= BAD_ARGS
;
9042 /* Calculate the immediate operand.
9043 The operand is a 7bit signed number. */
9044 skip_whitespace (str
);
9049 if (!ISDIGIT (*str
) && *str
!= '-')
9051 inst
.error
= _("expecting immediate, 7bit operand");
9061 for (imm
= 0; *str
&& ISDIGIT (*str
); ++str
)
9062 imm
= imm
* 10 + *str
- '0';
9066 inst
.error
= _("immediate out of range");
9070 /* Make negative imm's into 7bit signed numbers. */
9077 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
9078 Bits 5-7 of the insn should have bits 4-6 of the immediate.
9079 Bit 4 should be 0. */
9080 imm
= (imm
& 0xf) | ((imm
& 0x70) << 1);
9082 inst
.instruction
|= imm
;
9087 do_mav_shift_1 (char * str
)
9089 do_mav_shift (str
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
9093 do_mav_shift_2 (char * str
)
9095 do_mav_shift (str
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
9099 mav_parse_offset (char ** str
, int * negative
)
9106 skip_whitespace (p
);
9119 inst
.error
= _("offset expected");
9123 for (offset
= 0; *p
&& ISDIGIT (*p
); ++p
)
9124 offset
= offset
* 10 + *p
- '0';
9128 inst
.error
= _("offset out of range");
9133 inst
.error
= _("offset not a multiple of 4");
9139 return *negative
? -offset
: offset
;
9142 /* Maverick load/store instructions.
9143 <insn><cond> CRd,[Rn,<offset>]{!}.
9144 <insn><cond> CRd,[Rn],<offset>. */
9147 do_mav_ldst (char * str
, enum arm_reg_type reg0
)
9149 int offset
, negative
;
9151 skip_whitespace (str
);
9153 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
9154 || skip_past_comma (&str
) == FAIL
9156 || reg_required_here (&str
, 16) == FAIL
)
9159 if (skip_past_comma (&str
) == SUCCESS
)
9161 /* You are here: "<offset>]{!}". */
9162 inst
.instruction
|= PRE_INDEX
;
9164 offset
= mav_parse_offset (&str
, &negative
);
9171 inst
.error
= _("missing ]");
9177 inst
.instruction
|= WRITE_BACK
;
9183 /* You are here: "], <offset>". */
9186 inst
.error
= _("missing ]");
9190 if (skip_past_comma (&str
) == FAIL
9191 || (offset
= mav_parse_offset (&str
, &negative
), inst
.error
))
9194 inst
.instruction
|= CP_T_WB
; /* Post indexed, set bit W. */
9200 inst
.instruction
|= CP_T_UD
; /* Positive, so set bit U. */
9202 inst
.instruction
|= offset
>> 2;
9208 inst
.error
= BAD_ARGS
;
9212 do_mav_ldst_1 (char * str
)
9214 do_mav_ldst (str
, REG_TYPE_MVF
);
9218 do_mav_ldst_2 (char * str
)
9220 do_mav_ldst (str
, REG_TYPE_MVD
);
9224 do_mav_ldst_3 (char * str
)
9226 do_mav_ldst (str
, REG_TYPE_MVFX
);
9230 do_mav_ldst_4 (char * str
)
9232 do_mav_ldst (str
, REG_TYPE_MVDX
);
9236 do_t_nop (char * str
)
9242 /* Handle the Format 4 instructions that do not have equivalents in other
9243 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
9247 do_t_arit (char * str
)
9251 skip_whitespace (str
);
9253 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9254 || skip_past_comma (&str
) == FAIL
9255 || (Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9257 inst
.error
= BAD_ARGS
;
9261 if (skip_past_comma (&str
) != FAIL
)
9263 /* Three operand format not allowed for TST, CMN, NEG and MVN.
9264 (It isn't allowed for CMP either, but that isn't handled by this
9266 if (inst
.instruction
== T_OPCODE_TST
9267 || inst
.instruction
== T_OPCODE_CMN
9268 || inst
.instruction
== T_OPCODE_NEG
9269 || inst
.instruction
== T_OPCODE_MVN
)
9271 inst
.error
= BAD_ARGS
;
9275 if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9280 inst
.error
= _("dest and source1 must be the same register");
9286 if (inst
.instruction
== T_OPCODE_MUL
9288 as_tsktsk (_("Rs and Rd must be different in MUL"));
9290 inst
.instruction
|= Rd
| (Rs
<< 3);
9295 do_t_add (char * str
)
9297 thumb_add_sub (str
, 0);
9301 do_t_asr (char * str
)
9303 thumb_shift (str
, THUMB_ASR
);
9307 do_t_branch9 (char * str
)
9309 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9311 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH9
;
9312 inst
.reloc
.pc_rel
= 1;
9317 do_t_branch12 (char * str
)
9319 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9321 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH12
;
9322 inst
.reloc
.pc_rel
= 1;
9326 /* Find the real, Thumb encoded start of a Thumb function. */
9329 find_real_start (symbolS
* symbolP
)
9332 const char * name
= S_GET_NAME (symbolP
);
9333 symbolS
* new_target
;
9335 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
9336 #define STUB_NAME ".real_start_of"
9341 /* Names that start with '.' are local labels, not function entry points.
9342 The compiler may generate BL instructions to these labels because it
9343 needs to perform a branch to a far away location. */
9347 real_start
= malloc (strlen (name
) + strlen (STUB_NAME
) + 1);
9348 sprintf (real_start
, "%s%s", STUB_NAME
, name
);
9350 new_target
= symbol_find (real_start
);
9352 if (new_target
== NULL
)
9354 as_warn ("Failed to find real start of function: %s\n", name
);
9355 new_target
= symbolP
;
9364 do_t_branch23 (char * str
)
9366 if (my_get_expression (& inst
.reloc
.exp
, & str
))
9369 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH23
;
9370 inst
.reloc
.pc_rel
= 1;
9373 /* If the destination of the branch is a defined symbol which does not have
9374 the THUMB_FUNC attribute, then we must be calling a function which has
9375 the (interfacearm) attribute. We look for the Thumb entry point to that
9376 function and change the branch to refer to that function instead. */
9377 if ( inst
.reloc
.exp
.X_op
== O_symbol
9378 && inst
.reloc
.exp
.X_add_symbol
!= NULL
9379 && S_IS_DEFINED (inst
.reloc
.exp
.X_add_symbol
)
9380 && ! THUMB_IS_FUNC (inst
.reloc
.exp
.X_add_symbol
))
9381 inst
.reloc
.exp
.X_add_symbol
=
9382 find_real_start (inst
.reloc
.exp
.X_add_symbol
);
9386 do_t_bx (char * str
)
9390 skip_whitespace (str
);
9392 if ((reg
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
9395 /* This sets THUMB_H2 from the top bit of reg. */
9396 inst
.instruction
|= reg
<< 3;
9398 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
9399 should cause the alignment to be checked once it is known. This is
9400 because BX PC only works if the instruction is word aligned. */
9406 do_t_compare (char * str
)
9408 thumb_mov_compare (str
, THUMB_COMPARE
);
9412 do_t_ldmstm (char * str
)
9417 skip_whitespace (str
);
9419 if ((Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9423 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
9427 if (skip_past_comma (&str
) == FAIL
9428 || (range
= reg_list (&str
)) == FAIL
)
9431 inst
.error
= BAD_ARGS
;
9435 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
9437 /* This really doesn't seem worth it. */
9438 inst
.reloc
.type
= BFD_RELOC_NONE
;
9439 inst
.error
= _("expression too complex");
9445 inst
.error
= _("only lo-regs valid in load/store multiple");
9449 inst
.instruction
|= (Rb
<< 8) | range
;
9454 do_t_ldr (char * str
)
9456 thumb_load_store (str
, THUMB_LOAD
, THUMB_WORD
);
9460 do_t_ldrb (char * str
)
9462 thumb_load_store (str
, THUMB_LOAD
, THUMB_BYTE
);
9466 do_t_ldrh (char * str
)
9468 thumb_load_store (str
, THUMB_LOAD
, THUMB_HALFWORD
);
9472 do_t_lds (char * str
)
9476 skip_whitespace (str
);
9478 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9479 || skip_past_comma (&str
) == FAIL
9481 || (Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9482 || skip_past_comma (&str
) == FAIL
9483 || (Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9487 inst
.error
= _("syntax: ldrs[b] Rd, [Rb, Ro]");
9491 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
9496 do_t_lsl (char * str
)
9498 thumb_shift (str
, THUMB_LSL
);
9502 do_t_lsr (char * str
)
9504 thumb_shift (str
, THUMB_LSR
);
9508 do_t_mov (char * str
)
9510 thumb_mov_compare (str
, THUMB_MOVE
);
9514 do_t_push_pop (char * str
)
9518 skip_whitespace (str
);
9520 if ((range
= reg_list (&str
)) == FAIL
)
9523 inst
.error
= BAD_ARGS
;
9527 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
9529 /* This really doesn't seem worth it. */
9530 inst
.reloc
.type
= BFD_RELOC_NONE
;
9531 inst
.error
= _("expression too complex");
9537 if ((inst
.instruction
== T_OPCODE_PUSH
9538 && (range
& ~0xff) == 1 << REG_LR
)
9539 || (inst
.instruction
== T_OPCODE_POP
9540 && (range
& ~0xff) == 1 << REG_PC
))
9542 inst
.instruction
|= THUMB_PP_PC_LR
;
9547 inst
.error
= _("invalid register list to push/pop instruction");
9552 inst
.instruction
|= range
;
9557 do_t_str (char * str
)
9559 thumb_load_store (str
, THUMB_STORE
, THUMB_WORD
);
9563 do_t_strb (char * str
)
9565 thumb_load_store (str
, THUMB_STORE
, THUMB_BYTE
);
9569 do_t_strh (char * str
)
9571 thumb_load_store (str
, THUMB_STORE
, THUMB_HALFWORD
);
9575 do_t_sub (char * str
)
9577 thumb_add_sub (str
, 1);
9581 do_t_swi (char * str
)
9583 skip_whitespace (str
);
9585 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9588 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
9593 do_t_adr (char * str
)
9597 /* This is a pseudo-op of the form "adr rd, label" to be converted
9598 into a relative address of the form "add rd, pc, #label-.-4". */
9599 skip_whitespace (str
);
9601 /* Store Rd in temporary location inside instruction. */
9602 if ((reg
= reg_required_here (&str
, 4)) == FAIL
9603 || (reg
> 7) /* For Thumb reg must be r0..r7. */
9604 || skip_past_comma (&str
) == FAIL
9605 || my_get_expression (&inst
.reloc
.exp
, &str
))
9608 inst
.error
= BAD_ARGS
;
9612 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
9613 inst
.reloc
.exp
.X_add_number
-= 4; /* PC relative adjust. */
9614 inst
.reloc
.pc_rel
= 1;
9615 inst
.instruction
|= REG_PC
; /* Rd is already placed into the instruction. */
9621 insert_reg (const struct reg_entry
* r
,
9622 struct hash_control
* htab
)
9624 int len
= strlen (r
->name
) + 2;
9625 char * buf
= xmalloc (len
);
9626 char * buf2
= xmalloc (len
);
9629 #ifdef REGISTER_PREFIX
9630 buf
[i
++] = REGISTER_PREFIX
;
9633 strcpy (buf
+ i
, r
->name
);
9635 for (i
= 0; buf
[i
]; i
++)
9636 buf2
[i
] = TOUPPER (buf
[i
]);
9640 hash_insert (htab
, buf
, (PTR
) r
);
9641 hash_insert (htab
, buf2
, (PTR
) r
);
9645 build_reg_hsh (struct reg_map
* map
)
9647 const struct reg_entry
*r
;
9649 if ((map
->htab
= hash_new ()) == NULL
)
9650 as_fatal (_("virtual memory exhausted"));
9652 for (r
= map
->names
; r
->name
!= NULL
; r
++)
9653 insert_reg (r
, map
->htab
);
9657 insert_reg_alias (char * str
,
9659 struct hash_control
*htab
)
9662 struct reg_entry
* new = xmalloc (sizeof (struct reg_entry
));
9663 const char * name
= xmalloc (strlen (str
) + 1);
9665 strcpy ((char *) name
, str
);
9668 new->number
= regnum
;
9669 new->builtin
= FALSE
;
9671 error
= hash_insert (htab
, name
, (PTR
) new);
9674 as_bad (_("failed to create an alias for %s, reason: %s"),
9676 free ((char *) name
);
9681 /* Look for the .req directive. This is of the form:
9683 new_register_name .req existing_register_name
9685 If we find one, or if it looks sufficiently like one that we want to
9686 handle any error here, return non-zero. Otherwise return zero. */
9689 create_register_alias (char * newname
, char * p
)
9695 skip_whitespace (q
);
9700 if (*q
&& !strncmp (q
, ".req ", 5))
9705 #ifndef IGNORE_OPCODE_CASE
9706 newname
= original_case_string
;
9708 copy_of_str
= newname
;
9711 skip_whitespace (q
);
9713 for (r
= q
; *r
!= '\0'; r
++)
9719 enum arm_reg_type new_type
, old_type
;
9724 old_type
= arm_reg_parse_any (q
);
9727 new_type
= arm_reg_parse_any (newname
);
9729 if (new_type
== REG_TYPE_MAX
)
9731 if (old_type
!= REG_TYPE_MAX
)
9733 old_regno
= arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
);
9734 insert_reg_alias (newname
, old_regno
,
9735 all_reg_maps
[old_type
].htab
);
9738 as_warn (_("register '%s' does not exist\n"), q
);
9740 else if (old_type
== REG_TYPE_MAX
)
9742 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
9747 /* Do not warn about redefinitions to the same alias. */
9748 if (new_type
!= old_type
9749 || (arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
)
9750 != arm_reg_parse (&q
, all_reg_maps
[new_type
].htab
)))
9751 as_warn (_("ignoring redefinition of register alias '%s'"),
9757 as_warn (_("ignoring incomplete .req pseuso op"));
9768 set_constant_flonums (void)
9772 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
9773 if (atof_ieee ((char *) fp_const
[i
], 'x', fp_values
[i
]) == NULL
)
9778 static const struct asm_opcode insns
[] =
9780 /* Core ARM Instructions. */
9781 {"and", 0xe0000000, 3, ARM_EXT_V1
, do_arit
},
9782 {"ands", 0xe0100000, 3, ARM_EXT_V1
, do_arit
},
9783 {"eor", 0xe0200000, 3, ARM_EXT_V1
, do_arit
},
9784 {"eors", 0xe0300000, 3, ARM_EXT_V1
, do_arit
},
9785 {"sub", 0xe0400000, 3, ARM_EXT_V1
, do_arit
},
9786 {"subs", 0xe0500000, 3, ARM_EXT_V1
, do_arit
},
9787 {"rsb", 0xe0600000, 3, ARM_EXT_V1
, do_arit
},
9788 {"rsbs", 0xe0700000, 3, ARM_EXT_V1
, do_arit
},
9789 {"add", 0xe0800000, 3, ARM_EXT_V1
, do_arit
},
9790 {"adds", 0xe0900000, 3, ARM_EXT_V1
, do_arit
},
9791 {"adc", 0xe0a00000, 3, ARM_EXT_V1
, do_arit
},
9792 {"adcs", 0xe0b00000, 3, ARM_EXT_V1
, do_arit
},
9793 {"sbc", 0xe0c00000, 3, ARM_EXT_V1
, do_arit
},
9794 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1
, do_arit
},
9795 {"rsc", 0xe0e00000, 3, ARM_EXT_V1
, do_arit
},
9796 {"rscs", 0xe0f00000, 3, ARM_EXT_V1
, do_arit
},
9797 {"orr", 0xe1800000, 3, ARM_EXT_V1
, do_arit
},
9798 {"orrs", 0xe1900000, 3, ARM_EXT_V1
, do_arit
},
9799 {"bic", 0xe1c00000, 3, ARM_EXT_V1
, do_arit
},
9800 {"bics", 0xe1d00000, 3, ARM_EXT_V1
, do_arit
},
9802 {"tst", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
9803 {"tsts", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
9804 {"tstp", 0xe110f000, 3, ARM_EXT_V1
, do_cmp
},
9805 {"teq", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
9806 {"teqs", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
9807 {"teqp", 0xe130f000, 3, ARM_EXT_V1
, do_cmp
},
9808 {"cmp", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
9809 {"cmps", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
9810 {"cmpp", 0xe150f000, 3, ARM_EXT_V1
, do_cmp
},
9811 {"cmn", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
9812 {"cmns", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
9813 {"cmnp", 0xe170f000, 3, ARM_EXT_V1
, do_cmp
},
9815 {"mov", 0xe1a00000, 3, ARM_EXT_V1
, do_mov
},
9816 {"movs", 0xe1b00000, 3, ARM_EXT_V1
, do_mov
},
9817 {"mvn", 0xe1e00000, 3, ARM_EXT_V1
, do_mov
},
9818 {"mvns", 0xe1f00000, 3, ARM_EXT_V1
, do_mov
},
9820 {"ldr", 0xe4100000, 3, ARM_EXT_V1
, do_ldst
},
9821 {"ldrb", 0xe4500000, 3, ARM_EXT_V1
, do_ldst
},
9822 {"ldrt", 0xe4300000, 3, ARM_EXT_V1
, do_ldstt
},
9823 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1
, do_ldstt
},
9824 {"str", 0xe4000000, 3, ARM_EXT_V1
, do_ldst
},
9825 {"strb", 0xe4400000, 3, ARM_EXT_V1
, do_ldst
},
9826 {"strt", 0xe4200000, 3, ARM_EXT_V1
, do_ldstt
},
9827 {"strbt", 0xe4600000, 3, ARM_EXT_V1
, do_ldstt
},
9829 {"stmia", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
9830 {"stmib", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
9831 {"stmda", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
9832 {"stmdb", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
9833 {"stmfd", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
9834 {"stmfa", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
9835 {"stmea", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
9836 {"stmed", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
9838 {"ldmia", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
9839 {"ldmib", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
9840 {"ldmda", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
9841 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
9842 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
9843 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
9844 {"ldmea", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
9845 {"ldmed", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
9847 {"swi", 0xef000000, 3, ARM_EXT_V1
, do_swi
},
9849 /* XXX This is the wrong place to do this. Think multi-arch. */
9850 {"bl", 0xeb000000, 2, ARM_EXT_V1
, do_branch
},
9851 {"b", 0xea000000, 1, ARM_EXT_V1
, do_branch
},
9853 {"bl", 0xebfffffe, 2, ARM_EXT_V1
, do_branch
},
9854 {"b", 0xeafffffe, 1, ARM_EXT_V1
, do_branch
},
9858 {"adr", 0xe28f0000, 3, ARM_EXT_V1
, do_adr
},
9859 {"adrl", 0xe28f0000, 3, ARM_EXT_V1
, do_adrl
},
9860 {"nop", 0xe1a00000, 3, ARM_EXT_V1
, do_nop
},
9862 /* ARM 2 multiplies. */
9863 {"mul", 0xe0000090, 3, ARM_EXT_V2
, do_mul
},
9864 {"muls", 0xe0100090, 3, ARM_EXT_V2
, do_mul
},
9865 {"mla", 0xe0200090, 3, ARM_EXT_V2
, do_mla
},
9866 {"mlas", 0xe0300090, 3, ARM_EXT_V2
, do_mla
},
9868 /* Generic coprocessor instructions. */
9869 {"cdp", 0xee000000, 3, ARM_EXT_V2
, do_cdp
},
9870 {"ldc", 0xec100000, 3, ARM_EXT_V2
, do_lstc
},
9871 {"ldcl", 0xec500000, 3, ARM_EXT_V2
, do_lstc
},
9872 {"stc", 0xec000000, 3, ARM_EXT_V2
, do_lstc
},
9873 {"stcl", 0xec400000, 3, ARM_EXT_V2
, do_lstc
},
9874 {"mcr", 0xee000010, 3, ARM_EXT_V2
, do_co_reg
},
9875 {"mrc", 0xee100010, 3, ARM_EXT_V2
, do_co_reg
},
9877 /* ARM 3 - swp instructions. */
9878 {"swp", 0xe1000090, 3, ARM_EXT_V2S
, do_swap
},
9879 {"swpb", 0xe1400090, 3, ARM_EXT_V2S
, do_swap
},
9881 /* ARM 6 Status register instructions. */
9882 {"mrs", 0xe10f0000, 3, ARM_EXT_V3
, do_mrs
},
9883 {"msr", 0xe120f000, 3, ARM_EXT_V3
, do_msr
},
9884 /* ScottB: our code uses 0xe128f000 for msr.
9885 NickC: but this is wrong because the bits 16 through 19 are
9886 handled by the PSR_xxx defines above. */
9888 /* ARM 7M long multiplies. */
9889 {"smull", 0xe0c00090, 5, ARM_EXT_V3M
, do_mull
},
9890 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M
, do_mull
},
9891 {"umull", 0xe0800090, 5, ARM_EXT_V3M
, do_mull
},
9892 {"umulls", 0xe0900090, 5, ARM_EXT_V3M
, do_mull
},
9893 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M
, do_mull
},
9894 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M
, do_mull
},
9895 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M
, do_mull
},
9896 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M
, do_mull
},
9898 /* ARM Architecture 4. */
9899 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4
, do_ldstv4
},
9900 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4
, do_ldstv4
},
9901 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4
, do_ldstv4
},
9902 {"strh", 0xe00000b0, 3, ARM_EXT_V4
, do_ldstv4
},
9904 /* ARM Architecture 4T. */
9905 /* Note: bx (and blx) are required on V5, even if the processor does
9906 not support Thumb. */
9907 {"bx", 0xe12fff10, 2, ARM_EXT_V4T
| ARM_EXT_V5
, do_bx
},
9909 /* ARM Architecture 5T. */
9910 /* Note: blx has 2 variants, so the .value is set dynamically.
9911 Only one of the variants has conditional execution. */
9912 {"blx", 0xe0000000, 3, ARM_EXT_V5
, do_blx
},
9913 {"clz", 0xe16f0f10, 3, ARM_EXT_V5
, do_clz
},
9914 {"bkpt", 0xe1200070, 0, ARM_EXT_V5
, do_bkpt
},
9915 {"ldc2", 0xfc100000, 0, ARM_EXT_V5
, do_lstc2
},
9916 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5
, do_lstc2
},
9917 {"stc2", 0xfc000000, 0, ARM_EXT_V5
, do_lstc2
},
9918 {"stc2l", 0xfc400000, 0, ARM_EXT_V5
, do_lstc2
},
9919 {"cdp2", 0xfe000000, 0, ARM_EXT_V5
, do_cdp2
},
9920 {"mcr2", 0xfe000010, 0, ARM_EXT_V5
, do_co_reg2
},
9921 {"mrc2", 0xfe100010, 0, ARM_EXT_V5
, do_co_reg2
},
9923 /* ARM Architecture 5TExP. */
9924 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP
, do_smla
},
9925 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP
, do_smla
},
9926 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP
, do_smla
},
9927 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP
, do_smla
},
9929 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP
, do_smla
},
9930 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP
, do_smla
},
9932 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP
, do_smlal
},
9933 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP
, do_smlal
},
9934 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP
, do_smlal
},
9935 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP
, do_smlal
},
9937 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP
, do_smul
},
9938 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP
, do_smul
},
9939 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP
, do_smul
},
9940 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP
, do_smul
},
9942 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP
, do_smul
},
9943 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP
, do_smul
},
9945 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP
, do_qadd
},
9946 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP
, do_qadd
},
9947 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP
, do_qadd
},
9948 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP
, do_qadd
},
9950 /* ARM Architecture 5TE. */
9951 {"pld", 0xf450f000, 0, ARM_EXT_V5E
, do_pld
},
9952 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E
, do_ldrd
},
9953 {"strd", 0xe00000f0, 3, ARM_EXT_V5E
, do_ldrd
},
9955 {"mcrr", 0xec400000, 4, ARM_EXT_V5E
, do_co_reg2c
},
9956 {"mrrc", 0xec500000, 4, ARM_EXT_V5E
, do_co_reg2c
},
9958 /* ARM Architecture 5TEJ. */
9959 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J
, do_bxj
},
9962 { "cps", 0xf1020000, 0, ARM_EXT_V6
, do_cps
},
9963 { "cpsie", 0xf1080000, 0, ARM_EXT_V6
, do_cpsi
},
9964 { "cpsid", 0xf10C0000, 0, ARM_EXT_V6
, do_cpsi
},
9965 { "ldrex", 0xe1900f9f, 5, ARM_EXT_V6
, do_ldrex
},
9966 { "mcrr2", 0xfc400000, 0, ARM_EXT_V6
, do_co_reg2c
},
9967 { "mrrc2", 0xfc500000, 0, ARM_EXT_V6
, do_co_reg2c
},
9968 { "pkhbt", 0xe6800010, 5, ARM_EXT_V6
, do_pkhbt
},
9969 { "pkhtb", 0xe6800050, 5, ARM_EXT_V6
, do_pkhtb
},
9970 { "qadd16", 0xe6200f10, 6, ARM_EXT_V6
, do_qadd16
},
9971 { "qadd8", 0xe6200f90, 5, ARM_EXT_V6
, do_qadd16
},
9972 { "qaddsubx", 0xe6200f30, 8, ARM_EXT_V6
, do_qadd16
},
9973 { "qsub16", 0xe6200f70, 6, ARM_EXT_V6
, do_qadd16
},
9974 { "qsub8", 0xe6200ff0, 5, ARM_EXT_V6
, do_qadd16
},
9975 { "qsubaddx", 0xe6200f50, 8, ARM_EXT_V6
, do_qadd16
},
9976 { "sadd16", 0xe6100f10, 6, ARM_EXT_V6
, do_qadd16
},
9977 { "sadd8", 0xe6100f90, 5, ARM_EXT_V6
, do_qadd16
},
9978 { "saddsubx", 0xe6100f30, 8, ARM_EXT_V6
, do_qadd16
},
9979 { "shadd16", 0xe6300f10, 7, ARM_EXT_V6
, do_qadd16
},
9980 { "shadd8", 0xe6300f90, 6, ARM_EXT_V6
, do_qadd16
},
9981 { "shaddsubx", 0xe6300f30, 9, ARM_EXT_V6
, do_qadd16
},
9982 { "shsub16", 0xe6300f70, 7, ARM_EXT_V6
, do_qadd16
},
9983 { "shsub8", 0xe6300ff0, 6, ARM_EXT_V6
, do_qadd16
},
9984 { "shsubaddx", 0xe6300f50, 9, ARM_EXT_V6
, do_qadd16
},
9985 { "ssub16", 0xe6100f70, 6, ARM_EXT_V6
, do_qadd16
},
9986 { "ssub8", 0xe6100ff0, 5, ARM_EXT_V6
, do_qadd16
},
9987 { "ssubaddx", 0xe6100f50, 8, ARM_EXT_V6
, do_qadd16
},
9988 { "uadd16", 0xe6500f10, 6, ARM_EXT_V6
, do_qadd16
},
9989 { "uadd8", 0xe6500f90, 5, ARM_EXT_V6
, do_qadd16
},
9990 { "uaddsubx", 0xe6500f30, 8, ARM_EXT_V6
, do_qadd16
},
9991 { "uhadd16", 0xe6700f10, 7, ARM_EXT_V6
, do_qadd16
},
9992 { "uhadd8", 0xe6700f90, 6, ARM_EXT_V6
, do_qadd16
},
9993 { "uhaddsubx", 0xe6700f30, 9, ARM_EXT_V6
, do_qadd16
},
9994 { "uhsub16", 0xe6700f70, 7, ARM_EXT_V6
, do_qadd16
},
9995 { "uhsub8", 0xe6700ff0, 6, ARM_EXT_V6
, do_qadd16
},
9996 { "uhsubaddx", 0xe6700f50, 9, ARM_EXT_V6
, do_qadd16
},
9997 { "uqadd16", 0xe6600f10, 7, ARM_EXT_V6
, do_qadd16
},
9998 { "uqadd8", 0xe6600f90, 6, ARM_EXT_V6
, do_qadd16
},
9999 { "uqaddsubx", 0xe6600f30, 9, ARM_EXT_V6
, do_qadd16
},
10000 { "uqsub16", 0xe6600f70, 7, ARM_EXT_V6
, do_qadd16
},
10001 { "uqsub8", 0xe6600ff0, 6, ARM_EXT_V6
, do_qadd16
},
10002 { "uqsubaddx", 0xe6600f50, 9, ARM_EXT_V6
, do_qadd16
},
10003 { "usub16", 0xe6500f70, 6, ARM_EXT_V6
, do_qadd16
},
10004 { "usub8", 0xe6500ff0, 5, ARM_EXT_V6
, do_qadd16
},
10005 { "usubaddx", 0xe6500f50, 8, ARM_EXT_V6
, do_qadd16
},
10006 { "rev", 0xe6bf0f30, 3, ARM_EXT_V6
, do_rev
},
10007 { "rev16", 0xe6bf0fb0, 5, ARM_EXT_V6
, do_rev
},
10008 { "revsh", 0xe6ff0fb0, 5, ARM_EXT_V6
, do_rev
},
10009 { "rfeia", 0xf8900a00, 0, ARM_EXT_V6
, do_rfe
},
10010 { "rfeib", 0xf9900a00, 0, ARM_EXT_V6
, do_rfe
},
10011 { "rfeda", 0xf8100a00, 0, ARM_EXT_V6
, do_rfe
},
10012 { "rfedb", 0xf9100a00, 0, ARM_EXT_V6
, do_rfe
},
10013 { "rfefd", 0xf8900a00, 0, ARM_EXT_V6
, do_rfe
},
10014 { "rfefa", 0xf9900a00, 0, ARM_EXT_V6
, do_rfe
},
10015 { "rfeea", 0xf8100a00, 0, ARM_EXT_V6
, do_rfe
},
10016 { "rfeed", 0xf9100a00, 0, ARM_EXT_V6
, do_rfe
},
10017 { "sxtah", 0xe6b00070, 5, ARM_EXT_V6
, do_sxtah
},
10018 { "sxtab16", 0xe6800070, 7, ARM_EXT_V6
, do_sxtah
},
10019 { "sxtab", 0xe6a00070, 5, ARM_EXT_V6
, do_sxtah
},
10020 { "sxth", 0xe6bf0070, 4, ARM_EXT_V6
, do_sxth
},
10021 { "sxtb16", 0xe68f0070, 6, ARM_EXT_V6
, do_sxth
},
10022 { "sxtb", 0xe6af0070, 4, ARM_EXT_V6
, do_sxth
},
10023 { "uxtah", 0xe6f00070, 5, ARM_EXT_V6
, do_sxtah
},
10024 { "uxtab16", 0xe6c00070, 7, ARM_EXT_V6
, do_sxtah
},
10025 { "uxtab", 0xe6e00070, 5, ARM_EXT_V6
, do_sxtah
},
10026 { "uxth", 0xe6ff0070, 4, ARM_EXT_V6
, do_sxth
},
10027 { "uxtb16", 0xe6cf0070, 6, ARM_EXT_V6
, do_sxth
},
10028 { "uxtb", 0xe6ef0070, 4, ARM_EXT_V6
, do_sxth
},
10029 { "sel", 0xe68000b0, 3, ARM_EXT_V6
, do_qadd16
},
10030 { "setend", 0xf1010000, 0, ARM_EXT_V6
, do_setend
},
10031 { "smlad", 0xe7000010, 5, ARM_EXT_V6
, do_smlad
},
10032 { "smladx", 0xe7000030, 6, ARM_EXT_V6
, do_smlad
},
10033 { "smlald", 0xe7400010, 6, ARM_EXT_V6
, do_smlald
},
10034 { "smlaldx", 0xe7400030, 7, ARM_EXT_V6
, do_smlald
},
10035 { "smlsd", 0xe7000050, 5, ARM_EXT_V6
, do_smlad
},
10036 { "smlsdx", 0xe7000070, 6, ARM_EXT_V6
, do_smlad
},
10037 { "smlsld", 0xe7400050, 6, ARM_EXT_V6
, do_smlald
},
10038 { "smlsldx", 0xe7400070, 7, ARM_EXT_V6
, do_smlald
},
10039 { "smmla", 0xe7500010, 5, ARM_EXT_V6
, do_smlad
},
10040 { "smmlar", 0xe7500030, 6, ARM_EXT_V6
, do_smlad
},
10041 { "smmls", 0xe75000d0, 5, ARM_EXT_V6
, do_smlad
},
10042 { "smmlsr", 0xe75000f0, 6, ARM_EXT_V6
, do_smlad
},
10043 { "smmul", 0xe750f010, 5, ARM_EXT_V6
, do_smmul
},
10044 { "smmulr", 0xe750f030, 6, ARM_EXT_V6
, do_smmul
},
10045 { "smuad", 0xe700f010, 5, ARM_EXT_V6
, do_smmul
},
10046 { "smuadx", 0xe700f030, 6, ARM_EXT_V6
, do_smmul
},
10047 { "smusd", 0xe700f050, 5, ARM_EXT_V6
, do_smmul
},
10048 { "smusdx", 0xe700f070, 6, ARM_EXT_V6
, do_smmul
},
10049 { "srsia", 0xf8cd0500, 0, ARM_EXT_V6
, do_srs
},
10050 { "srsib", 0xf9cd0500, 0, ARM_EXT_V6
, do_srs
},
10051 { "srsda", 0xf84d0500, 0, ARM_EXT_V6
, do_srs
},
10052 { "srsdb", 0xf94d0500, 0, ARM_EXT_V6
, do_srs
},
10053 { "ssat", 0xe6a00010, 4, ARM_EXT_V6
, do_ssat
},
10054 { "ssat16", 0xe6a00f30, 6, ARM_EXT_V6
, do_ssat16
},
10055 { "strex", 0xe1800f90, 5, ARM_EXT_V6
, do_strex
},
10056 { "umaal", 0xe0400090, 5, ARM_EXT_V6
, do_umaal
},
10057 { "usad8", 0xe780f010, 5, ARM_EXT_V6
, do_smmul
},
10058 { "usada8", 0xe7800010, 6, ARM_EXT_V6
, do_smlad
},
10059 { "usat", 0xe6e00010, 4, ARM_EXT_V6
, do_usat
},
10060 { "usat16", 0xe6e00f30, 6, ARM_EXT_V6
, do_usat16
},
10063 { "clrex", 0xf57ff01f, 0, ARM_EXT_V6K
, do_empty
},
10064 { "ldrexb", 0xe1d00f9f, 6, ARM_EXT_V6K
, do_ldrex
},
10065 { "ldrexd", 0xe1b00f9f, 6, ARM_EXT_V6K
, do_ldrex
},
10066 { "ldrexh", 0xe1f00f9f, 6, ARM_EXT_V6K
, do_ldrex
},
10067 { "sev", 0xe320f004, 3, ARM_EXT_V6K
, do_empty
},
10068 { "strexb", 0xe1c00f90, 6, ARM_EXT_V6K
, do_strex
},
10069 { "strexd", 0xe1a00f90, 6, ARM_EXT_V6K
, do_strex
},
10070 { "strexh", 0xe1e00f90, 6, ARM_EXT_V6K
, do_strex
},
10071 { "wfe", 0xe320f002, 3, ARM_EXT_V6K
, do_empty
},
10072 { "wfi", 0xe320f003, 3, ARM_EXT_V6K
, do_empty
},
10073 { "yield", 0xe320f001, 5, ARM_EXT_V6K
, do_empty
},
10076 { "smi", 0xe1600070, 3, ARM_EXT_V6Z
, do_smi
},
10078 /* Core FPA instruction set (V1). */
10079 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
10080 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
10081 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
10082 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
10084 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10085 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10086 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10087 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10089 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10090 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10091 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10092 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10094 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10095 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10096 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10097 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10098 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10099 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10100 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10101 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10102 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10103 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10104 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10105 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10107 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10108 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10109 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10110 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10111 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10112 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10113 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10114 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10115 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10116 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10117 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10118 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10120 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10121 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10122 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10123 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10124 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10125 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10126 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10127 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10128 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10129 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10130 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10131 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10133 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10134 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10135 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10136 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10137 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10138 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10139 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10140 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10141 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10142 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10143 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10144 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10146 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10147 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10148 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10149 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10150 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10151 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10152 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10153 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10154 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10155 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10156 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10157 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10159 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10160 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10161 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10162 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10163 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10164 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10165 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10166 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10167 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10168 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10169 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10170 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10172 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10173 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10174 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10175 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10176 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10177 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10178 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10179 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10180 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10181 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10182 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10183 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10185 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10186 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10187 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10188 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10189 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10190 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10191 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10192 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10193 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10194 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10195 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10196 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10198 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10199 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10200 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10201 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10202 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10203 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10204 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10205 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10206 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10207 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10208 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10209 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10211 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10212 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10213 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10214 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10215 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10216 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10217 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10218 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10219 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10220 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10221 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10222 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10224 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10225 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10226 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10227 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10228 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10229 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10230 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10231 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10232 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10233 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10234 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10235 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10237 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10238 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10239 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10240 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10241 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10242 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10243 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10244 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10245 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10246 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10247 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10248 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10250 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10251 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10252 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10253 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10254 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10255 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10256 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10257 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10258 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10259 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10260 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10261 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10263 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10264 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10265 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10266 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10267 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10268 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10269 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10270 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10271 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10272 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10273 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10274 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10276 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10277 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10278 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10279 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10280 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10281 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10282 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10283 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10284 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10285 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10286 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10287 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10289 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10290 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10291 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10292 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10293 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10294 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10295 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10296 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10297 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10298 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10299 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10300 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10302 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10303 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10304 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10305 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10306 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10307 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10308 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10309 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10310 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10311 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10312 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10313 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10315 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10316 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10317 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10318 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10319 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10320 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10321 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10322 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10323 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10324 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10325 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10326 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10328 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10329 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10330 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10331 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10332 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10333 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10334 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10335 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10336 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10337 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10338 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10339 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10341 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10342 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10343 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10344 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10345 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10346 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10347 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10348 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10349 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10350 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10351 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10352 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10354 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10355 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10356 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10357 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10358 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10359 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10360 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10361 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10362 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10363 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10364 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10365 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10367 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10368 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10369 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10370 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10371 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10372 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10373 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10374 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10375 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10376 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10377 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10378 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10380 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10381 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10382 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10383 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10384 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10385 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10386 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10387 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10388 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10389 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10390 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10391 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10393 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10394 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10395 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10396 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10397 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10398 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10399 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10400 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10401 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10402 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10403 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10404 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10406 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10407 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10408 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10409 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10410 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10411 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10412 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10413 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10414 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10415 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10416 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10417 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10419 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10420 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10421 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10422 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10423 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10424 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10425 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10426 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10427 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10428 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10429 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10430 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10432 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10433 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10434 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10435 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10436 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10437 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10438 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10439 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10440 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10441 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10442 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10443 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10445 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10446 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10447 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10448 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10449 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10450 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10451 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10452 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10453 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10454 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10455 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10456 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10458 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10459 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10460 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10461 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10462 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10463 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10464 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10465 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10466 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10467 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10468 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10469 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10471 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10472 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10473 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10474 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10475 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
10476 not be an optional suffix, but part of the instruction. To be
10477 compatible, we accept either. */
10478 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10479 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10481 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10482 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10483 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10484 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10485 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10486 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10487 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10488 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10489 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10490 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10491 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10492 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10494 /* The implementation of the FIX instruction is broken on some
10495 assemblers, in that it accepts a precision specifier as well as a
10496 rounding specifier, despite the fact that this is meaningless.
10497 To be more compatible, we accept it as well, though of course it
10498 does not set any bits. */
10499 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10500 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10501 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10502 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10503 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10504 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10505 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10506 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10507 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10508 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10509 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10510 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10511 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10513 /* Instructions that were new with the real FPA, call them V2. */
10514 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10515 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10516 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10517 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10518 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10519 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10521 /* VFP V1xD (single precision). */
10522 /* Moves and type conversions. */
10523 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10524 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_reg_from_sp
},
10525 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_from_reg
},
10526 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD
, do_empty
},
10527 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10528 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10529 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10530 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10531 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10532 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10533 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_reg_from_ctrl
},
10534 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_ctrl_from_reg
},
10536 /* Memory operations. */
10537 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldst
},
10538 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldst
},
10539 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
10540 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
10541 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
10542 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
10543 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
10544 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
10545 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
10546 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
10547 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
10548 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
10549 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
10550 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
10551 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
10552 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
10553 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
10554 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
10556 /* Monadic operations. */
10557 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10558 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10559 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10561 /* Dyadic operations. */
10562 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10563 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10564 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10565 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10566 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10567 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10568 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10569 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10570 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10573 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10574 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_compare_z
},
10575 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10576 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_compare_z
},
10578 /* VFP V1 (Double precision). */
10579 /* Moves and type conversions. */
10580 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10581 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
10582 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10583 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1
, do_vfp_dp_from_reg
},
10584 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1
, do_vfp_dp_from_reg
},
10585 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1
, do_vfp_reg_from_dp
},
10586 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1
, do_vfp_reg_from_dp
},
10587 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
10588 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
10589 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10590 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10591 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10592 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10594 /* Memory operations. */
10595 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1
, do_vfp_dp_ldst
},
10596 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1
, do_vfp_dp_ldst
},
10597 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
10598 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
10599 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
10600 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
10601 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
10602 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
10603 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
10604 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
10606 /* Monadic operations. */
10607 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10608 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10609 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10611 /* Dyadic operations. */
10612 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10613 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10614 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10615 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10616 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10617 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10618 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10619 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10620 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10623 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10624 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_compare_z
},
10625 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10626 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1
, do_vfp_dp_compare_z
},
10629 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2
, do_vfp_sp2_from_reg2
},
10630 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2
, do_vfp_reg2_from_sp2
},
10631 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2
, do_vfp_dp_from_reg2
},
10632 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2
, do_vfp_reg2_from_dp
},
10634 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
10635 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE
, do_xsc_mia
},
10636 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10637 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10638 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10639 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10640 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10641 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE
, do_xsc_mar
},
10642 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE
, do_xsc_mra
},
10644 /* Intel Wireless MMX technology instructions. */
10645 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
10646 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
10647 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
10648 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
10649 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
10650 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
10651 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
10652 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
10653 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
10654 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10655 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10656 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10657 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10658 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10659 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10660 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
10661 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
10662 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
10663 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmcr
},
10664 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_tmcrr
},
10665 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10666 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10667 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10668 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10669 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10670 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10671 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
10672 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
10673 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
10674 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmrc
},
10675 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_tmrrc
},
10676 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
10677 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
10678 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
10679 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10680 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10681 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10682 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10683 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10684 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10685 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10686 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10687 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10688 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10689 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10690 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10691 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_waligni
},
10692 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10693 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10694 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10695 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10696 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10697 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10698 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10699 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10700 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10701 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10702 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10703 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10704 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10705 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10706 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10707 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10708 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10709 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10710 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10711 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
10712 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
10713 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
10714 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
10715 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10716 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10717 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10718 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10719 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10720 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10721 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10722 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10723 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10724 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10725 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10726 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10727 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10728 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10729 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10730 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10731 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10732 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10733 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wmov
},
10734 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10735 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10736 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10737 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10738 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10739 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10740 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10741 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10742 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10743 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10744 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10745 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10746 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10747 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10748 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10749 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10750 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10751 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10752 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10753 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10754 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10755 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wshufh
},
10756 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10757 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10758 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10759 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10760 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10761 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10762 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10763 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10764 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10765 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10766 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10767 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10768 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10769 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10770 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10771 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10772 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10773 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10774 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
10775 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
10776 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
10777 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
10778 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10779 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10780 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10781 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10782 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10783 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10784 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10785 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10786 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10787 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10788 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10789 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10790 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10791 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10792 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10793 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10794 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10795 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10796 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10797 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10798 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10799 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10800 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10801 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10802 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10803 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10804 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10805 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10806 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wzero
},
10808 /* Cirrus Maverick instructions. */
10809 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_1
},
10810 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_2
},
10811 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_3
},
10812 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_4
},
10813 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_1
},
10814 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_2
},
10815 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_3
},
10816 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_4
},
10817 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK
, do_mav_binops_2a
},
10818 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1a
},
10819 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK
, do_mav_binops_2b
},
10820 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1b
},
10821 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK
, do_mav_binops_2b
},
10822 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1b
},
10823 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK
, do_mav_binops_2c
},
10824 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1c
},
10825 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK
, do_mav_binops_2c
},
10826 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1c
},
10827 {"cfmval32", 0xee200440, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
10828 {"cfmv32al", 0xee100440, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
10829 {"cfmvam32", 0xee200460, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
10830 {"cfmv32am", 0xee100460, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
10831 {"cfmvah32", 0xee200480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
10832 {"cfmv32ah", 0xee100480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
10833 {"cfmva32", 0xee2004a0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
10834 {"cfmv32a", 0xee1004a0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
10835 {"cfmva64", 0xee2004c0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3c
},
10836 {"cfmv64a", 0xee1004c0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3d
},
10837 {"cfmvsc32", 0xee2004e0, 8, ARM_CEXT_MAVERICK
, do_mav_dspsc_1
},
10838 {"cfmv32sc", 0xee1004e0, 8, ARM_CEXT_MAVERICK
, do_mav_dspsc_2
},
10839 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
10840 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
10841 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1f
},
10842 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1g
},
10843 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1h
},
10844 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1i
},
10845 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1j
},
10846 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1k
},
10847 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1l
},
10848 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1m
},
10849 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK
, do_mav_binops_1l
},
10850 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK
, do_mav_binops_1m
},
10851 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK
, do_mav_triple_4a
},
10852 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK
, do_mav_triple_4b
},
10853 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK
, do_mav_shift_1
},
10854 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK
, do_mav_shift_2
},
10855 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5a
},
10856 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5b
},
10857 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5c
},
10858 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5d
},
10859 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
10860 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
10861 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
10862 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
10863 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
10864 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
10865 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
10866 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
10867 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
10868 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
10869 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1n
},
10870 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1o
},
10871 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1n
},
10872 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1o
},
10873 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
10874 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
10875 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
10876 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
10877 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
10878 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
10879 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
10880 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
10881 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK
, do_mav_quad_6a
},
10882 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK
, do_mav_quad_6a
},
10883 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK
, do_mav_quad_6b
},
10884 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK
, do_mav_quad_6b
},
10887 /* Iterate over the base tables to create the instruction patterns. */
10890 build_arm_ops_hsh (void)
10894 static struct obstack insn_obstack
;
10896 obstack_begin (&insn_obstack
, 4000);
10898 for (i
= 0; i
< sizeof (insns
) / sizeof (struct asm_opcode
); i
++)
10900 const struct asm_opcode
*insn
= insns
+ i
;
10902 if (insn
->cond_offset
!= 0)
10904 /* Insn supports conditional execution. Build the varaints
10905 and insert them in the hash table. */
10906 for (j
= 0; j
< sizeof (conds
) / sizeof (struct asm_cond
); j
++)
10908 unsigned len
= strlen (insn
->template);
10909 struct asm_opcode
*new;
10912 new = obstack_alloc (&insn_obstack
, sizeof (struct asm_opcode
));
10913 /* All condition codes are two characters. */
10914 template = obstack_alloc (&insn_obstack
, len
+ 3);
10916 strncpy (template, insn
->template, insn
->cond_offset
);
10917 strcpy (template + insn
->cond_offset
, conds
[j
].template);
10918 if (len
> insn
->cond_offset
)
10919 strcpy (template + insn
->cond_offset
+ 2,
10920 insn
->template + insn
->cond_offset
);
10921 new->template = template;
10922 new->cond_offset
= 0;
10923 new->variant
= insn
->variant
;
10924 new->parms
= insn
->parms
;
10925 new->value
= (insn
->value
& ~COND_MASK
) | conds
[j
].value
;
10927 hash_insert (arm_ops_hsh
, new->template, (PTR
) new);
10930 /* Finally, insert the unconditional insn in the table directly;
10931 no need to build a copy. */
10932 hash_insert (arm_ops_hsh
, insn
->template, (PTR
) insn
);
10936 #if 0 /* Suppressed - for now. */
10937 #if defined OBJ_ELF || defined OBJ_COFF
10940 #define arm_Note Elf_External_Note
10944 unsigned char namesz
[4]; /* Size of entry's owner string. */
10945 unsigned char descsz
[4]; /* Size of the note descriptor. */
10946 unsigned char type
[4]; /* Interpretation of the descriptor. */
10947 char name
[1]; /* Start of the name+desc data. */
10951 /* The description is kept to a fix sized in order to make updating
10952 it and merging it easier. */
10953 #define ARM_NOTE_DESCRIPTION_LENGTH 8
10956 arm_add_note (const char * name
,
10957 const char * description
,
10960 arm_Note note ATTRIBUTE_UNUSED
;
10962 unsigned int name_len
;
10964 name_len
= (strlen (name
) + 1 + 3) & ~3;
10966 p
= frag_more (sizeof (note
.namesz
));
10967 md_number_to_chars (p
, (valueT
) name_len
, sizeof (note
.namesz
));
10969 p
= frag_more (sizeof (note
.descsz
));
10970 md_number_to_chars (p
, (valueT
) ARM_NOTE_DESCRIPTION_LENGTH
, sizeof (note
.descsz
));
10972 p
= frag_more (sizeof (note
.type
));
10973 md_number_to_chars (p
, (valueT
) type
, sizeof (note
.type
));
10975 p
= frag_more (name_len
);
10978 p
= frag_more (ARM_NOTE_DESCRIPTION_LENGTH
);
10979 strncpy (p
, description
, ARM_NOTE_DESCRIPTION_LENGTH
);
10980 frag_align (2, 0, 0);
10986 static const struct thumb_opcode tinsns
[] =
10988 /* Thumb v1 (ARMv4T). */
10989 {"adc", 0x4140, 2, ARM_EXT_V4T
, do_t_arit
},
10990 {"add", 0x0000, 2, ARM_EXT_V4T
, do_t_add
},
10991 {"and", 0x4000, 2, ARM_EXT_V4T
, do_t_arit
},
10992 {"asr", 0x0000, 2, ARM_EXT_V4T
, do_t_asr
},
10993 {"b", T_OPCODE_BRANCH
, 2, ARM_EXT_V4T
, do_t_branch12
},
10994 {"beq", 0xd0fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10995 {"bne", 0xd1fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10996 {"bcs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10997 {"bhs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10998 {"bcc", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10999 {"bul", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11000 {"blo", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11001 {"bmi", 0xd4fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11002 {"bpl", 0xd5fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11003 {"bvs", 0xd6fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11004 {"bvc", 0xd7fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11005 {"bhi", 0xd8fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11006 {"bls", 0xd9fe, 2, ARM_EXT_V4T
, do_t_branch9
},
11007 {"bge", 0xdafe, 2, ARM_EXT_V4T
, do_t_branch9
},
11008 {"blt", 0xdbfe, 2, ARM_EXT_V4T
, do_t_branch9
},
11009 {"bgt", 0xdcfe, 2, ARM_EXT_V4T
, do_t_branch9
},
11010 {"ble", 0xddfe, 2, ARM_EXT_V4T
, do_t_branch9
},
11011 {"bal", 0xdefe, 2, ARM_EXT_V4T
, do_t_branch9
},
11012 {"bic", 0x4380, 2, ARM_EXT_V4T
, do_t_arit
},
11013 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T
, do_t_branch23
},
11014 {"bx", 0x4700, 2, ARM_EXT_V4T
, do_t_bx
},
11015 {"cmn", T_OPCODE_CMN
, 2, ARM_EXT_V4T
, do_t_arit
},
11016 {"cmp", 0x0000, 2, ARM_EXT_V4T
, do_t_compare
},
11017 {"eor", 0x4040, 2, ARM_EXT_V4T
, do_t_arit
},
11018 {"ldmia", 0xc800, 2, ARM_EXT_V4T
, do_t_ldmstm
},
11019 {"ldr", 0x0000, 2, ARM_EXT_V4T
, do_t_ldr
},
11020 {"ldrb", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrb
},
11021 {"ldrh", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrh
},
11022 {"ldrsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
11023 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
11024 {"ldsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
11025 {"ldsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
11026 {"lsl", 0x0000, 2, ARM_EXT_V4T
, do_t_lsl
},
11027 {"lsr", 0x0000, 2, ARM_EXT_V4T
, do_t_lsr
},
11028 {"mov", 0x0000, 2, ARM_EXT_V4T
, do_t_mov
},
11029 {"mul", T_OPCODE_MUL
, 2, ARM_EXT_V4T
, do_t_arit
},
11030 {"mvn", T_OPCODE_MVN
, 2, ARM_EXT_V4T
, do_t_arit
},
11031 {"neg", T_OPCODE_NEG
, 2, ARM_EXT_V4T
, do_t_arit
},
11032 {"orr", 0x4300, 2, ARM_EXT_V4T
, do_t_arit
},
11033 {"pop", 0xbc00, 2, ARM_EXT_V4T
, do_t_push_pop
},
11034 {"push", 0xb400, 2, ARM_EXT_V4T
, do_t_push_pop
},
11035 {"ror", 0x41c0, 2, ARM_EXT_V4T
, do_t_arit
},
11036 {"sbc", 0x4180, 2, ARM_EXT_V4T
, do_t_arit
},
11037 {"stmia", 0xc000, 2, ARM_EXT_V4T
, do_t_ldmstm
},
11038 {"str", 0x0000, 2, ARM_EXT_V4T
, do_t_str
},
11039 {"strb", 0x0000, 2, ARM_EXT_V4T
, do_t_strb
},
11040 {"strh", 0x0000, 2, ARM_EXT_V4T
, do_t_strh
},
11041 {"swi", 0xdf00, 2, ARM_EXT_V4T
, do_t_swi
},
11042 {"sub", 0x0000, 2, ARM_EXT_V4T
, do_t_sub
},
11043 {"tst", T_OPCODE_TST
, 2, ARM_EXT_V4T
, do_t_arit
},
11045 {"adr", 0x0000, 2, ARM_EXT_V4T
, do_t_adr
},
11046 {"nop", 0x46C0, 2, ARM_EXT_V4T
, do_t_nop
}, /* mov r8,r8 */
11047 /* Thumb v2 (ARMv5T). */
11048 {"blx", 0, 0, ARM_EXT_V5T
, do_t_blx
},
11049 {"bkpt", 0xbe00, 2, ARM_EXT_V5T
, do_t_bkpt
},
11052 {"cpsie", 0xb660, 2, ARM_EXT_V6
, do_t_cps
},
11053 {"cpsid", 0xb670, 2, ARM_EXT_V6
, do_t_cps
},
11054 {"cpy", 0x4600, 2, ARM_EXT_V6
, do_t_cpy
},
11055 {"rev", 0xba00, 2, ARM_EXT_V6
, do_t_arit
},
11056 {"rev16", 0xba40, 2, ARM_EXT_V6
, do_t_arit
},
11057 {"revsh", 0xbac0, 2, ARM_EXT_V6
, do_t_arit
},
11058 {"setend", 0xb650, 2, ARM_EXT_V6
, do_t_setend
},
11059 {"sxth", 0xb200, 2, ARM_EXT_V6
, do_t_arit
},
11060 {"sxtb", 0xb240, 2, ARM_EXT_V6
, do_t_arit
},
11061 {"uxth", 0xb280, 2, ARM_EXT_V6
, do_t_arit
},
11062 {"uxtb", 0xb2c0, 2, ARM_EXT_V6
, do_t_arit
},
11071 if ( (arm_ops_hsh
= hash_new ()) == NULL
11072 || (arm_tops_hsh
= hash_new ()) == NULL
11073 || (arm_cond_hsh
= hash_new ()) == NULL
11074 || (arm_shift_hsh
= hash_new ()) == NULL
11075 || (arm_psr_hsh
= hash_new ()) == NULL
)
11076 as_fatal (_("virtual memory exhausted"));
11078 build_arm_ops_hsh ();
11079 for (i
= 0; i
< sizeof (tinsns
) / sizeof (struct thumb_opcode
); i
++)
11080 hash_insert (arm_tops_hsh
, tinsns
[i
].template, (PTR
) (tinsns
+ i
));
11081 for (i
= 0; i
< sizeof (conds
) / sizeof (struct asm_cond
); i
++)
11082 hash_insert (arm_cond_hsh
, conds
[i
].template, (PTR
) (conds
+ i
));
11083 for (i
= 0; i
< sizeof (shift_names
) / sizeof (struct asm_shift_name
); i
++)
11084 hash_insert (arm_shift_hsh
, shift_names
[i
].name
, (PTR
) (shift_names
+ i
));
11085 for (i
= 0; i
< sizeof (psrs
) / sizeof (struct asm_psr
); i
++)
11086 hash_insert (arm_psr_hsh
, psrs
[i
].template, (PTR
) (psrs
+ i
));
11088 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
11089 build_reg_hsh (all_reg_maps
+ i
);
11091 set_constant_flonums ();
11093 /* Set the cpu variant based on the command-line options. We prefer
11094 -mcpu= over -march= if both are set (as for GCC); and we prefer
11095 -mfpu= over any other way of setting the floating point unit.
11096 Use of legacy options with new options are faulted. */
11097 if (legacy_cpu
!= -1)
11099 if (mcpu_cpu_opt
!= -1 || march_cpu_opt
!= -1)
11100 as_bad (_("use of old and new-style options to set CPU type"));
11102 mcpu_cpu_opt
= legacy_cpu
;
11104 else if (mcpu_cpu_opt
== -1)
11105 mcpu_cpu_opt
= march_cpu_opt
;
11107 if (legacy_fpu
!= -1)
11109 if (mfpu_opt
!= -1)
11110 as_bad (_("use of old and new-style options to set FPU type"));
11112 mfpu_opt
= legacy_fpu
;
11114 else if (mfpu_opt
== -1)
11116 #if !(defined (TE_LINUX) || defined (TE_NetBSD))
11117 /* Some environments specify a default FPU. If they don't, infer it
11118 from the processor. */
11119 if (mcpu_fpu_opt
!= -1)
11120 mfpu_opt
= mcpu_fpu_opt
;
11122 mfpu_opt
= march_fpu_opt
;
11124 mfpu_opt
= FPU_DEFAULT
;
11128 if (mfpu_opt
== -1)
11130 if (mcpu_cpu_opt
== -1)
11131 mfpu_opt
= FPU_DEFAULT
;
11132 else if (mcpu_cpu_opt
& ARM_EXT_V5
)
11133 mfpu_opt
= FPU_ARCH_VFP_V2
;
11135 mfpu_opt
= FPU_ARCH_FPA
;
11138 if (mcpu_cpu_opt
== -1)
11139 mcpu_cpu_opt
= CPU_DEFAULT
;
11141 cpu_variant
= mcpu_cpu_opt
| mfpu_opt
;
11144 unsigned int flags
= 0;
11146 #if defined OBJ_ELF
11147 flags
= meabi_flags
;
11149 switch (meabi_flags
)
11151 case EF_ARM_EABI_UNKNOWN
:
11153 #if defined OBJ_COFF || defined OBJ_ELF
11154 /* Set the flags in the private structure. */
11155 if (uses_apcs_26
) flags
|= F_APCS26
;
11156 if (support_interwork
) flags
|= F_INTERWORK
;
11157 if (uses_apcs_float
) flags
|= F_APCS_FLOAT
;
11158 if (pic_code
) flags
|= F_PIC
;
11159 if ((cpu_variant
& FPU_ANY
) == FPU_NONE
11160 || (cpu_variant
& FPU_ANY
) == FPU_ARCH_VFP
) /* VFP layout only. */
11161 flags
|= F_SOFT_FLOAT
;
11163 switch (mfloat_abi_opt
)
11165 case ARM_FLOAT_ABI_SOFT
:
11166 case ARM_FLOAT_ABI_SOFTFP
:
11167 flags
|= F_SOFT_FLOAT
;
11170 case ARM_FLOAT_ABI_HARD
:
11171 if (flags
& F_SOFT_FLOAT
)
11172 as_bad (_("hard-float conflicts with specified fpu"));
11176 /* Using VFP conventions (even if soft-float). */
11177 if (cpu_variant
& FPU_VFP_EXT_NONE
)
11178 flags
|= F_VFP_FLOAT
;
11180 #if defined OBJ_ELF
11181 if (cpu_variant
& FPU_ARCH_MAVERICK
)
11182 flags
|= EF_ARM_MAVERICK_FLOAT
;
11185 case EF_ARM_EABI_VER3
:
11186 /* No additional flags to set. */
11193 #if defined OBJ_COFF || defined OBJ_ELF
11194 bfd_set_private_flags (stdoutput
, flags
);
11196 /* We have run out flags in the COFF header to encode the
11197 status of ATPCS support, so instead we create a dummy,
11198 empty, debug section called .arm.atpcs. */
11203 sec
= bfd_make_section (stdoutput
, ".arm.atpcs");
11207 bfd_set_section_flags
11208 (stdoutput
, sec
, SEC_READONLY
| SEC_DEBUGGING
/* | SEC_HAS_CONTENTS */);
11209 bfd_set_section_size (stdoutput
, sec
, 0);
11210 bfd_set_section_contents (stdoutput
, sec
, NULL
, 0, 0);
11216 /* Record the CPU type as well. */
11217 switch (cpu_variant
& ARM_CPU_MASK
)
11220 mach
= bfd_mach_arm_2
;
11223 case ARM_3
: /* Also ARM_250. */
11224 mach
= bfd_mach_arm_2a
;
11227 case ARM_6
: /* Also ARM_7. */
11228 mach
= bfd_mach_arm_3
;
11232 mach
= bfd_mach_arm_unknown
;
11236 /* Catch special cases. */
11237 if (cpu_variant
& ARM_CEXT_IWMMXT
)
11238 mach
= bfd_mach_arm_iWMMXt
;
11239 else if (cpu_variant
& ARM_CEXT_XSCALE
)
11240 mach
= bfd_mach_arm_XScale
;
11241 else if (cpu_variant
& ARM_CEXT_MAVERICK
)
11242 mach
= bfd_mach_arm_ep9312
;
11243 else if (cpu_variant
& ARM_EXT_V5E
)
11244 mach
= bfd_mach_arm_5TE
;
11245 else if (cpu_variant
& ARM_EXT_V5
)
11247 if (cpu_variant
& ARM_EXT_V4T
)
11248 mach
= bfd_mach_arm_5T
;
11250 mach
= bfd_mach_arm_5
;
11252 else if (cpu_variant
& ARM_EXT_V4
)
11254 if (cpu_variant
& ARM_EXT_V4T
)
11255 mach
= bfd_mach_arm_4T
;
11257 mach
= bfd_mach_arm_4
;
11259 else if (cpu_variant
& ARM_EXT_V3M
)
11260 mach
= bfd_mach_arm_3M
;
11262 #if 0 /* Suppressed - for now. */
11263 #if defined (OBJ_ELF) || defined (OBJ_COFF)
11265 /* Create a .note section to fully identify this arm binary. */
11267 #define NOTE_ARCH_STRING "arch: "
11269 #if defined OBJ_COFF && ! defined NT_VERSION
11270 #define NT_VERSION 1
11275 segT current_seg
= now_seg
;
11276 subsegT current_subseg
= now_subseg
;
11277 asection
* arm_arch
;
11278 const char * arch_string
;
11280 arm_arch
= bfd_make_section_old_way (stdoutput
, ARM_NOTE_SECTION
);
11283 bfd_set_section_flags (stdoutput
, arm_arch
,
11284 SEC_DATA
| SEC_ALLOC
| SEC_LOAD
| SEC_LINK_ONCE \
11285 | SEC_HAS_CONTENTS
);
11287 bfd_set_section_flags (stdoutput
, arm_arch
,
11288 SEC_READONLY
| SEC_HAS_CONTENTS
);
11290 arm_arch
->output_section
= arm_arch
;
11291 subseg_set (arm_arch
, 0);
11296 case bfd_mach_arm_unknown
: arch_string
= "unknown"; break;
11297 case bfd_mach_arm_2
: arch_string
= "armv2"; break;
11298 case bfd_mach_arm_2a
: arch_string
= "armv2a"; break;
11299 case bfd_mach_arm_3
: arch_string
= "armv3"; break;
11300 case bfd_mach_arm_3M
: arch_string
= "armv3M"; break;
11301 case bfd_mach_arm_4
: arch_string
= "armv4"; break;
11302 case bfd_mach_arm_4T
: arch_string
= "armv4t"; break;
11303 case bfd_mach_arm_5
: arch_string
= "armv5"; break;
11304 case bfd_mach_arm_5T
: arch_string
= "armv5t"; break;
11305 case bfd_mach_arm_5TE
: arch_string
= "armv5te"; break;
11306 case bfd_mach_arm_XScale
: arch_string
= "XScale"; break;
11307 case bfd_mach_arm_ep9312
: arch_string
= "ep9312"; break;
11308 case bfd_mach_arm_iWMMXt
: arch_string
= "iWMMXt"; break;
11311 arm_add_note (NOTE_ARCH_STRING
, arch_string
, NT_ARCH
);
11313 subseg_set (current_seg
, current_subseg
);
11316 #endif /* Suppressed code. */
11318 bfd_set_arch_mach (stdoutput
, TARGET_ARCH
, mach
);
11321 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11322 for use in the a.out file, and stores them in the array pointed to by buf.
11323 This knows about the endian-ness of the target machine and does
11324 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11325 2 (short) and 4 (long) Floating numbers are put out as a series of
11326 LITTLENUMS (shorts, here at least). */
11329 md_number_to_chars (char * buf
, valueT val
, int n
)
11331 if (target_big_endian
)
11332 number_to_chars_bigendian (buf
, val
, n
);
11334 number_to_chars_littleendian (buf
, val
, n
);
11338 md_chars_to_number (char * buf
, int n
)
11341 unsigned char * where
= (unsigned char *) buf
;
11343 if (target_big_endian
)
11348 result
|= (*where
++ & 255);
11356 result
|= (where
[n
] & 255);
11363 /* Turn a string in input_line_pointer into a floating point constant
11364 of type TYPE, and store the appropriate bytes in *LITP. The number
11365 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11366 returned, or NULL on OK.
11368 Note that fp constants aren't represent in the normal way on the ARM.
11369 In big endian mode, things are as expected. However, in little endian
11370 mode fp constants are big-endian word-wise, and little-endian byte-wise
11371 within the words. For example, (double) 1.1 in big endian mode is
11372 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11373 the byte sequence 99 99 f1 3f 9a 99 99 99.
11375 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11378 md_atof (int type
, char * litP
, int * sizeP
)
11381 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
11413 return _("bad call to MD_ATOF()");
11416 t
= atof_ieee (input_line_pointer
, type
, words
);
11418 input_line_pointer
= t
;
11421 if (target_big_endian
)
11423 for (i
= 0; i
< prec
; i
++)
11425 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
11431 if (cpu_variant
& FPU_ARCH_VFP
)
11432 for (i
= prec
- 1; i
>= 0; i
--)
11434 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
11438 /* For a 4 byte float the order of elements in `words' is 1 0.
11439 For an 8 byte float the order is 1 0 3 2. */
11440 for (i
= 0; i
< prec
; i
+= 2)
11442 md_number_to_chars (litP
, (valueT
) words
[i
+ 1], 2);
11443 md_number_to_chars (litP
+ 2, (valueT
) words
[i
], 2);
11451 /* The knowledge of the PC's pipeline offset is built into the insns
11455 md_pcrel_from (fixS
* fixP
)
11458 && S_GET_SEGMENT (fixP
->fx_addsy
) == undefined_section
11459 && fixP
->fx_subsy
== NULL
)
11462 if (fixP
->fx_pcrel
&& (fixP
->fx_r_type
== BFD_RELOC_ARM_THUMB_ADD
))
11464 /* PC relative addressing on the Thumb is slightly odd
11465 as the bottom two bits of the PC are forced to zero
11466 for the calculation. */
11467 return (fixP
->fx_where
+ fixP
->fx_frag
->fr_address
) & ~3;
11471 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
11472 so we un-adjust here to compensate for the accommodation. */
11473 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
+ 8;
11475 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
11479 /* Round up a section size to the appropriate boundary. */
11482 md_section_align (segT segment ATTRIBUTE_UNUSED
,
11488 /* Round all sects to multiple of 4. */
11489 return (size
+ 3) & ~3;
11493 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
11494 Otherwise we have no need to default values of symbols. */
11497 md_undefined_symbol (char * name ATTRIBUTE_UNUSED
)
11500 if (name
[0] == '_' && name
[1] == 'G'
11501 && streq (name
, GLOBAL_OFFSET_TABLE_NAME
))
11505 if (symbol_find (name
))
11506 as_bad ("GOT already in the symbol table");
11508 GOT_symbol
= symbol_new (name
, undefined_section
,
11509 (valueT
) 0, & zero_address_frag
);
11520 md_apply_fix3 (fixS
* fixP
,
11524 offsetT value
= * valP
;
11526 unsigned int newimm
;
11527 unsigned long temp
;
11529 char * buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
11530 arm_fix_data
* arm_data
= (arm_fix_data
*) fixP
->tc_fix_data
;
11532 assert (fixP
->fx_r_type
< BFD_RELOC_UNUSED
);
11534 /* Note whether this will delete the relocation. */
11536 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
11537 doesn't work fully.) */
11538 if ((fixP
->fx_addsy
== 0 || symbol_constant_p (fixP
->fx_addsy
))
11539 && !fixP
->fx_pcrel
)
11541 if (fixP
->fx_addsy
== 0 && !fixP
->fx_pcrel
)
11545 /* If this symbol is in a different section then we need to leave it for
11546 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
11547 so we have to undo it's effects here. */
11548 if (fixP
->fx_pcrel
)
11550 if (fixP
->fx_addsy
!= NULL
11551 && S_IS_DEFINED (fixP
->fx_addsy
)
11552 && S_GET_SEGMENT (fixP
->fx_addsy
) != seg
)
11555 && (fixP
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
11556 || fixP
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
11560 value
+= md_pcrel_from (fixP
);
11564 /* Remember value for emit_reloc. */
11565 fixP
->fx_addnumber
= value
;
11567 switch (fixP
->fx_r_type
)
11569 case BFD_RELOC_ARM_IMMEDIATE
:
11570 /* We claim that this fixup has been processed here,
11571 even if in fact we generate an error because we do
11572 not have a reloc for it, so tc_gen_reloc will reject it. */
11576 && ! S_IS_DEFINED (fixP
->fx_addsy
))
11578 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11579 _("undefined symbol %s used as an immediate value"),
11580 S_GET_NAME (fixP
->fx_addsy
));
11584 newimm
= validate_immediate (value
);
11585 temp
= md_chars_to_number (buf
, INSN_SIZE
);
11587 /* If the instruction will fail, see if we can fix things up by
11588 changing the opcode. */
11589 if (newimm
== (unsigned int) FAIL
11590 && (newimm
= negate_data_op (&temp
, value
)) == (unsigned int) FAIL
)
11592 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11593 _("invalid constant (%lx) after fixup"),
11594 (unsigned long) value
);
11598 newimm
|= (temp
& 0xfffff000);
11599 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
11602 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
11604 unsigned int highpart
= 0;
11605 unsigned int newinsn
= 0xe1a00000; /* nop. */
11607 newimm
= validate_immediate (value
);
11608 temp
= md_chars_to_number (buf
, INSN_SIZE
);
11610 /* If the instruction will fail, see if we can fix things up by
11611 changing the opcode. */
11612 if (newimm
== (unsigned int) FAIL
11613 && (newimm
= negate_data_op (& temp
, value
)) == (unsigned int) FAIL
)
11615 /* No ? OK - try using two ADD instructions to generate
11617 newimm
= validate_immediate_twopart (value
, & highpart
);
11619 /* Yes - then make sure that the second instruction is
11621 if (newimm
!= (unsigned int) FAIL
)
11623 /* Still No ? Try using a negated value. */
11624 else if ((newimm
= validate_immediate_twopart (- value
, & highpart
)) != (unsigned int) FAIL
)
11625 temp
= newinsn
= (temp
& OPCODE_MASK
) | OPCODE_SUB
<< DATA_OP_SHIFT
;
11626 /* Otherwise - give up. */
11629 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11630 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
11635 /* Replace the first operand in the 2nd instruction (which
11636 is the PC) with the destination register. We have
11637 already added in the PC in the first instruction and we
11638 do not want to do it again. */
11639 newinsn
&= ~ 0xf0000;
11640 newinsn
|= ((newinsn
& 0x0f000) << 4);
11643 newimm
|= (temp
& 0xfffff000);
11644 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
11646 highpart
|= (newinsn
& 0xfffff000);
11647 md_number_to_chars (buf
+ INSN_SIZE
, (valueT
) highpart
, INSN_SIZE
);
11651 case BFD_RELOC_ARM_OFFSET_IMM
:
11657 if (validate_offset_imm (value
, 0) == FAIL
)
11659 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11660 _("bad immediate value for offset (%ld)"),
11665 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11666 newval
&= 0xff7ff000;
11667 newval
|= value
| (sign
? INDEX_UP
: 0);
11668 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11671 case BFD_RELOC_ARM_OFFSET_IMM8
:
11672 case BFD_RELOC_ARM_HWLITERAL
:
11678 if (validate_offset_imm (value
, 1) == FAIL
)
11680 if (fixP
->fx_r_type
== BFD_RELOC_ARM_HWLITERAL
)
11681 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11682 _("invalid literal constant: pool needs to be closer"));
11684 as_bad (_("bad immediate value for half-word offset (%ld)"),
11689 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11690 newval
&= 0xff7ff0f0;
11691 newval
|= ((value
>> 4) << 8) | (value
& 0xf) | (sign
? INDEX_UP
: 0);
11692 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11695 case BFD_RELOC_ARM_LITERAL
:
11701 if (validate_offset_imm (value
, 0) == FAIL
)
11703 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11704 _("invalid literal constant: pool needs to be closer"));
11708 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11709 newval
&= 0xff7ff000;
11710 newval
|= value
| (sign
? INDEX_UP
: 0);
11711 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11714 case BFD_RELOC_ARM_SHIFT_IMM
:
11715 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11716 if (((unsigned long) value
) > 32
11718 && (((newval
& 0x60) == 0) || (newval
& 0x60) == 0x60)))
11720 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11721 _("shift expression is too large"));
11726 /* Shifts of zero must be done as lsl. */
11728 else if (value
== 32)
11730 newval
&= 0xfffff07f;
11731 newval
|= (value
& 0x1f) << 7;
11732 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11735 case BFD_RELOC_ARM_SMI
:
11736 if (((unsigned long) value
) > 0xffff)
11737 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11738 _("invalid smi expression"));
11739 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xfff000f0;
11740 newval
|= (value
& 0xf) | ((value
& 0xfff0) << 4);
11741 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11744 case BFD_RELOC_ARM_SWI
:
11745 if (arm_data
->thumb_mode
)
11747 if (((unsigned long) value
) > 0xff)
11748 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11749 _("invalid swi expression"));
11750 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xff00;
11752 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11756 if (((unsigned long) value
) > 0x00ffffff)
11757 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11758 _("invalid swi expression"));
11759 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff000000;
11761 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11765 case BFD_RELOC_ARM_MULTI
:
11766 if (((unsigned long) value
) > 0xffff)
11767 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11768 _("invalid expression in load/store multiple"));
11769 newval
= value
| md_chars_to_number (buf
, INSN_SIZE
);
11770 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11773 case BFD_RELOC_ARM_PCREL_BRANCH
:
11774 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11776 /* Sign-extend a 24-bit number. */
11777 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
11781 value
= fixP
->fx_offset
;
11784 /* We are going to store value (shifted right by two) in the
11785 instruction, in a 24 bit, signed field. Thus we need to check
11786 that none of the top 8 bits of the shifted value (top 7 bits of
11787 the unshifted, unsigned value) are set, or that they are all set. */
11788 if ((value
& ~ ((offsetT
) 0x1ffffff)) != 0
11789 && ((value
& ~ ((offsetT
) 0x1ffffff)) != ~ ((offsetT
) 0x1ffffff)))
11792 /* Normally we would be stuck at this point, since we cannot store
11793 the absolute address that is the destination of the branch in the
11794 24 bits of the branch instruction. If however, we happen to know
11795 that the destination of the branch is in the same section as the
11796 branch instruction itself, then we can compute the relocation for
11797 ourselves and not have to bother the linker with it.
11799 FIXME: The tests for OBJ_ELF and ! target_oabi are only here
11800 because I have not worked out how to do this for OBJ_COFF or
11803 && fixP
->fx_addsy
!= NULL
11804 && S_IS_DEFINED (fixP
->fx_addsy
)
11805 && S_GET_SEGMENT (fixP
->fx_addsy
) == seg
)
11807 /* Get pc relative value to go into the branch. */
11810 /* Permit a backward branch provided that enough bits
11811 are set. Allow a forwards branch, provided that
11812 enough bits are clear. */
11813 if ( (value
& ~ ((offsetT
) 0x1ffffff)) == ~ ((offsetT
) 0x1ffffff)
11814 || (value
& ~ ((offsetT
) 0x1ffffff)) == 0)
11818 if (! fixP
->fx_done
)
11820 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11821 _("GAS can't handle same-section branch dest >= 0x04000000"));
11825 value
+= SEXT24 (newval
);
11827 if ( (value
& ~ ((offsetT
) 0xffffff)) != 0
11828 && ((value
& ~ ((offsetT
) 0xffffff)) != ~ ((offsetT
) 0xffffff)))
11829 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11830 _("out of range branch"));
11832 newval
= (value
& 0x00ffffff) | (newval
& 0xff000000);
11833 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11836 case BFD_RELOC_ARM_PCREL_BLX
:
11839 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11843 value
= fixP
->fx_offset
;
11845 hbit
= (value
>> 1) & 1;
11846 value
= (value
>> 2) & 0x00ffffff;
11847 value
= (value
+ (newval
& 0x00ffffff)) & 0x00ffffff;
11848 newval
= value
| (newval
& 0xfe000000) | (hbit
<< 24);
11849 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11853 case BFD_RELOC_THUMB_PCREL_BRANCH9
: /* Conditional branch. */
11854 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11856 addressT diff
= (newval
& 0xff) << 1;
11861 if ((value
& ~0xff) && ((value
& ~0xff) != ~0xff))
11862 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11863 _("branch out of range"));
11864 newval
= (newval
& 0xff00) | ((value
& 0x1ff) >> 1);
11866 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11869 case BFD_RELOC_THUMB_PCREL_BRANCH12
: /* Unconditional branch. */
11870 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11872 addressT diff
= (newval
& 0x7ff) << 1;
11877 if ((value
& ~0x7ff) && ((value
& ~0x7ff) != ~0x7ff))
11878 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11879 _("branch out of range"));
11880 newval
= (newval
& 0xf800) | ((value
& 0xfff) >> 1);
11882 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11885 case BFD_RELOC_THUMB_PCREL_BLX
:
11886 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
11891 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11892 newval2
= md_chars_to_number (buf
+ THUMB_SIZE
, THUMB_SIZE
);
11893 diff
= ((newval
& 0x7ff) << 12) | ((newval2
& 0x7ff) << 1);
11894 if (diff
& 0x400000)
11897 value
= fixP
->fx_offset
;
11901 if ((value
& ~0x3fffff) && ((value
& ~0x3fffff) != ~0x3fffff))
11902 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11903 _("branch with link out of range"));
11905 newval
= (newval
& 0xf800) | ((value
& 0x7fffff) >> 12);
11906 newval2
= (newval2
& 0xf800) | ((value
& 0xfff) >> 1);
11907 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
)
11908 /* For a BLX instruction, make sure that the relocation is rounded up
11909 to a word boundary. This follows the semantics of the instruction
11910 which specifies that bit 1 of the target address will come from bit
11911 1 of the base address. */
11912 newval2
= (newval2
+ 1) & ~ 1;
11913 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11914 md_number_to_chars (buf
+ THUMB_SIZE
, newval2
, THUMB_SIZE
);
11919 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11920 md_number_to_chars (buf
, value
, 1);
11922 else if (!target_oabi
)
11924 value
= fixP
->fx_offset
;
11925 md_number_to_chars (buf
, value
, 1);
11931 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11932 md_number_to_chars (buf
, value
, 2);
11934 else if (!target_oabi
)
11936 value
= fixP
->fx_offset
;
11937 md_number_to_chars (buf
, value
, 2);
11943 case BFD_RELOC_ARM_GOT32
:
11944 case BFD_RELOC_ARM_GOTOFF
:
11945 case BFD_RELOC_ARM_TARGET2
:
11946 md_number_to_chars (buf
, 0, 4);
11950 case BFD_RELOC_RVA
:
11952 case BFD_RELOC_ARM_TARGET1
:
11953 case BFD_RELOC_ARM_ROSEGREL32
:
11954 case BFD_RELOC_ARM_SBREL32
:
11955 case BFD_RELOC_32_PCREL
:
11956 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11957 md_number_to_chars (buf
, value
, 4);
11959 else if (!target_oabi
)
11961 value
= fixP
->fx_offset
;
11962 md_number_to_chars (buf
, value
, 4);
11968 case BFD_RELOC_ARM_PREL31
:
11969 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11971 newval
= md_chars_to_number (buf
, 4) & 0x80000000;
11972 if ((value
^ (value
>> 1)) & 0x40000000)
11974 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11975 _("rel31 relocation overflow"));
11977 newval
|= value
& 0x7fffffff;
11978 md_number_to_chars (buf
, newval
, 4);
11982 case BFD_RELOC_ARM_PLT32
:
11983 /* It appears the instruction is fully prepared at this point. */
11987 case BFD_RELOC_ARM_CP_OFF_IMM
:
11989 if (value
< -1023 || value
> 1023 || (value
& 3))
11990 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11991 _("illegal value for co-processor offset"));
11994 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
11995 newval
|= (value
>> 2) | (sign
? INDEX_UP
: 0);
11996 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11999 case BFD_RELOC_ARM_CP_OFF_IMM_S2
:
12001 if (value
< -255 || value
> 255)
12002 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12003 _("Illegal value for co-processor offset"));
12006 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
12007 newval
|= value
| (sign
? INDEX_UP
: 0);
12008 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12011 case BFD_RELOC_ARM_THUMB_OFFSET
:
12012 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12013 /* Exactly what ranges, and where the offset is inserted depends
12014 on the type of instruction, we can establish this from the
12016 switch (newval
>> 12)
12018 case 4: /* PC load. */
12019 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
12020 forced to zero for these loads, so we will need to round
12021 up the offset if the instruction address is not word
12022 aligned (since the final address produced must be, and
12023 we can only describe word-aligned immediate offsets). */
12025 if ((fixP
->fx_frag
->fr_address
+ fixP
->fx_where
+ value
) & 3)
12026 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12027 _("invalid offset, target not word aligned (0x%08X)"),
12028 (unsigned int) (fixP
->fx_frag
->fr_address
12029 + fixP
->fx_where
+ value
));
12031 if ((value
+ 2) & ~0x3fe)
12032 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12033 _("invalid offset, value too big (0x%08lX)"),
12036 /* Round up, since pc will be rounded down. */
12037 newval
|= (value
+ 2) >> 2;
12040 case 9: /* SP load/store. */
12041 if (value
& ~0x3fc)
12042 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12043 _("invalid offset, value too big (0x%08lX)"),
12045 newval
|= value
>> 2;
12048 case 6: /* Word load/store. */
12050 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12051 _("invalid offset, value too big (0x%08lX)"),
12053 newval
|= value
<< 4; /* 6 - 2. */
12056 case 7: /* Byte load/store. */
12058 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12059 _("invalid offset, value too big (0x%08lX)"),
12061 newval
|= value
<< 6;
12064 case 8: /* Halfword load/store. */
12066 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12067 _("invalid offset, value too big (0x%08lX)"),
12069 newval
|= value
<< 5; /* 6 - 1. */
12073 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12074 "Unable to process relocation for thumb opcode: %lx",
12075 (unsigned long) newval
);
12078 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12081 case BFD_RELOC_ARM_THUMB_ADD
:
12082 /* This is a complicated relocation, since we use it for all of
12083 the following immediate relocations:
12087 9bit ADD/SUB SP word-aligned
12088 10bit ADD PC/SP word-aligned
12090 The type of instruction being processed is encoded in the
12097 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12099 int rd
= (newval
>> 4) & 0xf;
12100 int rs
= newval
& 0xf;
12101 int subtract
= newval
& 0x8000;
12105 if (value
& ~0x1fc)
12106 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12107 _("invalid immediate for stack address calculation"));
12108 newval
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
12109 newval
|= value
>> 2;
12111 else if (rs
== REG_PC
|| rs
== REG_SP
)
12115 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12116 _("invalid immediate for address calculation (value = 0x%08lX)"),
12117 (unsigned long) value
);
12118 newval
= (rs
== REG_PC
? T_OPCODE_ADD_PC
: T_OPCODE_ADD_SP
);
12120 newval
|= value
>> 2;
12125 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12126 _("invalid 8bit immediate"));
12127 newval
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
12128 newval
|= (rd
<< 8) | value
;
12133 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12134 _("invalid 3bit immediate"));
12135 newval
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
12136 newval
|= rd
| (rs
<< 3) | (value
<< 6);
12139 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12142 case BFD_RELOC_ARM_THUMB_IMM
:
12143 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12144 switch (newval
>> 11)
12146 case 0x04: /* 8bit immediate MOV. */
12147 case 0x05: /* 8bit immediate CMP. */
12148 if (value
< 0 || value
> 255)
12149 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12150 _("invalid immediate: %ld is too large"),
12158 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12161 case BFD_RELOC_ARM_THUMB_SHIFT
:
12162 /* 5bit shift value (0..31). */
12163 if (value
< 0 || value
> 31)
12164 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12165 _("illegal Thumb shift value: %ld"), (long) value
);
12166 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xf03f;
12167 newval
|= value
<< 6;
12168 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12171 case BFD_RELOC_VTABLE_INHERIT
:
12172 case BFD_RELOC_VTABLE_ENTRY
:
12176 case BFD_RELOC_NONE
:
12178 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12179 _("bad relocation fixup type (%d)"), fixP
->fx_r_type
);
12183 /* Translate internal representation of relocation info to BFD target
12187 tc_gen_reloc (asection
* section ATTRIBUTE_UNUSED
,
12191 bfd_reloc_code_real_type code
;
12193 reloc
= xmalloc (sizeof (arelent
));
12195 reloc
->sym_ptr_ptr
= xmalloc (sizeof (asymbol
*));
12196 *reloc
->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
12197 reloc
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
12199 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12201 if (fixp
->fx_pcrel
== 0)
12202 reloc
->addend
= fixp
->fx_offset
;
12204 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
12205 #else /* OBJ_ELF */
12206 reloc
->addend
= fixp
->fx_offset
;
12209 switch (fixp
->fx_r_type
)
12212 if (fixp
->fx_pcrel
)
12214 code
= BFD_RELOC_8_PCREL
;
12219 if (fixp
->fx_pcrel
)
12221 code
= BFD_RELOC_16_PCREL
;
12226 if (fixp
->fx_pcrel
)
12228 code
= BFD_RELOC_32_PCREL
;
12232 case BFD_RELOC_ARM_PCREL_BRANCH
:
12233 case BFD_RELOC_ARM_PCREL_BLX
:
12234 case BFD_RELOC_RVA
:
12235 case BFD_RELOC_THUMB_PCREL_BRANCH9
:
12236 case BFD_RELOC_THUMB_PCREL_BRANCH12
:
12237 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
12238 case BFD_RELOC_THUMB_PCREL_BLX
:
12239 case BFD_RELOC_VTABLE_ENTRY
:
12240 case BFD_RELOC_VTABLE_INHERIT
:
12241 code
= fixp
->fx_r_type
;
12244 case BFD_RELOC_ARM_LITERAL
:
12245 case BFD_RELOC_ARM_HWLITERAL
:
12246 /* If this is called then the a literal has
12247 been referenced across a section boundary. */
12248 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12249 _("literal referenced across section boundary"));
12253 case BFD_RELOC_ARM_GOT32
:
12254 case BFD_RELOC_ARM_GOTOFF
:
12255 case BFD_RELOC_ARM_PLT32
:
12256 case BFD_RELOC_ARM_TARGET1
:
12257 case BFD_RELOC_ARM_ROSEGREL32
:
12258 case BFD_RELOC_ARM_SBREL32
:
12259 case BFD_RELOC_ARM_PREL31
:
12260 case BFD_RELOC_ARM_TARGET2
:
12261 code
= fixp
->fx_r_type
;
12265 case BFD_RELOC_ARM_IMMEDIATE
:
12266 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12267 _("internal relocation (type: IMMEDIATE) not fixed up"));
12270 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
12271 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12272 _("ADRL used for a symbol not defined in the same file"));
12275 case BFD_RELOC_ARM_OFFSET_IMM
:
12276 if (fixp
->fx_addsy
!= NULL
12277 && !S_IS_DEFINED (fixp
->fx_addsy
)
12278 && S_IS_LOCAL (fixp
->fx_addsy
))
12280 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12281 _("undefined local label `%s'"),
12282 S_GET_NAME (fixp
->fx_addsy
));
12286 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12287 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
12294 switch (fixp
->fx_r_type
)
12296 case BFD_RELOC_ARM_OFFSET_IMM8
: type
= "OFFSET_IMM8"; break;
12297 case BFD_RELOC_ARM_SHIFT_IMM
: type
= "SHIFT_IMM"; break;
12298 case BFD_RELOC_ARM_SMI
: type
= "SMI"; break;
12299 case BFD_RELOC_ARM_SWI
: type
= "SWI"; break;
12300 case BFD_RELOC_ARM_MULTI
: type
= "MULTI"; break;
12301 case BFD_RELOC_ARM_CP_OFF_IMM
: type
= "CP_OFF_IMM"; break;
12302 case BFD_RELOC_ARM_THUMB_ADD
: type
= "THUMB_ADD"; break;
12303 case BFD_RELOC_ARM_THUMB_SHIFT
: type
= "THUMB_SHIFT"; break;
12304 case BFD_RELOC_ARM_THUMB_IMM
: type
= "THUMB_IMM"; break;
12305 case BFD_RELOC_ARM_THUMB_OFFSET
: type
= "THUMB_OFFSET"; break;
12306 default: type
= _("<unknown>"); break;
12308 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12309 _("cannot represent %s relocation in this object file format"),
12316 if ((code
== BFD_RELOC_32_PCREL
|| code
== BFD_RELOC_32
)
12318 && fixp
->fx_addsy
== GOT_symbol
)
12320 code
= BFD_RELOC_ARM_GOTPC
;
12321 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
12325 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, code
);
12327 if (reloc
->howto
== NULL
)
12329 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12330 _("cannot represent %s relocation in this object file format"),
12331 bfd_get_reloc_code_name (code
));
12335 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12336 vtable entry to be used in the relocation's section offset. */
12337 if (fixp
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
12338 reloc
->address
= fixp
->fx_offset
;
12344 md_estimate_size_before_relax (fragS
* fragP ATTRIBUTE_UNUSED
,
12345 segT segtype ATTRIBUTE_UNUSED
)
12347 as_fatal (_("md_estimate_size_before_relax\n"));
12351 /* We need to be able to fix up arbitrary expressions in some statements.
12352 This is so that we can handle symbols that are an arbitrary distance from
12353 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
12354 which returns part of an address in a form which will be valid for
12355 a data instruction. We do this by pushing the expression into a symbol
12356 in the expr_section, and creating a fix for that. */
12359 fix_new_arm (fragS
* frag
,
12367 arm_fix_data
* arm_data
;
12375 new_fix
= fix_new_exp (frag
, where
, size
, exp
, pc_rel
, reloc
);
12379 new_fix
= fix_new (frag
, where
, size
, make_expr_symbol (exp
), 0,
12384 /* Mark whether the fix is to a THUMB instruction, or an ARM
12386 arm_data
= obstack_alloc (& notes
, sizeof (arm_fix_data
));
12387 new_fix
->tc_fix_data
= (PTR
) arm_data
;
12388 arm_data
->thumb_mode
= thumb_mode
;
12392 output_inst (const char * str
)
12398 as_bad ("%s -- `%s'", inst
.error
, str
);
12402 to
= frag_more (inst
.size
);
12404 if (thumb_mode
&& (inst
.size
> THUMB_SIZE
))
12406 assert (inst
.size
== (2 * THUMB_SIZE
));
12407 md_number_to_chars (to
, inst
.instruction
>> 16, THUMB_SIZE
);
12408 md_number_to_chars (to
+ THUMB_SIZE
, inst
.instruction
, THUMB_SIZE
);
12410 else if (inst
.size
> INSN_SIZE
)
12412 assert (inst
.size
== (2 * INSN_SIZE
));
12413 md_number_to_chars (to
, inst
.instruction
, INSN_SIZE
);
12414 md_number_to_chars (to
+ INSN_SIZE
, inst
.instruction
, INSN_SIZE
);
12417 md_number_to_chars (to
, inst
.instruction
, inst
.size
);
12419 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
12420 fix_new_arm (frag_now
, to
- frag_now
->fr_literal
,
12421 inst
.size
, & inst
.reloc
.exp
, inst
.reloc
.pc_rel
,
12425 dwarf2_emit_insn (inst
.size
);
12430 md_assemble (char * str
)
12436 /* Align the instruction.
12437 This may not be the right thing to do but ... */
12442 /* Align the previous label if needed. */
12443 if (last_label_seen
!= NULL
)
12445 symbol_set_frag (last_label_seen
, frag_now
);
12446 S_SET_VALUE (last_label_seen
, (valueT
) frag_now_fix ());
12447 S_SET_SEGMENT (last_label_seen
, now_seg
);
12450 memset (&inst
, '\0', sizeof (inst
));
12451 inst
.reloc
.type
= BFD_RELOC_NONE
;
12453 skip_whitespace (str
);
12455 /* Scan up to the end of the op-code, which must end in white space or
12457 for (start
= p
= str
; *p
!= '\0'; p
++)
12463 as_bad (_("no operator -- statement `%s'\n"), str
);
12469 const struct thumb_opcode
* opcode
;
12473 opcode
= (const struct thumb_opcode
*) hash_find (arm_tops_hsh
, str
);
12478 /* Check that this instruction is supported for this CPU. */
12479 if (thumb_mode
== 1 && (opcode
->variant
& cpu_variant
) == 0)
12481 as_bad (_("selected processor does not support `%s'"), str
);
12485 mapping_state (MAP_THUMB
);
12486 inst
.instruction
= opcode
->value
;
12487 inst
.size
= opcode
->size
;
12495 const struct asm_opcode
* opcode
;
12499 opcode
= (const struct asm_opcode
*) hash_find (arm_ops_hsh
, str
);
12504 /* Check that this instruction is supported for this CPU. */
12505 if ((opcode
->variant
& cpu_variant
) == 0)
12507 as_bad (_("selected processor does not support `%s'"), str
);
12511 mapping_state (MAP_ARM
);
12512 inst
.instruction
= opcode
->value
;
12513 inst
.size
= INSN_SIZE
;
12520 /* It wasn't an instruction, but it might be a register alias of the form
12522 if (create_register_alias (str
, p
))
12525 as_bad (_("bad instruction `%s'"), start
);
12529 Invocation line includes a switch not recognized by the base assembler.
12530 See if it's a processor-specific option.
12532 This routine is somewhat complicated by the need for backwards
12533 compatibility (since older releases of gcc can't be changed).
12534 The new options try to make the interface as compatible as
12537 New options (supported) are:
12539 -mcpu=<cpu name> Assemble for selected processor
12540 -march=<architecture name> Assemble for selected architecture
12541 -mfpu=<fpu architecture> Assemble for selected FPU.
12542 -EB/-mbig-endian Big-endian
12543 -EL/-mlittle-endian Little-endian
12544 -k Generate PIC code
12545 -mthumb Start in Thumb mode
12546 -mthumb-interwork Code supports ARM/Thumb interworking
12548 For now we will also provide support for:
12550 -mapcs-32 32-bit Program counter
12551 -mapcs-26 26-bit Program counter
12552 -macps-float Floats passed in FP registers
12553 -mapcs-reentrant Reentrant code
12555 (sometime these will probably be replaced with -mapcs=<list of options>
12556 and -matpcs=<list of options>)
12558 The remaining options are only supported for back-wards compatibility.
12559 Cpu variants, the arm part is optional:
12560 -m[arm]1 Currently not supported.
12561 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
12562 -m[arm]3 Arm 3 processor
12563 -m[arm]6[xx], Arm 6 processors
12564 -m[arm]7[xx][t][[d]m] Arm 7 processors
12565 -m[arm]8[10] Arm 8 processors
12566 -m[arm]9[20][tdmi] Arm 9 processors
12567 -mstrongarm[110[0]] StrongARM processors
12568 -mxscale XScale processors
12569 -m[arm]v[2345[t[e]]] Arm architectures
12570 -mall All (except the ARM1)
12572 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
12573 -mfpe-old (No float load/store multiples)
12574 -mvfpxd VFP Single precision
12576 -mno-fpu Disable all floating point instructions
12578 The following CPU names are recognized:
12579 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
12580 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
12581 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
12582 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
12583 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
12584 arm10t arm10e, arm1020t, arm1020e, arm10200e,
12585 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
12589 const char * md_shortopts
= "m:k";
12591 #ifdef ARM_BI_ENDIAN
12592 #define OPTION_EB (OPTION_MD_BASE + 0)
12593 #define OPTION_EL (OPTION_MD_BASE + 1)
12595 #if TARGET_BYTES_BIG_ENDIAN
12596 #define OPTION_EB (OPTION_MD_BASE + 0)
12598 #define OPTION_EL (OPTION_MD_BASE + 1)
12602 struct option md_longopts
[] =
12605 {"EB", no_argument
, NULL
, OPTION_EB
},
12608 {"EL", no_argument
, NULL
, OPTION_EL
},
12610 {NULL
, no_argument
, NULL
, 0}
12613 size_t md_longopts_size
= sizeof (md_longopts
);
12615 struct arm_option_table
12617 char *option
; /* Option name to match. */
12618 char *help
; /* Help information. */
12619 int *var
; /* Variable to change. */
12620 int value
; /* What to change it to. */
12621 char *deprecated
; /* If non-null, print this message. */
12624 struct arm_option_table arm_opts
[] =
12626 {"k", N_("generate PIC code"), &pic_code
, 1, NULL
},
12627 {"mthumb", N_("assemble Thumb code"), &thumb_mode
, 1, NULL
},
12628 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
12629 &support_interwork
, 1, NULL
},
12630 {"moabi", N_("use old ABI (ELF only)"), &target_oabi
, 1, NULL
},
12631 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26
, 0, NULL
},
12632 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26
, 1, NULL
},
12633 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float
,
12635 {"mapcs-reentrant", N_("re-entrant code"), &pic_code
, 1, NULL
},
12636 {"matpcs", N_("code is ATPCS conformant"), &atpcs
, 1, NULL
},
12637 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian
, 1, NULL
},
12638 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian
, 1,
12641 /* These are recognized by the assembler, but have no affect on code. */
12642 {"mapcs-frame", N_("use frame pointer"), NULL
, 0, NULL
},
12643 {"mapcs-stack-check", N_("use stack size checking"), NULL
, 0, NULL
},
12645 /* DON'T add any new processors to this list -- we want the whole list
12646 to go away... Add them to the processors table instead. */
12647 {"marm1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
12648 {"m1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
12649 {"marm2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
12650 {"m2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
12651 {"marm250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
12652 {"m250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
12653 {"marm3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
12654 {"m3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
12655 {"marm6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
12656 {"m6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
12657 {"marm600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
12658 {"m600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
12659 {"marm610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
12660 {"m610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
12661 {"marm620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
12662 {"m620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
12663 {"marm7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
12664 {"m7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
12665 {"marm70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
12666 {"m70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
12667 {"marm700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
12668 {"m700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
12669 {"marm700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
12670 {"m700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
12671 {"marm710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
12672 {"m710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
12673 {"marm710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
12674 {"m710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
12675 {"marm720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
12676 {"m720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
12677 {"marm7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
12678 {"m7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
12679 {"marm7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
12680 {"m7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
12681 {"marm7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
12682 {"m7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
12683 {"marm7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
12684 {"m7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
12685 {"marm7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
12686 {"m7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
12687 {"marm7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
12688 {"m7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
12689 {"marm7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
12690 {"m7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
12691 {"marm7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
12692 {"m7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
12693 {"marm7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12694 {"m7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12695 {"marm7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12696 {"m7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12697 {"marm710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
12698 {"m710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
12699 {"marm720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
12700 {"m720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
12701 {"marm740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
12702 {"m740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
12703 {"marm8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
12704 {"m8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
12705 {"marm810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
12706 {"m810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
12707 {"marm9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
12708 {"m9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
12709 {"marm9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
12710 {"m9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
12711 {"marm920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
12712 {"m920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
12713 {"marm940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
12714 {"m940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
12715 {"mstrongarm", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=strongarm")},
12716 {"mstrongarm110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
12717 N_("use -mcpu=strongarm110")},
12718 {"mstrongarm1100", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
12719 N_("use -mcpu=strongarm1100")},
12720 {"mstrongarm1110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
12721 N_("use -mcpu=strongarm1110")},
12722 {"mxscale", NULL
, &legacy_cpu
, ARM_ARCH_XSCALE
, N_("use -mcpu=xscale")},
12723 {"miwmmxt", NULL
, &legacy_cpu
, ARM_ARCH_IWMMXT
, N_("use -mcpu=iwmmxt")},
12724 {"mall", NULL
, &legacy_cpu
, ARM_ANY
, N_("use -mcpu=all")},
12726 /* Architecture variants -- don't add any more to this list either. */
12727 {"mv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
12728 {"marmv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
12729 {"mv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
12730 {"marmv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
12731 {"mv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
12732 {"marmv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
12733 {"mv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
12734 {"marmv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
12735 {"mv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
12736 {"marmv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
12737 {"mv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
12738 {"marmv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
12739 {"mv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
12740 {"marmv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
12741 {"mv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
12742 {"marmv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
12743 {"mv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
12744 {"marmv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
12746 /* Floating point variants -- don't add any more to this list either. */
12747 {"mfpe-old", NULL
, &legacy_fpu
, FPU_ARCH_FPE
, N_("use -mfpu=fpe")},
12748 {"mfpa10", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa10")},
12749 {"mfpa11", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa11")},
12750 {"mno-fpu", NULL
, &legacy_fpu
, 0,
12751 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
12753 {NULL
, NULL
, NULL
, 0, NULL
}
12756 struct arm_cpu_option_table
12760 /* For some CPUs we assume an FPU unless the user explicitly sets
12765 /* This list should, at a minimum, contain all the cpu names
12766 recognized by GCC. */
12767 static struct arm_cpu_option_table arm_cpus
[] =
12769 {"all", ARM_ANY
, FPU_ARCH_FPA
},
12770 {"arm1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
12771 {"arm2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
12772 {"arm250", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
12773 {"arm3", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
12774 {"arm6", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12775 {"arm60", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12776 {"arm600", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12777 {"arm610", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12778 {"arm620", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12779 {"arm7", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12780 {"arm7m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
12781 {"arm7d", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12782 {"arm7dm", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
12783 {"arm7di", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12784 {"arm7dmi", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
12785 {"arm70", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12786 {"arm700", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12787 {"arm700i", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12788 {"arm710", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12789 {"arm710t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12790 {"arm720", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12791 {"arm720t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12792 {"arm740t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12793 {"arm710c", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12794 {"arm7100", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12795 {"arm7500", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12796 {"arm7500fe", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12797 {"arm7t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12798 {"arm7tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12799 {"arm7tdmi-s", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12800 {"arm8", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12801 {"arm810", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12802 {"strongarm", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12803 {"strongarm1", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12804 {"strongarm110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12805 {"strongarm1100", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12806 {"strongarm1110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12807 {"arm9", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12808 {"arm920", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12809 {"arm920t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12810 {"arm922t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12811 {"arm940t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12812 {"arm9tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12813 /* For V5 or later processors we default to using VFP; but the user
12814 should really set the FPU type explicitly. */
12815 {"arm9e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
12816 {"arm9e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12817 {"arm926ej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
12818 {"arm926ejs", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
12819 {"arm926ej-s", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
12820 {"arm946e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
12821 {"arm946e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12822 {"arm966e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
12823 {"arm966e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12824 {"arm10t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
12825 {"arm10e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12826 {"arm1020", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12827 {"arm1020t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
12828 {"arm1020e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12829 {"arm1026ejs", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12830 {"arm1026ej-s", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12831 {"arm1136js", ARM_ARCH_V6
, FPU_NONE
},
12832 {"arm1136j-s", ARM_ARCH_V6
, FPU_NONE
},
12833 {"arm1136jfs", ARM_ARCH_V6
, FPU_ARCH_VFP_V2
},
12834 {"arm1136jf-s", ARM_ARCH_V6
, FPU_ARCH_VFP_V2
},
12835 {"mpcore", ARM_ARCH_V6K
, FPU_ARCH_VFP_V2
},
12836 {"mpcorenovfp", ARM_ARCH_V6K
, FPU_NONE
},
12837 {"arm1176jz-s", ARM_ARCH_V6ZK
, FPU_NONE
},
12838 {"arm1176jzf-s", ARM_ARCH_V6ZK
, FPU_ARCH_VFP_V2
},
12839 /* ??? XSCALE is really an architecture. */
12840 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
12841 /* ??? iwmmxt is not a processor. */
12842 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP_V2
},
12843 {"i80200", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
12845 {"ep9312", ARM_ARCH_V4T
| ARM_CEXT_MAVERICK
, FPU_ARCH_MAVERICK
},
12849 struct arm_arch_option_table
12856 /* This list should, at a minimum, contain all the architecture names
12857 recognized by GCC. */
12858 static struct arm_arch_option_table arm_archs
[] =
12860 {"all", ARM_ANY
, FPU_ARCH_FPA
},
12861 {"armv1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
12862 {"armv2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
12863 {"armv2a", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
12864 {"armv2s", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
12865 {"armv3", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12866 {"armv3m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
12867 {"armv4", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12868 {"armv4xm", ARM_ARCH_V4xM
, FPU_ARCH_FPA
},
12869 {"armv4t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12870 {"armv4txm", ARM_ARCH_V4TxM
, FPU_ARCH_FPA
},
12871 {"armv5", ARM_ARCH_V5
, FPU_ARCH_VFP
},
12872 {"armv5t", ARM_ARCH_V5T
, FPU_ARCH_VFP
},
12873 {"armv5txm", ARM_ARCH_V5TxM
, FPU_ARCH_VFP
},
12874 {"armv5te", ARM_ARCH_V5TE
, FPU_ARCH_VFP
},
12875 {"armv5texp", ARM_ARCH_V5TExP
, FPU_ARCH_VFP
},
12876 {"armv5tej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP
},
12877 {"armv6", ARM_ARCH_V6
, FPU_ARCH_VFP
},
12878 {"armv6j", ARM_ARCH_V6
, FPU_ARCH_VFP
},
12879 {"armv6k", ARM_ARCH_V6K
, FPU_ARCH_VFP
},
12880 {"armv6z", ARM_ARCH_V6Z
, FPU_ARCH_VFP
},
12881 {"armv6zk", ARM_ARCH_V6ZK
, FPU_ARCH_VFP
},
12882 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP
},
12883 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP
},
12887 /* ISA extensions in the co-processor space. */
12888 struct arm_arch_extension_table
12894 static struct arm_arch_extension_table arm_extensions
[] =
12896 {"maverick", ARM_CEXT_MAVERICK
},
12897 {"xscale", ARM_CEXT_XSCALE
},
12898 {"iwmmxt", ARM_CEXT_IWMMXT
},
12902 struct arm_fpu_option_table
12908 /* This list should, at a minimum, contain all the fpu names
12909 recognized by GCC. */
12910 static struct arm_fpu_option_table arm_fpus
[] =
12912 {"softfpa", FPU_NONE
},
12913 {"fpe", FPU_ARCH_FPE
},
12914 {"fpe2", FPU_ARCH_FPE
},
12915 {"fpe3", FPU_ARCH_FPA
}, /* Third release supports LFM/SFM. */
12916 {"fpa", FPU_ARCH_FPA
},
12917 {"fpa10", FPU_ARCH_FPA
},
12918 {"fpa11", FPU_ARCH_FPA
},
12919 {"arm7500fe", FPU_ARCH_FPA
},
12920 {"softvfp", FPU_ARCH_VFP
},
12921 {"softvfp+vfp", FPU_ARCH_VFP_V2
},
12922 {"vfp", FPU_ARCH_VFP_V2
},
12923 {"vfp9", FPU_ARCH_VFP_V2
},
12924 {"vfp10", FPU_ARCH_VFP_V2
},
12925 {"vfp10-r0", FPU_ARCH_VFP_V1
},
12926 {"vfpxd", FPU_ARCH_VFP_V1xD
},
12927 {"arm1020t", FPU_ARCH_VFP_V1
},
12928 {"arm1020e", FPU_ARCH_VFP_V2
},
12929 {"arm1136jfs", FPU_ARCH_VFP_V2
},
12930 {"arm1136jf-s", FPU_ARCH_VFP_V2
},
12931 {"maverick", FPU_ARCH_MAVERICK
},
12935 struct arm_float_abi_option_table
12941 static struct arm_float_abi_option_table arm_float_abis
[] =
12943 {"hard", ARM_FLOAT_ABI_HARD
},
12944 {"softfp", ARM_FLOAT_ABI_SOFTFP
},
12945 {"soft", ARM_FLOAT_ABI_SOFT
},
12949 struct arm_eabi_option_table
12952 unsigned int value
;
12956 /* We only know hot to output GNU and ver 3 (AAELF) formats. */
12957 static struct arm_eabi_option_table arm_eabis
[] =
12959 {"gnu", EF_ARM_EABI_UNKNOWN
},
12960 {"3", EF_ARM_EABI_VER3
},
12965 struct arm_long_option_table
12967 char * option
; /* Substring to match. */
12968 char * help
; /* Help information. */
12969 int (* func
) (char * subopt
); /* Function to decode sub-option. */
12970 char * deprecated
; /* If non-null, print this message. */
12974 arm_parse_extension (char * str
, int * opt_p
)
12976 while (str
!= NULL
&& *str
!= 0)
12978 struct arm_arch_extension_table
* opt
;
12984 as_bad (_("invalid architectural extension"));
12989 ext
= strchr (str
, '+');
12992 optlen
= ext
- str
;
12994 optlen
= strlen (str
);
12998 as_bad (_("missing architectural extension"));
13002 for (opt
= arm_extensions
; opt
->name
!= NULL
; opt
++)
13003 if (strncmp (opt
->name
, str
, optlen
) == 0)
13005 *opt_p
|= opt
->value
;
13009 if (opt
->name
== NULL
)
13011 as_bad (_("unknown architectural extnsion `%s'"), str
);
13022 arm_parse_cpu (char * str
)
13024 struct arm_cpu_option_table
* opt
;
13025 char * ext
= strchr (str
, '+');
13029 optlen
= ext
- str
;
13031 optlen
= strlen (str
);
13035 as_bad (_("missing cpu name `%s'"), str
);
13039 for (opt
= arm_cpus
; opt
->name
!= NULL
; opt
++)
13040 if (strncmp (opt
->name
, str
, optlen
) == 0)
13042 mcpu_cpu_opt
= opt
->value
;
13043 mcpu_fpu_opt
= opt
->default_fpu
;
13046 return arm_parse_extension (ext
, &mcpu_cpu_opt
);
13051 as_bad (_("unknown cpu `%s'"), str
);
13056 arm_parse_arch (char * str
)
13058 struct arm_arch_option_table
*opt
;
13059 char *ext
= strchr (str
, '+');
13063 optlen
= ext
- str
;
13065 optlen
= strlen (str
);
13069 as_bad (_("missing architecture name `%s'"), str
);
13074 for (opt
= arm_archs
; opt
->name
!= NULL
; opt
++)
13075 if (streq (opt
->name
, str
))
13077 march_cpu_opt
= opt
->value
;
13078 march_fpu_opt
= opt
->default_fpu
;
13081 return arm_parse_extension (ext
, &march_cpu_opt
);
13086 as_bad (_("unknown architecture `%s'\n"), str
);
13091 arm_parse_fpu (char * str
)
13093 struct arm_fpu_option_table
* opt
;
13095 for (opt
= arm_fpus
; opt
->name
!= NULL
; opt
++)
13096 if (streq (opt
->name
, str
))
13098 mfpu_opt
= opt
->value
;
13102 as_bad (_("unknown floating point format `%s'\n"), str
);
13107 arm_parse_float_abi (char * str
)
13109 struct arm_float_abi_option_table
* opt
;
13111 for (opt
= arm_float_abis
; opt
->name
!= NULL
; opt
++)
13112 if (streq (opt
->name
, str
))
13114 mfloat_abi_opt
= opt
->value
;
13118 as_bad (_("unknown floating point abi `%s'\n"), str
);
13124 arm_parse_eabi (char * str
)
13126 struct arm_eabi_option_table
*opt
;
13128 for (opt
= arm_eabis
; opt
->name
!= NULL
; opt
++)
13129 if (streq (opt
->name
, str
))
13131 meabi_flags
= opt
->value
;
13134 as_bad (_("unknown EABI `%s'\n"), str
);
13139 struct arm_long_option_table arm_long_opts
[] =
13141 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13142 arm_parse_cpu
, NULL
},
13143 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13144 arm_parse_arch
, NULL
},
13145 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13146 arm_parse_fpu
, NULL
},
13147 {"mfloat-abi=", N_("<abi>\t assemble for floating point ABI <abi>"),
13148 arm_parse_float_abi
, NULL
},
13150 {"meabi=", N_("<ver>\t assemble for eabi version <ver>"),
13151 arm_parse_eabi
, NULL
},
13153 {NULL
, NULL
, 0, NULL
}
13157 md_parse_option (int c
, char * arg
)
13159 struct arm_option_table
*opt
;
13160 struct arm_long_option_table
*lopt
;
13166 target_big_endian
= 1;
13172 target_big_endian
= 0;
13177 /* Listing option. Just ignore these, we don't support additional
13182 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
13184 if (c
== opt
->option
[0]
13185 && ((arg
== NULL
&& opt
->option
[1] == 0)
13186 || streq (arg
, opt
->option
+ 1)))
13188 #if WARN_DEPRECATED
13189 /* If the option is deprecated, tell the user. */
13190 if (opt
->deprecated
!= NULL
)
13191 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
,
13192 arg
? arg
: "", _(opt
->deprecated
));
13195 if (opt
->var
!= NULL
)
13196 *opt
->var
= opt
->value
;
13202 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
13204 /* These options are expected to have an argument. */
13205 if (c
== lopt
->option
[0]
13207 && strncmp (arg
, lopt
->option
+ 1,
13208 strlen (lopt
->option
+ 1)) == 0)
13210 #if WARN_DEPRECATED
13211 /* If the option is deprecated, tell the user. */
13212 if (lopt
->deprecated
!= NULL
)
13213 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
, arg
,
13214 _(lopt
->deprecated
));
13217 /* Call the sup-option parser. */
13218 return lopt
->func (arg
+ strlen (lopt
->option
) - 1);
13229 md_show_usage (FILE * fp
)
13231 struct arm_option_table
*opt
;
13232 struct arm_long_option_table
*lopt
;
13234 fprintf (fp
, _(" ARM-specific assembler options:\n"));
13236 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
13237 if (opt
->help
!= NULL
)
13238 fprintf (fp
, " -%-23s%s\n", opt
->option
, _(opt
->help
));
13240 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
13241 if (lopt
->help
!= NULL
)
13242 fprintf (fp
, " -%s%s\n", lopt
->option
, _(lopt
->help
));
13246 -EB assemble code for a big-endian cpu\n"));
13251 -EL assemble code for a little-endian cpu\n"));
13255 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13258 cons_fix_new_arm (fragS
* frag
,
13263 bfd_reloc_code_real_type type
;
13267 FIXME: @@ Should look at CPU word size. */
13271 type
= BFD_RELOC_8
;
13274 type
= BFD_RELOC_16
;
13278 type
= BFD_RELOC_32
;
13281 type
= BFD_RELOC_64
;
13285 fix_new_exp (frag
, where
, (int) size
, exp
, pcrel
, type
);
13288 /* A good place to do this, although this was probably not intended
13289 for this kind of use. We need to dump the literal pool before
13290 references are made to a null symbol pointer. */
13295 literal_pool
* pool
;
13297 for (pool
= list_of_pools
; pool
; pool
= pool
->next
)
13299 /* Put it at the end of the relevent section. */
13300 subseg_set (pool
->section
, pool
->sub_section
);
13302 arm_elf_change_section ();
13309 arm_start_line_hook (void)
13311 last_label_seen
= NULL
;
13315 arm_frob_label (symbolS
* sym
)
13317 last_label_seen
= sym
;
13319 ARM_SET_THUMB (sym
, thumb_mode
);
13321 #if defined OBJ_COFF || defined OBJ_ELF
13322 ARM_SET_INTERWORK (sym
, support_interwork
);
13325 /* Note - do not allow local symbols (.Lxxx) to be labeled
13326 as Thumb functions. This is because these labels, whilst
13327 they exist inside Thumb code, are not the entry points for
13328 possible ARM->Thumb calls. Also, these labels can be used
13329 as part of a computed goto or switch statement. eg gcc
13330 can generate code that looks like this:
13332 ldr r2, [pc, .Laaa]
13342 The first instruction loads the address of the jump table.
13343 The second instruction converts a table index into a byte offset.
13344 The third instruction gets the jump address out of the table.
13345 The fourth instruction performs the jump.
13347 If the address stored at .Laaa is that of a symbol which has the
13348 Thumb_Func bit set, then the linker will arrange for this address
13349 to have the bottom bit set, which in turn would mean that the
13350 address computation performed by the third instruction would end
13351 up with the bottom bit set. Since the ARM is capable of unaligned
13352 word loads, the instruction would then load the incorrect address
13353 out of the jump table, and chaos would ensue. */
13354 if (label_is_thumb_function_name
13355 && (S_GET_NAME (sym
)[0] != '.' || S_GET_NAME (sym
)[1] != 'L')
13356 && (bfd_get_section_flags (stdoutput
, now_seg
) & SEC_CODE
) != 0)
13358 /* When the address of a Thumb function is taken the bottom
13359 bit of that address should be set. This will allow
13360 interworking between Arm and Thumb functions to work
13363 THUMB_SET_FUNC (sym
, 1);
13365 label_is_thumb_function_name
= FALSE
;
13369 /* Adjust the symbol table. This marks Thumb symbols as distinct from
13373 arm_adjust_symtab (void)
13378 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
13380 if (ARM_IS_THUMB (sym
))
13382 if (THUMB_IS_FUNC (sym
))
13384 /* Mark the symbol as a Thumb function. */
13385 if ( S_GET_STORAGE_CLASS (sym
) == C_STAT
13386 || S_GET_STORAGE_CLASS (sym
) == C_LABEL
) /* This can happen! */
13387 S_SET_STORAGE_CLASS (sym
, C_THUMBSTATFUNC
);
13389 else if (S_GET_STORAGE_CLASS (sym
) == C_EXT
)
13390 S_SET_STORAGE_CLASS (sym
, C_THUMBEXTFUNC
);
13392 as_bad (_("%s: unexpected function type: %d"),
13393 S_GET_NAME (sym
), S_GET_STORAGE_CLASS (sym
));
13395 else switch (S_GET_STORAGE_CLASS (sym
))
13398 S_SET_STORAGE_CLASS (sym
, C_THUMBEXT
);
13401 S_SET_STORAGE_CLASS (sym
, C_THUMBSTAT
);
13404 S_SET_STORAGE_CLASS (sym
, C_THUMBLABEL
);
13412 if (ARM_IS_INTERWORK (sym
))
13413 coffsymbol (symbol_get_bfdsym (sym
))->native
->u
.syment
.n_flags
= 0xFF;
13420 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
13422 if (ARM_IS_THUMB (sym
))
13424 elf_symbol_type
* elf_sym
;
13426 elf_sym
= elf_symbol (symbol_get_bfdsym (sym
));
13427 bind
= ELF_ST_BIND (elf_sym
);
13429 /* If it's a .thumb_func, declare it as so,
13430 otherwise tag label as .code 16. */
13431 if (THUMB_IS_FUNC (sym
))
13432 elf_sym
->internal_elf_sym
.st_info
=
13433 ELF_ST_INFO (bind
, STT_ARM_TFUNC
);
13435 elf_sym
->internal_elf_sym
.st_info
=
13436 ELF_ST_INFO (bind
, STT_ARM_16BIT
);
13443 arm_data_in_code (void)
13445 if (thumb_mode
&& ! strncmp (input_line_pointer
+ 1, "data:", 5))
13447 *input_line_pointer
= '/';
13448 input_line_pointer
+= 5;
13449 *input_line_pointer
= 0;
13457 arm_canonicalize_symbol_name (char * name
)
13461 if (thumb_mode
&& (len
= strlen (name
)) > 5
13462 && streq (name
+ len
- 5, "/data"))
13463 *(name
+ len
- 5) = 0;
13468 #if defined OBJ_COFF || defined OBJ_ELF
13470 arm_validate_fix (fixS
* fixP
)
13472 /* If the destination of the branch is a defined symbol which does not have
13473 the THUMB_FUNC attribute, then we must be calling a function which has
13474 the (interfacearm) attribute. We look for the Thumb entry point to that
13475 function and change the branch to refer to that function instead. */
13476 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
13477 && fixP
->fx_addsy
!= NULL
13478 && S_IS_DEFINED (fixP
->fx_addsy
)
13479 && ! THUMB_IS_FUNC (fixP
->fx_addsy
))
13481 fixP
->fx_addsy
= find_real_start (fixP
->fx_addsy
);
13487 arm_force_relocation (struct fix
* fixp
)
13489 #if defined (OBJ_COFF) && defined (TE_PE)
13490 if (fixp
->fx_r_type
== BFD_RELOC_RVA
)
13494 if (fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
13495 || fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
13496 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
13497 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
)
13501 /* Resolve these relocations even if the symbol is extern or weak. */
13502 if (fixp
->fx_r_type
== BFD_RELOC_ARM_IMMEDIATE
13503 || fixp
->fx_r_type
== BFD_RELOC_ARM_OFFSET_IMM
13504 || fixp
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
13507 return generic_force_reloc (fixp
);
13511 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
13512 local labels from being added to the output symbol table when they
13513 are used with the ADRL pseudo op. The ADRL relocation should always
13514 be resolved before the binbary is emitted, so it is safe to say that
13515 it is adjustable. */
13518 arm_fix_adjustable (fixS
* fixP
)
13520 if (fixP
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
13527 /* Relocations against Thumb function names must be left unadjusted,
13528 so that the linker can use this information to correctly set the
13529 bottom bit of their addresses. The MIPS version of this function
13530 also prevents relocations that are mips-16 specific, but I do not
13531 know why it does this.
13534 There is one other problem that ought to be addressed here, but
13535 which currently is not: Taking the address of a label (rather
13536 than a function) and then later jumping to that address. Such
13537 addresses also ought to have their bottom bit set (assuming that
13538 they reside in Thumb code), but at the moment they will not. */
13541 arm_fix_adjustable (fixS
* fixP
)
13543 if (fixP
->fx_addsy
== NULL
)
13546 if (THUMB_IS_FUNC (fixP
->fx_addsy
)
13547 && fixP
->fx_subsy
== NULL
)
13550 /* We need the symbol name for the VTABLE entries. */
13551 if ( fixP
->fx_r_type
== BFD_RELOC_VTABLE_INHERIT
13552 || fixP
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
13555 /* Don't allow symbols to be discarded on GOT related relocs. */
13556 if (fixP
->fx_r_type
== BFD_RELOC_ARM_PLT32
13557 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOT32
13558 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOTOFF
13559 || fixP
->fx_r_type
== BFD_RELOC_ARM_TARGET2
)
13566 elf32_arm_target_format (void)
13569 return (target_big_endian
13570 ? "elf32-bigarm-symbian"
13571 : "elf32-littlearm-symbian");
13573 if (target_big_endian
)
13576 return "elf32-bigarm-oabi";
13578 return "elf32-bigarm";
13583 return "elf32-littlearm-oabi";
13585 return "elf32-littlearm";
13591 armelf_frob_symbol (symbolS
* symp
,
13594 elf_frob_symbol (symp
, puntp
);
13598 s_arm_elf_cons (int nbytes
)
13602 #ifdef md_flush_pending_output
13603 md_flush_pending_output ();
13606 if (is_it_end_of_statement ())
13608 demand_empty_rest_of_line ();
13612 #ifdef md_cons_align
13613 md_cons_align (nbytes
);
13616 mapping_state (MAP_DATA
);
13619 bfd_reloc_code_real_type reloc
;
13621 expression (& exp
);
13623 if (exp
.X_op
== O_symbol
13624 && * input_line_pointer
== '('
13625 && (reloc
= arm_parse_reloc ()) != BFD_RELOC_UNUSED
)
13627 reloc_howto_type
*howto
= bfd_reloc_type_lookup (stdoutput
, reloc
);
13628 int size
= bfd_get_reloc_size (howto
);
13631 as_bad ("%s relocations do not fit in %d bytes",
13632 howto
->name
, nbytes
);
13635 char *p
= frag_more ((int) nbytes
);
13636 int offset
= nbytes
- size
;
13638 fix_new_exp (frag_now
, p
- frag_now
->fr_literal
+ offset
, size
,
13643 emit_expr (&exp
, (unsigned int) nbytes
);
13645 while (*input_line_pointer
++ == ',');
13647 /* Put terminator back into stream. */
13648 input_line_pointer
--;
13649 demand_empty_rest_of_line ();
13653 /* Parse a .rel31 directive. */
13656 s_arm_rel31 (int ignored ATTRIBUTE_UNUSED
)
13662 SKIP_WHITESPACE ();
13665 if (*input_line_pointer
== '1')
13666 highbit
= 0x80000000;
13667 else if (*input_line_pointer
!= '0')
13668 as_bad (_("expected 0 or 1"));
13670 input_line_pointer
++;
13671 SKIP_WHITESPACE ();
13672 if (*input_line_pointer
!= ',')
13673 as_bad (_("missing comma"));
13674 input_line_pointer
++;
13676 #ifdef md_flush_pending_output
13677 md_flush_pending_output ();
13680 #ifdef md_cons_align
13684 mapping_state (MAP_DATA
);
13689 md_number_to_chars (p
, highbit
, 4);
13690 fix_new_arm (frag_now
, p
- frag_now
->fr_literal
, 4, &exp
, 1,
13691 BFD_RELOC_ARM_PREL31
);
13693 demand_empty_rest_of_line ();
13696 #endif /* OBJ_ELF */
13698 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
13699 of an rs_align_code fragment. */
13702 arm_handle_align (fragS
* fragP
)
13704 static char const arm_noop
[4] = { 0x00, 0x00, 0xa0, 0xe1 };
13705 static char const thumb_noop
[2] = { 0xc0, 0x46 };
13706 static char const arm_bigend_noop
[4] = { 0xe1, 0xa0, 0x00, 0x00 };
13707 static char const thumb_bigend_noop
[2] = { 0x46, 0xc0 };
13709 int bytes
, fix
, noop_size
;
13713 if (fragP
->fr_type
!= rs_align_code
)
13716 bytes
= fragP
->fr_next
->fr_address
- fragP
->fr_address
- fragP
->fr_fix
;
13717 p
= fragP
->fr_literal
+ fragP
->fr_fix
;
13720 if (bytes
> MAX_MEM_FOR_RS_ALIGN_CODE
)
13721 bytes
&= MAX_MEM_FOR_RS_ALIGN_CODE
;
13723 if (fragP
->tc_frag_data
)
13725 if (target_big_endian
)
13726 noop
= thumb_bigend_noop
;
13729 noop_size
= sizeof (thumb_noop
);
13733 if (target_big_endian
)
13734 noop
= arm_bigend_noop
;
13737 noop_size
= sizeof (arm_noop
);
13740 if (bytes
& (noop_size
- 1))
13742 fix
= bytes
& (noop_size
- 1);
13743 memset (p
, 0, fix
);
13748 while (bytes
>= noop_size
)
13750 memcpy (p
, noop
, noop_size
);
13752 bytes
-= noop_size
;
13756 fragP
->fr_fix
+= fix
;
13757 fragP
->fr_var
= noop_size
;
13760 /* Called from md_do_align. Used to create an alignment
13761 frag in a code section. */
13764 arm_frag_align_code (int n
, int max
)
13768 /* We assume that there will never be a requirement
13769 to support alignments greater than 32 bytes. */
13770 if (max
> MAX_MEM_FOR_RS_ALIGN_CODE
)
13771 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
13773 p
= frag_var (rs_align_code
,
13774 MAX_MEM_FOR_RS_ALIGN_CODE
,
13776 (relax_substateT
) max
,
13783 /* Perform target specific initialisation of a frag. */
13786 arm_init_frag (fragS
* fragP
)
13788 /* Record whether this frag is in an ARM or a THUMB area. */
13789 fragP
->tc_frag_data
= thumb_mode
;
13792 /* This table describes all the machine specific pseudo-ops the assembler
13793 has to support. The fields are:
13794 pseudo-op name without dot
13795 function to call to execute this pseudo-op
13796 Integer arg to pass to the function. */
13798 const pseudo_typeS md_pseudo_table
[] =
13800 /* Never called because '.req' does not start a line. */
13801 { "req", s_req
, 0 },
13802 { "unreq", s_unreq
, 0 },
13803 { "bss", s_bss
, 0 },
13804 { "align", s_align
, 0 },
13805 { "arm", s_arm
, 0 },
13806 { "thumb", s_thumb
, 0 },
13807 { "code", s_code
, 0 },
13808 { "force_thumb", s_force_thumb
, 0 },
13809 { "thumb_func", s_thumb_func
, 0 },
13810 { "thumb_set", s_thumb_set
, 0 },
13811 { "even", s_even
, 0 },
13812 { "ltorg", s_ltorg
, 0 },
13813 { "pool", s_ltorg
, 0 },
13815 { "word", s_arm_elf_cons
, 4 },
13816 { "long", s_arm_elf_cons
, 4 },
13817 { "rel31", s_arm_rel31
, 0 },
13819 { "word", cons
, 4},
13821 { "extend", float_cons
, 'x' },
13822 { "ldouble", float_cons
, 'x' },
13823 { "packed", float_cons
, 'p' },