1 /* tc-arm.c -- Assemble for the ARM
2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
3 Free Software Foundation, Inc.
4 Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
5 Modified by David Taylor (dtaylor@armltd.co.uk)
6 Cirrus coprocessor mods by Aldy Hernandez (aldyh@redhat.com)
7 Cirrus coprocessor fixes by Petko Manolov (petkan@nucleusys.com)
8 Cirrus coprocessor fixes by Vladimir Ivanov (vladitx@nucleusys.com)
10 This file is part of GAS, the GNU Assembler.
12 GAS is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2, or (at your option)
17 GAS is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with GAS; see the file COPYING. If not, write to the Free
24 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
30 #include "safe-ctype.h"
32 /* Need TARGET_CPU. */
39 #include "opcode/arm.h"
43 #include "dwarf2dbg.h"
46 /* XXX Set this to 1 after the next binutils release */
47 #define WARN_DEPRECATED 0
56 /* Types of processor to assemble for. */
57 #define ARM_1 ARM_ARCH_V1
58 #define ARM_2 ARM_ARCH_V2
59 #define ARM_3 ARM_ARCH_V2S
60 #define ARM_250 ARM_ARCH_V2S
61 #define ARM_6 ARM_ARCH_V3
62 #define ARM_7 ARM_ARCH_V3
63 #define ARM_8 ARM_ARCH_V4
64 #define ARM_9 ARM_ARCH_V4T
65 #define ARM_STRONG ARM_ARCH_V4
66 #define ARM_CPU_MASK 0x0000000f /* XXX? */
69 #if defined __XSCALE__
70 #define CPU_DEFAULT (ARM_ARCH_XSCALE)
73 #define CPU_DEFAULT (ARM_ARCH_V5T)
75 #define CPU_DEFAULT ARM_ANY
81 #define FPU_DEFAULT FPU_ARCH_FPA
86 #define FPU_DEFAULT FPU_ARCH_VFP /* Soft-float, but VFP order. */
88 /* Legacy a.out format. */
89 #define FPU_DEFAULT FPU_ARCH_FPA /* Soft-float, but FPA order. */
93 /* For backwards compatibility we default to the FPA. */
95 #define FPU_DEFAULT FPU_ARCH_FPA
98 #define streq(a, b) (strcmp (a, b) == 0)
99 #define skip_whitespace(str) while (*(str) == ' ') ++(str)
101 static unsigned long cpu_variant
;
102 static int target_oabi
= 0;
104 /* Flags stored in private area of BFD structure. */
105 static int uses_apcs_26
= FALSE
;
106 static int atpcs
= FALSE
;
107 static int support_interwork
= FALSE
;
108 static int uses_apcs_float
= FALSE
;
109 static int pic_code
= FALSE
;
111 /* Variables that we set while parsing command-line options. Once all
112 options have been read we re-process these values to set the real
114 static int legacy_cpu
= -1;
115 static int legacy_fpu
= -1;
117 static int mcpu_cpu_opt
= -1;
118 static int mcpu_fpu_opt
= -1;
119 static int march_cpu_opt
= -1;
120 static int march_fpu_opt
= -1;
121 static int mfpu_opt
= -1;
122 static int mfloat_abi_opt
= -1;
124 static int meabi_flags
= EF_ARM_EABI_UNKNOWN
;
127 /* This array holds the chars that always start a comment. If the
128 pre-processor is disabled, these aren't very useful. */
129 const char comment_chars
[] = "@";
131 /* This array holds the chars that only start a comment at the beginning of
132 a line. If the line seems to have the form '# 123 filename'
133 .line and .file directives will appear in the pre-processed output. */
134 /* Note that input_file.c hand checks for '#' at the beginning of the
135 first line of the input file. This is because the compiler outputs
136 #NO_APP at the beginning of its output. */
137 /* Also note that comments like this one will always work. */
138 const char line_comment_chars
[] = "#";
140 const char line_separator_chars
[] = ";";
142 /* Chars that can be used to separate mant
143 from exp in floating point numbers. */
144 const char EXP_CHARS
[] = "eE";
146 /* Chars that mean this number is a floating point constant. */
150 const char FLT_CHARS
[] = "rRsSfFdDxXeEpP";
152 /* Prefix characters that indicate the start of an immediate
154 #define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
157 /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
158 symbolS
* GOT_symbol
;
161 /* Size of relocation record. */
162 const int md_reloc_size
= 8;
164 /* 0: assemble for ARM,
165 1: assemble for Thumb,
166 2: assemble for Thumb even though target CPU does not support thumb
168 static int thumb_mode
= 0;
170 typedef struct arm_fix
178 unsigned long instruction
;
182 bfd_reloc_code_real_type type
;
199 struct asm_shift_properties
201 enum asm_shift_index index
;
202 unsigned long bit_field
;
203 unsigned int allows_0
: 1;
204 unsigned int allows_32
: 1;
207 static const struct asm_shift_properties shift_properties
[] =
209 { SHIFT_LSL
, 0, 1, 0},
210 { SHIFT_LSR
, 0x20, 0, 1},
211 { SHIFT_ASR
, 0x40, 0, 1},
212 { SHIFT_ROR
, 0x60, 0, 0},
213 { SHIFT_RRX
, 0x60, 0, 0}
216 struct asm_shift_name
219 const struct asm_shift_properties
* properties
;
222 static const struct asm_shift_name shift_names
[] =
224 { "asl", shift_properties
+ SHIFT_LSL
},
225 { "lsl", shift_properties
+ SHIFT_LSL
},
226 { "lsr", shift_properties
+ SHIFT_LSR
},
227 { "asr", shift_properties
+ SHIFT_ASR
},
228 { "ror", shift_properties
+ SHIFT_ROR
},
229 { "rrx", shift_properties
+ SHIFT_RRX
},
230 { "ASL", shift_properties
+ SHIFT_LSL
},
231 { "LSL", shift_properties
+ SHIFT_LSL
},
232 { "LSR", shift_properties
+ SHIFT_LSR
},
233 { "ASR", shift_properties
+ SHIFT_ASR
},
234 { "ROR", shift_properties
+ SHIFT_ROR
},
235 { "RRX", shift_properties
+ SHIFT_RRX
}
238 /* Any kind of shift is accepted. */
239 #define NO_SHIFT_RESTRICT 1
240 /* The shift operand must be an immediate value, not a register. */
241 #define SHIFT_IMMEDIATE 0
242 /* The shift must be LSL or ASR and the operand must be an immediate. */
243 #define SHIFT_LSL_OR_ASR_IMMEDIATE 2
244 /* The shift must be ASR and the operand must be an immediate. */
245 #define SHIFT_ASR_IMMEDIATE 3
246 /* The shift must be LSL and the operand must be an immediate. */
247 #define SHIFT_LSL_IMMEDIATE 4
249 #define NUM_FLOAT_VALS 8
251 const char * fp_const
[] =
253 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
256 /* Number of littlenums required to hold an extended precision number. */
257 #define MAX_LITTLENUMS 6
259 LITTLENUM_TYPE fp_values
[NUM_FLOAT_VALS
][MAX_LITTLENUMS
];
264 /* Whether a Co-processor load/store operation accepts write-back forms. */
273 #define CP_T_X 0x00008000
274 #define CP_T_Y 0x00400000
275 #define CP_T_Pre 0x01000000
276 #define CP_T_UD 0x00800000
277 #define CP_T_WB 0x00200000
279 #define CONDS_BIT 0x00100000
280 #define LOAD_BIT 0x00100000
282 #define DOUBLE_LOAD_FLAG 0x00000001
286 const char * template;
290 #define COND_ALWAYS 0xe0000000
291 #define COND_MASK 0xf0000000
293 static const struct asm_cond conds
[] =
297 {"cs", 0x20000000}, {"hs", 0x20000000},
298 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
315 const char *template;
320 /* The bit that distinguishes CPSR and SPSR. */
321 #define SPSR_BIT (1 << 22)
323 /* How many bits to shift the PSR_xxx bits up by. */
326 #define PSR_c (1 << 0)
327 #define PSR_x (1 << 1)
328 #define PSR_s (1 << 2)
329 #define PSR_f (1 << 3)
331 static const struct asm_psr psrs
[] =
333 {"CPSR", TRUE
, PSR_c
| PSR_f
},
334 {"CPSR_all", TRUE
, PSR_c
| PSR_f
},
335 {"SPSR", FALSE
, PSR_c
| PSR_f
},
336 {"SPSR_all", FALSE
, PSR_c
| PSR_f
},
337 {"CPSR_flg", TRUE
, PSR_f
},
338 {"CPSR_f", TRUE
, PSR_f
},
339 {"SPSR_flg", FALSE
, PSR_f
},
340 {"SPSR_f", FALSE
, PSR_f
},
341 {"CPSR_c", TRUE
, PSR_c
},
342 {"CPSR_ctl", TRUE
, PSR_c
},
343 {"SPSR_c", FALSE
, PSR_c
},
344 {"SPSR_ctl", FALSE
, PSR_c
},
345 {"CPSR_x", TRUE
, PSR_x
},
346 {"CPSR_s", TRUE
, PSR_s
},
347 {"SPSR_x", FALSE
, PSR_x
},
348 {"SPSR_s", FALSE
, PSR_s
},
349 /* Combinations of flags. */
350 {"CPSR_fs", TRUE
, PSR_f
| PSR_s
},
351 {"CPSR_fx", TRUE
, PSR_f
| PSR_x
},
352 {"CPSR_fc", TRUE
, PSR_f
| PSR_c
},
353 {"CPSR_sf", TRUE
, PSR_s
| PSR_f
},
354 {"CPSR_sx", TRUE
, PSR_s
| PSR_x
},
355 {"CPSR_sc", TRUE
, PSR_s
| PSR_c
},
356 {"CPSR_xf", TRUE
, PSR_x
| PSR_f
},
357 {"CPSR_xs", TRUE
, PSR_x
| PSR_s
},
358 {"CPSR_xc", TRUE
, PSR_x
| PSR_c
},
359 {"CPSR_cf", TRUE
, PSR_c
| PSR_f
},
360 {"CPSR_cs", TRUE
, PSR_c
| PSR_s
},
361 {"CPSR_cx", TRUE
, PSR_c
| PSR_x
},
362 {"CPSR_fsx", TRUE
, PSR_f
| PSR_s
| PSR_x
},
363 {"CPSR_fsc", TRUE
, PSR_f
| PSR_s
| PSR_c
},
364 {"CPSR_fxs", TRUE
, PSR_f
| PSR_x
| PSR_s
},
365 {"CPSR_fxc", TRUE
, PSR_f
| PSR_x
| PSR_c
},
366 {"CPSR_fcs", TRUE
, PSR_f
| PSR_c
| PSR_s
},
367 {"CPSR_fcx", TRUE
, PSR_f
| PSR_c
| PSR_x
},
368 {"CPSR_sfx", TRUE
, PSR_s
| PSR_f
| PSR_x
},
369 {"CPSR_sfc", TRUE
, PSR_s
| PSR_f
| PSR_c
},
370 {"CPSR_sxf", TRUE
, PSR_s
| PSR_x
| PSR_f
},
371 {"CPSR_sxc", TRUE
, PSR_s
| PSR_x
| PSR_c
},
372 {"CPSR_scf", TRUE
, PSR_s
| PSR_c
| PSR_f
},
373 {"CPSR_scx", TRUE
, PSR_s
| PSR_c
| PSR_x
},
374 {"CPSR_xfs", TRUE
, PSR_x
| PSR_f
| PSR_s
},
375 {"CPSR_xfc", TRUE
, PSR_x
| PSR_f
| PSR_c
},
376 {"CPSR_xsf", TRUE
, PSR_x
| PSR_s
| PSR_f
},
377 {"CPSR_xsc", TRUE
, PSR_x
| PSR_s
| PSR_c
},
378 {"CPSR_xcf", TRUE
, PSR_x
| PSR_c
| PSR_f
},
379 {"CPSR_xcs", TRUE
, PSR_x
| PSR_c
| PSR_s
},
380 {"CPSR_cfs", TRUE
, PSR_c
| PSR_f
| PSR_s
},
381 {"CPSR_cfx", TRUE
, PSR_c
| PSR_f
| PSR_x
},
382 {"CPSR_csf", TRUE
, PSR_c
| PSR_s
| PSR_f
},
383 {"CPSR_csx", TRUE
, PSR_c
| PSR_s
| PSR_x
},
384 {"CPSR_cxf", TRUE
, PSR_c
| PSR_x
| PSR_f
},
385 {"CPSR_cxs", TRUE
, PSR_c
| PSR_x
| PSR_s
},
386 {"CPSR_fsxc", TRUE
, PSR_f
| PSR_s
| PSR_x
| PSR_c
},
387 {"CPSR_fscx", TRUE
, PSR_f
| PSR_s
| PSR_c
| PSR_x
},
388 {"CPSR_fxsc", TRUE
, PSR_f
| PSR_x
| PSR_s
| PSR_c
},
389 {"CPSR_fxcs", TRUE
, PSR_f
| PSR_x
| PSR_c
| PSR_s
},
390 {"CPSR_fcsx", TRUE
, PSR_f
| PSR_c
| PSR_s
| PSR_x
},
391 {"CPSR_fcxs", TRUE
, PSR_f
| PSR_c
| PSR_x
| PSR_s
},
392 {"CPSR_sfxc", TRUE
, PSR_s
| PSR_f
| PSR_x
| PSR_c
},
393 {"CPSR_sfcx", TRUE
, PSR_s
| PSR_f
| PSR_c
| PSR_x
},
394 {"CPSR_sxfc", TRUE
, PSR_s
| PSR_x
| PSR_f
| PSR_c
},
395 {"CPSR_sxcf", TRUE
, PSR_s
| PSR_x
| PSR_c
| PSR_f
},
396 {"CPSR_scfx", TRUE
, PSR_s
| PSR_c
| PSR_f
| PSR_x
},
397 {"CPSR_scxf", TRUE
, PSR_s
| PSR_c
| PSR_x
| PSR_f
},
398 {"CPSR_xfsc", TRUE
, PSR_x
| PSR_f
| PSR_s
| PSR_c
},
399 {"CPSR_xfcs", TRUE
, PSR_x
| PSR_f
| PSR_c
| PSR_s
},
400 {"CPSR_xsfc", TRUE
, PSR_x
| PSR_s
| PSR_f
| PSR_c
},
401 {"CPSR_xscf", TRUE
, PSR_x
| PSR_s
| PSR_c
| PSR_f
},
402 {"CPSR_xcfs", TRUE
, PSR_x
| PSR_c
| PSR_f
| PSR_s
},
403 {"CPSR_xcsf", TRUE
, PSR_x
| PSR_c
| PSR_s
| PSR_f
},
404 {"CPSR_cfsx", TRUE
, PSR_c
| PSR_f
| PSR_s
| PSR_x
},
405 {"CPSR_cfxs", TRUE
, PSR_c
| PSR_f
| PSR_x
| PSR_s
},
406 {"CPSR_csfx", TRUE
, PSR_c
| PSR_s
| PSR_f
| PSR_x
},
407 {"CPSR_csxf", TRUE
, PSR_c
| PSR_s
| PSR_x
| PSR_f
},
408 {"CPSR_cxfs", TRUE
, PSR_c
| PSR_x
| PSR_f
| PSR_s
},
409 {"CPSR_cxsf", TRUE
, PSR_c
| PSR_x
| PSR_s
| PSR_f
},
410 {"SPSR_fs", FALSE
, PSR_f
| PSR_s
},
411 {"SPSR_fx", FALSE
, PSR_f
| PSR_x
},
412 {"SPSR_fc", FALSE
, PSR_f
| PSR_c
},
413 {"SPSR_sf", FALSE
, PSR_s
| PSR_f
},
414 {"SPSR_sx", FALSE
, PSR_s
| PSR_x
},
415 {"SPSR_sc", FALSE
, PSR_s
| PSR_c
},
416 {"SPSR_xf", FALSE
, PSR_x
| PSR_f
},
417 {"SPSR_xs", FALSE
, PSR_x
| PSR_s
},
418 {"SPSR_xc", FALSE
, PSR_x
| PSR_c
},
419 {"SPSR_cf", FALSE
, PSR_c
| PSR_f
},
420 {"SPSR_cs", FALSE
, PSR_c
| PSR_s
},
421 {"SPSR_cx", FALSE
, PSR_c
| PSR_x
},
422 {"SPSR_fsx", FALSE
, PSR_f
| PSR_s
| PSR_x
},
423 {"SPSR_fsc", FALSE
, PSR_f
| PSR_s
| PSR_c
},
424 {"SPSR_fxs", FALSE
, PSR_f
| PSR_x
| PSR_s
},
425 {"SPSR_fxc", FALSE
, PSR_f
| PSR_x
| PSR_c
},
426 {"SPSR_fcs", FALSE
, PSR_f
| PSR_c
| PSR_s
},
427 {"SPSR_fcx", FALSE
, PSR_f
| PSR_c
| PSR_x
},
428 {"SPSR_sfx", FALSE
, PSR_s
| PSR_f
| PSR_x
},
429 {"SPSR_sfc", FALSE
, PSR_s
| PSR_f
| PSR_c
},
430 {"SPSR_sxf", FALSE
, PSR_s
| PSR_x
| PSR_f
},
431 {"SPSR_sxc", FALSE
, PSR_s
| PSR_x
| PSR_c
},
432 {"SPSR_scf", FALSE
, PSR_s
| PSR_c
| PSR_f
},
433 {"SPSR_scx", FALSE
, PSR_s
| PSR_c
| PSR_x
},
434 {"SPSR_xfs", FALSE
, PSR_x
| PSR_f
| PSR_s
},
435 {"SPSR_xfc", FALSE
, PSR_x
| PSR_f
| PSR_c
},
436 {"SPSR_xsf", FALSE
, PSR_x
| PSR_s
| PSR_f
},
437 {"SPSR_xsc", FALSE
, PSR_x
| PSR_s
| PSR_c
},
438 {"SPSR_xcf", FALSE
, PSR_x
| PSR_c
| PSR_f
},
439 {"SPSR_xcs", FALSE
, PSR_x
| PSR_c
| PSR_s
},
440 {"SPSR_cfs", FALSE
, PSR_c
| PSR_f
| PSR_s
},
441 {"SPSR_cfx", FALSE
, PSR_c
| PSR_f
| PSR_x
},
442 {"SPSR_csf", FALSE
, PSR_c
| PSR_s
| PSR_f
},
443 {"SPSR_csx", FALSE
, PSR_c
| PSR_s
| PSR_x
},
444 {"SPSR_cxf", FALSE
, PSR_c
| PSR_x
| PSR_f
},
445 {"SPSR_cxs", FALSE
, PSR_c
| PSR_x
| PSR_s
},
446 {"SPSR_fsxc", FALSE
, PSR_f
| PSR_s
| PSR_x
| PSR_c
},
447 {"SPSR_fscx", FALSE
, PSR_f
| PSR_s
| PSR_c
| PSR_x
},
448 {"SPSR_fxsc", FALSE
, PSR_f
| PSR_x
| PSR_s
| PSR_c
},
449 {"SPSR_fxcs", FALSE
, PSR_f
| PSR_x
| PSR_c
| PSR_s
},
450 {"SPSR_fcsx", FALSE
, PSR_f
| PSR_c
| PSR_s
| PSR_x
},
451 {"SPSR_fcxs", FALSE
, PSR_f
| PSR_c
| PSR_x
| PSR_s
},
452 {"SPSR_sfxc", FALSE
, PSR_s
| PSR_f
| PSR_x
| PSR_c
},
453 {"SPSR_sfcx", FALSE
, PSR_s
| PSR_f
| PSR_c
| PSR_x
},
454 {"SPSR_sxfc", FALSE
, PSR_s
| PSR_x
| PSR_f
| PSR_c
},
455 {"SPSR_sxcf", FALSE
, PSR_s
| PSR_x
| PSR_c
| PSR_f
},
456 {"SPSR_scfx", FALSE
, PSR_s
| PSR_c
| PSR_f
| PSR_x
},
457 {"SPSR_scxf", FALSE
, PSR_s
| PSR_c
| PSR_x
| PSR_f
},
458 {"SPSR_xfsc", FALSE
, PSR_x
| PSR_f
| PSR_s
| PSR_c
},
459 {"SPSR_xfcs", FALSE
, PSR_x
| PSR_f
| PSR_c
| PSR_s
},
460 {"SPSR_xsfc", FALSE
, PSR_x
| PSR_s
| PSR_f
| PSR_c
},
461 {"SPSR_xscf", FALSE
, PSR_x
| PSR_s
| PSR_c
| PSR_f
},
462 {"SPSR_xcfs", FALSE
, PSR_x
| PSR_c
| PSR_f
| PSR_s
},
463 {"SPSR_xcsf", FALSE
, PSR_x
| PSR_c
| PSR_s
| PSR_f
},
464 {"SPSR_cfsx", FALSE
, PSR_c
| PSR_f
| PSR_s
| PSR_x
},
465 {"SPSR_cfxs", FALSE
, PSR_c
| PSR_f
| PSR_x
| PSR_s
},
466 {"SPSR_csfx", FALSE
, PSR_c
| PSR_s
| PSR_f
| PSR_x
},
467 {"SPSR_csxf", FALSE
, PSR_c
| PSR_s
| PSR_x
| PSR_f
},
468 {"SPSR_cxfs", FALSE
, PSR_c
| PSR_x
| PSR_f
| PSR_s
},
469 {"SPSR_cxsf", FALSE
, PSR_c
| PSR_x
| PSR_s
| PSR_f
},
476 IWMMXT_REG_WR_OR_WC
= 2,
480 enum iwmmxt_insn_type
503 VFP_REG_Dd
, VFP_REG_Dm
, VFP_REG_Dn
508 VFP_REG_Sd
, VFP_REG_Sm
, VFP_REG_Sn
513 VFP_LDSTMIA
, VFP_LDSTMDB
, VFP_LDSTMIAX
, VFP_LDSTMDBX
516 /* VFP system registers. */
523 static const struct vfp_reg vfp_regs
[] =
525 {"fpsid", 0x00000000},
526 {"FPSID", 0x00000000},
527 {"fpscr", 0x00010000},
528 {"FPSCR", 0x00010000},
529 {"fpexc", 0x00080000},
530 {"FPEXC", 0x00080000}
533 /* Structure for a hash table entry for a register. */
541 /* Some well known registers that we refer to directly elsewhere. */
546 #define wr_register(reg) ((reg ^ WR_PREFIX) >= 0 && (reg ^ WR_PREFIX) <= 15)
547 #define wc_register(reg) ((reg ^ WC_PREFIX) >= 0 && (reg ^ WC_PREFIX) <= 15)
548 #define wcg_register(reg) ((reg ^ WC_PREFIX) >= 8 && (reg ^ WC_PREFIX) <= 11)
550 /* These are the standard names. Users can add aliases with .req.
551 and delete them with .unreq. */
553 /* Integer Register Numbers. */
554 static const struct reg_entry rn_table
[] =
556 {"r0", 0, TRUE
}, {"r1", 1, TRUE
}, {"r2", 2, TRUE
}, {"r3", 3, TRUE
},
557 {"r4", 4, TRUE
}, {"r5", 5, TRUE
}, {"r6", 6, TRUE
}, {"r7", 7, TRUE
},
558 {"r8", 8, TRUE
}, {"r9", 9, TRUE
}, {"r10", 10, TRUE
}, {"r11", 11, TRUE
},
559 {"r12", 12, TRUE
}, {"r13", REG_SP
, TRUE
}, {"r14", REG_LR
, TRUE
}, {"r15", REG_PC
, TRUE
},
560 /* ATPCS Synonyms. */
561 {"a1", 0, TRUE
}, {"a2", 1, TRUE
}, {"a3", 2, TRUE
}, {"a4", 3, TRUE
},
562 {"v1", 4, TRUE
}, {"v2", 5, TRUE
}, {"v3", 6, TRUE
}, {"v4", 7, TRUE
},
563 {"v5", 8, TRUE
}, {"v6", 9, TRUE
}, {"v7", 10, TRUE
}, {"v8", 11, TRUE
},
564 /* Well-known aliases. */
565 {"wr", 7, TRUE
}, {"sb", 9, TRUE
}, {"sl", 10, TRUE
}, {"fp", 11, TRUE
},
566 {"ip", 12, TRUE
}, {"sp", REG_SP
, TRUE
}, {"lr", REG_LR
, TRUE
}, {"pc", REG_PC
, TRUE
},
570 #define WR_PREFIX 0x200
571 #define WC_PREFIX 0x400
573 static const struct reg_entry iwmmxt_table
[] =
575 /* Intel Wireless MMX technology register names. */
576 { "wr0", 0x0 | WR_PREFIX
, TRUE
}, {"wr1", 0x1 | WR_PREFIX
, TRUE
},
577 { "wr2", 0x2 | WR_PREFIX
, TRUE
}, {"wr3", 0x3 | WR_PREFIX
, TRUE
},
578 { "wr4", 0x4 | WR_PREFIX
, TRUE
}, {"wr5", 0x5 | WR_PREFIX
, TRUE
},
579 { "wr6", 0x6 | WR_PREFIX
, TRUE
}, {"wr7", 0x7 | WR_PREFIX
, TRUE
},
580 { "wr8", 0x8 | WR_PREFIX
, TRUE
}, {"wr9", 0x9 | WR_PREFIX
, TRUE
},
581 { "wr10", 0xa | WR_PREFIX
, TRUE
}, {"wr11", 0xb | WR_PREFIX
, TRUE
},
582 { "wr12", 0xc | WR_PREFIX
, TRUE
}, {"wr13", 0xd | WR_PREFIX
, TRUE
},
583 { "wr14", 0xe | WR_PREFIX
, TRUE
}, {"wr15", 0xf | WR_PREFIX
, TRUE
},
584 { "wcid", 0x0 | WC_PREFIX
, TRUE
}, {"wcon", 0x1 | WC_PREFIX
, TRUE
},
585 {"wcssf", 0x2 | WC_PREFIX
, TRUE
}, {"wcasf", 0x3 | WC_PREFIX
, TRUE
},
586 {"wcgr0", 0x8 | WC_PREFIX
, TRUE
}, {"wcgr1", 0x9 | WC_PREFIX
, TRUE
},
587 {"wcgr2", 0xa | WC_PREFIX
, TRUE
}, {"wcgr3", 0xb | WC_PREFIX
, TRUE
},
589 { "wR0", 0x0 | WR_PREFIX
, TRUE
}, {"wR1", 0x1 | WR_PREFIX
, TRUE
},
590 { "wR2", 0x2 | WR_PREFIX
, TRUE
}, {"wR3", 0x3 | WR_PREFIX
, TRUE
},
591 { "wR4", 0x4 | WR_PREFIX
, TRUE
}, {"wR5", 0x5 | WR_PREFIX
, TRUE
},
592 { "wR6", 0x6 | WR_PREFIX
, TRUE
}, {"wR7", 0x7 | WR_PREFIX
, TRUE
},
593 { "wR8", 0x8 | WR_PREFIX
, TRUE
}, {"wR9", 0x9 | WR_PREFIX
, TRUE
},
594 { "wR10", 0xa | WR_PREFIX
, TRUE
}, {"wR11", 0xb | WR_PREFIX
, TRUE
},
595 { "wR12", 0xc | WR_PREFIX
, TRUE
}, {"wR13", 0xd | WR_PREFIX
, TRUE
},
596 { "wR14", 0xe | WR_PREFIX
, TRUE
}, {"wR15", 0xf | WR_PREFIX
, TRUE
},
597 { "wCID", 0x0 | WC_PREFIX
, TRUE
}, {"wCon", 0x1 | WC_PREFIX
, TRUE
},
598 {"wCSSF", 0x2 | WC_PREFIX
, TRUE
}, {"wCASF", 0x3 | WC_PREFIX
, TRUE
},
599 {"wCGR0", 0x8 | WC_PREFIX
, TRUE
}, {"wCGR1", 0x9 | WC_PREFIX
, TRUE
},
600 {"wCGR2", 0xa | WC_PREFIX
, TRUE
}, {"wCGR3", 0xb | WC_PREFIX
, TRUE
},
604 /* Co-processor Numbers. */
605 static const struct reg_entry cp_table
[] =
607 {"p0", 0, TRUE
}, {"p1", 1, TRUE
}, {"p2", 2, TRUE
}, {"p3", 3, TRUE
},
608 {"p4", 4, TRUE
}, {"p5", 5, TRUE
}, {"p6", 6, TRUE
}, {"p7", 7, TRUE
},
609 {"p8", 8, TRUE
}, {"p9", 9, TRUE
}, {"p10", 10, TRUE
}, {"p11", 11, TRUE
},
610 {"p12", 12, TRUE
}, {"p13", 13, TRUE
}, {"p14", 14, TRUE
}, {"p15", 15, TRUE
},
614 /* Co-processor Register Numbers. */
615 static const struct reg_entry cn_table
[] =
617 {"c0", 0, TRUE
}, {"c1", 1, TRUE
}, {"c2", 2, TRUE
}, {"c3", 3, TRUE
},
618 {"c4", 4, TRUE
}, {"c5", 5, TRUE
}, {"c6", 6, TRUE
}, {"c7", 7, TRUE
},
619 {"c8", 8, TRUE
}, {"c9", 9, TRUE
}, {"c10", 10, TRUE
}, {"c11", 11, TRUE
},
620 {"c12", 12, TRUE
}, {"c13", 13, TRUE
}, {"c14", 14, TRUE
}, {"c15", 15, TRUE
},
621 /* Not really valid, but kept for back-wards compatibility. */
622 {"cr0", 0, TRUE
}, {"cr1", 1, TRUE
}, {"cr2", 2, TRUE
}, {"cr3", 3, TRUE
},
623 {"cr4", 4, TRUE
}, {"cr5", 5, TRUE
}, {"cr6", 6, TRUE
}, {"cr7", 7, TRUE
},
624 {"cr8", 8, TRUE
}, {"cr9", 9, TRUE
}, {"cr10", 10, TRUE
}, {"cr11", 11, TRUE
},
625 {"cr12", 12, TRUE
}, {"cr13", 13, TRUE
}, {"cr14", 14, TRUE
}, {"cr15", 15, TRUE
},
630 static const struct reg_entry fn_table
[] =
632 {"f0", 0, TRUE
}, {"f1", 1, TRUE
}, {"f2", 2, TRUE
}, {"f3", 3, TRUE
},
633 {"f4", 4, TRUE
}, {"f5", 5, TRUE
}, {"f6", 6, TRUE
}, {"f7", 7, TRUE
},
637 /* VFP SP Registers. */
638 static const struct reg_entry sn_table
[] =
640 {"s0", 0, TRUE
}, {"s1", 1, TRUE
}, {"s2", 2, TRUE
}, {"s3", 3, TRUE
},
641 {"s4", 4, TRUE
}, {"s5", 5, TRUE
}, {"s6", 6, TRUE
}, {"s7", 7, TRUE
},
642 {"s8", 8, TRUE
}, {"s9", 9, TRUE
}, {"s10", 10, TRUE
}, {"s11", 11, TRUE
},
643 {"s12", 12, TRUE
}, {"s13", 13, TRUE
}, {"s14", 14, TRUE
}, {"s15", 15, TRUE
},
644 {"s16", 16, TRUE
}, {"s17", 17, TRUE
}, {"s18", 18, TRUE
}, {"s19", 19, TRUE
},
645 {"s20", 20, TRUE
}, {"s21", 21, TRUE
}, {"s22", 22, TRUE
}, {"s23", 23, TRUE
},
646 {"s24", 24, TRUE
}, {"s25", 25, TRUE
}, {"s26", 26, TRUE
}, {"s27", 27, TRUE
},
647 {"s28", 28, TRUE
}, {"s29", 29, TRUE
}, {"s30", 30, TRUE
}, {"s31", 31, TRUE
},
651 /* VFP DP Registers. */
652 static const struct reg_entry dn_table
[] =
654 {"d0", 0, TRUE
}, {"d1", 1, TRUE
}, {"d2", 2, TRUE
}, {"d3", 3, TRUE
},
655 {"d4", 4, TRUE
}, {"d5", 5, TRUE
}, {"d6", 6, TRUE
}, {"d7", 7, TRUE
},
656 {"d8", 8, TRUE
}, {"d9", 9, TRUE
}, {"d10", 10, TRUE
}, {"d11", 11, TRUE
},
657 {"d12", 12, TRUE
}, {"d13", 13, TRUE
}, {"d14", 14, TRUE
}, {"d15", 15, TRUE
},
661 /* Maverick DSP coprocessor registers. */
662 static const struct reg_entry mav_mvf_table
[] =
664 {"mvf0", 0, TRUE
}, {"mvf1", 1, TRUE
}, {"mvf2", 2, TRUE
}, {"mvf3", 3, TRUE
},
665 {"mvf4", 4, TRUE
}, {"mvf5", 5, TRUE
}, {"mvf6", 6, TRUE
}, {"mvf7", 7, TRUE
},
666 {"mvf8", 8, TRUE
}, {"mvf9", 9, TRUE
}, {"mvf10", 10, TRUE
}, {"mvf11", 11, TRUE
},
667 {"mvf12", 12, TRUE
}, {"mvf13", 13, TRUE
}, {"mvf14", 14, TRUE
}, {"mvf15", 15, TRUE
},
671 static const struct reg_entry mav_mvd_table
[] =
673 {"mvd0", 0, TRUE
}, {"mvd1", 1, TRUE
}, {"mvd2", 2, TRUE
}, {"mvd3", 3, TRUE
},
674 {"mvd4", 4, TRUE
}, {"mvd5", 5, TRUE
}, {"mvd6", 6, TRUE
}, {"mvd7", 7, TRUE
},
675 {"mvd8", 8, TRUE
}, {"mvd9", 9, TRUE
}, {"mvd10", 10, TRUE
}, {"mvd11", 11, TRUE
},
676 {"mvd12", 12, TRUE
}, {"mvd13", 13, TRUE
}, {"mvd14", 14, TRUE
}, {"mvd15", 15, TRUE
},
680 static const struct reg_entry mav_mvfx_table
[] =
682 {"mvfx0", 0, TRUE
}, {"mvfx1", 1, TRUE
}, {"mvfx2", 2, TRUE
}, {"mvfx3", 3, TRUE
},
683 {"mvfx4", 4, TRUE
}, {"mvfx5", 5, TRUE
}, {"mvfx6", 6, TRUE
}, {"mvfx7", 7, TRUE
},
684 {"mvfx8", 8, TRUE
}, {"mvfx9", 9, TRUE
}, {"mvfx10", 10, TRUE
}, {"mvfx11", 11, TRUE
},
685 {"mvfx12", 12, TRUE
}, {"mvfx13", 13, TRUE
}, {"mvfx14", 14, TRUE
}, {"mvfx15", 15, TRUE
},
689 static const struct reg_entry mav_mvdx_table
[] =
691 {"mvdx0", 0, TRUE
}, {"mvdx1", 1, TRUE
}, {"mvdx2", 2, TRUE
}, {"mvdx3", 3, TRUE
},
692 {"mvdx4", 4, TRUE
}, {"mvdx5", 5, TRUE
}, {"mvdx6", 6, TRUE
}, {"mvdx7", 7, TRUE
},
693 {"mvdx8", 8, TRUE
}, {"mvdx9", 9, TRUE
}, {"mvdx10", 10, TRUE
}, {"mvdx11", 11, TRUE
},
694 {"mvdx12", 12, TRUE
}, {"mvdx13", 13, TRUE
}, {"mvdx14", 14, TRUE
}, {"mvdx15", 15, TRUE
},
698 static const struct reg_entry mav_mvax_table
[] =
700 {"mvax0", 0, TRUE
}, {"mvax1", 1, TRUE
}, {"mvax2", 2, TRUE
}, {"mvax3", 3, TRUE
},
704 static const struct reg_entry mav_dspsc_table
[] =
712 const struct reg_entry
* names
;
714 struct hash_control
* htab
;
715 const char * expected
;
718 struct reg_map all_reg_maps
[] =
720 {rn_table
, 15, NULL
, N_("ARM register expected")},
721 {cp_table
, 15, NULL
, N_("bad or missing co-processor number")},
722 {cn_table
, 15, NULL
, N_("co-processor register expected")},
723 {fn_table
, 7, NULL
, N_("FPA register expected")},
724 {sn_table
, 31, NULL
, N_("VFP single precision register expected")},
725 {dn_table
, 15, NULL
, N_("VFP double precision register expected")},
726 {mav_mvf_table
, 15, NULL
, N_("Maverick MVF register expected")},
727 {mav_mvd_table
, 15, NULL
, N_("Maverick MVD register expected")},
728 {mav_mvfx_table
, 15, NULL
, N_("Maverick MVFX register expected")},
729 {mav_mvdx_table
, 15, NULL
, N_("Maverick MVDX register expected")},
730 {mav_mvax_table
, 3, NULL
, N_("Maverick MVAX register expected")},
731 {mav_dspsc_table
, 0, NULL
, N_("Maverick DSPSC register expected")},
732 {iwmmxt_table
, 23, NULL
, N_("Intel Wireless MMX technology register expected")},
735 /* Enumeration matching entries in table above. */
739 #define REG_TYPE_FIRST REG_TYPE_RN
751 REG_TYPE_IWMMXT
= 12,
756 /* ARM instructions take 4bytes in the object file, Thumb instructions
760 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
761 #define MAV_MODE1 0x100c
763 /* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
764 #define MAV_MODE2 0x0c10
766 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
767 #define MAV_MODE3 0x100c
769 /* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
770 #define MAV_MODE4 0x0c0010
772 /* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
773 #define MAV_MODE5 0x00100c
775 /* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
776 #define MAV_MODE6 0x00100c05
780 /* Basic string to match. */
781 const char * template;
783 /* Basic instruction code. */
786 /* Offset into the template where the condition code (if any) will be.
787 If zero, then the instruction is never conditional. */
788 unsigned cond_offset
;
790 /* Which architecture variant provides this instruction. */
791 unsigned long variant
;
793 /* Function to call to parse args. */
794 void (* parms
) (char *);
797 /* Defines for various bits that we will want to toggle. */
798 #define INST_IMMEDIATE 0x02000000
799 #define OFFSET_REG 0x02000000
800 #define HWOFFSET_IMM 0x00400000
801 #define SHIFT_BY_REG 0x00000010
802 #define PRE_INDEX 0x01000000
803 #define INDEX_UP 0x00800000
804 #define WRITE_BACK 0x00200000
805 #define LDM_TYPE_2_OR_3 0x00400000
807 #define LITERAL_MASK 0xf000f000
808 #define OPCODE_MASK 0xfe1fffff
809 #define V4_STR_BIT 0x00000020
811 #define DATA_OP_SHIFT 21
813 /* Codes to distinguish the arithmetic instructions. */
824 #define OPCODE_CMP 10
825 #define OPCODE_CMN 11
826 #define OPCODE_ORR 12
827 #define OPCODE_MOV 13
828 #define OPCODE_BIC 14
829 #define OPCODE_MVN 15
831 #define T_OPCODE_MUL 0x4340
832 #define T_OPCODE_TST 0x4200
833 #define T_OPCODE_CMN 0x42c0
834 #define T_OPCODE_NEG 0x4240
835 #define T_OPCODE_MVN 0x43c0
837 #define T_OPCODE_ADD_R3 0x1800
838 #define T_OPCODE_SUB_R3 0x1a00
839 #define T_OPCODE_ADD_HI 0x4400
840 #define T_OPCODE_ADD_ST 0xb000
841 #define T_OPCODE_SUB_ST 0xb080
842 #define T_OPCODE_ADD_SP 0xa800
843 #define T_OPCODE_ADD_PC 0xa000
844 #define T_OPCODE_ADD_I8 0x3000
845 #define T_OPCODE_SUB_I8 0x3800
846 #define T_OPCODE_ADD_I3 0x1c00
847 #define T_OPCODE_SUB_I3 0x1e00
849 #define T_OPCODE_ASR_R 0x4100
850 #define T_OPCODE_LSL_R 0x4080
851 #define T_OPCODE_LSR_R 0x40c0
852 #define T_OPCODE_ASR_I 0x1000
853 #define T_OPCODE_LSL_I 0x0000
854 #define T_OPCODE_LSR_I 0x0800
856 #define T_OPCODE_MOV_I8 0x2000
857 #define T_OPCODE_CMP_I8 0x2800
858 #define T_OPCODE_CMP_LR 0x4280
859 #define T_OPCODE_MOV_HR 0x4600
860 #define T_OPCODE_CMP_HR 0x4500
862 #define T_OPCODE_LDR_PC 0x4800
863 #define T_OPCODE_LDR_SP 0x9800
864 #define T_OPCODE_STR_SP 0x9000
865 #define T_OPCODE_LDR_IW 0x6800
866 #define T_OPCODE_STR_IW 0x6000
867 #define T_OPCODE_LDR_IH 0x8800
868 #define T_OPCODE_STR_IH 0x8000
869 #define T_OPCODE_LDR_IB 0x7800
870 #define T_OPCODE_STR_IB 0x7000
871 #define T_OPCODE_LDR_RW 0x5800
872 #define T_OPCODE_STR_RW 0x5000
873 #define T_OPCODE_LDR_RH 0x5a00
874 #define T_OPCODE_STR_RH 0x5200
875 #define T_OPCODE_LDR_RB 0x5c00
876 #define T_OPCODE_STR_RB 0x5400
878 #define T_OPCODE_PUSH 0xb400
879 #define T_OPCODE_POP 0xbc00
881 #define T_OPCODE_BRANCH 0xe7fe
883 #define THUMB_SIZE 2 /* Size of thumb instruction. */
884 #define THUMB_REG_LO 0x1
885 #define THUMB_REG_HI 0x2
886 #define THUMB_REG_ANY 0x3
888 #define THUMB_H1 0x0080
889 #define THUMB_H2 0x0040
896 #define THUMB_COMPARE 1
900 #define THUMB_STORE 1
902 #define THUMB_PP_PC_LR 0x0100
904 /* These three are used for immediate shifts, do not alter. */
906 #define THUMB_HALFWORD 1
911 /* Basic string to match. */
912 const char * template;
914 /* Basic instruction code. */
919 /* Which CPU variants this exists for. */
920 unsigned long variant
;
922 /* Function to call to parse args. */
923 void (* parms
) (char *);
926 #define BAD_ARGS _("bad arguments to instruction")
927 #define BAD_PC _("r15 not allowed here")
928 #define BAD_COND _("instruction is not conditional")
929 #define ERR_NO_ACCUM _("acc0 expected")
931 static struct hash_control
* arm_ops_hsh
= NULL
;
932 static struct hash_control
* arm_tops_hsh
= NULL
;
933 static struct hash_control
* arm_cond_hsh
= NULL
;
934 static struct hash_control
* arm_shift_hsh
= NULL
;
935 static struct hash_control
* arm_psr_hsh
= NULL
;
937 /* Stuff needed to resolve the label ambiguity
947 symbolS
* last_label_seen
;
948 static int label_is_thumb_function_name
= FALSE
;
950 /* Literal Pool stuff. */
952 #define MAX_LITERAL_POOL_SIZE 1024
954 /* Literal pool structure. Held on a per-section
955 and per-sub-section basis. */
957 typedef struct literal_pool
959 expressionS literals
[MAX_LITERAL_POOL_SIZE
];
960 unsigned int next_free_entry
;
965 struct literal_pool
* next
;
968 /* Pointer to a linked list of literal pools. */
969 literal_pool
* list_of_pools
= NULL
;
971 static literal_pool
*
972 find_literal_pool (void)
976 for (pool
= list_of_pools
; pool
!= NULL
; pool
= pool
->next
)
978 if (pool
->section
== now_seg
979 && pool
->sub_section
== now_subseg
)
986 static literal_pool
*
987 find_or_make_literal_pool (void)
989 /* Next literal pool ID number. */
990 static unsigned int latest_pool_num
= 1;
993 pool
= find_literal_pool ();
997 /* Create a new pool. */
998 pool
= xmalloc (sizeof (* pool
));
1002 pool
->next_free_entry
= 0;
1003 pool
->section
= now_seg
;
1004 pool
->sub_section
= now_subseg
;
1005 pool
->next
= list_of_pools
;
1006 pool
->symbol
= NULL
;
1008 /* Add it to the list. */
1009 list_of_pools
= pool
;
1012 /* New pools, and emptied pools, will have a NULL symbol. */
1013 if (pool
->symbol
== NULL
)
1015 pool
->symbol
= symbol_create (FAKE_LABEL_NAME
, undefined_section
,
1016 (valueT
) 0, &zero_address_frag
);
1017 pool
->id
= latest_pool_num
++;
1024 /* Add the literal in the global 'inst'
1025 structure to the relevent literal pool. */
1028 add_to_lit_pool (void)
1030 literal_pool
* pool
;
1033 pool
= find_or_make_literal_pool ();
1035 /* Check if this literal value is already in the pool. */
1036 for (entry
= 0; entry
< pool
->next_free_entry
; entry
++)
1038 if ((pool
->literals
[entry
].X_op
== inst
.reloc
.exp
.X_op
)
1039 && (inst
.reloc
.exp
.X_op
== O_constant
)
1040 && (pool
->literals
[entry
].X_add_number
1041 == inst
.reloc
.exp
.X_add_number
)
1042 && (pool
->literals
[entry
].X_unsigned
1043 == inst
.reloc
.exp
.X_unsigned
))
1046 if ((pool
->literals
[entry
].X_op
== inst
.reloc
.exp
.X_op
)
1047 && (inst
.reloc
.exp
.X_op
== O_symbol
)
1048 && (pool
->literals
[entry
].X_add_number
1049 == inst
.reloc
.exp
.X_add_number
)
1050 && (pool
->literals
[entry
].X_add_symbol
1051 == inst
.reloc
.exp
.X_add_symbol
)
1052 && (pool
->literals
[entry
].X_op_symbol
1053 == inst
.reloc
.exp
.X_op_symbol
))
1057 /* Do we need to create a new entry? */
1058 if (entry
== pool
->next_free_entry
)
1060 if (entry
>= MAX_LITERAL_POOL_SIZE
)
1062 inst
.error
= _("literal pool overflow");
1066 pool
->literals
[entry
] = inst
.reloc
.exp
;
1067 pool
->next_free_entry
+= 1;
1070 inst
.reloc
.exp
.X_op
= O_symbol
;
1071 inst
.reloc
.exp
.X_add_number
= ((int) entry
) * 4 - 8;
1072 inst
.reloc
.exp
.X_add_symbol
= pool
->symbol
;
1077 /* Can't use symbol_new here, so have to create a symbol and then at
1078 a later date assign it a value. Thats what these functions do. */
1081 symbol_locate (symbolS
* symbolP
,
1082 const char * name
, /* It is copied, the caller can modify. */
1083 segT segment
, /* Segment identifier (SEG_<something>). */
1084 valueT valu
, /* Symbol value. */
1085 fragS
* frag
) /* Associated fragment. */
1087 unsigned int name_length
;
1088 char * preserved_copy_of_name
;
1090 name_length
= strlen (name
) + 1; /* +1 for \0. */
1091 obstack_grow (¬es
, name
, name_length
);
1092 preserved_copy_of_name
= obstack_finish (¬es
);
1093 #ifdef STRIP_UNDERSCORE
1094 if (preserved_copy_of_name
[0] == '_')
1095 preserved_copy_of_name
++;
1098 #ifdef tc_canonicalize_symbol_name
1099 preserved_copy_of_name
=
1100 tc_canonicalize_symbol_name (preserved_copy_of_name
);
1103 S_SET_NAME (symbolP
, preserved_copy_of_name
);
1105 S_SET_SEGMENT (symbolP
, segment
);
1106 S_SET_VALUE (symbolP
, valu
);
1107 symbol_clear_list_pointers (symbolP
);
1109 symbol_set_frag (symbolP
, frag
);
1111 /* Link to end of symbol chain. */
1113 extern int symbol_table_frozen
;
1115 if (symbol_table_frozen
)
1119 symbol_append (symbolP
, symbol_lastP
, & symbol_rootP
, & symbol_lastP
);
1121 obj_symbol_new_hook (symbolP
);
1123 #ifdef tc_symbol_new_hook
1124 tc_symbol_new_hook (symbolP
);
1128 verify_symbol_chain (symbol_rootP
, symbol_lastP
);
1129 #endif /* DEBUG_SYMS */
1132 /* Check that an immediate is valid.
1133 If so, convert it to the right format. */
1136 validate_immediate (unsigned int val
)
1141 #define rotate_left(v, n) (v << n | v >> (32 - n))
1143 for (i
= 0; i
< 32; i
+= 2)
1144 if ((a
= rotate_left (val
, i
)) <= 0xff)
1145 return a
| (i
<< 7); /* 12-bit pack: [shift-cnt,const]. */
1150 /* Check to see if an immediate can be computed as two separate immediate
1151 values, added together. We already know that this value cannot be
1152 computed by just one ARM instruction. */
1155 validate_immediate_twopart (unsigned int val
,
1156 unsigned int * highpart
)
1161 for (i
= 0; i
< 32; i
+= 2)
1162 if (((a
= rotate_left (val
, i
)) & 0xff) != 0)
1168 * highpart
= (a
>> 8) | ((i
+ 24) << 7);
1170 else if (a
& 0xff0000)
1174 * highpart
= (a
>> 16) | ((i
+ 16) << 7);
1178 assert (a
& 0xff000000);
1179 * highpart
= (a
>> 24) | ((i
+ 8) << 7);
1182 return (a
& 0xff) | (i
<< 7);
1189 validate_offset_imm (unsigned int val
, int hwse
)
1191 if ((hwse
&& val
> 255) || val
> 4095)
1198 /* This code is to handle mapping symbols as defined in the ARM ELF spec.
1199 (This text is taken from version B-02 of the spec):
1201 4.4.7 Mapping and tagging symbols
1203 A section of an ARM ELF file can contain a mixture of ARM code,
1204 Thumb code, and data. There are inline transitions between code
1205 and data at literal pool boundaries. There can also be inline
1206 transitions between ARM code and Thumb code, for example in
1207 ARM-Thumb inter-working veneers. Linkers, machine-level
1208 debuggers, profiling tools, and disassembly tools need to map
1209 images accurately. For example, setting an ARM breakpoint on a
1210 Thumb location, or in a literal pool, can crash the program
1211 being debugged, ruining the debugging session.
1213 ARM ELF entities are mapped (see section 4.4.7.1 below) and
1214 tagged (see section 4.4.7.2 below) using local symbols (with
1215 binding STB_LOCAL). To assist consumers, mapping and tagging
1216 symbols should be collated first in the symbol table, before
1217 other symbols with binding STB_LOCAL.
1219 To allow properly collated mapping and tagging symbols to be
1220 skipped by consumers that have no interest in them, the first
1221 such symbol should have the name $m and its st_value field equal
1222 to the total number of mapping and tagging symbols (including
1223 the $m) in the symbol table.
1225 4.4.7.1 Mapping symbols
1227 $a Labels the first byte of a sequence of ARM instructions.
1228 Its type is STT_FUNC.
1230 $d Labels the first byte of a sequence of data items.
1231 Its type is STT_OBJECT.
1233 $t Labels the first byte of a sequence of Thumb instructions.
1234 Its type is STT_FUNC.
1236 This list of mapping symbols may be extended in the future.
1238 Section-relative mapping symbols
1240 Mapping symbols defined in a section define a sequence of
1241 half-open address intervals that cover the address range of the
1242 section. Each interval starts at the address defined by a
1243 mapping symbol, and continues up to, but not including, the
1244 address defined by the next (in address order) mapping symbol or
1245 the end of the section. A corollary is that there must be a
1246 mapping symbol defined at the beginning of each section.
1247 Consumers can ignore the size of a section-relative mapping
1248 symbol. Producers can set it to 0.
1250 Absolute mapping symbols
1252 Because of the need to crystallize a Thumb address with the
1253 Thumb-bit set, absolute symbol of type STT_FUNC (symbols of type
1254 STT_FUNC defined in section SHN_ABS) need to be mapped with $a
1257 The extent of a mapping symbol defined in SHN_ABS is [st_value,
1258 st_value + st_size), or [st_value, st_value + 1) if st_size = 0,
1259 where [x, y) denotes the half-open address range from x,
1260 inclusive, to y, exclusive.
1262 In the absence of a mapping symbol, a consumer can interpret a
1263 function symbol with an odd value as the Thumb code address
1264 obtained by clearing the least significant bit of the
1265 value. This interpretation is deprecated, and it may not work in
1268 Note - the Tagging symbols ($b, $f, $p $m) have been dropped from
1269 the EABI (which is still under development), so they are not
1270 implemented here. */
1272 static enum mstate mapstate
= MAP_UNDEFINED
;
1275 mapping_state (enum mstate state
)
1278 const char * symname
;
1281 if (mapstate
== state
)
1282 /* The mapping symbol has already been emitted.
1283 There is nothing else to do. */
1296 type
= BSF_FUNCTION
;
1300 type
= BSF_FUNCTION
;
1308 seg_info (now_seg
)->tc_segment_info_data
= state
;
1310 symbolP
= symbol_new (symname
, now_seg
, (valueT
) frag_now_fix (), frag_now
);
1311 symbol_table_insert (symbolP
);
1312 symbol_get_bfdsym (symbolP
)->flags
|= type
| BSF_LOCAL
;
1317 THUMB_SET_FUNC (symbolP
, 0);
1318 ARM_SET_THUMB (symbolP
, 0);
1319 ARM_SET_INTERWORK (symbolP
, support_interwork
);
1323 THUMB_SET_FUNC (symbolP
, 1);
1324 ARM_SET_THUMB (symbolP
, 1);
1325 ARM_SET_INTERWORK (symbolP
, support_interwork
);
1334 /* When we change sections we need to issue a new mapping symbol. */
1337 arm_elf_change_section (void)
1341 if (!SEG_NORMAL (now_seg
))
1344 flags
= bfd_get_section_flags (stdoutput
, now_seg
);
1346 /* We can ignore sections that only contain debug info. */
1347 if ((flags
& SEC_ALLOC
) == 0)
1350 mapstate
= seg_info (now_seg
)->tc_segment_info_data
;
1353 #define mapping_state(a)
1354 #endif /* OBJ_ELF */
1356 /* arm_reg_parse () := if it looks like a register, return its token and
1357 advance the pointer. */
1360 arm_reg_parse (char ** ccp
, struct hash_control
* htab
)
1362 char * start
= * ccp
;
1365 struct reg_entry
* reg
;
1367 #ifdef REGISTER_PREFIX
1368 if (*start
!= REGISTER_PREFIX
)
1373 #ifdef OPTIONAL_REGISTER_PREFIX
1374 if (*p
== OPTIONAL_REGISTER_PREFIX
)
1378 if (!ISALPHA (*p
) || !is_name_beginner (*p
))
1382 while (ISALPHA (c
) || ISDIGIT (c
) || c
== '_')
1386 reg
= (struct reg_entry
*) hash_find (htab
, start
);
1398 /* Search for the following register name in each of the possible reg name
1399 tables. Return the classification if found, or REG_TYPE_MAX if not
1402 static enum arm_reg_type
1403 arm_reg_parse_any (char *cp
)
1407 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
1408 if (arm_reg_parse (&cp
, all_reg_maps
[i
].htab
) != FAIL
)
1409 return (enum arm_reg_type
) i
;
1411 return REG_TYPE_MAX
;
1415 opcode_select (int width
)
1422 if (! (cpu_variant
& ARM_EXT_V4T
))
1423 as_bad (_("selected processor does not support THUMB opcodes"));
1426 /* No need to force the alignment, since we will have been
1427 coming from ARM mode, which is word-aligned. */
1428 record_alignment (now_seg
, 1);
1430 mapping_state (MAP_THUMB
);
1436 if ((cpu_variant
& ARM_ALL
) == ARM_EXT_V4T
)
1437 as_bad (_("selected processor does not support ARM opcodes"));
1442 frag_align (2, 0, 0);
1444 record_alignment (now_seg
, 1);
1446 mapping_state (MAP_ARM
);
1450 as_bad (_("invalid instruction size selected (%d)"), width
);
1455 s_req (int a ATTRIBUTE_UNUSED
)
1457 as_bad (_("invalid syntax for .req directive"));
1460 /* The .unreq directive deletes an alias which was previously defined
1461 by .req. For example:
1467 s_unreq (int a ATTRIBUTE_UNUSED
)
1472 skip_whitespace (input_line_pointer
);
1473 name
= input_line_pointer
;
1475 while (*input_line_pointer
!= 0
1476 && *input_line_pointer
!= ' '
1477 && *input_line_pointer
!= '\n')
1478 ++input_line_pointer
;
1480 saved_char
= *input_line_pointer
;
1481 *input_line_pointer
= 0;
1485 enum arm_reg_type req_type
= arm_reg_parse_any (name
);
1487 if (req_type
!= REG_TYPE_MAX
)
1489 char *temp_name
= name
;
1490 int req_no
= arm_reg_parse (&temp_name
, all_reg_maps
[req_type
].htab
);
1494 struct reg_entry
*req_entry
;
1496 /* Check to see if this alias is a builtin one. */
1497 req_entry
= hash_delete (all_reg_maps
[req_type
].htab
, name
);
1500 as_bad (_("unreq: missing hash entry for \"%s\""), name
);
1501 else if (req_entry
->builtin
)
1502 /* FIXME: We are deleting a built in register alias which
1503 points to a const data structure, so we only need to
1504 free up the memory used by the key in the hash table.
1505 Unfortunately we have not recorded this value, so this
1506 is a memory leak. */
1507 /* FIXME: Should we issue a warning message ? */
1511 /* Deleting a user defined alias. We need to free the
1512 key and the value, but fortunately the key is the same
1513 as the value->name field. */
1514 free ((char *) req_entry
->name
);
1519 as_bad (_(".unreq: unrecognized symbol \"%s\""), name
);
1522 as_bad (_(".unreq: unrecognized symbol \"%s\""), name
);
1525 as_bad (_("invalid syntax for .unreq directive"));
1527 *input_line_pointer
= saved_char
;
1528 demand_empty_rest_of_line ();
1532 s_bss (int ignore ATTRIBUTE_UNUSED
)
1534 /* We don't support putting frags in the BSS segment, we fake it by
1535 marking in_bss, then looking at s_skip for clues. */
1536 subseg_set (bss_section
, 0);
1537 demand_empty_rest_of_line ();
1538 mapping_state (MAP_DATA
);
1542 s_even (int ignore ATTRIBUTE_UNUSED
)
1544 /* Never make frag if expect extra pass. */
1546 frag_align (1, 0, 0);
1548 record_alignment (now_seg
, 1);
1550 demand_empty_rest_of_line ();
1554 s_ltorg (int ignored ATTRIBUTE_UNUSED
)
1557 literal_pool
* pool
;
1560 pool
= find_literal_pool ();
1562 || pool
->symbol
== NULL
1563 || pool
->next_free_entry
== 0)
1566 mapping_state (MAP_DATA
);
1568 /* Align pool as you have word accesses.
1569 Only make a frag if we have to. */
1571 frag_align (2, 0, 0);
1573 record_alignment (now_seg
, 2);
1575 sprintf (sym_name
, "$$lit_\002%x", pool
->id
);
1577 symbol_locate (pool
->symbol
, sym_name
, now_seg
,
1578 (valueT
) frag_now_fix (), frag_now
);
1579 symbol_table_insert (pool
->symbol
);
1581 ARM_SET_THUMB (pool
->symbol
, thumb_mode
);
1583 #if defined OBJ_COFF || defined OBJ_ELF
1584 ARM_SET_INTERWORK (pool
->symbol
, support_interwork
);
1587 for (entry
= 0; entry
< pool
->next_free_entry
; entry
++)
1588 /* First output the expression in the instruction to the pool. */
1589 emit_expr (&(pool
->literals
[entry
]), 4); /* .word */
1591 /* Mark the pool as empty. */
1592 pool
->next_free_entry
= 0;
1593 pool
->symbol
= NULL
;
1596 /* Same as s_align_ptwo but align 0 => align 2. */
1599 s_align (int unused ATTRIBUTE_UNUSED
)
1603 long max_alignment
= 15;
1605 temp
= get_absolute_expression ();
1606 if (temp
> max_alignment
)
1607 as_bad (_("alignment too large: %d assumed"), temp
= max_alignment
);
1610 as_bad (_("alignment negative. 0 assumed."));
1614 if (*input_line_pointer
== ',')
1616 input_line_pointer
++;
1617 temp_fill
= get_absolute_expression ();
1625 /* Only make a frag if we HAVE to. */
1626 if (temp
&& !need_pass_2
)
1627 frag_align (temp
, (int) temp_fill
, 0);
1628 demand_empty_rest_of_line ();
1630 record_alignment (now_seg
, temp
);
1634 s_force_thumb (int ignore ATTRIBUTE_UNUSED
)
1636 /* If we are not already in thumb mode go into it, EVEN if
1637 the target processor does not support thumb instructions.
1638 This is used by gcc/config/arm/lib1funcs.asm for example
1639 to compile interworking support functions even if the
1640 target processor should not support interworking. */
1645 record_alignment (now_seg
, 1);
1648 demand_empty_rest_of_line ();
1652 s_thumb_func (int ignore ATTRIBUTE_UNUSED
)
1657 /* The following label is the name/address of the start of a Thumb function.
1658 We need to know this for the interworking support. */
1659 label_is_thumb_function_name
= TRUE
;
1661 demand_empty_rest_of_line ();
1664 /* Perform a .set directive, but also mark the alias as
1665 being a thumb function. */
1668 s_thumb_set (int equiv
)
1670 /* XXX the following is a duplicate of the code for s_set() in read.c
1671 We cannot just call that code as we need to get at the symbol that
1678 /* Especial apologies for the random logic:
1679 This just grew, and could be parsed much more simply!
1681 name
= input_line_pointer
;
1682 delim
= get_symbol_end ();
1683 end_name
= input_line_pointer
;
1688 if (*input_line_pointer
!= ',')
1691 as_bad (_("expected comma after name \"%s\""), name
);
1693 ignore_rest_of_line ();
1697 input_line_pointer
++;
1700 if (name
[0] == '.' && name
[1] == '\0')
1702 /* XXX - this should not happen to .thumb_set. */
1706 if ((symbolP
= symbol_find (name
)) == NULL
1707 && (symbolP
= md_undefined_symbol (name
)) == NULL
)
1710 /* When doing symbol listings, play games with dummy fragments living
1711 outside the normal fragment chain to record the file and line info
1713 if (listing
& LISTING_SYMBOLS
)
1715 extern struct list_info_struct
* listing_tail
;
1716 fragS
* dummy_frag
= xmalloc (sizeof (fragS
));
1718 memset (dummy_frag
, 0, sizeof (fragS
));
1719 dummy_frag
->fr_type
= rs_fill
;
1720 dummy_frag
->line
= listing_tail
;
1721 symbolP
= symbol_new (name
, undefined_section
, 0, dummy_frag
);
1722 dummy_frag
->fr_symbol
= symbolP
;
1726 symbolP
= symbol_new (name
, undefined_section
, 0, &zero_address_frag
);
1729 /* "set" symbols are local unless otherwise specified. */
1730 SF_SET_LOCAL (symbolP
);
1731 #endif /* OBJ_COFF */
1732 } /* Make a new symbol. */
1734 symbol_table_insert (symbolP
);
1739 && S_IS_DEFINED (symbolP
)
1740 && S_GET_SEGMENT (symbolP
) != reg_section
)
1741 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP
));
1743 pseudo_set (symbolP
);
1745 demand_empty_rest_of_line ();
1747 /* XXX Now we come to the Thumb specific bit of code. */
1749 THUMB_SET_FUNC (symbolP
, 1);
1750 ARM_SET_THUMB (symbolP
, 1);
1751 #if defined OBJ_ELF || defined OBJ_COFF
1752 ARM_SET_INTERWORK (symbolP
, support_interwork
);
1757 s_arm (int ignore ATTRIBUTE_UNUSED
)
1760 demand_empty_rest_of_line ();
1764 s_thumb (int ignore ATTRIBUTE_UNUSED
)
1767 demand_empty_rest_of_line ();
1771 s_code (int unused ATTRIBUTE_UNUSED
)
1775 temp
= get_absolute_expression ();
1780 opcode_select (temp
);
1784 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp
);
1789 end_of_line (char * str
)
1791 skip_whitespace (str
);
1793 if (*str
!= '\0' && !inst
.error
)
1794 inst
.error
= _("garbage following instruction");
1798 skip_past_comma (char ** str
)
1800 char * p
= * str
, c
;
1803 while ((c
= *p
) == ' ' || c
== ',')
1806 if (c
== ',' && comma
++)
1814 return comma
? SUCCESS
: FAIL
;
1817 /* Return TRUE if anything in the expression is a bignum. */
1820 walk_no_bignums (symbolS
* sp
)
1822 if (symbol_get_value_expression (sp
)->X_op
== O_big
)
1825 if (symbol_get_value_expression (sp
)->X_add_symbol
)
1827 return (walk_no_bignums (symbol_get_value_expression (sp
)->X_add_symbol
)
1828 || (symbol_get_value_expression (sp
)->X_op_symbol
1829 && walk_no_bignums (symbol_get_value_expression (sp
)->X_op_symbol
)));
1835 static int in_my_get_expression
= 0;
1838 my_get_expression (expressionS
* ep
, char ** str
)
1843 save_in
= input_line_pointer
;
1844 input_line_pointer
= *str
;
1845 in_my_get_expression
= 1;
1846 seg
= expression (ep
);
1847 in_my_get_expression
= 0;
1849 if (ep
->X_op
== O_illegal
)
1851 /* We found a bad expression in md_operand(). */
1852 *str
= input_line_pointer
;
1853 input_line_pointer
= save_in
;
1858 if (seg
!= absolute_section
1859 && seg
!= text_section
1860 && seg
!= data_section
1861 && seg
!= bss_section
1862 && seg
!= undefined_section
)
1864 inst
.error
= _("bad_segment");
1865 *str
= input_line_pointer
;
1866 input_line_pointer
= save_in
;
1871 /* Get rid of any bignums now, so that we don't generate an error for which
1872 we can't establish a line number later on. Big numbers are never valid
1873 in instructions, which is where this routine is always called. */
1874 if (ep
->X_op
== O_big
1875 || (ep
->X_add_symbol
1876 && (walk_no_bignums (ep
->X_add_symbol
)
1878 && walk_no_bignums (ep
->X_op_symbol
)))))
1880 inst
.error
= _("invalid constant");
1881 *str
= input_line_pointer
;
1882 input_line_pointer
= save_in
;
1886 *str
= input_line_pointer
;
1887 input_line_pointer
= save_in
;
1891 /* A standard register must be given at this point.
1892 SHIFT is the place to put it in inst.instruction.
1893 Restores input start point on error.
1894 Returns the reg#, or FAIL. */
1897 reg_required_here (char ** str
, int shift
)
1899 static char buff
[128]; /* XXX */
1901 char * start
= * str
;
1903 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_RN
].htab
)) != FAIL
)
1906 inst
.instruction
|= reg
<< shift
;
1910 /* Restore the start point, we may have got a reg of the wrong class. */
1913 /* In the few cases where we might be able to accept something else
1914 this error can be overridden. */
1915 sprintf (buff
, _("register expected, not '%.100s'"), start
);
1921 /* A Intel Wireless MMX technology register
1922 must be given at this point.
1923 Shift is the place to put it in inst.instruction.
1924 Restores input start point on err.
1925 Returns the reg#, or FAIL. */
1928 wreg_required_here (char ** str
,
1930 enum wreg_type reg_type
)
1932 static char buff
[128];
1934 char * start
= *str
;
1936 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_IWMMXT
].htab
)) != FAIL
)
1938 if (wr_register (reg
)
1939 && (reg_type
== IWMMXT_REG_WR
|| reg_type
== IWMMXT_REG_WR_OR_WC
))
1942 inst
.instruction
|= (reg
^ WR_PREFIX
) << shift
;
1945 else if (wc_register (reg
)
1946 && (reg_type
== IWMMXT_REG_WC
|| reg_type
== IWMMXT_REG_WR_OR_WC
))
1949 inst
.instruction
|= (reg
^ WC_PREFIX
) << shift
;
1952 else if ((wcg_register (reg
) && reg_type
== IWMMXT_REG_WCG
))
1955 inst
.instruction
|= ((reg
^ WC_PREFIX
) - 8) << shift
;
1960 /* Restore the start point, we may have got a reg of the wrong class. */
1963 /* In the few cases where we might be able to accept
1964 something else this error can be overridden. */
1965 sprintf (buff
, _("Intel Wireless MMX technology register expected, not '%.100s'"), start
);
1971 static const struct asm_psr
*
1972 arm_psr_parse (char ** ccp
)
1974 char * start
= * ccp
;
1977 const struct asm_psr
* psr
;
1981 /* Skip to the end of the next word in the input stream. */
1986 while (ISALPHA (c
) || c
== '_');
1988 /* Terminate the word. */
1991 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
1992 feature for ease of use and backwards compatibility. */
1993 if (!strncmp (start
, "cpsr", 4))
1994 strncpy (start
, "CPSR", 4);
1995 else if (!strncmp (start
, "spsr", 4))
1996 strncpy (start
, "SPSR", 4);
1998 /* Now locate the word in the psr hash table. */
1999 psr
= (const struct asm_psr
*) hash_find (arm_psr_hsh
, start
);
2001 /* Restore the input stream. */
2004 /* If we found a valid match, advance the
2005 stream pointer past the end of the word. */
2011 /* Parse the input looking for a PSR flag. */
2014 psr_required_here (char ** str
)
2016 char * start
= * str
;
2017 const struct asm_psr
* psr
;
2019 psr
= arm_psr_parse (str
);
2023 /* If this is the SPSR that is being modified, set the R bit. */
2025 inst
.instruction
|= SPSR_BIT
;
2027 /* Set the psr flags in the MSR instruction. */
2028 inst
.instruction
|= psr
->field
<< PSR_SHIFT
;
2033 /* In the few cases where we might be able to accept
2034 something else this error can be overridden. */
2035 inst
.error
= _("flag for {c}psr instruction expected");
2037 /* Restore the start point. */
2043 co_proc_number (char ** str
)
2045 int processor
, pchar
;
2048 skip_whitespace (*str
);
2051 /* The data sheet seems to imply that just a number on its own is valid
2052 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
2054 if ((processor
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CP
].htab
))
2060 if (pchar
>= '0' && pchar
<= '9')
2062 processor
= pchar
- '0';
2063 if (**str
>= '0' && **str
<= '9')
2065 processor
= processor
* 10 + *(*str
)++ - '0';
2068 inst
.error
= _("illegal co-processor number");
2075 inst
.error
= all_reg_maps
[REG_TYPE_CP
].expected
;
2080 inst
.instruction
|= processor
<< 8;
2085 cp_opc_expr (char ** str
, int where
, int length
)
2089 skip_whitespace (* str
);
2091 memset (&expr
, '\0', sizeof (expr
));
2093 if (my_get_expression (&expr
, str
))
2095 if (expr
.X_op
!= O_constant
)
2097 inst
.error
= _("bad or missing expression");
2101 if ((expr
.X_add_number
& ((1 << length
) - 1)) != expr
.X_add_number
)
2103 inst
.error
= _("immediate co-processor expression too large");
2107 inst
.instruction
|= expr
.X_add_number
<< where
;
2112 cp_reg_required_here (char ** str
, int where
)
2115 char * start
= *str
;
2117 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CN
].htab
)) != FAIL
)
2119 inst
.instruction
|= reg
<< where
;
2123 /* In the few cases where we might be able to accept something else
2124 this error can be overridden. */
2125 inst
.error
= all_reg_maps
[REG_TYPE_CN
].expected
;
2127 /* Restore the start point. */
2133 fp_reg_required_here (char ** str
, int where
)
2136 char * start
= * str
;
2138 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_FN
].htab
)) != FAIL
)
2140 inst
.instruction
|= reg
<< where
;
2144 /* In the few cases where we might be able to accept something else
2145 this error can be overridden. */
2146 inst
.error
= all_reg_maps
[REG_TYPE_FN
].expected
;
2148 /* Restore the start point. */
2154 cp_address_offset (char ** str
)
2158 skip_whitespace (* str
);
2160 if (! is_immediate_prefix (**str
))
2162 inst
.error
= _("immediate expression expected");
2168 if (my_get_expression (& inst
.reloc
.exp
, str
))
2171 if (inst
.reloc
.exp
.X_op
== O_constant
)
2173 offset
= inst
.reloc
.exp
.X_add_number
;
2177 inst
.error
= _("co-processor address must be word aligned");
2181 if (offset
> 1023 || offset
< -1023)
2183 inst
.error
= _("offset too large");
2188 inst
.instruction
|= INDEX_UP
;
2192 inst
.instruction
|= offset
>> 2;
2195 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
2201 cp_address_required_here (char ** str
, int wb_ok
)
2212 skip_whitespace (p
);
2214 if ((reg
= reg_required_here (& p
, 16)) == FAIL
)
2217 skip_whitespace (p
);
2223 skip_whitespace (p
);
2227 /* As an extension to the official ARM syntax we allow:
2229 as a short hand for:
2231 inst
.instruction
|= PRE_INDEX
| INDEX_UP
;
2236 if (skip_past_comma (& p
) == FAIL
)
2238 inst
.error
= _("comma expected after closing square bracket");
2242 skip_whitespace (p
);
2249 write_back
= WRITE_BACK
;
2253 inst
.error
= _("pc may not be used in post-increment");
2257 if (cp_address_offset (& p
) == FAIL
)
2261 pre_inc
= PRE_INDEX
| INDEX_UP
;
2267 /* [Rn], {<expr>} */
2270 skip_whitespace (p
);
2272 if (my_get_expression (& inst
.reloc
.exp
, & p
))
2275 if (inst
.reloc
.exp
.X_op
== O_constant
)
2277 option
= inst
.reloc
.exp
.X_add_number
;
2279 if (option
> 255 || option
< 0)
2281 inst
.error
= _("'option' field too large");
2285 skip_whitespace (p
);
2289 inst
.error
= _("'}' expected at end of 'option' field");
2295 inst
.instruction
|= option
;
2296 inst
.instruction
|= INDEX_UP
;
2301 inst
.error
= _("non-constant expressions for 'option' field not supported");
2307 inst
.error
= _("# or { expected after comma");
2313 /* '['Rn, #expr']'[!] */
2315 if (skip_past_comma (& p
) == FAIL
)
2317 inst
.error
= _("pre-indexed expression expected");
2321 pre_inc
= PRE_INDEX
;
2323 if (cp_address_offset (& p
) == FAIL
)
2326 skip_whitespace (p
);
2330 inst
.error
= _("missing ]");
2334 skip_whitespace (p
);
2336 if (wb_ok
&& *p
== '!')
2340 inst
.error
= _("pc may not be used with write-back");
2345 write_back
= WRITE_BACK
;
2351 if (my_get_expression (&inst
.reloc
.exp
, &p
))
2354 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
2355 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
2356 inst
.reloc
.pc_rel
= 1;
2357 inst
.instruction
|= (REG_PC
<< 16);
2358 pre_inc
= PRE_INDEX
;
2361 inst
.instruction
|= write_back
| pre_inc
;
2367 cp_byte_address_offset (char ** str
)
2371 skip_whitespace (* str
);
2373 if (! is_immediate_prefix (**str
))
2375 inst
.error
= _("immediate expression expected");
2381 if (my_get_expression (& inst
.reloc
.exp
, str
))
2384 if (inst
.reloc
.exp
.X_op
== O_constant
)
2386 offset
= inst
.reloc
.exp
.X_add_number
;
2388 if (offset
> 255 || offset
< -255)
2390 inst
.error
= _("offset too large");
2395 inst
.instruction
|= INDEX_UP
;
2399 inst
.instruction
|= offset
;
2402 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM_S2
;
2408 cp_byte_address_required_here (char ** str
)
2419 skip_whitespace (p
);
2421 if ((reg
= reg_required_here (& p
, 16)) == FAIL
)
2424 skip_whitespace (p
);
2430 if (skip_past_comma (& p
) == SUCCESS
)
2433 write_back
= WRITE_BACK
;
2437 inst
.error
= _("pc may not be used in post-increment");
2441 if (cp_byte_address_offset (& p
) == FAIL
)
2445 pre_inc
= PRE_INDEX
| INDEX_UP
;
2449 /* '['Rn, #expr']'[!] */
2451 if (skip_past_comma (& p
) == FAIL
)
2453 inst
.error
= _("pre-indexed expression expected");
2457 pre_inc
= PRE_INDEX
;
2459 if (cp_byte_address_offset (& p
) == FAIL
)
2462 skip_whitespace (p
);
2466 inst
.error
= _("missing ]");
2470 skip_whitespace (p
);
2476 inst
.error
= _("pc may not be used with write-back");
2481 write_back
= WRITE_BACK
;
2487 if (my_get_expression (&inst
.reloc
.exp
, &p
))
2490 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM_S2
;
2491 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
2492 inst
.reloc
.pc_rel
= 1;
2493 inst
.instruction
|= (REG_PC
<< 16);
2494 pre_inc
= PRE_INDEX
;
2497 inst
.instruction
|= write_back
| pre_inc
;
2505 skip_whitespace (str
);
2510 if (my_get_expression (&inst
.reloc
.exp
, &str
))
2511 inst
.reloc
.exp
.X_op
= O_illegal
;
2514 skip_whitespace (str
);
2518 inst
.reloc
.exp
.X_op
= O_illegal
;
2521 if (inst
.reloc
.exp
.X_op
!= O_constant
2522 || inst
.reloc
.exp
.X_add_number
> 255
2523 || inst
.reloc
.exp
.X_add_number
< 0)
2525 inst
.error
= _("Invalid NOP hint");
2529 /* Arcitectural NOP hints are CPSR sets with no bits selected. */
2530 inst
.instruction
&= 0xf0000000;
2531 inst
.instruction
|= 0x0320f000 + inst
.reloc
.exp
.X_add_number
;
2538 do_empty (char * str
)
2540 /* Do nothing really. */
2549 /* Only one syntax. */
2550 skip_whitespace (str
);
2552 if (reg_required_here (&str
, 12) == FAIL
)
2554 inst
.error
= BAD_ARGS
;
2558 if (skip_past_comma (&str
) == FAIL
)
2560 inst
.error
= _("comma expected after register name");
2564 skip_whitespace (str
);
2566 if ( streq (str
, "CPSR")
2567 || streq (str
, "SPSR")
2568 /* Lower case versions for backwards compatibility. */
2569 || streq (str
, "cpsr")
2570 || streq (str
, "spsr"))
2573 /* This is for backwards compatibility with older toolchains. */
2574 else if ( streq (str
, "cpsr_all")
2575 || streq (str
, "spsr_all"))
2579 inst
.error
= _("CPSR or SPSR expected");
2583 if (* str
== 's' || * str
== 'S')
2584 inst
.instruction
|= SPSR_BIT
;
2590 /* Two possible forms:
2591 "{C|S}PSR_<field>, Rm",
2592 "{C|S}PSR_f, #expression". */
2597 skip_whitespace (str
);
2599 if (psr_required_here (& str
) == FAIL
)
2602 if (skip_past_comma (& str
) == FAIL
)
2604 inst
.error
= _("comma missing after psr flags");
2608 skip_whitespace (str
);
2610 if (reg_required_here (& str
, 0) != FAIL
)
2617 if (! is_immediate_prefix (* str
))
2620 _("only a register or immediate value can follow a psr flag");
2627 if (my_get_expression (& inst
.reloc
.exp
, & str
))
2630 _("only a register or immediate value can follow a psr flag");
2634 #if 0 /* The first edition of the ARM architecture manual stated that
2635 writing anything other than the flags with an immediate operation
2636 had UNPREDICTABLE effects. This constraint was removed in the
2637 second edition of the specification. */
2638 if ((cpu_variant
& ARM_EXT_V5
) != ARM_EXT_V5
2639 && inst
.instruction
& ((PSR_c
| PSR_x
| PSR_s
) << PSR_SHIFT
))
2641 inst
.error
= _("immediate value cannot be used to set this field");
2646 inst
.instruction
|= INST_IMMEDIATE
;
2648 if (inst
.reloc
.exp
.X_add_symbol
)
2650 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
2651 inst
.reloc
.pc_rel
= 0;
2655 unsigned value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
2657 if (value
== (unsigned) FAIL
)
2659 inst
.error
= _("invalid constant");
2663 inst
.instruction
|= value
;
2670 /* Long Multiply Parser
2671 UMULL RdLo, RdHi, Rm, Rs
2672 SMULL RdLo, RdHi, Rm, Rs
2673 UMLAL RdLo, RdHi, Rm, Rs
2674 SMLAL RdLo, RdHi, Rm, Rs. */
2677 do_mull (char * str
)
2679 int rdlo
, rdhi
, rm
, rs
;
2681 /* Only one format "rdlo, rdhi, rm, rs". */
2682 skip_whitespace (str
);
2684 if ((rdlo
= reg_required_here (&str
, 12)) == FAIL
)
2686 inst
.error
= BAD_ARGS
;
2690 if (skip_past_comma (&str
) == FAIL
2691 || (rdhi
= reg_required_here (&str
, 16)) == FAIL
)
2693 inst
.error
= BAD_ARGS
;
2697 if (skip_past_comma (&str
) == FAIL
2698 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
2700 inst
.error
= BAD_ARGS
;
2704 /* rdhi, rdlo and rm must all be different. */
2705 if (rdlo
== rdhi
|| rdlo
== rm
|| rdhi
== rm
)
2706 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
2708 if (skip_past_comma (&str
) == FAIL
2709 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
2711 inst
.error
= BAD_ARGS
;
2715 if (rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
)
2717 inst
.error
= BAD_PC
;
2729 /* Only one format "rd, rm, rs". */
2730 skip_whitespace (str
);
2732 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
2734 inst
.error
= BAD_ARGS
;
2740 inst
.error
= BAD_PC
;
2744 if (skip_past_comma (&str
) == FAIL
2745 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
2747 inst
.error
= BAD_ARGS
;
2753 inst
.error
= BAD_PC
;
2758 as_tsktsk (_("rd and rm should be different in mul"));
2760 if (skip_past_comma (&str
) == FAIL
2761 || (rm
= reg_required_here (&str
, 8)) == FAIL
)
2763 inst
.error
= BAD_ARGS
;
2769 inst
.error
= BAD_PC
;
2781 /* Only one format "rd, rm, rs, rn". */
2782 skip_whitespace (str
);
2784 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
2786 inst
.error
= BAD_ARGS
;
2792 inst
.error
= BAD_PC
;
2796 if (skip_past_comma (&str
) == FAIL
2797 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
2799 inst
.error
= BAD_ARGS
;
2805 inst
.error
= BAD_PC
;
2810 as_tsktsk (_("rd and rm should be different in mla"));
2812 if (skip_past_comma (&str
) == FAIL
2813 || (rd
= reg_required_here (&str
, 8)) == FAIL
2814 || skip_past_comma (&str
) == FAIL
2815 || (rm
= reg_required_here (&str
, 12)) == FAIL
)
2817 inst
.error
= BAD_ARGS
;
2821 if (rd
== REG_PC
|| rm
== REG_PC
)
2823 inst
.error
= BAD_PC
;
2830 /* Expects *str -> the characters "acc0", possibly with leading blanks.
2831 Advances *str to the next non-alphanumeric.
2832 Returns 0, or else FAIL (in which case sets inst.error).
2834 (In a future XScale, there may be accumulators other than zero.
2835 At that time this routine and its callers can be upgraded to suit.) */
2838 accum0_required_here (char ** str
)
2840 static char buff
[128]; /* Note the address is taken. Hence, static. */
2843 int result
= 0; /* The accum number. */
2845 skip_whitespace (p
);
2847 *str
= p
; /* Advance caller's string pointer too. */
2852 *--p
= 0; /* Aap nul into input buffer at non-alnum. */
2854 if (! ( streq (*str
, "acc0") || streq (*str
, "ACC0")))
2856 sprintf (buff
, _("acc0 expected, not '%.100s'"), *str
);
2861 *p
= c
; /* Unzap. */
2862 *str
= p
; /* Caller's string pointer to after match. */
2867 ldst_extend_v4 (char ** str
)
2876 if (my_get_expression (& inst
.reloc
.exp
, str
))
2879 if (inst
.reloc
.exp
.X_op
== O_constant
)
2881 int value
= inst
.reloc
.exp
.X_add_number
;
2883 if (value
< -255 || value
> 255)
2885 inst
.error
= _("address offset too large");
2895 /* Halfword and signextension instructions have the
2896 immediate value split across bits 11..8 and bits 3..0. */
2897 inst
.instruction
|= (add
| HWOFFSET_IMM
2898 | ((value
>> 4) << 8) | (value
& 0xF));
2902 inst
.instruction
|= HWOFFSET_IMM
;
2903 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
2904 inst
.reloc
.pc_rel
= 0;
2917 if (reg_required_here (str
, 0) == FAIL
)
2920 inst
.instruction
|= add
;
2925 /* Expects **str -> after a comma. May be leading blanks.
2926 Advances *str, recognizing a load mode, and setting inst.instruction.
2927 Returns rn, or else FAIL (in which case may set inst.error
2928 and not advance str)
2930 Note: doesn't know Rd, so no err checks that require such knowledge. */
2933 ld_mode_required_here (char ** string
)
2935 char * str
= * string
;
2939 skip_whitespace (str
);
2945 skip_whitespace (str
);
2947 if ((rn
= reg_required_here (& str
, 16)) == FAIL
)
2950 skip_whitespace (str
);
2956 if (skip_past_comma (& str
) == SUCCESS
)
2958 /* [Rn],... (post inc) */
2959 if (ldst_extend_v4 (&str
) == FAIL
)
2964 skip_whitespace (str
);
2969 inst
.instruction
|= WRITE_BACK
;
2972 inst
.instruction
|= INDEX_UP
| HWOFFSET_IMM
;
2978 if (skip_past_comma (& str
) == FAIL
)
2980 inst
.error
= _("pre-indexed expression expected");
2986 if (ldst_extend_v4 (&str
) == FAIL
)
2989 skip_whitespace (str
);
2991 if (* str
++ != ']')
2993 inst
.error
= _("missing ]");
2997 skip_whitespace (str
);
3002 inst
.instruction
|= WRITE_BACK
;
3006 else if (* str
== '=') /* ldr's "r,=label" syntax */
3007 /* We should never reach here, because <text> = <expression> is
3008 caught gas/read.c read_a_source_file() as a .set operation. */
3010 else /* PC +- 8 bit immediate offset. */
3012 if (my_get_expression (& inst
.reloc
.exp
, & str
))
3015 inst
.instruction
|= HWOFFSET_IMM
; /* The I bit. */
3016 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
3017 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
3018 inst
.reloc
.pc_rel
= 1;
3019 inst
.instruction
|= (REG_PC
<< 16);
3025 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
3031 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
3032 SMLAxy{cond} Rd,Rm,Rs,Rn
3033 SMLAWy{cond} Rd,Rm,Rs,Rn
3034 Error if any register is R15. */
3037 do_smla (char * str
)
3041 skip_whitespace (str
);
3043 if ((rd
= reg_required_here (& str
, 16)) == FAIL
3044 || skip_past_comma (& str
) == FAIL
3045 || (rm
= reg_required_here (& str
, 0)) == FAIL
3046 || skip_past_comma (& str
) == FAIL
3047 || (rs
= reg_required_here (& str
, 8)) == FAIL
3048 || skip_past_comma (& str
) == FAIL
3049 || (rn
= reg_required_here (& str
, 12)) == FAIL
)
3050 inst
.error
= BAD_ARGS
;
3052 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
|| rn
== REG_PC
)
3053 inst
.error
= BAD_PC
;
3059 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
3060 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
3061 Error if any register is R15.
3062 Warning if Rdlo == Rdhi. */
3065 do_smlal (char * str
)
3067 int rdlo
, rdhi
, rm
, rs
;
3069 skip_whitespace (str
);
3071 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
3072 || skip_past_comma (& str
) == FAIL
3073 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
3074 || skip_past_comma (& str
) == FAIL
3075 || (rm
= reg_required_here (& str
, 0)) == FAIL
3076 || skip_past_comma (& str
) == FAIL
3077 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
3079 inst
.error
= BAD_ARGS
;
3083 if (rdlo
== REG_PC
|| rdhi
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
3085 inst
.error
= BAD_PC
;
3090 as_tsktsk (_("rdhi and rdlo must be different"));
3095 /* ARM V5E (El Segundo) signed-multiply (argument parse)
3096 SMULxy{cond} Rd,Rm,Rs
3097 Error if any register is R15. */
3100 do_smul (char * str
)
3104 skip_whitespace (str
);
3106 if ((rd
= reg_required_here (& str
, 16)) == FAIL
3107 || skip_past_comma (& str
) == FAIL
3108 || (rm
= reg_required_here (& str
, 0)) == FAIL
3109 || skip_past_comma (& str
) == FAIL
3110 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
3111 inst
.error
= BAD_ARGS
;
3113 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
3114 inst
.error
= BAD_PC
;
3120 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
3121 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
3122 Error if any register is R15. */
3125 do_qadd (char * str
)
3129 skip_whitespace (str
);
3131 if ((rd
= reg_required_here (& str
, 12)) == FAIL
3132 || skip_past_comma (& str
) == FAIL
3133 || (rm
= reg_required_here (& str
, 0)) == FAIL
3134 || skip_past_comma (& str
) == FAIL
3135 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
3136 inst
.error
= BAD_ARGS
;
3138 else if (rd
== REG_PC
|| rm
== REG_PC
|| rn
== REG_PC
)
3139 inst
.error
= BAD_PC
;
3145 /* ARM V5E (el Segundo)
3146 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3147 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3149 These are equivalent to the XScale instructions MAR and MRA,
3150 respectively, when coproc == 0, opcode == 0, and CRm == 0.
3152 Result unpredicatable if Rd or Rn is R15. */
3155 do_co_reg2c (char * str
)
3159 skip_whitespace (str
);
3161 if (co_proc_number (& str
) == FAIL
)
3164 inst
.error
= BAD_ARGS
;
3168 if (skip_past_comma (& str
) == FAIL
3169 || cp_opc_expr (& str
, 4, 4) == FAIL
)
3172 inst
.error
= BAD_ARGS
;
3176 if (skip_past_comma (& str
) == FAIL
3177 || (rd
= reg_required_here (& str
, 12)) == FAIL
)
3180 inst
.error
= BAD_ARGS
;
3184 if (skip_past_comma (& str
) == FAIL
3185 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
3188 inst
.error
= BAD_ARGS
;
3192 /* Unpredictable result if rd or rn is R15. */
3193 if (rd
== REG_PC
|| rn
== REG_PC
)
3195 (_("Warning: instruction unpredictable when using r15"));
3197 if (skip_past_comma (& str
) == FAIL
3198 || cp_reg_required_here (& str
, 0) == FAIL
)
3201 inst
.error
= BAD_ARGS
;
3208 /* ARM V5 count-leading-zeroes instruction (argument parse)
3209 CLZ{<cond>} <Rd>, <Rm>
3210 Condition defaults to COND_ALWAYS.
3211 Error if Rd or Rm are R15. */
3218 skip_whitespace (str
);
3220 if (((rd
= reg_required_here (& str
, 12)) == FAIL
)
3221 || (skip_past_comma (& str
) == FAIL
)
3222 || ((rm
= reg_required_here (& str
, 0)) == FAIL
))
3223 inst
.error
= BAD_ARGS
;
3225 else if (rd
== REG_PC
|| rm
== REG_PC
)
3226 inst
.error
= BAD_PC
;
3232 /* ARM V5 (argument parse)
3233 LDC2{L} <coproc>, <CRd>, <addressing mode>
3234 STC2{L} <coproc>, <CRd>, <addressing mode>
3235 Instruction is not conditional, and has 0xf in the condition field.
3236 Otherwise, it's the same as LDC/STC. */
3239 do_lstc2 (char * str
)
3241 skip_whitespace (str
);
3243 if (co_proc_number (& str
) == FAIL
)
3246 inst
.error
= BAD_ARGS
;
3248 else if (skip_past_comma (& str
) == FAIL
3249 || cp_reg_required_here (& str
, 12) == FAIL
)
3252 inst
.error
= BAD_ARGS
;
3254 else if (skip_past_comma (& str
) == FAIL
3255 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
3258 inst
.error
= BAD_ARGS
;
3264 /* ARM V5 (argument parse)
3265 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
3266 Instruction is not conditional, and has 0xf in the condition field.
3267 Otherwise, it's the same as CDP. */
3270 do_cdp2 (char * str
)
3272 skip_whitespace (str
);
3274 if (co_proc_number (& str
) == FAIL
)
3277 inst
.error
= BAD_ARGS
;
3281 if (skip_past_comma (& str
) == FAIL
3282 || cp_opc_expr (& str
, 20,4) == FAIL
)
3285 inst
.error
= BAD_ARGS
;
3289 if (skip_past_comma (& str
) == FAIL
3290 || cp_reg_required_here (& str
, 12) == FAIL
)
3293 inst
.error
= BAD_ARGS
;
3297 if (skip_past_comma (& str
) == FAIL
3298 || cp_reg_required_here (& str
, 16) == FAIL
)
3301 inst
.error
= BAD_ARGS
;
3305 if (skip_past_comma (& str
) == FAIL
3306 || cp_reg_required_here (& str
, 0) == FAIL
)
3309 inst
.error
= BAD_ARGS
;
3313 if (skip_past_comma (& str
) == SUCCESS
)
3315 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
3318 inst
.error
= BAD_ARGS
;
3326 /* ARM V5 (argument parse)
3327 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3328 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3329 Instruction is not conditional, and has 0xf in the condition field.
3330 Otherwise, it's the same as MCR/MRC. */
3333 do_co_reg2 (char * str
)
3335 skip_whitespace (str
);
3337 if (co_proc_number (& str
) == FAIL
)
3340 inst
.error
= BAD_ARGS
;
3344 if (skip_past_comma (& str
) == FAIL
3345 || cp_opc_expr (& str
, 21, 3) == FAIL
)
3348 inst
.error
= BAD_ARGS
;
3352 if (skip_past_comma (& str
) == FAIL
3353 || reg_required_here (& str
, 12) == FAIL
)
3356 inst
.error
= BAD_ARGS
;
3360 if (skip_past_comma (& str
) == FAIL
3361 || cp_reg_required_here (& str
, 16) == FAIL
)
3364 inst
.error
= BAD_ARGS
;
3368 if (skip_past_comma (& str
) == FAIL
3369 || cp_reg_required_here (& str
, 0) == FAIL
)
3372 inst
.error
= BAD_ARGS
;
3376 if (skip_past_comma (& str
) == SUCCESS
)
3378 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
3381 inst
.error
= BAD_ARGS
;
3394 skip_whitespace (str
);
3396 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
3398 inst
.error
= BAD_ARGS
;
3402 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
3404 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
3409 /* ARM v5TEJ. Jump to Jazelle code. */
3416 skip_whitespace (str
);
3418 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
3420 inst
.error
= BAD_ARGS
;
3424 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
3426 as_tsktsk (_("use of r15 in bxj is not really useful"));
3431 /* ARM V6 umaal (argument parse). */
3434 do_umaal (char * str
)
3436 int rdlo
, rdhi
, rm
, rs
;
3438 skip_whitespace (str
);
3439 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
3440 || skip_past_comma (& str
) == FAIL
3441 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
3442 || skip_past_comma (& str
) == FAIL
3443 || (rm
= reg_required_here (& str
, 0)) == FAIL
3444 || skip_past_comma (& str
) == FAIL
3445 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
3447 inst
.error
= BAD_ARGS
;
3451 if (rdlo
== REG_PC
|| rdhi
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
3453 inst
.error
= BAD_PC
;
3460 /* ARM V6 strex (argument parse). */
3463 do_strex (char * str
)
3467 /* Parse Rd, Rm,. */
3468 skip_whitespace (str
);
3469 if ((rd
= reg_required_here (& str
, 12)) == FAIL
3470 || skip_past_comma (& str
) == FAIL
3471 || (rm
= reg_required_here (& str
, 0)) == FAIL
3472 || skip_past_comma (& str
) == FAIL
)
3474 inst
.error
= BAD_ARGS
;
3477 if (rd
== REG_PC
|| rm
== REG_PC
)
3479 inst
.error
= BAD_PC
;
3484 inst
.error
= _("Rd equal to Rm or Rn yields unpredictable results");
3488 /* Skip past '['. */
3489 if ((strlen (str
) >= 1)
3490 && strncmp (str
, "[", 1) == 0)
3493 skip_whitespace (str
);
3496 if ((rn
= reg_required_here (& str
, 16)) == FAIL
)
3498 inst
.error
= BAD_ARGS
;
3501 else if (rn
== REG_PC
)
3503 inst
.error
= BAD_PC
;
3508 inst
.error
= _("Rd equal to Rm or Rn yields unpredictable results");
3511 skip_whitespace (str
);
3513 /* Skip past ']'. */
3514 if ((strlen (str
) >= 1)
3515 && strncmp (str
, "]", 1) == 0)
3521 /* KIND indicates what kind of shifts are accepted. */
3524 decode_shift (char ** str
, int kind
)
3526 const struct asm_shift_name
* shift
;
3530 skip_whitespace (* str
);
3532 for (p
= * str
; ISALPHA (* p
); p
++)
3537 inst
.error
= _("shift expression expected");
3543 shift
= (const struct asm_shift_name
*) hash_find (arm_shift_hsh
, * str
);
3548 inst
.error
= _("shift expression expected");
3552 assert (shift
->properties
->index
== shift_properties
[shift
->properties
->index
].index
);
3554 if (kind
== SHIFT_LSL_OR_ASR_IMMEDIATE
3555 && shift
->properties
->index
!= SHIFT_LSL
3556 && shift
->properties
->index
!= SHIFT_ASR
)
3558 inst
.error
= _("'LSL' or 'ASR' required");
3561 else if (kind
== SHIFT_LSL_IMMEDIATE
3562 && shift
->properties
->index
!= SHIFT_LSL
)
3564 inst
.error
= _("'LSL' required");
3567 else if (kind
== SHIFT_ASR_IMMEDIATE
3568 && shift
->properties
->index
!= SHIFT_ASR
)
3570 inst
.error
= _("'ASR' required");
3574 if (shift
->properties
->index
== SHIFT_RRX
)
3577 inst
.instruction
|= shift
->properties
->bit_field
;
3581 skip_whitespace (p
);
3583 if (kind
== NO_SHIFT_RESTRICT
&& reg_required_here (& p
, 8) != FAIL
)
3585 inst
.instruction
|= shift
->properties
->bit_field
| SHIFT_BY_REG
;
3589 else if (! is_immediate_prefix (* p
))
3591 inst
.error
= (NO_SHIFT_RESTRICT
3592 ? _("shift requires register or #expression")
3593 : _("shift requires #expression"));
3601 if (my_get_expression (& inst
.reloc
.exp
, & p
))
3604 /* Validate some simple #expressions. */
3605 if (inst
.reloc
.exp
.X_op
== O_constant
)
3607 unsigned num
= inst
.reloc
.exp
.X_add_number
;
3609 /* Reject operations greater than 32. */
3611 /* Reject a shift of 0 unless the mode allows it. */
3612 || (num
== 0 && shift
->properties
->allows_0
== 0)
3613 /* Reject a shift of 32 unless the mode allows it. */
3614 || (num
== 32 && shift
->properties
->allows_32
== 0)
3617 /* As a special case we allow a shift of zero for
3618 modes that do not support it to be recoded as an
3619 logical shift left of zero (ie nothing). We warn
3620 about this though. */
3623 as_warn (_("shift of 0 ignored."));
3624 shift
= & shift_names
[0];
3625 assert (shift
->properties
->index
== SHIFT_LSL
);
3629 inst
.error
= _("invalid immediate shift");
3634 /* Shifts of 32 are encoded as 0, for those shifts that
3639 inst
.instruction
|= (num
<< 7) | shift
->properties
->bit_field
;
3643 inst
.reloc
.type
= BFD_RELOC_ARM_SHIFT_IMM
;
3644 inst
.reloc
.pc_rel
= 0;
3645 inst
.instruction
|= shift
->properties
->bit_field
;
3653 do_sat (char ** str
, int bias
)
3658 skip_whitespace (*str
);
3660 /* Parse <Rd>, field. */
3661 if ((rd
= reg_required_here (str
, 12)) == FAIL
3662 || skip_past_comma (str
) == FAIL
)
3664 inst
.error
= BAD_ARGS
;
3669 inst
.error
= BAD_PC
;
3673 /* Parse #<immed>, field. */
3674 if (is_immediate_prefix (**str
))
3678 inst
.error
= _("immediate expression expected");
3681 if (my_get_expression (&expr
, str
))
3683 inst
.error
= _("bad expression");
3686 if (expr
.X_op
!= O_constant
)
3688 inst
.error
= _("constant expression expected");
3691 if (expr
.X_add_number
+ bias
< 0
3692 || expr
.X_add_number
+ bias
> 31)
3694 inst
.error
= _("immediate value out of range");
3697 inst
.instruction
|= (expr
.X_add_number
+ bias
) << 16;
3698 if (skip_past_comma (str
) == FAIL
)
3700 inst
.error
= BAD_ARGS
;
3704 /* Parse <Rm> field. */
3705 if ((rm
= reg_required_here (str
, 0)) == FAIL
)
3707 inst
.error
= BAD_ARGS
;
3712 inst
.error
= BAD_PC
;
3716 if (skip_past_comma (str
) == SUCCESS
)
3717 decode_shift (str
, SHIFT_LSL_OR_ASR_IMMEDIATE
);
3720 /* ARM V6 ssat (argument parse). */
3723 do_ssat (char * str
)
3725 do_sat (&str
, /*bias=*/-1);
3729 /* ARM V6 usat (argument parse). */
3732 do_usat (char * str
)
3734 do_sat (&str
, /*bias=*/0);
3739 do_sat16 (char ** str
, int bias
)
3744 skip_whitespace (*str
);
3746 /* Parse the <Rd> field. */
3747 if ((rd
= reg_required_here (str
, 12)) == FAIL
3748 || skip_past_comma (str
) == FAIL
)
3750 inst
.error
= BAD_ARGS
;
3755 inst
.error
= BAD_PC
;
3759 /* Parse #<immed>, field. */
3760 if (is_immediate_prefix (**str
))
3764 inst
.error
= _("immediate expression expected");
3767 if (my_get_expression (&expr
, str
))
3769 inst
.error
= _("bad expression");
3772 if (expr
.X_op
!= O_constant
)
3774 inst
.error
= _("constant expression expected");
3777 if (expr
.X_add_number
+ bias
< 0
3778 || expr
.X_add_number
+ bias
> 15)
3780 inst
.error
= _("immediate value out of range");
3783 inst
.instruction
|= (expr
.X_add_number
+ bias
) << 16;
3784 if (skip_past_comma (str
) == FAIL
)
3786 inst
.error
= BAD_ARGS
;
3790 /* Parse <Rm> field. */
3791 if ((rm
= reg_required_here (str
, 0)) == FAIL
)
3793 inst
.error
= BAD_ARGS
;
3798 inst
.error
= BAD_PC
;
3803 /* ARM V6 ssat16 (argument parse). */
3806 do_ssat16 (char * str
)
3808 do_sat16 (&str
, /*bias=*/-1);
3813 do_usat16 (char * str
)
3815 do_sat16 (&str
, /*bias=*/0);
3820 do_cps_mode (char ** str
)
3824 skip_whitespace (*str
);
3826 if (! is_immediate_prefix (**str
))
3828 inst
.error
= _("immediate expression expected");
3832 (*str
)++; /* Strip off the immediate signifier. */
3833 if (my_get_expression (&expr
, str
))
3835 inst
.error
= _("bad expression");
3839 if (expr
.X_op
!= O_constant
)
3841 inst
.error
= _("constant expression expected");
3845 /* The mode is a 5 bit field. Valid values are 0-31. */
3846 if (((unsigned) expr
.X_add_number
) > 31
3847 || (inst
.reloc
.exp
.X_add_number
) < 0)
3849 inst
.error
= _("invalid constant");
3853 inst
.instruction
|= expr
.X_add_number
;
3856 /* ARM V6 srs (argument parse). */
3862 skip_whitespace (str
);
3863 exclam
= strchr (str
, '!');
3871 inst
.instruction
|= WRITE_BACK
;
3877 /* ARM V6 SMMUL (argument parse). */
3880 do_smmul (char * str
)
3884 skip_whitespace (str
);
3885 if ((rd
= reg_required_here (&str
, 16)) == FAIL
3886 || skip_past_comma (&str
) == FAIL
3887 || (rm
= reg_required_here (&str
, 0)) == FAIL
3888 || skip_past_comma (&str
) == FAIL
3889 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
3891 inst
.error
= BAD_ARGS
;
3899 inst
.error
= BAD_PC
;
3906 /* ARM V6 SMLALD (argument parse). */
3909 do_smlald (char * str
)
3911 int rdlo
, rdhi
, rm
, rs
;
3913 skip_whitespace (str
);
3914 if ((rdlo
= reg_required_here (&str
, 12)) == FAIL
3915 || skip_past_comma (&str
) == FAIL
3916 || (rdhi
= reg_required_here (&str
, 16)) == FAIL
3917 || skip_past_comma (&str
) == FAIL
3918 || (rm
= reg_required_here (&str
, 0)) == FAIL
3919 || skip_past_comma (&str
) == FAIL
3920 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
3922 inst
.error
= BAD_ARGS
;
3931 inst
.error
= BAD_PC
;
3938 /* ARM V6 SMLAD (argument parse). Signed multiply accumulate dual.
3939 smlad{x}{<cond>} Rd, Rm, Rs, Rn */
3942 do_smlad (char * str
)
3946 skip_whitespace (str
);
3947 if ((rd
= reg_required_here (&str
, 16)) == FAIL
3948 || skip_past_comma (&str
) == FAIL
3949 || (rm
= reg_required_here (&str
, 0)) == FAIL
3950 || skip_past_comma (&str
) == FAIL
3951 || (rs
= reg_required_here (&str
, 8)) == FAIL
3952 || skip_past_comma (&str
) == FAIL
3953 || (rn
= reg_required_here (&str
, 12)) == FAIL
)
3955 inst
.error
= BAD_ARGS
;
3964 inst
.error
= BAD_PC
;
3971 /* Returns true if the endian-specifier indicates big-endianness. */
3974 do_endian_specifier (char * str
)
3978 skip_whitespace (str
);
3979 if (strlen (str
) < 2)
3980 inst
.error
= _("missing endian specifier");
3981 else if (strncasecmp (str
, "BE", 2) == 0)
3986 else if (strncasecmp (str
, "LE", 2) == 0)
3989 inst
.error
= _("valid endian specifiers are be or le");
3996 /* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
3997 preserving the other bits.
3999 setend <endian_specifier>, where <endian_specifier> is either
4003 do_setend (char * str
)
4005 if (do_endian_specifier (str
))
4006 inst
.instruction
|= 0x200;
4011 SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
4012 Condition defaults to COND_ALWAYS.
4013 Error if any register uses R15. */
4016 do_sxth (char * str
)
4020 int rotation_clear_mask
= 0xfffff3ff;
4021 int rotation_eight_mask
= 0x00000400;
4022 int rotation_sixteen_mask
= 0x00000800;
4023 int rotation_twenty_four_mask
= 0x00000c00;
4025 skip_whitespace (str
);
4026 if ((rd
= reg_required_here (&str
, 12)) == FAIL
4027 || skip_past_comma (&str
) == FAIL
4028 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4030 inst
.error
= BAD_ARGS
;
4034 else if (rd
== REG_PC
|| rm
== REG_PC
)
4036 inst
.error
= BAD_PC
;
4040 /* Zero out the rotation field. */
4041 inst
.instruction
&= rotation_clear_mask
;
4043 /* Check for lack of optional rotation field. */
4044 if (skip_past_comma (&str
) == FAIL
)
4050 /* Move past 'ROR'. */
4051 skip_whitespace (str
);
4052 if (strncasecmp (str
, "ROR", 3) == 0)
4056 inst
.error
= _("missing rotation field after comma");
4060 /* Get the immediate constant. */
4061 skip_whitespace (str
);
4062 if (is_immediate_prefix (* str
))
4066 inst
.error
= _("immediate expression expected");
4070 if (my_get_expression (&expr
, &str
))
4072 inst
.error
= _("bad expression");
4076 if (expr
.X_op
!= O_constant
)
4078 inst
.error
= _("constant expression expected");
4082 switch (expr
.X_add_number
)
4085 /* Rotation field has already been zeroed. */
4088 inst
.instruction
|= rotation_eight_mask
;
4092 inst
.instruction
|= rotation_sixteen_mask
;
4096 inst
.instruction
|= rotation_twenty_four_mask
;
4100 inst
.error
= _("rotation can be 8, 16, 24 or 0 when field is ommited");
4107 /* ARM V6 SXTAH extracts a 16-bit value from a register, sign
4108 extends it to 32-bits, and adds the result to a value in another
4109 register. You can specify a rotation by 0, 8, 16, or 24 bits
4110 before extracting the 16-bit value.
4111 SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
4112 Condition defaults to COND_ALWAYS.
4113 Error if any register uses R15. */
4116 do_sxtah (char * str
)
4120 int rotation_clear_mask
= 0xfffff3ff;
4121 int rotation_eight_mask
= 0x00000400;
4122 int rotation_sixteen_mask
= 0x00000800;
4123 int rotation_twenty_four_mask
= 0x00000c00;
4125 skip_whitespace (str
);
4126 if ((rd
= reg_required_here (&str
, 12)) == FAIL
4127 || skip_past_comma (&str
) == FAIL
4128 || (rn
= reg_required_here (&str
, 16)) == FAIL
4129 || skip_past_comma (&str
) == FAIL
4130 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4132 inst
.error
= BAD_ARGS
;
4136 else if (rd
== REG_PC
|| rn
== REG_PC
|| rm
== REG_PC
)
4138 inst
.error
= BAD_PC
;
4142 /* Zero out the rotation field. */
4143 inst
.instruction
&= rotation_clear_mask
;
4145 /* Check for lack of optional rotation field. */
4146 if (skip_past_comma (&str
) == FAIL
)
4152 /* Move past 'ROR'. */
4153 skip_whitespace (str
);
4154 if (strncasecmp (str
, "ROR", 3) == 0)
4158 inst
.error
= _("missing rotation field after comma");
4162 /* Get the immediate constant. */
4163 skip_whitespace (str
);
4164 if (is_immediate_prefix (* str
))
4168 inst
.error
= _("immediate expression expected");
4172 if (my_get_expression (&expr
, &str
))
4174 inst
.error
= _("bad expression");
4178 if (expr
.X_op
!= O_constant
)
4180 inst
.error
= _("constant expression expected");
4184 switch (expr
.X_add_number
)
4187 /* Rotation field has already been zeroed. */
4191 inst
.instruction
|= rotation_eight_mask
;
4195 inst
.instruction
|= rotation_sixteen_mask
;
4199 inst
.instruction
|= rotation_twenty_four_mask
;
4203 inst
.error
= _("rotation can be 8, 16, 24 or 0 when field is ommited");
4211 /* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
4212 word at the specified address and the following word
4214 Unconditionally executed.
4215 Error if Rn is R15. */
4222 skip_whitespace (str
);
4224 if ((rn
= reg_required_here (&str
, 16)) == FAIL
)
4229 inst
.error
= BAD_PC
;
4233 skip_whitespace (str
);
4237 inst
.instruction
|= WRITE_BACK
;
4243 /* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
4244 register (argument parse).
4246 Condition defaults to COND_ALWAYS.
4247 Error if Rd or Rm are R15. */
4254 skip_whitespace (str
);
4256 if ((rd
= reg_required_here (&str
, 12)) == FAIL
4257 || skip_past_comma (&str
) == FAIL
4258 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4259 inst
.error
= BAD_ARGS
;
4261 else if (rd
== REG_PC
|| rm
== REG_PC
)
4262 inst
.error
= BAD_PC
;
4268 /* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
4269 QADD16{<cond>} <Rd>, <Rn>, <Rm>
4270 Condition defaults to COND_ALWAYS.
4271 Error if Rd, Rn or Rm are R15. */
4274 do_qadd16 (char * str
)
4278 skip_whitespace (str
);
4280 if ((rd
= reg_required_here (&str
, 12)) == FAIL
4281 || skip_past_comma (&str
) == FAIL
4282 || (rn
= reg_required_here (&str
, 16)) == FAIL
4283 || skip_past_comma (&str
) == FAIL
4284 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4285 inst
.error
= BAD_ARGS
;
4287 else if (rd
== REG_PC
|| rm
== REG_PC
|| rn
== REG_PC
)
4288 inst
.error
= BAD_PC
;
4295 do_pkh_core (char * str
, int shift
)
4299 skip_whitespace (str
);
4300 if (((rd
= reg_required_here (&str
, 12)) == FAIL
)
4301 || (skip_past_comma (&str
) == FAIL
)
4302 || ((rn
= reg_required_here (&str
, 16)) == FAIL
)
4303 || (skip_past_comma (&str
) == FAIL
)
4304 || ((rm
= reg_required_here (&str
, 0)) == FAIL
))
4306 inst
.error
= BAD_ARGS
;
4310 else if (rd
== REG_PC
|| rn
== REG_PC
|| rm
== REG_PC
)
4312 inst
.error
= BAD_PC
;
4316 /* Check for optional shift immediate constant. */
4317 if (skip_past_comma (&str
) == FAIL
)
4319 if (shift
== SHIFT_ASR_IMMEDIATE
)
4321 /* If the shift specifier is ommited, turn the instruction
4322 into pkhbt rd, rm, rn. First, switch the instruction
4323 code, and clear the rn and rm fields. */
4324 inst
.instruction
&= 0xfff0f010;
4325 /* Now, re-encode the registers. */
4326 inst
.instruction
|= (rm
<< 16) | rn
;
4331 decode_shift (&str
, shift
);
4334 /* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
4335 PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
4336 Condition defaults to COND_ALWAYS.
4337 Error if Rd, Rn or Rm are R15. */
4340 do_pkhbt (char * str
)
4342 do_pkh_core (str
, SHIFT_LSL_IMMEDIATE
);
4345 /* ARM V6 PKHTB (Argument Parse). */
4348 do_pkhtb (char * str
)
4350 do_pkh_core (str
, SHIFT_ASR_IMMEDIATE
);
4353 /* ARM V6 Load Register Exclusive instruction (argument parse).
4354 LDREX{,B,D,H}{<cond>} <Rd, [<Rn>]
4355 Condition defaults to COND_ALWAYS.
4356 Error if Rd or Rn are R15.
4357 See ARMARMv6 A4.1.27: LDREX. */
4360 do_ldrex (char * str
)
4364 skip_whitespace (str
);
4367 if (((rd
= reg_required_here (&str
, 12)) == FAIL
)
4368 || (skip_past_comma (&str
) == FAIL
))
4370 inst
.error
= BAD_ARGS
;
4373 else if (rd
== REG_PC
)
4375 inst
.error
= BAD_PC
;
4378 skip_whitespace (str
);
4380 /* Skip past '['. */
4381 if ((strlen (str
) >= 1)
4382 &&strncmp (str
, "[", 1) == 0)
4384 skip_whitespace (str
);
4387 if ((rn
= reg_required_here (&str
, 16)) == FAIL
)
4389 inst
.error
= BAD_ARGS
;
4392 else if (rn
== REG_PC
)
4394 inst
.error
= BAD_PC
;
4397 skip_whitespace (str
);
4399 /* Skip past ']'. */
4400 if ((strlen (str
) >= 1)
4401 && strncmp (str
, "]", 1) == 0)
4407 /* ARM V6 change processor state instruction (argument parse)
4408 CPS, CPSIE, CSPID . */
4418 do_cps_flags (char ** str
, int thumb_p
)
4423 unsigned long arm_value
;
4424 unsigned long thumb_value
;
4426 static struct cps_flag flag_table
[] =
4435 skip_whitespace (*str
);
4437 /* Get the a, f and i flags. */
4438 while (**str
&& **str
!= ',')
4441 struct cps_flag
*q
= flag_table
+ sizeof (flag_table
)/sizeof (*p
);
4443 for (p
= flag_table
; p
< q
; ++p
)
4444 if (strncasecmp (*str
, &p
->character
, 1) == 0)
4446 inst
.instruction
|= (thumb_p
? p
->thumb_value
: p
->arm_value
);
4452 inst
.error
= _("unrecognized flag");
4459 inst
.error
= _("no 'a', 'i', or 'f' flags for 'cps'");
4463 do_cpsi (char * str
)
4465 do_cps_flags (&str
, /*thumb_p=*/0);
4467 if (skip_past_comma (&str
) == SUCCESS
)
4469 skip_whitespace (str
);
4475 /* THUMB V5 breakpoint instruction (argument parse)
4479 do_t_bkpt (char * str
)
4482 unsigned long number
;
4484 skip_whitespace (str
);
4486 /* Allow optional leading '#'. */
4487 if (is_immediate_prefix (*str
))
4490 memset (& expr
, '\0', sizeof (expr
));
4491 if (my_get_expression (& expr
, & str
)
4492 || (expr
.X_op
!= O_constant
4493 /* As a convenience we allow 'bkpt' without an operand. */
4494 && expr
.X_op
!= O_absent
))
4496 inst
.error
= _("bad expression");
4500 number
= expr
.X_add_number
;
4502 /* Check it fits an 8 bit unsigned. */
4503 if (number
!= (number
& 0xff))
4505 inst
.error
= _("immediate value out of range");
4509 inst
.instruction
|= number
;
4514 static bfd_reloc_code_real_type
4515 arm_parse_reloc (void)
4524 bfd_reloc_code_real_type reloc
;
4528 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
4529 MAP ("(got)", BFD_RELOC_ARM_GOT32
),
4530 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF
),
4531 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
4532 branch instructions generated by GCC for PLT relocs. */
4533 MAP ("(plt)", BFD_RELOC_ARM_PLT32
),
4534 MAP ("(target1)", BFD_RELOC_ARM_TARGET1
),
4535 MAP ("(sbrel)", BFD_RELOC_ARM_SBREL32
),
4536 MAP ("(target2)", BFD_RELOC_ARM_TARGET2
),
4537 { NULL
, 0, BFD_RELOC_UNUSED
}
4541 for (i
= 0, ip
= input_line_pointer
;
4542 i
< sizeof (id
) && (ISALNUM (*ip
) || ISPUNCT (*ip
));
4544 id
[i
] = TOLOWER (*ip
);
4546 for (i
= 0; reloc_map
[i
].str
; i
++)
4547 if (strncmp (id
, reloc_map
[i
].str
, reloc_map
[i
].len
) == 0)
4550 input_line_pointer
+= reloc_map
[i
].len
;
4552 return reloc_map
[i
].reloc
;
4555 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
4556 Expects inst.instruction is set for BLX(1).
4557 Note: this is cloned from do_branch, and the reloc changed to be a
4558 new one that can cope with setting one extra bit (the H bit). */
4561 do_branch25 (char * str
)
4563 if (my_get_expression (& inst
.reloc
.exp
, & str
))
4570 /* ScottB: February 5, 1998 */
4571 /* Check to see of PLT32 reloc required for the instruction. */
4573 /* arm_parse_reloc() works on input_line_pointer.
4574 We actually want to parse the operands to the branch instruction
4575 passed in 'str'. Save the input pointer and restore it later. */
4576 save_in
= input_line_pointer
;
4577 input_line_pointer
= str
;
4579 if (inst
.reloc
.exp
.X_op
== O_symbol
4581 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
4583 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
4584 inst
.reloc
.pc_rel
= 0;
4585 /* Modify str to point to after parsed operands, otherwise
4586 end_of_line() will complain about the (PLT) left in str. */
4587 str
= input_line_pointer
;
4591 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
4592 inst
.reloc
.pc_rel
= 1;
4595 input_line_pointer
= save_in
;
4598 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
4599 inst
.reloc
.pc_rel
= 1;
4600 #endif /* OBJ_ELF */
4605 /* ARM V5 branch-link-exchange instruction (argument parse)
4606 BLX <target_addr> ie BLX(1)
4607 BLX{<condition>} <Rm> ie BLX(2)
4608 Unfortunately, there are two different opcodes for this mnemonic.
4609 So, the insns[].value is not used, and the code here zaps values
4610 into inst.instruction.
4611 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
4619 skip_whitespace (mystr
);
4620 rm
= reg_required_here (& mystr
, 0);
4622 /* The above may set inst.error. Ignore his opinion. */
4627 /* Arg is a register.
4628 Use the condition code our caller put in inst.instruction.
4629 Pass ourselves off as a BX with a funny opcode. */
4630 inst
.instruction
|= 0x012fff30;
4635 /* This must be is BLX <target address>, no condition allowed. */
4636 if (inst
.instruction
!= COND_ALWAYS
)
4638 inst
.error
= BAD_COND
;
4642 inst
.instruction
= 0xfafffffe;
4644 /* Process like a B/BL, but with a different reloc.
4645 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
4650 /* ARM V5 Thumb BLX (argument parse)
4651 BLX <target_addr> which is BLX(1)
4652 BLX <Rm> which is BLX(2)
4653 Unfortunately, there are two different opcodes for this mnemonic.
4654 So, the tinsns[].value is not used, and the code here zaps values
4655 into inst.instruction. */
4658 do_t_blx (char * str
)
4663 skip_whitespace (mystr
);
4664 inst
.instruction
= 0x4780;
4666 /* Note that this call is to the ARM register recognizer. BLX(2)
4667 uses the ARM register space, not the Thumb one, so a call to
4668 thumb_reg() would be wrong. */
4669 rm
= reg_required_here (& mystr
, 3);
4674 /* It's BLX(2). The .instruction was zapped with rm & is final. */
4679 /* No ARM register. This must be BLX(1). Change the .instruction. */
4680 inst
.instruction
= 0xf7ffeffe;
4683 if (my_get_expression (& inst
.reloc
.exp
, & mystr
))
4686 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BLX
;
4687 inst
.reloc
.pc_rel
= 1;
4690 end_of_line (mystr
);
4693 /* ARM V5 breakpoint instruction (argument parse)
4694 BKPT <16 bit unsigned immediate>
4695 Instruction is not conditional.
4696 The bit pattern given in insns[] has the COND_ALWAYS condition,
4697 and it is an error if the caller tried to override that. */
4700 do_bkpt (char * str
)
4703 unsigned long number
;
4705 skip_whitespace (str
);
4707 /* Allow optional leading '#'. */
4708 if (is_immediate_prefix (* str
))
4711 memset (& expr
, '\0', sizeof (expr
));
4713 if (my_get_expression (& expr
, & str
)
4714 || (expr
.X_op
!= O_constant
4715 /* As a convenience we allow 'bkpt' without an operand. */
4716 && expr
.X_op
!= O_absent
))
4718 inst
.error
= _("bad expression");
4722 number
= expr
.X_add_number
;
4724 /* Check it fits a 16 bit unsigned. */
4725 if (number
!= (number
& 0xffff))
4727 inst
.error
= _("immediate value out of range");
4731 /* Top 12 of 16 bits to bits 19:8. */
4732 inst
.instruction
|= (number
& 0xfff0) << 4;
4734 /* Bottom 4 of 16 bits to bits 3:0. */
4735 inst
.instruction
|= number
& 0xf;
4740 /* THUMB CPS instruction (argument parse). */
4743 do_t_cps (char * str
)
4745 do_cps_flags (&str
, /*thumb_p=*/1);
4749 /* Parse and validate that a register is of the right form, this saves
4750 repeated checking of this information in many similar cases.
4751 Unlike the 32-bit case we do not insert the register into the opcode
4752 here, since the position is often unknown until the full instruction
4756 thumb_reg (char ** strp
, int hi_lo
)
4760 if ((reg
= reg_required_here (strp
, -1)) == FAIL
)
4768 inst
.error
= _("lo register required");
4776 inst
.error
= _("hi register required");
4789 thumb_mov_compare (char * str
, int move
)
4793 skip_whitespace (str
);
4795 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
4796 || skip_past_comma (&str
) == FAIL
)
4799 inst
.error
= BAD_ARGS
;
4803 if (move
!= THUMB_CPY
&& is_immediate_prefix (*str
))
4806 if (my_get_expression (&inst
.reloc
.exp
, &str
))
4809 else if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
4814 if (move
!= THUMB_CPY
&& Rs
< 8 && Rd
< 8)
4816 if (move
== THUMB_MOVE
)
4817 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
4818 since a MOV instruction produces unpredictable results. */
4819 inst
.instruction
= T_OPCODE_ADD_I3
;
4821 inst
.instruction
= T_OPCODE_CMP_LR
;
4822 inst
.instruction
|= Rd
| (Rs
<< 3);
4826 if (move
== THUMB_MOVE
)
4827 inst
.instruction
= T_OPCODE_MOV_HR
;
4828 else if (move
!= THUMB_CPY
)
4829 inst
.instruction
= T_OPCODE_CMP_HR
;
4832 inst
.instruction
|= THUMB_H1
;
4835 inst
.instruction
|= THUMB_H2
;
4837 inst
.instruction
|= (Rd
& 7) | ((Rs
& 7) << 3);
4844 inst
.error
= _("only lo regs allowed with immediate");
4848 if (move
== THUMB_MOVE
)
4849 inst
.instruction
= T_OPCODE_MOV_I8
;
4851 inst
.instruction
= T_OPCODE_CMP_I8
;
4853 inst
.instruction
|= Rd
<< 8;
4855 if (inst
.reloc
.exp
.X_op
!= O_constant
)
4856 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_IMM
;
4859 unsigned value
= inst
.reloc
.exp
.X_add_number
;
4863 inst
.error
= _("invalid immediate");
4867 inst
.instruction
|= value
;
4874 /* THUMB CPY instruction (argument parse). */
4877 do_t_cpy (char * str
)
4879 thumb_mov_compare (str
, THUMB_CPY
);
4882 /* THUMB SETEND instruction (argument parse). */
4885 do_t_setend (char * str
)
4887 if (do_endian_specifier (str
))
4888 inst
.instruction
|= 0x8;
4891 /* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
4893 static unsigned long
4894 check_iwmmxt_insn (char * str
,
4895 enum iwmmxt_insn_type insn_type
,
4899 const char * inst_error
;
4901 unsigned long number
;
4903 inst_error
= inst
.error
;
4905 inst
.error
= BAD_ARGS
;
4906 skip_whitespace (str
);
4911 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
4916 if ((wreg_required_here (&str
, 0, IWMMXT_REG_WR
)) == FAIL
)
4921 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
4922 || skip_past_comma (&str
) == FAIL
4923 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
))
4928 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
4929 || skip_past_comma (&str
) == FAIL
4930 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4931 || skip_past_comma (&str
) == FAIL
4932 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
))
4937 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
4938 || skip_past_comma (&str
) == FAIL
4939 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4940 || skip_past_comma (&str
) == FAIL
4941 || wreg_required_here (&str
, 0, IWMMXT_REG_WCG
) == FAIL
))
4946 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4947 || skip_past_comma (&str
) == FAIL
4948 || reg_required_here (&str
, 12) == FAIL
))
4953 if ((reg_required_here (&str
, 12) == FAIL
4954 || skip_past_comma (&str
) == FAIL
4955 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
))
4960 if ((wreg_required_here (&str
, 5, IWMMXT_REG_WR
) == FAIL
4961 || skip_past_comma (&str
) == FAIL
4962 || reg_required_here (&str
, 0) == FAIL
4963 || skip_past_comma (&str
) == FAIL
4964 || reg_required_here (&str
, 12) == FAIL
))
4969 if ((wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
4970 || skip_past_comma (&str
) == FAIL
4971 || reg_required_here (&str
, 12) == FAIL
4972 || skip_past_comma (&str
) == FAIL
4973 || reg_required_here (&str
, 16) == FAIL
))
4978 if ((reg_required_here (&str
, 12) == FAIL
4979 || skip_past_comma (&str
) == FAIL
4980 || reg_required_here (&str
, 16) == FAIL
4981 || skip_past_comma (&str
) == FAIL
4982 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
))
4987 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WC
) == FAIL
4988 || skip_past_comma (&str
) == FAIL
4989 || reg_required_here (&str
, 12) == FAIL
))
4994 if ((reg_required_here (&str
, 12) == FAIL
4995 || skip_past_comma (&str
) == FAIL
4996 || wreg_required_here (&str
, 16, IWMMXT_REG_WC
) == FAIL
))
5001 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5002 || skip_past_comma (&str
) == FAIL
5003 || reg_required_here (&str
, 12) == FAIL
5004 || skip_past_comma (&str
) == FAIL
))
5009 if ((reg_required_here (&str
, 12) == FAIL
5010 || skip_past_comma (&str
) == FAIL
))
5015 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
5016 || skip_past_comma (&str
) == FAIL
5017 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5018 || skip_past_comma (&str
) == FAIL
5019 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
5020 || skip_past_comma (&str
) == FAIL
))
5025 if ((reg_required_here (&str
, 12) == FAIL
5026 || skip_past_comma (&str
) == FAIL
5027 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5028 || skip_past_comma (&str
) == FAIL
))
5033 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
5034 || skip_past_comma (&str
) == FAIL
5035 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5036 || skip_past_comma (&str
) == FAIL
))
5041 if (immediate_size
== 0)
5044 inst
.error
= inst_error
;
5049 skip_whitespace (str
);
5051 /* Allow optional leading '#'. */
5052 if (is_immediate_prefix (* str
))
5055 memset (& expr
, '\0', sizeof (expr
));
5057 if (my_get_expression (& expr
, & str
) || (expr
.X_op
!= O_constant
))
5059 inst
.error
= _("bad or missing expression");
5063 number
= expr
.X_add_number
;
5065 if (number
!= (number
& immediate_size
))
5067 inst
.error
= _("immediate value out of range");
5071 inst
.error
= inst_error
;
5077 do_iwmmxt_byte_addr (char * str
)
5079 int op
= (inst
.instruction
& 0x300) >> 8;
5082 inst
.instruction
&= ~0x300;
5083 inst
.instruction
|= (op
& 1) << 22 | (op
& 2) << 7;
5085 skip_whitespace (str
);
5087 if ((reg
= wreg_required_here (&str
, 12, IWMMXT_REG_WR_OR_WC
)) == FAIL
5088 || skip_past_comma (& str
) == FAIL
5089 || cp_byte_address_required_here (&str
) == FAIL
)
5092 inst
.error
= BAD_ARGS
;
5097 if (wc_register (reg
))
5099 as_bad (_("non-word size not supported with control register"));
5100 inst
.instruction
|= 0xf0000100;
5101 inst
.instruction
&= ~0x00400000;
5106 do_iwmmxt_tandc (char * str
)
5110 reg
= check_iwmmxt_insn (str
, check_rd
, 0);
5112 if (reg
!= REG_PC
&& !inst
.error
)
5113 inst
.error
= _("only r15 allowed here");
5117 do_iwmmxt_tbcst (char * str
)
5119 check_iwmmxt_insn (str
, check_tbcst
, 0);
5123 do_iwmmxt_textrc (char * str
)
5125 unsigned long number
;
5127 if ((number
= check_iwmmxt_insn (str
, check_textrc
, 7)) == (unsigned long) FAIL
)
5130 inst
.instruction
|= number
& 0x7;
5134 do_iwmmxt_textrm (char * str
)
5136 unsigned long number
;
5138 if ((number
= check_iwmmxt_insn (str
, check_textrm
, 7)) == (unsigned long) FAIL
)
5141 inst
.instruction
|= number
& 0x7;
5145 do_iwmmxt_tinsr (char * str
)
5147 unsigned long number
;
5149 if ((number
= check_iwmmxt_insn (str
, check_tinsr
, 7)) == (unsigned long) FAIL
)
5152 inst
.instruction
|= number
& 0x7;
5156 do_iwmmxt_tmcr (char * str
)
5158 check_iwmmxt_insn (str
, check_tmcr
, 0);
5162 do_iwmmxt_tmcrr (char * str
)
5164 check_iwmmxt_insn (str
, check_tmcrr
, 0);
5168 do_iwmmxt_tmia (char * str
)
5170 check_iwmmxt_insn (str
, check_tmia
, 0);
5174 do_iwmmxt_tmovmsk (char * str
)
5176 check_iwmmxt_insn (str
, check_tmovmsk
, 0);
5180 do_iwmmxt_tmrc (char * str
)
5182 check_iwmmxt_insn (str
, check_tmrc
, 0);
5186 do_iwmmxt_tmrrc (char * str
)
5188 check_iwmmxt_insn (str
, check_tmrrc
, 0);
5192 do_iwmmxt_torc (char * str
)
5194 check_iwmmxt_insn (str
, check_rd
, 0);
5198 do_iwmmxt_waligni (char * str
)
5200 unsigned long number
;
5202 if ((number
= check_iwmmxt_insn (str
, check_waligni
, 7)) == (unsigned long) FAIL
)
5205 inst
.instruction
|= ((number
& 0x7) << 20);
5209 do_iwmmxt_wmov (char * str
)
5211 if (check_iwmmxt_insn (str
, check_wrwr
, 0) == (unsigned long) FAIL
)
5214 inst
.instruction
|= ((inst
.instruction
>> 16) & 0xf);
5218 do_iwmmxt_word_addr (char * str
)
5220 int op
= (inst
.instruction
& 0x300) >> 8;
5223 inst
.instruction
&= ~0x300;
5224 inst
.instruction
|= (op
& 1) << 22 | (op
& 2) << 7;
5226 skip_whitespace (str
);
5228 if ((reg
= wreg_required_here (&str
, 12, IWMMXT_REG_WR_OR_WC
)) == FAIL
5229 || skip_past_comma (& str
) == FAIL
5230 || cp_address_required_here (& str
, CP_WB_OK
) == FAIL
)
5233 inst
.error
= BAD_ARGS
;
5238 if (wc_register (reg
))
5240 if ((inst
.instruction
& COND_MASK
) != COND_ALWAYS
)
5241 as_bad (_("conditional execution not supported with control register"));
5243 as_bad (_("non-word size not supported with control register"));
5244 inst
.instruction
|= 0xf0000100;
5245 inst
.instruction
&= ~0x00400000;
5250 do_iwmmxt_wrwr (char * str
)
5252 check_iwmmxt_insn (str
, check_wrwr
, 0);
5256 do_iwmmxt_wrwrwcg (char * str
)
5258 check_iwmmxt_insn (str
, check_wrwrwcg
, 0);
5262 do_iwmmxt_wrwrwr (char * str
)
5264 check_iwmmxt_insn (str
, check_wrwrwr
, 0);
5268 do_iwmmxt_wshufh (char * str
)
5270 unsigned long number
;
5272 if ((number
= check_iwmmxt_insn (str
, check_wshufh
, 0xff)) == (unsigned long) FAIL
)
5275 inst
.instruction
|= ((number
& 0xf0) << 16) | (number
& 0xf);
5279 do_iwmmxt_wzero (char * str
)
5281 if (check_iwmmxt_insn (str
, check_wr
, 0) == (unsigned long) FAIL
)
5284 inst
.instruction
|= ((inst
.instruction
& 0xf) << 12) | ((inst
.instruction
& 0xf) << 16);
5287 /* Xscale multiply-accumulate (argument parse)
5290 MIAxycc acc0,Rm,Rs. */
5293 do_xsc_mia (char * str
)
5298 if (accum0_required_here (& str
) == FAIL
)
5299 inst
.error
= ERR_NO_ACCUM
;
5301 else if (skip_past_comma (& str
) == FAIL
5302 || (rm
= reg_required_here (& str
, 0)) == FAIL
)
5303 inst
.error
= BAD_ARGS
;
5305 else if (skip_past_comma (& str
) == FAIL
5306 || (rs
= reg_required_here (& str
, 12)) == FAIL
)
5307 inst
.error
= BAD_ARGS
;
5309 /* inst.instruction has now been zapped with both rm and rs. */
5310 else if (rm
== REG_PC
|| rs
== REG_PC
)
5311 inst
.error
= BAD_PC
; /* Undefined result if rm or rs is R15. */
5317 /* Xscale move-accumulator-register (argument parse)
5319 MARcc acc0,RdLo,RdHi. */
5322 do_xsc_mar (char * str
)
5326 if (accum0_required_here (& str
) == FAIL
)
5327 inst
.error
= ERR_NO_ACCUM
;
5329 else if (skip_past_comma (& str
) == FAIL
5330 || (rdlo
= reg_required_here (& str
, 12)) == FAIL
)
5331 inst
.error
= BAD_ARGS
;
5333 else if (skip_past_comma (& str
) == FAIL
5334 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
5335 inst
.error
= BAD_ARGS
;
5337 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5338 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
5339 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
5345 /* Xscale move-register-accumulator (argument parse)
5347 MRAcc RdLo,RdHi,acc0. */
5350 do_xsc_mra (char * str
)
5355 skip_whitespace (str
);
5357 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
)
5358 inst
.error
= BAD_ARGS
;
5360 else if (skip_past_comma (& str
) == FAIL
5361 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
5362 inst
.error
= BAD_ARGS
;
5364 else if (skip_past_comma (& str
) == FAIL
5365 || accum0_required_here (& str
) == FAIL
)
5366 inst
.error
= ERR_NO_ACCUM
;
5368 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5369 else if (rdlo
== rdhi
)
5370 inst
.error
= BAD_ARGS
; /* Undefined result if 2 writes to same reg. */
5372 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
5373 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
5379 ldst_extend (char ** str
)
5388 if (my_get_expression (& inst
.reloc
.exp
, str
))
5391 if (inst
.reloc
.exp
.X_op
== O_constant
)
5393 int value
= inst
.reloc
.exp
.X_add_number
;
5395 if (value
< -4095 || value
> 4095)
5397 inst
.error
= _("address offset too large");
5407 inst
.instruction
|= add
| value
;
5411 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
5412 inst
.reloc
.pc_rel
= 0;
5425 if (reg_required_here (str
, 0) == FAIL
)
5428 inst
.instruction
|= add
| OFFSET_REG
;
5429 if (skip_past_comma (str
) == SUCCESS
)
5430 return decode_shift (str
, SHIFT_IMMEDIATE
);
5436 /* ARMv5TE: Preload-Cache
5440 Syntactically, like LDR with B=1, W=0, L=1. */
5447 skip_whitespace (str
);
5451 inst
.error
= _("'[' expected after PLD mnemonic");
5456 skip_whitespace (str
);
5458 if ((rd
= reg_required_here (& str
, 16)) == FAIL
)
5461 skip_whitespace (str
);
5467 skip_whitespace (str
);
5469 /* Post-indexed addressing is not allowed with PLD. */
5470 if (skip_past_comma (&str
) == SUCCESS
)
5473 = _("post-indexed expression used in preload instruction");
5476 else if (*str
== '!') /* [Rn]! */
5478 inst
.error
= _("writeback used in preload instruction");
5482 inst
.instruction
|= INDEX_UP
| PRE_INDEX
;
5484 else /* [Rn, ...] */
5486 if (skip_past_comma (& str
) == FAIL
)
5488 inst
.error
= _("pre-indexed expression expected");
5492 if (ldst_extend (&str
) == FAIL
)
5495 skip_whitespace (str
);
5499 inst
.error
= _("missing ]");
5504 skip_whitespace (str
);
5506 if (* str
== '!') /* [Rn]! */
5508 inst
.error
= _("writeback used in preload instruction");
5512 inst
.instruction
|= PRE_INDEX
;
5518 /* ARMv5TE load-consecutive (argument parse)
5525 do_ldrd (char * str
)
5530 skip_whitespace (str
);
5532 if ((rd
= reg_required_here (& str
, 12)) == FAIL
)
5534 inst
.error
= BAD_ARGS
;
5538 if (skip_past_comma (& str
) == FAIL
5539 || (rn
= ld_mode_required_here (& str
)) == FAIL
)
5542 inst
.error
= BAD_ARGS
;
5546 /* inst.instruction has now been zapped with Rd and the addressing mode. */
5547 if (rd
& 1) /* Unpredictable result if Rd is odd. */
5549 inst
.error
= _("destination register must be even");
5555 inst
.error
= _("r14 not allowed here");
5559 if (((rd
== rn
) || (rd
+ 1 == rn
))
5560 && ((inst
.instruction
& WRITE_BACK
)
5561 || (!(inst
.instruction
& PRE_INDEX
))))
5562 as_warn (_("pre/post-indexing used when modified address register is destination"));
5564 /* For an index-register load, the index register must not overlap the
5565 destination (even if not write-back). */
5566 if ((inst
.instruction
& V4_STR_BIT
) == 0
5567 && (inst
.instruction
& HWOFFSET_IMM
) == 0)
5569 int rm
= inst
.instruction
& 0x0000000f;
5571 if (rm
== rd
|| (rm
== rd
+ 1))
5572 as_warn (_("ldrd destination registers must not overlap index register"));
5578 /* Returns the index into fp_values of a floating point number,
5579 or -1 if not in the table. */
5582 my_get_float_expression (char ** str
)
5584 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
5590 memset (words
, 0, MAX_LITTLENUMS
* sizeof (LITTLENUM_TYPE
));
5592 /* Look for a raw floating point number. */
5593 if ((save_in
= atof_ieee (*str
, 'x', words
)) != NULL
5594 && is_end_of_line
[(unsigned char) *save_in
])
5596 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
5598 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
5600 if (words
[j
] != fp_values
[i
][j
])
5604 if (j
== MAX_LITTLENUMS
)
5612 /* Try and parse a more complex expression, this will probably fail
5613 unless the code uses a floating point prefix (eg "0f"). */
5614 save_in
= input_line_pointer
;
5615 input_line_pointer
= *str
;
5616 if (expression (&exp
) == absolute_section
5617 && exp
.X_op
== O_big
5618 && exp
.X_add_number
< 0)
5620 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
5622 if (gen_to_words (words
, 5, (long) 15) == 0)
5624 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
5626 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
5628 if (words
[j
] != fp_values
[i
][j
])
5632 if (j
== MAX_LITTLENUMS
)
5634 *str
= input_line_pointer
;
5635 input_line_pointer
= save_in
;
5642 *str
= input_line_pointer
;
5643 input_line_pointer
= save_in
;
5647 /* We handle all bad expressions here, so that we can report the faulty
5648 instruction in the error message. */
5650 md_operand (expressionS
* expr
)
5652 if (in_my_get_expression
)
5654 expr
->X_op
= O_illegal
;
5655 if (inst
.error
== NULL
)
5656 inst
.error
= _("bad expression");
5660 /* Do those data_ops which can take a negative immediate constant
5661 by altering the instruction. A bit of a hack really.
5665 by inverting the second operand, and
5668 by negating the second operand. */
5671 negate_data_op (unsigned long * instruction
,
5672 unsigned long value
)
5675 unsigned long negated
, inverted
;
5677 negated
= validate_immediate (-value
);
5678 inverted
= validate_immediate (~value
);
5680 op
= (*instruction
>> DATA_OP_SHIFT
) & 0xf;
5683 /* First negates. */
5684 case OPCODE_SUB
: /* ADD <-> SUB */
5685 new_inst
= OPCODE_ADD
;
5690 new_inst
= OPCODE_SUB
;
5694 case OPCODE_CMP
: /* CMP <-> CMN */
5695 new_inst
= OPCODE_CMN
;
5700 new_inst
= OPCODE_CMP
;
5704 /* Now Inverted ops. */
5705 case OPCODE_MOV
: /* MOV <-> MVN */
5706 new_inst
= OPCODE_MVN
;
5711 new_inst
= OPCODE_MOV
;
5715 case OPCODE_AND
: /* AND <-> BIC */
5716 new_inst
= OPCODE_BIC
;
5721 new_inst
= OPCODE_AND
;
5725 case OPCODE_ADC
: /* ADC <-> SBC */
5726 new_inst
= OPCODE_SBC
;
5731 new_inst
= OPCODE_ADC
;
5735 /* We cannot do anything. */
5740 if (value
== (unsigned) FAIL
)
5743 *instruction
&= OPCODE_MASK
;
5744 *instruction
|= new_inst
<< DATA_OP_SHIFT
;
5749 data_op2 (char ** str
)
5754 skip_whitespace (* str
);
5756 if (reg_required_here (str
, 0) != FAIL
)
5758 if (skip_past_comma (str
) == SUCCESS
)
5759 /* Shift operation on register. */
5760 return decode_shift (str
, NO_SHIFT_RESTRICT
);
5766 /* Immediate expression. */
5767 if (is_immediate_prefix (**str
))
5772 if (my_get_expression (&inst
.reloc
.exp
, str
))
5775 if (inst
.reloc
.exp
.X_add_symbol
)
5777 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
5778 inst
.reloc
.pc_rel
= 0;
5782 if (skip_past_comma (str
) == SUCCESS
)
5784 /* #x, y -- ie explicit rotation by Y. */
5785 if (my_get_expression (&expr
, str
))
5788 if (expr
.X_op
!= O_constant
)
5790 inst
.error
= _("constant expression expected");
5794 /* Rotate must be a multiple of 2. */
5795 if (((unsigned) expr
.X_add_number
) > 30
5796 || (expr
.X_add_number
& 1) != 0
5797 || ((unsigned) inst
.reloc
.exp
.X_add_number
) > 255)
5799 inst
.error
= _("invalid constant");
5802 inst
.instruction
|= INST_IMMEDIATE
;
5803 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
5804 inst
.instruction
|= expr
.X_add_number
<< 7;
5808 /* Implicit rotation, select a suitable one. */
5809 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
5813 /* Can't be done. Perhaps the code reads something like
5814 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
5815 if ((value
= negate_data_op (&inst
.instruction
,
5816 inst
.reloc
.exp
.X_add_number
))
5819 inst
.error
= _("invalid constant");
5824 inst
.instruction
|= value
;
5827 inst
.instruction
|= INST_IMMEDIATE
;
5832 inst
.error
= _("register or shift expression expected");
5838 fp_op2 (char ** str
)
5840 skip_whitespace (* str
);
5842 if (fp_reg_required_here (str
, 0) != FAIL
)
5846 /* Immediate expression. */
5847 if (*((*str
)++) == '#')
5853 skip_whitespace (* str
);
5855 /* First try and match exact strings, this is to guarantee
5856 that some formats will work even for cross assembly. */
5858 for (i
= 0; fp_const
[i
]; i
++)
5860 if (strncmp (*str
, fp_const
[i
], strlen (fp_const
[i
])) == 0)
5864 *str
+= strlen (fp_const
[i
]);
5865 if (is_end_of_line
[(unsigned char) **str
])
5867 inst
.instruction
|= i
+ 8;
5874 /* Just because we didn't get a match doesn't mean that the
5875 constant isn't valid, just that it is in a format that we
5876 don't automatically recognize. Try parsing it with
5877 the standard expression routines. */
5878 if ((i
= my_get_float_expression (str
)) >= 0)
5880 inst
.instruction
|= i
+ 8;
5884 inst
.error
= _("invalid floating point immediate expression");
5888 _("floating point register or immediate expression expected");
5894 do_arit (char * str
)
5896 skip_whitespace (str
);
5898 if (reg_required_here (&str
, 12) == FAIL
5899 || skip_past_comma (&str
) == FAIL
5900 || reg_required_here (&str
, 16) == FAIL
5901 || skip_past_comma (&str
) == FAIL
5902 || data_op2 (&str
) == FAIL
)
5905 inst
.error
= BAD_ARGS
;
5915 /* This is a pseudo-op of the form "adr rd, label" to be converted
5916 into a relative address of the form "add rd, pc, #label-.-8". */
5917 skip_whitespace (str
);
5919 if (reg_required_here (&str
, 12) == FAIL
5920 || skip_past_comma (&str
) == FAIL
5921 || my_get_expression (&inst
.reloc
.exp
, &str
))
5924 inst
.error
= BAD_ARGS
;
5928 /* Frag hacking will turn this into a sub instruction if the offset turns
5929 out to be negative. */
5930 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
5932 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust. */
5934 inst
.reloc
.pc_rel
= 1;
5940 do_adrl (char * str
)
5942 /* This is a pseudo-op of the form "adrl rd, label" to be converted
5943 into a relative address of the form:
5944 add rd, pc, #low(label-.-8)"
5945 add rd, rd, #high(label-.-8)" */
5947 skip_whitespace (str
);
5949 if (reg_required_here (&str
, 12) == FAIL
5950 || skip_past_comma (&str
) == FAIL
5951 || my_get_expression (&inst
.reloc
.exp
, &str
))
5954 inst
.error
= BAD_ARGS
;
5960 /* Frag hacking will turn this into a sub instruction if the offset turns
5961 out to be negative. */
5962 inst
.reloc
.type
= BFD_RELOC_ARM_ADRL_IMMEDIATE
;
5964 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust */
5966 inst
.reloc
.pc_rel
= 1;
5967 inst
.size
= INSN_SIZE
* 2;
5973 skip_whitespace (str
);
5975 if (reg_required_here (&str
, 16) == FAIL
)
5978 inst
.error
= BAD_ARGS
;
5982 if (skip_past_comma (&str
) == FAIL
5983 || data_op2 (&str
) == FAIL
)
5986 inst
.error
= BAD_ARGS
;
5996 skip_whitespace (str
);
5998 if (reg_required_here (&str
, 12) == FAIL
)
6001 inst
.error
= BAD_ARGS
;
6005 if (skip_past_comma (&str
) == FAIL
6006 || data_op2 (&str
) == FAIL
)
6009 inst
.error
= BAD_ARGS
;
6017 do_ldst (char * str
)
6023 skip_whitespace (str
);
6025 if ((conflict_reg
= reg_required_here (&str
, 12)) == FAIL
)
6028 inst
.error
= BAD_ARGS
;
6032 if (skip_past_comma (&str
) == FAIL
)
6034 inst
.error
= _("address expected");
6044 skip_whitespace (str
);
6046 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6049 /* Conflicts can occur on stores as well as loads. */
6050 conflict_reg
= (conflict_reg
== reg
);
6052 skip_whitespace (str
);
6058 if (skip_past_comma (&str
) == SUCCESS
)
6060 /* [Rn],... (post inc) */
6061 if (ldst_extend (&str
) == FAIL
)
6064 as_warn (_("%s register same as write-back base"),
6065 ((inst
.instruction
& LOAD_BIT
)
6066 ? _("destination") : _("source")));
6071 skip_whitespace (str
);
6076 as_warn (_("%s register same as write-back base"),
6077 ((inst
.instruction
& LOAD_BIT
)
6078 ? _("destination") : _("source")));
6080 inst
.instruction
|= WRITE_BACK
;
6083 inst
.instruction
|= INDEX_UP
;
6090 if (skip_past_comma (&str
) == FAIL
)
6092 inst
.error
= _("pre-indexed expression expected");
6097 if (ldst_extend (&str
) == FAIL
)
6100 skip_whitespace (str
);
6104 inst
.error
= _("missing ]");
6108 skip_whitespace (str
);
6113 as_warn (_("%s register same as write-back base"),
6114 ((inst
.instruction
& LOAD_BIT
)
6115 ? _("destination") : _("source")));
6117 inst
.instruction
|= WRITE_BACK
;
6121 else if (*str
== '=')
6123 if ((inst
.instruction
& LOAD_BIT
) == 0)
6125 inst
.error
= _("invalid pseudo operation");
6129 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6132 skip_whitespace (str
);
6134 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6137 if (inst
.reloc
.exp
.X_op
!= O_constant
6138 && inst
.reloc
.exp
.X_op
!= O_symbol
)
6140 inst
.error
= _("constant expression expected");
6144 if (inst
.reloc
.exp
.X_op
== O_constant
)
6146 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
6150 /* This can be done with a mov instruction. */
6151 inst
.instruction
&= LITERAL_MASK
;
6152 inst
.instruction
|= (INST_IMMEDIATE
6153 | (OPCODE_MOV
<< DATA_OP_SHIFT
));
6154 inst
.instruction
|= value
& 0xfff;
6159 value
= validate_immediate (~inst
.reloc
.exp
.X_add_number
);
6163 /* This can be done with a mvn instruction. */
6164 inst
.instruction
&= LITERAL_MASK
;
6165 inst
.instruction
|= (INST_IMMEDIATE
6166 | (OPCODE_MVN
<< DATA_OP_SHIFT
));
6167 inst
.instruction
|= value
& 0xfff;
6173 /* Insert into literal pool. */
6174 if (add_to_lit_pool () == FAIL
)
6177 inst
.error
= _("literal pool insertion failed");
6181 /* Change the instruction exp to point to the pool. */
6182 inst
.reloc
.type
= BFD_RELOC_ARM_LITERAL
;
6183 inst
.reloc
.pc_rel
= 1;
6184 inst
.instruction
|= (REG_PC
<< 16);
6189 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6192 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
6194 /* PC rel adjust. */
6195 inst
.reloc
.exp
.X_add_number
-= 8;
6197 inst
.reloc
.pc_rel
= 1;
6198 inst
.instruction
|= (REG_PC
<< 16);
6202 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
6207 do_ldstt (char * str
)
6211 skip_whitespace (str
);
6213 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
6216 inst
.error
= BAD_ARGS
;
6220 if (skip_past_comma (& str
) == FAIL
)
6222 inst
.error
= _("address expected");
6232 skip_whitespace (str
);
6234 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6237 /* ldrt/strt always use post-indexed addressing, so if the base is
6238 the same as Rd, we warn. */
6239 if (conflict_reg
== reg
)
6240 as_warn (_("%s register same as write-back base"),
6241 ((inst
.instruction
& LOAD_BIT
)
6242 ? _("destination") : _("source")));
6244 skip_whitespace (str
);
6250 if (skip_past_comma (&str
) == SUCCESS
)
6252 /* [Rn],... (post inc) */
6253 if (ldst_extend (&str
) == FAIL
)
6259 skip_whitespace (str
);
6261 /* Skip a write-back '!'. */
6265 inst
.instruction
|= INDEX_UP
;
6270 inst
.error
= _("post-indexed expression expected");
6276 inst
.error
= _("post-indexed expression expected");
6283 /* Halfword and signed-byte load/store operations. */
6286 do_ldstv4 (char * str
)
6292 skip_whitespace (str
);
6294 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
6297 inst
.error
= BAD_ARGS
;
6301 if (skip_past_comma (& str
) == FAIL
)
6303 inst
.error
= _("address expected");
6313 skip_whitespace (str
);
6315 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6318 /* Conflicts can occur on stores as well as loads. */
6319 conflict_reg
= (conflict_reg
== reg
);
6321 skip_whitespace (str
);
6327 if (skip_past_comma (&str
) == SUCCESS
)
6329 /* [Rn],... (post inc) */
6330 if (ldst_extend_v4 (&str
) == FAIL
)
6333 as_warn (_("%s register same as write-back base"),
6334 ((inst
.instruction
& LOAD_BIT
)
6335 ? _("destination") : _("source")));
6340 inst
.instruction
|= HWOFFSET_IMM
;
6342 skip_whitespace (str
);
6347 as_warn (_("%s register same as write-back base"),
6348 ((inst
.instruction
& LOAD_BIT
)
6349 ? _("destination") : _("source")));
6351 inst
.instruction
|= WRITE_BACK
;
6354 inst
.instruction
|= INDEX_UP
;
6361 if (skip_past_comma (&str
) == FAIL
)
6363 inst
.error
= _("pre-indexed expression expected");
6368 if (ldst_extend_v4 (&str
) == FAIL
)
6371 skip_whitespace (str
);
6375 inst
.error
= _("missing ]");
6379 skip_whitespace (str
);
6384 as_warn (_("%s register same as write-back base"),
6385 ((inst
.instruction
& LOAD_BIT
)
6386 ? _("destination") : _("source")));
6388 inst
.instruction
|= WRITE_BACK
;
6392 else if (*str
== '=')
6394 if ((inst
.instruction
& LOAD_BIT
) == 0)
6396 inst
.error
= _("invalid pseudo operation");
6400 /* XXX Does this work correctly for half-word/byte ops? */
6401 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6404 skip_whitespace (str
);
6406 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6409 if (inst
.reloc
.exp
.X_op
!= O_constant
6410 && inst
.reloc
.exp
.X_op
!= O_symbol
)
6412 inst
.error
= _("constant expression expected");
6416 if (inst
.reloc
.exp
.X_op
== O_constant
)
6418 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
6422 /* This can be done with a mov instruction. */
6423 inst
.instruction
&= LITERAL_MASK
;
6424 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MOV
<< DATA_OP_SHIFT
);
6425 inst
.instruction
|= value
& 0xfff;
6430 value
= validate_immediate (~ inst
.reloc
.exp
.X_add_number
);
6434 /* This can be done with a mvn instruction. */
6435 inst
.instruction
&= LITERAL_MASK
;
6436 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MVN
<< DATA_OP_SHIFT
);
6437 inst
.instruction
|= value
& 0xfff;
6443 /* Insert into literal pool. */
6444 if (add_to_lit_pool () == FAIL
)
6447 inst
.error
= _("literal pool insertion failed");
6451 /* Change the instruction exp to point to the pool. */
6452 inst
.instruction
|= HWOFFSET_IMM
;
6453 inst
.reloc
.type
= BFD_RELOC_ARM_HWLITERAL
;
6454 inst
.reloc
.pc_rel
= 1;
6455 inst
.instruction
|= (REG_PC
<< 16);
6460 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6463 inst
.instruction
|= HWOFFSET_IMM
;
6464 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
6466 /* PC rel adjust. */
6467 inst
.reloc
.exp
.X_add_number
-= 8;
6469 inst
.reloc
.pc_rel
= 1;
6470 inst
.instruction
|= (REG_PC
<< 16);
6474 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
6479 reg_list (char ** strp
)
6481 char * str
= * strp
;
6485 /* We come back here if we get ranges concatenated by '+' or '|'. */
6500 skip_whitespace (str
);
6502 if ((reg
= reg_required_here (& str
, -1)) == FAIL
)
6511 inst
.error
= _("bad range in register list");
6515 for (i
= cur_reg
+ 1; i
< reg
; i
++)
6517 if (range
& (1 << i
))
6519 (_("Warning: duplicated register (r%d) in register list"),
6527 if (range
& (1 << reg
))
6528 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
6530 else if (reg
<= cur_reg
)
6531 as_tsktsk (_("Warning: register range not in ascending order"));
6536 while (skip_past_comma (&str
) != FAIL
6537 || (in_range
= 1, *str
++ == '-'));
6539 skip_whitespace (str
);
6543 inst
.error
= _("missing `}'");
6551 if (my_get_expression (&expr
, &str
))
6554 if (expr
.X_op
== O_constant
)
6556 if (expr
.X_add_number
6557 != (expr
.X_add_number
& 0x0000ffff))
6559 inst
.error
= _("invalid register mask");
6563 if ((range
& expr
.X_add_number
) != 0)
6565 int regno
= range
& expr
.X_add_number
;
6568 regno
= (1 << regno
) - 1;
6570 (_("Warning: duplicated register (r%d) in register list"),
6574 range
|= expr
.X_add_number
;
6578 if (inst
.reloc
.type
!= 0)
6580 inst
.error
= _("expression too complex");
6584 memcpy (&inst
.reloc
.exp
, &expr
, sizeof (expressionS
));
6585 inst
.reloc
.type
= BFD_RELOC_ARM_MULTI
;
6586 inst
.reloc
.pc_rel
= 0;
6590 skip_whitespace (str
);
6592 if (*str
== '|' || *str
== '+')
6598 while (another_range
);
6605 do_ldmstm (char * str
)
6610 skip_whitespace (str
);
6612 if ((base_reg
= reg_required_here (&str
, 16)) == FAIL
)
6615 if (base_reg
== REG_PC
)
6617 inst
.error
= _("r15 not allowed as base register");
6621 skip_whitespace (str
);
6625 inst
.instruction
|= WRITE_BACK
;
6629 if (skip_past_comma (&str
) == FAIL
6630 || (range
= reg_list (&str
)) == FAIL
)
6633 inst
.error
= BAD_ARGS
;
6640 inst
.instruction
|= LDM_TYPE_2_OR_3
;
6643 if (inst
.instruction
& WRITE_BACK
)
6645 /* Check for unpredictable uses of writeback. */
6646 if (inst
.instruction
& LOAD_BIT
)
6648 /* Not allowed in LDM type 2. */
6649 if ((inst
.instruction
& LDM_TYPE_2_OR_3
)
6650 && ((range
& (1 << REG_PC
)) == 0))
6651 as_warn (_("writeback of base register is UNPREDICTABLE"));
6652 /* Only allowed if base reg not in list for other types. */
6653 else if (range
& (1 << base_reg
))
6654 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
6658 /* Not allowed for type 2. */
6659 if (inst
.instruction
& LDM_TYPE_2_OR_3
)
6660 as_warn (_("writeback of base register is UNPREDICTABLE"));
6661 /* Only allowed if base reg not in list, or first in list. */
6662 else if ((range
& (1 << base_reg
))
6663 && (range
& ((1 << base_reg
) - 1)))
6664 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
6668 inst
.instruction
|= range
;
6675 skip_whitespace (str
);
6677 /* Allow optional leading '#'. */
6678 if (is_immediate_prefix (*str
))
6681 if (my_get_expression (& inst
.reloc
.exp
, & str
))
6684 inst
.reloc
.type
= BFD_RELOC_ARM_SMI
;
6685 inst
.reloc
.pc_rel
= 0;
6692 skip_whitespace (str
);
6694 /* Allow optional leading '#'. */
6695 if (is_immediate_prefix (*str
))
6698 if (my_get_expression (& inst
.reloc
.exp
, & str
))
6701 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
6702 inst
.reloc
.pc_rel
= 0;
6707 do_swap (char * str
)
6711 skip_whitespace (str
);
6713 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
6718 inst
.error
= _("r15 not allowed in swap");
6722 if (skip_past_comma (&str
) == FAIL
6723 || (reg
= reg_required_here (&str
, 0)) == FAIL
)
6726 inst
.error
= BAD_ARGS
;
6732 inst
.error
= _("r15 not allowed in swap");
6736 if (skip_past_comma (&str
) == FAIL
6739 inst
.error
= BAD_ARGS
;
6743 skip_whitespace (str
);
6745 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6750 inst
.error
= BAD_PC
;
6754 skip_whitespace (str
);
6758 inst
.error
= _("missing ]");
6766 do_branch (char * str
)
6768 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6775 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
6776 required for the instruction. */
6778 /* arm_parse_reloc () works on input_line_pointer.
6779 We actually want to parse the operands to the branch instruction
6780 passed in 'str'. Save the input pointer and restore it later. */
6781 save_in
= input_line_pointer
;
6782 input_line_pointer
= str
;
6783 if (inst
.reloc
.exp
.X_op
== O_symbol
6785 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
6787 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
6788 inst
.reloc
.pc_rel
= 0;
6789 /* Modify str to point to after parsed operands, otherwise
6790 end_of_line() will complain about the (PLT) left in str. */
6791 str
= input_line_pointer
;
6795 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
6796 inst
.reloc
.pc_rel
= 1;
6798 input_line_pointer
= save_in
;
6801 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
6802 inst
.reloc
.pc_rel
= 1;
6803 #endif /* OBJ_ELF */
6811 /* Co-processor data operation.
6812 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
6813 skip_whitespace (str
);
6815 if (co_proc_number (&str
) == FAIL
)
6818 inst
.error
= BAD_ARGS
;
6822 if (skip_past_comma (&str
) == FAIL
6823 || cp_opc_expr (&str
, 20,4) == FAIL
)
6826 inst
.error
= BAD_ARGS
;
6830 if (skip_past_comma (&str
) == FAIL
6831 || cp_reg_required_here (&str
, 12) == FAIL
)
6834 inst
.error
= BAD_ARGS
;
6838 if (skip_past_comma (&str
) == FAIL
6839 || cp_reg_required_here (&str
, 16) == FAIL
)
6842 inst
.error
= BAD_ARGS
;
6846 if (skip_past_comma (&str
) == FAIL
6847 || cp_reg_required_here (&str
, 0) == FAIL
)
6850 inst
.error
= BAD_ARGS
;
6854 if (skip_past_comma (&str
) == SUCCESS
)
6856 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
6859 inst
.error
= BAD_ARGS
;
6868 do_lstc (char * str
)
6870 /* Co-processor register load/store.
6871 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
6873 skip_whitespace (str
);
6875 if (co_proc_number (&str
) == FAIL
)
6878 inst
.error
= BAD_ARGS
;
6882 if (skip_past_comma (&str
) == FAIL
6883 || cp_reg_required_here (&str
, 12) == FAIL
)
6886 inst
.error
= BAD_ARGS
;
6890 if (skip_past_comma (&str
) == FAIL
6891 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
6894 inst
.error
= BAD_ARGS
;
6902 do_co_reg (char * str
)
6904 /* Co-processor register transfer.
6905 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
6907 skip_whitespace (str
);
6909 if (co_proc_number (&str
) == FAIL
)
6912 inst
.error
= BAD_ARGS
;
6916 if (skip_past_comma (&str
) == FAIL
6917 || cp_opc_expr (&str
, 21, 3) == FAIL
)
6920 inst
.error
= BAD_ARGS
;
6924 if (skip_past_comma (&str
) == FAIL
6925 || reg_required_here (&str
, 12) == FAIL
)
6928 inst
.error
= BAD_ARGS
;
6932 if (skip_past_comma (&str
) == FAIL
6933 || cp_reg_required_here (&str
, 16) == FAIL
)
6936 inst
.error
= BAD_ARGS
;
6940 if (skip_past_comma (&str
) == FAIL
6941 || cp_reg_required_here (&str
, 0) == FAIL
)
6944 inst
.error
= BAD_ARGS
;
6948 if (skip_past_comma (&str
) == SUCCESS
)
6950 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
6953 inst
.error
= BAD_ARGS
;
6962 do_fpa_ctrl (char * str
)
6964 /* FP control registers.
6965 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
6967 skip_whitespace (str
);
6969 if (reg_required_here (&str
, 12) == FAIL
)
6972 inst
.error
= BAD_ARGS
;
6980 do_fpa_ldst (char * str
)
6982 skip_whitespace (str
);
6984 if (fp_reg_required_here (&str
, 12) == FAIL
)
6987 inst
.error
= BAD_ARGS
;
6991 if (skip_past_comma (&str
) == FAIL
6992 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
6995 inst
.error
= BAD_ARGS
;
7003 do_fpa_ldmstm (char * str
)
7007 skip_whitespace (str
);
7009 if (fp_reg_required_here (&str
, 12) == FAIL
)
7012 inst
.error
= BAD_ARGS
;
7016 /* Get Number of registers to transfer. */
7017 if (skip_past_comma (&str
) == FAIL
7018 || my_get_expression (&inst
.reloc
.exp
, &str
))
7021 inst
.error
= _("constant expression expected");
7025 if (inst
.reloc
.exp
.X_op
!= O_constant
)
7027 inst
.error
= _("constant value required for number of registers");
7031 num_regs
= inst
.reloc
.exp
.X_add_number
;
7033 if (num_regs
< 1 || num_regs
> 4)
7035 inst
.error
= _("number of registers must be in the range [1:4]");
7042 inst
.instruction
|= CP_T_X
;
7045 inst
.instruction
|= CP_T_Y
;
7048 inst
.instruction
|= CP_T_Y
| CP_T_X
;
7056 if (inst
.instruction
& (CP_T_Pre
| CP_T_UD
)) /* ea/fd format. */
7062 /* The instruction specified "ea" or "fd", so we can only accept
7063 [Rn]{!}. The instruction does not really support stacking or
7064 unstacking, so we have to emulate these by setting appropriate
7065 bits and offsets. */
7066 if (skip_past_comma (&str
) == FAIL
7070 inst
.error
= BAD_ARGS
;
7075 skip_whitespace (str
);
7077 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
7080 skip_whitespace (str
);
7084 inst
.error
= BAD_ARGS
;
7096 _("r15 not allowed as base register with write-back");
7103 if (inst
.instruction
& CP_T_Pre
)
7105 /* Pre-decrement. */
7106 offset
= 3 * num_regs
;
7108 inst
.instruction
|= CP_T_WB
;
7112 /* Post-increment. */
7115 inst
.instruction
|= CP_T_WB
;
7116 offset
= 3 * num_regs
;
7120 /* No write-back, so convert this into a standard pre-increment
7121 instruction -- aesthetically more pleasing. */
7122 inst
.instruction
|= CP_T_Pre
| CP_T_UD
;
7127 inst
.instruction
|= offset
;
7129 else if (skip_past_comma (&str
) == FAIL
7130 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
7133 inst
.error
= BAD_ARGS
;
7141 do_fpa_dyadic (char * str
)
7143 skip_whitespace (str
);
7145 if (fp_reg_required_here (&str
, 12) == FAIL
)
7148 inst
.error
= BAD_ARGS
;
7152 if (skip_past_comma (&str
) == FAIL
7153 || fp_reg_required_here (&str
, 16) == FAIL
)
7156 inst
.error
= BAD_ARGS
;
7160 if (skip_past_comma (&str
) == FAIL
7161 || fp_op2 (&str
) == FAIL
)
7164 inst
.error
= BAD_ARGS
;
7172 do_fpa_monadic (char * str
)
7174 skip_whitespace (str
);
7176 if (fp_reg_required_here (&str
, 12) == FAIL
)
7179 inst
.error
= BAD_ARGS
;
7183 if (skip_past_comma (&str
) == FAIL
7184 || fp_op2 (&str
) == FAIL
)
7187 inst
.error
= BAD_ARGS
;
7195 do_fpa_cmp (char * str
)
7197 skip_whitespace (str
);
7199 if (fp_reg_required_here (&str
, 16) == FAIL
)
7202 inst
.error
= BAD_ARGS
;
7206 if (skip_past_comma (&str
) == FAIL
7207 || fp_op2 (&str
) == FAIL
)
7210 inst
.error
= BAD_ARGS
;
7218 do_fpa_from_reg (char * str
)
7220 skip_whitespace (str
);
7222 if (fp_reg_required_here (&str
, 16) == FAIL
)
7225 inst
.error
= BAD_ARGS
;
7229 if (skip_past_comma (&str
) == FAIL
7230 || reg_required_here (&str
, 12) == FAIL
)
7233 inst
.error
= BAD_ARGS
;
7241 do_fpa_to_reg (char * str
)
7243 skip_whitespace (str
);
7245 if (reg_required_here (&str
, 12) == FAIL
)
7248 if (skip_past_comma (&str
) == FAIL
7249 || fp_reg_required_here (&str
, 0) == FAIL
)
7252 inst
.error
= BAD_ARGS
;
7260 vfp_sp_reg_required_here (char ** str
,
7261 enum vfp_sp_reg_pos pos
)
7266 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_SN
].htab
)) != FAIL
)
7271 inst
.instruction
|= ((reg
>> 1) << 12) | ((reg
& 1) << 22);
7275 inst
.instruction
|= ((reg
>> 1) << 16) | ((reg
& 1) << 7);
7279 inst
.instruction
|= ((reg
>> 1) << 0) | ((reg
& 1) << 5);
7288 /* In the few cases where we might be able to accept something else
7289 this error can be overridden. */
7290 inst
.error
= _(all_reg_maps
[REG_TYPE_SN
].expected
);
7292 /* Restore the start point. */
7298 vfp_dp_reg_required_here (char ** str
,
7299 enum vfp_dp_reg_pos pos
)
7302 char * start
= *str
;
7304 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_DN
].htab
)) != FAIL
)
7309 inst
.instruction
|= reg
<< 12;
7313 inst
.instruction
|= reg
<< 16;
7317 inst
.instruction
|= reg
<< 0;
7326 /* In the few cases where we might be able to accept something else
7327 this error can be overridden. */
7328 inst
.error
= _(all_reg_maps
[REG_TYPE_DN
].expected
);
7330 /* Restore the start point. */
7336 do_vfp_sp_monadic (char * str
)
7338 skip_whitespace (str
);
7340 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7343 if (skip_past_comma (&str
) == FAIL
7344 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
7347 inst
.error
= BAD_ARGS
;
7355 do_vfp_dp_monadic (char * str
)
7357 skip_whitespace (str
);
7359 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7362 if (skip_past_comma (&str
) == FAIL
7363 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7366 inst
.error
= BAD_ARGS
;
7374 do_vfp_sp_dyadic (char * str
)
7376 skip_whitespace (str
);
7378 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7381 if (skip_past_comma (&str
) == FAIL
7382 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
7383 || skip_past_comma (&str
) == FAIL
7384 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
7387 inst
.error
= BAD_ARGS
;
7395 do_vfp_dp_dyadic (char * str
)
7397 skip_whitespace (str
);
7399 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7402 if (skip_past_comma (&str
) == FAIL
7403 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
7404 || skip_past_comma (&str
) == FAIL
7405 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7408 inst
.error
= BAD_ARGS
;
7416 do_vfp_reg_from_sp (char * str
)
7418 skip_whitespace (str
);
7420 if (reg_required_here (&str
, 12) == FAIL
)
7423 if (skip_past_comma (&str
) == FAIL
7424 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
7427 inst
.error
= BAD_ARGS
;
7434 /* Parse and encode a VFP SP register list, storing the initial
7435 register in position POS and returning the range as the result. If
7436 the string is invalid return FAIL (an invalid range). */
7439 vfp_sp_reg_list (char ** str
, enum vfp_sp_reg_pos pos
)
7447 unsigned long mask
= 0;
7454 skip_whitespace (*str
);
7456 tempinst
= inst
.instruction
;
7460 inst
.instruction
= 0;
7462 if ((new_base
= vfp_sp_reg_required_here (str
, pos
)) == FAIL
)
7465 if (count
== 0 || base_reg
> new_base
)
7467 base_reg
= new_base
;
7468 base_bits
= inst
.instruction
;
7471 if (mask
& (1 << new_base
))
7473 inst
.error
= _("invalid register list");
7477 if ((mask
>> new_base
) != 0 && ! warned
)
7479 as_tsktsk (_("register list not in ascending order"));
7483 mask
|= 1 << new_base
;
7486 skip_whitespace (*str
);
7488 if (**str
== '-') /* We have the start of a range expression */
7495 = arm_reg_parse (str
, all_reg_maps
[REG_TYPE_SN
].htab
))
7498 inst
.error
= _(all_reg_maps
[REG_TYPE_SN
].expected
);
7502 if (high_range
<= new_base
)
7504 inst
.error
= _("register range not in ascending order");
7508 for (new_base
++; new_base
<= high_range
; new_base
++)
7510 if (mask
& (1 << new_base
))
7512 inst
.error
= _("invalid register list");
7516 mask
|= 1 << new_base
;
7521 while (skip_past_comma (str
) != FAIL
);
7525 inst
.error
= _("invalid register list");
7533 /* Sanity check -- should have raised a parse error above. */
7534 if (count
== 0 || count
> 32)
7537 /* Final test -- the registers must be consecutive. */
7540 if ((mask
& (1 << base_reg
++)) == 0)
7542 inst
.error
= _("non-contiguous register range");
7547 inst
.instruction
= tempinst
| base_bits
;
7552 do_vfp_reg2_from_sp2 (char * str
)
7554 skip_whitespace (str
);
7556 if (reg_required_here (&str
, 12) == FAIL
7557 || skip_past_comma (&str
) == FAIL
7558 || reg_required_here (&str
, 16) == FAIL
7559 || skip_past_comma (&str
) == FAIL
)
7562 inst
.error
= BAD_ARGS
;
7566 /* We require exactly two consecutive SP registers. */
7567 if (vfp_sp_reg_list (&str
, VFP_REG_Sm
) != 2)
7570 inst
.error
= _("only two consecutive VFP SP registers allowed here");
7577 do_vfp_sp_from_reg (char * str
)
7579 skip_whitespace (str
);
7581 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
7584 if (skip_past_comma (&str
) == FAIL
7585 || reg_required_here (&str
, 12) == FAIL
)
7588 inst
.error
= BAD_ARGS
;
7596 do_vfp_sp2_from_reg2 (char * str
)
7598 skip_whitespace (str
);
7600 /* We require exactly two consecutive SP registers. */
7601 if (vfp_sp_reg_list (&str
, VFP_REG_Sm
) != 2)
7604 inst
.error
= _("only two consecutive VFP SP registers allowed here");
7607 if (skip_past_comma (&str
) == FAIL
7608 || reg_required_here (&str
, 12) == FAIL
7609 || skip_past_comma (&str
) == FAIL
7610 || reg_required_here (&str
, 16) == FAIL
)
7613 inst
.error
= BAD_ARGS
;
7621 do_vfp_reg_from_dp (char * str
)
7623 skip_whitespace (str
);
7625 if (reg_required_here (&str
, 12) == FAIL
)
7628 if (skip_past_comma (&str
) == FAIL
7629 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
7632 inst
.error
= BAD_ARGS
;
7640 do_vfp_reg2_from_dp (char * str
)
7642 skip_whitespace (str
);
7644 if (reg_required_here (&str
, 12) == FAIL
)
7647 if (skip_past_comma (&str
) == FAIL
7648 || reg_required_here (&str
, 16) == FAIL
7649 || skip_past_comma (&str
) == FAIL
7650 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7653 inst
.error
= BAD_ARGS
;
7661 do_vfp_dp_from_reg (char * str
)
7663 skip_whitespace (str
);
7665 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
7668 if (skip_past_comma (&str
) == FAIL
7669 || reg_required_here (&str
, 12) == FAIL
)
7672 inst
.error
= BAD_ARGS
;
7680 do_vfp_dp_from_reg2 (char * str
)
7682 skip_whitespace (str
);
7684 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7687 if (skip_past_comma (&str
) == FAIL
7688 || reg_required_here (&str
, 12) == FAIL
7689 || skip_past_comma (&str
) == FAIL
7690 || reg_required_here (&str
, 16) == FAIL
)
7693 inst
.error
= BAD_ARGS
;
7700 static const struct vfp_reg
*
7701 vfp_psr_parse (char ** str
)
7706 const struct vfp_reg
*vreg
;
7710 /* Find the end of the current token. */
7715 while (ISALPHA (c
));
7720 for (vreg
= vfp_regs
+ 0;
7721 vreg
< vfp_regs
+ sizeof (vfp_regs
) / sizeof (struct vfp_reg
);
7724 if (streq (start
, vreg
->name
))
7737 vfp_psr_required_here (char ** str
)
7740 const struct vfp_reg
*vreg
;
7742 vreg
= vfp_psr_parse (str
);
7746 inst
.instruction
|= vreg
->regno
;
7750 inst
.error
= _("VFP system register expected");
7757 do_vfp_reg_from_ctrl (char * str
)
7759 skip_whitespace (str
);
7761 if (reg_required_here (&str
, 12) == FAIL
)
7764 if (skip_past_comma (&str
) == FAIL
7765 || vfp_psr_required_here (&str
) == FAIL
)
7768 inst
.error
= BAD_ARGS
;
7776 do_vfp_ctrl_from_reg (char * str
)
7778 skip_whitespace (str
);
7780 if (vfp_psr_required_here (&str
) == FAIL
)
7783 if (skip_past_comma (&str
) == FAIL
7784 || reg_required_here (&str
, 12) == FAIL
)
7787 inst
.error
= BAD_ARGS
;
7795 do_vfp_sp_ldst (char * str
)
7797 skip_whitespace (str
);
7799 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7802 inst
.error
= BAD_ARGS
;
7806 if (skip_past_comma (&str
) == FAIL
7807 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
7810 inst
.error
= BAD_ARGS
;
7818 do_vfp_dp_ldst (char * str
)
7820 skip_whitespace (str
);
7822 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7825 inst
.error
= BAD_ARGS
;
7829 if (skip_past_comma (&str
) == FAIL
7830 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
7833 inst
.error
= BAD_ARGS
;
7841 vfp_dp_reg_list (char ** str
)
7848 unsigned long mask
= 0;
7855 skip_whitespace (*str
);
7857 tempinst
= inst
.instruction
;
7861 inst
.instruction
= 0;
7863 if ((new_base
= vfp_dp_reg_required_here (str
, VFP_REG_Dd
)) == FAIL
)
7866 if (count
== 0 || base_reg
> new_base
)
7868 base_reg
= new_base
;
7869 range
= inst
.instruction
;
7872 if (mask
& (1 << new_base
))
7874 inst
.error
= _("invalid register list");
7878 if ((mask
>> new_base
) != 0 && ! warned
)
7880 as_tsktsk (_("register list not in ascending order"));
7884 mask
|= 1 << new_base
;
7887 skip_whitespace (*str
);
7889 if (**str
== '-') /* We have the start of a range expression */
7896 = arm_reg_parse (str
, all_reg_maps
[REG_TYPE_DN
].htab
))
7899 inst
.error
= _(all_reg_maps
[REG_TYPE_DN
].expected
);
7903 if (high_range
<= new_base
)
7905 inst
.error
= _("register range not in ascending order");
7909 for (new_base
++; new_base
<= high_range
; new_base
++)
7911 if (mask
& (1 << new_base
))
7913 inst
.error
= _("invalid register list");
7917 mask
|= 1 << new_base
;
7922 while (skip_past_comma (str
) != FAIL
);
7926 inst
.error
= _("invalid register list");
7934 /* Sanity check -- should have raised a parse error above. */
7935 if (count
== 0 || count
> 16)
7938 /* Final test -- the registers must be consecutive. */
7941 if ((mask
& (1 << base_reg
++)) == 0)
7943 inst
.error
= _("non-contiguous register range");
7948 inst
.instruction
= tempinst
;
7953 vfp_sp_ldstm (char * str
, enum vfp_ldstm_type ldstm_type
)
7957 skip_whitespace (str
);
7959 if (reg_required_here (&str
, 16) == FAIL
)
7962 skip_whitespace (str
);
7966 inst
.instruction
|= WRITE_BACK
;
7969 else if (ldstm_type
!= VFP_LDSTMIA
)
7971 inst
.error
= _("this addressing mode requires base-register writeback");
7975 if (skip_past_comma (&str
) == FAIL
7976 || (range
= vfp_sp_reg_list (&str
, VFP_REG_Sd
)) == FAIL
)
7979 inst
.error
= BAD_ARGS
;
7983 inst
.instruction
|= range
;
7988 vfp_dp_ldstm (char * str
, enum vfp_ldstm_type ldstm_type
)
7992 skip_whitespace (str
);
7994 if (reg_required_here (&str
, 16) == FAIL
)
7997 skip_whitespace (str
);
8001 inst
.instruction
|= WRITE_BACK
;
8004 else if (ldstm_type
!= VFP_LDSTMIA
&& ldstm_type
!= VFP_LDSTMIAX
)
8006 inst
.error
= _("this addressing mode requires base-register writeback");
8010 if (skip_past_comma (&str
) == FAIL
8011 || (range
= vfp_dp_reg_list (&str
)) == FAIL
)
8014 inst
.error
= BAD_ARGS
;
8018 if (ldstm_type
== VFP_LDSTMIAX
|| ldstm_type
== VFP_LDSTMDBX
)
8021 inst
.instruction
|= range
;
8026 do_vfp_sp_ldstmia (char * str
)
8028 vfp_sp_ldstm (str
, VFP_LDSTMIA
);
8032 do_vfp_sp_ldstmdb (char * str
)
8034 vfp_sp_ldstm (str
, VFP_LDSTMDB
);
8038 do_vfp_dp_ldstmia (char * str
)
8040 vfp_dp_ldstm (str
, VFP_LDSTMIA
);
8044 do_vfp_dp_ldstmdb (char * str
)
8046 vfp_dp_ldstm (str
, VFP_LDSTMDB
);
8050 do_vfp_xp_ldstmia (char *str
)
8052 vfp_dp_ldstm (str
, VFP_LDSTMIAX
);
8056 do_vfp_xp_ldstmdb (char * str
)
8058 vfp_dp_ldstm (str
, VFP_LDSTMDBX
);
8062 do_vfp_sp_compare_z (char * str
)
8064 skip_whitespace (str
);
8066 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8069 inst
.error
= BAD_ARGS
;
8077 do_vfp_dp_compare_z (char * str
)
8079 skip_whitespace (str
);
8081 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8084 inst
.error
= BAD_ARGS
;
8092 do_vfp_dp_sp_cvt (char * str
)
8094 skip_whitespace (str
);
8096 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8099 if (skip_past_comma (&str
) == FAIL
8100 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
8103 inst
.error
= BAD_ARGS
;
8111 do_vfp_sp_dp_cvt (char * str
)
8113 skip_whitespace (str
);
8115 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8118 if (skip_past_comma (&str
) == FAIL
8119 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
8122 inst
.error
= BAD_ARGS
;
8129 /* Thumb specific routines. */
8131 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
8135 thumb_add_sub (char * str
, int subtract
)
8137 int Rd
, Rs
, Rn
= FAIL
;
8139 skip_whitespace (str
);
8141 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
8142 || skip_past_comma (&str
) == FAIL
)
8145 inst
.error
= BAD_ARGS
;
8149 if (is_immediate_prefix (*str
))
8153 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8158 if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8161 if (skip_past_comma (&str
) == FAIL
)
8163 /* Two operand format, shuffle the registers
8164 and pretend there are 3. */
8168 else if (is_immediate_prefix (*str
))
8171 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8174 else if ((Rn
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8178 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8179 for the latter case, EXPR contains the immediate that was found. */
8182 /* All register format. */
8183 if (Rd
> 7 || Rs
> 7 || Rn
> 7)
8187 inst
.error
= _("dest and source1 must be the same register");
8191 /* Can't do this for SUB. */
8194 inst
.error
= _("subtract valid only on lo regs");
8198 inst
.instruction
= (T_OPCODE_ADD_HI
8199 | (Rd
> 7 ? THUMB_H1
: 0)
8200 | (Rn
> 7 ? THUMB_H2
: 0));
8201 inst
.instruction
|= (Rd
& 7) | ((Rn
& 7) << 3);
8205 inst
.instruction
= subtract
? T_OPCODE_SUB_R3
: T_OPCODE_ADD_R3
;
8206 inst
.instruction
|= Rd
| (Rs
<< 3) | (Rn
<< 6);
8211 /* Immediate expression, now things start to get nasty. */
8213 /* First deal with HI regs, only very restricted cases allowed:
8214 Adjusting SP, and using PC or SP to get an address. */
8215 if ((Rd
> 7 && (Rd
!= REG_SP
|| Rs
!= REG_SP
))
8216 || (Rs
> 7 && Rs
!= REG_SP
&& Rs
!= REG_PC
))
8218 inst
.error
= _("invalid Hi register with immediate");
8222 if (inst
.reloc
.exp
.X_op
!= O_constant
)
8224 /* Value isn't known yet, all we can do is store all the fragments
8225 we know about in the instruction and let the reloc hacking
8227 inst
.instruction
= (subtract
? 0x8000 : 0) | (Rd
<< 4) | Rs
;
8228 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
8232 int offset
= inst
.reloc
.exp
.X_add_number
;
8242 /* Quick check, in case offset is MIN_INT. */
8245 inst
.error
= _("immediate value out of range");
8249 /* Note - you cannot convert a subtract of 0 into an
8250 add of 0 because the carry flag is set differently. */
8251 else if (offset
> 0)
8256 if (offset
& ~0x1fc)
8258 inst
.error
= _("invalid immediate value for stack adjust");
8261 inst
.instruction
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
8262 inst
.instruction
|= offset
>> 2;
8264 else if (Rs
== REG_PC
|| Rs
== REG_SP
)
8267 || (offset
& ~0x3fc))
8269 inst
.error
= _("invalid immediate for address calculation");
8272 inst
.instruction
= (Rs
== REG_PC
? T_OPCODE_ADD_PC
8274 inst
.instruction
|= (Rd
<< 8) | (offset
>> 2);
8280 inst
.error
= _("immediate value out of range");
8283 inst
.instruction
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
8284 inst
.instruction
|= (Rd
<< 8) | offset
;
8290 inst
.error
= _("immediate value out of range");
8293 inst
.instruction
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
8294 inst
.instruction
|= Rd
| (Rs
<< 3) | (offset
<< 6);
8303 thumb_shift (char * str
, int shift
)
8305 int Rd
, Rs
, Rn
= FAIL
;
8307 skip_whitespace (str
);
8309 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
8310 || skip_past_comma (&str
) == FAIL
)
8313 inst
.error
= BAD_ARGS
;
8317 if (is_immediate_prefix (*str
))
8319 /* Two operand immediate format, set Rs to Rd. */
8322 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8327 if ((Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8330 if (skip_past_comma (&str
) == FAIL
)
8332 /* Two operand format, shuffle the registers
8333 and pretend there are 3. */
8337 else if (is_immediate_prefix (*str
))
8340 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8343 else if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8347 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8348 for the latter case, EXPR contains the immediate that was found. */
8354 inst
.error
= _("source1 and dest must be same register");
8360 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_R
; break;
8361 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_R
; break;
8362 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_R
; break;
8365 inst
.instruction
|= Rd
| (Rn
<< 3);
8371 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_I
; break;
8372 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_I
; break;
8373 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_I
; break;
8376 if (inst
.reloc
.exp
.X_op
!= O_constant
)
8378 /* Value isn't known yet, create a dummy reloc and let reloc
8379 hacking fix it up. */
8380 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_SHIFT
;
8384 unsigned shift_value
= inst
.reloc
.exp
.X_add_number
;
8386 if (shift_value
> 32 || (shift_value
== 32 && shift
== THUMB_LSL
))
8388 inst
.error
= _("invalid immediate for shift");
8392 /* Shifts of zero are handled by converting to LSL. */
8393 if (shift_value
== 0)
8394 inst
.instruction
= T_OPCODE_LSL_I
;
8396 /* Shifts of 32 are encoded as a shift of zero. */
8397 if (shift_value
== 32)
8400 inst
.instruction
|= shift_value
<< 6;
8403 inst
.instruction
|= Rd
| (Rs
<< 3);
8410 thumb_load_store (char * str
, int load_store
, int size
)
8412 int Rd
, Rb
, Ro
= FAIL
;
8414 skip_whitespace (str
);
8416 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
8417 || skip_past_comma (&str
) == FAIL
)
8420 inst
.error
= BAD_ARGS
;
8427 if ((Rb
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8430 if (skip_past_comma (&str
) != FAIL
)
8432 if (is_immediate_prefix (*str
))
8435 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8438 else if ((Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8443 inst
.reloc
.exp
.X_op
= O_constant
;
8444 inst
.reloc
.exp
.X_add_number
= 0;
8449 inst
.error
= _("expected ']'");
8454 else if (*str
== '=')
8456 if (load_store
!= THUMB_LOAD
)
8458 inst
.error
= _("invalid pseudo operation");
8462 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
8465 skip_whitespace (str
);
8467 if (my_get_expression (& inst
.reloc
.exp
, & str
))
8472 if ( inst
.reloc
.exp
.X_op
!= O_constant
8473 && inst
.reloc
.exp
.X_op
!= O_symbol
)
8475 inst
.error
= "Constant expression expected";
8479 if (inst
.reloc
.exp
.X_op
== O_constant
8480 && ((inst
.reloc
.exp
.X_add_number
& ~0xFF) == 0))
8482 /* This can be done with a mov instruction. */
8484 inst
.instruction
= T_OPCODE_MOV_I8
| (Rd
<< 8);
8485 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
8489 /* Insert into literal pool. */
8490 if (add_to_lit_pool () == FAIL
)
8493 inst
.error
= "literal pool insertion failed";
8497 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8498 inst
.reloc
.pc_rel
= 1;
8499 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
8500 /* Adjust ARM pipeline offset to Thumb. */
8501 inst
.reloc
.exp
.X_add_number
+= 4;
8507 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8510 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
8511 inst
.reloc
.pc_rel
= 1;
8512 inst
.reloc
.exp
.X_add_number
-= 4; /* Pipeline offset. */
8513 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8518 if (Rb
== REG_PC
|| Rb
== REG_SP
)
8520 if (size
!= THUMB_WORD
)
8522 inst
.error
= _("byte or halfword not valid for base register");
8525 else if (Rb
== REG_PC
&& load_store
!= THUMB_LOAD
)
8527 inst
.error
= _("r15 based store not allowed");
8530 else if (Ro
!= FAIL
)
8532 inst
.error
= _("invalid base register for register offset");
8537 inst
.instruction
= T_OPCODE_LDR_PC
;
8538 else if (load_store
== THUMB_LOAD
)
8539 inst
.instruction
= T_OPCODE_LDR_SP
;
8541 inst
.instruction
= T_OPCODE_STR_SP
;
8543 inst
.instruction
|= Rd
<< 8;
8544 if (inst
.reloc
.exp
.X_op
== O_constant
)
8546 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
8548 if (offset
& ~0x3fc)
8550 inst
.error
= _("invalid offset");
8554 inst
.instruction
|= offset
>> 2;
8557 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8561 inst
.error
= _("invalid base register in load/store");
8564 else if (Ro
== FAIL
)
8566 /* Immediate offset. */
8567 if (size
== THUMB_WORD
)
8568 inst
.instruction
= (load_store
== THUMB_LOAD
8569 ? T_OPCODE_LDR_IW
: T_OPCODE_STR_IW
);
8570 else if (size
== THUMB_HALFWORD
)
8571 inst
.instruction
= (load_store
== THUMB_LOAD
8572 ? T_OPCODE_LDR_IH
: T_OPCODE_STR_IH
);
8574 inst
.instruction
= (load_store
== THUMB_LOAD
8575 ? T_OPCODE_LDR_IB
: T_OPCODE_STR_IB
);
8577 inst
.instruction
|= Rd
| (Rb
<< 3);
8579 if (inst
.reloc
.exp
.X_op
== O_constant
)
8581 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
8583 if (offset
& ~(0x1f << size
))
8585 inst
.error
= _("invalid offset");
8588 inst
.instruction
|= (offset
>> size
) << 6;
8591 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8595 /* Register offset. */
8596 if (size
== THUMB_WORD
)
8597 inst
.instruction
= (load_store
== THUMB_LOAD
8598 ? T_OPCODE_LDR_RW
: T_OPCODE_STR_RW
);
8599 else if (size
== THUMB_HALFWORD
)
8600 inst
.instruction
= (load_store
== THUMB_LOAD
8601 ? T_OPCODE_LDR_RH
: T_OPCODE_STR_RH
);
8603 inst
.instruction
= (load_store
== THUMB_LOAD
8604 ? T_OPCODE_LDR_RB
: T_OPCODE_STR_RB
);
8606 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
8612 /* A register must be given at this point.
8614 Shift is the place to put it in inst.instruction.
8616 Restores input start point on err.
8617 Returns the reg#, or FAIL. */
8620 mav_reg_required_here (char ** str
, int shift
, enum arm_reg_type regtype
)
8625 if ((reg
= arm_reg_parse (str
, all_reg_maps
[regtype
].htab
)) != FAIL
)
8628 inst
.instruction
|= reg
<< shift
;
8633 /* Restore the start point. */
8636 /* Try generic coprocessor name if applicable. */
8637 if (regtype
== REG_TYPE_MVF
||
8638 regtype
== REG_TYPE_MVD
||
8639 regtype
== REG_TYPE_MVFX
||
8640 regtype
== REG_TYPE_MVDX
)
8642 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CN
].htab
)) != FAIL
)
8645 inst
.instruction
|= reg
<< shift
;
8650 /* Restore the start point. */
8654 /* In the few cases where we might be able to accept something else
8655 this error can be overridden. */
8656 inst
.error
= _(all_reg_maps
[regtype
].expected
);
8661 /* Cirrus Maverick Instructions. */
8663 /* Isnsn like "foo X,Y". */
8666 do_mav_binops (char * str
,
8668 enum arm_reg_type reg0
,
8669 enum arm_reg_type reg1
)
8673 shift0
= mode
& 0xff;
8674 shift1
= (mode
>> 8) & 0xff;
8676 skip_whitespace (str
);
8678 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
8679 || skip_past_comma (&str
) == FAIL
8680 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
)
8683 inst
.error
= BAD_ARGS
;
8689 /* Isnsn like "foo X,Y,Z". */
8692 do_mav_triple (char * str
,
8694 enum arm_reg_type reg0
,
8695 enum arm_reg_type reg1
,
8696 enum arm_reg_type reg2
)
8698 int shift0
, shift1
, shift2
;
8700 shift0
= mode
& 0xff;
8701 shift1
= (mode
>> 8) & 0xff;
8702 shift2
= (mode
>> 16) & 0xff;
8704 skip_whitespace (str
);
8706 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
8707 || skip_past_comma (&str
) == FAIL
8708 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
8709 || skip_past_comma (&str
) == FAIL
8710 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
)
8713 inst
.error
= BAD_ARGS
;
8719 /* Wrapper functions. */
8722 do_mav_binops_1a (char * str
)
8724 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVF
);
8728 do_mav_binops_1b (char * str
)
8730 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVD
);
8734 do_mav_binops_1c (char * str
)
8736 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVDX
);
8740 do_mav_binops_1d (char * str
)
8742 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVF
);
8746 do_mav_binops_1e (char * str
)
8748 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVD
);
8752 do_mav_binops_1f (char * str
)
8754 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVF
);
8758 do_mav_binops_1g (char * str
)
8760 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVD
);
8764 do_mav_binops_1h (char * str
)
8766 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVFX
);
8770 do_mav_binops_1i (char * str
)
8772 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVFX
);
8776 do_mav_binops_1j (char * str
)
8778 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVDX
);
8782 do_mav_binops_1k (char * str
)
8784 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVDX
);
8788 do_mav_binops_1l (char * str
)
8790 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVF
);
8794 do_mav_binops_1m (char * str
)
8796 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVD
);
8800 do_mav_binops_1n (char * str
)
8802 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
8806 do_mav_binops_1o (char * str
)
8808 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
8812 do_mav_binops_2a (char * str
)
8814 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVF
, REG_TYPE_RN
);
8818 do_mav_binops_2b (char * str
)
8820 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVD
, REG_TYPE_RN
);
8824 do_mav_binops_2c (char * str
)
8826 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVDX
, REG_TYPE_RN
);
8830 do_mav_binops_3a (char * str
)
8832 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVFX
);
8836 do_mav_binops_3b (char * str
)
8838 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVFX
, REG_TYPE_MVAX
);
8842 do_mav_binops_3c (char * str
)
8844 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVDX
);
8848 do_mav_binops_3d (char * str
)
8850 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVDX
, REG_TYPE_MVAX
);
8854 do_mav_triple_4a (char * str
)
8856 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_RN
);
8860 do_mav_triple_4b (char * str
)
8862 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_RN
);
8866 do_mav_triple_5a (char * str
)
8868 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVF
, REG_TYPE_MVF
);
8872 do_mav_triple_5b (char * str
)
8874 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVD
, REG_TYPE_MVD
);
8878 do_mav_triple_5c (char * str
)
8880 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
8884 do_mav_triple_5d (char * str
)
8886 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
8890 do_mav_triple_5e (char * str
)
8892 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVF
, REG_TYPE_MVF
, REG_TYPE_MVF
);
8896 do_mav_triple_5f (char * str
)
8898 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVD
, REG_TYPE_MVD
, REG_TYPE_MVD
);
8902 do_mav_triple_5g (char * str
)
8904 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
8908 do_mav_triple_5h (char * str
)
8910 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
8913 /* Isnsn like "foo W,X,Y,Z".
8914 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
8917 do_mav_quad (char * str
,
8919 enum arm_reg_type reg0
,
8920 enum arm_reg_type reg1
,
8921 enum arm_reg_type reg2
,
8922 enum arm_reg_type reg3
)
8924 int shift0
, shift1
, shift2
, shift3
;
8926 shift0
= mode
& 0xff;
8927 shift1
= (mode
>> 8) & 0xff;
8928 shift2
= (mode
>> 16) & 0xff;
8929 shift3
= (mode
>> 24) & 0xff;
8931 skip_whitespace (str
);
8933 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
8934 || skip_past_comma (&str
) == FAIL
8935 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
8936 || skip_past_comma (&str
) == FAIL
8937 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
8938 || skip_past_comma (&str
) == FAIL
8939 || mav_reg_required_here (&str
, shift3
, reg3
) == FAIL
)
8942 inst
.error
= BAD_ARGS
;
8949 do_mav_quad_6a (char * str
)
8951 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
,
8956 do_mav_quad_6b (char * str
)
8958 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVAX
, REG_TYPE_MVFX
,
8962 /* cfmvsc32<cond> DSPSC,MVDX[15:0]. */
8964 do_mav_dspsc_1 (char * str
)
8966 skip_whitespace (str
);
8969 if (mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
8970 || skip_past_comma (&str
) == FAIL
8971 || mav_reg_required_here (&str
, 12, REG_TYPE_MVDX
) == FAIL
)
8974 inst
.error
= BAD_ARGS
;
8982 /* cfmv32sc<cond> MVDX[15:0],DSPSC. */
8984 do_mav_dspsc_2 (char * str
)
8986 skip_whitespace (str
);
8989 if (mav_reg_required_here (&str
, 12, REG_TYPE_MVDX
) == FAIL
8990 || skip_past_comma (&str
) == FAIL
8991 || mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
)
8994 inst
.error
= BAD_ARGS
;
9002 /* Maverick shift immediate instructions.
9003 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
9004 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
9007 do_mav_shift (char * str
,
9008 enum arm_reg_type reg0
,
9009 enum arm_reg_type reg1
)
9014 skip_whitespace (str
);
9018 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
9019 || skip_past_comma (&str
) == FAIL
9020 || mav_reg_required_here (&str
, 16, reg1
) == FAIL
9021 || skip_past_comma (&str
) == FAIL
)
9024 inst
.error
= BAD_ARGS
;
9028 /* Calculate the immediate operand.
9029 The operand is a 7bit signed number. */
9030 skip_whitespace (str
);
9035 if (!ISDIGIT (*str
) && *str
!= '-')
9037 inst
.error
= _("expecting immediate, 7bit operand");
9047 for (imm
= 0; *str
&& ISDIGIT (*str
); ++str
)
9048 imm
= imm
* 10 + *str
- '0';
9052 inst
.error
= _("immediate out of range");
9056 /* Make negative imm's into 7bit signed numbers. */
9063 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
9064 Bits 5-7 of the insn should have bits 4-6 of the immediate.
9065 Bit 4 should be 0. */
9066 imm
= (imm
& 0xf) | ((imm
& 0x70) << 1);
9068 inst
.instruction
|= imm
;
9073 do_mav_shift_1 (char * str
)
9075 do_mav_shift (str
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
9079 do_mav_shift_2 (char * str
)
9081 do_mav_shift (str
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
9085 mav_parse_offset (char ** str
, int * negative
)
9092 skip_whitespace (p
);
9105 inst
.error
= _("offset expected");
9109 for (offset
= 0; *p
&& ISDIGIT (*p
); ++p
)
9110 offset
= offset
* 10 + *p
- '0';
9114 inst
.error
= _("offset out of range");
9119 inst
.error
= _("offset not a multiple of 4");
9125 return *negative
? -offset
: offset
;
9128 /* Maverick load/store instructions.
9129 <insn><cond> CRd,[Rn,<offset>]{!}.
9130 <insn><cond> CRd,[Rn],<offset>. */
9133 do_mav_ldst (char * str
, enum arm_reg_type reg0
)
9135 int offset
, negative
;
9137 skip_whitespace (str
);
9139 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
9140 || skip_past_comma (&str
) == FAIL
9142 || reg_required_here (&str
, 16) == FAIL
)
9145 if (skip_past_comma (&str
) == SUCCESS
)
9147 /* You are here: "<offset>]{!}". */
9148 inst
.instruction
|= PRE_INDEX
;
9150 offset
= mav_parse_offset (&str
, &negative
);
9157 inst
.error
= _("missing ]");
9163 inst
.instruction
|= WRITE_BACK
;
9169 /* You are here: "], <offset>". */
9172 inst
.error
= _("missing ]");
9176 if (skip_past_comma (&str
) == FAIL
9177 || (offset
= mav_parse_offset (&str
, &negative
), inst
.error
))
9180 inst
.instruction
|= CP_T_WB
; /* Post indexed, set bit W. */
9186 inst
.instruction
|= CP_T_UD
; /* Positive, so set bit U. */
9188 inst
.instruction
|= offset
>> 2;
9194 inst
.error
= BAD_ARGS
;
9198 do_mav_ldst_1 (char * str
)
9200 do_mav_ldst (str
, REG_TYPE_MVF
);
9204 do_mav_ldst_2 (char * str
)
9206 do_mav_ldst (str
, REG_TYPE_MVD
);
9210 do_mav_ldst_3 (char * str
)
9212 do_mav_ldst (str
, REG_TYPE_MVFX
);
9216 do_mav_ldst_4 (char * str
)
9218 do_mav_ldst (str
, REG_TYPE_MVDX
);
9222 do_t_nop (char * str
)
9228 /* Handle the Format 4 instructions that do not have equivalents in other
9229 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
9233 do_t_arit (char * str
)
9237 skip_whitespace (str
);
9239 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9240 || skip_past_comma (&str
) == FAIL
9241 || (Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9243 inst
.error
= BAD_ARGS
;
9247 if (skip_past_comma (&str
) != FAIL
)
9249 /* Three operand format not allowed for TST, CMN, NEG and MVN.
9250 (It isn't allowed for CMP either, but that isn't handled by this
9252 if (inst
.instruction
== T_OPCODE_TST
9253 || inst
.instruction
== T_OPCODE_CMN
9254 || inst
.instruction
== T_OPCODE_NEG
9255 || inst
.instruction
== T_OPCODE_MVN
)
9257 inst
.error
= BAD_ARGS
;
9261 if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9266 inst
.error
= _("dest and source1 must be the same register");
9272 if (inst
.instruction
== T_OPCODE_MUL
9274 as_tsktsk (_("Rs and Rd must be different in MUL"));
9276 inst
.instruction
|= Rd
| (Rs
<< 3);
9281 do_t_add (char * str
)
9283 thumb_add_sub (str
, 0);
9287 do_t_asr (char * str
)
9289 thumb_shift (str
, THUMB_ASR
);
9293 do_t_branch9 (char * str
)
9295 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9297 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH9
;
9298 inst
.reloc
.pc_rel
= 1;
9303 do_t_branch12 (char * str
)
9305 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9307 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH12
;
9308 inst
.reloc
.pc_rel
= 1;
9312 /* Find the real, Thumb encoded start of a Thumb function. */
9315 find_real_start (symbolS
* symbolP
)
9318 const char * name
= S_GET_NAME (symbolP
);
9319 symbolS
* new_target
;
9321 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
9322 #define STUB_NAME ".real_start_of"
9327 /* Names that start with '.' are local labels, not function entry points.
9328 The compiler may generate BL instructions to these labels because it
9329 needs to perform a branch to a far away location. */
9333 real_start
= malloc (strlen (name
) + strlen (STUB_NAME
) + 1);
9334 sprintf (real_start
, "%s%s", STUB_NAME
, name
);
9336 new_target
= symbol_find (real_start
);
9338 if (new_target
== NULL
)
9340 as_warn ("Failed to find real start of function: %s\n", name
);
9341 new_target
= symbolP
;
9350 do_t_branch23 (char * str
)
9352 if (my_get_expression (& inst
.reloc
.exp
, & str
))
9355 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH23
;
9356 inst
.reloc
.pc_rel
= 1;
9359 /* If the destination of the branch is a defined symbol which does not have
9360 the THUMB_FUNC attribute, then we must be calling a function which has
9361 the (interfacearm) attribute. We look for the Thumb entry point to that
9362 function and change the branch to refer to that function instead. */
9363 if ( inst
.reloc
.exp
.X_op
== O_symbol
9364 && inst
.reloc
.exp
.X_add_symbol
!= NULL
9365 && S_IS_DEFINED (inst
.reloc
.exp
.X_add_symbol
)
9366 && ! THUMB_IS_FUNC (inst
.reloc
.exp
.X_add_symbol
))
9367 inst
.reloc
.exp
.X_add_symbol
=
9368 find_real_start (inst
.reloc
.exp
.X_add_symbol
);
9372 do_t_bx (char * str
)
9376 skip_whitespace (str
);
9378 if ((reg
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
9381 /* This sets THUMB_H2 from the top bit of reg. */
9382 inst
.instruction
|= reg
<< 3;
9384 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
9385 should cause the alignment to be checked once it is known. This is
9386 because BX PC only works if the instruction is word aligned. */
9392 do_t_compare (char * str
)
9394 thumb_mov_compare (str
, THUMB_COMPARE
);
9398 do_t_ldmstm (char * str
)
9403 skip_whitespace (str
);
9405 if ((Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9409 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
9413 if (skip_past_comma (&str
) == FAIL
9414 || (range
= reg_list (&str
)) == FAIL
)
9417 inst
.error
= BAD_ARGS
;
9421 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
9423 /* This really doesn't seem worth it. */
9424 inst
.reloc
.type
= BFD_RELOC_NONE
;
9425 inst
.error
= _("expression too complex");
9431 inst
.error
= _("only lo-regs valid in load/store multiple");
9435 inst
.instruction
|= (Rb
<< 8) | range
;
9440 do_t_ldr (char * str
)
9442 thumb_load_store (str
, THUMB_LOAD
, THUMB_WORD
);
9446 do_t_ldrb (char * str
)
9448 thumb_load_store (str
, THUMB_LOAD
, THUMB_BYTE
);
9452 do_t_ldrh (char * str
)
9454 thumb_load_store (str
, THUMB_LOAD
, THUMB_HALFWORD
);
9458 do_t_lds (char * str
)
9462 skip_whitespace (str
);
9464 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9465 || skip_past_comma (&str
) == FAIL
9467 || (Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9468 || skip_past_comma (&str
) == FAIL
9469 || (Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9473 inst
.error
= _("syntax: ldrs[b] Rd, [Rb, Ro]");
9477 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
9482 do_t_lsl (char * str
)
9484 thumb_shift (str
, THUMB_LSL
);
9488 do_t_lsr (char * str
)
9490 thumb_shift (str
, THUMB_LSR
);
9494 do_t_mov (char * str
)
9496 thumb_mov_compare (str
, THUMB_MOVE
);
9500 do_t_push_pop (char * str
)
9504 skip_whitespace (str
);
9506 if ((range
= reg_list (&str
)) == FAIL
)
9509 inst
.error
= BAD_ARGS
;
9513 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
9515 /* This really doesn't seem worth it. */
9516 inst
.reloc
.type
= BFD_RELOC_NONE
;
9517 inst
.error
= _("expression too complex");
9523 if ((inst
.instruction
== T_OPCODE_PUSH
9524 && (range
& ~0xff) == 1 << REG_LR
)
9525 || (inst
.instruction
== T_OPCODE_POP
9526 && (range
& ~0xff) == 1 << REG_PC
))
9528 inst
.instruction
|= THUMB_PP_PC_LR
;
9533 inst
.error
= _("invalid register list to push/pop instruction");
9538 inst
.instruction
|= range
;
9543 do_t_str (char * str
)
9545 thumb_load_store (str
, THUMB_STORE
, THUMB_WORD
);
9549 do_t_strb (char * str
)
9551 thumb_load_store (str
, THUMB_STORE
, THUMB_BYTE
);
9555 do_t_strh (char * str
)
9557 thumb_load_store (str
, THUMB_STORE
, THUMB_HALFWORD
);
9561 do_t_sub (char * str
)
9563 thumb_add_sub (str
, 1);
9567 do_t_swi (char * str
)
9569 skip_whitespace (str
);
9571 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9574 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
9579 do_t_adr (char * str
)
9583 /* This is a pseudo-op of the form "adr rd, label" to be converted
9584 into a relative address of the form "add rd, pc, #label-.-4". */
9585 skip_whitespace (str
);
9587 /* Store Rd in temporary location inside instruction. */
9588 if ((reg
= reg_required_here (&str
, 4)) == FAIL
9589 || (reg
> 7) /* For Thumb reg must be r0..r7. */
9590 || skip_past_comma (&str
) == FAIL
9591 || my_get_expression (&inst
.reloc
.exp
, &str
))
9594 inst
.error
= BAD_ARGS
;
9598 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
9599 inst
.reloc
.exp
.X_add_number
-= 4; /* PC relative adjust. */
9600 inst
.reloc
.pc_rel
= 1;
9601 inst
.instruction
|= REG_PC
; /* Rd is already placed into the instruction. */
9607 insert_reg (const struct reg_entry
* r
,
9608 struct hash_control
* htab
)
9610 int len
= strlen (r
->name
) + 2;
9611 char * buf
= xmalloc (len
);
9612 char * buf2
= xmalloc (len
);
9615 #ifdef REGISTER_PREFIX
9616 buf
[i
++] = REGISTER_PREFIX
;
9619 strcpy (buf
+ i
, r
->name
);
9621 for (i
= 0; buf
[i
]; i
++)
9622 buf2
[i
] = TOUPPER (buf
[i
]);
9626 hash_insert (htab
, buf
, (PTR
) r
);
9627 hash_insert (htab
, buf2
, (PTR
) r
);
9631 build_reg_hsh (struct reg_map
* map
)
9633 const struct reg_entry
*r
;
9635 if ((map
->htab
= hash_new ()) == NULL
)
9636 as_fatal (_("virtual memory exhausted"));
9638 for (r
= map
->names
; r
->name
!= NULL
; r
++)
9639 insert_reg (r
, map
->htab
);
9643 insert_reg_alias (char * str
,
9645 struct hash_control
*htab
)
9648 struct reg_entry
* new = xmalloc (sizeof (struct reg_entry
));
9649 const char * name
= xmalloc (strlen (str
) + 1);
9651 strcpy ((char *) name
, str
);
9654 new->number
= regnum
;
9655 new->builtin
= FALSE
;
9657 error
= hash_insert (htab
, name
, (PTR
) new);
9660 as_bad (_("failed to create an alias for %s, reason: %s"),
9662 free ((char *) name
);
9667 /* Look for the .req directive. This is of the form:
9669 new_register_name .req existing_register_name
9671 If we find one, or if it looks sufficiently like one that we want to
9672 handle any error here, return non-zero. Otherwise return zero. */
9675 create_register_alias (char * newname
, char * p
)
9681 skip_whitespace (q
);
9686 if (*q
&& !strncmp (q
, ".req ", 5))
9691 #ifndef IGNORE_OPCODE_CASE
9692 newname
= original_case_string
;
9694 copy_of_str
= newname
;
9697 skip_whitespace (q
);
9699 for (r
= q
; *r
!= '\0'; r
++)
9705 enum arm_reg_type new_type
, old_type
;
9710 old_type
= arm_reg_parse_any (q
);
9713 new_type
= arm_reg_parse_any (newname
);
9715 if (new_type
== REG_TYPE_MAX
)
9717 if (old_type
!= REG_TYPE_MAX
)
9719 old_regno
= arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
);
9720 insert_reg_alias (newname
, old_regno
,
9721 all_reg_maps
[old_type
].htab
);
9724 as_warn (_("register '%s' does not exist\n"), q
);
9726 else if (old_type
== REG_TYPE_MAX
)
9728 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
9733 /* Do not warn about redefinitions to the same alias. */
9734 if (new_type
!= old_type
9735 || (arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
)
9736 != arm_reg_parse (&q
, all_reg_maps
[new_type
].htab
)))
9737 as_warn (_("ignoring redefinition of register alias '%s'"),
9743 as_warn (_("ignoring incomplete .req pseuso op"));
9754 set_constant_flonums (void)
9758 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
9759 if (atof_ieee ((char *) fp_const
[i
], 'x', fp_values
[i
]) == NULL
)
9764 static const struct asm_opcode insns
[] =
9766 /* Core ARM Instructions. */
9767 {"and", 0xe0000000, 3, ARM_EXT_V1
, do_arit
},
9768 {"ands", 0xe0100000, 3, ARM_EXT_V1
, do_arit
},
9769 {"eor", 0xe0200000, 3, ARM_EXT_V1
, do_arit
},
9770 {"eors", 0xe0300000, 3, ARM_EXT_V1
, do_arit
},
9771 {"sub", 0xe0400000, 3, ARM_EXT_V1
, do_arit
},
9772 {"subs", 0xe0500000, 3, ARM_EXT_V1
, do_arit
},
9773 {"rsb", 0xe0600000, 3, ARM_EXT_V1
, do_arit
},
9774 {"rsbs", 0xe0700000, 3, ARM_EXT_V1
, do_arit
},
9775 {"add", 0xe0800000, 3, ARM_EXT_V1
, do_arit
},
9776 {"adds", 0xe0900000, 3, ARM_EXT_V1
, do_arit
},
9777 {"adc", 0xe0a00000, 3, ARM_EXT_V1
, do_arit
},
9778 {"adcs", 0xe0b00000, 3, ARM_EXT_V1
, do_arit
},
9779 {"sbc", 0xe0c00000, 3, ARM_EXT_V1
, do_arit
},
9780 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1
, do_arit
},
9781 {"rsc", 0xe0e00000, 3, ARM_EXT_V1
, do_arit
},
9782 {"rscs", 0xe0f00000, 3, ARM_EXT_V1
, do_arit
},
9783 {"orr", 0xe1800000, 3, ARM_EXT_V1
, do_arit
},
9784 {"orrs", 0xe1900000, 3, ARM_EXT_V1
, do_arit
},
9785 {"bic", 0xe1c00000, 3, ARM_EXT_V1
, do_arit
},
9786 {"bics", 0xe1d00000, 3, ARM_EXT_V1
, do_arit
},
9788 {"tst", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
9789 {"tsts", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
9790 {"tstp", 0xe110f000, 3, ARM_EXT_V1
, do_cmp
},
9791 {"teq", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
9792 {"teqs", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
9793 {"teqp", 0xe130f000, 3, ARM_EXT_V1
, do_cmp
},
9794 {"cmp", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
9795 {"cmps", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
9796 {"cmpp", 0xe150f000, 3, ARM_EXT_V1
, do_cmp
},
9797 {"cmn", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
9798 {"cmns", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
9799 {"cmnp", 0xe170f000, 3, ARM_EXT_V1
, do_cmp
},
9801 {"mov", 0xe1a00000, 3, ARM_EXT_V1
, do_mov
},
9802 {"movs", 0xe1b00000, 3, ARM_EXT_V1
, do_mov
},
9803 {"mvn", 0xe1e00000, 3, ARM_EXT_V1
, do_mov
},
9804 {"mvns", 0xe1f00000, 3, ARM_EXT_V1
, do_mov
},
9806 {"ldr", 0xe4100000, 3, ARM_EXT_V1
, do_ldst
},
9807 {"ldrb", 0xe4500000, 3, ARM_EXT_V1
, do_ldst
},
9808 {"ldrt", 0xe4300000, 3, ARM_EXT_V1
, do_ldstt
},
9809 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1
, do_ldstt
},
9810 {"str", 0xe4000000, 3, ARM_EXT_V1
, do_ldst
},
9811 {"strb", 0xe4400000, 3, ARM_EXT_V1
, do_ldst
},
9812 {"strt", 0xe4200000, 3, ARM_EXT_V1
, do_ldstt
},
9813 {"strbt", 0xe4600000, 3, ARM_EXT_V1
, do_ldstt
},
9815 {"stmia", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
9816 {"stmib", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
9817 {"stmda", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
9818 {"stmdb", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
9819 {"stmfd", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
9820 {"stmfa", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
9821 {"stmea", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
9822 {"stmed", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
9824 {"ldmia", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
9825 {"ldmib", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
9826 {"ldmda", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
9827 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
9828 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
9829 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
9830 {"ldmea", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
9831 {"ldmed", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
9833 {"swi", 0xef000000, 3, ARM_EXT_V1
, do_swi
},
9835 /* XXX This is the wrong place to do this. Think multi-arch. */
9836 {"bl", 0xeb000000, 2, ARM_EXT_V1
, do_branch
},
9837 {"b", 0xea000000, 1, ARM_EXT_V1
, do_branch
},
9839 {"bl", 0xebfffffe, 2, ARM_EXT_V1
, do_branch
},
9840 {"b", 0xeafffffe, 1, ARM_EXT_V1
, do_branch
},
9844 {"adr", 0xe28f0000, 3, ARM_EXT_V1
, do_adr
},
9845 {"adrl", 0xe28f0000, 3, ARM_EXT_V1
, do_adrl
},
9846 {"nop", 0xe1a00000, 3, ARM_EXT_V1
, do_nop
},
9848 /* ARM 2 multiplies. */
9849 {"mul", 0xe0000090, 3, ARM_EXT_V2
, do_mul
},
9850 {"muls", 0xe0100090, 3, ARM_EXT_V2
, do_mul
},
9851 {"mla", 0xe0200090, 3, ARM_EXT_V2
, do_mla
},
9852 {"mlas", 0xe0300090, 3, ARM_EXT_V2
, do_mla
},
9854 /* Generic coprocessor instructions. */
9855 {"cdp", 0xee000000, 3, ARM_EXT_V2
, do_cdp
},
9856 {"ldc", 0xec100000, 3, ARM_EXT_V2
, do_lstc
},
9857 {"ldcl", 0xec500000, 3, ARM_EXT_V2
, do_lstc
},
9858 {"stc", 0xec000000, 3, ARM_EXT_V2
, do_lstc
},
9859 {"stcl", 0xec400000, 3, ARM_EXT_V2
, do_lstc
},
9860 {"mcr", 0xee000010, 3, ARM_EXT_V2
, do_co_reg
},
9861 {"mrc", 0xee100010, 3, ARM_EXT_V2
, do_co_reg
},
9863 /* ARM 3 - swp instructions. */
9864 {"swp", 0xe1000090, 3, ARM_EXT_V2S
, do_swap
},
9865 {"swpb", 0xe1400090, 3, ARM_EXT_V2S
, do_swap
},
9867 /* ARM 6 Status register instructions. */
9868 {"mrs", 0xe10f0000, 3, ARM_EXT_V3
, do_mrs
},
9869 {"msr", 0xe120f000, 3, ARM_EXT_V3
, do_msr
},
9870 /* ScottB: our code uses 0xe128f000 for msr.
9871 NickC: but this is wrong because the bits 16 through 19 are
9872 handled by the PSR_xxx defines above. */
9874 /* ARM 7M long multiplies. */
9875 {"smull", 0xe0c00090, 5, ARM_EXT_V3M
, do_mull
},
9876 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M
, do_mull
},
9877 {"umull", 0xe0800090, 5, ARM_EXT_V3M
, do_mull
},
9878 {"umulls", 0xe0900090, 5, ARM_EXT_V3M
, do_mull
},
9879 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M
, do_mull
},
9880 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M
, do_mull
},
9881 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M
, do_mull
},
9882 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M
, do_mull
},
9884 /* ARM Architecture 4. */
9885 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4
, do_ldstv4
},
9886 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4
, do_ldstv4
},
9887 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4
, do_ldstv4
},
9888 {"strh", 0xe00000b0, 3, ARM_EXT_V4
, do_ldstv4
},
9890 /* ARM Architecture 4T. */
9891 /* Note: bx (and blx) are required on V5, even if the processor does
9892 not support Thumb. */
9893 {"bx", 0xe12fff10, 2, ARM_EXT_V4T
| ARM_EXT_V5
, do_bx
},
9895 /* ARM Architecture 5T. */
9896 /* Note: blx has 2 variants, so the .value is set dynamically.
9897 Only one of the variants has conditional execution. */
9898 {"blx", 0xe0000000, 3, ARM_EXT_V5
, do_blx
},
9899 {"clz", 0xe16f0f10, 3, ARM_EXT_V5
, do_clz
},
9900 {"bkpt", 0xe1200070, 0, ARM_EXT_V5
, do_bkpt
},
9901 {"ldc2", 0xfc100000, 0, ARM_EXT_V5
, do_lstc2
},
9902 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5
, do_lstc2
},
9903 {"stc2", 0xfc000000, 0, ARM_EXT_V5
, do_lstc2
},
9904 {"stc2l", 0xfc400000, 0, ARM_EXT_V5
, do_lstc2
},
9905 {"cdp2", 0xfe000000, 0, ARM_EXT_V5
, do_cdp2
},
9906 {"mcr2", 0xfe000010, 0, ARM_EXT_V5
, do_co_reg2
},
9907 {"mrc2", 0xfe100010, 0, ARM_EXT_V5
, do_co_reg2
},
9909 /* ARM Architecture 5TExP. */
9910 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP
, do_smla
},
9911 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP
, do_smla
},
9912 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP
, do_smla
},
9913 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP
, do_smla
},
9915 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP
, do_smla
},
9916 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP
, do_smla
},
9918 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP
, do_smlal
},
9919 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP
, do_smlal
},
9920 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP
, do_smlal
},
9921 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP
, do_smlal
},
9923 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP
, do_smul
},
9924 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP
, do_smul
},
9925 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP
, do_smul
},
9926 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP
, do_smul
},
9928 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP
, do_smul
},
9929 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP
, do_smul
},
9931 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP
, do_qadd
},
9932 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP
, do_qadd
},
9933 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP
, do_qadd
},
9934 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP
, do_qadd
},
9936 /* ARM Architecture 5TE. */
9937 {"pld", 0xf450f000, 0, ARM_EXT_V5E
, do_pld
},
9938 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E
, do_ldrd
},
9939 {"strd", 0xe00000f0, 3, ARM_EXT_V5E
, do_ldrd
},
9941 {"mcrr", 0xec400000, 4, ARM_EXT_V5E
, do_co_reg2c
},
9942 {"mrrc", 0xec500000, 4, ARM_EXT_V5E
, do_co_reg2c
},
9944 /* ARM Architecture 5TEJ. */
9945 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J
, do_bxj
},
9948 { "cps", 0xf1020000, 0, ARM_EXT_V6
, do_cps
},
9949 { "cpsie", 0xf1080000, 0, ARM_EXT_V6
, do_cpsi
},
9950 { "cpsid", 0xf10C0000, 0, ARM_EXT_V6
, do_cpsi
},
9951 { "ldrex", 0xe1900f9f, 5, ARM_EXT_V6
, do_ldrex
},
9952 { "mcrr2", 0xfc400000, 0, ARM_EXT_V6
, do_co_reg2c
},
9953 { "mrrc2", 0xfc500000, 0, ARM_EXT_V6
, do_co_reg2c
},
9954 { "pkhbt", 0xe6800010, 5, ARM_EXT_V6
, do_pkhbt
},
9955 { "pkhtb", 0xe6800050, 5, ARM_EXT_V6
, do_pkhtb
},
9956 { "qadd16", 0xe6200f10, 6, ARM_EXT_V6
, do_qadd16
},
9957 { "qadd8", 0xe6200f90, 5, ARM_EXT_V6
, do_qadd16
},
9958 { "qaddsubx", 0xe6200f30, 8, ARM_EXT_V6
, do_qadd16
},
9959 { "qsub16", 0xe6200f70, 6, ARM_EXT_V6
, do_qadd16
},
9960 { "qsub8", 0xe6200ff0, 5, ARM_EXT_V6
, do_qadd16
},
9961 { "qsubaddx", 0xe6200f50, 8, ARM_EXT_V6
, do_qadd16
},
9962 { "sadd16", 0xe6100f10, 6, ARM_EXT_V6
, do_qadd16
},
9963 { "sadd8", 0xe6100f90, 5, ARM_EXT_V6
, do_qadd16
},
9964 { "saddsubx", 0xe6100f30, 8, ARM_EXT_V6
, do_qadd16
},
9965 { "shadd16", 0xe6300f10, 7, ARM_EXT_V6
, do_qadd16
},
9966 { "shadd8", 0xe6300f90, 6, ARM_EXT_V6
, do_qadd16
},
9967 { "shaddsubx", 0xe6300f30, 9, ARM_EXT_V6
, do_qadd16
},
9968 { "shsub16", 0xe6300f70, 7, ARM_EXT_V6
, do_qadd16
},
9969 { "shsub8", 0xe6300ff0, 6, ARM_EXT_V6
, do_qadd16
},
9970 { "shsubaddx", 0xe6300f50, 9, ARM_EXT_V6
, do_qadd16
},
9971 { "ssub16", 0xe6100f70, 6, ARM_EXT_V6
, do_qadd16
},
9972 { "ssub8", 0xe6100ff0, 5, ARM_EXT_V6
, do_qadd16
},
9973 { "ssubaddx", 0xe6100f50, 8, ARM_EXT_V6
, do_qadd16
},
9974 { "uadd16", 0xe6500f10, 6, ARM_EXT_V6
, do_qadd16
},
9975 { "uadd8", 0xe6500f90, 5, ARM_EXT_V6
, do_qadd16
},
9976 { "uaddsubx", 0xe6500f30, 8, ARM_EXT_V6
, do_qadd16
},
9977 { "uhadd16", 0xe6700f10, 7, ARM_EXT_V6
, do_qadd16
},
9978 { "uhadd8", 0xe6700f90, 6, ARM_EXT_V6
, do_qadd16
},
9979 { "uhaddsubx", 0xe6700f30, 9, ARM_EXT_V6
, do_qadd16
},
9980 { "uhsub16", 0xe6700f70, 7, ARM_EXT_V6
, do_qadd16
},
9981 { "uhsub8", 0xe6700ff0, 6, ARM_EXT_V6
, do_qadd16
},
9982 { "uhsubaddx", 0xe6700f50, 9, ARM_EXT_V6
, do_qadd16
},
9983 { "uqadd16", 0xe6600f10, 7, ARM_EXT_V6
, do_qadd16
},
9984 { "uqadd8", 0xe6600f90, 6, ARM_EXT_V6
, do_qadd16
},
9985 { "uqaddsubx", 0xe6600f30, 9, ARM_EXT_V6
, do_qadd16
},
9986 { "uqsub16", 0xe6600f70, 7, ARM_EXT_V6
, do_qadd16
},
9987 { "uqsub8", 0xe6600ff0, 6, ARM_EXT_V6
, do_qadd16
},
9988 { "uqsubaddx", 0xe6600f50, 9, ARM_EXT_V6
, do_qadd16
},
9989 { "usub16", 0xe6500f70, 6, ARM_EXT_V6
, do_qadd16
},
9990 { "usub8", 0xe6500ff0, 5, ARM_EXT_V6
, do_qadd16
},
9991 { "usubaddx", 0xe6500f50, 8, ARM_EXT_V6
, do_qadd16
},
9992 { "rev", 0xe6bf0f30, 3, ARM_EXT_V6
, do_rev
},
9993 { "rev16", 0xe6bf0fb0, 5, ARM_EXT_V6
, do_rev
},
9994 { "revsh", 0xe6ff0fb0, 5, ARM_EXT_V6
, do_rev
},
9995 { "rfeia", 0xf8900a00, 0, ARM_EXT_V6
, do_rfe
},
9996 { "rfeib", 0xf9900a00, 0, ARM_EXT_V6
, do_rfe
},
9997 { "rfeda", 0xf8100a00, 0, ARM_EXT_V6
, do_rfe
},
9998 { "rfedb", 0xf9100a00, 0, ARM_EXT_V6
, do_rfe
},
9999 { "rfefd", 0xf8900a00, 0, ARM_EXT_V6
, do_rfe
},
10000 { "rfefa", 0xf9900a00, 0, ARM_EXT_V6
, do_rfe
},
10001 { "rfeea", 0xf8100a00, 0, ARM_EXT_V6
, do_rfe
},
10002 { "rfeed", 0xf9100a00, 0, ARM_EXT_V6
, do_rfe
},
10003 { "sxtah", 0xe6b00070, 5, ARM_EXT_V6
, do_sxtah
},
10004 { "sxtab16", 0xe6800070, 7, ARM_EXT_V6
, do_sxtah
},
10005 { "sxtab", 0xe6a00070, 5, ARM_EXT_V6
, do_sxtah
},
10006 { "sxth", 0xe6bf0070, 4, ARM_EXT_V6
, do_sxth
},
10007 { "sxtb16", 0xe68f0070, 6, ARM_EXT_V6
, do_sxth
},
10008 { "sxtb", 0xe6af0070, 4, ARM_EXT_V6
, do_sxth
},
10009 { "uxtah", 0xe6f00070, 5, ARM_EXT_V6
, do_sxtah
},
10010 { "uxtab16", 0xe6c00070, 7, ARM_EXT_V6
, do_sxtah
},
10011 { "uxtab", 0xe6e00070, 5, ARM_EXT_V6
, do_sxtah
},
10012 { "uxth", 0xe6ff0070, 4, ARM_EXT_V6
, do_sxth
},
10013 { "uxtb16", 0xe6cf0070, 6, ARM_EXT_V6
, do_sxth
},
10014 { "uxtb", 0xe6ef0070, 4, ARM_EXT_V6
, do_sxth
},
10015 { "sel", 0xe68000b0, 3, ARM_EXT_V6
, do_qadd16
},
10016 { "setend", 0xf1010000, 0, ARM_EXT_V6
, do_setend
},
10017 { "smlad", 0xe7000010, 5, ARM_EXT_V6
, do_smlad
},
10018 { "smladx", 0xe7000030, 6, ARM_EXT_V6
, do_smlad
},
10019 { "smlald", 0xe7400010, 6, ARM_EXT_V6
, do_smlald
},
10020 { "smlaldx", 0xe7400030, 7, ARM_EXT_V6
, do_smlald
},
10021 { "smlsd", 0xe7000050, 5, ARM_EXT_V6
, do_smlad
},
10022 { "smlsdx", 0xe7000070, 6, ARM_EXT_V6
, do_smlad
},
10023 { "smlsld", 0xe7400050, 6, ARM_EXT_V6
, do_smlald
},
10024 { "smlsldx", 0xe7400070, 7, ARM_EXT_V6
, do_smlald
},
10025 { "smmla", 0xe7500010, 5, ARM_EXT_V6
, do_smlad
},
10026 { "smmlar", 0xe7500030, 6, ARM_EXT_V6
, do_smlad
},
10027 { "smmls", 0xe75000d0, 5, ARM_EXT_V6
, do_smlad
},
10028 { "smmlsr", 0xe75000f0, 6, ARM_EXT_V6
, do_smlad
},
10029 { "smmul", 0xe750f010, 5, ARM_EXT_V6
, do_smmul
},
10030 { "smmulr", 0xe750f030, 6, ARM_EXT_V6
, do_smmul
},
10031 { "smuad", 0xe700f010, 5, ARM_EXT_V6
, do_smmul
},
10032 { "smuadx", 0xe700f030, 6, ARM_EXT_V6
, do_smmul
},
10033 { "smusd", 0xe700f050, 5, ARM_EXT_V6
, do_smmul
},
10034 { "smusdx", 0xe700f070, 6, ARM_EXT_V6
, do_smmul
},
10035 { "srsia", 0xf8cd0500, 0, ARM_EXT_V6
, do_srs
},
10036 { "srsib", 0xf9cd0500, 0, ARM_EXT_V6
, do_srs
},
10037 { "srsda", 0xf84d0500, 0, ARM_EXT_V6
, do_srs
},
10038 { "srsdb", 0xf94d0500, 0, ARM_EXT_V6
, do_srs
},
10039 { "ssat", 0xe6a00010, 4, ARM_EXT_V6
, do_ssat
},
10040 { "ssat16", 0xe6a00f30, 6, ARM_EXT_V6
, do_ssat16
},
10041 { "strex", 0xe1800f90, 5, ARM_EXT_V6
, do_strex
},
10042 { "umaal", 0xe0400090, 5, ARM_EXT_V6
, do_umaal
},
10043 { "usad8", 0xe780f010, 5, ARM_EXT_V6
, do_smmul
},
10044 { "usada8", 0xe7800010, 6, ARM_EXT_V6
, do_smlad
},
10045 { "usat", 0xe6e00010, 4, ARM_EXT_V6
, do_usat
},
10046 { "usat16", 0xe6e00f30, 6, ARM_EXT_V6
, do_usat16
},
10049 { "clrex", 0xf57ff01f, 0, ARM_EXT_V6K
, do_empty
},
10050 { "ldrexb", 0xe1d00f9f, 6, ARM_EXT_V6K
, do_ldrex
},
10051 { "ldrexd", 0xe1b00f9f, 6, ARM_EXT_V6K
, do_ldrex
},
10052 { "ldrexh", 0xe1f00f9f, 6, ARM_EXT_V6K
, do_ldrex
},
10053 { "sev", 0xe320f004, 3, ARM_EXT_V6K
, do_empty
},
10054 { "strexb", 0xe1c00f90, 6, ARM_EXT_V6K
, do_strex
},
10055 { "strexd", 0xe1a00f90, 6, ARM_EXT_V6K
, do_strex
},
10056 { "strexh", 0xe1e00f90, 6, ARM_EXT_V6K
, do_strex
},
10057 { "wfe", 0xe320f002, 3, ARM_EXT_V6K
, do_empty
},
10058 { "wfi", 0xe320f003, 3, ARM_EXT_V6K
, do_empty
},
10059 { "yield", 0xe320f001, 5, ARM_EXT_V6K
, do_empty
},
10062 { "smi", 0xe1600070, 3, ARM_EXT_V6Z
, do_smi
},
10064 /* Core FPA instruction set (V1). */
10065 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
10066 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
10067 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
10068 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
10070 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10071 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10072 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10073 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10075 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10076 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10077 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10078 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10080 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10081 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10082 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10083 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10084 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10085 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10086 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10087 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10088 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10089 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10090 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10091 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10093 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10094 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10095 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10096 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10097 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10098 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10099 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10100 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10101 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10102 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10103 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10104 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10106 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10107 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10108 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10109 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10110 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10111 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10112 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10113 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10114 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10115 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10116 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10117 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10119 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10120 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10121 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10122 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10123 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10124 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10125 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10126 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10127 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10128 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10129 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10130 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10132 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10133 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10134 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10135 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10136 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10137 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10138 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10139 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10140 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10141 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10142 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10143 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10145 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10146 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10147 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10148 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10149 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10150 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10151 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10152 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10153 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10154 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10155 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10156 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10158 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10159 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10160 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10161 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10162 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10163 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10164 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10165 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10166 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10167 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10168 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10169 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10171 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10172 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10173 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10174 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10175 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10176 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10177 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10178 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10179 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10180 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10181 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10182 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10184 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10185 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10186 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10187 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10188 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10189 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10190 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10191 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10192 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10193 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10194 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10195 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10197 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10198 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10199 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10200 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10201 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10202 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10203 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10204 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10205 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10206 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10207 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10208 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10210 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10211 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10212 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10213 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10214 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10215 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10216 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10217 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10218 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10219 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10220 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10221 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10223 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10224 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10225 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10226 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10227 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10228 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10229 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10230 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10231 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10232 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10233 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10234 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10236 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10237 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10238 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10239 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10240 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10241 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10242 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10243 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10244 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10245 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10246 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10247 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10249 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10250 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10251 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10252 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10253 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10254 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10255 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10256 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10257 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10258 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10259 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10260 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10262 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10263 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10264 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10265 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10266 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10267 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10268 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10269 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10270 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10271 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10272 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10273 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10275 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10276 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10277 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10278 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10279 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10280 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10281 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10282 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10283 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10284 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10285 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10286 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10288 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10289 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10290 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10291 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10292 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10293 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10294 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10295 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10296 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10297 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10298 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10299 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10301 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10302 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10303 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10304 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10305 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10306 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10307 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10308 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10309 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10310 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10311 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10312 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10314 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10315 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10316 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10317 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10318 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10319 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10320 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10321 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10322 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10323 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10324 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10325 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10327 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10328 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10329 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10330 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10331 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10332 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10333 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10334 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10335 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10336 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10337 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10338 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10340 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10341 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10342 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10343 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10344 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10345 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10346 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10347 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10348 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10349 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10350 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10351 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10353 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10354 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10355 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10356 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10357 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10358 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10359 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10360 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10361 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10362 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10363 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10364 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10366 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10367 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10368 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10369 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10370 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10371 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10372 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10373 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10374 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10375 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10376 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10377 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10379 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10380 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10381 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10382 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10383 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10384 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10385 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10386 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10387 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10388 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10389 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10390 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10392 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10393 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10394 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10395 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10396 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10397 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10398 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10399 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10400 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10401 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10402 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10403 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10405 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10406 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10407 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10408 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10409 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10410 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10411 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10412 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10413 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10414 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10415 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10416 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10418 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10419 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10420 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10421 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10422 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10423 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10424 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10425 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10426 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10427 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10428 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10429 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10431 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10432 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10433 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10434 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10435 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10436 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10437 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10438 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10439 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10440 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10441 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10442 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10444 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10445 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10446 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10447 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10448 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10449 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10450 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10451 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10452 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10453 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10454 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10455 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10457 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10458 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10459 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10460 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10461 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
10462 not be an optional suffix, but part of the instruction. To be
10463 compatible, we accept either. */
10464 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10465 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10467 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10468 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10469 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10470 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10471 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10472 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10473 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10474 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10475 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10476 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10477 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10478 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10480 /* The implementation of the FIX instruction is broken on some
10481 assemblers, in that it accepts a precision specifier as well as a
10482 rounding specifier, despite the fact that this is meaningless.
10483 To be more compatible, we accept it as well, though of course it
10484 does not set any bits. */
10485 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10486 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10487 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10488 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10489 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10490 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10491 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10492 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10493 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10494 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10495 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10496 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10497 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10499 /* Instructions that were new with the real FPA, call them V2. */
10500 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10501 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10502 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10503 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10504 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10505 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10507 /* VFP V1xD (single precision). */
10508 /* Moves and type conversions. */
10509 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10510 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_reg_from_sp
},
10511 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_from_reg
},
10512 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD
, do_empty
},
10513 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10514 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10515 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10516 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10517 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10518 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10519 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_reg_from_ctrl
},
10520 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_ctrl_from_reg
},
10522 /* Memory operations. */
10523 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldst
},
10524 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldst
},
10525 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
10526 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
10527 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
10528 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
10529 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
10530 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
10531 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
10532 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
10533 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
10534 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
10535 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
10536 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
10537 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
10538 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
10539 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
10540 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
10542 /* Monadic operations. */
10543 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10544 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10545 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10547 /* Dyadic operations. */
10548 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10549 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10550 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10551 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10552 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10553 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10554 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10555 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10556 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10559 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10560 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_compare_z
},
10561 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10562 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_compare_z
},
10564 /* VFP V1 (Double precision). */
10565 /* Moves and type conversions. */
10566 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10567 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
10568 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10569 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1
, do_vfp_dp_from_reg
},
10570 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1
, do_vfp_dp_from_reg
},
10571 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1
, do_vfp_reg_from_dp
},
10572 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1
, do_vfp_reg_from_dp
},
10573 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
10574 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
10575 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10576 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10577 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10578 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10580 /* Memory operations. */
10581 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1
, do_vfp_dp_ldst
},
10582 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1
, do_vfp_dp_ldst
},
10583 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
10584 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
10585 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
10586 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
10587 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
10588 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
10589 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
10590 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
10592 /* Monadic operations. */
10593 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10594 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10595 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10597 /* Dyadic operations. */
10598 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10599 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10600 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10601 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10602 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10603 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10604 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10605 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10606 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10609 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10610 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_compare_z
},
10611 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10612 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1
, do_vfp_dp_compare_z
},
10615 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2
, do_vfp_sp2_from_reg2
},
10616 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2
, do_vfp_reg2_from_sp2
},
10617 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2
, do_vfp_dp_from_reg2
},
10618 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2
, do_vfp_reg2_from_dp
},
10620 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
10621 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE
, do_xsc_mia
},
10622 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10623 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10624 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10625 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10626 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10627 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE
, do_xsc_mar
},
10628 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE
, do_xsc_mra
},
10630 /* Intel Wireless MMX technology instructions. */
10631 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
10632 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
10633 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
10634 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
10635 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
10636 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
10637 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
10638 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
10639 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
10640 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10641 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10642 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10643 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10644 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10645 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10646 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
10647 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
10648 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
10649 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmcr
},
10650 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_tmcrr
},
10651 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10652 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10653 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10654 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10655 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10656 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10657 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
10658 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
10659 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
10660 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmrc
},
10661 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_tmrrc
},
10662 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
10663 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
10664 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
10665 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10666 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10667 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10668 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10669 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10670 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10671 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10672 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10673 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10674 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10675 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10676 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10677 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_waligni
},
10678 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10679 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10680 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10681 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10682 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10683 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10684 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10685 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10686 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10687 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10688 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10689 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10690 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10691 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10692 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10693 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10694 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10695 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10696 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10697 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
10698 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
10699 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
10700 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
10701 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10702 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10703 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10704 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10705 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10706 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10707 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10708 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10709 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10710 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10711 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10712 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10713 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10714 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10715 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10716 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10717 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10718 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10719 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wmov
},
10720 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10721 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10722 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10723 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10724 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10725 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10726 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10727 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10728 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10729 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10730 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10731 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10732 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10733 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10734 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10735 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10736 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10737 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10738 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10739 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10740 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10741 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wshufh
},
10742 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10743 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10744 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10745 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10746 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10747 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10748 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10749 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10750 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10751 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10752 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10753 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10754 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10755 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10756 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10757 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10758 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10759 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10760 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
10761 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
10762 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
10763 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
10764 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10765 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10766 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10767 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10768 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10769 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10770 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10771 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10772 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10773 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10774 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10775 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10776 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10777 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10778 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10779 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10780 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10781 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10782 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10783 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10784 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10785 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10786 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10787 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10788 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10789 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10790 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10791 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10792 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wzero
},
10794 /* Cirrus Maverick instructions. */
10795 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_1
},
10796 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_2
},
10797 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_3
},
10798 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_4
},
10799 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_1
},
10800 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_2
},
10801 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_3
},
10802 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_4
},
10803 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK
, do_mav_binops_2a
},
10804 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1a
},
10805 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK
, do_mav_binops_2b
},
10806 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1b
},
10807 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK
, do_mav_binops_2b
},
10808 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1b
},
10809 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK
, do_mav_binops_2c
},
10810 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1c
},
10811 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK
, do_mav_binops_2c
},
10812 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1c
},
10813 {"cfmval32", 0xee200440, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
10814 {"cfmv32al", 0xee100440, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
10815 {"cfmvam32", 0xee200460, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
10816 {"cfmv32am", 0xee100460, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
10817 {"cfmvah32", 0xee200480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
10818 {"cfmv32ah", 0xee100480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
10819 {"cfmva32", 0xee2004a0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
10820 {"cfmv32a", 0xee1004a0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
10821 {"cfmva64", 0xee2004c0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3c
},
10822 {"cfmv64a", 0xee1004c0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3d
},
10823 {"cfmvsc32", 0xee2004e0, 8, ARM_CEXT_MAVERICK
, do_mav_dspsc_1
},
10824 {"cfmv32sc", 0xee1004e0, 8, ARM_CEXT_MAVERICK
, do_mav_dspsc_2
},
10825 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
10826 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
10827 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1f
},
10828 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1g
},
10829 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1h
},
10830 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1i
},
10831 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1j
},
10832 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1k
},
10833 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1l
},
10834 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1m
},
10835 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK
, do_mav_binops_1l
},
10836 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK
, do_mav_binops_1m
},
10837 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK
, do_mav_triple_4a
},
10838 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK
, do_mav_triple_4b
},
10839 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK
, do_mav_shift_1
},
10840 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK
, do_mav_shift_2
},
10841 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5a
},
10842 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5b
},
10843 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5c
},
10844 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5d
},
10845 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
10846 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
10847 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
10848 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
10849 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
10850 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
10851 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
10852 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
10853 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
10854 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
10855 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1n
},
10856 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1o
},
10857 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1n
},
10858 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1o
},
10859 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
10860 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
10861 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
10862 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
10863 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
10864 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
10865 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
10866 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
10867 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK
, do_mav_quad_6a
},
10868 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK
, do_mav_quad_6a
},
10869 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK
, do_mav_quad_6b
},
10870 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK
, do_mav_quad_6b
},
10873 /* Iterate over the base tables to create the instruction patterns. */
10876 build_arm_ops_hsh (void)
10880 static struct obstack insn_obstack
;
10882 obstack_begin (&insn_obstack
, 4000);
10884 for (i
= 0; i
< sizeof (insns
) / sizeof (struct asm_opcode
); i
++)
10886 const struct asm_opcode
*insn
= insns
+ i
;
10888 if (insn
->cond_offset
!= 0)
10890 /* Insn supports conditional execution. Build the varaints
10891 and insert them in the hash table. */
10892 for (j
= 0; j
< sizeof (conds
) / sizeof (struct asm_cond
); j
++)
10894 unsigned len
= strlen (insn
->template);
10895 struct asm_opcode
*new;
10898 new = obstack_alloc (&insn_obstack
, sizeof (struct asm_opcode
));
10899 /* All condition codes are two characters. */
10900 template = obstack_alloc (&insn_obstack
, len
+ 3);
10902 strncpy (template, insn
->template, insn
->cond_offset
);
10903 strcpy (template + insn
->cond_offset
, conds
[j
].template);
10904 if (len
> insn
->cond_offset
)
10905 strcpy (template + insn
->cond_offset
+ 2,
10906 insn
->template + insn
->cond_offset
);
10907 new->template = template;
10908 new->cond_offset
= 0;
10909 new->variant
= insn
->variant
;
10910 new->parms
= insn
->parms
;
10911 new->value
= (insn
->value
& ~COND_MASK
) | conds
[j
].value
;
10913 hash_insert (arm_ops_hsh
, new->template, (PTR
) new);
10916 /* Finally, insert the unconditional insn in the table directly;
10917 no need to build a copy. */
10918 hash_insert (arm_ops_hsh
, insn
->template, (PTR
) insn
);
10922 #if 0 /* Suppressed - for now. */
10923 #if defined OBJ_ELF || defined OBJ_COFF
10926 #define arm_Note Elf_External_Note
10930 unsigned char namesz
[4]; /* Size of entry's owner string. */
10931 unsigned char descsz
[4]; /* Size of the note descriptor. */
10932 unsigned char type
[4]; /* Interpretation of the descriptor. */
10933 char name
[1]; /* Start of the name+desc data. */
10937 /* The description is kept to a fix sized in order to make updating
10938 it and merging it easier. */
10939 #define ARM_NOTE_DESCRIPTION_LENGTH 8
10942 arm_add_note (const char * name
,
10943 const char * description
,
10946 arm_Note note ATTRIBUTE_UNUSED
;
10948 unsigned int name_len
;
10950 name_len
= (strlen (name
) + 1 + 3) & ~3;
10952 p
= frag_more (sizeof (note
.namesz
));
10953 md_number_to_chars (p
, (valueT
) name_len
, sizeof (note
.namesz
));
10955 p
= frag_more (sizeof (note
.descsz
));
10956 md_number_to_chars (p
, (valueT
) ARM_NOTE_DESCRIPTION_LENGTH
, sizeof (note
.descsz
));
10958 p
= frag_more (sizeof (note
.type
));
10959 md_number_to_chars (p
, (valueT
) type
, sizeof (note
.type
));
10961 p
= frag_more (name_len
);
10964 p
= frag_more (ARM_NOTE_DESCRIPTION_LENGTH
);
10965 strncpy (p
, description
, ARM_NOTE_DESCRIPTION_LENGTH
);
10966 frag_align (2, 0, 0);
10972 static const struct thumb_opcode tinsns
[] =
10974 /* Thumb v1 (ARMv4T). */
10975 {"adc", 0x4140, 2, ARM_EXT_V4T
, do_t_arit
},
10976 {"add", 0x0000, 2, ARM_EXT_V4T
, do_t_add
},
10977 {"and", 0x4000, 2, ARM_EXT_V4T
, do_t_arit
},
10978 {"asr", 0x0000, 2, ARM_EXT_V4T
, do_t_asr
},
10979 {"b", T_OPCODE_BRANCH
, 2, ARM_EXT_V4T
, do_t_branch12
},
10980 {"beq", 0xd0fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10981 {"bne", 0xd1fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10982 {"bcs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10983 {"bhs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10984 {"bcc", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10985 {"bul", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10986 {"blo", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10987 {"bmi", 0xd4fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10988 {"bpl", 0xd5fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10989 {"bvs", 0xd6fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10990 {"bvc", 0xd7fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10991 {"bhi", 0xd8fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10992 {"bls", 0xd9fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10993 {"bge", 0xdafe, 2, ARM_EXT_V4T
, do_t_branch9
},
10994 {"blt", 0xdbfe, 2, ARM_EXT_V4T
, do_t_branch9
},
10995 {"bgt", 0xdcfe, 2, ARM_EXT_V4T
, do_t_branch9
},
10996 {"ble", 0xddfe, 2, ARM_EXT_V4T
, do_t_branch9
},
10997 {"bal", 0xdefe, 2, ARM_EXT_V4T
, do_t_branch9
},
10998 {"bic", 0x4380, 2, ARM_EXT_V4T
, do_t_arit
},
10999 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T
, do_t_branch23
},
11000 {"bx", 0x4700, 2, ARM_EXT_V4T
, do_t_bx
},
11001 {"cmn", T_OPCODE_CMN
, 2, ARM_EXT_V4T
, do_t_arit
},
11002 {"cmp", 0x0000, 2, ARM_EXT_V4T
, do_t_compare
},
11003 {"eor", 0x4040, 2, ARM_EXT_V4T
, do_t_arit
},
11004 {"ldmia", 0xc800, 2, ARM_EXT_V4T
, do_t_ldmstm
},
11005 {"ldr", 0x0000, 2, ARM_EXT_V4T
, do_t_ldr
},
11006 {"ldrb", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrb
},
11007 {"ldrh", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrh
},
11008 {"ldrsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
11009 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
11010 {"ldsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
11011 {"ldsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
11012 {"lsl", 0x0000, 2, ARM_EXT_V4T
, do_t_lsl
},
11013 {"lsr", 0x0000, 2, ARM_EXT_V4T
, do_t_lsr
},
11014 {"mov", 0x0000, 2, ARM_EXT_V4T
, do_t_mov
},
11015 {"mul", T_OPCODE_MUL
, 2, ARM_EXT_V4T
, do_t_arit
},
11016 {"mvn", T_OPCODE_MVN
, 2, ARM_EXT_V4T
, do_t_arit
},
11017 {"neg", T_OPCODE_NEG
, 2, ARM_EXT_V4T
, do_t_arit
},
11018 {"orr", 0x4300, 2, ARM_EXT_V4T
, do_t_arit
},
11019 {"pop", 0xbc00, 2, ARM_EXT_V4T
, do_t_push_pop
},
11020 {"push", 0xb400, 2, ARM_EXT_V4T
, do_t_push_pop
},
11021 {"ror", 0x41c0, 2, ARM_EXT_V4T
, do_t_arit
},
11022 {"sbc", 0x4180, 2, ARM_EXT_V4T
, do_t_arit
},
11023 {"stmia", 0xc000, 2, ARM_EXT_V4T
, do_t_ldmstm
},
11024 {"str", 0x0000, 2, ARM_EXT_V4T
, do_t_str
},
11025 {"strb", 0x0000, 2, ARM_EXT_V4T
, do_t_strb
},
11026 {"strh", 0x0000, 2, ARM_EXT_V4T
, do_t_strh
},
11027 {"swi", 0xdf00, 2, ARM_EXT_V4T
, do_t_swi
},
11028 {"sub", 0x0000, 2, ARM_EXT_V4T
, do_t_sub
},
11029 {"tst", T_OPCODE_TST
, 2, ARM_EXT_V4T
, do_t_arit
},
11031 {"adr", 0x0000, 2, ARM_EXT_V4T
, do_t_adr
},
11032 {"nop", 0x46C0, 2, ARM_EXT_V4T
, do_t_nop
}, /* mov r8,r8 */
11033 /* Thumb v2 (ARMv5T). */
11034 {"blx", 0, 0, ARM_EXT_V5T
, do_t_blx
},
11035 {"bkpt", 0xbe00, 2, ARM_EXT_V5T
, do_t_bkpt
},
11038 {"cpsie", 0xb660, 2, ARM_EXT_V6
, do_t_cps
},
11039 {"cpsid", 0xb670, 2, ARM_EXT_V6
, do_t_cps
},
11040 {"cpy", 0x4600, 2, ARM_EXT_V6
, do_t_cpy
},
11041 {"rev", 0xba00, 2, ARM_EXT_V6
, do_t_arit
},
11042 {"rev16", 0xba40, 2, ARM_EXT_V6
, do_t_arit
},
11043 {"revsh", 0xbac0, 2, ARM_EXT_V6
, do_t_arit
},
11044 {"setend", 0xb650, 2, ARM_EXT_V6
, do_t_setend
},
11045 {"sxth", 0xb200, 2, ARM_EXT_V6
, do_t_arit
},
11046 {"sxtb", 0xb240, 2, ARM_EXT_V6
, do_t_arit
},
11047 {"uxth", 0xb280, 2, ARM_EXT_V6
, do_t_arit
},
11048 {"uxtb", 0xb2c0, 2, ARM_EXT_V6
, do_t_arit
},
11057 if ( (arm_ops_hsh
= hash_new ()) == NULL
11058 || (arm_tops_hsh
= hash_new ()) == NULL
11059 || (arm_cond_hsh
= hash_new ()) == NULL
11060 || (arm_shift_hsh
= hash_new ()) == NULL
11061 || (arm_psr_hsh
= hash_new ()) == NULL
)
11062 as_fatal (_("virtual memory exhausted"));
11064 build_arm_ops_hsh ();
11065 for (i
= 0; i
< sizeof (tinsns
) / sizeof (struct thumb_opcode
); i
++)
11066 hash_insert (arm_tops_hsh
, tinsns
[i
].template, (PTR
) (tinsns
+ i
));
11067 for (i
= 0; i
< sizeof (conds
) / sizeof (struct asm_cond
); i
++)
11068 hash_insert (arm_cond_hsh
, conds
[i
].template, (PTR
) (conds
+ i
));
11069 for (i
= 0; i
< sizeof (shift_names
) / sizeof (struct asm_shift_name
); i
++)
11070 hash_insert (arm_shift_hsh
, shift_names
[i
].name
, (PTR
) (shift_names
+ i
));
11071 for (i
= 0; i
< sizeof (psrs
) / sizeof (struct asm_psr
); i
++)
11072 hash_insert (arm_psr_hsh
, psrs
[i
].template, (PTR
) (psrs
+ i
));
11074 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
11075 build_reg_hsh (all_reg_maps
+ i
);
11077 set_constant_flonums ();
11079 /* Set the cpu variant based on the command-line options. We prefer
11080 -mcpu= over -march= if both are set (as for GCC); and we prefer
11081 -mfpu= over any other way of setting the floating point unit.
11082 Use of legacy options with new options are faulted. */
11083 if (legacy_cpu
!= -1)
11085 if (mcpu_cpu_opt
!= -1 || march_cpu_opt
!= -1)
11086 as_bad (_("use of old and new-style options to set CPU type"));
11088 mcpu_cpu_opt
= legacy_cpu
;
11090 else if (mcpu_cpu_opt
== -1)
11091 mcpu_cpu_opt
= march_cpu_opt
;
11093 if (legacy_fpu
!= -1)
11095 if (mfpu_opt
!= -1)
11096 as_bad (_("use of old and new-style options to set FPU type"));
11098 mfpu_opt
= legacy_fpu
;
11100 else if (mfpu_opt
== -1)
11102 #if !(defined (TE_LINUX) || defined (TE_NetBSD))
11103 /* Some environments specify a default FPU. If they don't, infer it
11104 from the processor. */
11105 if (mcpu_fpu_opt
!= -1)
11106 mfpu_opt
= mcpu_fpu_opt
;
11108 mfpu_opt
= march_fpu_opt
;
11110 mfpu_opt
= FPU_DEFAULT
;
11114 if (mfpu_opt
== -1)
11116 if (mcpu_cpu_opt
== -1)
11117 mfpu_opt
= FPU_DEFAULT
;
11118 else if (mcpu_cpu_opt
& ARM_EXT_V5
)
11119 mfpu_opt
= FPU_ARCH_VFP_V2
;
11121 mfpu_opt
= FPU_ARCH_FPA
;
11124 if (mcpu_cpu_opt
== -1)
11125 mcpu_cpu_opt
= CPU_DEFAULT
;
11127 cpu_variant
= mcpu_cpu_opt
| mfpu_opt
;
11130 unsigned int flags
= 0;
11132 #if defined OBJ_ELF
11133 flags
= meabi_flags
;
11135 switch (meabi_flags
)
11137 case EF_ARM_EABI_UNKNOWN
:
11139 #if defined OBJ_COFF || defined OBJ_ELF
11140 /* Set the flags in the private structure. */
11141 if (uses_apcs_26
) flags
|= F_APCS26
;
11142 if (support_interwork
) flags
|= F_INTERWORK
;
11143 if (uses_apcs_float
) flags
|= F_APCS_FLOAT
;
11144 if (pic_code
) flags
|= F_PIC
;
11145 if ((cpu_variant
& FPU_ANY
) == FPU_NONE
11146 || (cpu_variant
& FPU_ANY
) == FPU_ARCH_VFP
) /* VFP layout only. */
11147 flags
|= F_SOFT_FLOAT
;
11149 switch (mfloat_abi_opt
)
11151 case ARM_FLOAT_ABI_SOFT
:
11152 case ARM_FLOAT_ABI_SOFTFP
:
11153 flags
|= F_SOFT_FLOAT
;
11156 case ARM_FLOAT_ABI_HARD
:
11157 if (flags
& F_SOFT_FLOAT
)
11158 as_bad (_("hard-float conflicts with specified fpu"));
11162 /* Using VFP conventions (even if soft-float). */
11163 if (cpu_variant
& FPU_VFP_EXT_NONE
)
11164 flags
|= F_VFP_FLOAT
;
11166 #if defined OBJ_ELF
11167 if (cpu_variant
& FPU_ARCH_MAVERICK
)
11168 flags
|= EF_ARM_MAVERICK_FLOAT
;
11171 case EF_ARM_EABI_VER3
:
11172 /* No additional flags to set. */
11179 #if defined OBJ_COFF || defined OBJ_ELF
11180 bfd_set_private_flags (stdoutput
, flags
);
11182 /* We have run out flags in the COFF header to encode the
11183 status of ATPCS support, so instead we create a dummy,
11184 empty, debug section called .arm.atpcs. */
11189 sec
= bfd_make_section (stdoutput
, ".arm.atpcs");
11193 bfd_set_section_flags
11194 (stdoutput
, sec
, SEC_READONLY
| SEC_DEBUGGING
/* | SEC_HAS_CONTENTS */);
11195 bfd_set_section_size (stdoutput
, sec
, 0);
11196 bfd_set_section_contents (stdoutput
, sec
, NULL
, 0, 0);
11202 /* Record the CPU type as well. */
11203 switch (cpu_variant
& ARM_CPU_MASK
)
11206 mach
= bfd_mach_arm_2
;
11209 case ARM_3
: /* Also ARM_250. */
11210 mach
= bfd_mach_arm_2a
;
11213 case ARM_6
: /* Also ARM_7. */
11214 mach
= bfd_mach_arm_3
;
11218 mach
= bfd_mach_arm_unknown
;
11222 /* Catch special cases. */
11223 if (cpu_variant
& ARM_CEXT_IWMMXT
)
11224 mach
= bfd_mach_arm_iWMMXt
;
11225 else if (cpu_variant
& ARM_CEXT_XSCALE
)
11226 mach
= bfd_mach_arm_XScale
;
11227 else if (cpu_variant
& ARM_CEXT_MAVERICK
)
11228 mach
= bfd_mach_arm_ep9312
;
11229 else if (cpu_variant
& ARM_EXT_V5E
)
11230 mach
= bfd_mach_arm_5TE
;
11231 else if (cpu_variant
& ARM_EXT_V5
)
11233 if (cpu_variant
& ARM_EXT_V4T
)
11234 mach
= bfd_mach_arm_5T
;
11236 mach
= bfd_mach_arm_5
;
11238 else if (cpu_variant
& ARM_EXT_V4
)
11240 if (cpu_variant
& ARM_EXT_V4T
)
11241 mach
= bfd_mach_arm_4T
;
11243 mach
= bfd_mach_arm_4
;
11245 else if (cpu_variant
& ARM_EXT_V3M
)
11246 mach
= bfd_mach_arm_3M
;
11248 #if 0 /* Suppressed - for now. */
11249 #if defined (OBJ_ELF) || defined (OBJ_COFF)
11251 /* Create a .note section to fully identify this arm binary. */
11253 #define NOTE_ARCH_STRING "arch: "
11255 #if defined OBJ_COFF && ! defined NT_VERSION
11256 #define NT_VERSION 1
11261 segT current_seg
= now_seg
;
11262 subsegT current_subseg
= now_subseg
;
11263 asection
* arm_arch
;
11264 const char * arch_string
;
11266 arm_arch
= bfd_make_section_old_way (stdoutput
, ARM_NOTE_SECTION
);
11269 bfd_set_section_flags (stdoutput
, arm_arch
,
11270 SEC_DATA
| SEC_ALLOC
| SEC_LOAD
| SEC_LINK_ONCE \
11271 | SEC_HAS_CONTENTS
);
11273 bfd_set_section_flags (stdoutput
, arm_arch
,
11274 SEC_READONLY
| SEC_HAS_CONTENTS
);
11276 arm_arch
->output_section
= arm_arch
;
11277 subseg_set (arm_arch
, 0);
11282 case bfd_mach_arm_unknown
: arch_string
= "unknown"; break;
11283 case bfd_mach_arm_2
: arch_string
= "armv2"; break;
11284 case bfd_mach_arm_2a
: arch_string
= "armv2a"; break;
11285 case bfd_mach_arm_3
: arch_string
= "armv3"; break;
11286 case bfd_mach_arm_3M
: arch_string
= "armv3M"; break;
11287 case bfd_mach_arm_4
: arch_string
= "armv4"; break;
11288 case bfd_mach_arm_4T
: arch_string
= "armv4t"; break;
11289 case bfd_mach_arm_5
: arch_string
= "armv5"; break;
11290 case bfd_mach_arm_5T
: arch_string
= "armv5t"; break;
11291 case bfd_mach_arm_5TE
: arch_string
= "armv5te"; break;
11292 case bfd_mach_arm_XScale
: arch_string
= "XScale"; break;
11293 case bfd_mach_arm_ep9312
: arch_string
= "ep9312"; break;
11294 case bfd_mach_arm_iWMMXt
: arch_string
= "iWMMXt"; break;
11297 arm_add_note (NOTE_ARCH_STRING
, arch_string
, NT_ARCH
);
11299 subseg_set (current_seg
, current_subseg
);
11302 #endif /* Suppressed code. */
11304 bfd_set_arch_mach (stdoutput
, TARGET_ARCH
, mach
);
11307 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11308 for use in the a.out file, and stores them in the array pointed to by buf.
11309 This knows about the endian-ness of the target machine and does
11310 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11311 2 (short) and 4 (long) Floating numbers are put out as a series of
11312 LITTLENUMS (shorts, here at least). */
11315 md_number_to_chars (char * buf
, valueT val
, int n
)
11317 if (target_big_endian
)
11318 number_to_chars_bigendian (buf
, val
, n
);
11320 number_to_chars_littleendian (buf
, val
, n
);
11324 md_chars_to_number (char * buf
, int n
)
11327 unsigned char * where
= (unsigned char *) buf
;
11329 if (target_big_endian
)
11334 result
|= (*where
++ & 255);
11342 result
|= (where
[n
] & 255);
11349 /* Turn a string in input_line_pointer into a floating point constant
11350 of type TYPE, and store the appropriate bytes in *LITP. The number
11351 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11352 returned, or NULL on OK.
11354 Note that fp constants aren't represent in the normal way on the ARM.
11355 In big endian mode, things are as expected. However, in little endian
11356 mode fp constants are big-endian word-wise, and little-endian byte-wise
11357 within the words. For example, (double) 1.1 in big endian mode is
11358 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11359 the byte sequence 99 99 f1 3f 9a 99 99 99.
11361 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11364 md_atof (int type
, char * litP
, int * sizeP
)
11367 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
11399 return _("bad call to MD_ATOF()");
11402 t
= atof_ieee (input_line_pointer
, type
, words
);
11404 input_line_pointer
= t
;
11407 if (target_big_endian
)
11409 for (i
= 0; i
< prec
; i
++)
11411 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
11417 if (cpu_variant
& FPU_ARCH_VFP
)
11418 for (i
= prec
- 1; i
>= 0; i
--)
11420 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
11424 /* For a 4 byte float the order of elements in `words' is 1 0.
11425 For an 8 byte float the order is 1 0 3 2. */
11426 for (i
= 0; i
< prec
; i
+= 2)
11428 md_number_to_chars (litP
, (valueT
) words
[i
+ 1], 2);
11429 md_number_to_chars (litP
+ 2, (valueT
) words
[i
], 2);
11437 /* The knowledge of the PC's pipeline offset is built into the insns
11441 md_pcrel_from (fixS
* fixP
)
11444 && S_GET_SEGMENT (fixP
->fx_addsy
) == undefined_section
11445 && fixP
->fx_subsy
== NULL
)
11448 if (fixP
->fx_pcrel
&& (fixP
->fx_r_type
== BFD_RELOC_ARM_THUMB_ADD
))
11450 /* PC relative addressing on the Thumb is slightly odd
11451 as the bottom two bits of the PC are forced to zero
11452 for the calculation. */
11453 return (fixP
->fx_where
+ fixP
->fx_frag
->fr_address
) & ~3;
11457 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
11458 so we un-adjust here to compensate for the accommodation. */
11459 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
+ 8;
11461 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
11465 /* Round up a section size to the appropriate boundary. */
11468 md_section_align (segT segment ATTRIBUTE_UNUSED
,
11474 /* Round all sects to multiple of 4. */
11475 return (size
+ 3) & ~3;
11479 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
11480 Otherwise we have no need to default values of symbols. */
11483 md_undefined_symbol (char * name ATTRIBUTE_UNUSED
)
11486 if (name
[0] == '_' && name
[1] == 'G'
11487 && streq (name
, GLOBAL_OFFSET_TABLE_NAME
))
11491 if (symbol_find (name
))
11492 as_bad ("GOT already in the symbol table");
11494 GOT_symbol
= symbol_new (name
, undefined_section
,
11495 (valueT
) 0, & zero_address_frag
);
11506 md_apply_fix3 (fixS
* fixP
,
11510 offsetT value
= * valP
;
11512 unsigned int newimm
;
11513 unsigned long temp
;
11515 char * buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
11516 arm_fix_data
* arm_data
= (arm_fix_data
*) fixP
->tc_fix_data
;
11518 assert (fixP
->fx_r_type
< BFD_RELOC_UNUSED
);
11520 /* Note whether this will delete the relocation. */
11522 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
11523 doesn't work fully.) */
11524 if ((fixP
->fx_addsy
== 0 || symbol_constant_p (fixP
->fx_addsy
))
11525 && !fixP
->fx_pcrel
)
11527 if (fixP
->fx_addsy
== 0 && !fixP
->fx_pcrel
)
11531 /* If this symbol is in a different section then we need to leave it for
11532 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
11533 so we have to undo it's effects here. */
11534 if (fixP
->fx_pcrel
)
11536 if (fixP
->fx_addsy
!= NULL
11537 && S_IS_DEFINED (fixP
->fx_addsy
)
11538 && S_GET_SEGMENT (fixP
->fx_addsy
) != seg
)
11541 && (fixP
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
11542 || fixP
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
11546 value
+= md_pcrel_from (fixP
);
11550 /* Remember value for emit_reloc. */
11551 fixP
->fx_addnumber
= value
;
11553 switch (fixP
->fx_r_type
)
11555 case BFD_RELOC_ARM_IMMEDIATE
:
11556 /* We claim that this fixup has been processed here,
11557 even if in fact we generate an error because we do
11558 not have a reloc for it, so tc_gen_reloc will reject it. */
11562 && ! S_IS_DEFINED (fixP
->fx_addsy
))
11564 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11565 _("undefined symbol %s used as an immediate value"),
11566 S_GET_NAME (fixP
->fx_addsy
));
11570 newimm
= validate_immediate (value
);
11571 temp
= md_chars_to_number (buf
, INSN_SIZE
);
11573 /* If the instruction will fail, see if we can fix things up by
11574 changing the opcode. */
11575 if (newimm
== (unsigned int) FAIL
11576 && (newimm
= negate_data_op (&temp
, value
)) == (unsigned int) FAIL
)
11578 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11579 _("invalid constant (%lx) after fixup"),
11580 (unsigned long) value
);
11584 newimm
|= (temp
& 0xfffff000);
11585 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
11588 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
11590 unsigned int highpart
= 0;
11591 unsigned int newinsn
= 0xe1a00000; /* nop. */
11593 newimm
= validate_immediate (value
);
11594 temp
= md_chars_to_number (buf
, INSN_SIZE
);
11596 /* If the instruction will fail, see if we can fix things up by
11597 changing the opcode. */
11598 if (newimm
== (unsigned int) FAIL
11599 && (newimm
= negate_data_op (& temp
, value
)) == (unsigned int) FAIL
)
11601 /* No ? OK - try using two ADD instructions to generate
11603 newimm
= validate_immediate_twopart (value
, & highpart
);
11605 /* Yes - then make sure that the second instruction is
11607 if (newimm
!= (unsigned int) FAIL
)
11609 /* Still No ? Try using a negated value. */
11610 else if ((newimm
= validate_immediate_twopart (- value
, & highpart
)) != (unsigned int) FAIL
)
11611 temp
= newinsn
= (temp
& OPCODE_MASK
) | OPCODE_SUB
<< DATA_OP_SHIFT
;
11612 /* Otherwise - give up. */
11615 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11616 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
11621 /* Replace the first operand in the 2nd instruction (which
11622 is the PC) with the destination register. We have
11623 already added in the PC in the first instruction and we
11624 do not want to do it again. */
11625 newinsn
&= ~ 0xf0000;
11626 newinsn
|= ((newinsn
& 0x0f000) << 4);
11629 newimm
|= (temp
& 0xfffff000);
11630 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
11632 highpart
|= (newinsn
& 0xfffff000);
11633 md_number_to_chars (buf
+ INSN_SIZE
, (valueT
) highpart
, INSN_SIZE
);
11637 case BFD_RELOC_ARM_OFFSET_IMM
:
11643 if (validate_offset_imm (value
, 0) == FAIL
)
11645 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11646 _("bad immediate value for offset (%ld)"),
11651 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11652 newval
&= 0xff7ff000;
11653 newval
|= value
| (sign
? INDEX_UP
: 0);
11654 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11657 case BFD_RELOC_ARM_OFFSET_IMM8
:
11658 case BFD_RELOC_ARM_HWLITERAL
:
11664 if (validate_offset_imm (value
, 1) == FAIL
)
11666 if (fixP
->fx_r_type
== BFD_RELOC_ARM_HWLITERAL
)
11667 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11668 _("invalid literal constant: pool needs to be closer"));
11670 as_bad (_("bad immediate value for half-word offset (%ld)"),
11675 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11676 newval
&= 0xff7ff0f0;
11677 newval
|= ((value
>> 4) << 8) | (value
& 0xf) | (sign
? INDEX_UP
: 0);
11678 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11681 case BFD_RELOC_ARM_LITERAL
:
11687 if (validate_offset_imm (value
, 0) == FAIL
)
11689 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11690 _("invalid literal constant: pool needs to be closer"));
11694 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11695 newval
&= 0xff7ff000;
11696 newval
|= value
| (sign
? INDEX_UP
: 0);
11697 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11700 case BFD_RELOC_ARM_SHIFT_IMM
:
11701 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11702 if (((unsigned long) value
) > 32
11704 && (((newval
& 0x60) == 0) || (newval
& 0x60) == 0x60)))
11706 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11707 _("shift expression is too large"));
11712 /* Shifts of zero must be done as lsl. */
11714 else if (value
== 32)
11716 newval
&= 0xfffff07f;
11717 newval
|= (value
& 0x1f) << 7;
11718 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11721 case BFD_RELOC_ARM_SMI
:
11722 if (((unsigned long) value
) > 0xffff)
11723 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11724 _("invalid smi expression"));
11725 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xfff000f0;
11726 newval
|= (value
& 0xf) | ((value
& 0xfff0) << 4);
11727 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11730 case BFD_RELOC_ARM_SWI
:
11731 if (arm_data
->thumb_mode
)
11733 if (((unsigned long) value
) > 0xff)
11734 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11735 _("invalid swi expression"));
11736 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xff00;
11738 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11742 if (((unsigned long) value
) > 0x00ffffff)
11743 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11744 _("invalid swi expression"));
11745 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff000000;
11747 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11751 case BFD_RELOC_ARM_MULTI
:
11752 if (((unsigned long) value
) > 0xffff)
11753 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11754 _("invalid expression in load/store multiple"));
11755 newval
= value
| md_chars_to_number (buf
, INSN_SIZE
);
11756 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11759 case BFD_RELOC_ARM_PCREL_BRANCH
:
11760 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11762 /* Sign-extend a 24-bit number. */
11763 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
11767 value
= fixP
->fx_offset
;
11770 /* We are going to store value (shifted right by two) in the
11771 instruction, in a 24 bit, signed field. Thus we need to check
11772 that none of the top 8 bits of the shifted value (top 7 bits of
11773 the unshifted, unsigned value) are set, or that they are all set. */
11774 if ((value
& ~ ((offsetT
) 0x1ffffff)) != 0
11775 && ((value
& ~ ((offsetT
) 0x1ffffff)) != ~ ((offsetT
) 0x1ffffff)))
11778 /* Normally we would be stuck at this point, since we cannot store
11779 the absolute address that is the destination of the branch in the
11780 24 bits of the branch instruction. If however, we happen to know
11781 that the destination of the branch is in the same section as the
11782 branch instruction itself, then we can compute the relocation for
11783 ourselves and not have to bother the linker with it.
11785 FIXME: The tests for OBJ_ELF and ! target_oabi are only here
11786 because I have not worked out how to do this for OBJ_COFF or
11789 && fixP
->fx_addsy
!= NULL
11790 && S_IS_DEFINED (fixP
->fx_addsy
)
11791 && S_GET_SEGMENT (fixP
->fx_addsy
) == seg
)
11793 /* Get pc relative value to go into the branch. */
11796 /* Permit a backward branch provided that enough bits
11797 are set. Allow a forwards branch, provided that
11798 enough bits are clear. */
11799 if ( (value
& ~ ((offsetT
) 0x1ffffff)) == ~ ((offsetT
) 0x1ffffff)
11800 || (value
& ~ ((offsetT
) 0x1ffffff)) == 0)
11804 if (! fixP
->fx_done
)
11806 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11807 _("GAS can't handle same-section branch dest >= 0x04000000"));
11811 value
+= SEXT24 (newval
);
11813 if ( (value
& ~ ((offsetT
) 0xffffff)) != 0
11814 && ((value
& ~ ((offsetT
) 0xffffff)) != ~ ((offsetT
) 0xffffff)))
11815 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11816 _("out of range branch"));
11818 newval
= (value
& 0x00ffffff) | (newval
& 0xff000000);
11819 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11822 case BFD_RELOC_ARM_PCREL_BLX
:
11825 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11829 value
= fixP
->fx_offset
;
11831 hbit
= (value
>> 1) & 1;
11832 value
= (value
>> 2) & 0x00ffffff;
11833 value
= (value
+ (newval
& 0x00ffffff)) & 0x00ffffff;
11834 newval
= value
| (newval
& 0xfe000000) | (hbit
<< 24);
11835 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11839 case BFD_RELOC_THUMB_PCREL_BRANCH9
: /* Conditional branch. */
11840 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11842 addressT diff
= (newval
& 0xff) << 1;
11847 if ((value
& ~0xff) && ((value
& ~0xff) != ~0xff))
11848 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11849 _("branch out of range"));
11850 newval
= (newval
& 0xff00) | ((value
& 0x1ff) >> 1);
11852 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11855 case BFD_RELOC_THUMB_PCREL_BRANCH12
: /* Unconditional branch. */
11856 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11858 addressT diff
= (newval
& 0x7ff) << 1;
11863 if ((value
& ~0x7ff) && ((value
& ~0x7ff) != ~0x7ff))
11864 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11865 _("branch out of range"));
11866 newval
= (newval
& 0xf800) | ((value
& 0xfff) >> 1);
11868 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11871 case BFD_RELOC_THUMB_PCREL_BLX
:
11872 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
11877 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11878 newval2
= md_chars_to_number (buf
+ THUMB_SIZE
, THUMB_SIZE
);
11879 diff
= ((newval
& 0x7ff) << 12) | ((newval2
& 0x7ff) << 1);
11880 if (diff
& 0x400000)
11883 value
= fixP
->fx_offset
;
11887 if ((value
& ~0x3fffff) && ((value
& ~0x3fffff) != ~0x3fffff))
11888 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11889 _("branch with link out of range"));
11891 newval
= (newval
& 0xf800) | ((value
& 0x7fffff) >> 12);
11892 newval2
= (newval2
& 0xf800) | ((value
& 0xfff) >> 1);
11893 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
)
11894 /* For a BLX instruction, make sure that the relocation is rounded up
11895 to a word boundary. This follows the semantics of the instruction
11896 which specifies that bit 1 of the target address will come from bit
11897 1 of the base address. */
11898 newval2
= (newval2
+ 1) & ~ 1;
11899 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11900 md_number_to_chars (buf
+ THUMB_SIZE
, newval2
, THUMB_SIZE
);
11905 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11906 md_number_to_chars (buf
, value
, 1);
11908 else if (!target_oabi
)
11910 value
= fixP
->fx_offset
;
11911 md_number_to_chars (buf
, value
, 1);
11917 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11918 md_number_to_chars (buf
, value
, 2);
11920 else if (!target_oabi
)
11922 value
= fixP
->fx_offset
;
11923 md_number_to_chars (buf
, value
, 2);
11929 case BFD_RELOC_ARM_GOT32
:
11930 case BFD_RELOC_ARM_GOTOFF
:
11931 case BFD_RELOC_ARM_TARGET2
:
11932 md_number_to_chars (buf
, 0, 4);
11936 case BFD_RELOC_RVA
:
11938 case BFD_RELOC_ARM_TARGET1
:
11939 case BFD_RELOC_ARM_ROSEGREL32
:
11940 case BFD_RELOC_ARM_SBREL32
:
11941 case BFD_RELOC_32_PCREL
:
11942 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11943 md_number_to_chars (buf
, value
, 4);
11945 else if (!target_oabi
)
11947 value
= fixP
->fx_offset
;
11948 md_number_to_chars (buf
, value
, 4);
11954 case BFD_RELOC_ARM_PREL31
:
11955 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11957 newval
= md_chars_to_number (buf
, 4) & 0x80000000;
11958 if ((value
^ (value
>> 1)) & 0x40000000)
11960 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11961 _("rel31 relocation overflow"));
11963 newval
|= value
& 0x7fffffff;
11964 md_number_to_chars (buf
, newval
, 4);
11968 case BFD_RELOC_ARM_PLT32
:
11969 /* It appears the instruction is fully prepared at this point. */
11973 case BFD_RELOC_ARM_CP_OFF_IMM
:
11975 if (value
< -1023 || value
> 1023 || (value
& 3))
11976 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11977 _("illegal value for co-processor offset"));
11980 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
11981 newval
|= (value
>> 2) | (sign
? INDEX_UP
: 0);
11982 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11985 case BFD_RELOC_ARM_CP_OFF_IMM_S2
:
11987 if (value
< -255 || value
> 255)
11988 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11989 _("Illegal value for co-processor offset"));
11992 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
11993 newval
|= value
| (sign
? INDEX_UP
: 0);
11994 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11997 case BFD_RELOC_ARM_THUMB_OFFSET
:
11998 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11999 /* Exactly what ranges, and where the offset is inserted depends
12000 on the type of instruction, we can establish this from the
12002 switch (newval
>> 12)
12004 case 4: /* PC load. */
12005 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
12006 forced to zero for these loads, so we will need to round
12007 up the offset if the instruction address is not word
12008 aligned (since the final address produced must be, and
12009 we can only describe word-aligned immediate offsets). */
12011 if ((fixP
->fx_frag
->fr_address
+ fixP
->fx_where
+ value
) & 3)
12012 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12013 _("invalid offset, target not word aligned (0x%08X)"),
12014 (unsigned int) (fixP
->fx_frag
->fr_address
12015 + fixP
->fx_where
+ value
));
12017 if ((value
+ 2) & ~0x3fe)
12018 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12019 _("invalid offset, value too big (0x%08lX)"),
12022 /* Round up, since pc will be rounded down. */
12023 newval
|= (value
+ 2) >> 2;
12026 case 9: /* SP load/store. */
12027 if (value
& ~0x3fc)
12028 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12029 _("invalid offset, value too big (0x%08lX)"),
12031 newval
|= value
>> 2;
12034 case 6: /* Word load/store. */
12036 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12037 _("invalid offset, value too big (0x%08lX)"),
12039 newval
|= value
<< 4; /* 6 - 2. */
12042 case 7: /* Byte load/store. */
12044 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12045 _("invalid offset, value too big (0x%08lX)"),
12047 newval
|= value
<< 6;
12050 case 8: /* Halfword load/store. */
12052 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12053 _("invalid offset, value too big (0x%08lX)"),
12055 newval
|= value
<< 5; /* 6 - 1. */
12059 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12060 "Unable to process relocation for thumb opcode: %lx",
12061 (unsigned long) newval
);
12064 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12067 case BFD_RELOC_ARM_THUMB_ADD
:
12068 /* This is a complicated relocation, since we use it for all of
12069 the following immediate relocations:
12073 9bit ADD/SUB SP word-aligned
12074 10bit ADD PC/SP word-aligned
12076 The type of instruction being processed is encoded in the
12083 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12085 int rd
= (newval
>> 4) & 0xf;
12086 int rs
= newval
& 0xf;
12087 int subtract
= newval
& 0x8000;
12091 if (value
& ~0x1fc)
12092 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12093 _("invalid immediate for stack address calculation"));
12094 newval
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
12095 newval
|= value
>> 2;
12097 else if (rs
== REG_PC
|| rs
== REG_SP
)
12101 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12102 _("invalid immediate for address calculation (value = 0x%08lX)"),
12103 (unsigned long) value
);
12104 newval
= (rs
== REG_PC
? T_OPCODE_ADD_PC
: T_OPCODE_ADD_SP
);
12106 newval
|= value
>> 2;
12111 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12112 _("invalid 8bit immediate"));
12113 newval
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
12114 newval
|= (rd
<< 8) | value
;
12119 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12120 _("invalid 3bit immediate"));
12121 newval
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
12122 newval
|= rd
| (rs
<< 3) | (value
<< 6);
12125 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12128 case BFD_RELOC_ARM_THUMB_IMM
:
12129 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12130 switch (newval
>> 11)
12132 case 0x04: /* 8bit immediate MOV. */
12133 case 0x05: /* 8bit immediate CMP. */
12134 if (value
< 0 || value
> 255)
12135 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12136 _("invalid immediate: %ld is too large"),
12144 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12147 case BFD_RELOC_ARM_THUMB_SHIFT
:
12148 /* 5bit shift value (0..31). */
12149 if (value
< 0 || value
> 31)
12150 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12151 _("illegal Thumb shift value: %ld"), (long) value
);
12152 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xf03f;
12153 newval
|= value
<< 6;
12154 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12157 case BFD_RELOC_VTABLE_INHERIT
:
12158 case BFD_RELOC_VTABLE_ENTRY
:
12162 case BFD_RELOC_NONE
:
12164 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12165 _("bad relocation fixup type (%d)"), fixP
->fx_r_type
);
12169 /* Translate internal representation of relocation info to BFD target
12173 tc_gen_reloc (asection
* section ATTRIBUTE_UNUSED
,
12177 bfd_reloc_code_real_type code
;
12179 reloc
= xmalloc (sizeof (arelent
));
12181 reloc
->sym_ptr_ptr
= xmalloc (sizeof (asymbol
*));
12182 *reloc
->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
12183 reloc
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
12185 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12187 if (fixp
->fx_pcrel
== 0)
12188 reloc
->addend
= fixp
->fx_offset
;
12190 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
12191 #else /* OBJ_ELF */
12192 reloc
->addend
= fixp
->fx_offset
;
12195 switch (fixp
->fx_r_type
)
12198 if (fixp
->fx_pcrel
)
12200 code
= BFD_RELOC_8_PCREL
;
12205 if (fixp
->fx_pcrel
)
12207 code
= BFD_RELOC_16_PCREL
;
12212 if (fixp
->fx_pcrel
)
12214 code
= BFD_RELOC_32_PCREL
;
12218 case BFD_RELOC_ARM_PCREL_BRANCH
:
12219 case BFD_RELOC_ARM_PCREL_BLX
:
12220 case BFD_RELOC_RVA
:
12221 case BFD_RELOC_THUMB_PCREL_BRANCH9
:
12222 case BFD_RELOC_THUMB_PCREL_BRANCH12
:
12223 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
12224 case BFD_RELOC_THUMB_PCREL_BLX
:
12225 case BFD_RELOC_VTABLE_ENTRY
:
12226 case BFD_RELOC_VTABLE_INHERIT
:
12227 code
= fixp
->fx_r_type
;
12230 case BFD_RELOC_ARM_LITERAL
:
12231 case BFD_RELOC_ARM_HWLITERAL
:
12232 /* If this is called then the a literal has
12233 been referenced across a section boundary. */
12234 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12235 _("literal referenced across section boundary"));
12239 case BFD_RELOC_ARM_GOT32
:
12240 case BFD_RELOC_ARM_GOTOFF
:
12241 case BFD_RELOC_ARM_PLT32
:
12242 case BFD_RELOC_ARM_TARGET1
:
12243 case BFD_RELOC_ARM_ROSEGREL32
:
12244 case BFD_RELOC_ARM_SBREL32
:
12245 case BFD_RELOC_ARM_PREL31
:
12246 case BFD_RELOC_ARM_TARGET2
:
12247 code
= fixp
->fx_r_type
;
12251 case BFD_RELOC_ARM_IMMEDIATE
:
12252 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12253 _("internal relocation (type: IMMEDIATE) not fixed up"));
12256 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
12257 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12258 _("ADRL used for a symbol not defined in the same file"));
12261 case BFD_RELOC_ARM_OFFSET_IMM
:
12262 if (fixp
->fx_addsy
!= NULL
12263 && !S_IS_DEFINED (fixp
->fx_addsy
)
12264 && S_IS_LOCAL (fixp
->fx_addsy
))
12266 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12267 _("undefined local label `%s'"),
12268 S_GET_NAME (fixp
->fx_addsy
));
12272 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12273 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
12280 switch (fixp
->fx_r_type
)
12282 case BFD_RELOC_ARM_OFFSET_IMM8
: type
= "OFFSET_IMM8"; break;
12283 case BFD_RELOC_ARM_SHIFT_IMM
: type
= "SHIFT_IMM"; break;
12284 case BFD_RELOC_ARM_SMI
: type
= "SMI"; break;
12285 case BFD_RELOC_ARM_SWI
: type
= "SWI"; break;
12286 case BFD_RELOC_ARM_MULTI
: type
= "MULTI"; break;
12287 case BFD_RELOC_ARM_CP_OFF_IMM
: type
= "CP_OFF_IMM"; break;
12288 case BFD_RELOC_ARM_THUMB_ADD
: type
= "THUMB_ADD"; break;
12289 case BFD_RELOC_ARM_THUMB_SHIFT
: type
= "THUMB_SHIFT"; break;
12290 case BFD_RELOC_ARM_THUMB_IMM
: type
= "THUMB_IMM"; break;
12291 case BFD_RELOC_ARM_THUMB_OFFSET
: type
= "THUMB_OFFSET"; break;
12292 default: type
= _("<unknown>"); break;
12294 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12295 _("cannot represent %s relocation in this object file format"),
12302 if ((code
== BFD_RELOC_32_PCREL
|| code
== BFD_RELOC_32
)
12304 && fixp
->fx_addsy
== GOT_symbol
)
12306 code
= BFD_RELOC_ARM_GOTPC
;
12307 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
12311 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, code
);
12313 if (reloc
->howto
== NULL
)
12315 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12316 _("cannot represent %s relocation in this object file format"),
12317 bfd_get_reloc_code_name (code
));
12321 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12322 vtable entry to be used in the relocation's section offset. */
12323 if (fixp
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
12324 reloc
->address
= fixp
->fx_offset
;
12330 md_estimate_size_before_relax (fragS
* fragP ATTRIBUTE_UNUSED
,
12331 segT segtype ATTRIBUTE_UNUSED
)
12333 as_fatal (_("md_estimate_size_before_relax\n"));
12337 /* We need to be able to fix up arbitrary expressions in some statements.
12338 This is so that we can handle symbols that are an arbitrary distance from
12339 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
12340 which returns part of an address in a form which will be valid for
12341 a data instruction. We do this by pushing the expression into a symbol
12342 in the expr_section, and creating a fix for that. */
12345 fix_new_arm (fragS
* frag
,
12353 arm_fix_data
* arm_data
;
12361 new_fix
= fix_new_exp (frag
, where
, size
, exp
, pc_rel
, reloc
);
12365 new_fix
= fix_new (frag
, where
, size
, make_expr_symbol (exp
), 0,
12370 /* Mark whether the fix is to a THUMB instruction, or an ARM
12372 arm_data
= obstack_alloc (& notes
, sizeof (arm_fix_data
));
12373 new_fix
->tc_fix_data
= (PTR
) arm_data
;
12374 arm_data
->thumb_mode
= thumb_mode
;
12378 output_inst (const char * str
)
12384 as_bad ("%s -- `%s'", inst
.error
, str
);
12388 to
= frag_more (inst
.size
);
12390 if (thumb_mode
&& (inst
.size
> THUMB_SIZE
))
12392 assert (inst
.size
== (2 * THUMB_SIZE
));
12393 md_number_to_chars (to
, inst
.instruction
>> 16, THUMB_SIZE
);
12394 md_number_to_chars (to
+ THUMB_SIZE
, inst
.instruction
, THUMB_SIZE
);
12396 else if (inst
.size
> INSN_SIZE
)
12398 assert (inst
.size
== (2 * INSN_SIZE
));
12399 md_number_to_chars (to
, inst
.instruction
, INSN_SIZE
);
12400 md_number_to_chars (to
+ INSN_SIZE
, inst
.instruction
, INSN_SIZE
);
12403 md_number_to_chars (to
, inst
.instruction
, inst
.size
);
12405 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
12406 fix_new_arm (frag_now
, to
- frag_now
->fr_literal
,
12407 inst
.size
, & inst
.reloc
.exp
, inst
.reloc
.pc_rel
,
12411 dwarf2_emit_insn (inst
.size
);
12416 md_assemble (char * str
)
12422 /* Align the instruction.
12423 This may not be the right thing to do but ... */
12428 /* Align the previous label if needed. */
12429 if (last_label_seen
!= NULL
)
12431 symbol_set_frag (last_label_seen
, frag_now
);
12432 S_SET_VALUE (last_label_seen
, (valueT
) frag_now_fix ());
12433 S_SET_SEGMENT (last_label_seen
, now_seg
);
12436 memset (&inst
, '\0', sizeof (inst
));
12437 inst
.reloc
.type
= BFD_RELOC_NONE
;
12439 skip_whitespace (str
);
12441 /* Scan up to the end of the op-code, which must end in white space or
12443 for (start
= p
= str
; *p
!= '\0'; p
++)
12449 as_bad (_("no operator -- statement `%s'\n"), str
);
12455 const struct thumb_opcode
* opcode
;
12459 opcode
= (const struct thumb_opcode
*) hash_find (arm_tops_hsh
, str
);
12464 /* Check that this instruction is supported for this CPU. */
12465 if (thumb_mode
== 1 && (opcode
->variant
& cpu_variant
) == 0)
12467 as_bad (_("selected processor does not support `%s'"), str
);
12471 mapping_state (MAP_THUMB
);
12472 inst
.instruction
= opcode
->value
;
12473 inst
.size
= opcode
->size
;
12481 const struct asm_opcode
* opcode
;
12485 opcode
= (const struct asm_opcode
*) hash_find (arm_ops_hsh
, str
);
12490 /* Check that this instruction is supported for this CPU. */
12491 if ((opcode
->variant
& cpu_variant
) == 0)
12493 as_bad (_("selected processor does not support `%s'"), str
);
12497 mapping_state (MAP_ARM
);
12498 inst
.instruction
= opcode
->value
;
12499 inst
.size
= INSN_SIZE
;
12506 /* It wasn't an instruction, but it might be a register alias of the form
12508 if (create_register_alias (str
, p
))
12511 as_bad (_("bad instruction `%s'"), start
);
12515 Invocation line includes a switch not recognized by the base assembler.
12516 See if it's a processor-specific option.
12518 This routine is somewhat complicated by the need for backwards
12519 compatibility (since older releases of gcc can't be changed).
12520 The new options try to make the interface as compatible as
12523 New options (supported) are:
12525 -mcpu=<cpu name> Assemble for selected processor
12526 -march=<architecture name> Assemble for selected architecture
12527 -mfpu=<fpu architecture> Assemble for selected FPU.
12528 -EB/-mbig-endian Big-endian
12529 -EL/-mlittle-endian Little-endian
12530 -k Generate PIC code
12531 -mthumb Start in Thumb mode
12532 -mthumb-interwork Code supports ARM/Thumb interworking
12534 For now we will also provide support for:
12536 -mapcs-32 32-bit Program counter
12537 -mapcs-26 26-bit Program counter
12538 -macps-float Floats passed in FP registers
12539 -mapcs-reentrant Reentrant code
12541 (sometime these will probably be replaced with -mapcs=<list of options>
12542 and -matpcs=<list of options>)
12544 The remaining options are only supported for back-wards compatibility.
12545 Cpu variants, the arm part is optional:
12546 -m[arm]1 Currently not supported.
12547 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
12548 -m[arm]3 Arm 3 processor
12549 -m[arm]6[xx], Arm 6 processors
12550 -m[arm]7[xx][t][[d]m] Arm 7 processors
12551 -m[arm]8[10] Arm 8 processors
12552 -m[arm]9[20][tdmi] Arm 9 processors
12553 -mstrongarm[110[0]] StrongARM processors
12554 -mxscale XScale processors
12555 -m[arm]v[2345[t[e]]] Arm architectures
12556 -mall All (except the ARM1)
12558 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
12559 -mfpe-old (No float load/store multiples)
12560 -mvfpxd VFP Single precision
12562 -mno-fpu Disable all floating point instructions
12564 The following CPU names are recognized:
12565 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
12566 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
12567 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
12568 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
12569 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
12570 arm10t arm10e, arm1020t, arm1020e, arm10200e,
12571 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
12575 const char * md_shortopts
= "m:k";
12577 #ifdef ARM_BI_ENDIAN
12578 #define OPTION_EB (OPTION_MD_BASE + 0)
12579 #define OPTION_EL (OPTION_MD_BASE + 1)
12581 #if TARGET_BYTES_BIG_ENDIAN
12582 #define OPTION_EB (OPTION_MD_BASE + 0)
12584 #define OPTION_EL (OPTION_MD_BASE + 1)
12588 struct option md_longopts
[] =
12591 {"EB", no_argument
, NULL
, OPTION_EB
},
12594 {"EL", no_argument
, NULL
, OPTION_EL
},
12596 {NULL
, no_argument
, NULL
, 0}
12599 size_t md_longopts_size
= sizeof (md_longopts
);
12601 struct arm_option_table
12603 char *option
; /* Option name to match. */
12604 char *help
; /* Help information. */
12605 int *var
; /* Variable to change. */
12606 int value
; /* What to change it to. */
12607 char *deprecated
; /* If non-null, print this message. */
12610 struct arm_option_table arm_opts
[] =
12612 {"k", N_("generate PIC code"), &pic_code
, 1, NULL
},
12613 {"mthumb", N_("assemble Thumb code"), &thumb_mode
, 1, NULL
},
12614 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
12615 &support_interwork
, 1, NULL
},
12616 {"moabi", N_("use old ABI (ELF only)"), &target_oabi
, 1, NULL
},
12617 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26
, 0, NULL
},
12618 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26
, 1, NULL
},
12619 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float
,
12621 {"mapcs-reentrant", N_("re-entrant code"), &pic_code
, 1, NULL
},
12622 {"matpcs", N_("code is ATPCS conformant"), &atpcs
, 1, NULL
},
12623 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian
, 1, NULL
},
12624 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian
, 1,
12627 /* These are recognized by the assembler, but have no affect on code. */
12628 {"mapcs-frame", N_("use frame pointer"), NULL
, 0, NULL
},
12629 {"mapcs-stack-check", N_("use stack size checking"), NULL
, 0, NULL
},
12631 /* DON'T add any new processors to this list -- we want the whole list
12632 to go away... Add them to the processors table instead. */
12633 {"marm1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
12634 {"m1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
12635 {"marm2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
12636 {"m2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
12637 {"marm250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
12638 {"m250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
12639 {"marm3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
12640 {"m3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
12641 {"marm6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
12642 {"m6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
12643 {"marm600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
12644 {"m600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
12645 {"marm610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
12646 {"m610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
12647 {"marm620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
12648 {"m620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
12649 {"marm7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
12650 {"m7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
12651 {"marm70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
12652 {"m70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
12653 {"marm700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
12654 {"m700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
12655 {"marm700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
12656 {"m700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
12657 {"marm710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
12658 {"m710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
12659 {"marm710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
12660 {"m710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
12661 {"marm720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
12662 {"m720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
12663 {"marm7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
12664 {"m7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
12665 {"marm7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
12666 {"m7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
12667 {"marm7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
12668 {"m7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
12669 {"marm7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
12670 {"m7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
12671 {"marm7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
12672 {"m7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
12673 {"marm7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
12674 {"m7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
12675 {"marm7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
12676 {"m7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
12677 {"marm7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
12678 {"m7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
12679 {"marm7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12680 {"m7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12681 {"marm7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12682 {"m7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12683 {"marm710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
12684 {"m710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
12685 {"marm720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
12686 {"m720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
12687 {"marm740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
12688 {"m740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
12689 {"marm8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
12690 {"m8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
12691 {"marm810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
12692 {"m810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
12693 {"marm9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
12694 {"m9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
12695 {"marm9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
12696 {"m9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
12697 {"marm920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
12698 {"m920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
12699 {"marm940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
12700 {"m940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
12701 {"mstrongarm", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=strongarm")},
12702 {"mstrongarm110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
12703 N_("use -mcpu=strongarm110")},
12704 {"mstrongarm1100", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
12705 N_("use -mcpu=strongarm1100")},
12706 {"mstrongarm1110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
12707 N_("use -mcpu=strongarm1110")},
12708 {"mxscale", NULL
, &legacy_cpu
, ARM_ARCH_XSCALE
, N_("use -mcpu=xscale")},
12709 {"miwmmxt", NULL
, &legacy_cpu
, ARM_ARCH_IWMMXT
, N_("use -mcpu=iwmmxt")},
12710 {"mall", NULL
, &legacy_cpu
, ARM_ANY
, N_("use -mcpu=all")},
12712 /* Architecture variants -- don't add any more to this list either. */
12713 {"mv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
12714 {"marmv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
12715 {"mv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
12716 {"marmv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
12717 {"mv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
12718 {"marmv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
12719 {"mv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
12720 {"marmv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
12721 {"mv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
12722 {"marmv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
12723 {"mv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
12724 {"marmv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
12725 {"mv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
12726 {"marmv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
12727 {"mv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
12728 {"marmv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
12729 {"mv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
12730 {"marmv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
12732 /* Floating point variants -- don't add any more to this list either. */
12733 {"mfpe-old", NULL
, &legacy_fpu
, FPU_ARCH_FPE
, N_("use -mfpu=fpe")},
12734 {"mfpa10", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa10")},
12735 {"mfpa11", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa11")},
12736 {"mno-fpu", NULL
, &legacy_fpu
, 0,
12737 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
12739 {NULL
, NULL
, NULL
, 0, NULL
}
12742 struct arm_cpu_option_table
12746 /* For some CPUs we assume an FPU unless the user explicitly sets
12751 /* This list should, at a minimum, contain all the cpu names
12752 recognized by GCC. */
12753 static struct arm_cpu_option_table arm_cpus
[] =
12755 {"all", ARM_ANY
, FPU_ARCH_FPA
},
12756 {"arm1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
12757 {"arm2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
12758 {"arm250", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
12759 {"arm3", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
12760 {"arm6", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12761 {"arm60", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12762 {"arm600", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12763 {"arm610", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12764 {"arm620", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12765 {"arm7", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12766 {"arm7m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
12767 {"arm7d", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12768 {"arm7dm", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
12769 {"arm7di", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12770 {"arm7dmi", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
12771 {"arm70", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12772 {"arm700", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12773 {"arm700i", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12774 {"arm710", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12775 {"arm710t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12776 {"arm720", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12777 {"arm720t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12778 {"arm740t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12779 {"arm710c", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12780 {"arm7100", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12781 {"arm7500", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12782 {"arm7500fe", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12783 {"arm7t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12784 {"arm7tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12785 {"arm7tdmi-s", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12786 {"arm8", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12787 {"arm810", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12788 {"strongarm", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12789 {"strongarm1", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12790 {"strongarm110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12791 {"strongarm1100", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12792 {"strongarm1110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12793 {"arm9", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12794 {"arm920", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12795 {"arm920t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12796 {"arm922t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12797 {"arm940t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12798 {"arm9tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12799 /* For V5 or later processors we default to using VFP; but the user
12800 should really set the FPU type explicitly. */
12801 {"arm9e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
12802 {"arm9e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12803 {"arm926ej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
12804 {"arm926ejs", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
12805 {"arm926ej-s", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
12806 {"arm946e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
12807 {"arm946e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12808 {"arm966e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
12809 {"arm966e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12810 {"arm10t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
12811 {"arm10e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12812 {"arm1020", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12813 {"arm1020t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
12814 {"arm1020e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12815 {"arm1026ejs", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12816 {"arm1026ej-s", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12817 {"arm1136js", ARM_ARCH_V6
, FPU_NONE
},
12818 {"arm1136j-s", ARM_ARCH_V6
, FPU_NONE
},
12819 {"arm1136jfs", ARM_ARCH_V6
, FPU_ARCH_VFP_V2
},
12820 {"arm1136jf-s", ARM_ARCH_V6
, FPU_ARCH_VFP_V2
},
12821 {"mpcore", ARM_ARCH_V6K
, FPU_ARCH_VFP_V2
},
12822 {"mpcorenovfp", ARM_ARCH_V6K
, FPU_NONE
},
12823 {"arm1176jz-s", ARM_ARCH_V6ZK
, FPU_NONE
},
12824 {"arm1176jzf-s", ARM_ARCH_V6ZK
, FPU_ARCH_VFP_V2
},
12825 /* ??? XSCALE is really an architecture. */
12826 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
12827 /* ??? iwmmxt is not a processor. */
12828 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP_V2
},
12829 {"i80200", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
12831 {"ep9312", ARM_ARCH_V4T
| ARM_CEXT_MAVERICK
, FPU_ARCH_MAVERICK
},
12835 struct arm_arch_option_table
12842 /* This list should, at a minimum, contain all the architecture names
12843 recognized by GCC. */
12844 static struct arm_arch_option_table arm_archs
[] =
12846 {"all", ARM_ANY
, FPU_ARCH_FPA
},
12847 {"armv1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
12848 {"armv2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
12849 {"armv2a", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
12850 {"armv2s", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
12851 {"armv3", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12852 {"armv3m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
12853 {"armv4", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12854 {"armv4xm", ARM_ARCH_V4xM
, FPU_ARCH_FPA
},
12855 {"armv4t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12856 {"armv4txm", ARM_ARCH_V4TxM
, FPU_ARCH_FPA
},
12857 {"armv5", ARM_ARCH_V5
, FPU_ARCH_VFP
},
12858 {"armv5t", ARM_ARCH_V5T
, FPU_ARCH_VFP
},
12859 {"armv5txm", ARM_ARCH_V5TxM
, FPU_ARCH_VFP
},
12860 {"armv5te", ARM_ARCH_V5TE
, FPU_ARCH_VFP
},
12861 {"armv5texp", ARM_ARCH_V5TExP
, FPU_ARCH_VFP
},
12862 {"armv5tej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP
},
12863 {"armv6", ARM_ARCH_V6
, FPU_ARCH_VFP
},
12864 {"armv6j", ARM_ARCH_V6
, FPU_ARCH_VFP
},
12865 {"armv6k", ARM_ARCH_V6K
, FPU_ARCH_VFP
},
12866 {"armv6z", ARM_ARCH_V6Z
, FPU_ARCH_VFP
},
12867 {"armv6zk", ARM_ARCH_V6ZK
, FPU_ARCH_VFP
},
12868 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP
},
12869 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP
},
12873 /* ISA extensions in the co-processor space. */
12874 struct arm_arch_extension_table
12880 static struct arm_arch_extension_table arm_extensions
[] =
12882 {"maverick", ARM_CEXT_MAVERICK
},
12883 {"xscale", ARM_CEXT_XSCALE
},
12884 {"iwmmxt", ARM_CEXT_IWMMXT
},
12888 struct arm_fpu_option_table
12894 /* This list should, at a minimum, contain all the fpu names
12895 recognized by GCC. */
12896 static struct arm_fpu_option_table arm_fpus
[] =
12898 {"softfpa", FPU_NONE
},
12899 {"fpe", FPU_ARCH_FPE
},
12900 {"fpe2", FPU_ARCH_FPE
},
12901 {"fpe3", FPU_ARCH_FPA
}, /* Third release supports LFM/SFM. */
12902 {"fpa", FPU_ARCH_FPA
},
12903 {"fpa10", FPU_ARCH_FPA
},
12904 {"fpa11", FPU_ARCH_FPA
},
12905 {"arm7500fe", FPU_ARCH_FPA
},
12906 {"softvfp", FPU_ARCH_VFP
},
12907 {"softvfp+vfp", FPU_ARCH_VFP_V2
},
12908 {"vfp", FPU_ARCH_VFP_V2
},
12909 {"vfp9", FPU_ARCH_VFP_V2
},
12910 {"vfp10", FPU_ARCH_VFP_V2
},
12911 {"vfp10-r0", FPU_ARCH_VFP_V1
},
12912 {"vfpxd", FPU_ARCH_VFP_V1xD
},
12913 {"arm1020t", FPU_ARCH_VFP_V1
},
12914 {"arm1020e", FPU_ARCH_VFP_V2
},
12915 {"arm1136jfs", FPU_ARCH_VFP_V2
},
12916 {"arm1136jf-s", FPU_ARCH_VFP_V2
},
12917 {"maverick", FPU_ARCH_MAVERICK
},
12921 struct arm_float_abi_option_table
12927 static struct arm_float_abi_option_table arm_float_abis
[] =
12929 {"hard", ARM_FLOAT_ABI_HARD
},
12930 {"softfp", ARM_FLOAT_ABI_SOFTFP
},
12931 {"soft", ARM_FLOAT_ABI_SOFT
},
12935 struct arm_eabi_option_table
12938 unsigned int value
;
12942 /* We only know hot to output GNU and ver 3 (AAELF) formats. */
12943 static struct arm_eabi_option_table arm_eabis
[] =
12945 {"gnu", EF_ARM_EABI_UNKNOWN
},
12946 {"3", EF_ARM_EABI_VER3
},
12951 struct arm_long_option_table
12953 char * option
; /* Substring to match. */
12954 char * help
; /* Help information. */
12955 int (* func
) (char * subopt
); /* Function to decode sub-option. */
12956 char * deprecated
; /* If non-null, print this message. */
12960 arm_parse_extension (char * str
, int * opt_p
)
12962 while (str
!= NULL
&& *str
!= 0)
12964 struct arm_arch_extension_table
* opt
;
12970 as_bad (_("invalid architectural extension"));
12975 ext
= strchr (str
, '+');
12978 optlen
= ext
- str
;
12980 optlen
= strlen (str
);
12984 as_bad (_("missing architectural extension"));
12988 for (opt
= arm_extensions
; opt
->name
!= NULL
; opt
++)
12989 if (strncmp (opt
->name
, str
, optlen
) == 0)
12991 *opt_p
|= opt
->value
;
12995 if (opt
->name
== NULL
)
12997 as_bad (_("unknown architectural extnsion `%s'"), str
);
13008 arm_parse_cpu (char * str
)
13010 struct arm_cpu_option_table
* opt
;
13011 char * ext
= strchr (str
, '+');
13015 optlen
= ext
- str
;
13017 optlen
= strlen (str
);
13021 as_bad (_("missing cpu name `%s'"), str
);
13025 for (opt
= arm_cpus
; opt
->name
!= NULL
; opt
++)
13026 if (strncmp (opt
->name
, str
, optlen
) == 0)
13028 mcpu_cpu_opt
= opt
->value
;
13029 mcpu_fpu_opt
= opt
->default_fpu
;
13032 return arm_parse_extension (ext
, &mcpu_cpu_opt
);
13037 as_bad (_("unknown cpu `%s'"), str
);
13042 arm_parse_arch (char * str
)
13044 struct arm_arch_option_table
*opt
;
13045 char *ext
= strchr (str
, '+');
13049 optlen
= ext
- str
;
13051 optlen
= strlen (str
);
13055 as_bad (_("missing architecture name `%s'"), str
);
13060 for (opt
= arm_archs
; opt
->name
!= NULL
; opt
++)
13061 if (streq (opt
->name
, str
))
13063 march_cpu_opt
= opt
->value
;
13064 march_fpu_opt
= opt
->default_fpu
;
13067 return arm_parse_extension (ext
, &march_cpu_opt
);
13072 as_bad (_("unknown architecture `%s'\n"), str
);
13077 arm_parse_fpu (char * str
)
13079 struct arm_fpu_option_table
* opt
;
13081 for (opt
= arm_fpus
; opt
->name
!= NULL
; opt
++)
13082 if (streq (opt
->name
, str
))
13084 mfpu_opt
= opt
->value
;
13088 as_bad (_("unknown floating point format `%s'\n"), str
);
13093 arm_parse_float_abi (char * str
)
13095 struct arm_float_abi_option_table
* opt
;
13097 for (opt
= arm_float_abis
; opt
->name
!= NULL
; opt
++)
13098 if (streq (opt
->name
, str
))
13100 mfloat_abi_opt
= opt
->value
;
13104 as_bad (_("unknown floating point abi `%s'\n"), str
);
13110 arm_parse_eabi (char * str
)
13112 struct arm_eabi_option_table
*opt
;
13114 for (opt
= arm_eabis
; opt
->name
!= NULL
; opt
++)
13115 if (streq (opt
->name
, str
))
13117 meabi_flags
= opt
->value
;
13120 as_bad (_("unknown EABI `%s'\n"), str
);
13125 struct arm_long_option_table arm_long_opts
[] =
13127 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13128 arm_parse_cpu
, NULL
},
13129 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13130 arm_parse_arch
, NULL
},
13131 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13132 arm_parse_fpu
, NULL
},
13133 {"mfloat-abi=", N_("<abi>\t assemble for floating point ABI <abi>"),
13134 arm_parse_float_abi
, NULL
},
13136 {"meabi=", N_("<ver>\t assemble for eabi version <ver>"),
13137 arm_parse_eabi
, NULL
},
13139 {NULL
, NULL
, 0, NULL
}
13143 md_parse_option (int c
, char * arg
)
13145 struct arm_option_table
*opt
;
13146 struct arm_long_option_table
*lopt
;
13152 target_big_endian
= 1;
13158 target_big_endian
= 0;
13163 /* Listing option. Just ignore these, we don't support additional
13168 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
13170 if (c
== opt
->option
[0]
13171 && ((arg
== NULL
&& opt
->option
[1] == 0)
13172 || streq (arg
, opt
->option
+ 1)))
13174 #if WARN_DEPRECATED
13175 /* If the option is deprecated, tell the user. */
13176 if (opt
->deprecated
!= NULL
)
13177 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
,
13178 arg
? arg
: "", _(opt
->deprecated
));
13181 if (opt
->var
!= NULL
)
13182 *opt
->var
= opt
->value
;
13188 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
13190 /* These options are expected to have an argument. */
13191 if (c
== lopt
->option
[0]
13193 && strncmp (arg
, lopt
->option
+ 1,
13194 strlen (lopt
->option
+ 1)) == 0)
13196 #if WARN_DEPRECATED
13197 /* If the option is deprecated, tell the user. */
13198 if (lopt
->deprecated
!= NULL
)
13199 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
, arg
,
13200 _(lopt
->deprecated
));
13203 /* Call the sup-option parser. */
13204 return lopt
->func (arg
+ strlen (lopt
->option
) - 1);
13215 md_show_usage (FILE * fp
)
13217 struct arm_option_table
*opt
;
13218 struct arm_long_option_table
*lopt
;
13220 fprintf (fp
, _(" ARM-specific assembler options:\n"));
13222 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
13223 if (opt
->help
!= NULL
)
13224 fprintf (fp
, " -%-23s%s\n", opt
->option
, _(opt
->help
));
13226 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
13227 if (lopt
->help
!= NULL
)
13228 fprintf (fp
, " -%s%s\n", lopt
->option
, _(lopt
->help
));
13232 -EB assemble code for a big-endian cpu\n"));
13237 -EL assemble code for a little-endian cpu\n"));
13241 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13244 cons_fix_new_arm (fragS
* frag
,
13249 bfd_reloc_code_real_type type
;
13253 FIXME: @@ Should look at CPU word size. */
13257 type
= BFD_RELOC_8
;
13260 type
= BFD_RELOC_16
;
13264 type
= BFD_RELOC_32
;
13267 type
= BFD_RELOC_64
;
13271 fix_new_exp (frag
, where
, (int) size
, exp
, pcrel
, type
);
13274 /* A good place to do this, although this was probably not intended
13275 for this kind of use. We need to dump the literal pool before
13276 references are made to a null symbol pointer. */
13281 literal_pool
* pool
;
13283 for (pool
= list_of_pools
; pool
; pool
= pool
->next
)
13285 /* Put it at the end of the relevent section. */
13286 subseg_set (pool
->section
, pool
->sub_section
);
13288 arm_elf_change_section ();
13295 arm_start_line_hook (void)
13297 last_label_seen
= NULL
;
13301 arm_frob_label (symbolS
* sym
)
13303 last_label_seen
= sym
;
13305 ARM_SET_THUMB (sym
, thumb_mode
);
13307 #if defined OBJ_COFF || defined OBJ_ELF
13308 ARM_SET_INTERWORK (sym
, support_interwork
);
13311 /* Note - do not allow local symbols (.Lxxx) to be labeled
13312 as Thumb functions. This is because these labels, whilst
13313 they exist inside Thumb code, are not the entry points for
13314 possible ARM->Thumb calls. Also, these labels can be used
13315 as part of a computed goto or switch statement. eg gcc
13316 can generate code that looks like this:
13318 ldr r2, [pc, .Laaa]
13328 The first instruction loads the address of the jump table.
13329 The second instruction converts a table index into a byte offset.
13330 The third instruction gets the jump address out of the table.
13331 The fourth instruction performs the jump.
13333 If the address stored at .Laaa is that of a symbol which has the
13334 Thumb_Func bit set, then the linker will arrange for this address
13335 to have the bottom bit set, which in turn would mean that the
13336 address computation performed by the third instruction would end
13337 up with the bottom bit set. Since the ARM is capable of unaligned
13338 word loads, the instruction would then load the incorrect address
13339 out of the jump table, and chaos would ensue. */
13340 if (label_is_thumb_function_name
13341 && (S_GET_NAME (sym
)[0] != '.' || S_GET_NAME (sym
)[1] != 'L')
13342 && (bfd_get_section_flags (stdoutput
, now_seg
) & SEC_CODE
) != 0)
13344 /* When the address of a Thumb function is taken the bottom
13345 bit of that address should be set. This will allow
13346 interworking between Arm and Thumb functions to work
13349 THUMB_SET_FUNC (sym
, 1);
13351 label_is_thumb_function_name
= FALSE
;
13355 /* Adjust the symbol table. This marks Thumb symbols as distinct from
13359 arm_adjust_symtab (void)
13364 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
13366 if (ARM_IS_THUMB (sym
))
13368 if (THUMB_IS_FUNC (sym
))
13370 /* Mark the symbol as a Thumb function. */
13371 if ( S_GET_STORAGE_CLASS (sym
) == C_STAT
13372 || S_GET_STORAGE_CLASS (sym
) == C_LABEL
) /* This can happen! */
13373 S_SET_STORAGE_CLASS (sym
, C_THUMBSTATFUNC
);
13375 else if (S_GET_STORAGE_CLASS (sym
) == C_EXT
)
13376 S_SET_STORAGE_CLASS (sym
, C_THUMBEXTFUNC
);
13378 as_bad (_("%s: unexpected function type: %d"),
13379 S_GET_NAME (sym
), S_GET_STORAGE_CLASS (sym
));
13381 else switch (S_GET_STORAGE_CLASS (sym
))
13384 S_SET_STORAGE_CLASS (sym
, C_THUMBEXT
);
13387 S_SET_STORAGE_CLASS (sym
, C_THUMBSTAT
);
13390 S_SET_STORAGE_CLASS (sym
, C_THUMBLABEL
);
13398 if (ARM_IS_INTERWORK (sym
))
13399 coffsymbol (symbol_get_bfdsym (sym
))->native
->u
.syment
.n_flags
= 0xFF;
13406 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
13408 if (ARM_IS_THUMB (sym
))
13410 elf_symbol_type
* elf_sym
;
13412 elf_sym
= elf_symbol (symbol_get_bfdsym (sym
));
13413 bind
= ELF_ST_BIND (elf_sym
);
13415 /* If it's a .thumb_func, declare it as so,
13416 otherwise tag label as .code 16. */
13417 if (THUMB_IS_FUNC (sym
))
13418 elf_sym
->internal_elf_sym
.st_info
=
13419 ELF_ST_INFO (bind
, STT_ARM_TFUNC
);
13421 elf_sym
->internal_elf_sym
.st_info
=
13422 ELF_ST_INFO (bind
, STT_ARM_16BIT
);
13429 arm_data_in_code (void)
13431 if (thumb_mode
&& ! strncmp (input_line_pointer
+ 1, "data:", 5))
13433 *input_line_pointer
= '/';
13434 input_line_pointer
+= 5;
13435 *input_line_pointer
= 0;
13443 arm_canonicalize_symbol_name (char * name
)
13447 if (thumb_mode
&& (len
= strlen (name
)) > 5
13448 && streq (name
+ len
- 5, "/data"))
13449 *(name
+ len
- 5) = 0;
13454 #if defined OBJ_COFF || defined OBJ_ELF
13456 arm_validate_fix (fixS
* fixP
)
13458 /* If the destination of the branch is a defined symbol which does not have
13459 the THUMB_FUNC attribute, then we must be calling a function which has
13460 the (interfacearm) attribute. We look for the Thumb entry point to that
13461 function and change the branch to refer to that function instead. */
13462 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
13463 && fixP
->fx_addsy
!= NULL
13464 && S_IS_DEFINED (fixP
->fx_addsy
)
13465 && ! THUMB_IS_FUNC (fixP
->fx_addsy
))
13467 fixP
->fx_addsy
= find_real_start (fixP
->fx_addsy
);
13473 arm_force_relocation (struct fix
* fixp
)
13475 #if defined (OBJ_COFF) && defined (TE_PE)
13476 if (fixp
->fx_r_type
== BFD_RELOC_RVA
)
13480 if (fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
13481 || fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
13482 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
13483 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
)
13487 /* Resolve these relocations even if the symbol is extern or weak. */
13488 if (fixp
->fx_r_type
== BFD_RELOC_ARM_IMMEDIATE
13489 || fixp
->fx_r_type
== BFD_RELOC_ARM_OFFSET_IMM
13490 || fixp
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
13493 return generic_force_reloc (fixp
);
13497 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
13498 local labels from being added to the output symbol table when they
13499 are used with the ADRL pseudo op. The ADRL relocation should always
13500 be resolved before the binbary is emitted, so it is safe to say that
13501 it is adjustable. */
13504 arm_fix_adjustable (fixS
* fixP
)
13506 if (fixP
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
13513 /* Relocations against Thumb function names must be left unadjusted,
13514 so that the linker can use this information to correctly set the
13515 bottom bit of their addresses. The MIPS version of this function
13516 also prevents relocations that are mips-16 specific, but I do not
13517 know why it does this.
13520 There is one other problem that ought to be addressed here, but
13521 which currently is not: Taking the address of a label (rather
13522 than a function) and then later jumping to that address. Such
13523 addresses also ought to have their bottom bit set (assuming that
13524 they reside in Thumb code), but at the moment they will not. */
13527 arm_fix_adjustable (fixS
* fixP
)
13529 if (fixP
->fx_addsy
== NULL
)
13532 if (THUMB_IS_FUNC (fixP
->fx_addsy
)
13533 && fixP
->fx_subsy
== NULL
)
13536 /* We need the symbol name for the VTABLE entries. */
13537 if ( fixP
->fx_r_type
== BFD_RELOC_VTABLE_INHERIT
13538 || fixP
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
13541 /* Don't allow symbols to be discarded on GOT related relocs. */
13542 if (fixP
->fx_r_type
== BFD_RELOC_ARM_PLT32
13543 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOT32
13544 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOTOFF
13545 || fixP
->fx_r_type
== BFD_RELOC_ARM_TARGET2
)
13552 elf32_arm_target_format (void)
13555 return (target_big_endian
13556 ? "elf32-bigarm-symbian"
13557 : "elf32-littlearm-symbian");
13559 if (target_big_endian
)
13562 return "elf32-bigarm-oabi";
13564 return "elf32-bigarm";
13569 return "elf32-littlearm-oabi";
13571 return "elf32-littlearm";
13577 armelf_frob_symbol (symbolS
* symp
,
13580 elf_frob_symbol (symp
, puntp
);
13584 s_arm_elf_cons (int nbytes
)
13588 #ifdef md_flush_pending_output
13589 md_flush_pending_output ();
13592 if (is_it_end_of_statement ())
13594 demand_empty_rest_of_line ();
13598 #ifdef md_cons_align
13599 md_cons_align (nbytes
);
13602 mapping_state (MAP_DATA
);
13605 bfd_reloc_code_real_type reloc
;
13607 expression (& exp
);
13609 if (exp
.X_op
== O_symbol
13610 && * input_line_pointer
== '('
13611 && (reloc
= arm_parse_reloc ()) != BFD_RELOC_UNUSED
)
13613 reloc_howto_type
*howto
= bfd_reloc_type_lookup (stdoutput
, reloc
);
13614 int size
= bfd_get_reloc_size (howto
);
13617 as_bad ("%s relocations do not fit in %d bytes",
13618 howto
->name
, nbytes
);
13621 char *p
= frag_more ((int) nbytes
);
13622 int offset
= nbytes
- size
;
13624 fix_new_exp (frag_now
, p
- frag_now
->fr_literal
+ offset
, size
,
13629 emit_expr (&exp
, (unsigned int) nbytes
);
13631 while (*input_line_pointer
++ == ',');
13633 /* Put terminator back into stream. */
13634 input_line_pointer
--;
13635 demand_empty_rest_of_line ();
13639 /* Parse a .rel31 directive. */
13642 s_arm_rel31 (int ignored ATTRIBUTE_UNUSED
)
13648 SKIP_WHITESPACE ();
13651 if (*input_line_pointer
== '1')
13652 highbit
= 0x80000000;
13653 else if (*input_line_pointer
!= '0')
13654 as_bad (_("expected 0 or 1"));
13656 input_line_pointer
++;
13657 SKIP_WHITESPACE ();
13658 if (*input_line_pointer
!= ',')
13659 as_bad (_("missing comma"));
13660 input_line_pointer
++;
13662 #ifdef md_flush_pending_output
13663 md_flush_pending_output ();
13666 #ifdef md_cons_align
13670 mapping_state (MAP_DATA
);
13675 md_number_to_chars (p
, highbit
, 4);
13676 fix_new_arm (frag_now
, p
- frag_now
->fr_literal
, 4, &exp
, 1,
13677 BFD_RELOC_ARM_PREL31
);
13679 demand_empty_rest_of_line ();
13682 #endif /* OBJ_ELF */
13684 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
13685 of an rs_align_code fragment. */
13688 arm_handle_align (fragS
* fragP
)
13690 static char const arm_noop
[4] = { 0x00, 0x00, 0xa0, 0xe1 };
13691 static char const thumb_noop
[2] = { 0xc0, 0x46 };
13692 static char const arm_bigend_noop
[4] = { 0xe1, 0xa0, 0x00, 0x00 };
13693 static char const thumb_bigend_noop
[2] = { 0x46, 0xc0 };
13695 int bytes
, fix
, noop_size
;
13699 if (fragP
->fr_type
!= rs_align_code
)
13702 bytes
= fragP
->fr_next
->fr_address
- fragP
->fr_address
- fragP
->fr_fix
;
13703 p
= fragP
->fr_literal
+ fragP
->fr_fix
;
13706 if (bytes
> MAX_MEM_FOR_RS_ALIGN_CODE
)
13707 bytes
&= MAX_MEM_FOR_RS_ALIGN_CODE
;
13709 if (fragP
->tc_frag_data
)
13711 if (target_big_endian
)
13712 noop
= thumb_bigend_noop
;
13715 noop_size
= sizeof (thumb_noop
);
13719 if (target_big_endian
)
13720 noop
= arm_bigend_noop
;
13723 noop_size
= sizeof (arm_noop
);
13726 if (bytes
& (noop_size
- 1))
13728 fix
= bytes
& (noop_size
- 1);
13729 memset (p
, 0, fix
);
13734 while (bytes
>= noop_size
)
13736 memcpy (p
, noop
, noop_size
);
13738 bytes
-= noop_size
;
13742 fragP
->fr_fix
+= fix
;
13743 fragP
->fr_var
= noop_size
;
13746 /* Called from md_do_align. Used to create an alignment
13747 frag in a code section. */
13750 arm_frag_align_code (int n
, int max
)
13754 /* We assume that there will never be a requirement
13755 to support alignments greater than 32 bytes. */
13756 if (max
> MAX_MEM_FOR_RS_ALIGN_CODE
)
13757 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
13759 p
= frag_var (rs_align_code
,
13760 MAX_MEM_FOR_RS_ALIGN_CODE
,
13762 (relax_substateT
) max
,
13769 /* Perform target specific initialisation of a frag. */
13772 arm_init_frag (fragS
* fragP
)
13774 /* Record whether this frag is in an ARM or a THUMB area. */
13775 fragP
->tc_frag_data
= thumb_mode
;
13778 /* This table describes all the machine specific pseudo-ops the assembler
13779 has to support. The fields are:
13780 pseudo-op name without dot
13781 function to call to execute this pseudo-op
13782 Integer arg to pass to the function. */
13784 const pseudo_typeS md_pseudo_table
[] =
13786 /* Never called because '.req' does not start a line. */
13787 { "req", s_req
, 0 },
13788 { "unreq", s_unreq
, 0 },
13789 { "bss", s_bss
, 0 },
13790 { "align", s_align
, 0 },
13791 { "arm", s_arm
, 0 },
13792 { "thumb", s_thumb
, 0 },
13793 { "code", s_code
, 0 },
13794 { "force_thumb", s_force_thumb
, 0 },
13795 { "thumb_func", s_thumb_func
, 0 },
13796 { "thumb_set", s_thumb_set
, 0 },
13797 { "even", s_even
, 0 },
13798 { "ltorg", s_ltorg
, 0 },
13799 { "pool", s_ltorg
, 0 },
13801 { "word", s_arm_elf_cons
, 4 },
13802 { "long", s_arm_elf_cons
, 4 },
13803 { "rel31", s_arm_rel31
, 0 },
13805 { "word", cons
, 4},
13807 { "extend", float_cons
, 'x' },
13808 { "ldouble", float_cons
, 'x' },
13809 { "packed", float_cons
, 'p' },