1 /* tc-arm.c -- Assemble for the ARM
2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
4 Free Software Foundation, Inc.
5 Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
6 Modified by David Taylor (dtaylor@armltd.co.uk)
7 Cirrus coprocessor mods by Aldy Hernandez (aldyh@redhat.com)
8 Cirrus coprocessor fixes by Petko Manolov (petkan@nucleusys.com)
9 Cirrus coprocessor fixes by Vladimir Ivanov (vladitx@nucleusys.com)
11 This file is part of GAS, the GNU Assembler.
13 GAS is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 2, or (at your option)
18 GAS is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with GAS; see the file COPYING. If not, write to the Free
25 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
31 #include "safe-ctype.h"
33 /* Need TARGET_CPU. */
40 #include "opcode/arm.h"
44 #include "dwarf2dbg.h"
45 #include "dw2gencfi.h"
48 /* XXX Set this to 1 after the next binutils release. */
49 #define WARN_DEPRECATED 0
52 /* Must be at least the size of the largest unwind opcode (currently two). */
53 #define ARM_OPCODE_CHUNK_SIZE 8
55 /* This structure holds the unwinding state. */
60 symbolS
* table_entry
;
61 symbolS
* personality_routine
;
62 int personality_index
;
63 /* The segment containing the function. */
66 /* Opcodes generated from this function. */
67 unsigned char * opcodes
;
70 /* The number of bytes pushed to the stack. */
72 /* We don't add stack adjustment opcodes immediately so that we can merge
73 multiple adjustments. We can also omit the final adjustment
74 when using a frame pointer. */
75 offsetT pending_offset
;
76 /* These two fields are set by both unwind_movsp and unwind_setfp. They
77 hold the reg+offset to use when restoring sp from a frame pointer. */
80 /* Nonzero if an unwind_setfp directive has been seen. */
82 /* Nonzero if the last opcode restores sp from fp_reg. */
83 unsigned sp_restored
:1;
95 /* Types of processor to assemble for. */
96 #define ARM_1 ARM_ARCH_V1
97 #define ARM_2 ARM_ARCH_V2
98 #define ARM_3 ARM_ARCH_V2S
99 #define ARM_250 ARM_ARCH_V2S
100 #define ARM_6 ARM_ARCH_V3
101 #define ARM_7 ARM_ARCH_V3
102 #define ARM_8 ARM_ARCH_V4
103 #define ARM_9 ARM_ARCH_V4T
104 #define ARM_STRONG ARM_ARCH_V4
105 #define ARM_CPU_MASK 0x0000000f /* XXX? */
108 #if defined __XSCALE__
109 #define CPU_DEFAULT (ARM_ARCH_XSCALE)
111 #if defined __thumb__
112 #define CPU_DEFAULT (ARM_ARCH_V5T)
114 #define CPU_DEFAULT ARM_ANY
121 # define FPU_DEFAULT FPU_ARCH_FPA
122 # elif defined (TE_NetBSD)
124 # define FPU_DEFAULT FPU_ARCH_VFP /* Soft-float, but VFP order. */
126 /* Legacy a.out format. */
127 # define FPU_DEFAULT FPU_ARCH_FPA /* Soft-float, but FPA order. */
129 # elif defined (TE_VXWORKS)
130 # define FPU_DEFAULT FPU_ARCH_VFP /* Soft-float, VFP order. */
132 /* For backwards compatibility, default to FPA. */
133 # define FPU_DEFAULT FPU_ARCH_FPA
135 #endif /* ifndef FPU_DEFAULT */
137 #define streq(a, b) (strcmp (a, b) == 0)
138 #define skip_whitespace(str) while (*(str) == ' ') ++(str)
140 static unsigned long cpu_variant
;
142 /* Flags stored in private area of BFD structure. */
143 static int uses_apcs_26
= FALSE
;
144 static int atpcs
= FALSE
;
145 static int support_interwork
= FALSE
;
146 static int uses_apcs_float
= FALSE
;
147 static int pic_code
= FALSE
;
149 /* Variables that we set while parsing command-line options. Once all
150 options have been read we re-process these values to set the real
152 static int legacy_cpu
= -1;
153 static int legacy_fpu
= -1;
155 static int mcpu_cpu_opt
= -1;
156 static int mcpu_fpu_opt
= -1;
157 static int march_cpu_opt
= -1;
158 static int march_fpu_opt
= -1;
159 static int mfpu_opt
= -1;
160 static int mfloat_abi_opt
= -1;
162 static int meabi_flags
= EF_ARM_EABI_UNKNOWN
;
165 /* This array holds the chars that always start a comment. If the
166 pre-processor is disabled, these aren't very useful. */
167 const char comment_chars
[] = "@";
169 /* This array holds the chars that only start a comment at the beginning of
170 a line. If the line seems to have the form '# 123 filename'
171 .line and .file directives will appear in the pre-processed output. */
172 /* Note that input_file.c hand checks for '#' at the beginning of the
173 first line of the input file. This is because the compiler outputs
174 #NO_APP at the beginning of its output. */
175 /* Also note that comments like this one will always work. */
176 const char line_comment_chars
[] = "#";
178 const char line_separator_chars
[] = ";";
180 /* Chars that can be used to separate mant
181 from exp in floating point numbers. */
182 const char EXP_CHARS
[] = "eE";
184 /* Chars that mean this number is a floating point constant. */
188 const char FLT_CHARS
[] = "rRsSfFdDxXeEpP";
190 /* Prefix characters that indicate the start of an immediate
192 #define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
195 /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
196 symbolS
* GOT_symbol
;
199 /* Size of relocation record. */
200 const int md_reloc_size
= 8;
202 /* 0: assemble for ARM,
203 1: assemble for Thumb,
204 2: assemble for Thumb even though target CPU does not support thumb
206 static int thumb_mode
= 0;
208 typedef struct arm_fix
216 unsigned long instruction
;
220 bfd_reloc_code_real_type type
;
237 struct asm_shift_properties
239 enum asm_shift_index index
;
240 unsigned long bit_field
;
241 unsigned int allows_0
: 1;
242 unsigned int allows_32
: 1;
245 static const struct asm_shift_properties shift_properties
[] =
247 { SHIFT_LSL
, 0, 1, 0},
248 { SHIFT_LSR
, 0x20, 0, 1},
249 { SHIFT_ASR
, 0x40, 0, 1},
250 { SHIFT_ROR
, 0x60, 0, 0},
251 { SHIFT_RRX
, 0x60, 0, 0}
254 struct asm_shift_name
257 const struct asm_shift_properties
* properties
;
260 static const struct asm_shift_name shift_names
[] =
262 { "asl", shift_properties
+ SHIFT_LSL
},
263 { "lsl", shift_properties
+ SHIFT_LSL
},
264 { "lsr", shift_properties
+ SHIFT_LSR
},
265 { "asr", shift_properties
+ SHIFT_ASR
},
266 { "ror", shift_properties
+ SHIFT_ROR
},
267 { "rrx", shift_properties
+ SHIFT_RRX
},
268 { "ASL", shift_properties
+ SHIFT_LSL
},
269 { "LSL", shift_properties
+ SHIFT_LSL
},
270 { "LSR", shift_properties
+ SHIFT_LSR
},
271 { "ASR", shift_properties
+ SHIFT_ASR
},
272 { "ROR", shift_properties
+ SHIFT_ROR
},
273 { "RRX", shift_properties
+ SHIFT_RRX
}
276 /* Any kind of shift is accepted. */
277 #define NO_SHIFT_RESTRICT 1
278 /* The shift operand must be an immediate value, not a register. */
279 #define SHIFT_IMMEDIATE 0
280 /* The shift must be LSL or ASR and the operand must be an immediate. */
281 #define SHIFT_LSL_OR_ASR_IMMEDIATE 2
282 /* The shift must be ASR and the operand must be an immediate. */
283 #define SHIFT_ASR_IMMEDIATE 3
284 /* The shift must be LSL and the operand must be an immediate. */
285 #define SHIFT_LSL_IMMEDIATE 4
287 #define NUM_FLOAT_VALS 8
289 const char * fp_const
[] =
291 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
294 /* Number of littlenums required to hold an extended precision number. */
295 #define MAX_LITTLENUMS 6
297 LITTLENUM_TYPE fp_values
[NUM_FLOAT_VALS
][MAX_LITTLENUMS
];
302 /* Whether a Co-processor load/store operation accepts write-back forms. */
311 #define CP_T_X 0x00008000
312 #define CP_T_Y 0x00400000
313 #define CP_T_Pre 0x01000000
314 #define CP_T_UD 0x00800000
315 #define CP_T_WB 0x00200000
317 #define CONDS_BIT 0x00100000
318 #define LOAD_BIT 0x00100000
320 #define DOUBLE_LOAD_FLAG 0x00000001
324 const char * template;
328 #define COND_ALWAYS 0xe0000000
329 #define COND_MASK 0xf0000000
331 static const struct asm_cond conds
[] =
335 {"cs", 0x20000000}, {"hs", 0x20000000},
336 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
353 const char *template;
358 /* The bit that distinguishes CPSR and SPSR. */
359 #define SPSR_BIT (1 << 22)
361 /* How many bits to shift the PSR_xxx bits up by. */
364 #define PSR_c (1 << 0)
365 #define PSR_x (1 << 1)
366 #define PSR_s (1 << 2)
367 #define PSR_f (1 << 3)
369 static const struct asm_psr psrs
[] =
371 {"CPSR", TRUE
, PSR_c
| PSR_f
},
372 {"CPSR_all", TRUE
, PSR_c
| PSR_f
},
373 {"SPSR", FALSE
, PSR_c
| PSR_f
},
374 {"SPSR_all", FALSE
, PSR_c
| PSR_f
},
375 {"CPSR_flg", TRUE
, PSR_f
},
376 {"CPSR_f", TRUE
, PSR_f
},
377 {"SPSR_flg", FALSE
, PSR_f
},
378 {"SPSR_f", FALSE
, PSR_f
},
379 {"CPSR_c", TRUE
, PSR_c
},
380 {"CPSR_ctl", TRUE
, PSR_c
},
381 {"SPSR_c", FALSE
, PSR_c
},
382 {"SPSR_ctl", FALSE
, PSR_c
},
383 {"CPSR_x", TRUE
, PSR_x
},
384 {"CPSR_s", TRUE
, PSR_s
},
385 {"SPSR_x", FALSE
, PSR_x
},
386 {"SPSR_s", FALSE
, PSR_s
},
387 /* Combinations of flags. */
388 {"CPSR_fs", TRUE
, PSR_f
| PSR_s
},
389 {"CPSR_fx", TRUE
, PSR_f
| PSR_x
},
390 {"CPSR_fc", TRUE
, PSR_f
| PSR_c
},
391 {"CPSR_sf", TRUE
, PSR_s
| PSR_f
},
392 {"CPSR_sx", TRUE
, PSR_s
| PSR_x
},
393 {"CPSR_sc", TRUE
, PSR_s
| PSR_c
},
394 {"CPSR_xf", TRUE
, PSR_x
| PSR_f
},
395 {"CPSR_xs", TRUE
, PSR_x
| PSR_s
},
396 {"CPSR_xc", TRUE
, PSR_x
| PSR_c
},
397 {"CPSR_cf", TRUE
, PSR_c
| PSR_f
},
398 {"CPSR_cs", TRUE
, PSR_c
| PSR_s
},
399 {"CPSR_cx", TRUE
, PSR_c
| PSR_x
},
400 {"CPSR_fsx", TRUE
, PSR_f
| PSR_s
| PSR_x
},
401 {"CPSR_fsc", TRUE
, PSR_f
| PSR_s
| PSR_c
},
402 {"CPSR_fxs", TRUE
, PSR_f
| PSR_x
| PSR_s
},
403 {"CPSR_fxc", TRUE
, PSR_f
| PSR_x
| PSR_c
},
404 {"CPSR_fcs", TRUE
, PSR_f
| PSR_c
| PSR_s
},
405 {"CPSR_fcx", TRUE
, PSR_f
| PSR_c
| PSR_x
},
406 {"CPSR_sfx", TRUE
, PSR_s
| PSR_f
| PSR_x
},
407 {"CPSR_sfc", TRUE
, PSR_s
| PSR_f
| PSR_c
},
408 {"CPSR_sxf", TRUE
, PSR_s
| PSR_x
| PSR_f
},
409 {"CPSR_sxc", TRUE
, PSR_s
| PSR_x
| PSR_c
},
410 {"CPSR_scf", TRUE
, PSR_s
| PSR_c
| PSR_f
},
411 {"CPSR_scx", TRUE
, PSR_s
| PSR_c
| PSR_x
},
412 {"CPSR_xfs", TRUE
, PSR_x
| PSR_f
| PSR_s
},
413 {"CPSR_xfc", TRUE
, PSR_x
| PSR_f
| PSR_c
},
414 {"CPSR_xsf", TRUE
, PSR_x
| PSR_s
| PSR_f
},
415 {"CPSR_xsc", TRUE
, PSR_x
| PSR_s
| PSR_c
},
416 {"CPSR_xcf", TRUE
, PSR_x
| PSR_c
| PSR_f
},
417 {"CPSR_xcs", TRUE
, PSR_x
| PSR_c
| PSR_s
},
418 {"CPSR_cfs", TRUE
, PSR_c
| PSR_f
| PSR_s
},
419 {"CPSR_cfx", TRUE
, PSR_c
| PSR_f
| PSR_x
},
420 {"CPSR_csf", TRUE
, PSR_c
| PSR_s
| PSR_f
},
421 {"CPSR_csx", TRUE
, PSR_c
| PSR_s
| PSR_x
},
422 {"CPSR_cxf", TRUE
, PSR_c
| PSR_x
| PSR_f
},
423 {"CPSR_cxs", TRUE
, PSR_c
| PSR_x
| PSR_s
},
424 {"CPSR_fsxc", TRUE
, PSR_f
| PSR_s
| PSR_x
| PSR_c
},
425 {"CPSR_fscx", TRUE
, PSR_f
| PSR_s
| PSR_c
| PSR_x
},
426 {"CPSR_fxsc", TRUE
, PSR_f
| PSR_x
| PSR_s
| PSR_c
},
427 {"CPSR_fxcs", TRUE
, PSR_f
| PSR_x
| PSR_c
| PSR_s
},
428 {"CPSR_fcsx", TRUE
, PSR_f
| PSR_c
| PSR_s
| PSR_x
},
429 {"CPSR_fcxs", TRUE
, PSR_f
| PSR_c
| PSR_x
| PSR_s
},
430 {"CPSR_sfxc", TRUE
, PSR_s
| PSR_f
| PSR_x
| PSR_c
},
431 {"CPSR_sfcx", TRUE
, PSR_s
| PSR_f
| PSR_c
| PSR_x
},
432 {"CPSR_sxfc", TRUE
, PSR_s
| PSR_x
| PSR_f
| PSR_c
},
433 {"CPSR_sxcf", TRUE
, PSR_s
| PSR_x
| PSR_c
| PSR_f
},
434 {"CPSR_scfx", TRUE
, PSR_s
| PSR_c
| PSR_f
| PSR_x
},
435 {"CPSR_scxf", TRUE
, PSR_s
| PSR_c
| PSR_x
| PSR_f
},
436 {"CPSR_xfsc", TRUE
, PSR_x
| PSR_f
| PSR_s
| PSR_c
},
437 {"CPSR_xfcs", TRUE
, PSR_x
| PSR_f
| PSR_c
| PSR_s
},
438 {"CPSR_xsfc", TRUE
, PSR_x
| PSR_s
| PSR_f
| PSR_c
},
439 {"CPSR_xscf", TRUE
, PSR_x
| PSR_s
| PSR_c
| PSR_f
},
440 {"CPSR_xcfs", TRUE
, PSR_x
| PSR_c
| PSR_f
| PSR_s
},
441 {"CPSR_xcsf", TRUE
, PSR_x
| PSR_c
| PSR_s
| PSR_f
},
442 {"CPSR_cfsx", TRUE
, PSR_c
| PSR_f
| PSR_s
| PSR_x
},
443 {"CPSR_cfxs", TRUE
, PSR_c
| PSR_f
| PSR_x
| PSR_s
},
444 {"CPSR_csfx", TRUE
, PSR_c
| PSR_s
| PSR_f
| PSR_x
},
445 {"CPSR_csxf", TRUE
, PSR_c
| PSR_s
| PSR_x
| PSR_f
},
446 {"CPSR_cxfs", TRUE
, PSR_c
| PSR_x
| PSR_f
| PSR_s
},
447 {"CPSR_cxsf", TRUE
, PSR_c
| PSR_x
| PSR_s
| PSR_f
},
448 {"SPSR_fs", FALSE
, PSR_f
| PSR_s
},
449 {"SPSR_fx", FALSE
, PSR_f
| PSR_x
},
450 {"SPSR_fc", FALSE
, PSR_f
| PSR_c
},
451 {"SPSR_sf", FALSE
, PSR_s
| PSR_f
},
452 {"SPSR_sx", FALSE
, PSR_s
| PSR_x
},
453 {"SPSR_sc", FALSE
, PSR_s
| PSR_c
},
454 {"SPSR_xf", FALSE
, PSR_x
| PSR_f
},
455 {"SPSR_xs", FALSE
, PSR_x
| PSR_s
},
456 {"SPSR_xc", FALSE
, PSR_x
| PSR_c
},
457 {"SPSR_cf", FALSE
, PSR_c
| PSR_f
},
458 {"SPSR_cs", FALSE
, PSR_c
| PSR_s
},
459 {"SPSR_cx", FALSE
, PSR_c
| PSR_x
},
460 {"SPSR_fsx", FALSE
, PSR_f
| PSR_s
| PSR_x
},
461 {"SPSR_fsc", FALSE
, PSR_f
| PSR_s
| PSR_c
},
462 {"SPSR_fxs", FALSE
, PSR_f
| PSR_x
| PSR_s
},
463 {"SPSR_fxc", FALSE
, PSR_f
| PSR_x
| PSR_c
},
464 {"SPSR_fcs", FALSE
, PSR_f
| PSR_c
| PSR_s
},
465 {"SPSR_fcx", FALSE
, PSR_f
| PSR_c
| PSR_x
},
466 {"SPSR_sfx", FALSE
, PSR_s
| PSR_f
| PSR_x
},
467 {"SPSR_sfc", FALSE
, PSR_s
| PSR_f
| PSR_c
},
468 {"SPSR_sxf", FALSE
, PSR_s
| PSR_x
| PSR_f
},
469 {"SPSR_sxc", FALSE
, PSR_s
| PSR_x
| PSR_c
},
470 {"SPSR_scf", FALSE
, PSR_s
| PSR_c
| PSR_f
},
471 {"SPSR_scx", FALSE
, PSR_s
| PSR_c
| PSR_x
},
472 {"SPSR_xfs", FALSE
, PSR_x
| PSR_f
| PSR_s
},
473 {"SPSR_xfc", FALSE
, PSR_x
| PSR_f
| PSR_c
},
474 {"SPSR_xsf", FALSE
, PSR_x
| PSR_s
| PSR_f
},
475 {"SPSR_xsc", FALSE
, PSR_x
| PSR_s
| PSR_c
},
476 {"SPSR_xcf", FALSE
, PSR_x
| PSR_c
| PSR_f
},
477 {"SPSR_xcs", FALSE
, PSR_x
| PSR_c
| PSR_s
},
478 {"SPSR_cfs", FALSE
, PSR_c
| PSR_f
| PSR_s
},
479 {"SPSR_cfx", FALSE
, PSR_c
| PSR_f
| PSR_x
},
480 {"SPSR_csf", FALSE
, PSR_c
| PSR_s
| PSR_f
},
481 {"SPSR_csx", FALSE
, PSR_c
| PSR_s
| PSR_x
},
482 {"SPSR_cxf", FALSE
, PSR_c
| PSR_x
| PSR_f
},
483 {"SPSR_cxs", FALSE
, PSR_c
| PSR_x
| PSR_s
},
484 {"SPSR_fsxc", FALSE
, PSR_f
| PSR_s
| PSR_x
| PSR_c
},
485 {"SPSR_fscx", FALSE
, PSR_f
| PSR_s
| PSR_c
| PSR_x
},
486 {"SPSR_fxsc", FALSE
, PSR_f
| PSR_x
| PSR_s
| PSR_c
},
487 {"SPSR_fxcs", FALSE
, PSR_f
| PSR_x
| PSR_c
| PSR_s
},
488 {"SPSR_fcsx", FALSE
, PSR_f
| PSR_c
| PSR_s
| PSR_x
},
489 {"SPSR_fcxs", FALSE
, PSR_f
| PSR_c
| PSR_x
| PSR_s
},
490 {"SPSR_sfxc", FALSE
, PSR_s
| PSR_f
| PSR_x
| PSR_c
},
491 {"SPSR_sfcx", FALSE
, PSR_s
| PSR_f
| PSR_c
| PSR_x
},
492 {"SPSR_sxfc", FALSE
, PSR_s
| PSR_x
| PSR_f
| PSR_c
},
493 {"SPSR_sxcf", FALSE
, PSR_s
| PSR_x
| PSR_c
| PSR_f
},
494 {"SPSR_scfx", FALSE
, PSR_s
| PSR_c
| PSR_f
| PSR_x
},
495 {"SPSR_scxf", FALSE
, PSR_s
| PSR_c
| PSR_x
| PSR_f
},
496 {"SPSR_xfsc", FALSE
, PSR_x
| PSR_f
| PSR_s
| PSR_c
},
497 {"SPSR_xfcs", FALSE
, PSR_x
| PSR_f
| PSR_c
| PSR_s
},
498 {"SPSR_xsfc", FALSE
, PSR_x
| PSR_s
| PSR_f
| PSR_c
},
499 {"SPSR_xscf", FALSE
, PSR_x
| PSR_s
| PSR_c
| PSR_f
},
500 {"SPSR_xcfs", FALSE
, PSR_x
| PSR_c
| PSR_f
| PSR_s
},
501 {"SPSR_xcsf", FALSE
, PSR_x
| PSR_c
| PSR_s
| PSR_f
},
502 {"SPSR_cfsx", FALSE
, PSR_c
| PSR_f
| PSR_s
| PSR_x
},
503 {"SPSR_cfxs", FALSE
, PSR_c
| PSR_f
| PSR_x
| PSR_s
},
504 {"SPSR_csfx", FALSE
, PSR_c
| PSR_s
| PSR_f
| PSR_x
},
505 {"SPSR_csxf", FALSE
, PSR_c
| PSR_s
| PSR_x
| PSR_f
},
506 {"SPSR_cxfs", FALSE
, PSR_c
| PSR_x
| PSR_f
| PSR_s
},
507 {"SPSR_cxsf", FALSE
, PSR_c
| PSR_x
| PSR_s
| PSR_f
},
514 IWMMXT_REG_WR_OR_WC
= 2,
518 enum iwmmxt_insn_type
541 VFP_REG_Dd
, VFP_REG_Dm
, VFP_REG_Dn
546 VFP_REG_Sd
, VFP_REG_Sm
, VFP_REG_Sn
551 VFP_LDSTMIA
, VFP_LDSTMDB
, VFP_LDSTMIAX
, VFP_LDSTMDBX
554 /* VFP system registers. */
561 static const struct vfp_reg vfp_regs
[] =
563 {"fpsid", 0x00000000},
564 {"FPSID", 0x00000000},
565 {"fpscr", 0x00010000},
566 {"FPSCR", 0x00010000},
567 {"fpexc", 0x00080000},
568 {"FPEXC", 0x00080000}
571 /* Structure for a hash table entry for a register. */
579 /* Some well known registers that we refer to directly elsewhere. */
584 #define wr_register(reg) ((reg ^ WR_PREFIX) >= 0 && (reg ^ WR_PREFIX) <= 15)
585 #define wc_register(reg) ((reg ^ WC_PREFIX) >= 0 && (reg ^ WC_PREFIX) <= 15)
586 #define wcg_register(reg) ((reg ^ WC_PREFIX) >= 8 && (reg ^ WC_PREFIX) <= 11)
588 /* These are the standard names. Users can add aliases with .req.
589 and delete them with .unreq. */
591 /* Integer Register Numbers. */
592 static const struct reg_entry rn_table
[] =
594 {"r0", 0, TRUE
}, {"r1", 1, TRUE
}, {"r2", 2, TRUE
}, {"r3", 3, TRUE
},
595 {"r4", 4, TRUE
}, {"r5", 5, TRUE
}, {"r6", 6, TRUE
}, {"r7", 7, TRUE
},
596 {"r8", 8, TRUE
}, {"r9", 9, TRUE
}, {"r10", 10, TRUE
}, {"r11", 11, TRUE
},
597 {"r12", 12, TRUE
}, {"r13", REG_SP
, TRUE
}, {"r14", REG_LR
, TRUE
}, {"r15", REG_PC
, TRUE
},
598 /* ATPCS Synonyms. */
599 {"a1", 0, TRUE
}, {"a2", 1, TRUE
}, {"a3", 2, TRUE
}, {"a4", 3, TRUE
},
600 {"v1", 4, TRUE
}, {"v2", 5, TRUE
}, {"v3", 6, TRUE
}, {"v4", 7, TRUE
},
601 {"v5", 8, TRUE
}, {"v6", 9, TRUE
}, {"v7", 10, TRUE
}, {"v8", 11, TRUE
},
602 /* Well-known aliases. */
603 {"wr", 7, TRUE
}, {"sb", 9, TRUE
}, {"sl", 10, TRUE
}, {"fp", 11, TRUE
},
604 {"ip", 12, TRUE
}, {"sp", REG_SP
, TRUE
}, {"lr", REG_LR
, TRUE
}, {"pc", REG_PC
, TRUE
},
608 #define WR_PREFIX 0x200
609 #define WC_PREFIX 0x400
611 static const struct reg_entry iwmmxt_table
[] =
613 /* Intel Wireless MMX technology register names. */
614 { "wr0", 0x0 | WR_PREFIX
, TRUE
}, {"wr1", 0x1 | WR_PREFIX
, TRUE
},
615 { "wr2", 0x2 | WR_PREFIX
, TRUE
}, {"wr3", 0x3 | WR_PREFIX
, TRUE
},
616 { "wr4", 0x4 | WR_PREFIX
, TRUE
}, {"wr5", 0x5 | WR_PREFIX
, TRUE
},
617 { "wr6", 0x6 | WR_PREFIX
, TRUE
}, {"wr7", 0x7 | WR_PREFIX
, TRUE
},
618 { "wr8", 0x8 | WR_PREFIX
, TRUE
}, {"wr9", 0x9 | WR_PREFIX
, TRUE
},
619 { "wr10", 0xa | WR_PREFIX
, TRUE
}, {"wr11", 0xb | WR_PREFIX
, TRUE
},
620 { "wr12", 0xc | WR_PREFIX
, TRUE
}, {"wr13", 0xd | WR_PREFIX
, TRUE
},
621 { "wr14", 0xe | WR_PREFIX
, TRUE
}, {"wr15", 0xf | WR_PREFIX
, TRUE
},
622 { "wcid", 0x0 | WC_PREFIX
, TRUE
}, {"wcon", 0x1 | WC_PREFIX
, TRUE
},
623 {"wcssf", 0x2 | WC_PREFIX
, TRUE
}, {"wcasf", 0x3 | WC_PREFIX
, TRUE
},
624 {"wcgr0", 0x8 | WC_PREFIX
, TRUE
}, {"wcgr1", 0x9 | WC_PREFIX
, TRUE
},
625 {"wcgr2", 0xa | WC_PREFIX
, TRUE
}, {"wcgr3", 0xb | WC_PREFIX
, TRUE
},
627 { "wR0", 0x0 | WR_PREFIX
, TRUE
}, {"wR1", 0x1 | WR_PREFIX
, TRUE
},
628 { "wR2", 0x2 | WR_PREFIX
, TRUE
}, {"wR3", 0x3 | WR_PREFIX
, TRUE
},
629 { "wR4", 0x4 | WR_PREFIX
, TRUE
}, {"wR5", 0x5 | WR_PREFIX
, TRUE
},
630 { "wR6", 0x6 | WR_PREFIX
, TRUE
}, {"wR7", 0x7 | WR_PREFIX
, TRUE
},
631 { "wR8", 0x8 | WR_PREFIX
, TRUE
}, {"wR9", 0x9 | WR_PREFIX
, TRUE
},
632 { "wR10", 0xa | WR_PREFIX
, TRUE
}, {"wR11", 0xb | WR_PREFIX
, TRUE
},
633 { "wR12", 0xc | WR_PREFIX
, TRUE
}, {"wR13", 0xd | WR_PREFIX
, TRUE
},
634 { "wR14", 0xe | WR_PREFIX
, TRUE
}, {"wR15", 0xf | WR_PREFIX
, TRUE
},
635 { "wCID", 0x0 | WC_PREFIX
, TRUE
}, {"wCon", 0x1 | WC_PREFIX
, TRUE
},
636 {"wCSSF", 0x2 | WC_PREFIX
, TRUE
}, {"wCASF", 0x3 | WC_PREFIX
, TRUE
},
637 {"wCGR0", 0x8 | WC_PREFIX
, TRUE
}, {"wCGR1", 0x9 | WC_PREFIX
, TRUE
},
638 {"wCGR2", 0xa | WC_PREFIX
, TRUE
}, {"wCGR3", 0xb | WC_PREFIX
, TRUE
},
642 /* Co-processor Numbers. */
643 static const struct reg_entry cp_table
[] =
645 {"p0", 0, TRUE
}, {"p1", 1, TRUE
}, {"p2", 2, TRUE
}, {"p3", 3, TRUE
},
646 {"p4", 4, TRUE
}, {"p5", 5, TRUE
}, {"p6", 6, TRUE
}, {"p7", 7, TRUE
},
647 {"p8", 8, TRUE
}, {"p9", 9, TRUE
}, {"p10", 10, TRUE
}, {"p11", 11, TRUE
},
648 {"p12", 12, TRUE
}, {"p13", 13, TRUE
}, {"p14", 14, TRUE
}, {"p15", 15, TRUE
},
652 /* Co-processor Register Numbers. */
653 static const struct reg_entry cn_table
[] =
655 {"c0", 0, TRUE
}, {"c1", 1, TRUE
}, {"c2", 2, TRUE
}, {"c3", 3, TRUE
},
656 {"c4", 4, TRUE
}, {"c5", 5, TRUE
}, {"c6", 6, TRUE
}, {"c7", 7, TRUE
},
657 {"c8", 8, TRUE
}, {"c9", 9, TRUE
}, {"c10", 10, TRUE
}, {"c11", 11, TRUE
},
658 {"c12", 12, TRUE
}, {"c13", 13, TRUE
}, {"c14", 14, TRUE
}, {"c15", 15, TRUE
},
659 /* Not really valid, but kept for back-wards compatibility. */
660 {"cr0", 0, TRUE
}, {"cr1", 1, TRUE
}, {"cr2", 2, TRUE
}, {"cr3", 3, TRUE
},
661 {"cr4", 4, TRUE
}, {"cr5", 5, TRUE
}, {"cr6", 6, TRUE
}, {"cr7", 7, TRUE
},
662 {"cr8", 8, TRUE
}, {"cr9", 9, TRUE
}, {"cr10", 10, TRUE
}, {"cr11", 11, TRUE
},
663 {"cr12", 12, TRUE
}, {"cr13", 13, TRUE
}, {"cr14", 14, TRUE
}, {"cr15", 15, TRUE
},
668 static const struct reg_entry fn_table
[] =
670 {"f0", 0, TRUE
}, {"f1", 1, TRUE
}, {"f2", 2, TRUE
}, {"f3", 3, TRUE
},
671 {"f4", 4, TRUE
}, {"f5", 5, TRUE
}, {"f6", 6, TRUE
}, {"f7", 7, TRUE
},
675 /* VFP SP Registers. */
676 static const struct reg_entry sn_table
[] =
678 {"s0", 0, TRUE
}, {"s1", 1, TRUE
}, {"s2", 2, TRUE
}, {"s3", 3, TRUE
},
679 {"s4", 4, TRUE
}, {"s5", 5, TRUE
}, {"s6", 6, TRUE
}, {"s7", 7, TRUE
},
680 {"s8", 8, TRUE
}, {"s9", 9, TRUE
}, {"s10", 10, TRUE
}, {"s11", 11, TRUE
},
681 {"s12", 12, TRUE
}, {"s13", 13, TRUE
}, {"s14", 14, TRUE
}, {"s15", 15, TRUE
},
682 {"s16", 16, TRUE
}, {"s17", 17, TRUE
}, {"s18", 18, TRUE
}, {"s19", 19, TRUE
},
683 {"s20", 20, TRUE
}, {"s21", 21, TRUE
}, {"s22", 22, TRUE
}, {"s23", 23, TRUE
},
684 {"s24", 24, TRUE
}, {"s25", 25, TRUE
}, {"s26", 26, TRUE
}, {"s27", 27, TRUE
},
685 {"s28", 28, TRUE
}, {"s29", 29, TRUE
}, {"s30", 30, TRUE
}, {"s31", 31, TRUE
},
689 /* VFP DP Registers. */
690 static const struct reg_entry dn_table
[] =
692 {"d0", 0, TRUE
}, {"d1", 1, TRUE
}, {"d2", 2, TRUE
}, {"d3", 3, TRUE
},
693 {"d4", 4, TRUE
}, {"d5", 5, TRUE
}, {"d6", 6, TRUE
}, {"d7", 7, TRUE
},
694 {"d8", 8, TRUE
}, {"d9", 9, TRUE
}, {"d10", 10, TRUE
}, {"d11", 11, TRUE
},
695 {"d12", 12, TRUE
}, {"d13", 13, TRUE
}, {"d14", 14, TRUE
}, {"d15", 15, TRUE
},
699 /* Maverick DSP coprocessor registers. */
700 static const struct reg_entry mav_mvf_table
[] =
702 {"mvf0", 0, TRUE
}, {"mvf1", 1, TRUE
}, {"mvf2", 2, TRUE
}, {"mvf3", 3, TRUE
},
703 {"mvf4", 4, TRUE
}, {"mvf5", 5, TRUE
}, {"mvf6", 6, TRUE
}, {"mvf7", 7, TRUE
},
704 {"mvf8", 8, TRUE
}, {"mvf9", 9, TRUE
}, {"mvf10", 10, TRUE
}, {"mvf11", 11, TRUE
},
705 {"mvf12", 12, TRUE
}, {"mvf13", 13, TRUE
}, {"mvf14", 14, TRUE
}, {"mvf15", 15, TRUE
},
709 static const struct reg_entry mav_mvd_table
[] =
711 {"mvd0", 0, TRUE
}, {"mvd1", 1, TRUE
}, {"mvd2", 2, TRUE
}, {"mvd3", 3, TRUE
},
712 {"mvd4", 4, TRUE
}, {"mvd5", 5, TRUE
}, {"mvd6", 6, TRUE
}, {"mvd7", 7, TRUE
},
713 {"mvd8", 8, TRUE
}, {"mvd9", 9, TRUE
}, {"mvd10", 10, TRUE
}, {"mvd11", 11, TRUE
},
714 {"mvd12", 12, TRUE
}, {"mvd13", 13, TRUE
}, {"mvd14", 14, TRUE
}, {"mvd15", 15, TRUE
},
718 static const struct reg_entry mav_mvfx_table
[] =
720 {"mvfx0", 0, TRUE
}, {"mvfx1", 1, TRUE
}, {"mvfx2", 2, TRUE
}, {"mvfx3", 3, TRUE
},
721 {"mvfx4", 4, TRUE
}, {"mvfx5", 5, TRUE
}, {"mvfx6", 6, TRUE
}, {"mvfx7", 7, TRUE
},
722 {"mvfx8", 8, TRUE
}, {"mvfx9", 9, TRUE
}, {"mvfx10", 10, TRUE
}, {"mvfx11", 11, TRUE
},
723 {"mvfx12", 12, TRUE
}, {"mvfx13", 13, TRUE
}, {"mvfx14", 14, TRUE
}, {"mvfx15", 15, TRUE
},
727 static const struct reg_entry mav_mvdx_table
[] =
729 {"mvdx0", 0, TRUE
}, {"mvdx1", 1, TRUE
}, {"mvdx2", 2, TRUE
}, {"mvdx3", 3, TRUE
},
730 {"mvdx4", 4, TRUE
}, {"mvdx5", 5, TRUE
}, {"mvdx6", 6, TRUE
}, {"mvdx7", 7, TRUE
},
731 {"mvdx8", 8, TRUE
}, {"mvdx9", 9, TRUE
}, {"mvdx10", 10, TRUE
}, {"mvdx11", 11, TRUE
},
732 {"mvdx12", 12, TRUE
}, {"mvdx13", 13, TRUE
}, {"mvdx14", 14, TRUE
}, {"mvdx15", 15, TRUE
},
736 static const struct reg_entry mav_mvax_table
[] =
738 {"mvax0", 0, TRUE
}, {"mvax1", 1, TRUE
}, {"mvax2", 2, TRUE
}, {"mvax3", 3, TRUE
},
742 static const struct reg_entry mav_dspsc_table
[] =
750 const struct reg_entry
* names
;
752 struct hash_control
* htab
;
753 const char * expected
;
756 struct reg_map all_reg_maps
[] =
758 {rn_table
, 15, NULL
, N_("ARM register expected")},
759 {cp_table
, 15, NULL
, N_("bad or missing co-processor number")},
760 {cn_table
, 15, NULL
, N_("co-processor register expected")},
761 {fn_table
, 7, NULL
, N_("FPA register expected")},
762 {sn_table
, 31, NULL
, N_("VFP single precision register expected")},
763 {dn_table
, 15, NULL
, N_("VFP double precision register expected")},
764 {mav_mvf_table
, 15, NULL
, N_("Maverick MVF register expected")},
765 {mav_mvd_table
, 15, NULL
, N_("Maverick MVD register expected")},
766 {mav_mvfx_table
, 15, NULL
, N_("Maverick MVFX register expected")},
767 {mav_mvdx_table
, 15, NULL
, N_("Maverick MVDX register expected")},
768 {mav_mvax_table
, 3, NULL
, N_("Maverick MVAX register expected")},
769 {mav_dspsc_table
, 0, NULL
, N_("Maverick DSPSC register expected")},
770 {iwmmxt_table
, 23, NULL
, N_("Intel Wireless MMX technology register expected")},
773 /* Enumeration matching entries in table above. */
777 #define REG_TYPE_FIRST REG_TYPE_RN
789 REG_TYPE_IWMMXT
= 12,
794 /* ARM instructions take 4bytes in the object file, Thumb instructions
798 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
799 #define MAV_MODE1 0x100c
801 /* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
802 #define MAV_MODE2 0x0c10
804 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
805 #define MAV_MODE3 0x100c
807 /* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
808 #define MAV_MODE4 0x0c0010
810 /* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
811 #define MAV_MODE5 0x00100c
813 /* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
814 #define MAV_MODE6 0x00100c05
818 /* Basic string to match. */
819 const char * template;
821 /* Basic instruction code. */
824 /* Offset into the template where the condition code (if any) will be.
825 If zero, then the instruction is never conditional. */
826 unsigned cond_offset
;
828 /* Which architecture variant provides this instruction. */
829 unsigned long variant
;
831 /* Function to call to parse args. */
832 void (* parms
) (char *);
835 /* Defines for various bits that we will want to toggle. */
836 #define INST_IMMEDIATE 0x02000000
837 #define OFFSET_REG 0x02000000
838 #define HWOFFSET_IMM 0x00400000
839 #define SHIFT_BY_REG 0x00000010
840 #define PRE_INDEX 0x01000000
841 #define INDEX_UP 0x00800000
842 #define WRITE_BACK 0x00200000
843 #define LDM_TYPE_2_OR_3 0x00400000
845 #define LITERAL_MASK 0xf000f000
846 #define OPCODE_MASK 0xfe1fffff
847 #define V4_STR_BIT 0x00000020
849 #define DATA_OP_SHIFT 21
851 /* Codes to distinguish the arithmetic instructions. */
862 #define OPCODE_CMP 10
863 #define OPCODE_CMN 11
864 #define OPCODE_ORR 12
865 #define OPCODE_MOV 13
866 #define OPCODE_BIC 14
867 #define OPCODE_MVN 15
869 #define T_OPCODE_MUL 0x4340
870 #define T_OPCODE_TST 0x4200
871 #define T_OPCODE_CMN 0x42c0
872 #define T_OPCODE_NEG 0x4240
873 #define T_OPCODE_MVN 0x43c0
875 #define T_OPCODE_ADD_R3 0x1800
876 #define T_OPCODE_SUB_R3 0x1a00
877 #define T_OPCODE_ADD_HI 0x4400
878 #define T_OPCODE_ADD_ST 0xb000
879 #define T_OPCODE_SUB_ST 0xb080
880 #define T_OPCODE_ADD_SP 0xa800
881 #define T_OPCODE_ADD_PC 0xa000
882 #define T_OPCODE_ADD_I8 0x3000
883 #define T_OPCODE_SUB_I8 0x3800
884 #define T_OPCODE_ADD_I3 0x1c00
885 #define T_OPCODE_SUB_I3 0x1e00
887 #define T_OPCODE_ASR_R 0x4100
888 #define T_OPCODE_LSL_R 0x4080
889 #define T_OPCODE_LSR_R 0x40c0
890 #define T_OPCODE_ASR_I 0x1000
891 #define T_OPCODE_LSL_I 0x0000
892 #define T_OPCODE_LSR_I 0x0800
894 #define T_OPCODE_MOV_I8 0x2000
895 #define T_OPCODE_CMP_I8 0x2800
896 #define T_OPCODE_CMP_LR 0x4280
897 #define T_OPCODE_MOV_HR 0x4600
898 #define T_OPCODE_CMP_HR 0x4500
900 #define T_OPCODE_LDR_PC 0x4800
901 #define T_OPCODE_LDR_SP 0x9800
902 #define T_OPCODE_STR_SP 0x9000
903 #define T_OPCODE_LDR_IW 0x6800
904 #define T_OPCODE_STR_IW 0x6000
905 #define T_OPCODE_LDR_IH 0x8800
906 #define T_OPCODE_STR_IH 0x8000
907 #define T_OPCODE_LDR_IB 0x7800
908 #define T_OPCODE_STR_IB 0x7000
909 #define T_OPCODE_LDR_RW 0x5800
910 #define T_OPCODE_STR_RW 0x5000
911 #define T_OPCODE_LDR_RH 0x5a00
912 #define T_OPCODE_STR_RH 0x5200
913 #define T_OPCODE_LDR_RB 0x5c00
914 #define T_OPCODE_STR_RB 0x5400
916 #define T_OPCODE_PUSH 0xb400
917 #define T_OPCODE_POP 0xbc00
919 #define T_OPCODE_BRANCH 0xe7fe
921 #define THUMB_SIZE 2 /* Size of thumb instruction. */
922 #define THUMB_REG_LO 0x1
923 #define THUMB_REG_HI 0x2
924 #define THUMB_REG_ANY 0x3
926 #define THUMB_H1 0x0080
927 #define THUMB_H2 0x0040
934 #define THUMB_COMPARE 1
938 #define THUMB_STORE 1
940 #define THUMB_PP_PC_LR 0x0100
942 /* These three are used for immediate shifts, do not alter. */
944 #define THUMB_HALFWORD 1
949 /* Basic string to match. */
950 const char * template;
952 /* Basic instruction code. */
957 /* Which CPU variants this exists for. */
958 unsigned long variant
;
960 /* Function to call to parse args. */
961 void (* parms
) (char *);
964 #define BAD_ARGS _("bad arguments to instruction")
965 #define BAD_PC _("r15 not allowed here")
966 #define BAD_COND _("instruction is not conditional")
967 #define ERR_NO_ACCUM _("acc0 expected")
969 static struct hash_control
* arm_ops_hsh
= NULL
;
970 static struct hash_control
* arm_tops_hsh
= NULL
;
971 static struct hash_control
* arm_cond_hsh
= NULL
;
972 static struct hash_control
* arm_shift_hsh
= NULL
;
973 static struct hash_control
* arm_psr_hsh
= NULL
;
975 /* Stuff needed to resolve the label ambiguity
985 symbolS
* last_label_seen
;
986 static int label_is_thumb_function_name
= FALSE
;
988 /* Literal Pool stuff. */
990 #define MAX_LITERAL_POOL_SIZE 1024
992 /* Literal pool structure. Held on a per-section
993 and per-sub-section basis. */
995 typedef struct literal_pool
997 expressionS literals
[MAX_LITERAL_POOL_SIZE
];
998 unsigned int next_free_entry
;
1002 subsegT sub_section
;
1003 struct literal_pool
* next
;
1006 /* Pointer to a linked list of literal pools. */
1007 literal_pool
* list_of_pools
= NULL
;
1009 static literal_pool
*
1010 find_literal_pool (void)
1012 literal_pool
* pool
;
1014 for (pool
= list_of_pools
; pool
!= NULL
; pool
= pool
->next
)
1016 if (pool
->section
== now_seg
1017 && pool
->sub_section
== now_subseg
)
1024 static literal_pool
*
1025 find_or_make_literal_pool (void)
1027 /* Next literal pool ID number. */
1028 static unsigned int latest_pool_num
= 1;
1029 literal_pool
* pool
;
1031 pool
= find_literal_pool ();
1035 /* Create a new pool. */
1036 pool
= xmalloc (sizeof (* pool
));
1040 pool
->next_free_entry
= 0;
1041 pool
->section
= now_seg
;
1042 pool
->sub_section
= now_subseg
;
1043 pool
->next
= list_of_pools
;
1044 pool
->symbol
= NULL
;
1046 /* Add it to the list. */
1047 list_of_pools
= pool
;
1050 /* New pools, and emptied pools, will have a NULL symbol. */
1051 if (pool
->symbol
== NULL
)
1053 pool
->symbol
= symbol_create (FAKE_LABEL_NAME
, undefined_section
,
1054 (valueT
) 0, &zero_address_frag
);
1055 pool
->id
= latest_pool_num
++;
1062 /* Add the literal in the global 'inst'
1063 structure to the relevent literal pool. */
1066 add_to_lit_pool (void)
1068 literal_pool
* pool
;
1071 pool
= find_or_make_literal_pool ();
1073 /* Check if this literal value is already in the pool. */
1074 for (entry
= 0; entry
< pool
->next_free_entry
; entry
++)
1076 if ((pool
->literals
[entry
].X_op
== inst
.reloc
.exp
.X_op
)
1077 && (inst
.reloc
.exp
.X_op
== O_constant
)
1078 && (pool
->literals
[entry
].X_add_number
1079 == inst
.reloc
.exp
.X_add_number
)
1080 && (pool
->literals
[entry
].X_unsigned
1081 == inst
.reloc
.exp
.X_unsigned
))
1084 if ((pool
->literals
[entry
].X_op
== inst
.reloc
.exp
.X_op
)
1085 && (inst
.reloc
.exp
.X_op
== O_symbol
)
1086 && (pool
->literals
[entry
].X_add_number
1087 == inst
.reloc
.exp
.X_add_number
)
1088 && (pool
->literals
[entry
].X_add_symbol
1089 == inst
.reloc
.exp
.X_add_symbol
)
1090 && (pool
->literals
[entry
].X_op_symbol
1091 == inst
.reloc
.exp
.X_op_symbol
))
1095 /* Do we need to create a new entry? */
1096 if (entry
== pool
->next_free_entry
)
1098 if (entry
>= MAX_LITERAL_POOL_SIZE
)
1100 inst
.error
= _("literal pool overflow");
1104 pool
->literals
[entry
] = inst
.reloc
.exp
;
1105 pool
->next_free_entry
+= 1;
1108 inst
.reloc
.exp
.X_op
= O_symbol
;
1109 inst
.reloc
.exp
.X_add_number
= ((int) entry
) * 4 - 8;
1110 inst
.reloc
.exp
.X_add_symbol
= pool
->symbol
;
1115 /* Can't use symbol_new here, so have to create a symbol and then at
1116 a later date assign it a value. Thats what these functions do. */
1119 symbol_locate (symbolS
* symbolP
,
1120 const char * name
, /* It is copied, the caller can modify. */
1121 segT segment
, /* Segment identifier (SEG_<something>). */
1122 valueT valu
, /* Symbol value. */
1123 fragS
* frag
) /* Associated fragment. */
1125 unsigned int name_length
;
1126 char * preserved_copy_of_name
;
1128 name_length
= strlen (name
) + 1; /* +1 for \0. */
1129 obstack_grow (¬es
, name
, name_length
);
1130 preserved_copy_of_name
= obstack_finish (¬es
);
1131 #ifdef STRIP_UNDERSCORE
1132 if (preserved_copy_of_name
[0] == '_')
1133 preserved_copy_of_name
++;
1136 #ifdef tc_canonicalize_symbol_name
1137 preserved_copy_of_name
=
1138 tc_canonicalize_symbol_name (preserved_copy_of_name
);
1141 S_SET_NAME (symbolP
, preserved_copy_of_name
);
1143 S_SET_SEGMENT (symbolP
, segment
);
1144 S_SET_VALUE (symbolP
, valu
);
1145 symbol_clear_list_pointers (symbolP
);
1147 symbol_set_frag (symbolP
, frag
);
1149 /* Link to end of symbol chain. */
1151 extern int symbol_table_frozen
;
1153 if (symbol_table_frozen
)
1157 symbol_append (symbolP
, symbol_lastP
, & symbol_rootP
, & symbol_lastP
);
1159 obj_symbol_new_hook (symbolP
);
1161 #ifdef tc_symbol_new_hook
1162 tc_symbol_new_hook (symbolP
);
1166 verify_symbol_chain (symbol_rootP
, symbol_lastP
);
1167 #endif /* DEBUG_SYMS */
1170 /* Check that an immediate is valid.
1171 If so, convert it to the right format. */
1174 validate_immediate (unsigned int val
)
1179 #define rotate_left(v, n) (v << n | v >> (32 - n))
1181 for (i
= 0; i
< 32; i
+= 2)
1182 if ((a
= rotate_left (val
, i
)) <= 0xff)
1183 return a
| (i
<< 7); /* 12-bit pack: [shift-cnt,const]. */
1188 /* Check to see if an immediate can be computed as two separate immediate
1189 values, added together. We already know that this value cannot be
1190 computed by just one ARM instruction. */
1193 validate_immediate_twopart (unsigned int val
,
1194 unsigned int * highpart
)
1199 for (i
= 0; i
< 32; i
+= 2)
1200 if (((a
= rotate_left (val
, i
)) & 0xff) != 0)
1206 * highpart
= (a
>> 8) | ((i
+ 24) << 7);
1208 else if (a
& 0xff0000)
1212 * highpart
= (a
>> 16) | ((i
+ 16) << 7);
1216 assert (a
& 0xff000000);
1217 * highpart
= (a
>> 24) | ((i
+ 8) << 7);
1220 return (a
& 0xff) | (i
<< 7);
1227 validate_offset_imm (unsigned int val
, int hwse
)
1229 if ((hwse
&& val
> 255) || val
> 4095)
1236 /* This code is to handle mapping symbols as defined in the ARM ELF spec.
1237 (This text is taken from version B-02 of the spec):
1239 4.4.7 Mapping and tagging symbols
1241 A section of an ARM ELF file can contain a mixture of ARM code,
1242 Thumb code, and data. There are inline transitions between code
1243 and data at literal pool boundaries. There can also be inline
1244 transitions between ARM code and Thumb code, for example in
1245 ARM-Thumb inter-working veneers. Linkers, machine-level
1246 debuggers, profiling tools, and disassembly tools need to map
1247 images accurately. For example, setting an ARM breakpoint on a
1248 Thumb location, or in a literal pool, can crash the program
1249 being debugged, ruining the debugging session.
1251 ARM ELF entities are mapped (see section 4.4.7.1 below) and
1252 tagged (see section 4.4.7.2 below) using local symbols (with
1253 binding STB_LOCAL). To assist consumers, mapping and tagging
1254 symbols should be collated first in the symbol table, before
1255 other symbols with binding STB_LOCAL.
1257 To allow properly collated mapping and tagging symbols to be
1258 skipped by consumers that have no interest in them, the first
1259 such symbol should have the name $m and its st_value field equal
1260 to the total number of mapping and tagging symbols (including
1261 the $m) in the symbol table.
1263 4.4.7.1 Mapping symbols
1265 $a Labels the first byte of a sequence of ARM instructions.
1266 Its type is STT_FUNC.
1268 $d Labels the first byte of a sequence of data items.
1269 Its type is STT_OBJECT.
1271 $t Labels the first byte of a sequence of Thumb instructions.
1272 Its type is STT_FUNC.
1274 This list of mapping symbols may be extended in the future.
1276 Section-relative mapping symbols
1278 Mapping symbols defined in a section define a sequence of
1279 half-open address intervals that cover the address range of the
1280 section. Each interval starts at the address defined by a
1281 mapping symbol, and continues up to, but not including, the
1282 address defined by the next (in address order) mapping symbol or
1283 the end of the section. A corollary is that there must be a
1284 mapping symbol defined at the beginning of each section.
1285 Consumers can ignore the size of a section-relative mapping
1286 symbol. Producers can set it to 0.
1288 Absolute mapping symbols
1290 Because of the need to crystallize a Thumb address with the
1291 Thumb-bit set, absolute symbol of type STT_FUNC (symbols of type
1292 STT_FUNC defined in section SHN_ABS) need to be mapped with $a
1295 The extent of a mapping symbol defined in SHN_ABS is [st_value,
1296 st_value + st_size), or [st_value, st_value + 1) if st_size = 0,
1297 where [x, y) denotes the half-open address range from x,
1298 inclusive, to y, exclusive.
1300 In the absence of a mapping symbol, a consumer can interpret a
1301 function symbol with an odd value as the Thumb code address
1302 obtained by clearing the least significant bit of the
1303 value. This interpretation is deprecated, and it may not work in
1306 Note - the Tagging symbols ($b, $f, $p $m) have been dropped from
1307 the EABI (which is still under development), so they are not
1308 implemented here. */
1310 static enum mstate mapstate
= MAP_UNDEFINED
;
1313 mapping_state (enum mstate state
)
1316 const char * symname
;
1319 if (mapstate
== state
)
1320 /* The mapping symbol has already been emitted.
1321 There is nothing else to do. */
1334 type
= BSF_FUNCTION
;
1338 type
= BSF_FUNCTION
;
1346 seg_info (now_seg
)->tc_segment_info_data
= state
;
1348 symbolP
= symbol_new (symname
, now_seg
, (valueT
) frag_now_fix (), frag_now
);
1349 symbol_table_insert (symbolP
);
1350 symbol_get_bfdsym (symbolP
)->flags
|= type
| BSF_LOCAL
;
1355 THUMB_SET_FUNC (symbolP
, 0);
1356 ARM_SET_THUMB (symbolP
, 0);
1357 ARM_SET_INTERWORK (symbolP
, support_interwork
);
1361 THUMB_SET_FUNC (symbolP
, 1);
1362 ARM_SET_THUMB (symbolP
, 1);
1363 ARM_SET_INTERWORK (symbolP
, support_interwork
);
1372 /* When we change sections we need to issue a new mapping symbol. */
1375 arm_elf_change_section (void)
1379 /* Link an unlinked unwind index table section to the .text section. */
1380 if (elf_section_type (now_seg
) == SHT_ARM_EXIDX
1381 && elf_linked_to_section (now_seg
) == NULL
)
1382 elf_linked_to_section (now_seg
) = text_section
;
1384 if (!SEG_NORMAL (now_seg
))
1387 flags
= bfd_get_section_flags (stdoutput
, now_seg
);
1389 /* We can ignore sections that only contain debug info. */
1390 if ((flags
& SEC_ALLOC
) == 0)
1393 mapstate
= seg_info (now_seg
)->tc_segment_info_data
;
1397 arm_elf_section_type (const char * str
, size_t len
)
1399 if (len
== 5 && strncmp (str
, "exidx", 5) == 0)
1400 return SHT_ARM_EXIDX
;
1405 #define mapping_state(a)
1406 #endif /* OBJ_ELF */
1408 /* arm_reg_parse () := if it looks like a register, return its token and
1409 advance the pointer. */
1412 arm_reg_parse (char ** ccp
, struct hash_control
* htab
)
1414 char * start
= * ccp
;
1417 struct reg_entry
* reg
;
1419 #ifdef REGISTER_PREFIX
1420 if (*start
!= REGISTER_PREFIX
)
1425 #ifdef OPTIONAL_REGISTER_PREFIX
1426 if (*p
== OPTIONAL_REGISTER_PREFIX
)
1430 if (!ISALPHA (*p
) || !is_name_beginner (*p
))
1434 while (ISALPHA (c
) || ISDIGIT (c
) || c
== '_')
1438 reg
= (struct reg_entry
*) hash_find (htab
, start
);
1450 /* Search for the following register name in each of the possible reg name
1451 tables. Return the classification if found, or REG_TYPE_MAX if not
1454 static enum arm_reg_type
1455 arm_reg_parse_any (char *cp
)
1459 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
1460 if (arm_reg_parse (&cp
, all_reg_maps
[i
].htab
) != FAIL
)
1461 return (enum arm_reg_type
) i
;
1463 return REG_TYPE_MAX
;
1467 opcode_select (int width
)
1474 if (! (cpu_variant
& ARM_EXT_V4T
))
1475 as_bad (_("selected processor does not support THUMB opcodes"));
1478 /* No need to force the alignment, since we will have been
1479 coming from ARM mode, which is word-aligned. */
1480 record_alignment (now_seg
, 1);
1482 mapping_state (MAP_THUMB
);
1488 if ((cpu_variant
& ARM_ALL
) == ARM_EXT_V4T
)
1489 as_bad (_("selected processor does not support ARM opcodes"));
1494 frag_align (2, 0, 0);
1496 record_alignment (now_seg
, 1);
1498 mapping_state (MAP_ARM
);
1502 as_bad (_("invalid instruction size selected (%d)"), width
);
1507 s_req (int a ATTRIBUTE_UNUSED
)
1509 as_bad (_("invalid syntax for .req directive"));
1512 /* The .unreq directive deletes an alias which was previously defined
1513 by .req. For example:
1519 s_unreq (int a ATTRIBUTE_UNUSED
)
1524 skip_whitespace (input_line_pointer
);
1525 name
= input_line_pointer
;
1527 while (*input_line_pointer
!= 0
1528 && *input_line_pointer
!= ' '
1529 && *input_line_pointer
!= '\n')
1530 ++input_line_pointer
;
1532 saved_char
= *input_line_pointer
;
1533 *input_line_pointer
= 0;
1537 enum arm_reg_type req_type
= arm_reg_parse_any (name
);
1539 if (req_type
!= REG_TYPE_MAX
)
1541 char *temp_name
= name
;
1542 int req_no
= arm_reg_parse (&temp_name
, all_reg_maps
[req_type
].htab
);
1546 struct reg_entry
*req_entry
;
1548 /* Check to see if this alias is a builtin one. */
1549 req_entry
= hash_delete (all_reg_maps
[req_type
].htab
, name
);
1552 as_bad (_("unreq: missing hash entry for \"%s\""), name
);
1553 else if (req_entry
->builtin
)
1554 /* FIXME: We are deleting a built in register alias which
1555 points to a const data structure, so we only need to
1556 free up the memory used by the key in the hash table.
1557 Unfortunately we have not recorded this value, so this
1558 is a memory leak. */
1559 /* FIXME: Should we issue a warning message ? */
1563 /* Deleting a user defined alias. We need to free the
1564 key and the value, but fortunately the key is the same
1565 as the value->name field. */
1566 free ((char *) req_entry
->name
);
1571 as_bad (_(".unreq: unrecognized symbol \"%s\""), name
);
1574 as_bad (_(".unreq: unrecognized symbol \"%s\""), name
);
1577 as_bad (_("invalid syntax for .unreq directive"));
1579 *input_line_pointer
= saved_char
;
1580 demand_empty_rest_of_line ();
1584 s_bss (int ignore ATTRIBUTE_UNUSED
)
1586 /* We don't support putting frags in the BSS segment, we fake it by
1587 marking in_bss, then looking at s_skip for clues. */
1588 subseg_set (bss_section
, 0);
1589 demand_empty_rest_of_line ();
1590 mapping_state (MAP_DATA
);
1594 s_even (int ignore ATTRIBUTE_UNUSED
)
1596 /* Never make frag if expect extra pass. */
1598 frag_align (1, 0, 0);
1600 record_alignment (now_seg
, 1);
1602 demand_empty_rest_of_line ();
1606 s_ltorg (int ignored ATTRIBUTE_UNUSED
)
1609 literal_pool
* pool
;
1612 pool
= find_literal_pool ();
1614 || pool
->symbol
== NULL
1615 || pool
->next_free_entry
== 0)
1618 mapping_state (MAP_DATA
);
1620 /* Align pool as you have word accesses.
1621 Only make a frag if we have to. */
1623 frag_align (2, 0, 0);
1625 record_alignment (now_seg
, 2);
1627 sprintf (sym_name
, "$$lit_\002%x", pool
->id
);
1629 symbol_locate (pool
->symbol
, sym_name
, now_seg
,
1630 (valueT
) frag_now_fix (), frag_now
);
1631 symbol_table_insert (pool
->symbol
);
1633 ARM_SET_THUMB (pool
->symbol
, thumb_mode
);
1635 #if defined OBJ_COFF || defined OBJ_ELF
1636 ARM_SET_INTERWORK (pool
->symbol
, support_interwork
);
1639 for (entry
= 0; entry
< pool
->next_free_entry
; entry
++)
1640 /* First output the expression in the instruction to the pool. */
1641 emit_expr (&(pool
->literals
[entry
]), 4); /* .word */
1643 /* Mark the pool as empty. */
1644 pool
->next_free_entry
= 0;
1645 pool
->symbol
= NULL
;
1648 /* Same as s_align_ptwo but align 0 => align 2. */
1651 s_align (int unused ATTRIBUTE_UNUSED
)
1655 long max_alignment
= 15;
1657 temp
= get_absolute_expression ();
1658 if (temp
> max_alignment
)
1659 as_bad (_("alignment too large: %d assumed"), temp
= max_alignment
);
1662 as_bad (_("alignment negative. 0 assumed."));
1666 if (*input_line_pointer
== ',')
1668 input_line_pointer
++;
1669 temp_fill
= get_absolute_expression ();
1677 /* Only make a frag if we HAVE to. */
1678 if (temp
&& !need_pass_2
)
1679 frag_align (temp
, (int) temp_fill
, 0);
1680 demand_empty_rest_of_line ();
1682 record_alignment (now_seg
, temp
);
1686 s_force_thumb (int ignore ATTRIBUTE_UNUSED
)
1688 /* If we are not already in thumb mode go into it, EVEN if
1689 the target processor does not support thumb instructions.
1690 This is used by gcc/config/arm/lib1funcs.asm for example
1691 to compile interworking support functions even if the
1692 target processor should not support interworking. */
1697 record_alignment (now_seg
, 1);
1700 demand_empty_rest_of_line ();
1704 s_thumb_func (int ignore ATTRIBUTE_UNUSED
)
1709 /* The following label is the name/address of the start of a Thumb function.
1710 We need to know this for the interworking support. */
1711 label_is_thumb_function_name
= TRUE
;
1713 demand_empty_rest_of_line ();
1716 /* Perform a .set directive, but also mark the alias as
1717 being a thumb function. */
1720 s_thumb_set (int equiv
)
1722 /* XXX the following is a duplicate of the code for s_set() in read.c
1723 We cannot just call that code as we need to get at the symbol that
1730 /* Especial apologies for the random logic:
1731 This just grew, and could be parsed much more simply!
1733 name
= input_line_pointer
;
1734 delim
= get_symbol_end ();
1735 end_name
= input_line_pointer
;
1740 if (*input_line_pointer
!= ',')
1743 as_bad (_("expected comma after name \"%s\""), name
);
1745 ignore_rest_of_line ();
1749 input_line_pointer
++;
1752 if (name
[0] == '.' && name
[1] == '\0')
1754 /* XXX - this should not happen to .thumb_set. */
1758 if ((symbolP
= symbol_find (name
)) == NULL
1759 && (symbolP
= md_undefined_symbol (name
)) == NULL
)
1762 /* When doing symbol listings, play games with dummy fragments living
1763 outside the normal fragment chain to record the file and line info
1765 if (listing
& LISTING_SYMBOLS
)
1767 extern struct list_info_struct
* listing_tail
;
1768 fragS
* dummy_frag
= xmalloc (sizeof (fragS
));
1770 memset (dummy_frag
, 0, sizeof (fragS
));
1771 dummy_frag
->fr_type
= rs_fill
;
1772 dummy_frag
->line
= listing_tail
;
1773 symbolP
= symbol_new (name
, undefined_section
, 0, dummy_frag
);
1774 dummy_frag
->fr_symbol
= symbolP
;
1778 symbolP
= symbol_new (name
, undefined_section
, 0, &zero_address_frag
);
1781 /* "set" symbols are local unless otherwise specified. */
1782 SF_SET_LOCAL (symbolP
);
1783 #endif /* OBJ_COFF */
1784 } /* Make a new symbol. */
1786 symbol_table_insert (symbolP
);
1791 && S_IS_DEFINED (symbolP
)
1792 && S_GET_SEGMENT (symbolP
) != reg_section
)
1793 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP
));
1795 pseudo_set (symbolP
);
1797 demand_empty_rest_of_line ();
1799 /* XXX Now we come to the Thumb specific bit of code. */
1801 THUMB_SET_FUNC (symbolP
, 1);
1802 ARM_SET_THUMB (symbolP
, 1);
1803 #if defined OBJ_ELF || defined OBJ_COFF
1804 ARM_SET_INTERWORK (symbolP
, support_interwork
);
1809 s_arm (int ignore ATTRIBUTE_UNUSED
)
1812 demand_empty_rest_of_line ();
1816 s_thumb (int ignore ATTRIBUTE_UNUSED
)
1819 demand_empty_rest_of_line ();
1823 s_code (int unused ATTRIBUTE_UNUSED
)
1827 temp
= get_absolute_expression ();
1832 opcode_select (temp
);
1836 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp
);
1841 end_of_line (char * str
)
1843 skip_whitespace (str
);
1845 if (*str
!= '\0' && !inst
.error
)
1846 inst
.error
= _("garbage following instruction");
1850 skip_past_comma (char ** str
)
1852 char * p
= * str
, c
;
1855 while ((c
= *p
) == ' ' || c
== ',')
1858 if (c
== ',' && comma
++)
1866 return comma
? SUCCESS
: FAIL
;
1869 /* Return TRUE if anything in the expression is a bignum. */
1872 walk_no_bignums (symbolS
* sp
)
1874 if (symbol_get_value_expression (sp
)->X_op
== O_big
)
1877 if (symbol_get_value_expression (sp
)->X_add_symbol
)
1879 return (walk_no_bignums (symbol_get_value_expression (sp
)->X_add_symbol
)
1880 || (symbol_get_value_expression (sp
)->X_op_symbol
1881 && walk_no_bignums (symbol_get_value_expression (sp
)->X_op_symbol
)));
1887 static int in_my_get_expression
= 0;
1890 my_get_expression (expressionS
* ep
, char ** str
)
1895 save_in
= input_line_pointer
;
1896 input_line_pointer
= *str
;
1897 in_my_get_expression
= 1;
1898 seg
= expression (ep
);
1899 in_my_get_expression
= 0;
1901 if (ep
->X_op
== O_illegal
)
1903 /* We found a bad expression in md_operand(). */
1904 *str
= input_line_pointer
;
1905 input_line_pointer
= save_in
;
1910 if (seg
!= absolute_section
1911 && seg
!= text_section
1912 && seg
!= data_section
1913 && seg
!= bss_section
1914 && seg
!= undefined_section
)
1916 inst
.error
= _("bad_segment");
1917 *str
= input_line_pointer
;
1918 input_line_pointer
= save_in
;
1923 /* Get rid of any bignums now, so that we don't generate an error for which
1924 we can't establish a line number later on. Big numbers are never valid
1925 in instructions, which is where this routine is always called. */
1926 if (ep
->X_op
== O_big
1927 || (ep
->X_add_symbol
1928 && (walk_no_bignums (ep
->X_add_symbol
)
1930 && walk_no_bignums (ep
->X_op_symbol
)))))
1932 inst
.error
= _("invalid constant");
1933 *str
= input_line_pointer
;
1934 input_line_pointer
= save_in
;
1938 *str
= input_line_pointer
;
1939 input_line_pointer
= save_in
;
1943 /* A standard register must be given at this point.
1944 SHIFT is the place to put it in inst.instruction.
1945 Restores input start point on error.
1946 Returns the reg#, or FAIL. */
1949 reg_required_here (char ** str
, int shift
)
1951 static char buff
[128]; /* XXX */
1953 char * start
= * str
;
1955 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_RN
].htab
)) != FAIL
)
1958 inst
.instruction
|= reg
<< shift
;
1962 /* Restore the start point, we may have got a reg of the wrong class. */
1965 /* In the few cases where we might be able to accept something else
1966 this error can be overridden. */
1967 sprintf (buff
, _("register expected, not '%.100s'"), start
);
1973 /* A Intel Wireless MMX technology register
1974 must be given at this point.
1975 Shift is the place to put it in inst.instruction.
1976 Restores input start point on err.
1977 Returns the reg#, or FAIL. */
1980 wreg_required_here (char ** str
,
1982 enum wreg_type reg_type
)
1984 static char buff
[128];
1986 char * start
= *str
;
1988 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_IWMMXT
].htab
)) != FAIL
)
1990 if (wr_register (reg
)
1991 && (reg_type
== IWMMXT_REG_WR
|| reg_type
== IWMMXT_REG_WR_OR_WC
))
1994 inst
.instruction
|= (reg
^ WR_PREFIX
) << shift
;
1997 else if (wc_register (reg
)
1998 && (reg_type
== IWMMXT_REG_WC
|| reg_type
== IWMMXT_REG_WR_OR_WC
))
2001 inst
.instruction
|= (reg
^ WC_PREFIX
) << shift
;
2004 else if ((wcg_register (reg
) && reg_type
== IWMMXT_REG_WCG
))
2007 inst
.instruction
|= ((reg
^ WC_PREFIX
) - 8) << shift
;
2012 /* Restore the start point, we may have got a reg of the wrong class. */
2015 /* In the few cases where we might be able to accept
2016 something else this error can be overridden. */
2017 sprintf (buff
, _("Intel Wireless MMX technology register expected, not '%.100s'"), start
);
2023 static const struct asm_psr
*
2024 arm_psr_parse (char ** ccp
)
2026 char * start
= * ccp
;
2029 const struct asm_psr
* psr
;
2033 /* Skip to the end of the next word in the input stream. */
2038 while (ISALPHA (c
) || c
== '_');
2040 /* Terminate the word. */
2043 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
2044 feature for ease of use and backwards compatibility. */
2045 if (!strncmp (start
, "cpsr", 4))
2046 strncpy (start
, "CPSR", 4);
2047 else if (!strncmp (start
, "spsr", 4))
2048 strncpy (start
, "SPSR", 4);
2050 /* Now locate the word in the psr hash table. */
2051 psr
= (const struct asm_psr
*) hash_find (arm_psr_hsh
, start
);
2053 /* Restore the input stream. */
2056 /* If we found a valid match, advance the
2057 stream pointer past the end of the word. */
2063 /* Parse the input looking for a PSR flag. */
2066 psr_required_here (char ** str
)
2068 char * start
= * str
;
2069 const struct asm_psr
* psr
;
2071 psr
= arm_psr_parse (str
);
2075 /* If this is the SPSR that is being modified, set the R bit. */
2077 inst
.instruction
|= SPSR_BIT
;
2079 /* Set the psr flags in the MSR instruction. */
2080 inst
.instruction
|= psr
->field
<< PSR_SHIFT
;
2085 /* In the few cases where we might be able to accept
2086 something else this error can be overridden. */
2087 inst
.error
= _("flag for {c}psr instruction expected");
2089 /* Restore the start point. */
2095 co_proc_number (char ** str
)
2097 int processor
, pchar
;
2100 skip_whitespace (*str
);
2103 /* The data sheet seems to imply that just a number on its own is valid
2104 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
2106 if ((processor
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CP
].htab
))
2112 if (pchar
>= '0' && pchar
<= '9')
2114 processor
= pchar
- '0';
2115 if (**str
>= '0' && **str
<= '9')
2117 processor
= processor
* 10 + *(*str
)++ - '0';
2120 inst
.error
= _("illegal co-processor number");
2127 inst
.error
= all_reg_maps
[REG_TYPE_CP
].expected
;
2132 inst
.instruction
|= processor
<< 8;
2137 cp_opc_expr (char ** str
, int where
, int length
)
2141 skip_whitespace (* str
);
2143 memset (&expr
, '\0', sizeof (expr
));
2145 if (my_get_expression (&expr
, str
))
2147 if (expr
.X_op
!= O_constant
)
2149 inst
.error
= _("bad or missing expression");
2153 if ((expr
.X_add_number
& ((1 << length
) - 1)) != expr
.X_add_number
)
2155 inst
.error
= _("immediate co-processor expression too large");
2159 inst
.instruction
|= expr
.X_add_number
<< where
;
2164 cp_reg_required_here (char ** str
, int where
)
2167 char * start
= *str
;
2169 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CN
].htab
)) != FAIL
)
2171 inst
.instruction
|= reg
<< where
;
2175 /* In the few cases where we might be able to accept something else
2176 this error can be overridden. */
2177 inst
.error
= all_reg_maps
[REG_TYPE_CN
].expected
;
2179 /* Restore the start point. */
2185 fp_reg_required_here (char ** str
, int where
)
2188 char * start
= * str
;
2190 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_FN
].htab
)) != FAIL
)
2192 inst
.instruction
|= reg
<< where
;
2196 /* In the few cases where we might be able to accept something else
2197 this error can be overridden. */
2198 inst
.error
= all_reg_maps
[REG_TYPE_FN
].expected
;
2200 /* Restore the start point. */
2206 cp_address_offset (char ** str
)
2210 skip_whitespace (* str
);
2212 if (! is_immediate_prefix (**str
))
2214 inst
.error
= _("immediate expression expected");
2220 if (my_get_expression (& inst
.reloc
.exp
, str
))
2223 if (inst
.reloc
.exp
.X_op
== O_constant
)
2225 offset
= inst
.reloc
.exp
.X_add_number
;
2229 inst
.error
= _("co-processor address must be word aligned");
2233 if (offset
> 1023 || offset
< -1023)
2235 inst
.error
= _("offset too large");
2240 inst
.instruction
|= INDEX_UP
;
2244 inst
.instruction
|= offset
>> 2;
2247 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
2253 cp_address_required_here (char ** str
, int wb_ok
)
2264 skip_whitespace (p
);
2266 if ((reg
= reg_required_here (& p
, 16)) == FAIL
)
2269 skip_whitespace (p
);
2275 skip_whitespace (p
);
2279 /* As an extension to the official ARM syntax we allow:
2281 as a short hand for:
2283 inst
.instruction
|= PRE_INDEX
| INDEX_UP
;
2288 if (skip_past_comma (& p
) == FAIL
)
2290 inst
.error
= _("comma expected after closing square bracket");
2294 skip_whitespace (p
);
2301 write_back
= WRITE_BACK
;
2305 inst
.error
= _("pc may not be used in post-increment");
2309 if (cp_address_offset (& p
) == FAIL
)
2313 pre_inc
= PRE_INDEX
| INDEX_UP
;
2319 /* [Rn], {<expr>} */
2322 skip_whitespace (p
);
2324 if (my_get_expression (& inst
.reloc
.exp
, & p
))
2327 if (inst
.reloc
.exp
.X_op
== O_constant
)
2329 option
= inst
.reloc
.exp
.X_add_number
;
2331 if (option
> 255 || option
< 0)
2333 inst
.error
= _("'option' field too large");
2337 skip_whitespace (p
);
2341 inst
.error
= _("'}' expected at end of 'option' field");
2347 inst
.instruction
|= option
;
2348 inst
.instruction
|= INDEX_UP
;
2353 inst
.error
= _("non-constant expressions for 'option' field not supported");
2359 inst
.error
= _("# or { expected after comma");
2365 /* '['Rn, #expr']'[!] */
2367 if (skip_past_comma (& p
) == FAIL
)
2369 inst
.error
= _("pre-indexed expression expected");
2373 pre_inc
= PRE_INDEX
;
2375 if (cp_address_offset (& p
) == FAIL
)
2378 skip_whitespace (p
);
2382 inst
.error
= _("missing ]");
2386 skip_whitespace (p
);
2388 if (wb_ok
&& *p
== '!')
2392 inst
.error
= _("pc may not be used with write-back");
2397 write_back
= WRITE_BACK
;
2403 if (my_get_expression (&inst
.reloc
.exp
, &p
))
2406 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
2407 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
2408 inst
.reloc
.pc_rel
= 1;
2409 inst
.instruction
|= (REG_PC
<< 16);
2410 pre_inc
= PRE_INDEX
;
2413 inst
.instruction
|= write_back
| pre_inc
;
2419 cp_byte_address_offset (char ** str
)
2423 skip_whitespace (* str
);
2425 if (! is_immediate_prefix (**str
))
2427 inst
.error
= _("immediate expression expected");
2433 if (my_get_expression (& inst
.reloc
.exp
, str
))
2436 if (inst
.reloc
.exp
.X_op
== O_constant
)
2438 offset
= inst
.reloc
.exp
.X_add_number
;
2440 if (offset
> 255 || offset
< -255)
2442 inst
.error
= _("offset too large");
2447 inst
.instruction
|= INDEX_UP
;
2451 inst
.instruction
|= offset
;
2454 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM_S2
;
2460 cp_byte_address_required_here (char ** str
)
2471 skip_whitespace (p
);
2473 if ((reg
= reg_required_here (& p
, 16)) == FAIL
)
2476 skip_whitespace (p
);
2482 if (skip_past_comma (& p
) == SUCCESS
)
2485 write_back
= WRITE_BACK
;
2489 inst
.error
= _("pc may not be used in post-increment");
2493 if (cp_byte_address_offset (& p
) == FAIL
)
2497 pre_inc
= PRE_INDEX
| INDEX_UP
;
2501 /* '['Rn, #expr']'[!] */
2503 if (skip_past_comma (& p
) == FAIL
)
2505 inst
.error
= _("pre-indexed expression expected");
2509 pre_inc
= PRE_INDEX
;
2511 if (cp_byte_address_offset (& p
) == FAIL
)
2514 skip_whitespace (p
);
2518 inst
.error
= _("missing ]");
2522 skip_whitespace (p
);
2528 inst
.error
= _("pc may not be used with write-back");
2533 write_back
= WRITE_BACK
;
2539 if (my_get_expression (&inst
.reloc
.exp
, &p
))
2542 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM_S2
;
2543 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
2544 inst
.reloc
.pc_rel
= 1;
2545 inst
.instruction
|= (REG_PC
<< 16);
2546 pre_inc
= PRE_INDEX
;
2549 inst
.instruction
|= write_back
| pre_inc
;
2557 skip_whitespace (str
);
2562 if (my_get_expression (&inst
.reloc
.exp
, &str
))
2563 inst
.reloc
.exp
.X_op
= O_illegal
;
2566 skip_whitespace (str
);
2570 inst
.reloc
.exp
.X_op
= O_illegal
;
2573 if (inst
.reloc
.exp
.X_op
!= O_constant
2574 || inst
.reloc
.exp
.X_add_number
> 255
2575 || inst
.reloc
.exp
.X_add_number
< 0)
2577 inst
.error
= _("Invalid NOP hint");
2581 /* Arcitectural NOP hints are CPSR sets with no bits selected. */
2582 inst
.instruction
&= 0xf0000000;
2583 inst
.instruction
|= 0x0320f000 + inst
.reloc
.exp
.X_add_number
;
2590 do_empty (char * str
)
2592 /* Do nothing really. */
2601 /* Only one syntax. */
2602 skip_whitespace (str
);
2604 if (reg_required_here (&str
, 12) == FAIL
)
2606 inst
.error
= BAD_ARGS
;
2610 if (skip_past_comma (&str
) == FAIL
)
2612 inst
.error
= _("comma expected after register name");
2616 skip_whitespace (str
);
2618 if ( streq (str
, "CPSR")
2619 || streq (str
, "SPSR")
2620 /* Lower case versions for backwards compatibility. */
2621 || streq (str
, "cpsr")
2622 || streq (str
, "spsr"))
2625 /* This is for backwards compatibility with older toolchains. */
2626 else if ( streq (str
, "cpsr_all")
2627 || streq (str
, "spsr_all"))
2631 inst
.error
= _("CPSR or SPSR expected");
2635 if (* str
== 's' || * str
== 'S')
2636 inst
.instruction
|= SPSR_BIT
;
2642 /* Two possible forms:
2643 "{C|S}PSR_<field>, Rm",
2644 "{C|S}PSR_f, #expression". */
2649 skip_whitespace (str
);
2651 if (psr_required_here (& str
) == FAIL
)
2654 if (skip_past_comma (& str
) == FAIL
)
2656 inst
.error
= _("comma missing after psr flags");
2660 skip_whitespace (str
);
2662 if (reg_required_here (& str
, 0) != FAIL
)
2669 if (! is_immediate_prefix (* str
))
2672 _("only a register or immediate value can follow a psr flag");
2679 if (my_get_expression (& inst
.reloc
.exp
, & str
))
2682 _("only a register or immediate value can follow a psr flag");
2686 inst
.instruction
|= INST_IMMEDIATE
;
2688 if (inst
.reloc
.exp
.X_add_symbol
)
2690 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
2691 inst
.reloc
.pc_rel
= 0;
2695 unsigned value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
2697 if (value
== (unsigned) FAIL
)
2699 inst
.error
= _("invalid constant");
2703 inst
.instruction
|= value
;
2710 /* Long Multiply Parser
2711 UMULL RdLo, RdHi, Rm, Rs
2712 SMULL RdLo, RdHi, Rm, Rs
2713 UMLAL RdLo, RdHi, Rm, Rs
2714 SMLAL RdLo, RdHi, Rm, Rs. */
2717 do_mull (char * str
)
2719 int rdlo
, rdhi
, rm
, rs
;
2721 /* Only one format "rdlo, rdhi, rm, rs". */
2722 skip_whitespace (str
);
2724 if ((rdlo
= reg_required_here (&str
, 12)) == FAIL
)
2726 inst
.error
= BAD_ARGS
;
2730 if (skip_past_comma (&str
) == FAIL
2731 || (rdhi
= reg_required_here (&str
, 16)) == FAIL
)
2733 inst
.error
= BAD_ARGS
;
2737 if (skip_past_comma (&str
) == FAIL
2738 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
2740 inst
.error
= BAD_ARGS
;
2744 /* rdhi, rdlo and rm must all be different. */
2745 if (rdlo
== rdhi
|| rdlo
== rm
|| rdhi
== rm
)
2746 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
2748 if (skip_past_comma (&str
) == FAIL
2749 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
2751 inst
.error
= BAD_ARGS
;
2755 if (rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
)
2757 inst
.error
= BAD_PC
;
2769 /* Only one format "rd, rm, rs". */
2770 skip_whitespace (str
);
2772 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
2774 inst
.error
= BAD_ARGS
;
2780 inst
.error
= BAD_PC
;
2784 if (skip_past_comma (&str
) == FAIL
2785 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
2787 inst
.error
= BAD_ARGS
;
2793 inst
.error
= BAD_PC
;
2798 as_tsktsk (_("rd and rm should be different in mul"));
2800 if (skip_past_comma (&str
) == FAIL
2801 || (rm
= reg_required_here (&str
, 8)) == FAIL
)
2803 inst
.error
= BAD_ARGS
;
2809 inst
.error
= BAD_PC
;
2821 /* Only one format "rd, rm, rs, rn". */
2822 skip_whitespace (str
);
2824 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
2826 inst
.error
= BAD_ARGS
;
2832 inst
.error
= BAD_PC
;
2836 if (skip_past_comma (&str
) == FAIL
2837 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
2839 inst
.error
= BAD_ARGS
;
2845 inst
.error
= BAD_PC
;
2850 as_tsktsk (_("rd and rm should be different in mla"));
2852 if (skip_past_comma (&str
) == FAIL
2853 || (rd
= reg_required_here (&str
, 8)) == FAIL
2854 || skip_past_comma (&str
) == FAIL
2855 || (rm
= reg_required_here (&str
, 12)) == FAIL
)
2857 inst
.error
= BAD_ARGS
;
2861 if (rd
== REG_PC
|| rm
== REG_PC
)
2863 inst
.error
= BAD_PC
;
2870 /* Expects *str -> the characters "acc0", possibly with leading blanks.
2871 Advances *str to the next non-alphanumeric.
2872 Returns 0, or else FAIL (in which case sets inst.error).
2874 (In a future XScale, there may be accumulators other than zero.
2875 At that time this routine and its callers can be upgraded to suit.) */
2878 accum0_required_here (char ** str
)
2880 static char buff
[128]; /* Note the address is taken. Hence, static. */
2883 int result
= 0; /* The accum number. */
2885 skip_whitespace (p
);
2887 *str
= p
; /* Advance caller's string pointer too. */
2892 *--p
= 0; /* Aap nul into input buffer at non-alnum. */
2894 if (! ( streq (*str
, "acc0") || streq (*str
, "ACC0")))
2896 sprintf (buff
, _("acc0 expected, not '%.100s'"), *str
);
2901 *p
= c
; /* Unzap. */
2902 *str
= p
; /* Caller's string pointer to after match. */
2907 ldst_extend_v4 (char ** str
)
2916 if (my_get_expression (& inst
.reloc
.exp
, str
))
2919 if (inst
.reloc
.exp
.X_op
== O_constant
)
2921 int value
= inst
.reloc
.exp
.X_add_number
;
2923 if (value
< -255 || value
> 255)
2925 inst
.error
= _("address offset too large");
2935 /* Halfword and signextension instructions have the
2936 immediate value split across bits 11..8 and bits 3..0. */
2937 inst
.instruction
|= (add
| HWOFFSET_IMM
2938 | ((value
>> 4) << 8) | (value
& 0xF));
2942 inst
.instruction
|= HWOFFSET_IMM
;
2943 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
2944 inst
.reloc
.pc_rel
= 0;
2957 if (reg_required_here (str
, 0) == FAIL
)
2960 inst
.instruction
|= add
;
2965 /* Expects **str -> after a comma. May be leading blanks.
2966 Advances *str, recognizing a load mode, and setting inst.instruction.
2967 Returns rn, or else FAIL (in which case may set inst.error
2968 and not advance str)
2970 Note: doesn't know Rd, so no err checks that require such knowledge. */
2973 ld_mode_required_here (char ** string
)
2975 char * str
= * string
;
2979 skip_whitespace (str
);
2985 skip_whitespace (str
);
2987 if ((rn
= reg_required_here (& str
, 16)) == FAIL
)
2990 skip_whitespace (str
);
2996 if (skip_past_comma (& str
) == SUCCESS
)
2998 /* [Rn],... (post inc) */
2999 if (ldst_extend_v4 (&str
) == FAIL
)
3004 skip_whitespace (str
);
3009 inst
.instruction
|= WRITE_BACK
;
3012 inst
.instruction
|= INDEX_UP
| HWOFFSET_IMM
;
3018 if (skip_past_comma (& str
) == FAIL
)
3020 inst
.error
= _("pre-indexed expression expected");
3026 if (ldst_extend_v4 (&str
) == FAIL
)
3029 skip_whitespace (str
);
3031 if (* str
++ != ']')
3033 inst
.error
= _("missing ]");
3037 skip_whitespace (str
);
3042 inst
.instruction
|= WRITE_BACK
;
3046 else if (* str
== '=') /* ldr's "r,=label" syntax */
3047 /* We should never reach here, because <text> = <expression> is
3048 caught gas/read.c read_a_source_file() as a .set operation. */
3050 else /* PC +- 8 bit immediate offset. */
3052 if (my_get_expression (& inst
.reloc
.exp
, & str
))
3055 inst
.instruction
|= HWOFFSET_IMM
; /* The I bit. */
3056 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
3057 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
3058 inst
.reloc
.pc_rel
= 1;
3059 inst
.instruction
|= (REG_PC
<< 16);
3065 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
3071 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
3072 SMLAxy{cond} Rd,Rm,Rs,Rn
3073 SMLAWy{cond} Rd,Rm,Rs,Rn
3074 Error if any register is R15. */
3077 do_smla (char * str
)
3081 skip_whitespace (str
);
3083 if ((rd
= reg_required_here (& str
, 16)) == FAIL
3084 || skip_past_comma (& str
) == FAIL
3085 || (rm
= reg_required_here (& str
, 0)) == FAIL
3086 || skip_past_comma (& str
) == FAIL
3087 || (rs
= reg_required_here (& str
, 8)) == FAIL
3088 || skip_past_comma (& str
) == FAIL
3089 || (rn
= reg_required_here (& str
, 12)) == FAIL
)
3090 inst
.error
= BAD_ARGS
;
3092 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
|| rn
== REG_PC
)
3093 inst
.error
= BAD_PC
;
3099 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
3100 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
3101 Error if any register is R15.
3102 Warning if Rdlo == Rdhi. */
3105 do_smlal (char * str
)
3107 int rdlo
, rdhi
, rm
, rs
;
3109 skip_whitespace (str
);
3111 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
3112 || skip_past_comma (& str
) == FAIL
3113 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
3114 || skip_past_comma (& str
) == FAIL
3115 || (rm
= reg_required_here (& str
, 0)) == FAIL
3116 || skip_past_comma (& str
) == FAIL
3117 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
3119 inst
.error
= BAD_ARGS
;
3123 if (rdlo
== REG_PC
|| rdhi
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
3125 inst
.error
= BAD_PC
;
3130 as_tsktsk (_("rdhi and rdlo must be different"));
3135 /* ARM V5E (El Segundo) signed-multiply (argument parse)
3136 SMULxy{cond} Rd,Rm,Rs
3137 Error if any register is R15. */
3140 do_smul (char * str
)
3144 skip_whitespace (str
);
3146 if ((rd
= reg_required_here (& str
, 16)) == FAIL
3147 || skip_past_comma (& str
) == FAIL
3148 || (rm
= reg_required_here (& str
, 0)) == FAIL
3149 || skip_past_comma (& str
) == FAIL
3150 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
3151 inst
.error
= BAD_ARGS
;
3153 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
3154 inst
.error
= BAD_PC
;
3160 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
3161 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
3162 Error if any register is R15. */
3165 do_qadd (char * str
)
3169 skip_whitespace (str
);
3171 if ((rd
= reg_required_here (& str
, 12)) == FAIL
3172 || skip_past_comma (& str
) == FAIL
3173 || (rm
= reg_required_here (& str
, 0)) == FAIL
3174 || skip_past_comma (& str
) == FAIL
3175 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
3176 inst
.error
= BAD_ARGS
;
3178 else if (rd
== REG_PC
|| rm
== REG_PC
|| rn
== REG_PC
)
3179 inst
.error
= BAD_PC
;
3185 /* ARM V5E (el Segundo)
3186 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3187 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3189 These are equivalent to the XScale instructions MAR and MRA,
3190 respectively, when coproc == 0, opcode == 0, and CRm == 0.
3192 Result unpredicatable if Rd or Rn is R15. */
3195 do_co_reg2c (char * str
)
3199 skip_whitespace (str
);
3201 if (co_proc_number (& str
) == FAIL
)
3204 inst
.error
= BAD_ARGS
;
3208 if (skip_past_comma (& str
) == FAIL
3209 || cp_opc_expr (& str
, 4, 4) == FAIL
)
3212 inst
.error
= BAD_ARGS
;
3216 if (skip_past_comma (& str
) == FAIL
3217 || (rd
= reg_required_here (& str
, 12)) == FAIL
)
3220 inst
.error
= BAD_ARGS
;
3224 if (skip_past_comma (& str
) == FAIL
3225 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
3228 inst
.error
= BAD_ARGS
;
3232 /* Unpredictable result if rd or rn is R15. */
3233 if (rd
== REG_PC
|| rn
== REG_PC
)
3235 (_("Warning: instruction unpredictable when using r15"));
3237 if (skip_past_comma (& str
) == FAIL
3238 || cp_reg_required_here (& str
, 0) == FAIL
)
3241 inst
.error
= BAD_ARGS
;
3248 /* ARM V5 count-leading-zeroes instruction (argument parse)
3249 CLZ{<cond>} <Rd>, <Rm>
3250 Condition defaults to COND_ALWAYS.
3251 Error if Rd or Rm are R15. */
3258 skip_whitespace (str
);
3260 if (((rd
= reg_required_here (& str
, 12)) == FAIL
)
3261 || (skip_past_comma (& str
) == FAIL
)
3262 || ((rm
= reg_required_here (& str
, 0)) == FAIL
))
3263 inst
.error
= BAD_ARGS
;
3265 else if (rd
== REG_PC
|| rm
== REG_PC
)
3266 inst
.error
= BAD_PC
;
3272 /* ARM V5 (argument parse)
3273 LDC2{L} <coproc>, <CRd>, <addressing mode>
3274 STC2{L} <coproc>, <CRd>, <addressing mode>
3275 Instruction is not conditional, and has 0xf in the condition field.
3276 Otherwise, it's the same as LDC/STC. */
3279 do_lstc2 (char * str
)
3281 skip_whitespace (str
);
3283 if (co_proc_number (& str
) == FAIL
)
3286 inst
.error
= BAD_ARGS
;
3288 else if (skip_past_comma (& str
) == FAIL
3289 || cp_reg_required_here (& str
, 12) == FAIL
)
3292 inst
.error
= BAD_ARGS
;
3294 else if (skip_past_comma (& str
) == FAIL
3295 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
3298 inst
.error
= BAD_ARGS
;
3304 /* ARM V5 (argument parse)
3305 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
3306 Instruction is not conditional, and has 0xf in the condition field.
3307 Otherwise, it's the same as CDP. */
3310 do_cdp2 (char * str
)
3312 skip_whitespace (str
);
3314 if (co_proc_number (& str
) == FAIL
)
3317 inst
.error
= BAD_ARGS
;
3321 if (skip_past_comma (& str
) == FAIL
3322 || cp_opc_expr (& str
, 20,4) == FAIL
)
3325 inst
.error
= BAD_ARGS
;
3329 if (skip_past_comma (& str
) == FAIL
3330 || cp_reg_required_here (& str
, 12) == FAIL
)
3333 inst
.error
= BAD_ARGS
;
3337 if (skip_past_comma (& str
) == FAIL
3338 || cp_reg_required_here (& str
, 16) == FAIL
)
3341 inst
.error
= BAD_ARGS
;
3345 if (skip_past_comma (& str
) == FAIL
3346 || cp_reg_required_here (& str
, 0) == FAIL
)
3349 inst
.error
= BAD_ARGS
;
3353 if (skip_past_comma (& str
) == SUCCESS
)
3355 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
3358 inst
.error
= BAD_ARGS
;
3366 /* ARM V5 (argument parse)
3367 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3368 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3369 Instruction is not conditional, and has 0xf in the condition field.
3370 Otherwise, it's the same as MCR/MRC. */
3373 do_co_reg2 (char * str
)
3375 skip_whitespace (str
);
3377 if (co_proc_number (& str
) == FAIL
)
3380 inst
.error
= BAD_ARGS
;
3384 if (skip_past_comma (& str
) == FAIL
3385 || cp_opc_expr (& str
, 21, 3) == FAIL
)
3388 inst
.error
= BAD_ARGS
;
3392 if (skip_past_comma (& str
) == FAIL
3393 || reg_required_here (& str
, 12) == FAIL
)
3396 inst
.error
= BAD_ARGS
;
3400 if (skip_past_comma (& str
) == FAIL
3401 || cp_reg_required_here (& str
, 16) == FAIL
)
3404 inst
.error
= BAD_ARGS
;
3408 if (skip_past_comma (& str
) == FAIL
3409 || cp_reg_required_here (& str
, 0) == FAIL
)
3412 inst
.error
= BAD_ARGS
;
3416 if (skip_past_comma (& str
) == SUCCESS
)
3418 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
3421 inst
.error
= BAD_ARGS
;
3434 skip_whitespace (str
);
3436 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
3438 inst
.error
= BAD_ARGS
;
3442 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
3444 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
3449 /* ARM v5TEJ. Jump to Jazelle code. */
3456 skip_whitespace (str
);
3458 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
3460 inst
.error
= BAD_ARGS
;
3464 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
3466 as_tsktsk (_("use of r15 in bxj is not really useful"));
3471 /* ARM V6 umaal (argument parse). */
3474 do_umaal (char * str
)
3476 int rdlo
, rdhi
, rm
, rs
;
3478 skip_whitespace (str
);
3479 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
3480 || skip_past_comma (& str
) == FAIL
3481 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
3482 || skip_past_comma (& str
) == FAIL
3483 || (rm
= reg_required_here (& str
, 0)) == FAIL
3484 || skip_past_comma (& str
) == FAIL
3485 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
3487 inst
.error
= BAD_ARGS
;
3491 if (rdlo
== REG_PC
|| rdhi
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
3493 inst
.error
= BAD_PC
;
3500 /* ARM V6 strex (argument parse). */
3503 do_strex (char * str
)
3507 /* Parse Rd, Rm,. */
3508 skip_whitespace (str
);
3509 if ((rd
= reg_required_here (& str
, 12)) == FAIL
3510 || skip_past_comma (& str
) == FAIL
3511 || (rm
= reg_required_here (& str
, 0)) == FAIL
3512 || skip_past_comma (& str
) == FAIL
)
3514 inst
.error
= BAD_ARGS
;
3517 if (rd
== REG_PC
|| rm
== REG_PC
)
3519 inst
.error
= BAD_PC
;
3524 inst
.error
= _("Rd equal to Rm or Rn yields unpredictable results");
3528 /* Skip past '['. */
3529 if ((strlen (str
) >= 1)
3530 && strncmp (str
, "[", 1) == 0)
3533 skip_whitespace (str
);
3536 if ((rn
= reg_required_here (& str
, 16)) == FAIL
)
3538 inst
.error
= BAD_ARGS
;
3541 else if (rn
== REG_PC
)
3543 inst
.error
= BAD_PC
;
3548 inst
.error
= _("Rd equal to Rm or Rn yields unpredictable results");
3551 skip_whitespace (str
);
3553 /* Skip past ']'. */
3554 if ((strlen (str
) >= 1)
3555 && strncmp (str
, "]", 1) == 0)
3561 /* KIND indicates what kind of shifts are accepted. */
3564 decode_shift (char ** str
, int kind
)
3566 const struct asm_shift_name
* shift
;
3570 skip_whitespace (* str
);
3572 for (p
= * str
; ISALPHA (* p
); p
++)
3577 inst
.error
= _("shift expression expected");
3583 shift
= (const struct asm_shift_name
*) hash_find (arm_shift_hsh
, * str
);
3588 inst
.error
= _("shift expression expected");
3592 assert (shift
->properties
->index
== shift_properties
[shift
->properties
->index
].index
);
3594 if (kind
== SHIFT_LSL_OR_ASR_IMMEDIATE
3595 && shift
->properties
->index
!= SHIFT_LSL
3596 && shift
->properties
->index
!= SHIFT_ASR
)
3598 inst
.error
= _("'LSL' or 'ASR' required");
3601 else if (kind
== SHIFT_LSL_IMMEDIATE
3602 && shift
->properties
->index
!= SHIFT_LSL
)
3604 inst
.error
= _("'LSL' required");
3607 else if (kind
== SHIFT_ASR_IMMEDIATE
3608 && shift
->properties
->index
!= SHIFT_ASR
)
3610 inst
.error
= _("'ASR' required");
3614 if (shift
->properties
->index
== SHIFT_RRX
)
3617 inst
.instruction
|= shift
->properties
->bit_field
;
3621 skip_whitespace (p
);
3623 if (kind
== NO_SHIFT_RESTRICT
&& reg_required_here (& p
, 8) != FAIL
)
3625 inst
.instruction
|= shift
->properties
->bit_field
| SHIFT_BY_REG
;
3629 else if (! is_immediate_prefix (* p
))
3631 inst
.error
= (NO_SHIFT_RESTRICT
3632 ? _("shift requires register or #expression")
3633 : _("shift requires #expression"));
3641 if (my_get_expression (& inst
.reloc
.exp
, & p
))
3644 /* Validate some simple #expressions. */
3645 if (inst
.reloc
.exp
.X_op
== O_constant
)
3647 unsigned num
= inst
.reloc
.exp
.X_add_number
;
3649 /* Reject operations greater than 32. */
3651 /* Reject a shift of 0 unless the mode allows it. */
3652 || (num
== 0 && shift
->properties
->allows_0
== 0)
3653 /* Reject a shift of 32 unless the mode allows it. */
3654 || (num
== 32 && shift
->properties
->allows_32
== 0)
3657 /* As a special case we allow a shift of zero for
3658 modes that do not support it to be recoded as an
3659 logical shift left of zero (ie nothing). We warn
3660 about this though. */
3663 as_warn (_("shift of 0 ignored."));
3664 shift
= & shift_names
[0];
3665 assert (shift
->properties
->index
== SHIFT_LSL
);
3669 inst
.error
= _("invalid immediate shift");
3674 /* Shifts of 32 are encoded as 0, for those shifts that
3679 inst
.instruction
|= (num
<< 7) | shift
->properties
->bit_field
;
3683 inst
.reloc
.type
= BFD_RELOC_ARM_SHIFT_IMM
;
3684 inst
.reloc
.pc_rel
= 0;
3685 inst
.instruction
|= shift
->properties
->bit_field
;
3693 do_sat (char ** str
, int bias
)
3698 skip_whitespace (*str
);
3700 /* Parse <Rd>, field. */
3701 if ((rd
= reg_required_here (str
, 12)) == FAIL
3702 || skip_past_comma (str
) == FAIL
)
3704 inst
.error
= BAD_ARGS
;
3709 inst
.error
= BAD_PC
;
3713 /* Parse #<immed>, field. */
3714 if (is_immediate_prefix (**str
))
3718 inst
.error
= _("immediate expression expected");
3721 if (my_get_expression (&expr
, str
))
3723 inst
.error
= _("bad expression");
3726 if (expr
.X_op
!= O_constant
)
3728 inst
.error
= _("constant expression expected");
3731 if (expr
.X_add_number
+ bias
< 0
3732 || expr
.X_add_number
+ bias
> 31)
3734 inst
.error
= _("immediate value out of range");
3737 inst
.instruction
|= (expr
.X_add_number
+ bias
) << 16;
3738 if (skip_past_comma (str
) == FAIL
)
3740 inst
.error
= BAD_ARGS
;
3744 /* Parse <Rm> field. */
3745 if ((rm
= reg_required_here (str
, 0)) == FAIL
)
3747 inst
.error
= BAD_ARGS
;
3752 inst
.error
= BAD_PC
;
3756 if (skip_past_comma (str
) == SUCCESS
)
3757 decode_shift (str
, SHIFT_LSL_OR_ASR_IMMEDIATE
);
3760 /* ARM V6 ssat (argument parse). */
3763 do_ssat (char * str
)
3765 do_sat (&str
, /*bias=*/-1);
3769 /* ARM V6 usat (argument parse). */
3772 do_usat (char * str
)
3774 do_sat (&str
, /*bias=*/0);
3779 do_sat16 (char ** str
, int bias
)
3784 skip_whitespace (*str
);
3786 /* Parse the <Rd> field. */
3787 if ((rd
= reg_required_here (str
, 12)) == FAIL
3788 || skip_past_comma (str
) == FAIL
)
3790 inst
.error
= BAD_ARGS
;
3795 inst
.error
= BAD_PC
;
3799 /* Parse #<immed>, field. */
3800 if (is_immediate_prefix (**str
))
3804 inst
.error
= _("immediate expression expected");
3807 if (my_get_expression (&expr
, str
))
3809 inst
.error
= _("bad expression");
3812 if (expr
.X_op
!= O_constant
)
3814 inst
.error
= _("constant expression expected");
3817 if (expr
.X_add_number
+ bias
< 0
3818 || expr
.X_add_number
+ bias
> 15)
3820 inst
.error
= _("immediate value out of range");
3823 inst
.instruction
|= (expr
.X_add_number
+ bias
) << 16;
3824 if (skip_past_comma (str
) == FAIL
)
3826 inst
.error
= BAD_ARGS
;
3830 /* Parse <Rm> field. */
3831 if ((rm
= reg_required_here (str
, 0)) == FAIL
)
3833 inst
.error
= BAD_ARGS
;
3838 inst
.error
= BAD_PC
;
3843 /* ARM V6 ssat16 (argument parse). */
3846 do_ssat16 (char * str
)
3848 do_sat16 (&str
, /*bias=*/-1);
3853 do_usat16 (char * str
)
3855 do_sat16 (&str
, /*bias=*/0);
3860 do_cps_mode (char ** str
)
3864 skip_whitespace (*str
);
3866 if (! is_immediate_prefix (**str
))
3868 inst
.error
= _("immediate expression expected");
3872 (*str
)++; /* Strip off the immediate signifier. */
3873 if (my_get_expression (&expr
, str
))
3875 inst
.error
= _("bad expression");
3879 if (expr
.X_op
!= O_constant
)
3881 inst
.error
= _("constant expression expected");
3885 /* The mode is a 5 bit field. Valid values are 0-31. */
3886 if (((unsigned) expr
.X_add_number
) > 31
3887 || (inst
.reloc
.exp
.X_add_number
) < 0)
3889 inst
.error
= _("invalid constant");
3893 inst
.instruction
|= expr
.X_add_number
;
3896 /* ARM V6 srs (argument parse). */
3902 skip_whitespace (str
);
3903 exclam
= strchr (str
, '!');
3911 inst
.instruction
|= WRITE_BACK
;
3917 /* ARM V6 SMMUL (argument parse). */
3920 do_smmul (char * str
)
3924 skip_whitespace (str
);
3925 if ((rd
= reg_required_here (&str
, 16)) == FAIL
3926 || skip_past_comma (&str
) == FAIL
3927 || (rm
= reg_required_here (&str
, 0)) == FAIL
3928 || skip_past_comma (&str
) == FAIL
3929 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
3931 inst
.error
= BAD_ARGS
;
3939 inst
.error
= BAD_PC
;
3946 /* ARM V6 SMLALD (argument parse). */
3949 do_smlald (char * str
)
3951 int rdlo
, rdhi
, rm
, rs
;
3953 skip_whitespace (str
);
3954 if ((rdlo
= reg_required_here (&str
, 12)) == FAIL
3955 || skip_past_comma (&str
) == FAIL
3956 || (rdhi
= reg_required_here (&str
, 16)) == FAIL
3957 || skip_past_comma (&str
) == FAIL
3958 || (rm
= reg_required_here (&str
, 0)) == FAIL
3959 || skip_past_comma (&str
) == FAIL
3960 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
3962 inst
.error
= BAD_ARGS
;
3971 inst
.error
= BAD_PC
;
3978 /* ARM V6 SMLAD (argument parse). Signed multiply accumulate dual.
3979 smlad{x}{<cond>} Rd, Rm, Rs, Rn */
3982 do_smlad (char * str
)
3986 skip_whitespace (str
);
3987 if ((rd
= reg_required_here (&str
, 16)) == FAIL
3988 || skip_past_comma (&str
) == FAIL
3989 || (rm
= reg_required_here (&str
, 0)) == FAIL
3990 || skip_past_comma (&str
) == FAIL
3991 || (rs
= reg_required_here (&str
, 8)) == FAIL
3992 || skip_past_comma (&str
) == FAIL
3993 || (rn
= reg_required_here (&str
, 12)) == FAIL
)
3995 inst
.error
= BAD_ARGS
;
4004 inst
.error
= BAD_PC
;
4011 /* Returns true if the endian-specifier indicates big-endianness. */
4014 do_endian_specifier (char * str
)
4018 skip_whitespace (str
);
4019 if (strlen (str
) < 2)
4020 inst
.error
= _("missing endian specifier");
4021 else if (strncasecmp (str
, "BE", 2) == 0)
4026 else if (strncasecmp (str
, "LE", 2) == 0)
4029 inst
.error
= _("valid endian specifiers are be or le");
4036 /* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
4037 preserving the other bits.
4039 setend <endian_specifier>, where <endian_specifier> is either
4043 do_setend (char * str
)
4045 if (do_endian_specifier (str
))
4046 inst
.instruction
|= 0x200;
4051 SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
4052 Condition defaults to COND_ALWAYS.
4053 Error if any register uses R15. */
4056 do_sxth (char * str
)
4060 int rotation_clear_mask
= 0xfffff3ff;
4061 int rotation_eight_mask
= 0x00000400;
4062 int rotation_sixteen_mask
= 0x00000800;
4063 int rotation_twenty_four_mask
= 0x00000c00;
4065 skip_whitespace (str
);
4066 if ((rd
= reg_required_here (&str
, 12)) == FAIL
4067 || skip_past_comma (&str
) == FAIL
4068 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4070 inst
.error
= BAD_ARGS
;
4074 else if (rd
== REG_PC
|| rm
== REG_PC
)
4076 inst
.error
= BAD_PC
;
4080 /* Zero out the rotation field. */
4081 inst
.instruction
&= rotation_clear_mask
;
4083 /* Check for lack of optional rotation field. */
4084 if (skip_past_comma (&str
) == FAIL
)
4090 /* Move past 'ROR'. */
4091 skip_whitespace (str
);
4092 if (strncasecmp (str
, "ROR", 3) == 0)
4096 inst
.error
= _("missing rotation field after comma");
4100 /* Get the immediate constant. */
4101 skip_whitespace (str
);
4102 if (is_immediate_prefix (* str
))
4106 inst
.error
= _("immediate expression expected");
4110 if (my_get_expression (&expr
, &str
))
4112 inst
.error
= _("bad expression");
4116 if (expr
.X_op
!= O_constant
)
4118 inst
.error
= _("constant expression expected");
4122 switch (expr
.X_add_number
)
4125 /* Rotation field has already been zeroed. */
4128 inst
.instruction
|= rotation_eight_mask
;
4132 inst
.instruction
|= rotation_sixteen_mask
;
4136 inst
.instruction
|= rotation_twenty_four_mask
;
4140 inst
.error
= _("rotation can be 8, 16, 24 or 0 when field is ommited");
4147 /* ARM V6 SXTAH extracts a 16-bit value from a register, sign
4148 extends it to 32-bits, and adds the result to a value in another
4149 register. You can specify a rotation by 0, 8, 16, or 24 bits
4150 before extracting the 16-bit value.
4151 SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
4152 Condition defaults to COND_ALWAYS.
4153 Error if any register uses R15. */
4156 do_sxtah (char * str
)
4160 int rotation_clear_mask
= 0xfffff3ff;
4161 int rotation_eight_mask
= 0x00000400;
4162 int rotation_sixteen_mask
= 0x00000800;
4163 int rotation_twenty_four_mask
= 0x00000c00;
4165 skip_whitespace (str
);
4166 if ((rd
= reg_required_here (&str
, 12)) == FAIL
4167 || skip_past_comma (&str
) == FAIL
4168 || (rn
= reg_required_here (&str
, 16)) == FAIL
4169 || skip_past_comma (&str
) == FAIL
4170 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4172 inst
.error
= BAD_ARGS
;
4176 else if (rd
== REG_PC
|| rn
== REG_PC
|| rm
== REG_PC
)
4178 inst
.error
= BAD_PC
;
4182 /* Zero out the rotation field. */
4183 inst
.instruction
&= rotation_clear_mask
;
4185 /* Check for lack of optional rotation field. */
4186 if (skip_past_comma (&str
) == FAIL
)
4192 /* Move past 'ROR'. */
4193 skip_whitespace (str
);
4194 if (strncasecmp (str
, "ROR", 3) == 0)
4198 inst
.error
= _("missing rotation field after comma");
4202 /* Get the immediate constant. */
4203 skip_whitespace (str
);
4204 if (is_immediate_prefix (* str
))
4208 inst
.error
= _("immediate expression expected");
4212 if (my_get_expression (&expr
, &str
))
4214 inst
.error
= _("bad expression");
4218 if (expr
.X_op
!= O_constant
)
4220 inst
.error
= _("constant expression expected");
4224 switch (expr
.X_add_number
)
4227 /* Rotation field has already been zeroed. */
4231 inst
.instruction
|= rotation_eight_mask
;
4235 inst
.instruction
|= rotation_sixteen_mask
;
4239 inst
.instruction
|= rotation_twenty_four_mask
;
4243 inst
.error
= _("rotation can be 8, 16, 24 or 0 when field is ommited");
4251 /* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
4252 word at the specified address and the following word
4254 Unconditionally executed.
4255 Error if Rn is R15. */
4262 skip_whitespace (str
);
4264 if ((rn
= reg_required_here (&str
, 16)) == FAIL
)
4269 inst
.error
= BAD_PC
;
4273 skip_whitespace (str
);
4277 inst
.instruction
|= WRITE_BACK
;
4283 /* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
4284 register (argument parse).
4286 Condition defaults to COND_ALWAYS.
4287 Error if Rd or Rm are R15. */
4294 skip_whitespace (str
);
4296 if ((rd
= reg_required_here (&str
, 12)) == FAIL
4297 || skip_past_comma (&str
) == FAIL
4298 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4299 inst
.error
= BAD_ARGS
;
4301 else if (rd
== REG_PC
|| rm
== REG_PC
)
4302 inst
.error
= BAD_PC
;
4308 /* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
4309 QADD16{<cond>} <Rd>, <Rn>, <Rm>
4310 Condition defaults to COND_ALWAYS.
4311 Error if Rd, Rn or Rm are R15. */
4314 do_qadd16 (char * str
)
4318 skip_whitespace (str
);
4320 if ((rd
= reg_required_here (&str
, 12)) == FAIL
4321 || skip_past_comma (&str
) == FAIL
4322 || (rn
= reg_required_here (&str
, 16)) == FAIL
4323 || skip_past_comma (&str
) == FAIL
4324 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4325 inst
.error
= BAD_ARGS
;
4327 else if (rd
== REG_PC
|| rm
== REG_PC
|| rn
== REG_PC
)
4328 inst
.error
= BAD_PC
;
4335 do_pkh_core (char * str
, int shift
)
4339 skip_whitespace (str
);
4340 if (((rd
= reg_required_here (&str
, 12)) == FAIL
)
4341 || (skip_past_comma (&str
) == FAIL
)
4342 || ((rn
= reg_required_here (&str
, 16)) == FAIL
)
4343 || (skip_past_comma (&str
) == FAIL
)
4344 || ((rm
= reg_required_here (&str
, 0)) == FAIL
))
4346 inst
.error
= BAD_ARGS
;
4350 else if (rd
== REG_PC
|| rn
== REG_PC
|| rm
== REG_PC
)
4352 inst
.error
= BAD_PC
;
4356 /* Check for optional shift immediate constant. */
4357 if (skip_past_comma (&str
) == FAIL
)
4359 if (shift
== SHIFT_ASR_IMMEDIATE
)
4361 /* If the shift specifier is ommited, turn the instruction
4362 into pkhbt rd, rm, rn. First, switch the instruction
4363 code, and clear the rn and rm fields. */
4364 inst
.instruction
&= 0xfff0f010;
4365 /* Now, re-encode the registers. */
4366 inst
.instruction
|= (rm
<< 16) | rn
;
4371 decode_shift (&str
, shift
);
4374 /* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
4375 PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
4376 Condition defaults to COND_ALWAYS.
4377 Error if Rd, Rn or Rm are R15. */
4380 do_pkhbt (char * str
)
4382 do_pkh_core (str
, SHIFT_LSL_IMMEDIATE
);
4385 /* ARM V6 PKHTB (Argument Parse). */
4388 do_pkhtb (char * str
)
4390 do_pkh_core (str
, SHIFT_ASR_IMMEDIATE
);
4393 /* ARM V6 Load Register Exclusive instruction (argument parse).
4394 LDREX{,B,D,H}{<cond>} <Rd, [<Rn>]
4395 Condition defaults to COND_ALWAYS.
4396 Error if Rd or Rn are R15.
4397 See ARMARMv6 A4.1.27: LDREX. */
4400 do_ldrex (char * str
)
4404 skip_whitespace (str
);
4407 if (((rd
= reg_required_here (&str
, 12)) == FAIL
)
4408 || (skip_past_comma (&str
) == FAIL
))
4410 inst
.error
= BAD_ARGS
;
4413 else if (rd
== REG_PC
)
4415 inst
.error
= BAD_PC
;
4418 skip_whitespace (str
);
4420 /* Skip past '['. */
4421 if ((strlen (str
) >= 1)
4422 &&strncmp (str
, "[", 1) == 0)
4424 skip_whitespace (str
);
4427 if ((rn
= reg_required_here (&str
, 16)) == FAIL
)
4429 inst
.error
= BAD_ARGS
;
4432 else if (rn
== REG_PC
)
4434 inst
.error
= BAD_PC
;
4437 skip_whitespace (str
);
4439 /* Skip past ']'. */
4440 if ((strlen (str
) >= 1)
4441 && strncmp (str
, "]", 1) == 0)
4447 /* ARM V6 change processor state instruction (argument parse)
4448 CPS, CPSIE, CSPID . */
4458 do_cps_flags (char ** str
, int thumb_p
)
4463 unsigned long arm_value
;
4464 unsigned long thumb_value
;
4466 static struct cps_flag flag_table
[] =
4475 skip_whitespace (*str
);
4477 /* Get the a, f and i flags. */
4478 while (**str
&& **str
!= ',')
4481 struct cps_flag
*q
= flag_table
+ sizeof (flag_table
)/sizeof (*p
);
4483 for (p
= flag_table
; p
< q
; ++p
)
4484 if (strncasecmp (*str
, &p
->character
, 1) == 0)
4486 inst
.instruction
|= (thumb_p
? p
->thumb_value
: p
->arm_value
);
4492 inst
.error
= _("unrecognized flag");
4499 inst
.error
= _("no 'a', 'i', or 'f' flags for 'cps'");
4503 do_cpsi (char * str
)
4505 do_cps_flags (&str
, /*thumb_p=*/0);
4507 if (skip_past_comma (&str
) == SUCCESS
)
4509 skip_whitespace (str
);
4515 /* THUMB V5 breakpoint instruction (argument parse)
4519 do_t_bkpt (char * str
)
4522 unsigned long number
;
4524 skip_whitespace (str
);
4526 /* Allow optional leading '#'. */
4527 if (is_immediate_prefix (*str
))
4530 memset (& expr
, '\0', sizeof (expr
));
4531 if (my_get_expression (& expr
, & str
)
4532 || (expr
.X_op
!= O_constant
4533 /* As a convenience we allow 'bkpt' without an operand. */
4534 && expr
.X_op
!= O_absent
))
4536 inst
.error
= _("bad expression");
4540 number
= expr
.X_add_number
;
4542 /* Check it fits an 8 bit unsigned. */
4543 if (number
!= (number
& 0xff))
4545 inst
.error
= _("immediate value out of range");
4549 inst
.instruction
|= number
;
4554 static bfd_reloc_code_real_type
4555 arm_parse_reloc (void)
4564 bfd_reloc_code_real_type reloc
;
4568 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
4569 MAP ("(got)", BFD_RELOC_ARM_GOT32
),
4570 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF
),
4571 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
4572 branch instructions generated by GCC for PLT relocs. */
4573 MAP ("(plt)", BFD_RELOC_ARM_PLT32
),
4574 MAP ("(target1)", BFD_RELOC_ARM_TARGET1
),
4575 MAP ("(sbrel)", BFD_RELOC_ARM_SBREL32
),
4576 MAP ("(target2)", BFD_RELOC_ARM_TARGET2
),
4577 { NULL
, 0, BFD_RELOC_UNUSED
}
4581 for (i
= 0, ip
= input_line_pointer
;
4582 i
< sizeof (id
) && (ISALNUM (*ip
) || ISPUNCT (*ip
));
4584 id
[i
] = TOLOWER (*ip
);
4586 for (i
= 0; reloc_map
[i
].str
; i
++)
4587 if (strncmp (id
, reloc_map
[i
].str
, reloc_map
[i
].len
) == 0)
4590 input_line_pointer
+= reloc_map
[i
].len
;
4592 return reloc_map
[i
].reloc
;
4595 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
4596 Expects inst.instruction is set for BLX(1).
4597 Note: this is cloned from do_branch, and the reloc changed to be a
4598 new one that can cope with setting one extra bit (the H bit). */
4601 do_branch25 (char * str
)
4603 if (my_get_expression (& inst
.reloc
.exp
, & str
))
4610 /* ScottB: February 5, 1998 */
4611 /* Check to see of PLT32 reloc required for the instruction. */
4613 /* arm_parse_reloc() works on input_line_pointer.
4614 We actually want to parse the operands to the branch instruction
4615 passed in 'str'. Save the input pointer and restore it later. */
4616 save_in
= input_line_pointer
;
4617 input_line_pointer
= str
;
4619 if (inst
.reloc
.exp
.X_op
== O_symbol
4621 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
4623 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
4624 inst
.reloc
.pc_rel
= 0;
4625 /* Modify str to point to after parsed operands, otherwise
4626 end_of_line() will complain about the (PLT) left in str. */
4627 str
= input_line_pointer
;
4631 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
4632 inst
.reloc
.pc_rel
= 1;
4635 input_line_pointer
= save_in
;
4638 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
4639 inst
.reloc
.pc_rel
= 1;
4640 #endif /* OBJ_ELF */
4645 /* ARM V5 branch-link-exchange instruction (argument parse)
4646 BLX <target_addr> ie BLX(1)
4647 BLX{<condition>} <Rm> ie BLX(2)
4648 Unfortunately, there are two different opcodes for this mnemonic.
4649 So, the insns[].value is not used, and the code here zaps values
4650 into inst.instruction.
4651 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
4659 skip_whitespace (mystr
);
4660 rm
= reg_required_here (& mystr
, 0);
4662 /* The above may set inst.error. Ignore his opinion. */
4667 /* Arg is a register.
4668 Use the condition code our caller put in inst.instruction.
4669 Pass ourselves off as a BX with a funny opcode. */
4670 inst
.instruction
|= 0x012fff30;
4675 /* This must be is BLX <target address>, no condition allowed. */
4676 if (inst
.instruction
!= COND_ALWAYS
)
4678 inst
.error
= BAD_COND
;
4682 inst
.instruction
= 0xfafffffe;
4684 /* Process like a B/BL, but with a different reloc.
4685 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
4690 /* ARM V5 Thumb BLX (argument parse)
4691 BLX <target_addr> which is BLX(1)
4692 BLX <Rm> which is BLX(2)
4693 Unfortunately, there are two different opcodes for this mnemonic.
4694 So, the tinsns[].value is not used, and the code here zaps values
4695 into inst.instruction. */
4698 do_t_blx (char * str
)
4703 skip_whitespace (mystr
);
4704 inst
.instruction
= 0x4780;
4706 /* Note that this call is to the ARM register recognizer. BLX(2)
4707 uses the ARM register space, not the Thumb one, so a call to
4708 thumb_reg() would be wrong. */
4709 rm
= reg_required_here (& mystr
, 3);
4714 /* It's BLX(2). The .instruction was zapped with rm & is final. */
4719 /* No ARM register. This must be BLX(1). Change the .instruction. */
4720 inst
.instruction
= 0xf7ffeffe;
4723 if (my_get_expression (& inst
.reloc
.exp
, & mystr
))
4726 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BLX
;
4727 inst
.reloc
.pc_rel
= 1;
4730 end_of_line (mystr
);
4733 /* ARM V5 breakpoint instruction (argument parse)
4734 BKPT <16 bit unsigned immediate>
4735 Instruction is not conditional.
4736 The bit pattern given in insns[] has the COND_ALWAYS condition,
4737 and it is an error if the caller tried to override that. */
4740 do_bkpt (char * str
)
4743 unsigned long number
;
4745 skip_whitespace (str
);
4747 /* Allow optional leading '#'. */
4748 if (is_immediate_prefix (* str
))
4751 memset (& expr
, '\0', sizeof (expr
));
4753 if (my_get_expression (& expr
, & str
)
4754 || (expr
.X_op
!= O_constant
4755 /* As a convenience we allow 'bkpt' without an operand. */
4756 && expr
.X_op
!= O_absent
))
4758 inst
.error
= _("bad expression");
4762 number
= expr
.X_add_number
;
4764 /* Check it fits a 16 bit unsigned. */
4765 if (number
!= (number
& 0xffff))
4767 inst
.error
= _("immediate value out of range");
4771 /* Top 12 of 16 bits to bits 19:8. */
4772 inst
.instruction
|= (number
& 0xfff0) << 4;
4774 /* Bottom 4 of 16 bits to bits 3:0. */
4775 inst
.instruction
|= number
& 0xf;
4780 /* THUMB CPS instruction (argument parse). */
4783 do_t_cps (char * str
)
4785 do_cps_flags (&str
, /*thumb_p=*/1);
4789 /* Parse and validate that a register is of the right form, this saves
4790 repeated checking of this information in many similar cases.
4791 Unlike the 32-bit case we do not insert the register into the opcode
4792 here, since the position is often unknown until the full instruction
4796 thumb_reg (char ** strp
, int hi_lo
)
4800 if ((reg
= reg_required_here (strp
, -1)) == FAIL
)
4808 inst
.error
= _("lo register required");
4816 inst
.error
= _("hi register required");
4829 thumb_mov_compare (char * str
, int move
)
4833 skip_whitespace (str
);
4835 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
4836 || skip_past_comma (&str
) == FAIL
)
4839 inst
.error
= BAD_ARGS
;
4843 if (move
!= THUMB_CPY
&& is_immediate_prefix (*str
))
4846 if (my_get_expression (&inst
.reloc
.exp
, &str
))
4849 else if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
4854 if (move
!= THUMB_CPY
&& Rs
< 8 && Rd
< 8)
4856 if (move
== THUMB_MOVE
)
4857 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
4858 since a MOV instruction produces unpredictable results. */
4859 inst
.instruction
= T_OPCODE_ADD_I3
;
4861 inst
.instruction
= T_OPCODE_CMP_LR
;
4862 inst
.instruction
|= Rd
| (Rs
<< 3);
4866 if (move
== THUMB_MOVE
)
4867 inst
.instruction
= T_OPCODE_MOV_HR
;
4868 else if (move
!= THUMB_CPY
)
4869 inst
.instruction
= T_OPCODE_CMP_HR
;
4872 inst
.instruction
|= THUMB_H1
;
4875 inst
.instruction
|= THUMB_H2
;
4877 inst
.instruction
|= (Rd
& 7) | ((Rs
& 7) << 3);
4884 inst
.error
= _("only lo regs allowed with immediate");
4888 if (move
== THUMB_MOVE
)
4889 inst
.instruction
= T_OPCODE_MOV_I8
;
4891 inst
.instruction
= T_OPCODE_CMP_I8
;
4893 inst
.instruction
|= Rd
<< 8;
4895 if (inst
.reloc
.exp
.X_op
!= O_constant
)
4896 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_IMM
;
4899 unsigned value
= inst
.reloc
.exp
.X_add_number
;
4903 inst
.error
= _("invalid immediate");
4907 inst
.instruction
|= value
;
4914 /* THUMB CPY instruction (argument parse). */
4917 do_t_cpy (char * str
)
4919 thumb_mov_compare (str
, THUMB_CPY
);
4922 /* THUMB SETEND instruction (argument parse). */
4925 do_t_setend (char * str
)
4927 if (do_endian_specifier (str
))
4928 inst
.instruction
|= 0x8;
4931 /* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
4933 static unsigned long
4934 check_iwmmxt_insn (char * str
,
4935 enum iwmmxt_insn_type insn_type
,
4939 const char * inst_error
;
4941 unsigned long number
;
4943 inst_error
= inst
.error
;
4945 inst
.error
= BAD_ARGS
;
4946 skip_whitespace (str
);
4951 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
4956 if ((wreg_required_here (&str
, 0, IWMMXT_REG_WR
)) == FAIL
)
4961 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
4962 || skip_past_comma (&str
) == FAIL
4963 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
))
4968 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
4969 || skip_past_comma (&str
) == FAIL
4970 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4971 || skip_past_comma (&str
) == FAIL
4972 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
))
4977 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
4978 || skip_past_comma (&str
) == FAIL
4979 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4980 || skip_past_comma (&str
) == FAIL
4981 || wreg_required_here (&str
, 0, IWMMXT_REG_WCG
) == FAIL
))
4986 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4987 || skip_past_comma (&str
) == FAIL
4988 || reg_required_here (&str
, 12) == FAIL
))
4993 if ((reg_required_here (&str
, 12) == FAIL
4994 || skip_past_comma (&str
) == FAIL
4995 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
))
5000 if ((wreg_required_here (&str
, 5, IWMMXT_REG_WR
) == FAIL
5001 || skip_past_comma (&str
) == FAIL
5002 || reg_required_here (&str
, 0) == FAIL
5003 || skip_past_comma (&str
) == FAIL
5004 || reg_required_here (&str
, 12) == FAIL
))
5009 if ((wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
5010 || skip_past_comma (&str
) == FAIL
5011 || reg_required_here (&str
, 12) == FAIL
5012 || skip_past_comma (&str
) == FAIL
5013 || reg_required_here (&str
, 16) == FAIL
))
5018 if ((reg_required_here (&str
, 12) == FAIL
5019 || skip_past_comma (&str
) == FAIL
5020 || reg_required_here (&str
, 16) == FAIL
5021 || skip_past_comma (&str
) == FAIL
5022 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
))
5027 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WC
) == FAIL
5028 || skip_past_comma (&str
) == FAIL
5029 || reg_required_here (&str
, 12) == FAIL
))
5034 if ((reg_required_here (&str
, 12) == FAIL
5035 || skip_past_comma (&str
) == FAIL
5036 || wreg_required_here (&str
, 16, IWMMXT_REG_WC
) == FAIL
))
5041 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5042 || skip_past_comma (&str
) == FAIL
5043 || reg_required_here (&str
, 12) == FAIL
5044 || skip_past_comma (&str
) == FAIL
))
5049 if ((reg_required_here (&str
, 12) == FAIL
5050 || skip_past_comma (&str
) == FAIL
))
5055 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
5056 || skip_past_comma (&str
) == FAIL
5057 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5058 || skip_past_comma (&str
) == FAIL
5059 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
5060 || skip_past_comma (&str
) == FAIL
))
5065 if ((reg_required_here (&str
, 12) == FAIL
5066 || skip_past_comma (&str
) == FAIL
5067 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5068 || skip_past_comma (&str
) == FAIL
))
5073 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
5074 || skip_past_comma (&str
) == FAIL
5075 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5076 || skip_past_comma (&str
) == FAIL
))
5081 if (immediate_size
== 0)
5084 inst
.error
= inst_error
;
5089 skip_whitespace (str
);
5091 /* Allow optional leading '#'. */
5092 if (is_immediate_prefix (* str
))
5095 memset (& expr
, '\0', sizeof (expr
));
5097 if (my_get_expression (& expr
, & str
) || (expr
.X_op
!= O_constant
))
5099 inst
.error
= _("bad or missing expression");
5103 number
= expr
.X_add_number
;
5105 if (number
!= (number
& immediate_size
))
5107 inst
.error
= _("immediate value out of range");
5111 inst
.error
= inst_error
;
5117 do_iwmmxt_byte_addr (char * str
)
5119 int op
= (inst
.instruction
& 0x300) >> 8;
5122 inst
.instruction
&= ~0x300;
5123 inst
.instruction
|= (op
& 1) << 22 | (op
& 2) << 7;
5125 skip_whitespace (str
);
5127 if ((reg
= wreg_required_here (&str
, 12, IWMMXT_REG_WR_OR_WC
)) == FAIL
5128 || skip_past_comma (& str
) == FAIL
5129 || cp_byte_address_required_here (&str
) == FAIL
)
5132 inst
.error
= BAD_ARGS
;
5137 if (wc_register (reg
))
5139 as_bad (_("non-word size not supported with control register"));
5140 inst
.instruction
|= 0xf0000100;
5141 inst
.instruction
&= ~0x00400000;
5146 do_iwmmxt_tandc (char * str
)
5150 reg
= check_iwmmxt_insn (str
, check_rd
, 0);
5152 if (reg
!= REG_PC
&& !inst
.error
)
5153 inst
.error
= _("only r15 allowed here");
5157 do_iwmmxt_tbcst (char * str
)
5159 check_iwmmxt_insn (str
, check_tbcst
, 0);
5163 do_iwmmxt_textrc (char * str
)
5165 unsigned long number
;
5167 if ((number
= check_iwmmxt_insn (str
, check_textrc
, 7)) == (unsigned long) FAIL
)
5170 inst
.instruction
|= number
& 0x7;
5174 do_iwmmxt_textrm (char * str
)
5176 unsigned long number
;
5178 if ((number
= check_iwmmxt_insn (str
, check_textrm
, 7)) == (unsigned long) FAIL
)
5181 inst
.instruction
|= number
& 0x7;
5185 do_iwmmxt_tinsr (char * str
)
5187 unsigned long number
;
5189 if ((number
= check_iwmmxt_insn (str
, check_tinsr
, 7)) == (unsigned long) FAIL
)
5192 inst
.instruction
|= number
& 0x7;
5196 do_iwmmxt_tmcr (char * str
)
5198 check_iwmmxt_insn (str
, check_tmcr
, 0);
5202 do_iwmmxt_tmcrr (char * str
)
5204 check_iwmmxt_insn (str
, check_tmcrr
, 0);
5208 do_iwmmxt_tmia (char * str
)
5210 check_iwmmxt_insn (str
, check_tmia
, 0);
5214 do_iwmmxt_tmovmsk (char * str
)
5216 check_iwmmxt_insn (str
, check_tmovmsk
, 0);
5220 do_iwmmxt_tmrc (char * str
)
5222 check_iwmmxt_insn (str
, check_tmrc
, 0);
5226 do_iwmmxt_tmrrc (char * str
)
5228 check_iwmmxt_insn (str
, check_tmrrc
, 0);
5232 do_iwmmxt_torc (char * str
)
5234 check_iwmmxt_insn (str
, check_rd
, 0);
5238 do_iwmmxt_waligni (char * str
)
5240 unsigned long number
;
5242 if ((number
= check_iwmmxt_insn (str
, check_waligni
, 7)) == (unsigned long) FAIL
)
5245 inst
.instruction
|= ((number
& 0x7) << 20);
5249 do_iwmmxt_wmov (char * str
)
5251 if (check_iwmmxt_insn (str
, check_wrwr
, 0) == (unsigned long) FAIL
)
5254 inst
.instruction
|= ((inst
.instruction
>> 16) & 0xf);
5258 do_iwmmxt_word_addr (char * str
)
5260 int op
= (inst
.instruction
& 0x300) >> 8;
5263 inst
.instruction
&= ~0x300;
5264 inst
.instruction
|= (op
& 1) << 22 | (op
& 2) << 7;
5266 skip_whitespace (str
);
5268 if ((reg
= wreg_required_here (&str
, 12, IWMMXT_REG_WR_OR_WC
)) == FAIL
5269 || skip_past_comma (& str
) == FAIL
5270 || cp_address_required_here (& str
, CP_WB_OK
) == FAIL
)
5273 inst
.error
= BAD_ARGS
;
5278 if (wc_register (reg
))
5280 if ((inst
.instruction
& COND_MASK
) != COND_ALWAYS
)
5281 as_bad (_("conditional execution not supported with control register"));
5283 as_bad (_("non-word size not supported with control register"));
5284 inst
.instruction
|= 0xf0000100;
5285 inst
.instruction
&= ~0x00400000;
5290 do_iwmmxt_wrwr (char * str
)
5292 check_iwmmxt_insn (str
, check_wrwr
, 0);
5296 do_iwmmxt_wrwrwcg (char * str
)
5298 check_iwmmxt_insn (str
, check_wrwrwcg
, 0);
5302 do_iwmmxt_wrwrwr (char * str
)
5304 check_iwmmxt_insn (str
, check_wrwrwr
, 0);
5308 do_iwmmxt_wshufh (char * str
)
5310 unsigned long number
;
5312 if ((number
= check_iwmmxt_insn (str
, check_wshufh
, 0xff)) == (unsigned long) FAIL
)
5315 inst
.instruction
|= ((number
& 0xf0) << 16) | (number
& 0xf);
5319 do_iwmmxt_wzero (char * str
)
5321 if (check_iwmmxt_insn (str
, check_wr
, 0) == (unsigned long) FAIL
)
5324 inst
.instruction
|= ((inst
.instruction
& 0xf) << 12) | ((inst
.instruction
& 0xf) << 16);
5327 /* Xscale multiply-accumulate (argument parse)
5330 MIAxycc acc0,Rm,Rs. */
5333 do_xsc_mia (char * str
)
5338 if (accum0_required_here (& str
) == FAIL
)
5339 inst
.error
= ERR_NO_ACCUM
;
5341 else if (skip_past_comma (& str
) == FAIL
5342 || (rm
= reg_required_here (& str
, 0)) == FAIL
)
5343 inst
.error
= BAD_ARGS
;
5345 else if (skip_past_comma (& str
) == FAIL
5346 || (rs
= reg_required_here (& str
, 12)) == FAIL
)
5347 inst
.error
= BAD_ARGS
;
5349 /* inst.instruction has now been zapped with both rm and rs. */
5350 else if (rm
== REG_PC
|| rs
== REG_PC
)
5351 inst
.error
= BAD_PC
; /* Undefined result if rm or rs is R15. */
5357 /* Xscale move-accumulator-register (argument parse)
5359 MARcc acc0,RdLo,RdHi. */
5362 do_xsc_mar (char * str
)
5366 if (accum0_required_here (& str
) == FAIL
)
5367 inst
.error
= ERR_NO_ACCUM
;
5369 else if (skip_past_comma (& str
) == FAIL
5370 || (rdlo
= reg_required_here (& str
, 12)) == FAIL
)
5371 inst
.error
= BAD_ARGS
;
5373 else if (skip_past_comma (& str
) == FAIL
5374 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
5375 inst
.error
= BAD_ARGS
;
5377 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5378 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
5379 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
5385 /* Xscale move-register-accumulator (argument parse)
5387 MRAcc RdLo,RdHi,acc0. */
5390 do_xsc_mra (char * str
)
5395 skip_whitespace (str
);
5397 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
)
5398 inst
.error
= BAD_ARGS
;
5400 else if (skip_past_comma (& str
) == FAIL
5401 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
5402 inst
.error
= BAD_ARGS
;
5404 else if (skip_past_comma (& str
) == FAIL
5405 || accum0_required_here (& str
) == FAIL
)
5406 inst
.error
= ERR_NO_ACCUM
;
5408 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5409 else if (rdlo
== rdhi
)
5410 inst
.error
= BAD_ARGS
; /* Undefined result if 2 writes to same reg. */
5412 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
5413 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
5419 ldst_extend (char ** str
)
5428 if (my_get_expression (& inst
.reloc
.exp
, str
))
5431 if (inst
.reloc
.exp
.X_op
== O_constant
)
5433 int value
= inst
.reloc
.exp
.X_add_number
;
5435 if (value
< -4095 || value
> 4095)
5437 inst
.error
= _("address offset too large");
5447 inst
.instruction
|= add
| value
;
5451 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
5452 inst
.reloc
.pc_rel
= 0;
5465 if (reg_required_here (str
, 0) == FAIL
)
5468 inst
.instruction
|= add
| OFFSET_REG
;
5469 if (skip_past_comma (str
) == SUCCESS
)
5470 return decode_shift (str
, SHIFT_IMMEDIATE
);
5476 /* ARMv5TE: Preload-Cache
5480 Syntactically, like LDR with B=1, W=0, L=1. */
5487 skip_whitespace (str
);
5491 inst
.error
= _("'[' expected after PLD mnemonic");
5496 skip_whitespace (str
);
5498 if ((rd
= reg_required_here (& str
, 16)) == FAIL
)
5501 skip_whitespace (str
);
5507 skip_whitespace (str
);
5509 /* Post-indexed addressing is not allowed with PLD. */
5510 if (skip_past_comma (&str
) == SUCCESS
)
5513 = _("post-indexed expression used in preload instruction");
5516 else if (*str
== '!') /* [Rn]! */
5518 inst
.error
= _("writeback used in preload instruction");
5522 inst
.instruction
|= INDEX_UP
| PRE_INDEX
;
5524 else /* [Rn, ...] */
5526 if (skip_past_comma (& str
) == FAIL
)
5528 inst
.error
= _("pre-indexed expression expected");
5532 if (ldst_extend (&str
) == FAIL
)
5535 skip_whitespace (str
);
5539 inst
.error
= _("missing ]");
5544 skip_whitespace (str
);
5546 if (* str
== '!') /* [Rn]! */
5548 inst
.error
= _("writeback used in preload instruction");
5552 inst
.instruction
|= PRE_INDEX
;
5558 /* ARMv5TE load-consecutive (argument parse)
5565 do_ldrd (char * str
)
5570 skip_whitespace (str
);
5572 if ((rd
= reg_required_here (& str
, 12)) == FAIL
)
5574 inst
.error
= BAD_ARGS
;
5578 if (skip_past_comma (& str
) == FAIL
5579 || (rn
= ld_mode_required_here (& str
)) == FAIL
)
5582 inst
.error
= BAD_ARGS
;
5586 /* inst.instruction has now been zapped with Rd and the addressing mode. */
5587 if (rd
& 1) /* Unpredictable result if Rd is odd. */
5589 inst
.error
= _("destination register must be even");
5595 inst
.error
= _("r14 not allowed here");
5599 if (((rd
== rn
) || (rd
+ 1 == rn
))
5600 && ((inst
.instruction
& WRITE_BACK
)
5601 || (!(inst
.instruction
& PRE_INDEX
))))
5602 as_warn (_("pre/post-indexing used when modified address register is destination"));
5604 /* For an index-register load, the index register must not overlap the
5605 destination (even if not write-back). */
5606 if ((inst
.instruction
& V4_STR_BIT
) == 0
5607 && (inst
.instruction
& HWOFFSET_IMM
) == 0)
5609 int rm
= inst
.instruction
& 0x0000000f;
5611 if (rm
== rd
|| (rm
== rd
+ 1))
5612 as_warn (_("ldrd destination registers must not overlap index register"));
5618 /* Returns the index into fp_values of a floating point number,
5619 or -1 if not in the table. */
5622 my_get_float_expression (char ** str
)
5624 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
5630 memset (words
, 0, MAX_LITTLENUMS
* sizeof (LITTLENUM_TYPE
));
5632 /* Look for a raw floating point number. */
5633 if ((save_in
= atof_ieee (*str
, 'x', words
)) != NULL
5634 && is_end_of_line
[(unsigned char) *save_in
])
5636 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
5638 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
5640 if (words
[j
] != fp_values
[i
][j
])
5644 if (j
== MAX_LITTLENUMS
)
5652 /* Try and parse a more complex expression, this will probably fail
5653 unless the code uses a floating point prefix (eg "0f"). */
5654 save_in
= input_line_pointer
;
5655 input_line_pointer
= *str
;
5656 if (expression (&exp
) == absolute_section
5657 && exp
.X_op
== O_big
5658 && exp
.X_add_number
< 0)
5660 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
5662 if (gen_to_words (words
, 5, (long) 15) == 0)
5664 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
5666 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
5668 if (words
[j
] != fp_values
[i
][j
])
5672 if (j
== MAX_LITTLENUMS
)
5674 *str
= input_line_pointer
;
5675 input_line_pointer
= save_in
;
5682 *str
= input_line_pointer
;
5683 input_line_pointer
= save_in
;
5687 /* We handle all bad expressions here, so that we can report the faulty
5688 instruction in the error message. */
5690 md_operand (expressionS
* expr
)
5692 if (in_my_get_expression
)
5694 expr
->X_op
= O_illegal
;
5695 if (inst
.error
== NULL
)
5696 inst
.error
= _("bad expression");
5700 /* Do those data_ops which can take a negative immediate constant
5701 by altering the instruction. A bit of a hack really.
5705 by inverting the second operand, and
5708 by negating the second operand. */
5711 negate_data_op (unsigned long * instruction
,
5712 unsigned long value
)
5715 unsigned long negated
, inverted
;
5717 negated
= validate_immediate (-value
);
5718 inverted
= validate_immediate (~value
);
5720 op
= (*instruction
>> DATA_OP_SHIFT
) & 0xf;
5723 /* First negates. */
5724 case OPCODE_SUB
: /* ADD <-> SUB */
5725 new_inst
= OPCODE_ADD
;
5730 new_inst
= OPCODE_SUB
;
5734 case OPCODE_CMP
: /* CMP <-> CMN */
5735 new_inst
= OPCODE_CMN
;
5740 new_inst
= OPCODE_CMP
;
5744 /* Now Inverted ops. */
5745 case OPCODE_MOV
: /* MOV <-> MVN */
5746 new_inst
= OPCODE_MVN
;
5751 new_inst
= OPCODE_MOV
;
5755 case OPCODE_AND
: /* AND <-> BIC */
5756 new_inst
= OPCODE_BIC
;
5761 new_inst
= OPCODE_AND
;
5765 case OPCODE_ADC
: /* ADC <-> SBC */
5766 new_inst
= OPCODE_SBC
;
5771 new_inst
= OPCODE_ADC
;
5775 /* We cannot do anything. */
5780 if (value
== (unsigned) FAIL
)
5783 *instruction
&= OPCODE_MASK
;
5784 *instruction
|= new_inst
<< DATA_OP_SHIFT
;
5789 data_op2 (char ** str
)
5794 skip_whitespace (* str
);
5796 if (reg_required_here (str
, 0) != FAIL
)
5798 if (skip_past_comma (str
) == SUCCESS
)
5799 /* Shift operation on register. */
5800 return decode_shift (str
, NO_SHIFT_RESTRICT
);
5806 /* Immediate expression. */
5807 if (is_immediate_prefix (**str
))
5812 if (my_get_expression (&inst
.reloc
.exp
, str
))
5815 if (inst
.reloc
.exp
.X_add_symbol
)
5817 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
5818 inst
.reloc
.pc_rel
= 0;
5822 if (skip_past_comma (str
) == SUCCESS
)
5824 /* #x, y -- ie explicit rotation by Y. */
5825 if (my_get_expression (&expr
, str
))
5828 if (expr
.X_op
!= O_constant
)
5830 inst
.error
= _("constant expression expected");
5834 /* Rotate must be a multiple of 2. */
5835 if (((unsigned) expr
.X_add_number
) > 30
5836 || (expr
.X_add_number
& 1) != 0
5837 || ((unsigned) inst
.reloc
.exp
.X_add_number
) > 255)
5839 inst
.error
= _("invalid constant");
5842 inst
.instruction
|= INST_IMMEDIATE
;
5843 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
5844 inst
.instruction
|= expr
.X_add_number
<< 7;
5848 /* Implicit rotation, select a suitable one. */
5849 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
5853 /* Can't be done. Perhaps the code reads something like
5854 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
5855 if ((value
= negate_data_op (&inst
.instruction
,
5856 inst
.reloc
.exp
.X_add_number
))
5859 inst
.error
= _("invalid constant");
5864 inst
.instruction
|= value
;
5867 inst
.instruction
|= INST_IMMEDIATE
;
5872 inst
.error
= _("register or shift expression expected");
5878 fp_op2 (char ** str
)
5880 skip_whitespace (* str
);
5882 if (fp_reg_required_here (str
, 0) != FAIL
)
5886 /* Immediate expression. */
5887 if (*((*str
)++) == '#')
5893 skip_whitespace (* str
);
5895 /* First try and match exact strings, this is to guarantee
5896 that some formats will work even for cross assembly. */
5898 for (i
= 0; fp_const
[i
]; i
++)
5900 if (strncmp (*str
, fp_const
[i
], strlen (fp_const
[i
])) == 0)
5904 *str
+= strlen (fp_const
[i
]);
5905 if (is_end_of_line
[(unsigned char) **str
])
5907 inst
.instruction
|= i
+ 8;
5914 /* Just because we didn't get a match doesn't mean that the
5915 constant isn't valid, just that it is in a format that we
5916 don't automatically recognize. Try parsing it with
5917 the standard expression routines. */
5918 if ((i
= my_get_float_expression (str
)) >= 0)
5920 inst
.instruction
|= i
+ 8;
5924 inst
.error
= _("invalid floating point immediate expression");
5928 _("floating point register or immediate expression expected");
5934 do_arit (char * str
)
5936 skip_whitespace (str
);
5938 if (reg_required_here (&str
, 12) == FAIL
5939 || skip_past_comma (&str
) == FAIL
5940 || reg_required_here (&str
, 16) == FAIL
5941 || skip_past_comma (&str
) == FAIL
5942 || data_op2 (&str
) == FAIL
)
5945 inst
.error
= BAD_ARGS
;
5955 /* This is a pseudo-op of the form "adr rd, label" to be converted
5956 into a relative address of the form "add rd, pc, #label-.-8". */
5957 skip_whitespace (str
);
5959 if (reg_required_here (&str
, 12) == FAIL
5960 || skip_past_comma (&str
) == FAIL
5961 || my_get_expression (&inst
.reloc
.exp
, &str
))
5964 inst
.error
= BAD_ARGS
;
5968 /* Frag hacking will turn this into a sub instruction if the offset turns
5969 out to be negative. */
5970 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
5972 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust. */
5974 inst
.reloc
.pc_rel
= 1;
5980 do_adrl (char * str
)
5982 /* This is a pseudo-op of the form "adrl rd, label" to be converted
5983 into a relative address of the form:
5984 add rd, pc, #low(label-.-8)"
5985 add rd, rd, #high(label-.-8)" */
5987 skip_whitespace (str
);
5989 if (reg_required_here (&str
, 12) == FAIL
5990 || skip_past_comma (&str
) == FAIL
5991 || my_get_expression (&inst
.reloc
.exp
, &str
))
5994 inst
.error
= BAD_ARGS
;
6000 /* Frag hacking will turn this into a sub instruction if the offset turns
6001 out to be negative. */
6002 inst
.reloc
.type
= BFD_RELOC_ARM_ADRL_IMMEDIATE
;
6004 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust */
6006 inst
.reloc
.pc_rel
= 1;
6007 inst
.size
= INSN_SIZE
* 2;
6013 skip_whitespace (str
);
6015 if (reg_required_here (&str
, 16) == FAIL
)
6018 inst
.error
= BAD_ARGS
;
6022 if (skip_past_comma (&str
) == FAIL
6023 || data_op2 (&str
) == FAIL
)
6026 inst
.error
= BAD_ARGS
;
6036 skip_whitespace (str
);
6038 if (reg_required_here (&str
, 12) == FAIL
)
6041 inst
.error
= BAD_ARGS
;
6045 if (skip_past_comma (&str
) == FAIL
6046 || data_op2 (&str
) == FAIL
)
6049 inst
.error
= BAD_ARGS
;
6057 do_ldst (char * str
)
6063 skip_whitespace (str
);
6065 if ((conflict_reg
= reg_required_here (&str
, 12)) == FAIL
)
6068 inst
.error
= BAD_ARGS
;
6072 if (skip_past_comma (&str
) == FAIL
)
6074 inst
.error
= _("address expected");
6084 skip_whitespace (str
);
6086 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6089 /* Conflicts can occur on stores as well as loads. */
6090 conflict_reg
= (conflict_reg
== reg
);
6092 skip_whitespace (str
);
6098 if (skip_past_comma (&str
) == SUCCESS
)
6100 /* [Rn],... (post inc) */
6101 if (ldst_extend (&str
) == FAIL
)
6104 as_warn (_("%s register same as write-back base"),
6105 ((inst
.instruction
& LOAD_BIT
)
6106 ? _("destination") : _("source")));
6111 skip_whitespace (str
);
6116 as_warn (_("%s register same as write-back base"),
6117 ((inst
.instruction
& LOAD_BIT
)
6118 ? _("destination") : _("source")));
6120 inst
.instruction
|= WRITE_BACK
;
6123 inst
.instruction
|= INDEX_UP
;
6130 if (skip_past_comma (&str
) == FAIL
)
6132 inst
.error
= _("pre-indexed expression expected");
6137 if (ldst_extend (&str
) == FAIL
)
6140 skip_whitespace (str
);
6144 inst
.error
= _("missing ]");
6148 skip_whitespace (str
);
6153 as_warn (_("%s register same as write-back base"),
6154 ((inst
.instruction
& LOAD_BIT
)
6155 ? _("destination") : _("source")));
6157 inst
.instruction
|= WRITE_BACK
;
6161 else if (*str
== '=')
6163 if ((inst
.instruction
& LOAD_BIT
) == 0)
6165 inst
.error
= _("invalid pseudo operation");
6169 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6172 skip_whitespace (str
);
6174 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6177 if (inst
.reloc
.exp
.X_op
!= O_constant
6178 && inst
.reloc
.exp
.X_op
!= O_symbol
)
6180 inst
.error
= _("constant expression expected");
6184 if (inst
.reloc
.exp
.X_op
== O_constant
)
6186 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
6190 /* This can be done with a mov instruction. */
6191 inst
.instruction
&= LITERAL_MASK
;
6192 inst
.instruction
|= (INST_IMMEDIATE
6193 | (OPCODE_MOV
<< DATA_OP_SHIFT
));
6194 inst
.instruction
|= value
& 0xfff;
6199 value
= validate_immediate (~inst
.reloc
.exp
.X_add_number
);
6203 /* This can be done with a mvn instruction. */
6204 inst
.instruction
&= LITERAL_MASK
;
6205 inst
.instruction
|= (INST_IMMEDIATE
6206 | (OPCODE_MVN
<< DATA_OP_SHIFT
));
6207 inst
.instruction
|= value
& 0xfff;
6213 /* Insert into literal pool. */
6214 if (add_to_lit_pool () == FAIL
)
6217 inst
.error
= _("literal pool insertion failed");
6221 /* Change the instruction exp to point to the pool. */
6222 inst
.reloc
.type
= BFD_RELOC_ARM_LITERAL
;
6223 inst
.reloc
.pc_rel
= 1;
6224 inst
.instruction
|= (REG_PC
<< 16);
6229 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6232 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
6234 /* PC rel adjust. */
6235 inst
.reloc
.exp
.X_add_number
-= 8;
6237 inst
.reloc
.pc_rel
= 1;
6238 inst
.instruction
|= (REG_PC
<< 16);
6242 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
6247 do_ldstt (char * str
)
6251 skip_whitespace (str
);
6253 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
6256 inst
.error
= BAD_ARGS
;
6260 if (skip_past_comma (& str
) == FAIL
)
6262 inst
.error
= _("address expected");
6272 skip_whitespace (str
);
6274 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6277 /* ldrt/strt always use post-indexed addressing, so if the base is
6278 the same as Rd, we warn. */
6279 if (conflict_reg
== reg
)
6280 as_warn (_("%s register same as write-back base"),
6281 ((inst
.instruction
& LOAD_BIT
)
6282 ? _("destination") : _("source")));
6284 skip_whitespace (str
);
6290 if (skip_past_comma (&str
) == SUCCESS
)
6292 /* [Rn],... (post inc) */
6293 if (ldst_extend (&str
) == FAIL
)
6299 skip_whitespace (str
);
6301 /* Skip a write-back '!'. */
6305 inst
.instruction
|= INDEX_UP
;
6310 inst
.error
= _("post-indexed expression expected");
6316 inst
.error
= _("post-indexed expression expected");
6323 /* Halfword and signed-byte load/store operations. */
6326 do_ldstv4 (char * str
)
6332 skip_whitespace (str
);
6334 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
6337 inst
.error
= BAD_ARGS
;
6341 if (skip_past_comma (& str
) == FAIL
)
6343 inst
.error
= _("address expected");
6353 skip_whitespace (str
);
6355 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6358 /* Conflicts can occur on stores as well as loads. */
6359 conflict_reg
= (conflict_reg
== reg
);
6361 skip_whitespace (str
);
6367 if (skip_past_comma (&str
) == SUCCESS
)
6369 /* [Rn],... (post inc) */
6370 if (ldst_extend_v4 (&str
) == FAIL
)
6373 as_warn (_("%s register same as write-back base"),
6374 ((inst
.instruction
& LOAD_BIT
)
6375 ? _("destination") : _("source")));
6380 inst
.instruction
|= HWOFFSET_IMM
;
6382 skip_whitespace (str
);
6387 as_warn (_("%s register same as write-back base"),
6388 ((inst
.instruction
& LOAD_BIT
)
6389 ? _("destination") : _("source")));
6391 inst
.instruction
|= WRITE_BACK
;
6394 inst
.instruction
|= INDEX_UP
;
6401 if (skip_past_comma (&str
) == FAIL
)
6403 inst
.error
= _("pre-indexed expression expected");
6408 if (ldst_extend_v4 (&str
) == FAIL
)
6411 skip_whitespace (str
);
6415 inst
.error
= _("missing ]");
6419 skip_whitespace (str
);
6424 as_warn (_("%s register same as write-back base"),
6425 ((inst
.instruction
& LOAD_BIT
)
6426 ? _("destination") : _("source")));
6428 inst
.instruction
|= WRITE_BACK
;
6432 else if (*str
== '=')
6434 if ((inst
.instruction
& LOAD_BIT
) == 0)
6436 inst
.error
= _("invalid pseudo operation");
6440 /* XXX Does this work correctly for half-word/byte ops? */
6441 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6444 skip_whitespace (str
);
6446 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6449 if (inst
.reloc
.exp
.X_op
!= O_constant
6450 && inst
.reloc
.exp
.X_op
!= O_symbol
)
6452 inst
.error
= _("constant expression expected");
6456 if (inst
.reloc
.exp
.X_op
== O_constant
)
6458 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
6462 /* This can be done with a mov instruction. */
6463 inst
.instruction
&= LITERAL_MASK
;
6464 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MOV
<< DATA_OP_SHIFT
);
6465 inst
.instruction
|= value
& 0xfff;
6470 value
= validate_immediate (~ inst
.reloc
.exp
.X_add_number
);
6474 /* This can be done with a mvn instruction. */
6475 inst
.instruction
&= LITERAL_MASK
;
6476 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MVN
<< DATA_OP_SHIFT
);
6477 inst
.instruction
|= value
& 0xfff;
6483 /* Insert into literal pool. */
6484 if (add_to_lit_pool () == FAIL
)
6487 inst
.error
= _("literal pool insertion failed");
6491 /* Change the instruction exp to point to the pool. */
6492 inst
.instruction
|= HWOFFSET_IMM
;
6493 inst
.reloc
.type
= BFD_RELOC_ARM_HWLITERAL
;
6494 inst
.reloc
.pc_rel
= 1;
6495 inst
.instruction
|= (REG_PC
<< 16);
6500 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6503 inst
.instruction
|= HWOFFSET_IMM
;
6504 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
6506 /* PC rel adjust. */
6507 inst
.reloc
.exp
.X_add_number
-= 8;
6509 inst
.reloc
.pc_rel
= 1;
6510 inst
.instruction
|= (REG_PC
<< 16);
6514 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
6519 reg_list (char ** strp
)
6521 char * str
= * strp
;
6525 /* We come back here if we get ranges concatenated by '+' or '|'. */
6540 skip_whitespace (str
);
6542 if ((reg
= reg_required_here (& str
, -1)) == FAIL
)
6551 inst
.error
= _("bad range in register list");
6555 for (i
= cur_reg
+ 1; i
< reg
; i
++)
6557 if (range
& (1 << i
))
6559 (_("Warning: duplicated register (r%d) in register list"),
6567 if (range
& (1 << reg
))
6568 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
6570 else if (reg
<= cur_reg
)
6571 as_tsktsk (_("Warning: register range not in ascending order"));
6576 while (skip_past_comma (&str
) != FAIL
6577 || (in_range
= 1, *str
++ == '-'));
6579 skip_whitespace (str
);
6583 inst
.error
= _("missing `}'");
6591 if (my_get_expression (&expr
, &str
))
6594 if (expr
.X_op
== O_constant
)
6596 if (expr
.X_add_number
6597 != (expr
.X_add_number
& 0x0000ffff))
6599 inst
.error
= _("invalid register mask");
6603 if ((range
& expr
.X_add_number
) != 0)
6605 int regno
= range
& expr
.X_add_number
;
6608 regno
= (1 << regno
) - 1;
6610 (_("Warning: duplicated register (r%d) in register list"),
6614 range
|= expr
.X_add_number
;
6618 if (inst
.reloc
.type
!= 0)
6620 inst
.error
= _("expression too complex");
6624 memcpy (&inst
.reloc
.exp
, &expr
, sizeof (expressionS
));
6625 inst
.reloc
.type
= BFD_RELOC_ARM_MULTI
;
6626 inst
.reloc
.pc_rel
= 0;
6630 skip_whitespace (str
);
6632 if (*str
== '|' || *str
== '+')
6638 while (another_range
);
6645 do_ldmstm (char * str
)
6650 skip_whitespace (str
);
6652 if ((base_reg
= reg_required_here (&str
, 16)) == FAIL
)
6655 if (base_reg
== REG_PC
)
6657 inst
.error
= _("r15 not allowed as base register");
6661 skip_whitespace (str
);
6665 inst
.instruction
|= WRITE_BACK
;
6669 if (skip_past_comma (&str
) == FAIL
6670 || (range
= reg_list (&str
)) == FAIL
)
6673 inst
.error
= BAD_ARGS
;
6680 inst
.instruction
|= LDM_TYPE_2_OR_3
;
6683 if (inst
.instruction
& WRITE_BACK
)
6685 /* Check for unpredictable uses of writeback. */
6686 if (inst
.instruction
& LOAD_BIT
)
6688 /* Not allowed in LDM type 2. */
6689 if ((inst
.instruction
& LDM_TYPE_2_OR_3
)
6690 && ((range
& (1 << REG_PC
)) == 0))
6691 as_warn (_("writeback of base register is UNPREDICTABLE"));
6692 /* Only allowed if base reg not in list for other types. */
6693 else if (range
& (1 << base_reg
))
6694 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
6698 /* Not allowed for type 2. */
6699 if (inst
.instruction
& LDM_TYPE_2_OR_3
)
6700 as_warn (_("writeback of base register is UNPREDICTABLE"));
6701 /* Only allowed if base reg not in list, or first in list. */
6702 else if ((range
& (1 << base_reg
))
6703 && (range
& ((1 << base_reg
) - 1)))
6704 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
6708 inst
.instruction
|= range
;
6715 skip_whitespace (str
);
6717 /* Allow optional leading '#'. */
6718 if (is_immediate_prefix (*str
))
6721 if (my_get_expression (& inst
.reloc
.exp
, & str
))
6724 inst
.reloc
.type
= BFD_RELOC_ARM_SMI
;
6725 inst
.reloc
.pc_rel
= 0;
6732 skip_whitespace (str
);
6734 /* Allow optional leading '#'. */
6735 if (is_immediate_prefix (*str
))
6738 if (my_get_expression (& inst
.reloc
.exp
, & str
))
6741 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
6742 inst
.reloc
.pc_rel
= 0;
6747 do_swap (char * str
)
6751 skip_whitespace (str
);
6753 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
6758 inst
.error
= _("r15 not allowed in swap");
6762 if (skip_past_comma (&str
) == FAIL
6763 || (reg
= reg_required_here (&str
, 0)) == FAIL
)
6766 inst
.error
= BAD_ARGS
;
6772 inst
.error
= _("r15 not allowed in swap");
6776 if (skip_past_comma (&str
) == FAIL
6779 inst
.error
= BAD_ARGS
;
6783 skip_whitespace (str
);
6785 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6790 inst
.error
= BAD_PC
;
6794 skip_whitespace (str
);
6798 inst
.error
= _("missing ]");
6806 do_branch (char * str
)
6808 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6815 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
6816 required for the instruction. */
6818 /* arm_parse_reloc () works on input_line_pointer.
6819 We actually want to parse the operands to the branch instruction
6820 passed in 'str'. Save the input pointer and restore it later. */
6821 save_in
= input_line_pointer
;
6822 input_line_pointer
= str
;
6823 if (inst
.reloc
.exp
.X_op
== O_symbol
6825 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
6827 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
6828 inst
.reloc
.pc_rel
= 0;
6829 /* Modify str to point to after parsed operands, otherwise
6830 end_of_line() will complain about the (PLT) left in str. */
6831 str
= input_line_pointer
;
6835 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
6836 inst
.reloc
.pc_rel
= 1;
6838 input_line_pointer
= save_in
;
6841 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
6842 inst
.reloc
.pc_rel
= 1;
6843 #endif /* OBJ_ELF */
6851 /* Co-processor data operation.
6852 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
6853 skip_whitespace (str
);
6855 if (co_proc_number (&str
) == FAIL
)
6858 inst
.error
= BAD_ARGS
;
6862 if (skip_past_comma (&str
) == FAIL
6863 || cp_opc_expr (&str
, 20,4) == FAIL
)
6866 inst
.error
= BAD_ARGS
;
6870 if (skip_past_comma (&str
) == FAIL
6871 || cp_reg_required_here (&str
, 12) == FAIL
)
6874 inst
.error
= BAD_ARGS
;
6878 if (skip_past_comma (&str
) == FAIL
6879 || cp_reg_required_here (&str
, 16) == FAIL
)
6882 inst
.error
= BAD_ARGS
;
6886 if (skip_past_comma (&str
) == FAIL
6887 || cp_reg_required_here (&str
, 0) == FAIL
)
6890 inst
.error
= BAD_ARGS
;
6894 if (skip_past_comma (&str
) == SUCCESS
)
6896 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
6899 inst
.error
= BAD_ARGS
;
6908 do_lstc (char * str
)
6910 /* Co-processor register load/store.
6911 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
6913 skip_whitespace (str
);
6915 if (co_proc_number (&str
) == FAIL
)
6918 inst
.error
= BAD_ARGS
;
6922 if (skip_past_comma (&str
) == FAIL
6923 || cp_reg_required_here (&str
, 12) == FAIL
)
6926 inst
.error
= BAD_ARGS
;
6930 if (skip_past_comma (&str
) == FAIL
6931 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
6934 inst
.error
= BAD_ARGS
;
6942 do_co_reg (char * str
)
6944 /* Co-processor register transfer.
6945 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
6947 skip_whitespace (str
);
6949 if (co_proc_number (&str
) == FAIL
)
6952 inst
.error
= BAD_ARGS
;
6956 if (skip_past_comma (&str
) == FAIL
6957 || cp_opc_expr (&str
, 21, 3) == FAIL
)
6960 inst
.error
= BAD_ARGS
;
6964 if (skip_past_comma (&str
) == FAIL
6965 || reg_required_here (&str
, 12) == FAIL
)
6968 inst
.error
= BAD_ARGS
;
6972 if (skip_past_comma (&str
) == FAIL
6973 || cp_reg_required_here (&str
, 16) == FAIL
)
6976 inst
.error
= BAD_ARGS
;
6980 if (skip_past_comma (&str
) == FAIL
6981 || cp_reg_required_here (&str
, 0) == FAIL
)
6984 inst
.error
= BAD_ARGS
;
6988 if (skip_past_comma (&str
) == SUCCESS
)
6990 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
6993 inst
.error
= BAD_ARGS
;
7002 do_fpa_ctrl (char * str
)
7004 /* FP control registers.
7005 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
7007 skip_whitespace (str
);
7009 if (reg_required_here (&str
, 12) == FAIL
)
7012 inst
.error
= BAD_ARGS
;
7020 do_fpa_ldst (char * str
)
7022 skip_whitespace (str
);
7024 if (fp_reg_required_here (&str
, 12) == FAIL
)
7027 inst
.error
= BAD_ARGS
;
7031 if (skip_past_comma (&str
) == FAIL
7032 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
7035 inst
.error
= BAD_ARGS
;
7043 do_fpa_ldmstm (char * str
)
7047 skip_whitespace (str
);
7049 if (fp_reg_required_here (&str
, 12) == FAIL
)
7052 inst
.error
= BAD_ARGS
;
7056 /* Get Number of registers to transfer. */
7057 if (skip_past_comma (&str
) == FAIL
7058 || my_get_expression (&inst
.reloc
.exp
, &str
))
7061 inst
.error
= _("constant expression expected");
7065 if (inst
.reloc
.exp
.X_op
!= O_constant
)
7067 inst
.error
= _("constant value required for number of registers");
7071 num_regs
= inst
.reloc
.exp
.X_add_number
;
7073 if (num_regs
< 1 || num_regs
> 4)
7075 inst
.error
= _("number of registers must be in the range [1:4]");
7082 inst
.instruction
|= CP_T_X
;
7085 inst
.instruction
|= CP_T_Y
;
7088 inst
.instruction
|= CP_T_Y
| CP_T_X
;
7096 if (inst
.instruction
& (CP_T_Pre
| CP_T_UD
)) /* ea/fd format. */
7102 /* The instruction specified "ea" or "fd", so we can only accept
7103 [Rn]{!}. The instruction does not really support stacking or
7104 unstacking, so we have to emulate these by setting appropriate
7105 bits and offsets. */
7106 if (skip_past_comma (&str
) == FAIL
7110 inst
.error
= BAD_ARGS
;
7115 skip_whitespace (str
);
7117 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
7120 skip_whitespace (str
);
7124 inst
.error
= BAD_ARGS
;
7136 _("r15 not allowed as base register with write-back");
7143 if (inst
.instruction
& CP_T_Pre
)
7145 /* Pre-decrement. */
7146 offset
= 3 * num_regs
;
7148 inst
.instruction
|= CP_T_WB
;
7152 /* Post-increment. */
7155 inst
.instruction
|= CP_T_WB
;
7156 offset
= 3 * num_regs
;
7160 /* No write-back, so convert this into a standard pre-increment
7161 instruction -- aesthetically more pleasing. */
7162 inst
.instruction
|= CP_T_Pre
| CP_T_UD
;
7167 inst
.instruction
|= offset
;
7169 else if (skip_past_comma (&str
) == FAIL
7170 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
7173 inst
.error
= BAD_ARGS
;
7181 do_fpa_dyadic (char * str
)
7183 skip_whitespace (str
);
7185 if (fp_reg_required_here (&str
, 12) == FAIL
)
7188 inst
.error
= BAD_ARGS
;
7192 if (skip_past_comma (&str
) == FAIL
7193 || fp_reg_required_here (&str
, 16) == FAIL
)
7196 inst
.error
= BAD_ARGS
;
7200 if (skip_past_comma (&str
) == FAIL
7201 || fp_op2 (&str
) == FAIL
)
7204 inst
.error
= BAD_ARGS
;
7212 do_fpa_monadic (char * str
)
7214 skip_whitespace (str
);
7216 if (fp_reg_required_here (&str
, 12) == FAIL
)
7219 inst
.error
= BAD_ARGS
;
7223 if (skip_past_comma (&str
) == FAIL
7224 || fp_op2 (&str
) == FAIL
)
7227 inst
.error
= BAD_ARGS
;
7235 do_fpa_cmp (char * str
)
7237 skip_whitespace (str
);
7239 if (fp_reg_required_here (&str
, 16) == FAIL
)
7242 inst
.error
= BAD_ARGS
;
7246 if (skip_past_comma (&str
) == FAIL
7247 || fp_op2 (&str
) == FAIL
)
7250 inst
.error
= BAD_ARGS
;
7258 do_fpa_from_reg (char * str
)
7260 skip_whitespace (str
);
7262 if (fp_reg_required_here (&str
, 16) == FAIL
)
7265 inst
.error
= BAD_ARGS
;
7269 if (skip_past_comma (&str
) == FAIL
7270 || reg_required_here (&str
, 12) == FAIL
)
7273 inst
.error
= BAD_ARGS
;
7281 do_fpa_to_reg (char * str
)
7283 skip_whitespace (str
);
7285 if (reg_required_here (&str
, 12) == FAIL
)
7288 if (skip_past_comma (&str
) == FAIL
7289 || fp_reg_required_here (&str
, 0) == FAIL
)
7292 inst
.error
= BAD_ARGS
;
7299 /* Encode a VFP SP register number. */
7302 vfp_sp_encode_reg (int reg
, enum vfp_sp_reg_pos pos
)
7307 inst
.instruction
|= ((reg
>> 1) << 12) | ((reg
& 1) << 22);
7311 inst
.instruction
|= ((reg
>> 1) << 16) | ((reg
& 1) << 7);
7315 inst
.instruction
|= ((reg
>> 1) << 0) | ((reg
& 1) << 5);
7324 vfp_sp_reg_required_here (char ** str
,
7325 enum vfp_sp_reg_pos pos
)
7328 char * start
= *str
;
7330 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_SN
].htab
)) != FAIL
)
7332 vfp_sp_encode_reg (reg
, pos
);
7336 /* In the few cases where we might be able to accept something else
7337 this error can be overridden. */
7338 inst
.error
= _(all_reg_maps
[REG_TYPE_SN
].expected
);
7340 /* Restore the start point. */
7346 vfp_dp_reg_required_here (char ** str
,
7347 enum vfp_dp_reg_pos pos
)
7350 char * start
= *str
;
7352 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_DN
].htab
)) != FAIL
)
7357 inst
.instruction
|= reg
<< 12;
7361 inst
.instruction
|= reg
<< 16;
7365 inst
.instruction
|= reg
<< 0;
7374 /* In the few cases where we might be able to accept something else
7375 this error can be overridden. */
7376 inst
.error
= _(all_reg_maps
[REG_TYPE_DN
].expected
);
7378 /* Restore the start point. */
7384 do_vfp_sp_monadic (char * str
)
7386 skip_whitespace (str
);
7388 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7391 if (skip_past_comma (&str
) == FAIL
7392 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
7395 inst
.error
= BAD_ARGS
;
7403 do_vfp_dp_monadic (char * str
)
7405 skip_whitespace (str
);
7407 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7410 if (skip_past_comma (&str
) == FAIL
7411 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7414 inst
.error
= BAD_ARGS
;
7422 do_vfp_sp_dyadic (char * str
)
7424 skip_whitespace (str
);
7426 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7429 if (skip_past_comma (&str
) == FAIL
7430 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
7431 || skip_past_comma (&str
) == FAIL
7432 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
7435 inst
.error
= BAD_ARGS
;
7443 do_vfp_dp_dyadic (char * str
)
7445 skip_whitespace (str
);
7447 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7450 if (skip_past_comma (&str
) == FAIL
7451 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
7452 || skip_past_comma (&str
) == FAIL
7453 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7456 inst
.error
= BAD_ARGS
;
7464 do_vfp_reg_from_sp (char * str
)
7466 skip_whitespace (str
);
7468 if (reg_required_here (&str
, 12) == FAIL
)
7471 if (skip_past_comma (&str
) == FAIL
7472 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
7475 inst
.error
= BAD_ARGS
;
7482 /* Parse a VFP register list. If the string is invalid return FAIL.
7483 Otherwise return the number of registers, and set PBASE to the first
7484 register. Double precision registers are matched if DP is nonzero. */
7487 vfp_parse_reg_list (char **str
, int *pbase
, int dp
)
7495 unsigned long mask
= 0;
7502 skip_whitespace (*str
);
7506 regtype
= REG_TYPE_DN
;
7511 regtype
= REG_TYPE_SN
;
7515 base_reg
= max_regs
;
7519 new_base
= arm_reg_parse (str
, all_reg_maps
[regtype
].htab
);
7520 if (new_base
== FAIL
)
7522 inst
.error
= _(all_reg_maps
[regtype
].expected
);
7526 if (new_base
< base_reg
)
7527 base_reg
= new_base
;
7529 if (mask
& (1 << new_base
))
7531 inst
.error
= _("invalid register list");
7535 if ((mask
>> new_base
) != 0 && ! warned
)
7537 as_tsktsk (_("register list not in ascending order"));
7541 mask
|= 1 << new_base
;
7544 skip_whitespace (*str
);
7546 if (**str
== '-') /* We have the start of a range expression */
7553 = arm_reg_parse (str
, all_reg_maps
[regtype
].htab
))
7556 inst
.error
= _(all_reg_maps
[regtype
].expected
);
7560 if (high_range
<= new_base
)
7562 inst
.error
= _("register range not in ascending order");
7566 for (new_base
++; new_base
<= high_range
; new_base
++)
7568 if (mask
& (1 << new_base
))
7570 inst
.error
= _("invalid register list");
7574 mask
|= 1 << new_base
;
7579 while (skip_past_comma (str
) != FAIL
);
7583 /* Sanity check -- should have raised a parse error above. */
7584 if (count
== 0 || count
> max_regs
)
7589 /* Final test -- the registers must be consecutive. */
7591 for (i
= 0; i
< count
; i
++)
7593 if ((mask
& (1u << i
)) == 0)
7595 inst
.error
= _("non-contiguous register range");
7604 do_vfp_reg2_from_sp2 (char * str
)
7608 skip_whitespace (str
);
7610 if (reg_required_here (&str
, 12) == FAIL
7611 || skip_past_comma (&str
) == FAIL
7612 || reg_required_here (&str
, 16) == FAIL
7613 || skip_past_comma (&str
) == FAIL
)
7616 inst
.error
= BAD_ARGS
;
7620 /* We require exactly two consecutive SP registers. */
7621 if (vfp_parse_reg_list (&str
, ®
, 0) != 2)
7624 inst
.error
= _("only two consecutive VFP SP registers allowed here");
7626 vfp_sp_encode_reg (reg
, VFP_REG_Sm
);
7632 do_vfp_sp_from_reg (char * str
)
7634 skip_whitespace (str
);
7636 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
7639 if (skip_past_comma (&str
) == FAIL
7640 || reg_required_here (&str
, 12) == FAIL
)
7643 inst
.error
= BAD_ARGS
;
7651 do_vfp_sp2_from_reg2 (char * str
)
7655 skip_whitespace (str
);
7657 /* We require exactly two consecutive SP registers. */
7658 if (vfp_parse_reg_list (&str
, ®
, 0) != 2)
7661 inst
.error
= _("only two consecutive VFP SP registers allowed here");
7663 vfp_sp_encode_reg (reg
, VFP_REG_Sm
);
7665 if (skip_past_comma (&str
) == FAIL
7666 || reg_required_here (&str
, 12) == FAIL
7667 || skip_past_comma (&str
) == FAIL
7668 || reg_required_here (&str
, 16) == FAIL
)
7671 inst
.error
= BAD_ARGS
;
7679 do_vfp_reg_from_dp (char * str
)
7681 skip_whitespace (str
);
7683 if (reg_required_here (&str
, 12) == FAIL
)
7686 if (skip_past_comma (&str
) == FAIL
7687 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
7690 inst
.error
= BAD_ARGS
;
7698 do_vfp_reg2_from_dp (char * str
)
7700 skip_whitespace (str
);
7702 if (reg_required_here (&str
, 12) == FAIL
)
7705 if (skip_past_comma (&str
) == FAIL
7706 || reg_required_here (&str
, 16) == FAIL
7707 || skip_past_comma (&str
) == FAIL
7708 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7711 inst
.error
= BAD_ARGS
;
7719 do_vfp_dp_from_reg (char * str
)
7721 skip_whitespace (str
);
7723 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
7726 if (skip_past_comma (&str
) == FAIL
7727 || reg_required_here (&str
, 12) == FAIL
)
7730 inst
.error
= BAD_ARGS
;
7738 do_vfp_dp_from_reg2 (char * str
)
7740 skip_whitespace (str
);
7742 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7745 if (skip_past_comma (&str
) == FAIL
7746 || reg_required_here (&str
, 12) == FAIL
7747 || skip_past_comma (&str
) == FAIL
7748 || reg_required_here (&str
, 16) == FAIL
)
7751 inst
.error
= BAD_ARGS
;
7758 static const struct vfp_reg
*
7759 vfp_psr_parse (char ** str
)
7764 const struct vfp_reg
*vreg
;
7768 /* Find the end of the current token. */
7773 while (ISALPHA (c
));
7778 for (vreg
= vfp_regs
+ 0;
7779 vreg
< vfp_regs
+ sizeof (vfp_regs
) / sizeof (struct vfp_reg
);
7782 if (streq (start
, vreg
->name
))
7795 vfp_psr_required_here (char ** str
)
7798 const struct vfp_reg
*vreg
;
7800 vreg
= vfp_psr_parse (str
);
7804 inst
.instruction
|= vreg
->regno
;
7808 inst
.error
= _("VFP system register expected");
7815 do_vfp_reg_from_ctrl (char * str
)
7817 skip_whitespace (str
);
7819 if (reg_required_here (&str
, 12) == FAIL
)
7822 if (skip_past_comma (&str
) == FAIL
7823 || vfp_psr_required_here (&str
) == FAIL
)
7826 inst
.error
= BAD_ARGS
;
7834 do_vfp_ctrl_from_reg (char * str
)
7836 skip_whitespace (str
);
7838 if (vfp_psr_required_here (&str
) == FAIL
)
7841 if (skip_past_comma (&str
) == FAIL
7842 || reg_required_here (&str
, 12) == FAIL
)
7845 inst
.error
= BAD_ARGS
;
7853 do_vfp_sp_ldst (char * str
)
7855 skip_whitespace (str
);
7857 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7860 inst
.error
= BAD_ARGS
;
7864 if (skip_past_comma (&str
) == FAIL
7865 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
7868 inst
.error
= BAD_ARGS
;
7876 do_vfp_dp_ldst (char * str
)
7878 skip_whitespace (str
);
7880 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7883 inst
.error
= BAD_ARGS
;
7887 if (skip_past_comma (&str
) == FAIL
7888 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
7891 inst
.error
= BAD_ARGS
;
7900 vfp_sp_ldstm (char * str
, enum vfp_ldstm_type ldstm_type
)
7905 skip_whitespace (str
);
7907 if (reg_required_here (&str
, 16) == FAIL
)
7910 skip_whitespace (str
);
7914 inst
.instruction
|= WRITE_BACK
;
7917 else if (ldstm_type
!= VFP_LDSTMIA
)
7919 inst
.error
= _("this addressing mode requires base-register writeback");
7923 if (skip_past_comma (&str
) == FAIL
7924 || (count
= vfp_parse_reg_list (&str
, ®
, 0)) == FAIL
)
7927 inst
.error
= BAD_ARGS
;
7930 vfp_sp_encode_reg (reg
, VFP_REG_Sd
);
7932 inst
.instruction
|= count
;
7937 vfp_dp_ldstm (char * str
, enum vfp_ldstm_type ldstm_type
)
7942 skip_whitespace (str
);
7944 if (reg_required_here (&str
, 16) == FAIL
)
7947 skip_whitespace (str
);
7951 inst
.instruction
|= WRITE_BACK
;
7954 else if (ldstm_type
!= VFP_LDSTMIA
&& ldstm_type
!= VFP_LDSTMIAX
)
7956 inst
.error
= _("this addressing mode requires base-register writeback");
7960 if (skip_past_comma (&str
) == FAIL
7961 || (count
= vfp_parse_reg_list (&str
, ®
, 1)) == FAIL
)
7964 inst
.error
= BAD_ARGS
;
7969 if (ldstm_type
== VFP_LDSTMIAX
|| ldstm_type
== VFP_LDSTMDBX
)
7972 inst
.instruction
|= (reg
<< 12) | count
;
7977 do_vfp_sp_ldstmia (char * str
)
7979 vfp_sp_ldstm (str
, VFP_LDSTMIA
);
7983 do_vfp_sp_ldstmdb (char * str
)
7985 vfp_sp_ldstm (str
, VFP_LDSTMDB
);
7989 do_vfp_dp_ldstmia (char * str
)
7991 vfp_dp_ldstm (str
, VFP_LDSTMIA
);
7995 do_vfp_dp_ldstmdb (char * str
)
7997 vfp_dp_ldstm (str
, VFP_LDSTMDB
);
8001 do_vfp_xp_ldstmia (char *str
)
8003 vfp_dp_ldstm (str
, VFP_LDSTMIAX
);
8007 do_vfp_xp_ldstmdb (char * str
)
8009 vfp_dp_ldstm (str
, VFP_LDSTMDBX
);
8013 do_vfp_sp_compare_z (char * str
)
8015 skip_whitespace (str
);
8017 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8020 inst
.error
= BAD_ARGS
;
8028 do_vfp_dp_compare_z (char * str
)
8030 skip_whitespace (str
);
8032 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8035 inst
.error
= BAD_ARGS
;
8043 do_vfp_dp_sp_cvt (char * str
)
8045 skip_whitespace (str
);
8047 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8050 if (skip_past_comma (&str
) == FAIL
8051 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
8054 inst
.error
= BAD_ARGS
;
8062 do_vfp_sp_dp_cvt (char * str
)
8064 skip_whitespace (str
);
8066 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8069 if (skip_past_comma (&str
) == FAIL
8070 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
8073 inst
.error
= BAD_ARGS
;
8080 /* Thumb specific routines. */
8082 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
8086 thumb_add_sub (char * str
, int subtract
)
8088 int Rd
, Rs
, Rn
= FAIL
;
8090 skip_whitespace (str
);
8092 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
8093 || skip_past_comma (&str
) == FAIL
)
8096 inst
.error
= BAD_ARGS
;
8100 if (is_immediate_prefix (*str
))
8104 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8109 if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8112 if (skip_past_comma (&str
) == FAIL
)
8114 /* Two operand format, shuffle the registers
8115 and pretend there are 3. */
8119 else if (is_immediate_prefix (*str
))
8122 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8125 else if ((Rn
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8129 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8130 for the latter case, EXPR contains the immediate that was found. */
8133 /* All register format. */
8134 if (Rd
> 7 || Rs
> 7 || Rn
> 7)
8138 inst
.error
= _("dest and source1 must be the same register");
8142 /* Can't do this for SUB. */
8145 inst
.error
= _("subtract valid only on lo regs");
8149 inst
.instruction
= (T_OPCODE_ADD_HI
8150 | (Rd
> 7 ? THUMB_H1
: 0)
8151 | (Rn
> 7 ? THUMB_H2
: 0));
8152 inst
.instruction
|= (Rd
& 7) | ((Rn
& 7) << 3);
8156 inst
.instruction
= subtract
? T_OPCODE_SUB_R3
: T_OPCODE_ADD_R3
;
8157 inst
.instruction
|= Rd
| (Rs
<< 3) | (Rn
<< 6);
8162 /* Immediate expression, now things start to get nasty. */
8164 /* First deal with HI regs, only very restricted cases allowed:
8165 Adjusting SP, and using PC or SP to get an address. */
8166 if ((Rd
> 7 && (Rd
!= REG_SP
|| Rs
!= REG_SP
))
8167 || (Rs
> 7 && Rs
!= REG_SP
&& Rs
!= REG_PC
))
8169 inst
.error
= _("invalid Hi register with immediate");
8173 if (inst
.reloc
.exp
.X_op
!= O_constant
)
8175 /* Value isn't known yet, all we can do is store all the fragments
8176 we know about in the instruction and let the reloc hacking
8178 inst
.instruction
= (subtract
? 0x8000 : 0) | (Rd
<< 4) | Rs
;
8179 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
8183 int offset
= inst
.reloc
.exp
.X_add_number
;
8193 /* Quick check, in case offset is MIN_INT. */
8196 inst
.error
= _("immediate value out of range");
8200 /* Note - you cannot convert a subtract of 0 into an
8201 add of 0 because the carry flag is set differently. */
8202 else if (offset
> 0)
8207 if (offset
& ~0x1fc)
8209 inst
.error
= _("invalid immediate value for stack adjust");
8212 inst
.instruction
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
8213 inst
.instruction
|= offset
>> 2;
8215 else if (Rs
== REG_PC
|| Rs
== REG_SP
)
8218 || (offset
& ~0x3fc))
8220 inst
.error
= _("invalid immediate for address calculation");
8223 inst
.instruction
= (Rs
== REG_PC
? T_OPCODE_ADD_PC
8225 inst
.instruction
|= (Rd
<< 8) | (offset
>> 2);
8231 inst
.error
= _("immediate value out of range");
8234 inst
.instruction
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
8235 inst
.instruction
|= (Rd
<< 8) | offset
;
8241 inst
.error
= _("immediate value out of range");
8244 inst
.instruction
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
8245 inst
.instruction
|= Rd
| (Rs
<< 3) | (offset
<< 6);
8254 thumb_shift (char * str
, int shift
)
8256 int Rd
, Rs
, Rn
= FAIL
;
8258 skip_whitespace (str
);
8260 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
8261 || skip_past_comma (&str
) == FAIL
)
8264 inst
.error
= BAD_ARGS
;
8268 if (is_immediate_prefix (*str
))
8270 /* Two operand immediate format, set Rs to Rd. */
8273 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8278 if ((Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8281 if (skip_past_comma (&str
) == FAIL
)
8283 /* Two operand format, shuffle the registers
8284 and pretend there are 3. */
8288 else if (is_immediate_prefix (*str
))
8291 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8294 else if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8298 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8299 for the latter case, EXPR contains the immediate that was found. */
8305 inst
.error
= _("source1 and dest must be same register");
8311 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_R
; break;
8312 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_R
; break;
8313 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_R
; break;
8316 inst
.instruction
|= Rd
| (Rn
<< 3);
8322 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_I
; break;
8323 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_I
; break;
8324 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_I
; break;
8327 if (inst
.reloc
.exp
.X_op
!= O_constant
)
8329 /* Value isn't known yet, create a dummy reloc and let reloc
8330 hacking fix it up. */
8331 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_SHIFT
;
8335 unsigned shift_value
= inst
.reloc
.exp
.X_add_number
;
8337 if (shift_value
> 32 || (shift_value
== 32 && shift
== THUMB_LSL
))
8339 inst
.error
= _("invalid immediate for shift");
8343 /* Shifts of zero are handled by converting to LSL. */
8344 if (shift_value
== 0)
8345 inst
.instruction
= T_OPCODE_LSL_I
;
8347 /* Shifts of 32 are encoded as a shift of zero. */
8348 if (shift_value
== 32)
8351 inst
.instruction
|= shift_value
<< 6;
8354 inst
.instruction
|= Rd
| (Rs
<< 3);
8361 thumb_load_store (char * str
, int load_store
, int size
)
8363 int Rd
, Rb
, Ro
= FAIL
;
8365 skip_whitespace (str
);
8367 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
8368 || skip_past_comma (&str
) == FAIL
)
8371 inst
.error
= BAD_ARGS
;
8378 if ((Rb
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8381 if (skip_past_comma (&str
) != FAIL
)
8383 if (is_immediate_prefix (*str
))
8386 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8389 else if ((Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8394 inst
.reloc
.exp
.X_op
= O_constant
;
8395 inst
.reloc
.exp
.X_add_number
= 0;
8400 inst
.error
= _("expected ']'");
8405 else if (*str
== '=')
8407 if (load_store
!= THUMB_LOAD
)
8409 inst
.error
= _("invalid pseudo operation");
8413 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
8416 skip_whitespace (str
);
8418 if (my_get_expression (& inst
.reloc
.exp
, & str
))
8423 if ( inst
.reloc
.exp
.X_op
!= O_constant
8424 && inst
.reloc
.exp
.X_op
!= O_symbol
)
8426 inst
.error
= "Constant expression expected";
8430 if (inst
.reloc
.exp
.X_op
== O_constant
8431 && ((inst
.reloc
.exp
.X_add_number
& ~0xFF) == 0))
8433 /* This can be done with a mov instruction. */
8435 inst
.instruction
= T_OPCODE_MOV_I8
| (Rd
<< 8);
8436 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
8440 /* Insert into literal pool. */
8441 if (add_to_lit_pool () == FAIL
)
8444 inst
.error
= "literal pool insertion failed";
8448 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8449 inst
.reloc
.pc_rel
= 1;
8450 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
8451 /* Adjust ARM pipeline offset to Thumb. */
8452 inst
.reloc
.exp
.X_add_number
+= 4;
8458 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8461 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
8462 inst
.reloc
.pc_rel
= 1;
8463 inst
.reloc
.exp
.X_add_number
-= 4; /* Pipeline offset. */
8464 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8469 if (Rb
== REG_PC
|| Rb
== REG_SP
)
8471 if (size
!= THUMB_WORD
)
8473 inst
.error
= _("byte or halfword not valid for base register");
8476 else if (Rb
== REG_PC
&& load_store
!= THUMB_LOAD
)
8478 inst
.error
= _("r15 based store not allowed");
8481 else if (Ro
!= FAIL
)
8483 inst
.error
= _("invalid base register for register offset");
8488 inst
.instruction
= T_OPCODE_LDR_PC
;
8489 else if (load_store
== THUMB_LOAD
)
8490 inst
.instruction
= T_OPCODE_LDR_SP
;
8492 inst
.instruction
= T_OPCODE_STR_SP
;
8494 inst
.instruction
|= Rd
<< 8;
8495 if (inst
.reloc
.exp
.X_op
== O_constant
)
8497 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
8499 if (offset
& ~0x3fc)
8501 inst
.error
= _("invalid offset");
8505 inst
.instruction
|= offset
>> 2;
8508 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8512 inst
.error
= _("invalid base register in load/store");
8515 else if (Ro
== FAIL
)
8517 /* Immediate offset. */
8518 if (size
== THUMB_WORD
)
8519 inst
.instruction
= (load_store
== THUMB_LOAD
8520 ? T_OPCODE_LDR_IW
: T_OPCODE_STR_IW
);
8521 else if (size
== THUMB_HALFWORD
)
8522 inst
.instruction
= (load_store
== THUMB_LOAD
8523 ? T_OPCODE_LDR_IH
: T_OPCODE_STR_IH
);
8525 inst
.instruction
= (load_store
== THUMB_LOAD
8526 ? T_OPCODE_LDR_IB
: T_OPCODE_STR_IB
);
8528 inst
.instruction
|= Rd
| (Rb
<< 3);
8530 if (inst
.reloc
.exp
.X_op
== O_constant
)
8532 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
8534 if (offset
& ~(0x1f << size
))
8536 inst
.error
= _("invalid offset");
8539 inst
.instruction
|= (offset
>> size
) << 6;
8542 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8546 /* Register offset. */
8547 if (size
== THUMB_WORD
)
8548 inst
.instruction
= (load_store
== THUMB_LOAD
8549 ? T_OPCODE_LDR_RW
: T_OPCODE_STR_RW
);
8550 else if (size
== THUMB_HALFWORD
)
8551 inst
.instruction
= (load_store
== THUMB_LOAD
8552 ? T_OPCODE_LDR_RH
: T_OPCODE_STR_RH
);
8554 inst
.instruction
= (load_store
== THUMB_LOAD
8555 ? T_OPCODE_LDR_RB
: T_OPCODE_STR_RB
);
8557 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
8563 /* A register must be given at this point.
8565 Shift is the place to put it in inst.instruction.
8567 Restores input start point on err.
8568 Returns the reg#, or FAIL. */
8571 mav_reg_required_here (char ** str
, int shift
, enum arm_reg_type regtype
)
8576 if ((reg
= arm_reg_parse (str
, all_reg_maps
[regtype
].htab
)) != FAIL
)
8579 inst
.instruction
|= reg
<< shift
;
8584 /* Restore the start point. */
8587 /* Try generic coprocessor name if applicable. */
8588 if (regtype
== REG_TYPE_MVF
||
8589 regtype
== REG_TYPE_MVD
||
8590 regtype
== REG_TYPE_MVFX
||
8591 regtype
== REG_TYPE_MVDX
)
8593 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CN
].htab
)) != FAIL
)
8596 inst
.instruction
|= reg
<< shift
;
8601 /* Restore the start point. */
8605 /* In the few cases where we might be able to accept something else
8606 this error can be overridden. */
8607 inst
.error
= _(all_reg_maps
[regtype
].expected
);
8612 /* Cirrus Maverick Instructions. */
8614 /* Isnsn like "foo X,Y". */
8617 do_mav_binops (char * str
,
8619 enum arm_reg_type reg0
,
8620 enum arm_reg_type reg1
)
8624 shift0
= mode
& 0xff;
8625 shift1
= (mode
>> 8) & 0xff;
8627 skip_whitespace (str
);
8629 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
8630 || skip_past_comma (&str
) == FAIL
8631 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
)
8634 inst
.error
= BAD_ARGS
;
8640 /* Isnsn like "foo X,Y,Z". */
8643 do_mav_triple (char * str
,
8645 enum arm_reg_type reg0
,
8646 enum arm_reg_type reg1
,
8647 enum arm_reg_type reg2
)
8649 int shift0
, shift1
, shift2
;
8651 shift0
= mode
& 0xff;
8652 shift1
= (mode
>> 8) & 0xff;
8653 shift2
= (mode
>> 16) & 0xff;
8655 skip_whitespace (str
);
8657 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
8658 || skip_past_comma (&str
) == FAIL
8659 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
8660 || skip_past_comma (&str
) == FAIL
8661 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
)
8664 inst
.error
= BAD_ARGS
;
8670 /* Wrapper functions. */
8673 do_mav_binops_1a (char * str
)
8675 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVF
);
8679 do_mav_binops_1b (char * str
)
8681 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVD
);
8685 do_mav_binops_1c (char * str
)
8687 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVDX
);
8691 do_mav_binops_1d (char * str
)
8693 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVF
);
8697 do_mav_binops_1e (char * str
)
8699 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVD
);
8703 do_mav_binops_1f (char * str
)
8705 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVF
);
8709 do_mav_binops_1g (char * str
)
8711 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVD
);
8715 do_mav_binops_1h (char * str
)
8717 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVFX
);
8721 do_mav_binops_1i (char * str
)
8723 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVFX
);
8727 do_mav_binops_1j (char * str
)
8729 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVDX
);
8733 do_mav_binops_1k (char * str
)
8735 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVDX
);
8739 do_mav_binops_1l (char * str
)
8741 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVF
);
8745 do_mav_binops_1m (char * str
)
8747 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVD
);
8751 do_mav_binops_1n (char * str
)
8753 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
8757 do_mav_binops_1o (char * str
)
8759 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
8763 do_mav_binops_2a (char * str
)
8765 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVF
, REG_TYPE_RN
);
8769 do_mav_binops_2b (char * str
)
8771 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVD
, REG_TYPE_RN
);
8775 do_mav_binops_2c (char * str
)
8777 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVDX
, REG_TYPE_RN
);
8781 do_mav_binops_3a (char * str
)
8783 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVFX
);
8787 do_mav_binops_3b (char * str
)
8789 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVFX
, REG_TYPE_MVAX
);
8793 do_mav_binops_3c (char * str
)
8795 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVDX
);
8799 do_mav_binops_3d (char * str
)
8801 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVDX
, REG_TYPE_MVAX
);
8805 do_mav_triple_4a (char * str
)
8807 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_RN
);
8811 do_mav_triple_4b (char * str
)
8813 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_RN
);
8817 do_mav_triple_5a (char * str
)
8819 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVF
, REG_TYPE_MVF
);
8823 do_mav_triple_5b (char * str
)
8825 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVD
, REG_TYPE_MVD
);
8829 do_mav_triple_5c (char * str
)
8831 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
8835 do_mav_triple_5d (char * str
)
8837 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
8841 do_mav_triple_5e (char * str
)
8843 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVF
, REG_TYPE_MVF
, REG_TYPE_MVF
);
8847 do_mav_triple_5f (char * str
)
8849 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVD
, REG_TYPE_MVD
, REG_TYPE_MVD
);
8853 do_mav_triple_5g (char * str
)
8855 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
8859 do_mav_triple_5h (char * str
)
8861 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
8864 /* Isnsn like "foo W,X,Y,Z".
8865 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
8868 do_mav_quad (char * str
,
8870 enum arm_reg_type reg0
,
8871 enum arm_reg_type reg1
,
8872 enum arm_reg_type reg2
,
8873 enum arm_reg_type reg3
)
8875 int shift0
, shift1
, shift2
, shift3
;
8877 shift0
= mode
& 0xff;
8878 shift1
= (mode
>> 8) & 0xff;
8879 shift2
= (mode
>> 16) & 0xff;
8880 shift3
= (mode
>> 24) & 0xff;
8882 skip_whitespace (str
);
8884 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
8885 || skip_past_comma (&str
) == FAIL
8886 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
8887 || skip_past_comma (&str
) == FAIL
8888 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
8889 || skip_past_comma (&str
) == FAIL
8890 || mav_reg_required_here (&str
, shift3
, reg3
) == FAIL
)
8893 inst
.error
= BAD_ARGS
;
8900 do_mav_quad_6a (char * str
)
8902 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
,
8907 do_mav_quad_6b (char * str
)
8909 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVAX
, REG_TYPE_MVFX
,
8913 /* cfmvsc32<cond> DSPSC,MVDX[15:0]. */
8915 do_mav_dspsc_1 (char * str
)
8917 skip_whitespace (str
);
8920 if (mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
8921 || skip_past_comma (&str
) == FAIL
8922 || mav_reg_required_here (&str
, 12, REG_TYPE_MVDX
) == FAIL
)
8925 inst
.error
= BAD_ARGS
;
8933 /* cfmv32sc<cond> MVDX[15:0],DSPSC. */
8935 do_mav_dspsc_2 (char * str
)
8937 skip_whitespace (str
);
8940 if (mav_reg_required_here (&str
, 12, REG_TYPE_MVDX
) == FAIL
8941 || skip_past_comma (&str
) == FAIL
8942 || mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
)
8945 inst
.error
= BAD_ARGS
;
8953 /* Maverick shift immediate instructions.
8954 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
8955 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
8958 do_mav_shift (char * str
,
8959 enum arm_reg_type reg0
,
8960 enum arm_reg_type reg1
)
8965 skip_whitespace (str
);
8969 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
8970 || skip_past_comma (&str
) == FAIL
8971 || mav_reg_required_here (&str
, 16, reg1
) == FAIL
8972 || skip_past_comma (&str
) == FAIL
)
8975 inst
.error
= BAD_ARGS
;
8979 /* Calculate the immediate operand.
8980 The operand is a 7bit signed number. */
8981 skip_whitespace (str
);
8986 if (!ISDIGIT (*str
) && *str
!= '-')
8988 inst
.error
= _("expecting immediate, 7bit operand");
8998 for (imm
= 0; *str
&& ISDIGIT (*str
); ++str
)
8999 imm
= imm
* 10 + *str
- '0';
9003 inst
.error
= _("immediate out of range");
9007 /* Make negative imm's into 7bit signed numbers. */
9014 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
9015 Bits 5-7 of the insn should have bits 4-6 of the immediate.
9016 Bit 4 should be 0. */
9017 imm
= (imm
& 0xf) | ((imm
& 0x70) << 1);
9019 inst
.instruction
|= imm
;
9024 do_mav_shift_1 (char * str
)
9026 do_mav_shift (str
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
9030 do_mav_shift_2 (char * str
)
9032 do_mav_shift (str
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
9036 mav_parse_offset (char ** str
, int * negative
)
9043 skip_whitespace (p
);
9056 inst
.error
= _("offset expected");
9060 for (offset
= 0; *p
&& ISDIGIT (*p
); ++p
)
9061 offset
= offset
* 10 + *p
- '0';
9065 inst
.error
= _("offset out of range");
9070 inst
.error
= _("offset not a multiple of 4");
9076 return *negative
? -offset
: offset
;
9079 /* Maverick load/store instructions.
9080 <insn><cond> CRd,[Rn,<offset>]{!}.
9081 <insn><cond> CRd,[Rn],<offset>. */
9084 do_mav_ldst (char * str
, enum arm_reg_type reg0
)
9086 int offset
, negative
;
9088 skip_whitespace (str
);
9090 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
9091 || skip_past_comma (&str
) == FAIL
9093 || reg_required_here (&str
, 16) == FAIL
)
9096 if (skip_past_comma (&str
) == SUCCESS
)
9098 /* You are here: "<offset>]{!}". */
9099 inst
.instruction
|= PRE_INDEX
;
9101 offset
= mav_parse_offset (&str
, &negative
);
9108 inst
.error
= _("missing ]");
9114 inst
.instruction
|= WRITE_BACK
;
9120 /* You are here: "], <offset>". */
9123 inst
.error
= _("missing ]");
9127 if (skip_past_comma (&str
) == FAIL
9128 || (offset
= mav_parse_offset (&str
, &negative
), inst
.error
))
9131 inst
.instruction
|= CP_T_WB
; /* Post indexed, set bit W. */
9137 inst
.instruction
|= CP_T_UD
; /* Positive, so set bit U. */
9139 inst
.instruction
|= offset
>> 2;
9145 inst
.error
= BAD_ARGS
;
9149 do_mav_ldst_1 (char * str
)
9151 do_mav_ldst (str
, REG_TYPE_MVF
);
9155 do_mav_ldst_2 (char * str
)
9157 do_mav_ldst (str
, REG_TYPE_MVD
);
9161 do_mav_ldst_3 (char * str
)
9163 do_mav_ldst (str
, REG_TYPE_MVFX
);
9167 do_mav_ldst_4 (char * str
)
9169 do_mav_ldst (str
, REG_TYPE_MVDX
);
9173 do_t_nop (char * str
)
9179 /* Handle the Format 4 instructions that do not have equivalents in other
9180 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
9184 do_t_arit (char * str
)
9188 skip_whitespace (str
);
9190 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9191 || skip_past_comma (&str
) == FAIL
9192 || (Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9194 inst
.error
= BAD_ARGS
;
9198 if (skip_past_comma (&str
) != FAIL
)
9200 /* Three operand format not allowed for TST, CMN, NEG and MVN.
9201 (It isn't allowed for CMP either, but that isn't handled by this
9203 if (inst
.instruction
== T_OPCODE_TST
9204 || inst
.instruction
== T_OPCODE_CMN
9205 || inst
.instruction
== T_OPCODE_NEG
9206 || inst
.instruction
== T_OPCODE_MVN
)
9208 inst
.error
= BAD_ARGS
;
9212 if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9217 inst
.error
= _("dest and source1 must be the same register");
9223 if (inst
.instruction
== T_OPCODE_MUL
9225 as_tsktsk (_("Rs and Rd must be different in MUL"));
9227 inst
.instruction
|= Rd
| (Rs
<< 3);
9232 do_t_add (char * str
)
9234 thumb_add_sub (str
, 0);
9238 do_t_asr (char * str
)
9240 thumb_shift (str
, THUMB_ASR
);
9244 do_t_branch9 (char * str
)
9246 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9248 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH9
;
9249 inst
.reloc
.pc_rel
= 1;
9254 do_t_branch12 (char * str
)
9256 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9258 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH12
;
9259 inst
.reloc
.pc_rel
= 1;
9263 /* Find the real, Thumb encoded start of a Thumb function. */
9266 find_real_start (symbolS
* symbolP
)
9269 const char * name
= S_GET_NAME (symbolP
);
9270 symbolS
* new_target
;
9272 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
9273 #define STUB_NAME ".real_start_of"
9278 /* Names that start with '.' are local labels, not function entry points.
9279 The compiler may generate BL instructions to these labels because it
9280 needs to perform a branch to a far away location. */
9284 real_start
= malloc (strlen (name
) + strlen (STUB_NAME
) + 1);
9285 sprintf (real_start
, "%s%s", STUB_NAME
, name
);
9287 new_target
= symbol_find (real_start
);
9289 if (new_target
== NULL
)
9291 as_warn ("Failed to find real start of function: %s\n", name
);
9292 new_target
= symbolP
;
9301 do_t_branch23 (char * str
)
9303 if (my_get_expression (& inst
.reloc
.exp
, & str
))
9306 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH23
;
9307 inst
.reloc
.pc_rel
= 1;
9310 /* If the destination of the branch is a defined symbol which does not have
9311 the THUMB_FUNC attribute, then we must be calling a function which has
9312 the (interfacearm) attribute. We look for the Thumb entry point to that
9313 function and change the branch to refer to that function instead. */
9314 if ( inst
.reloc
.exp
.X_op
== O_symbol
9315 && inst
.reloc
.exp
.X_add_symbol
!= NULL
9316 && S_IS_DEFINED (inst
.reloc
.exp
.X_add_symbol
)
9317 && ! THUMB_IS_FUNC (inst
.reloc
.exp
.X_add_symbol
))
9318 inst
.reloc
.exp
.X_add_symbol
=
9319 find_real_start (inst
.reloc
.exp
.X_add_symbol
);
9323 do_t_bx (char * str
)
9327 skip_whitespace (str
);
9329 if ((reg
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
9332 /* This sets THUMB_H2 from the top bit of reg. */
9333 inst
.instruction
|= reg
<< 3;
9335 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
9336 should cause the alignment to be checked once it is known. This is
9337 because BX PC only works if the instruction is word aligned. */
9343 do_t_compare (char * str
)
9345 thumb_mov_compare (str
, THUMB_COMPARE
);
9349 do_t_ldmstm (char * str
)
9354 skip_whitespace (str
);
9356 if ((Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9360 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
9364 if (skip_past_comma (&str
) == FAIL
9365 || (range
= reg_list (&str
)) == FAIL
)
9368 inst
.error
= BAD_ARGS
;
9372 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
9374 /* This really doesn't seem worth it. */
9375 inst
.reloc
.type
= BFD_RELOC_NONE
;
9376 inst
.error
= _("expression too complex");
9382 inst
.error
= _("only lo-regs valid in load/store multiple");
9386 inst
.instruction
|= (Rb
<< 8) | range
;
9391 do_t_ldr (char * str
)
9393 thumb_load_store (str
, THUMB_LOAD
, THUMB_WORD
);
9397 do_t_ldrb (char * str
)
9399 thumb_load_store (str
, THUMB_LOAD
, THUMB_BYTE
);
9403 do_t_ldrh (char * str
)
9405 thumb_load_store (str
, THUMB_LOAD
, THUMB_HALFWORD
);
9409 do_t_lds (char * str
)
9413 skip_whitespace (str
);
9415 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9416 || skip_past_comma (&str
) == FAIL
9418 || (Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9419 || skip_past_comma (&str
) == FAIL
9420 || (Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9424 inst
.error
= _("syntax: ldrs[b] Rd, [Rb, Ro]");
9428 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
9433 do_t_lsl (char * str
)
9435 thumb_shift (str
, THUMB_LSL
);
9439 do_t_lsr (char * str
)
9441 thumb_shift (str
, THUMB_LSR
);
9445 do_t_mov (char * str
)
9447 thumb_mov_compare (str
, THUMB_MOVE
);
9451 do_t_push_pop (char * str
)
9455 skip_whitespace (str
);
9457 if ((range
= reg_list (&str
)) == FAIL
)
9460 inst
.error
= BAD_ARGS
;
9464 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
9466 /* This really doesn't seem worth it. */
9467 inst
.reloc
.type
= BFD_RELOC_NONE
;
9468 inst
.error
= _("expression too complex");
9474 if ((inst
.instruction
== T_OPCODE_PUSH
9475 && (range
& ~0xff) == 1 << REG_LR
)
9476 || (inst
.instruction
== T_OPCODE_POP
9477 && (range
& ~0xff) == 1 << REG_PC
))
9479 inst
.instruction
|= THUMB_PP_PC_LR
;
9484 inst
.error
= _("invalid register list to push/pop instruction");
9489 inst
.instruction
|= range
;
9494 do_t_str (char * str
)
9496 thumb_load_store (str
, THUMB_STORE
, THUMB_WORD
);
9500 do_t_strb (char * str
)
9502 thumb_load_store (str
, THUMB_STORE
, THUMB_BYTE
);
9506 do_t_strh (char * str
)
9508 thumb_load_store (str
, THUMB_STORE
, THUMB_HALFWORD
);
9512 do_t_sub (char * str
)
9514 thumb_add_sub (str
, 1);
9518 do_t_swi (char * str
)
9520 skip_whitespace (str
);
9522 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9525 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
9530 do_t_adr (char * str
)
9534 /* This is a pseudo-op of the form "adr rd, label" to be converted
9535 into a relative address of the form "add rd, pc, #label-.-4". */
9536 skip_whitespace (str
);
9538 /* Store Rd in temporary location inside instruction. */
9539 if ((reg
= reg_required_here (&str
, 4)) == FAIL
9540 || (reg
> 7) /* For Thumb reg must be r0..r7. */
9541 || skip_past_comma (&str
) == FAIL
9542 || my_get_expression (&inst
.reloc
.exp
, &str
))
9545 inst
.error
= BAD_ARGS
;
9549 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
9550 inst
.reloc
.exp
.X_add_number
-= 4; /* PC relative adjust. */
9551 inst
.reloc
.pc_rel
= 1;
9552 inst
.instruction
|= REG_PC
; /* Rd is already placed into the instruction. */
9558 insert_reg (const struct reg_entry
* r
,
9559 struct hash_control
* htab
)
9561 int len
= strlen (r
->name
) + 2;
9562 char * buf
= xmalloc (len
);
9563 char * buf2
= xmalloc (len
);
9566 #ifdef REGISTER_PREFIX
9567 buf
[i
++] = REGISTER_PREFIX
;
9570 strcpy (buf
+ i
, r
->name
);
9572 for (i
= 0; buf
[i
]; i
++)
9573 buf2
[i
] = TOUPPER (buf
[i
]);
9577 hash_insert (htab
, buf
, (PTR
) r
);
9578 hash_insert (htab
, buf2
, (PTR
) r
);
9582 build_reg_hsh (struct reg_map
* map
)
9584 const struct reg_entry
*r
;
9586 if ((map
->htab
= hash_new ()) == NULL
)
9587 as_fatal (_("virtual memory exhausted"));
9589 for (r
= map
->names
; r
->name
!= NULL
; r
++)
9590 insert_reg (r
, map
->htab
);
9594 insert_reg_alias (char * str
,
9596 struct hash_control
*htab
)
9599 struct reg_entry
* new = xmalloc (sizeof (struct reg_entry
));
9600 const char * name
= xmalloc (strlen (str
) + 1);
9602 strcpy ((char *) name
, str
);
9605 new->number
= regnum
;
9606 new->builtin
= FALSE
;
9608 error
= hash_insert (htab
, name
, (PTR
) new);
9611 as_bad (_("failed to create an alias for %s, reason: %s"),
9613 free ((char *) name
);
9618 /* Look for the .req directive. This is of the form:
9620 new_register_name .req existing_register_name
9622 If we find one, or if it looks sufficiently like one that we want to
9623 handle any error here, return non-zero. Otherwise return zero. */
9626 create_register_alias (char * newname
, char * p
)
9632 skip_whitespace (q
);
9637 if (*q
&& !strncmp (q
, ".req ", 5))
9642 #ifndef IGNORE_OPCODE_CASE
9643 newname
= original_case_string
;
9645 copy_of_str
= newname
;
9648 skip_whitespace (q
);
9650 for (r
= q
; *r
!= '\0'; r
++)
9656 enum arm_reg_type new_type
, old_type
;
9661 old_type
= arm_reg_parse_any (q
);
9664 new_type
= arm_reg_parse_any (newname
);
9666 if (new_type
== REG_TYPE_MAX
)
9668 if (old_type
!= REG_TYPE_MAX
)
9670 old_regno
= arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
);
9671 insert_reg_alias (newname
, old_regno
,
9672 all_reg_maps
[old_type
].htab
);
9675 as_warn (_("register '%s' does not exist\n"), q
);
9677 else if (old_type
== REG_TYPE_MAX
)
9679 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
9684 /* Do not warn about redefinitions to the same alias. */
9685 if (new_type
!= old_type
9686 || (arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
)
9687 != arm_reg_parse (&q
, all_reg_maps
[new_type
].htab
)))
9688 as_warn (_("ignoring redefinition of register alias '%s'"),
9694 as_warn (_("ignoring incomplete .req pseuso op"));
9705 set_constant_flonums (void)
9709 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
9710 if (atof_ieee ((char *) fp_const
[i
], 'x', fp_values
[i
]) == NULL
)
9715 static const struct asm_opcode insns
[] =
9717 /* Core ARM Instructions. */
9718 {"and", 0xe0000000, 3, ARM_EXT_V1
, do_arit
},
9719 {"ands", 0xe0100000, 3, ARM_EXT_V1
, do_arit
},
9720 {"eor", 0xe0200000, 3, ARM_EXT_V1
, do_arit
},
9721 {"eors", 0xe0300000, 3, ARM_EXT_V1
, do_arit
},
9722 {"sub", 0xe0400000, 3, ARM_EXT_V1
, do_arit
},
9723 {"subs", 0xe0500000, 3, ARM_EXT_V1
, do_arit
},
9724 {"rsb", 0xe0600000, 3, ARM_EXT_V1
, do_arit
},
9725 {"rsbs", 0xe0700000, 3, ARM_EXT_V1
, do_arit
},
9726 {"add", 0xe0800000, 3, ARM_EXT_V1
, do_arit
},
9727 {"adds", 0xe0900000, 3, ARM_EXT_V1
, do_arit
},
9728 {"adc", 0xe0a00000, 3, ARM_EXT_V1
, do_arit
},
9729 {"adcs", 0xe0b00000, 3, ARM_EXT_V1
, do_arit
},
9730 {"sbc", 0xe0c00000, 3, ARM_EXT_V1
, do_arit
},
9731 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1
, do_arit
},
9732 {"rsc", 0xe0e00000, 3, ARM_EXT_V1
, do_arit
},
9733 {"rscs", 0xe0f00000, 3, ARM_EXT_V1
, do_arit
},
9734 {"orr", 0xe1800000, 3, ARM_EXT_V1
, do_arit
},
9735 {"orrs", 0xe1900000, 3, ARM_EXT_V1
, do_arit
},
9736 {"bic", 0xe1c00000, 3, ARM_EXT_V1
, do_arit
},
9737 {"bics", 0xe1d00000, 3, ARM_EXT_V1
, do_arit
},
9739 {"tst", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
9740 {"tsts", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
9741 {"tstp", 0xe110f000, 3, ARM_EXT_V1
, do_cmp
},
9742 {"teq", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
9743 {"teqs", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
9744 {"teqp", 0xe130f000, 3, ARM_EXT_V1
, do_cmp
},
9745 {"cmp", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
9746 {"cmps", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
9747 {"cmpp", 0xe150f000, 3, ARM_EXT_V1
, do_cmp
},
9748 {"cmn", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
9749 {"cmns", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
9750 {"cmnp", 0xe170f000, 3, ARM_EXT_V1
, do_cmp
},
9752 {"mov", 0xe1a00000, 3, ARM_EXT_V1
, do_mov
},
9753 {"movs", 0xe1b00000, 3, ARM_EXT_V1
, do_mov
},
9754 {"mvn", 0xe1e00000, 3, ARM_EXT_V1
, do_mov
},
9755 {"mvns", 0xe1f00000, 3, ARM_EXT_V1
, do_mov
},
9757 {"ldr", 0xe4100000, 3, ARM_EXT_V1
, do_ldst
},
9758 {"ldrb", 0xe4500000, 3, ARM_EXT_V1
, do_ldst
},
9759 {"ldrt", 0xe4300000, 3, ARM_EXT_V1
, do_ldstt
},
9760 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1
, do_ldstt
},
9761 {"str", 0xe4000000, 3, ARM_EXT_V1
, do_ldst
},
9762 {"strb", 0xe4400000, 3, ARM_EXT_V1
, do_ldst
},
9763 {"strt", 0xe4200000, 3, ARM_EXT_V1
, do_ldstt
},
9764 {"strbt", 0xe4600000, 3, ARM_EXT_V1
, do_ldstt
},
9766 {"stmia", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
9767 {"stmib", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
9768 {"stmda", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
9769 {"stmdb", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
9770 {"stmfd", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
9771 {"stmfa", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
9772 {"stmea", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
9773 {"stmed", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
9775 {"ldmia", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
9776 {"ldmib", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
9777 {"ldmda", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
9778 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
9779 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
9780 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
9781 {"ldmea", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
9782 {"ldmed", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
9784 {"swi", 0xef000000, 3, ARM_EXT_V1
, do_swi
},
9786 /* XXX This is the wrong place to do this. Think multi-arch. */
9787 {"bl", 0xeb000000, 2, ARM_EXT_V1
, do_branch
},
9788 {"b", 0xea000000, 1, ARM_EXT_V1
, do_branch
},
9790 {"bl", 0xebfffffe, 2, ARM_EXT_V1
, do_branch
},
9791 {"b", 0xeafffffe, 1, ARM_EXT_V1
, do_branch
},
9795 {"adr", 0xe28f0000, 3, ARM_EXT_V1
, do_adr
},
9796 {"adrl", 0xe28f0000, 3, ARM_EXT_V1
, do_adrl
},
9797 {"nop", 0xe1a00000, 3, ARM_EXT_V1
, do_nop
},
9799 /* ARM 2 multiplies. */
9800 {"mul", 0xe0000090, 3, ARM_EXT_V2
, do_mul
},
9801 {"muls", 0xe0100090, 3, ARM_EXT_V2
, do_mul
},
9802 {"mla", 0xe0200090, 3, ARM_EXT_V2
, do_mla
},
9803 {"mlas", 0xe0300090, 3, ARM_EXT_V2
, do_mla
},
9805 /* Generic coprocessor instructions. */
9806 {"cdp", 0xee000000, 3, ARM_EXT_V2
, do_cdp
},
9807 {"ldc", 0xec100000, 3, ARM_EXT_V2
, do_lstc
},
9808 {"ldcl", 0xec500000, 3, ARM_EXT_V2
, do_lstc
},
9809 {"stc", 0xec000000, 3, ARM_EXT_V2
, do_lstc
},
9810 {"stcl", 0xec400000, 3, ARM_EXT_V2
, do_lstc
},
9811 {"mcr", 0xee000010, 3, ARM_EXT_V2
, do_co_reg
},
9812 {"mrc", 0xee100010, 3, ARM_EXT_V2
, do_co_reg
},
9814 /* ARM 3 - swp instructions. */
9815 {"swp", 0xe1000090, 3, ARM_EXT_V2S
, do_swap
},
9816 {"swpb", 0xe1400090, 3, ARM_EXT_V2S
, do_swap
},
9818 /* ARM 6 Status register instructions. */
9819 {"mrs", 0xe10f0000, 3, ARM_EXT_V3
, do_mrs
},
9820 {"msr", 0xe120f000, 3, ARM_EXT_V3
, do_msr
},
9821 /* ScottB: our code uses 0xe128f000 for msr.
9822 NickC: but this is wrong because the bits 16 through 19 are
9823 handled by the PSR_xxx defines above. */
9825 /* ARM 7M long multiplies. */
9826 {"smull", 0xe0c00090, 5, ARM_EXT_V3M
, do_mull
},
9827 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M
, do_mull
},
9828 {"umull", 0xe0800090, 5, ARM_EXT_V3M
, do_mull
},
9829 {"umulls", 0xe0900090, 5, ARM_EXT_V3M
, do_mull
},
9830 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M
, do_mull
},
9831 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M
, do_mull
},
9832 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M
, do_mull
},
9833 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M
, do_mull
},
9835 /* ARM Architecture 4. */
9836 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4
, do_ldstv4
},
9837 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4
, do_ldstv4
},
9838 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4
, do_ldstv4
},
9839 {"strh", 0xe00000b0, 3, ARM_EXT_V4
, do_ldstv4
},
9841 /* ARM Architecture 4T. */
9842 /* Note: bx (and blx) are required on V5, even if the processor does
9843 not support Thumb. */
9844 {"bx", 0xe12fff10, 2, ARM_EXT_V4T
| ARM_EXT_V5
, do_bx
},
9846 /* ARM Architecture 5T. */
9847 /* Note: blx has 2 variants, so the .value is set dynamically.
9848 Only one of the variants has conditional execution. */
9849 {"blx", 0xe0000000, 3, ARM_EXT_V5
, do_blx
},
9850 {"clz", 0xe16f0f10, 3, ARM_EXT_V5
, do_clz
},
9851 {"bkpt", 0xe1200070, 0, ARM_EXT_V5
, do_bkpt
},
9852 {"ldc2", 0xfc100000, 0, ARM_EXT_V5
, do_lstc2
},
9853 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5
, do_lstc2
},
9854 {"stc2", 0xfc000000, 0, ARM_EXT_V5
, do_lstc2
},
9855 {"stc2l", 0xfc400000, 0, ARM_EXT_V5
, do_lstc2
},
9856 {"cdp2", 0xfe000000, 0, ARM_EXT_V5
, do_cdp2
},
9857 {"mcr2", 0xfe000010, 0, ARM_EXT_V5
, do_co_reg2
},
9858 {"mrc2", 0xfe100010, 0, ARM_EXT_V5
, do_co_reg2
},
9860 /* ARM Architecture 5TExP. */
9861 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP
, do_smla
},
9862 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP
, do_smla
},
9863 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP
, do_smla
},
9864 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP
, do_smla
},
9866 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP
, do_smla
},
9867 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP
, do_smla
},
9869 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP
, do_smlal
},
9870 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP
, do_smlal
},
9871 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP
, do_smlal
},
9872 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP
, do_smlal
},
9874 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP
, do_smul
},
9875 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP
, do_smul
},
9876 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP
, do_smul
},
9877 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP
, do_smul
},
9879 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP
, do_smul
},
9880 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP
, do_smul
},
9882 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP
, do_qadd
},
9883 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP
, do_qadd
},
9884 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP
, do_qadd
},
9885 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP
, do_qadd
},
9887 /* ARM Architecture 5TE. */
9888 {"pld", 0xf450f000, 0, ARM_EXT_V5E
, do_pld
},
9889 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E
, do_ldrd
},
9890 {"strd", 0xe00000f0, 3, ARM_EXT_V5E
, do_ldrd
},
9892 {"mcrr", 0xec400000, 4, ARM_EXT_V5E
, do_co_reg2c
},
9893 {"mrrc", 0xec500000, 4, ARM_EXT_V5E
, do_co_reg2c
},
9895 /* ARM Architecture 5TEJ. */
9896 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J
, do_bxj
},
9899 { "cps", 0xf1020000, 0, ARM_EXT_V6
, do_cps
},
9900 { "cpsie", 0xf1080000, 0, ARM_EXT_V6
, do_cpsi
},
9901 { "cpsid", 0xf10C0000, 0, ARM_EXT_V6
, do_cpsi
},
9902 { "ldrex", 0xe1900f9f, 5, ARM_EXT_V6
, do_ldrex
},
9903 { "mcrr2", 0xfc400000, 0, ARM_EXT_V6
, do_co_reg2c
},
9904 { "mrrc2", 0xfc500000, 0, ARM_EXT_V6
, do_co_reg2c
},
9905 { "pkhbt", 0xe6800010, 5, ARM_EXT_V6
, do_pkhbt
},
9906 { "pkhtb", 0xe6800050, 5, ARM_EXT_V6
, do_pkhtb
},
9907 { "qadd16", 0xe6200f10, 6, ARM_EXT_V6
, do_qadd16
},
9908 { "qadd8", 0xe6200f90, 5, ARM_EXT_V6
, do_qadd16
},
9909 { "qaddsubx", 0xe6200f30, 8, ARM_EXT_V6
, do_qadd16
},
9910 { "qsub16", 0xe6200f70, 6, ARM_EXT_V6
, do_qadd16
},
9911 { "qsub8", 0xe6200ff0, 5, ARM_EXT_V6
, do_qadd16
},
9912 { "qsubaddx", 0xe6200f50, 8, ARM_EXT_V6
, do_qadd16
},
9913 { "sadd16", 0xe6100f10, 6, ARM_EXT_V6
, do_qadd16
},
9914 { "sadd8", 0xe6100f90, 5, ARM_EXT_V6
, do_qadd16
},
9915 { "saddsubx", 0xe6100f30, 8, ARM_EXT_V6
, do_qadd16
},
9916 { "shadd16", 0xe6300f10, 7, ARM_EXT_V6
, do_qadd16
},
9917 { "shadd8", 0xe6300f90, 6, ARM_EXT_V6
, do_qadd16
},
9918 { "shaddsubx", 0xe6300f30, 9, ARM_EXT_V6
, do_qadd16
},
9919 { "shsub16", 0xe6300f70, 7, ARM_EXT_V6
, do_qadd16
},
9920 { "shsub8", 0xe6300ff0, 6, ARM_EXT_V6
, do_qadd16
},
9921 { "shsubaddx", 0xe6300f50, 9, ARM_EXT_V6
, do_qadd16
},
9922 { "ssub16", 0xe6100f70, 6, ARM_EXT_V6
, do_qadd16
},
9923 { "ssub8", 0xe6100ff0, 5, ARM_EXT_V6
, do_qadd16
},
9924 { "ssubaddx", 0xe6100f50, 8, ARM_EXT_V6
, do_qadd16
},
9925 { "uadd16", 0xe6500f10, 6, ARM_EXT_V6
, do_qadd16
},
9926 { "uadd8", 0xe6500f90, 5, ARM_EXT_V6
, do_qadd16
},
9927 { "uaddsubx", 0xe6500f30, 8, ARM_EXT_V6
, do_qadd16
},
9928 { "uhadd16", 0xe6700f10, 7, ARM_EXT_V6
, do_qadd16
},
9929 { "uhadd8", 0xe6700f90, 6, ARM_EXT_V6
, do_qadd16
},
9930 { "uhaddsubx", 0xe6700f30, 9, ARM_EXT_V6
, do_qadd16
},
9931 { "uhsub16", 0xe6700f70, 7, ARM_EXT_V6
, do_qadd16
},
9932 { "uhsub8", 0xe6700ff0, 6, ARM_EXT_V6
, do_qadd16
},
9933 { "uhsubaddx", 0xe6700f50, 9, ARM_EXT_V6
, do_qadd16
},
9934 { "uqadd16", 0xe6600f10, 7, ARM_EXT_V6
, do_qadd16
},
9935 { "uqadd8", 0xe6600f90, 6, ARM_EXT_V6
, do_qadd16
},
9936 { "uqaddsubx", 0xe6600f30, 9, ARM_EXT_V6
, do_qadd16
},
9937 { "uqsub16", 0xe6600f70, 7, ARM_EXT_V6
, do_qadd16
},
9938 { "uqsub8", 0xe6600ff0, 6, ARM_EXT_V6
, do_qadd16
},
9939 { "uqsubaddx", 0xe6600f50, 9, ARM_EXT_V6
, do_qadd16
},
9940 { "usub16", 0xe6500f70, 6, ARM_EXT_V6
, do_qadd16
},
9941 { "usub8", 0xe6500ff0, 5, ARM_EXT_V6
, do_qadd16
},
9942 { "usubaddx", 0xe6500f50, 8, ARM_EXT_V6
, do_qadd16
},
9943 { "rev", 0xe6bf0f30, 3, ARM_EXT_V6
, do_rev
},
9944 { "rev16", 0xe6bf0fb0, 5, ARM_EXT_V6
, do_rev
},
9945 { "revsh", 0xe6ff0fb0, 5, ARM_EXT_V6
, do_rev
},
9946 { "rfeia", 0xf8900a00, 0, ARM_EXT_V6
, do_rfe
},
9947 { "rfeib", 0xf9900a00, 0, ARM_EXT_V6
, do_rfe
},
9948 { "rfeda", 0xf8100a00, 0, ARM_EXT_V6
, do_rfe
},
9949 { "rfedb", 0xf9100a00, 0, ARM_EXT_V6
, do_rfe
},
9950 { "rfefd", 0xf8900a00, 0, ARM_EXT_V6
, do_rfe
},
9951 { "rfefa", 0xf9900a00, 0, ARM_EXT_V6
, do_rfe
},
9952 { "rfeea", 0xf8100a00, 0, ARM_EXT_V6
, do_rfe
},
9953 { "rfeed", 0xf9100a00, 0, ARM_EXT_V6
, do_rfe
},
9954 { "sxtah", 0xe6b00070, 5, ARM_EXT_V6
, do_sxtah
},
9955 { "sxtab16", 0xe6800070, 7, ARM_EXT_V6
, do_sxtah
},
9956 { "sxtab", 0xe6a00070, 5, ARM_EXT_V6
, do_sxtah
},
9957 { "sxth", 0xe6bf0070, 4, ARM_EXT_V6
, do_sxth
},
9958 { "sxtb16", 0xe68f0070, 6, ARM_EXT_V6
, do_sxth
},
9959 { "sxtb", 0xe6af0070, 4, ARM_EXT_V6
, do_sxth
},
9960 { "uxtah", 0xe6f00070, 5, ARM_EXT_V6
, do_sxtah
},
9961 { "uxtab16", 0xe6c00070, 7, ARM_EXT_V6
, do_sxtah
},
9962 { "uxtab", 0xe6e00070, 5, ARM_EXT_V6
, do_sxtah
},
9963 { "uxth", 0xe6ff0070, 4, ARM_EXT_V6
, do_sxth
},
9964 { "uxtb16", 0xe6cf0070, 6, ARM_EXT_V6
, do_sxth
},
9965 { "uxtb", 0xe6ef0070, 4, ARM_EXT_V6
, do_sxth
},
9966 { "sel", 0xe68000b0, 3, ARM_EXT_V6
, do_qadd16
},
9967 { "setend", 0xf1010000, 0, ARM_EXT_V6
, do_setend
},
9968 { "smlad", 0xe7000010, 5, ARM_EXT_V6
, do_smlad
},
9969 { "smladx", 0xe7000030, 6, ARM_EXT_V6
, do_smlad
},
9970 { "smlald", 0xe7400010, 6, ARM_EXT_V6
, do_smlald
},
9971 { "smlaldx", 0xe7400030, 7, ARM_EXT_V6
, do_smlald
},
9972 { "smlsd", 0xe7000050, 5, ARM_EXT_V6
, do_smlad
},
9973 { "smlsdx", 0xe7000070, 6, ARM_EXT_V6
, do_smlad
},
9974 { "smlsld", 0xe7400050, 6, ARM_EXT_V6
, do_smlald
},
9975 { "smlsldx", 0xe7400070, 7, ARM_EXT_V6
, do_smlald
},
9976 { "smmla", 0xe7500010, 5, ARM_EXT_V6
, do_smlad
},
9977 { "smmlar", 0xe7500030, 6, ARM_EXT_V6
, do_smlad
},
9978 { "smmls", 0xe75000d0, 5, ARM_EXT_V6
, do_smlad
},
9979 { "smmlsr", 0xe75000f0, 6, ARM_EXT_V6
, do_smlad
},
9980 { "smmul", 0xe750f010, 5, ARM_EXT_V6
, do_smmul
},
9981 { "smmulr", 0xe750f030, 6, ARM_EXT_V6
, do_smmul
},
9982 { "smuad", 0xe700f010, 5, ARM_EXT_V6
, do_smmul
},
9983 { "smuadx", 0xe700f030, 6, ARM_EXT_V6
, do_smmul
},
9984 { "smusd", 0xe700f050, 5, ARM_EXT_V6
, do_smmul
},
9985 { "smusdx", 0xe700f070, 6, ARM_EXT_V6
, do_smmul
},
9986 { "srsia", 0xf8cd0500, 0, ARM_EXT_V6
, do_srs
},
9987 { "srsib", 0xf9cd0500, 0, ARM_EXT_V6
, do_srs
},
9988 { "srsda", 0xf84d0500, 0, ARM_EXT_V6
, do_srs
},
9989 { "srsdb", 0xf94d0500, 0, ARM_EXT_V6
, do_srs
},
9990 { "ssat", 0xe6a00010, 4, ARM_EXT_V6
, do_ssat
},
9991 { "ssat16", 0xe6a00f30, 6, ARM_EXT_V6
, do_ssat16
},
9992 { "strex", 0xe1800f90, 5, ARM_EXT_V6
, do_strex
},
9993 { "umaal", 0xe0400090, 5, ARM_EXT_V6
, do_umaal
},
9994 { "usad8", 0xe780f010, 5, ARM_EXT_V6
, do_smmul
},
9995 { "usada8", 0xe7800010, 6, ARM_EXT_V6
, do_smlad
},
9996 { "usat", 0xe6e00010, 4, ARM_EXT_V6
, do_usat
},
9997 { "usat16", 0xe6e00f30, 6, ARM_EXT_V6
, do_usat16
},
10000 { "clrex", 0xf57ff01f, 0, ARM_EXT_V6K
, do_empty
},
10001 { "ldrexb", 0xe1d00f9f, 6, ARM_EXT_V6K
, do_ldrex
},
10002 { "ldrexd", 0xe1b00f9f, 6, ARM_EXT_V6K
, do_ldrex
},
10003 { "ldrexh", 0xe1f00f9f, 6, ARM_EXT_V6K
, do_ldrex
},
10004 { "sev", 0xe320f004, 3, ARM_EXT_V6K
, do_empty
},
10005 { "strexb", 0xe1c00f90, 6, ARM_EXT_V6K
, do_strex
},
10006 { "strexd", 0xe1a00f90, 6, ARM_EXT_V6K
, do_strex
},
10007 { "strexh", 0xe1e00f90, 6, ARM_EXT_V6K
, do_strex
},
10008 { "wfe", 0xe320f002, 3, ARM_EXT_V6K
, do_empty
},
10009 { "wfi", 0xe320f003, 3, ARM_EXT_V6K
, do_empty
},
10010 { "yield", 0xe320f001, 5, ARM_EXT_V6K
, do_empty
},
10013 { "smi", 0xe1600070, 3, ARM_EXT_V6Z
, do_smi
},
10015 /* Core FPA instruction set (V1). */
10016 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
10017 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
10018 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
10019 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
10021 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10022 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10023 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10024 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10026 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10027 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10028 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10029 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10031 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10032 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10033 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10034 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10035 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10036 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10037 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10038 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10039 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10040 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10041 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10042 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10044 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10045 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10046 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10047 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10048 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10049 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10050 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10051 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10052 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10053 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10054 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10055 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10057 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10058 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10059 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10060 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10061 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10062 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10063 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10064 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10065 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10066 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10067 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10068 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10070 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10071 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10072 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10073 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10074 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10075 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10076 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10077 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10078 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10079 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10080 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10081 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10083 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10084 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10085 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10086 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10087 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10088 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10089 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10090 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10091 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10092 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10093 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10094 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10096 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10097 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10098 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10099 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10100 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10101 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10102 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10103 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10104 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10105 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10106 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10107 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10109 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10110 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10111 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10112 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10113 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10114 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10115 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10116 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10117 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10118 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10119 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10120 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10122 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10123 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10124 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10125 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10126 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10127 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10128 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10129 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10130 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10131 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10132 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10133 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10135 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10136 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10137 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10138 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10139 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10140 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10141 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10142 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10143 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10144 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10145 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10146 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10148 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10149 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10150 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10151 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10152 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10153 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10154 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10155 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10156 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10157 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10158 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10159 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10161 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10162 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10163 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10164 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10165 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10166 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10167 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10168 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10169 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10170 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10171 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10172 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10174 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10175 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10176 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10177 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10178 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10179 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10180 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10181 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10182 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10183 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10184 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10185 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10187 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10188 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10189 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10190 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10191 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10192 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10193 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10194 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10195 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10196 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10197 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10198 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10200 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10201 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10202 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10203 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10204 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10205 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10206 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10207 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10208 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10209 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10210 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10211 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10213 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10214 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10215 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10216 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10217 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10218 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10219 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10220 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10221 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10222 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10223 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10224 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10226 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10227 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10228 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10229 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10230 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10231 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10232 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10233 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10234 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10235 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10236 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10237 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10239 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10240 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10241 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10242 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10243 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10244 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10245 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10246 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10247 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10248 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10249 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10250 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10252 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10253 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10254 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10255 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10256 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10257 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10258 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10259 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10260 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10261 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10262 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10263 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10265 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10266 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10267 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10268 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10269 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10270 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10271 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10272 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10273 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10274 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10275 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10276 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10278 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10279 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10280 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10281 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10282 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10283 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10284 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10285 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10286 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10287 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10288 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10289 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10291 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10292 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10293 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10294 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10295 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10296 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10297 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10298 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10299 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10300 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10301 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10302 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10304 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10305 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10306 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10307 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10308 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10309 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10310 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10311 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10312 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10313 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10314 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10315 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10317 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10318 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10319 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10320 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10321 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10322 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10323 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10324 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10325 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10326 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10327 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10328 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10330 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10331 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10332 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10333 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10334 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10335 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10336 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10337 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10338 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10339 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10340 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10341 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10343 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10344 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10345 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10346 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10347 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10348 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10349 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10350 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10351 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10352 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10353 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10354 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10356 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10357 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10358 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10359 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10360 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10361 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10362 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10363 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10364 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10365 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10366 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10367 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10369 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10370 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10371 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10372 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10373 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10374 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10375 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10376 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10377 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10378 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10379 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10380 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10382 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10383 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10384 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10385 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10386 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10387 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10388 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10389 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10390 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10391 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10392 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10393 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10395 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10396 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10397 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10398 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10399 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10400 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10401 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10402 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10403 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10404 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10405 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10406 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10408 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10409 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10410 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10411 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10412 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
10413 not be an optional suffix, but part of the instruction. To be
10414 compatible, we accept either. */
10415 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10416 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10418 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10419 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10420 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10421 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10422 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10423 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10424 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10425 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10426 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10427 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10428 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10429 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10431 /* The implementation of the FIX instruction is broken on some
10432 assemblers, in that it accepts a precision specifier as well as a
10433 rounding specifier, despite the fact that this is meaningless.
10434 To be more compatible, we accept it as well, though of course it
10435 does not set any bits. */
10436 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10437 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10438 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10439 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10440 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10441 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10442 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10443 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10444 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10445 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10446 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10447 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10448 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10450 /* Instructions that were new with the real FPA, call them V2. */
10451 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10452 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10453 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10454 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10455 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10456 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10458 /* VFP V1xD (single precision). */
10459 /* Moves and type conversions. */
10460 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10461 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_reg_from_sp
},
10462 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_from_reg
},
10463 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD
, do_empty
},
10464 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10465 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10466 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10467 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10468 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10469 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10470 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_reg_from_ctrl
},
10471 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_ctrl_from_reg
},
10473 /* Memory operations. */
10474 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldst
},
10475 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldst
},
10476 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
10477 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
10478 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
10479 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
10480 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
10481 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
10482 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
10483 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
10484 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
10485 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
10486 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
10487 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
10488 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
10489 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
10490 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
10491 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
10493 /* Monadic operations. */
10494 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10495 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10496 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10498 /* Dyadic operations. */
10499 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10500 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10501 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10502 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10503 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10504 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10505 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10506 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10507 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10510 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10511 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_compare_z
},
10512 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10513 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_compare_z
},
10515 /* VFP V1 (Double precision). */
10516 /* Moves and type conversions. */
10517 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10518 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
10519 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10520 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1
, do_vfp_dp_from_reg
},
10521 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1
, do_vfp_dp_from_reg
},
10522 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1
, do_vfp_reg_from_dp
},
10523 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1
, do_vfp_reg_from_dp
},
10524 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
10525 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
10526 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10527 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10528 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10529 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10531 /* Memory operations. */
10532 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1
, do_vfp_dp_ldst
},
10533 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1
, do_vfp_dp_ldst
},
10534 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
10535 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
10536 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
10537 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
10538 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
10539 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
10540 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
10541 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
10543 /* Monadic operations. */
10544 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10545 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10546 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10548 /* Dyadic operations. */
10549 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10550 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10551 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10552 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10553 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10554 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10555 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10556 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10557 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10560 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10561 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_compare_z
},
10562 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10563 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1
, do_vfp_dp_compare_z
},
10566 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2
, do_vfp_sp2_from_reg2
},
10567 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2
, do_vfp_reg2_from_sp2
},
10568 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2
, do_vfp_dp_from_reg2
},
10569 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2
, do_vfp_reg2_from_dp
},
10571 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
10572 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE
, do_xsc_mia
},
10573 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10574 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10575 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10576 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10577 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10578 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE
, do_xsc_mar
},
10579 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE
, do_xsc_mra
},
10581 /* Intel Wireless MMX technology instructions. */
10582 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
10583 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
10584 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
10585 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
10586 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
10587 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
10588 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
10589 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
10590 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
10591 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10592 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10593 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10594 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10595 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10596 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10597 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
10598 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
10599 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
10600 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmcr
},
10601 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_tmcrr
},
10602 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10603 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10604 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10605 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10606 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10607 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10608 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
10609 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
10610 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
10611 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmrc
},
10612 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_tmrrc
},
10613 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
10614 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
10615 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
10616 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10617 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10618 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10619 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10620 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10621 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10622 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10623 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10624 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10625 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10626 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10627 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10628 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_waligni
},
10629 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10630 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10631 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10632 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10633 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10634 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10635 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10636 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10637 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10638 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10639 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10640 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10641 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10642 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10643 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10644 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10645 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10646 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10647 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10648 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
10649 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
10650 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
10651 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
10652 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10653 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10654 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10655 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10656 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10657 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10658 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10659 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10660 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10661 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10662 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10663 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10664 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10665 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10666 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10667 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10668 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10669 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10670 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wmov
},
10671 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10672 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10673 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10674 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10675 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10676 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10677 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10678 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10679 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10680 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10681 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10682 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10683 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10684 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10685 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10686 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10687 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10688 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10689 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10690 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10691 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10692 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wshufh
},
10693 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10694 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10695 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10696 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10697 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10698 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10699 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10700 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10701 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10702 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10703 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10704 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10705 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10706 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10707 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10708 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10709 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10710 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10711 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
10712 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
10713 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
10714 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
10715 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10716 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10717 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10718 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10719 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10720 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10721 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10722 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10723 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10724 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10725 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10726 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10727 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10728 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10729 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10730 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10731 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10732 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10733 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10734 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10735 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10736 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10737 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10738 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10739 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10740 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10741 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10742 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10743 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wzero
},
10745 /* Cirrus Maverick instructions. */
10746 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_1
},
10747 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_2
},
10748 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_3
},
10749 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_4
},
10750 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_1
},
10751 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_2
},
10752 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_3
},
10753 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_4
},
10754 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK
, do_mav_binops_2a
},
10755 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1a
},
10756 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK
, do_mav_binops_2b
},
10757 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1b
},
10758 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK
, do_mav_binops_2b
},
10759 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1b
},
10760 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK
, do_mav_binops_2c
},
10761 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1c
},
10762 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK
, do_mav_binops_2c
},
10763 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1c
},
10764 {"cfmval32", 0xee200440, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
10765 {"cfmv32al", 0xee100440, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
10766 {"cfmvam32", 0xee200460, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
10767 {"cfmv32am", 0xee100460, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
10768 {"cfmvah32", 0xee200480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
10769 {"cfmv32ah", 0xee100480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
10770 {"cfmva32", 0xee2004a0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
10771 {"cfmv32a", 0xee1004a0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
10772 {"cfmva64", 0xee2004c0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3c
},
10773 {"cfmv64a", 0xee1004c0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3d
},
10774 {"cfmvsc32", 0xee2004e0, 8, ARM_CEXT_MAVERICK
, do_mav_dspsc_1
},
10775 {"cfmv32sc", 0xee1004e0, 8, ARM_CEXT_MAVERICK
, do_mav_dspsc_2
},
10776 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
10777 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
10778 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1f
},
10779 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1g
},
10780 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1h
},
10781 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1i
},
10782 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1j
},
10783 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1k
},
10784 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1l
},
10785 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1m
},
10786 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK
, do_mav_binops_1l
},
10787 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK
, do_mav_binops_1m
},
10788 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK
, do_mav_triple_4a
},
10789 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK
, do_mav_triple_4b
},
10790 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK
, do_mav_shift_1
},
10791 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK
, do_mav_shift_2
},
10792 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5a
},
10793 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5b
},
10794 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5c
},
10795 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5d
},
10796 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
10797 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
10798 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
10799 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
10800 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
10801 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
10802 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
10803 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
10804 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
10805 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
10806 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1n
},
10807 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1o
},
10808 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1n
},
10809 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1o
},
10810 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
10811 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
10812 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
10813 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
10814 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
10815 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
10816 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
10817 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
10818 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK
, do_mav_quad_6a
},
10819 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK
, do_mav_quad_6a
},
10820 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK
, do_mav_quad_6b
},
10821 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK
, do_mav_quad_6b
},
10824 /* Iterate over the base tables to create the instruction patterns. */
10827 build_arm_ops_hsh (void)
10831 static struct obstack insn_obstack
;
10833 obstack_begin (&insn_obstack
, 4000);
10835 for (i
= 0; i
< sizeof (insns
) / sizeof (struct asm_opcode
); i
++)
10837 const struct asm_opcode
*insn
= insns
+ i
;
10839 if (insn
->cond_offset
!= 0)
10841 /* Insn supports conditional execution. Build the varaints
10842 and insert them in the hash table. */
10843 for (j
= 0; j
< sizeof (conds
) / sizeof (struct asm_cond
); j
++)
10845 unsigned len
= strlen (insn
->template);
10846 struct asm_opcode
*new;
10849 new = obstack_alloc (&insn_obstack
, sizeof (struct asm_opcode
));
10850 /* All condition codes are two characters. */
10851 template = obstack_alloc (&insn_obstack
, len
+ 3);
10853 strncpy (template, insn
->template, insn
->cond_offset
);
10854 strcpy (template + insn
->cond_offset
, conds
[j
].template);
10855 if (len
> insn
->cond_offset
)
10856 strcpy (template + insn
->cond_offset
+ 2,
10857 insn
->template + insn
->cond_offset
);
10858 new->template = template;
10859 new->cond_offset
= 0;
10860 new->variant
= insn
->variant
;
10861 new->parms
= insn
->parms
;
10862 new->value
= (insn
->value
& ~COND_MASK
) | conds
[j
].value
;
10864 hash_insert (arm_ops_hsh
, new->template, (PTR
) new);
10867 /* Finally, insert the unconditional insn in the table directly;
10868 no need to build a copy. */
10869 hash_insert (arm_ops_hsh
, insn
->template, (PTR
) insn
);
10874 static const struct thumb_opcode tinsns
[] =
10876 /* Thumb v1 (ARMv4T). */
10877 {"adc", 0x4140, 2, ARM_EXT_V4T
, do_t_arit
},
10878 {"add", 0x0000, 2, ARM_EXT_V4T
, do_t_add
},
10879 {"and", 0x4000, 2, ARM_EXT_V4T
, do_t_arit
},
10880 {"asr", 0x0000, 2, ARM_EXT_V4T
, do_t_asr
},
10881 {"b", T_OPCODE_BRANCH
, 2, ARM_EXT_V4T
, do_t_branch12
},
10882 {"beq", 0xd0fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10883 {"bne", 0xd1fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10884 {"bcs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10885 {"bhs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10886 {"bcc", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10887 {"bul", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10888 {"blo", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10889 {"bmi", 0xd4fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10890 {"bpl", 0xd5fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10891 {"bvs", 0xd6fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10892 {"bvc", 0xd7fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10893 {"bhi", 0xd8fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10894 {"bls", 0xd9fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10895 {"bge", 0xdafe, 2, ARM_EXT_V4T
, do_t_branch9
},
10896 {"blt", 0xdbfe, 2, ARM_EXT_V4T
, do_t_branch9
},
10897 {"bgt", 0xdcfe, 2, ARM_EXT_V4T
, do_t_branch9
},
10898 {"ble", 0xddfe, 2, ARM_EXT_V4T
, do_t_branch9
},
10899 {"bal", 0xdefe, 2, ARM_EXT_V4T
, do_t_branch9
},
10900 {"bic", 0x4380, 2, ARM_EXT_V4T
, do_t_arit
},
10901 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T
, do_t_branch23
},
10902 {"bx", 0x4700, 2, ARM_EXT_V4T
, do_t_bx
},
10903 {"cmn", T_OPCODE_CMN
, 2, ARM_EXT_V4T
, do_t_arit
},
10904 {"cmp", 0x0000, 2, ARM_EXT_V4T
, do_t_compare
},
10905 {"eor", 0x4040, 2, ARM_EXT_V4T
, do_t_arit
},
10906 {"ldmia", 0xc800, 2, ARM_EXT_V4T
, do_t_ldmstm
},
10907 {"ldr", 0x0000, 2, ARM_EXT_V4T
, do_t_ldr
},
10908 {"ldrb", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrb
},
10909 {"ldrh", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrh
},
10910 {"ldrsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
10911 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
10912 {"ldsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
10913 {"ldsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
10914 {"lsl", 0x0000, 2, ARM_EXT_V4T
, do_t_lsl
},
10915 {"lsr", 0x0000, 2, ARM_EXT_V4T
, do_t_lsr
},
10916 {"mov", 0x0000, 2, ARM_EXT_V4T
, do_t_mov
},
10917 {"mul", T_OPCODE_MUL
, 2, ARM_EXT_V4T
, do_t_arit
},
10918 {"mvn", T_OPCODE_MVN
, 2, ARM_EXT_V4T
, do_t_arit
},
10919 {"neg", T_OPCODE_NEG
, 2, ARM_EXT_V4T
, do_t_arit
},
10920 {"orr", 0x4300, 2, ARM_EXT_V4T
, do_t_arit
},
10921 {"pop", 0xbc00, 2, ARM_EXT_V4T
, do_t_push_pop
},
10922 {"push", 0xb400, 2, ARM_EXT_V4T
, do_t_push_pop
},
10923 {"ror", 0x41c0, 2, ARM_EXT_V4T
, do_t_arit
},
10924 {"sbc", 0x4180, 2, ARM_EXT_V4T
, do_t_arit
},
10925 {"stmia", 0xc000, 2, ARM_EXT_V4T
, do_t_ldmstm
},
10926 {"str", 0x0000, 2, ARM_EXT_V4T
, do_t_str
},
10927 {"strb", 0x0000, 2, ARM_EXT_V4T
, do_t_strb
},
10928 {"strh", 0x0000, 2, ARM_EXT_V4T
, do_t_strh
},
10929 {"swi", 0xdf00, 2, ARM_EXT_V4T
, do_t_swi
},
10930 {"sub", 0x0000, 2, ARM_EXT_V4T
, do_t_sub
},
10931 {"tst", T_OPCODE_TST
, 2, ARM_EXT_V4T
, do_t_arit
},
10933 {"adr", 0x0000, 2, ARM_EXT_V4T
, do_t_adr
},
10934 {"nop", 0x46C0, 2, ARM_EXT_V4T
, do_t_nop
}, /* mov r8,r8 */
10935 /* Thumb v2 (ARMv5T). */
10936 {"blx", 0, 0, ARM_EXT_V5T
, do_t_blx
},
10937 {"bkpt", 0xbe00, 2, ARM_EXT_V5T
, do_t_bkpt
},
10940 {"cpsie", 0xb660, 2, ARM_EXT_V6
, do_t_cps
},
10941 {"cpsid", 0xb670, 2, ARM_EXT_V6
, do_t_cps
},
10942 {"cpy", 0x4600, 2, ARM_EXT_V6
, do_t_cpy
},
10943 {"rev", 0xba00, 2, ARM_EXT_V6
, do_t_arit
},
10944 {"rev16", 0xba40, 2, ARM_EXT_V6
, do_t_arit
},
10945 {"revsh", 0xbac0, 2, ARM_EXT_V6
, do_t_arit
},
10946 {"setend", 0xb650, 2, ARM_EXT_V6
, do_t_setend
},
10947 {"sxth", 0xb200, 2, ARM_EXT_V6
, do_t_arit
},
10948 {"sxtb", 0xb240, 2, ARM_EXT_V6
, do_t_arit
},
10949 {"uxth", 0xb280, 2, ARM_EXT_V6
, do_t_arit
},
10950 {"uxtb", 0xb2c0, 2, ARM_EXT_V6
, do_t_arit
},
10959 if ( (arm_ops_hsh
= hash_new ()) == NULL
10960 || (arm_tops_hsh
= hash_new ()) == NULL
10961 || (arm_cond_hsh
= hash_new ()) == NULL
10962 || (arm_shift_hsh
= hash_new ()) == NULL
10963 || (arm_psr_hsh
= hash_new ()) == NULL
)
10964 as_fatal (_("virtual memory exhausted"));
10966 build_arm_ops_hsh ();
10967 for (i
= 0; i
< sizeof (tinsns
) / sizeof (struct thumb_opcode
); i
++)
10968 hash_insert (arm_tops_hsh
, tinsns
[i
].template, (PTR
) (tinsns
+ i
));
10969 for (i
= 0; i
< sizeof (conds
) / sizeof (struct asm_cond
); i
++)
10970 hash_insert (arm_cond_hsh
, conds
[i
].template, (PTR
) (conds
+ i
));
10971 for (i
= 0; i
< sizeof (shift_names
) / sizeof (struct asm_shift_name
); i
++)
10972 hash_insert (arm_shift_hsh
, shift_names
[i
].name
, (PTR
) (shift_names
+ i
));
10973 for (i
= 0; i
< sizeof (psrs
) / sizeof (struct asm_psr
); i
++)
10974 hash_insert (arm_psr_hsh
, psrs
[i
].template, (PTR
) (psrs
+ i
));
10976 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
10977 build_reg_hsh (all_reg_maps
+ i
);
10979 set_constant_flonums ();
10981 /* Set the cpu variant based on the command-line options. We prefer
10982 -mcpu= over -march= if both are set (as for GCC); and we prefer
10983 -mfpu= over any other way of setting the floating point unit.
10984 Use of legacy options with new options are faulted. */
10985 if (legacy_cpu
!= -1)
10987 if (mcpu_cpu_opt
!= -1 || march_cpu_opt
!= -1)
10988 as_bad (_("use of old and new-style options to set CPU type"));
10990 mcpu_cpu_opt
= legacy_cpu
;
10992 else if (mcpu_cpu_opt
== -1)
10993 mcpu_cpu_opt
= march_cpu_opt
;
10995 if (legacy_fpu
!= -1)
10997 if (mfpu_opt
!= -1)
10998 as_bad (_("use of old and new-style options to set FPU type"));
11000 mfpu_opt
= legacy_fpu
;
11002 else if (mfpu_opt
== -1)
11004 #if !(defined (TE_LINUX) || defined (TE_NetBSD) || defined (TE_VXWORKS))
11005 /* Some environments specify a default FPU. If they don't, infer it
11006 from the processor. */
11007 if (mcpu_fpu_opt
!= -1)
11008 mfpu_opt
= mcpu_fpu_opt
;
11010 mfpu_opt
= march_fpu_opt
;
11012 mfpu_opt
= FPU_DEFAULT
;
11016 if (mfpu_opt
== -1)
11018 if (mcpu_cpu_opt
== -1)
11019 mfpu_opt
= FPU_DEFAULT
;
11020 else if (mcpu_cpu_opt
& ARM_EXT_V5
)
11021 mfpu_opt
= FPU_ARCH_VFP_V2
;
11023 mfpu_opt
= FPU_ARCH_FPA
;
11026 if (mcpu_cpu_opt
== -1)
11027 mcpu_cpu_opt
= CPU_DEFAULT
;
11029 cpu_variant
= mcpu_cpu_opt
| mfpu_opt
;
11032 unsigned int flags
= 0;
11034 #if defined OBJ_ELF
11035 flags
= meabi_flags
;
11037 switch (meabi_flags
)
11039 case EF_ARM_EABI_UNKNOWN
:
11041 #if defined OBJ_COFF || defined OBJ_ELF
11042 /* Set the flags in the private structure. */
11043 if (uses_apcs_26
) flags
|= F_APCS26
;
11044 if (support_interwork
) flags
|= F_INTERWORK
;
11045 if (uses_apcs_float
) flags
|= F_APCS_FLOAT
;
11046 if (pic_code
) flags
|= F_PIC
;
11047 if ((cpu_variant
& FPU_ANY
) == FPU_NONE
11048 || (cpu_variant
& FPU_ANY
) == FPU_ARCH_VFP
) /* VFP layout only. */
11049 flags
|= F_SOFT_FLOAT
;
11051 switch (mfloat_abi_opt
)
11053 case ARM_FLOAT_ABI_SOFT
:
11054 case ARM_FLOAT_ABI_SOFTFP
:
11055 flags
|= F_SOFT_FLOAT
;
11058 case ARM_FLOAT_ABI_HARD
:
11059 if (flags
& F_SOFT_FLOAT
)
11060 as_bad (_("hard-float conflicts with specified fpu"));
11064 /* Using VFP conventions (even if soft-float). */
11065 if (cpu_variant
& FPU_VFP_EXT_NONE
)
11066 flags
|= F_VFP_FLOAT
;
11068 #if defined OBJ_ELF
11069 if (cpu_variant
& FPU_ARCH_MAVERICK
)
11070 flags
|= EF_ARM_MAVERICK_FLOAT
;
11073 case EF_ARM_EABI_VER4
:
11074 /* No additional flags to set. */
11081 #if defined OBJ_COFF || defined OBJ_ELF
11082 bfd_set_private_flags (stdoutput
, flags
);
11084 /* We have run out flags in the COFF header to encode the
11085 status of ATPCS support, so instead we create a dummy,
11086 empty, debug section called .arm.atpcs. */
11091 sec
= bfd_make_section (stdoutput
, ".arm.atpcs");
11095 bfd_set_section_flags
11096 (stdoutput
, sec
, SEC_READONLY
| SEC_DEBUGGING
/* | SEC_HAS_CONTENTS */);
11097 bfd_set_section_size (stdoutput
, sec
, 0);
11098 bfd_set_section_contents (stdoutput
, sec
, NULL
, 0, 0);
11104 /* Record the CPU type as well. */
11105 switch (cpu_variant
& ARM_CPU_MASK
)
11108 mach
= bfd_mach_arm_2
;
11111 case ARM_3
: /* Also ARM_250. */
11112 mach
= bfd_mach_arm_2a
;
11115 case ARM_6
: /* Also ARM_7. */
11116 mach
= bfd_mach_arm_3
;
11120 mach
= bfd_mach_arm_unknown
;
11124 /* Catch special cases. */
11125 if (cpu_variant
& ARM_CEXT_IWMMXT
)
11126 mach
= bfd_mach_arm_iWMMXt
;
11127 else if (cpu_variant
& ARM_CEXT_XSCALE
)
11128 mach
= bfd_mach_arm_XScale
;
11129 else if (cpu_variant
& ARM_CEXT_MAVERICK
)
11130 mach
= bfd_mach_arm_ep9312
;
11131 else if (cpu_variant
& ARM_EXT_V5E
)
11132 mach
= bfd_mach_arm_5TE
;
11133 else if (cpu_variant
& ARM_EXT_V5
)
11135 if (cpu_variant
& ARM_EXT_V4T
)
11136 mach
= bfd_mach_arm_5T
;
11138 mach
= bfd_mach_arm_5
;
11140 else if (cpu_variant
& ARM_EXT_V4
)
11142 if (cpu_variant
& ARM_EXT_V4T
)
11143 mach
= bfd_mach_arm_4T
;
11145 mach
= bfd_mach_arm_4
;
11147 else if (cpu_variant
& ARM_EXT_V3M
)
11148 mach
= bfd_mach_arm_3M
;
11150 bfd_set_arch_mach (stdoutput
, TARGET_ARCH
, mach
);
11153 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11154 for use in the a.out file, and stores them in the array pointed to by buf.
11155 This knows about the endian-ness of the target machine and does
11156 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11157 2 (short) and 4 (long) Floating numbers are put out as a series of
11158 LITTLENUMS (shorts, here at least). */
11161 md_number_to_chars (char * buf
, valueT val
, int n
)
11163 if (target_big_endian
)
11164 number_to_chars_bigendian (buf
, val
, n
);
11166 number_to_chars_littleendian (buf
, val
, n
);
11170 md_chars_to_number (char * buf
, int n
)
11173 unsigned char * where
= (unsigned char *) buf
;
11175 if (target_big_endian
)
11180 result
|= (*where
++ & 255);
11188 result
|= (where
[n
] & 255);
11195 /* Turn a string in input_line_pointer into a floating point constant
11196 of type TYPE, and store the appropriate bytes in *LITP. The number
11197 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11198 returned, or NULL on OK.
11200 Note that fp constants aren't represent in the normal way on the ARM.
11201 In big endian mode, things are as expected. However, in little endian
11202 mode fp constants are big-endian word-wise, and little-endian byte-wise
11203 within the words. For example, (double) 1.1 in big endian mode is
11204 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11205 the byte sequence 99 99 f1 3f 9a 99 99 99.
11207 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11210 md_atof (int type
, char * litP
, int * sizeP
)
11213 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
11245 return _("bad call to MD_ATOF()");
11248 t
= atof_ieee (input_line_pointer
, type
, words
);
11250 input_line_pointer
= t
;
11253 if (target_big_endian
)
11255 for (i
= 0; i
< prec
; i
++)
11257 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
11263 if (cpu_variant
& FPU_ARCH_VFP
)
11264 for (i
= prec
- 1; i
>= 0; i
--)
11266 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
11270 /* For a 4 byte float the order of elements in `words' is 1 0.
11271 For an 8 byte float the order is 1 0 3 2. */
11272 for (i
= 0; i
< prec
; i
+= 2)
11274 md_number_to_chars (litP
, (valueT
) words
[i
+ 1], 2);
11275 md_number_to_chars (litP
+ 2, (valueT
) words
[i
], 2);
11283 /* The knowledge of the PC's pipeline offset is built into the insns
11287 md_pcrel_from (fixS
* fixP
)
11290 && S_GET_SEGMENT (fixP
->fx_addsy
) == undefined_section
11291 && fixP
->fx_subsy
== NULL
)
11294 if (fixP
->fx_pcrel
&& (fixP
->fx_r_type
== BFD_RELOC_ARM_THUMB_ADD
))
11296 /* PC relative addressing on the Thumb is slightly odd
11297 as the bottom two bits of the PC are forced to zero
11298 for the calculation. */
11299 return (fixP
->fx_where
+ fixP
->fx_frag
->fr_address
) & ~3;
11303 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
11304 so we un-adjust here to compensate for the accommodation. */
11305 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
+ 8;
11307 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
11311 /* Round up a section size to the appropriate boundary. */
11314 md_section_align (segT segment ATTRIBUTE_UNUSED
,
11320 /* Round all sects to multiple of 4. */
11321 return (size
+ 3) & ~3;
11325 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
11326 Otherwise we have no need to default values of symbols. */
11329 md_undefined_symbol (char * name ATTRIBUTE_UNUSED
)
11332 if (name
[0] == '_' && name
[1] == 'G'
11333 && streq (name
, GLOBAL_OFFSET_TABLE_NAME
))
11337 if (symbol_find (name
))
11338 as_bad ("GOT already in the symbol table");
11340 GOT_symbol
= symbol_new (name
, undefined_section
,
11341 (valueT
) 0, & zero_address_frag
);
11352 md_apply_fix3 (fixS
* fixP
,
11356 offsetT value
= * valP
;
11358 unsigned int newimm
;
11359 unsigned long temp
;
11361 char * buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
11362 arm_fix_data
* arm_data
= (arm_fix_data
*) fixP
->tc_fix_data
;
11364 assert (fixP
->fx_r_type
< BFD_RELOC_UNUSED
);
11366 /* Note whether this will delete the relocation. */
11367 if (fixP
->fx_addsy
== 0 && !fixP
->fx_pcrel
)
11370 /* If this symbol is in a different section then we need to leave it for
11371 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
11372 so we have to undo it's effects here. */
11373 if (fixP
->fx_pcrel
)
11375 if (fixP
->fx_addsy
!= NULL
11376 && S_IS_DEFINED (fixP
->fx_addsy
)
11377 && S_GET_SEGMENT (fixP
->fx_addsy
) != seg
)
11378 value
+= md_pcrel_from (fixP
);
11381 /* Remember value for emit_reloc. */
11382 fixP
->fx_addnumber
= value
;
11384 switch (fixP
->fx_r_type
)
11386 case BFD_RELOC_ARM_IMMEDIATE
:
11387 /* We claim that this fixup has been processed here,
11388 even if in fact we generate an error because we do
11389 not have a reloc for it, so tc_gen_reloc will reject it. */
11393 && ! S_IS_DEFINED (fixP
->fx_addsy
))
11395 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11396 _("undefined symbol %s used as an immediate value"),
11397 S_GET_NAME (fixP
->fx_addsy
));
11401 newimm
= validate_immediate (value
);
11402 temp
= md_chars_to_number (buf
, INSN_SIZE
);
11404 /* If the instruction will fail, see if we can fix things up by
11405 changing the opcode. */
11406 if (newimm
== (unsigned int) FAIL
11407 && (newimm
= negate_data_op (&temp
, value
)) == (unsigned int) FAIL
)
11409 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11410 _("invalid constant (%lx) after fixup"),
11411 (unsigned long) value
);
11415 newimm
|= (temp
& 0xfffff000);
11416 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
11419 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
11421 unsigned int highpart
= 0;
11422 unsigned int newinsn
= 0xe1a00000; /* nop. */
11424 newimm
= validate_immediate (value
);
11425 temp
= md_chars_to_number (buf
, INSN_SIZE
);
11427 /* If the instruction will fail, see if we can fix things up by
11428 changing the opcode. */
11429 if (newimm
== (unsigned int) FAIL
11430 && (newimm
= negate_data_op (& temp
, value
)) == (unsigned int) FAIL
)
11432 /* No ? OK - try using two ADD instructions to generate
11434 newimm
= validate_immediate_twopart (value
, & highpart
);
11436 /* Yes - then make sure that the second instruction is
11438 if (newimm
!= (unsigned int) FAIL
)
11440 /* Still No ? Try using a negated value. */
11441 else if ((newimm
= validate_immediate_twopart (- value
, & highpart
)) != (unsigned int) FAIL
)
11442 temp
= newinsn
= (temp
& OPCODE_MASK
) | OPCODE_SUB
<< DATA_OP_SHIFT
;
11443 /* Otherwise - give up. */
11446 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11447 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
11452 /* Replace the first operand in the 2nd instruction (which
11453 is the PC) with the destination register. We have
11454 already added in the PC in the first instruction and we
11455 do not want to do it again. */
11456 newinsn
&= ~ 0xf0000;
11457 newinsn
|= ((newinsn
& 0x0f000) << 4);
11460 newimm
|= (temp
& 0xfffff000);
11461 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
11463 highpart
|= (newinsn
& 0xfffff000);
11464 md_number_to_chars (buf
+ INSN_SIZE
, (valueT
) highpart
, INSN_SIZE
);
11468 case BFD_RELOC_ARM_OFFSET_IMM
:
11474 if (validate_offset_imm (value
, 0) == FAIL
)
11476 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11477 _("bad immediate value for offset (%ld)"),
11482 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11483 newval
&= 0xff7ff000;
11484 newval
|= value
| (sign
? INDEX_UP
: 0);
11485 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11488 case BFD_RELOC_ARM_OFFSET_IMM8
:
11489 case BFD_RELOC_ARM_HWLITERAL
:
11495 if (validate_offset_imm (value
, 1) == FAIL
)
11497 if (fixP
->fx_r_type
== BFD_RELOC_ARM_HWLITERAL
)
11498 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11499 _("invalid literal constant: pool needs to be closer"));
11501 as_bad (_("bad immediate value for half-word offset (%ld)"),
11506 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11507 newval
&= 0xff7ff0f0;
11508 newval
|= ((value
>> 4) << 8) | (value
& 0xf) | (sign
? INDEX_UP
: 0);
11509 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11512 case BFD_RELOC_ARM_LITERAL
:
11518 if (validate_offset_imm (value
, 0) == FAIL
)
11520 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11521 _("invalid literal constant: pool needs to be closer"));
11525 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11526 newval
&= 0xff7ff000;
11527 newval
|= value
| (sign
? INDEX_UP
: 0);
11528 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11531 case BFD_RELOC_ARM_SHIFT_IMM
:
11532 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11533 if (((unsigned long) value
) > 32
11535 && (((newval
& 0x60) == 0) || (newval
& 0x60) == 0x60)))
11537 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11538 _("shift expression is too large"));
11543 /* Shifts of zero must be done as lsl. */
11545 else if (value
== 32)
11547 newval
&= 0xfffff07f;
11548 newval
|= (value
& 0x1f) << 7;
11549 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11552 case BFD_RELOC_ARM_SMI
:
11553 if (((unsigned long) value
) > 0xffff)
11554 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11555 _("invalid smi expression"));
11556 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xfff000f0;
11557 newval
|= (value
& 0xf) | ((value
& 0xfff0) << 4);
11558 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11561 case BFD_RELOC_ARM_SWI
:
11562 if (arm_data
->thumb_mode
)
11564 if (((unsigned long) value
) > 0xff)
11565 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11566 _("invalid swi expression"));
11567 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xff00;
11569 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11573 if (((unsigned long) value
) > 0x00ffffff)
11574 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11575 _("invalid swi expression"));
11576 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff000000;
11578 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11582 case BFD_RELOC_ARM_MULTI
:
11583 if (((unsigned long) value
) > 0xffff)
11584 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11585 _("invalid expression in load/store multiple"));
11586 newval
= value
| md_chars_to_number (buf
, INSN_SIZE
);
11587 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11590 case BFD_RELOC_ARM_PCREL_BRANCH
:
11591 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11593 /* Sign-extend a 24-bit number. */
11594 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
11597 value
= fixP
->fx_offset
;
11600 /* We are going to store value (shifted right by two) in the
11601 instruction, in a 24 bit, signed field. Thus we need to check
11602 that none of the top 8 bits of the shifted value (top 7 bits of
11603 the unshifted, unsigned value) are set, or that they are all set. */
11604 if ((value
& ~ ((offsetT
) 0x1ffffff)) != 0
11605 && ((value
& ~ ((offsetT
) 0x1ffffff)) != ~ ((offsetT
) 0x1ffffff)))
11608 /* Normally we would be stuck at this point, since we cannot store
11609 the absolute address that is the destination of the branch in the
11610 24 bits of the branch instruction. If however, we happen to know
11611 that the destination of the branch is in the same section as the
11612 branch instruction itself, then we can compute the relocation for
11613 ourselves and not have to bother the linker with it.
11615 FIXME: The test for OBJ_ELF is only here because I have not
11616 worked out how to do this for OBJ_COFF. */
11617 if (fixP
->fx_addsy
!= NULL
11618 && S_IS_DEFINED (fixP
->fx_addsy
)
11619 && S_GET_SEGMENT (fixP
->fx_addsy
) == seg
)
11621 /* Get pc relative value to go into the branch. */
11624 /* Permit a backward branch provided that enough bits
11625 are set. Allow a forwards branch, provided that
11626 enough bits are clear. */
11627 if ( (value
& ~ ((offsetT
) 0x1ffffff)) == ~ ((offsetT
) 0x1ffffff)
11628 || (value
& ~ ((offsetT
) 0x1ffffff)) == 0)
11632 if (! fixP
->fx_done
)
11634 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11635 _("GAS can't handle same-section branch dest >= 0x04000000"));
11639 value
+= SEXT24 (newval
);
11641 if ( (value
& ~ ((offsetT
) 0xffffff)) != 0
11642 && ((value
& ~ ((offsetT
) 0xffffff)) != ~ ((offsetT
) 0xffffff)))
11643 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11644 _("out of range branch"));
11646 if (seg
->use_rela_p
&& !fixP
->fx_done
)
11648 /* Must unshift the value before storing it in the addend. */
11651 fixP
->fx_offset
= value
;
11653 fixP
->fx_addnumber
= value
;
11654 newval
= newval
& 0xff000000;
11657 newval
= (value
& 0x00ffffff) | (newval
& 0xff000000);
11658 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11661 case BFD_RELOC_ARM_PCREL_BLX
:
11664 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11667 value
= fixP
->fx_offset
;
11669 hbit
= (value
>> 1) & 1;
11670 value
= (value
>> 2) & 0x00ffffff;
11671 value
= (value
+ (newval
& 0x00ffffff)) & 0x00ffffff;
11673 if (seg
->use_rela_p
&& !fixP
->fx_done
)
11675 /* Must sign-extend and unshift the value before storing
11676 it in the addend. */
11677 value
= SEXT24 (value
);
11678 value
= (value
<< 2) | hbit
;
11680 fixP
->fx_offset
= value
;
11682 fixP
->fx_addnumber
= value
;
11683 newval
= newval
& 0xfe000000;
11686 newval
= value
| (newval
& 0xfe000000) | (hbit
<< 24);
11687 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11691 case BFD_RELOC_THUMB_PCREL_BRANCH9
: /* Conditional branch. */
11692 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11694 addressT diff
= (newval
& 0xff) << 1;
11699 if ((value
& ~0xff) && ((value
& ~0xff) != ~0xff))
11700 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11701 _("branch out of range"));
11702 if (seg
->use_rela_p
&& !fixP
->fx_done
)
11705 fixP
->fx_offset
= value
;
11707 fixP
->fx_addnumber
= value
;
11708 newval
= newval
& 0xff00;
11711 newval
= (newval
& 0xff00) | ((value
& 0x1ff) >> 1);
11713 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11716 case BFD_RELOC_THUMB_PCREL_BRANCH12
: /* Unconditional branch. */
11717 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11719 addressT diff
= (newval
& 0x7ff) << 1;
11724 if ((value
& ~0x7ff) && ((value
& ~0x7ff) != ~0x7ff))
11725 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11726 _("branch out of range"));
11727 if (seg
->use_rela_p
&& !fixP
->fx_done
)
11730 fixP
->fx_offset
= value
;
11732 fixP
->fx_addnumber
= value
;
11733 newval
= newval
& 0xf800;
11736 newval
= (newval
& 0xf800) | ((value
& 0xfff) >> 1);
11738 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11741 case BFD_RELOC_THUMB_PCREL_BLX
:
11742 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
11747 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11748 newval2
= md_chars_to_number (buf
+ THUMB_SIZE
, THUMB_SIZE
);
11749 diff
= ((newval
& 0x7ff) << 12) | ((newval2
& 0x7ff) << 1);
11750 if (diff
& 0x400000)
11753 value
= fixP
->fx_offset
;
11757 if ((value
& ~0x3fffff) && ((value
& ~0x3fffff) != ~0x3fffff))
11758 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11759 _("branch with link out of range"));
11761 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
)
11762 /* For a BLX instruction, make sure that the relocation is rounded up
11763 to a word boundary. This follows the semantics of the instruction
11764 which specifies that bit 1 of the target address will come from bit
11765 1 of the base address. */
11766 value
= (value
+ 1) & ~ 1;
11768 if (seg
->use_rela_p
&& !fixP
->fx_done
)
11771 fixP
->fx_offset
= value
;
11773 fixP
->fx_addnumber
= value
;
11774 newval
= newval
& 0xf800;
11775 newval2
= newval2
& 0xf800;
11779 newval
= (newval
& 0xf800) | ((value
& 0x7fffff) >> 12);
11780 newval2
= (newval2
& 0xf800) | ((value
& 0xfff) >> 1);
11782 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11783 md_number_to_chars (buf
+ THUMB_SIZE
, newval2
, THUMB_SIZE
);
11788 if (seg
->use_rela_p
&& !fixP
->fx_done
)
11790 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11791 md_number_to_chars (buf
, value
, 1);
11795 value
= fixP
->fx_offset
;
11796 md_number_to_chars (buf
, value
, 1);
11802 if (seg
->use_rela_p
&& !fixP
->fx_done
)
11804 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11805 md_number_to_chars (buf
, value
, 2);
11809 value
= fixP
->fx_offset
;
11810 md_number_to_chars (buf
, value
, 2);
11816 case BFD_RELOC_ARM_GOT32
:
11817 case BFD_RELOC_ARM_GOTOFF
:
11818 case BFD_RELOC_ARM_TARGET2
:
11819 if (seg
->use_rela_p
&& !fixP
->fx_done
)
11821 md_number_to_chars (buf
, 0, 4);
11825 case BFD_RELOC_RVA
:
11827 case BFD_RELOC_ARM_TARGET1
:
11828 case BFD_RELOC_ARM_ROSEGREL32
:
11829 case BFD_RELOC_ARM_SBREL32
:
11830 case BFD_RELOC_32_PCREL
:
11831 if (seg
->use_rela_p
&& !fixP
->fx_done
)
11833 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11834 md_number_to_chars (buf
, value
, 4);
11838 value
= fixP
->fx_offset
;
11839 md_number_to_chars (buf
, value
, 4);
11845 case BFD_RELOC_ARM_PREL31
:
11846 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11848 newval
= md_chars_to_number (buf
, 4) & 0x80000000;
11849 if ((value
^ (value
>> 1)) & 0x40000000)
11851 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11852 _("rel31 relocation overflow"));
11854 newval
|= value
& 0x7fffffff;
11855 md_number_to_chars (buf
, newval
, 4);
11859 case BFD_RELOC_ARM_PLT32
:
11860 /* It appears the instruction is fully prepared at this point. */
11864 case BFD_RELOC_ARM_CP_OFF_IMM
:
11866 if (value
< -1023 || value
> 1023 || (value
& 3))
11867 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11868 _("illegal value for co-processor offset"));
11871 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
11872 newval
|= (value
>> 2) | (sign
? INDEX_UP
: 0);
11873 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11876 case BFD_RELOC_ARM_CP_OFF_IMM_S2
:
11878 if (value
< -255 || value
> 255)
11879 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11880 _("Illegal value for co-processor offset"));
11883 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
11884 newval
|= value
| (sign
? INDEX_UP
: 0);
11885 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11888 case BFD_RELOC_ARM_THUMB_OFFSET
:
11889 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11890 /* Exactly what ranges, and where the offset is inserted depends
11891 on the type of instruction, we can establish this from the
11893 switch (newval
>> 12)
11895 case 4: /* PC load. */
11896 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
11897 forced to zero for these loads, so we will need to round
11898 up the offset if the instruction address is not word
11899 aligned (since the final address produced must be, and
11900 we can only describe word-aligned immediate offsets). */
11902 if ((fixP
->fx_frag
->fr_address
+ fixP
->fx_where
+ value
) & 3)
11903 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11904 _("invalid offset, target not word aligned (0x%08X)"),
11905 (unsigned int) (fixP
->fx_frag
->fr_address
11906 + fixP
->fx_where
+ value
));
11908 if ((value
+ 2) & ~0x3fe)
11909 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11910 _("invalid offset, value too big (0x%08lX)"),
11913 /* Round up, since pc will be rounded down. */
11914 newval
|= (value
+ 2) >> 2;
11917 case 9: /* SP load/store. */
11918 if (value
& ~0x3fc)
11919 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11920 _("invalid offset, value too big (0x%08lX)"),
11922 newval
|= value
>> 2;
11925 case 6: /* Word load/store. */
11927 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11928 _("invalid offset, value too big (0x%08lX)"),
11930 newval
|= value
<< 4; /* 6 - 2. */
11933 case 7: /* Byte load/store. */
11935 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11936 _("invalid offset, value too big (0x%08lX)"),
11938 newval
|= value
<< 6;
11941 case 8: /* Halfword load/store. */
11943 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11944 _("invalid offset, value too big (0x%08lX)"),
11946 newval
|= value
<< 5; /* 6 - 1. */
11950 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11951 "Unable to process relocation for thumb opcode: %lx",
11952 (unsigned long) newval
);
11955 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11958 case BFD_RELOC_ARM_THUMB_ADD
:
11959 /* This is a complicated relocation, since we use it for all of
11960 the following immediate relocations:
11964 9bit ADD/SUB SP word-aligned
11965 10bit ADD PC/SP word-aligned
11967 The type of instruction being processed is encoded in the
11974 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11976 int rd
= (newval
>> 4) & 0xf;
11977 int rs
= newval
& 0xf;
11978 int subtract
= newval
& 0x8000;
11982 if (value
& ~0x1fc)
11983 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11984 _("invalid immediate for stack address calculation"));
11985 newval
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
11986 newval
|= value
>> 2;
11988 else if (rs
== REG_PC
|| rs
== REG_SP
)
11992 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11993 _("invalid immediate for address calculation (value = 0x%08lX)"),
11994 (unsigned long) value
);
11995 newval
= (rs
== REG_PC
? T_OPCODE_ADD_PC
: T_OPCODE_ADD_SP
);
11997 newval
|= value
>> 2;
12002 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12003 _("invalid 8bit immediate"));
12004 newval
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
12005 newval
|= (rd
<< 8) | value
;
12010 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12011 _("invalid 3bit immediate"));
12012 newval
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
12013 newval
|= rd
| (rs
<< 3) | (value
<< 6);
12016 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12019 case BFD_RELOC_ARM_THUMB_IMM
:
12020 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12021 switch (newval
>> 11)
12023 case 0x04: /* 8bit immediate MOV. */
12024 case 0x05: /* 8bit immediate CMP. */
12025 if (value
< 0 || value
> 255)
12026 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12027 _("invalid immediate: %ld is too large"),
12035 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12038 case BFD_RELOC_ARM_THUMB_SHIFT
:
12039 /* 5bit shift value (0..31). */
12040 if (value
< 0 || value
> 31)
12041 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12042 _("illegal Thumb shift value: %ld"), (long) value
);
12043 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xf03f;
12044 newval
|= value
<< 6;
12045 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12048 case BFD_RELOC_VTABLE_INHERIT
:
12049 case BFD_RELOC_VTABLE_ENTRY
:
12053 case BFD_RELOC_NONE
:
12055 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12056 _("bad relocation fixup type (%d)"), fixP
->fx_r_type
);
12060 /* Translate internal representation of relocation info to BFD target
12064 tc_gen_reloc (asection
* section ATTRIBUTE_UNUSED
,
12068 bfd_reloc_code_real_type code
;
12070 reloc
= xmalloc (sizeof (arelent
));
12072 reloc
->sym_ptr_ptr
= xmalloc (sizeof (asymbol
*));
12073 *reloc
->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
12074 reloc
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
12076 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12078 if (fixp
->fx_pcrel
== 0)
12079 reloc
->addend
= fixp
->fx_offset
;
12081 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
12082 #else /* OBJ_ELF */
12083 reloc
->addend
= fixp
->fx_offset
;
12086 switch (fixp
->fx_r_type
)
12089 if (fixp
->fx_pcrel
)
12091 code
= BFD_RELOC_8_PCREL
;
12096 if (fixp
->fx_pcrel
)
12098 code
= BFD_RELOC_16_PCREL
;
12103 if (fixp
->fx_pcrel
)
12105 code
= BFD_RELOC_32_PCREL
;
12109 case BFD_RELOC_ARM_PCREL_BRANCH
:
12110 case BFD_RELOC_ARM_PCREL_BLX
:
12111 case BFD_RELOC_RVA
:
12112 case BFD_RELOC_THUMB_PCREL_BRANCH9
:
12113 case BFD_RELOC_THUMB_PCREL_BRANCH12
:
12114 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
12115 case BFD_RELOC_THUMB_PCREL_BLX
:
12116 case BFD_RELOC_VTABLE_ENTRY
:
12117 case BFD_RELOC_VTABLE_INHERIT
:
12118 code
= fixp
->fx_r_type
;
12121 case BFD_RELOC_ARM_LITERAL
:
12122 case BFD_RELOC_ARM_HWLITERAL
:
12123 /* If this is called then the a literal has
12124 been referenced across a section boundary. */
12125 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12126 _("literal referenced across section boundary"));
12130 case BFD_RELOC_ARM_GOT32
:
12131 case BFD_RELOC_ARM_GOTOFF
:
12132 case BFD_RELOC_ARM_PLT32
:
12133 case BFD_RELOC_ARM_TARGET1
:
12134 case BFD_RELOC_ARM_ROSEGREL32
:
12135 case BFD_RELOC_ARM_SBREL32
:
12136 case BFD_RELOC_ARM_PREL31
:
12137 case BFD_RELOC_ARM_TARGET2
:
12138 code
= fixp
->fx_r_type
;
12142 case BFD_RELOC_ARM_IMMEDIATE
:
12143 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12144 _("internal relocation (type: IMMEDIATE) not fixed up"));
12147 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
12148 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12149 _("ADRL used for a symbol not defined in the same file"));
12152 case BFD_RELOC_ARM_OFFSET_IMM
:
12153 if (fixp
->fx_addsy
!= NULL
12154 && !S_IS_DEFINED (fixp
->fx_addsy
)
12155 && S_IS_LOCAL (fixp
->fx_addsy
))
12157 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12158 _("undefined local label `%s'"),
12159 S_GET_NAME (fixp
->fx_addsy
));
12163 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12164 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
12171 switch (fixp
->fx_r_type
)
12173 case BFD_RELOC_ARM_OFFSET_IMM8
: type
= "OFFSET_IMM8"; break;
12174 case BFD_RELOC_ARM_SHIFT_IMM
: type
= "SHIFT_IMM"; break;
12175 case BFD_RELOC_ARM_SMI
: type
= "SMI"; break;
12176 case BFD_RELOC_ARM_SWI
: type
= "SWI"; break;
12177 case BFD_RELOC_ARM_MULTI
: type
= "MULTI"; break;
12178 case BFD_RELOC_ARM_CP_OFF_IMM
: type
= "CP_OFF_IMM"; break;
12179 case BFD_RELOC_ARM_THUMB_ADD
: type
= "THUMB_ADD"; break;
12180 case BFD_RELOC_ARM_THUMB_SHIFT
: type
= "THUMB_SHIFT"; break;
12181 case BFD_RELOC_ARM_THUMB_IMM
: type
= "THUMB_IMM"; break;
12182 case BFD_RELOC_ARM_THUMB_OFFSET
: type
= "THUMB_OFFSET"; break;
12183 default: type
= _("<unknown>"); break;
12185 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12186 _("cannot represent %s relocation in this object file format"),
12193 if ((code
== BFD_RELOC_32_PCREL
|| code
== BFD_RELOC_32
)
12195 && fixp
->fx_addsy
== GOT_symbol
)
12197 code
= BFD_RELOC_ARM_GOTPC
;
12198 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
12202 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, code
);
12204 if (reloc
->howto
== NULL
)
12206 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12207 _("cannot represent %s relocation in this object file format"),
12208 bfd_get_reloc_code_name (code
));
12212 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12213 vtable entry to be used in the relocation's section offset. */
12214 if (fixp
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
12215 reloc
->address
= fixp
->fx_offset
;
12221 md_estimate_size_before_relax (fragS
* fragP ATTRIBUTE_UNUSED
,
12222 segT segtype ATTRIBUTE_UNUSED
)
12224 as_fatal (_("md_estimate_size_before_relax\n"));
12228 /* We need to be able to fix up arbitrary expressions in some statements.
12229 This is so that we can handle symbols that are an arbitrary distance from
12230 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
12231 which returns part of an address in a form which will be valid for
12232 a data instruction. We do this by pushing the expression into a symbol
12233 in the expr_section, and creating a fix for that. */
12236 fix_new_arm (fragS
* frag
,
12244 arm_fix_data
* arm_data
;
12252 new_fix
= fix_new_exp (frag
, where
, size
, exp
, pc_rel
, reloc
);
12256 new_fix
= fix_new (frag
, where
, size
, make_expr_symbol (exp
), 0,
12261 /* Mark whether the fix is to a THUMB instruction, or an ARM
12263 arm_data
= obstack_alloc (& notes
, sizeof (arm_fix_data
));
12264 new_fix
->tc_fix_data
= (PTR
) arm_data
;
12265 arm_data
->thumb_mode
= thumb_mode
;
12269 output_inst (const char * str
)
12275 as_bad ("%s -- `%s'", inst
.error
, str
);
12279 to
= frag_more (inst
.size
);
12281 if (thumb_mode
&& (inst
.size
> THUMB_SIZE
))
12283 assert (inst
.size
== (2 * THUMB_SIZE
));
12284 md_number_to_chars (to
, inst
.instruction
>> 16, THUMB_SIZE
);
12285 md_number_to_chars (to
+ THUMB_SIZE
, inst
.instruction
, THUMB_SIZE
);
12287 else if (inst
.size
> INSN_SIZE
)
12289 assert (inst
.size
== (2 * INSN_SIZE
));
12290 md_number_to_chars (to
, inst
.instruction
, INSN_SIZE
);
12291 md_number_to_chars (to
+ INSN_SIZE
, inst
.instruction
, INSN_SIZE
);
12294 md_number_to_chars (to
, inst
.instruction
, inst
.size
);
12296 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
12297 fix_new_arm (frag_now
, to
- frag_now
->fr_literal
,
12298 inst
.size
, & inst
.reloc
.exp
, inst
.reloc
.pc_rel
,
12302 dwarf2_emit_insn (inst
.size
);
12307 md_assemble (char * str
)
12313 /* Align the previous label if needed. */
12314 if (last_label_seen
!= NULL
)
12316 symbol_set_frag (last_label_seen
, frag_now
);
12317 S_SET_VALUE (last_label_seen
, (valueT
) frag_now_fix ());
12318 S_SET_SEGMENT (last_label_seen
, now_seg
);
12321 memset (&inst
, '\0', sizeof (inst
));
12322 inst
.reloc
.type
= BFD_RELOC_NONE
;
12324 skip_whitespace (str
);
12326 /* Scan up to the end of the op-code, which must end in white space or
12328 for (start
= p
= str
; *p
!= '\0'; p
++)
12334 as_bad (_("no operator -- statement `%s'\n"), str
);
12340 const struct thumb_opcode
* opcode
;
12344 opcode
= (const struct thumb_opcode
*) hash_find (arm_tops_hsh
, str
);
12349 /* Check that this instruction is supported for this CPU. */
12350 if (thumb_mode
== 1 && (opcode
->variant
& cpu_variant
) == 0)
12352 as_bad (_("selected processor does not support `%s'"), str
);
12356 mapping_state (MAP_THUMB
);
12357 inst
.instruction
= opcode
->value
;
12358 inst
.size
= opcode
->size
;
12366 const struct asm_opcode
* opcode
;
12370 opcode
= (const struct asm_opcode
*) hash_find (arm_ops_hsh
, str
);
12375 /* Check that this instruction is supported for this CPU. */
12376 if ((opcode
->variant
& cpu_variant
) == 0)
12378 as_bad (_("selected processor does not support `%s'"), str
);
12382 mapping_state (MAP_ARM
);
12383 inst
.instruction
= opcode
->value
;
12384 inst
.size
= INSN_SIZE
;
12391 /* It wasn't an instruction, but it might be a register alias of the form
12393 if (create_register_alias (str
, p
))
12396 as_bad (_("bad instruction `%s'"), start
);
12400 Invocation line includes a switch not recognized by the base assembler.
12401 See if it's a processor-specific option.
12403 This routine is somewhat complicated by the need for backwards
12404 compatibility (since older releases of gcc can't be changed).
12405 The new options try to make the interface as compatible as
12408 New options (supported) are:
12410 -mcpu=<cpu name> Assemble for selected processor
12411 -march=<architecture name> Assemble for selected architecture
12412 -mfpu=<fpu architecture> Assemble for selected FPU.
12413 -EB/-mbig-endian Big-endian
12414 -EL/-mlittle-endian Little-endian
12415 -k Generate PIC code
12416 -mthumb Start in Thumb mode
12417 -mthumb-interwork Code supports ARM/Thumb interworking
12419 For now we will also provide support for:
12421 -mapcs-32 32-bit Program counter
12422 -mapcs-26 26-bit Program counter
12423 -macps-float Floats passed in FP registers
12424 -mapcs-reentrant Reentrant code
12426 (sometime these will probably be replaced with -mapcs=<list of options>
12427 and -matpcs=<list of options>)
12429 The remaining options are only supported for back-wards compatibility.
12430 Cpu variants, the arm part is optional:
12431 -m[arm]1 Currently not supported.
12432 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
12433 -m[arm]3 Arm 3 processor
12434 -m[arm]6[xx], Arm 6 processors
12435 -m[arm]7[xx][t][[d]m] Arm 7 processors
12436 -m[arm]8[10] Arm 8 processors
12437 -m[arm]9[20][tdmi] Arm 9 processors
12438 -mstrongarm[110[0]] StrongARM processors
12439 -mxscale XScale processors
12440 -m[arm]v[2345[t[e]]] Arm architectures
12441 -mall All (except the ARM1)
12443 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
12444 -mfpe-old (No float load/store multiples)
12445 -mvfpxd VFP Single precision
12447 -mno-fpu Disable all floating point instructions
12449 The following CPU names are recognized:
12450 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
12451 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
12452 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
12453 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
12454 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
12455 arm10t arm10e, arm1020t, arm1020e, arm10200e,
12456 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
12460 const char * md_shortopts
= "m:k";
12462 #ifdef ARM_BI_ENDIAN
12463 #define OPTION_EB (OPTION_MD_BASE + 0)
12464 #define OPTION_EL (OPTION_MD_BASE + 1)
12466 #if TARGET_BYTES_BIG_ENDIAN
12467 #define OPTION_EB (OPTION_MD_BASE + 0)
12469 #define OPTION_EL (OPTION_MD_BASE + 1)
12473 struct option md_longopts
[] =
12476 {"EB", no_argument
, NULL
, OPTION_EB
},
12479 {"EL", no_argument
, NULL
, OPTION_EL
},
12481 {NULL
, no_argument
, NULL
, 0}
12484 size_t md_longopts_size
= sizeof (md_longopts
);
12486 struct arm_option_table
12488 char *option
; /* Option name to match. */
12489 char *help
; /* Help information. */
12490 int *var
; /* Variable to change. */
12491 int value
; /* What to change it to. */
12492 char *deprecated
; /* If non-null, print this message. */
12495 struct arm_option_table arm_opts
[] =
12497 {"k", N_("generate PIC code"), &pic_code
, 1, NULL
},
12498 {"mthumb", N_("assemble Thumb code"), &thumb_mode
, 1, NULL
},
12499 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
12500 &support_interwork
, 1, NULL
},
12501 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26
, 0, NULL
},
12502 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26
, 1, NULL
},
12503 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float
,
12505 {"mapcs-reentrant", N_("re-entrant code"), &pic_code
, 1, NULL
},
12506 {"matpcs", N_("code is ATPCS conformant"), &atpcs
, 1, NULL
},
12507 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian
, 1, NULL
},
12508 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian
, 1,
12511 /* These are recognized by the assembler, but have no affect on code. */
12512 {"mapcs-frame", N_("use frame pointer"), NULL
, 0, NULL
},
12513 {"mapcs-stack-check", N_("use stack size checking"), NULL
, 0, NULL
},
12515 /* DON'T add any new processors to this list -- we want the whole list
12516 to go away... Add them to the processors table instead. */
12517 {"marm1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
12518 {"m1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
12519 {"marm2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
12520 {"m2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
12521 {"marm250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
12522 {"m250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
12523 {"marm3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
12524 {"m3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
12525 {"marm6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
12526 {"m6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
12527 {"marm600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
12528 {"m600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
12529 {"marm610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
12530 {"m610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
12531 {"marm620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
12532 {"m620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
12533 {"marm7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
12534 {"m7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
12535 {"marm70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
12536 {"m70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
12537 {"marm700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
12538 {"m700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
12539 {"marm700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
12540 {"m700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
12541 {"marm710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
12542 {"m710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
12543 {"marm710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
12544 {"m710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
12545 {"marm720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
12546 {"m720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
12547 {"marm7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
12548 {"m7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
12549 {"marm7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
12550 {"m7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
12551 {"marm7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
12552 {"m7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
12553 {"marm7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
12554 {"m7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
12555 {"marm7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
12556 {"m7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
12557 {"marm7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
12558 {"m7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
12559 {"marm7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
12560 {"m7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
12561 {"marm7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
12562 {"m7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
12563 {"marm7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12564 {"m7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12565 {"marm7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12566 {"m7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12567 {"marm710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
12568 {"m710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
12569 {"marm720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
12570 {"m720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
12571 {"marm740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
12572 {"m740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
12573 {"marm8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
12574 {"m8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
12575 {"marm810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
12576 {"m810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
12577 {"marm9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
12578 {"m9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
12579 {"marm9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
12580 {"m9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
12581 {"marm920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
12582 {"m920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
12583 {"marm940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
12584 {"m940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
12585 {"mstrongarm", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=strongarm")},
12586 {"mstrongarm110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
12587 N_("use -mcpu=strongarm110")},
12588 {"mstrongarm1100", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
12589 N_("use -mcpu=strongarm1100")},
12590 {"mstrongarm1110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
12591 N_("use -mcpu=strongarm1110")},
12592 {"mxscale", NULL
, &legacy_cpu
, ARM_ARCH_XSCALE
, N_("use -mcpu=xscale")},
12593 {"miwmmxt", NULL
, &legacy_cpu
, ARM_ARCH_IWMMXT
, N_("use -mcpu=iwmmxt")},
12594 {"mall", NULL
, &legacy_cpu
, ARM_ANY
, N_("use -mcpu=all")},
12596 /* Architecture variants -- don't add any more to this list either. */
12597 {"mv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
12598 {"marmv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
12599 {"mv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
12600 {"marmv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
12601 {"mv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
12602 {"marmv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
12603 {"mv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
12604 {"marmv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
12605 {"mv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
12606 {"marmv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
12607 {"mv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
12608 {"marmv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
12609 {"mv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
12610 {"marmv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
12611 {"mv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
12612 {"marmv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
12613 {"mv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
12614 {"marmv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
12616 /* Floating point variants -- don't add any more to this list either. */
12617 {"mfpe-old", NULL
, &legacy_fpu
, FPU_ARCH_FPE
, N_("use -mfpu=fpe")},
12618 {"mfpa10", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa10")},
12619 {"mfpa11", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa11")},
12620 {"mno-fpu", NULL
, &legacy_fpu
, 0,
12621 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
12623 {NULL
, NULL
, NULL
, 0, NULL
}
12626 struct arm_cpu_option_table
12630 /* For some CPUs we assume an FPU unless the user explicitly sets
12635 /* This list should, at a minimum, contain all the cpu names
12636 recognized by GCC. */
12637 static struct arm_cpu_option_table arm_cpus
[] =
12639 {"all", ARM_ANY
, FPU_ARCH_FPA
},
12640 {"arm1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
12641 {"arm2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
12642 {"arm250", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
12643 {"arm3", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
12644 {"arm6", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12645 {"arm60", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12646 {"arm600", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12647 {"arm610", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12648 {"arm620", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12649 {"arm7", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12650 {"arm7m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
12651 {"arm7d", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12652 {"arm7dm", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
12653 {"arm7di", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12654 {"arm7dmi", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
12655 {"arm70", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12656 {"arm700", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12657 {"arm700i", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12658 {"arm710", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12659 {"arm710t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12660 {"arm720", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12661 {"arm720t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12662 {"arm740t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12663 {"arm710c", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12664 {"arm7100", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12665 {"arm7500", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12666 {"arm7500fe", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12667 {"arm7t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12668 {"arm7tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12669 {"arm7tdmi-s", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12670 {"arm8", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12671 {"arm810", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12672 {"strongarm", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12673 {"strongarm1", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12674 {"strongarm110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12675 {"strongarm1100", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12676 {"strongarm1110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12677 {"arm9", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12678 {"arm920", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12679 {"arm920t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12680 {"arm922t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12681 {"arm940t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12682 {"arm9tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12683 /* For V5 or later processors we default to using VFP; but the user
12684 should really set the FPU type explicitly. */
12685 {"arm9e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
12686 {"arm9e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12687 {"arm926ej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
12688 {"arm926ejs", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
12689 {"arm926ej-s", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
12690 {"arm946e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
12691 {"arm946e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12692 {"arm966e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
12693 {"arm966e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12694 {"arm10t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
12695 {"arm10e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12696 {"arm1020", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12697 {"arm1020t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
12698 {"arm1020e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12699 {"arm1026ejs", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
12700 {"arm1026ej-s", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
12701 {"arm1136js", ARM_ARCH_V6
, FPU_NONE
},
12702 {"arm1136j-s", ARM_ARCH_V6
, FPU_NONE
},
12703 {"arm1136jfs", ARM_ARCH_V6
, FPU_ARCH_VFP_V2
},
12704 {"arm1136jf-s", ARM_ARCH_V6
, FPU_ARCH_VFP_V2
},
12705 {"mpcore", ARM_ARCH_V6K
, FPU_ARCH_VFP_V2
},
12706 {"mpcorenovfp", ARM_ARCH_V6K
, FPU_NONE
},
12707 {"arm1176jz-s", ARM_ARCH_V6ZK
, FPU_NONE
},
12708 {"arm1176jzf-s", ARM_ARCH_V6ZK
, FPU_ARCH_VFP_V2
},
12709 /* ??? XSCALE is really an architecture. */
12710 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
12711 /* ??? iwmmxt is not a processor. */
12712 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP_V2
},
12713 {"i80200", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
12715 {"ep9312", ARM_ARCH_V4T
| ARM_CEXT_MAVERICK
, FPU_ARCH_MAVERICK
},
12719 struct arm_arch_option_table
12726 /* This list should, at a minimum, contain all the architecture names
12727 recognized by GCC. */
12728 static struct arm_arch_option_table arm_archs
[] =
12730 {"all", ARM_ANY
, FPU_ARCH_FPA
},
12731 {"armv1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
12732 {"armv2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
12733 {"armv2a", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
12734 {"armv2s", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
12735 {"armv3", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12736 {"armv3m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
12737 {"armv4", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12738 {"armv4xm", ARM_ARCH_V4xM
, FPU_ARCH_FPA
},
12739 {"armv4t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12740 {"armv4txm", ARM_ARCH_V4TxM
, FPU_ARCH_FPA
},
12741 {"armv5", ARM_ARCH_V5
, FPU_ARCH_VFP
},
12742 {"armv5t", ARM_ARCH_V5T
, FPU_ARCH_VFP
},
12743 {"armv5txm", ARM_ARCH_V5TxM
, FPU_ARCH_VFP
},
12744 {"armv5te", ARM_ARCH_V5TE
, FPU_ARCH_VFP
},
12745 {"armv5texp", ARM_ARCH_V5TExP
, FPU_ARCH_VFP
},
12746 {"armv5tej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP
},
12747 {"armv6", ARM_ARCH_V6
, FPU_ARCH_VFP
},
12748 {"armv6j", ARM_ARCH_V6
, FPU_ARCH_VFP
},
12749 {"armv6k", ARM_ARCH_V6K
, FPU_ARCH_VFP
},
12750 {"armv6z", ARM_ARCH_V6Z
, FPU_ARCH_VFP
},
12751 {"armv6zk", ARM_ARCH_V6ZK
, FPU_ARCH_VFP
},
12752 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP
},
12753 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP
},
12757 /* ISA extensions in the co-processor space. */
12758 struct arm_arch_extension_table
12764 static struct arm_arch_extension_table arm_extensions
[] =
12766 {"maverick", ARM_CEXT_MAVERICK
},
12767 {"xscale", ARM_CEXT_XSCALE
},
12768 {"iwmmxt", ARM_CEXT_IWMMXT
},
12772 struct arm_fpu_option_table
12778 /* This list should, at a minimum, contain all the fpu names
12779 recognized by GCC. */
12780 static struct arm_fpu_option_table arm_fpus
[] =
12782 {"softfpa", FPU_NONE
},
12783 {"fpe", FPU_ARCH_FPE
},
12784 {"fpe2", FPU_ARCH_FPE
},
12785 {"fpe3", FPU_ARCH_FPA
}, /* Third release supports LFM/SFM. */
12786 {"fpa", FPU_ARCH_FPA
},
12787 {"fpa10", FPU_ARCH_FPA
},
12788 {"fpa11", FPU_ARCH_FPA
},
12789 {"arm7500fe", FPU_ARCH_FPA
},
12790 {"softvfp", FPU_ARCH_VFP
},
12791 {"softvfp+vfp", FPU_ARCH_VFP_V2
},
12792 {"vfp", FPU_ARCH_VFP_V2
},
12793 {"vfp9", FPU_ARCH_VFP_V2
},
12794 {"vfp10", FPU_ARCH_VFP_V2
},
12795 {"vfp10-r0", FPU_ARCH_VFP_V1
},
12796 {"vfpxd", FPU_ARCH_VFP_V1xD
},
12797 {"arm1020t", FPU_ARCH_VFP_V1
},
12798 {"arm1020e", FPU_ARCH_VFP_V2
},
12799 {"arm1136jfs", FPU_ARCH_VFP_V2
},
12800 {"arm1136jf-s", FPU_ARCH_VFP_V2
},
12801 {"maverick", FPU_ARCH_MAVERICK
},
12805 struct arm_float_abi_option_table
12811 static struct arm_float_abi_option_table arm_float_abis
[] =
12813 {"hard", ARM_FLOAT_ABI_HARD
},
12814 {"softfp", ARM_FLOAT_ABI_SOFTFP
},
12815 {"soft", ARM_FLOAT_ABI_SOFT
},
12819 struct arm_eabi_option_table
12822 unsigned int value
;
12826 /* We only know how to output GNU and ver 4 (AAELF) formats. */
12827 static struct arm_eabi_option_table arm_eabis
[] =
12829 {"gnu", EF_ARM_EABI_UNKNOWN
},
12830 {"4", EF_ARM_EABI_VER4
},
12835 struct arm_long_option_table
12837 char * option
; /* Substring to match. */
12838 char * help
; /* Help information. */
12839 int (* func
) (char * subopt
); /* Function to decode sub-option. */
12840 char * deprecated
; /* If non-null, print this message. */
12844 arm_parse_extension (char * str
, int * opt_p
)
12846 while (str
!= NULL
&& *str
!= 0)
12848 struct arm_arch_extension_table
* opt
;
12854 as_bad (_("invalid architectural extension"));
12859 ext
= strchr (str
, '+');
12862 optlen
= ext
- str
;
12864 optlen
= strlen (str
);
12868 as_bad (_("missing architectural extension"));
12872 for (opt
= arm_extensions
; opt
->name
!= NULL
; opt
++)
12873 if (strncmp (opt
->name
, str
, optlen
) == 0)
12875 *opt_p
|= opt
->value
;
12879 if (opt
->name
== NULL
)
12881 as_bad (_("unknown architectural extnsion `%s'"), str
);
12892 arm_parse_cpu (char * str
)
12894 struct arm_cpu_option_table
* opt
;
12895 char * ext
= strchr (str
, '+');
12899 optlen
= ext
- str
;
12901 optlen
= strlen (str
);
12905 as_bad (_("missing cpu name `%s'"), str
);
12909 for (opt
= arm_cpus
; opt
->name
!= NULL
; opt
++)
12910 if (strncmp (opt
->name
, str
, optlen
) == 0)
12912 mcpu_cpu_opt
= opt
->value
;
12913 mcpu_fpu_opt
= opt
->default_fpu
;
12916 return arm_parse_extension (ext
, &mcpu_cpu_opt
);
12921 as_bad (_("unknown cpu `%s'"), str
);
12926 arm_parse_arch (char * str
)
12928 struct arm_arch_option_table
*opt
;
12929 char *ext
= strchr (str
, '+');
12933 optlen
= ext
- str
;
12935 optlen
= strlen (str
);
12939 as_bad (_("missing architecture name `%s'"), str
);
12944 for (opt
= arm_archs
; opt
->name
!= NULL
; opt
++)
12945 if (streq (opt
->name
, str
))
12947 march_cpu_opt
= opt
->value
;
12948 march_fpu_opt
= opt
->default_fpu
;
12951 return arm_parse_extension (ext
, &march_cpu_opt
);
12956 as_bad (_("unknown architecture `%s'\n"), str
);
12961 arm_parse_fpu (char * str
)
12963 struct arm_fpu_option_table
* opt
;
12965 for (opt
= arm_fpus
; opt
->name
!= NULL
; opt
++)
12966 if (streq (opt
->name
, str
))
12968 mfpu_opt
= opt
->value
;
12972 as_bad (_("unknown floating point format `%s'\n"), str
);
12977 arm_parse_float_abi (char * str
)
12979 struct arm_float_abi_option_table
* opt
;
12981 for (opt
= arm_float_abis
; opt
->name
!= NULL
; opt
++)
12982 if (streq (opt
->name
, str
))
12984 mfloat_abi_opt
= opt
->value
;
12988 as_bad (_("unknown floating point abi `%s'\n"), str
);
12994 arm_parse_eabi (char * str
)
12996 struct arm_eabi_option_table
*opt
;
12998 for (opt
= arm_eabis
; opt
->name
!= NULL
; opt
++)
12999 if (streq (opt
->name
, str
))
13001 meabi_flags
= opt
->value
;
13004 as_bad (_("unknown EABI `%s'\n"), str
);
13009 struct arm_long_option_table arm_long_opts
[] =
13011 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13012 arm_parse_cpu
, NULL
},
13013 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13014 arm_parse_arch
, NULL
},
13015 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13016 arm_parse_fpu
, NULL
},
13017 {"mfloat-abi=", N_("<abi>\t assemble for floating point ABI <abi>"),
13018 arm_parse_float_abi
, NULL
},
13020 {"meabi=", N_("<ver>\t assemble for eabi version <ver>"),
13021 arm_parse_eabi
, NULL
},
13023 {NULL
, NULL
, 0, NULL
}
13027 md_parse_option (int c
, char * arg
)
13029 struct arm_option_table
*opt
;
13030 struct arm_long_option_table
*lopt
;
13036 target_big_endian
= 1;
13042 target_big_endian
= 0;
13047 /* Listing option. Just ignore these, we don't support additional
13052 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
13054 if (c
== opt
->option
[0]
13055 && ((arg
== NULL
&& opt
->option
[1] == 0)
13056 || streq (arg
, opt
->option
+ 1)))
13058 #if WARN_DEPRECATED
13059 /* If the option is deprecated, tell the user. */
13060 if (opt
->deprecated
!= NULL
)
13061 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
,
13062 arg
? arg
: "", _(opt
->deprecated
));
13065 if (opt
->var
!= NULL
)
13066 *opt
->var
= opt
->value
;
13072 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
13074 /* These options are expected to have an argument. */
13075 if (c
== lopt
->option
[0]
13077 && strncmp (arg
, lopt
->option
+ 1,
13078 strlen (lopt
->option
+ 1)) == 0)
13080 #if WARN_DEPRECATED
13081 /* If the option is deprecated, tell the user. */
13082 if (lopt
->deprecated
!= NULL
)
13083 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
, arg
,
13084 _(lopt
->deprecated
));
13087 /* Call the sup-option parser. */
13088 return lopt
->func (arg
+ strlen (lopt
->option
) - 1);
13099 md_show_usage (FILE * fp
)
13101 struct arm_option_table
*opt
;
13102 struct arm_long_option_table
*lopt
;
13104 fprintf (fp
, _(" ARM-specific assembler options:\n"));
13106 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
13107 if (opt
->help
!= NULL
)
13108 fprintf (fp
, " -%-23s%s\n", opt
->option
, _(opt
->help
));
13110 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
13111 if (lopt
->help
!= NULL
)
13112 fprintf (fp
, " -%s%s\n", lopt
->option
, _(lopt
->help
));
13116 -EB assemble code for a big-endian cpu\n"));
13121 -EL assemble code for a little-endian cpu\n"));
13125 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13128 cons_fix_new_arm (fragS
* frag
,
13133 bfd_reloc_code_real_type type
;
13137 FIXME: @@ Should look at CPU word size. */
13141 type
= BFD_RELOC_8
;
13144 type
= BFD_RELOC_16
;
13148 type
= BFD_RELOC_32
;
13151 type
= BFD_RELOC_64
;
13155 fix_new_exp (frag
, where
, (int) size
, exp
, pcrel
, type
);
13158 /* A good place to do this, although this was probably not intended
13159 for this kind of use. We need to dump the literal pool before
13160 references are made to a null symbol pointer. */
13165 literal_pool
* pool
;
13167 for (pool
= list_of_pools
; pool
; pool
= pool
->next
)
13169 /* Put it at the end of the relevent section. */
13170 subseg_set (pool
->section
, pool
->sub_section
);
13172 arm_elf_change_section ();
13179 arm_start_line_hook (void)
13181 last_label_seen
= NULL
;
13185 arm_frob_label (symbolS
* sym
)
13187 last_label_seen
= sym
;
13189 ARM_SET_THUMB (sym
, thumb_mode
);
13191 #if defined OBJ_COFF || defined OBJ_ELF
13192 ARM_SET_INTERWORK (sym
, support_interwork
);
13195 /* Note - do not allow local symbols (.Lxxx) to be labeled
13196 as Thumb functions. This is because these labels, whilst
13197 they exist inside Thumb code, are not the entry points for
13198 possible ARM->Thumb calls. Also, these labels can be used
13199 as part of a computed goto or switch statement. eg gcc
13200 can generate code that looks like this:
13202 ldr r2, [pc, .Laaa]
13212 The first instruction loads the address of the jump table.
13213 The second instruction converts a table index into a byte offset.
13214 The third instruction gets the jump address out of the table.
13215 The fourth instruction performs the jump.
13217 If the address stored at .Laaa is that of a symbol which has the
13218 Thumb_Func bit set, then the linker will arrange for this address
13219 to have the bottom bit set, which in turn would mean that the
13220 address computation performed by the third instruction would end
13221 up with the bottom bit set. Since the ARM is capable of unaligned
13222 word loads, the instruction would then load the incorrect address
13223 out of the jump table, and chaos would ensue. */
13224 if (label_is_thumb_function_name
13225 && (S_GET_NAME (sym
)[0] != '.' || S_GET_NAME (sym
)[1] != 'L')
13226 && (bfd_get_section_flags (stdoutput
, now_seg
) & SEC_CODE
) != 0)
13228 /* When the address of a Thumb function is taken the bottom
13229 bit of that address should be set. This will allow
13230 interworking between Arm and Thumb functions to work
13233 THUMB_SET_FUNC (sym
, 1);
13235 label_is_thumb_function_name
= FALSE
;
13239 /* Adjust the symbol table. This marks Thumb symbols as distinct from
13243 arm_adjust_symtab (void)
13248 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
13250 if (ARM_IS_THUMB (sym
))
13252 if (THUMB_IS_FUNC (sym
))
13254 /* Mark the symbol as a Thumb function. */
13255 if ( S_GET_STORAGE_CLASS (sym
) == C_STAT
13256 || S_GET_STORAGE_CLASS (sym
) == C_LABEL
) /* This can happen! */
13257 S_SET_STORAGE_CLASS (sym
, C_THUMBSTATFUNC
);
13259 else if (S_GET_STORAGE_CLASS (sym
) == C_EXT
)
13260 S_SET_STORAGE_CLASS (sym
, C_THUMBEXTFUNC
);
13262 as_bad (_("%s: unexpected function type: %d"),
13263 S_GET_NAME (sym
), S_GET_STORAGE_CLASS (sym
));
13265 else switch (S_GET_STORAGE_CLASS (sym
))
13268 S_SET_STORAGE_CLASS (sym
, C_THUMBEXT
);
13271 S_SET_STORAGE_CLASS (sym
, C_THUMBSTAT
);
13274 S_SET_STORAGE_CLASS (sym
, C_THUMBLABEL
);
13282 if (ARM_IS_INTERWORK (sym
))
13283 coffsymbol (symbol_get_bfdsym (sym
))->native
->u
.syment
.n_flags
= 0xFF;
13290 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
13292 if (ARM_IS_THUMB (sym
))
13294 elf_symbol_type
* elf_sym
;
13296 elf_sym
= elf_symbol (symbol_get_bfdsym (sym
));
13297 bind
= ELF_ST_BIND (elf_sym
);
13299 /* If it's a .thumb_func, declare it as so,
13300 otherwise tag label as .code 16. */
13301 if (THUMB_IS_FUNC (sym
))
13302 elf_sym
->internal_elf_sym
.st_info
=
13303 ELF_ST_INFO (bind
, STT_ARM_TFUNC
);
13305 elf_sym
->internal_elf_sym
.st_info
=
13306 ELF_ST_INFO (bind
, STT_ARM_16BIT
);
13313 arm_data_in_code (void)
13315 if (thumb_mode
&& ! strncmp (input_line_pointer
+ 1, "data:", 5))
13317 *input_line_pointer
= '/';
13318 input_line_pointer
+= 5;
13319 *input_line_pointer
= 0;
13327 arm_canonicalize_symbol_name (char * name
)
13331 if (thumb_mode
&& (len
= strlen (name
)) > 5
13332 && streq (name
+ len
- 5, "/data"))
13333 *(name
+ len
- 5) = 0;
13338 #if defined OBJ_COFF || defined OBJ_ELF
13340 arm_validate_fix (fixS
* fixP
)
13342 /* If the destination of the branch is a defined symbol which does not have
13343 the THUMB_FUNC attribute, then we must be calling a function which has
13344 the (interfacearm) attribute. We look for the Thumb entry point to that
13345 function and change the branch to refer to that function instead. */
13346 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
13347 && fixP
->fx_addsy
!= NULL
13348 && S_IS_DEFINED (fixP
->fx_addsy
)
13349 && ! THUMB_IS_FUNC (fixP
->fx_addsy
))
13351 fixP
->fx_addsy
= find_real_start (fixP
->fx_addsy
);
13357 arm_force_relocation (struct fix
* fixp
)
13359 #if defined (OBJ_COFF) && defined (TE_PE)
13360 if (fixp
->fx_r_type
== BFD_RELOC_RVA
)
13364 if (fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
13365 || fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
13366 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
13367 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
)
13371 /* Resolve these relocations even if the symbol is extern or weak. */
13372 if (fixp
->fx_r_type
== BFD_RELOC_ARM_IMMEDIATE
13373 || fixp
->fx_r_type
== BFD_RELOC_ARM_OFFSET_IMM
13374 || fixp
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
13377 return generic_force_reloc (fixp
);
13381 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
13382 local labels from being added to the output symbol table when they
13383 are used with the ADRL pseudo op. The ADRL relocation should always
13384 be resolved before the binbary is emitted, so it is safe to say that
13385 it is adjustable. */
13388 arm_fix_adjustable (fixS
* fixP
)
13390 if (fixP
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
13397 /* Relocations against Thumb function names must be left unadjusted,
13398 so that the linker can use this information to correctly set the
13399 bottom bit of their addresses. The MIPS version of this function
13400 also prevents relocations that are mips-16 specific, but I do not
13401 know why it does this.
13404 There is one other problem that ought to be addressed here, but
13405 which currently is not: Taking the address of a label (rather
13406 than a function) and then later jumping to that address. Such
13407 addresses also ought to have their bottom bit set (assuming that
13408 they reside in Thumb code), but at the moment they will not. */
13411 arm_fix_adjustable (fixS
* fixP
)
13413 if (fixP
->fx_addsy
== NULL
)
13416 if (THUMB_IS_FUNC (fixP
->fx_addsy
)
13417 && fixP
->fx_subsy
== NULL
)
13420 /* We need the symbol name for the VTABLE entries. */
13421 if ( fixP
->fx_r_type
== BFD_RELOC_VTABLE_INHERIT
13422 || fixP
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
13425 /* Don't allow symbols to be discarded on GOT related relocs. */
13426 if (fixP
->fx_r_type
== BFD_RELOC_ARM_PLT32
13427 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOT32
13428 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOTOFF
13429 || fixP
->fx_r_type
== BFD_RELOC_ARM_TARGET2
)
13436 elf32_arm_target_format (void)
13439 return (target_big_endian
13440 ? "elf32-bigarm-symbian"
13441 : "elf32-littlearm-symbian");
13442 #elif defined (TE_VXWORKS)
13443 return (target_big_endian
13444 ? "elf32-bigarm-vxworks"
13445 : "elf32-littlearm-vxworks");
13447 if (target_big_endian
)
13448 return "elf32-bigarm";
13450 return "elf32-littlearm";
13455 armelf_frob_symbol (symbolS
* symp
,
13458 elf_frob_symbol (symp
, puntp
);
13462 s_arm_elf_cons (int nbytes
)
13466 #ifdef md_flush_pending_output
13467 md_flush_pending_output ();
13470 if (is_it_end_of_statement ())
13472 demand_empty_rest_of_line ();
13476 #ifdef md_cons_align
13477 md_cons_align (nbytes
);
13480 mapping_state (MAP_DATA
);
13483 bfd_reloc_code_real_type reloc
;
13485 expression (& exp
);
13487 if (exp
.X_op
== O_symbol
13488 && * input_line_pointer
== '('
13489 && (reloc
= arm_parse_reloc ()) != BFD_RELOC_UNUSED
)
13491 reloc_howto_type
*howto
= bfd_reloc_type_lookup (stdoutput
, reloc
);
13492 int size
= bfd_get_reloc_size (howto
);
13495 as_bad ("%s relocations do not fit in %d bytes",
13496 howto
->name
, nbytes
);
13499 char *p
= frag_more ((int) nbytes
);
13500 int offset
= nbytes
- size
;
13502 fix_new_exp (frag_now
, p
- frag_now
->fr_literal
+ offset
, size
,
13507 emit_expr (&exp
, (unsigned int) nbytes
);
13509 while (*input_line_pointer
++ == ',');
13511 /* Put terminator back into stream. */
13512 input_line_pointer
--;
13513 demand_empty_rest_of_line ();
13517 /* Parse a .rel31 directive. */
13520 s_arm_rel31 (int ignored ATTRIBUTE_UNUSED
)
13526 SKIP_WHITESPACE ();
13529 if (*input_line_pointer
== '1')
13530 highbit
= 0x80000000;
13531 else if (*input_line_pointer
!= '0')
13532 as_bad (_("expected 0 or 1"));
13534 input_line_pointer
++;
13535 SKIP_WHITESPACE ();
13536 if (*input_line_pointer
!= ',')
13537 as_bad (_("missing comma"));
13538 input_line_pointer
++;
13540 #ifdef md_flush_pending_output
13541 md_flush_pending_output ();
13544 #ifdef md_cons_align
13548 mapping_state (MAP_DATA
);
13553 md_number_to_chars (p
, highbit
, 4);
13554 fix_new_arm (frag_now
, p
- frag_now
->fr_literal
, 4, &exp
, 1,
13555 BFD_RELOC_ARM_PREL31
);
13557 demand_empty_rest_of_line ();
13560 /* Code to deal with unwinding tables. */
13562 static void add_unwind_adjustsp (offsetT
);
13564 /* Switch to section NAME and create section if necessary. It's
13565 rather ugly that we have to manipulate input_line_pointer but I
13566 don't see any other way to accomplish the same thing without
13567 changing obj-elf.c (which may be the Right Thing, in the end).
13568 Copied from tc-ia64.c. */
13571 set_section (char *name
)
13573 char *saved_input_line_pointer
;
13575 saved_input_line_pointer
= input_line_pointer
;
13576 input_line_pointer
= name
;
13577 obj_elf_section (0);
13578 input_line_pointer
= saved_input_line_pointer
;
13581 /* Cenerate and deferred unwind frame offset. */
13584 flush_pending_unwind (void)
13588 offset
= unwind
.pending_offset
;
13589 unwind
.pending_offset
= 0;
13591 add_unwind_adjustsp (offset
);
13594 /* Add an opcode to this list for this function. Two-byte opcodes should
13595 be passed as op[0] << 8 | op[1]. The list of opcodes is built in reverse
13599 add_unwind_opcode (valueT op
, int length
)
13601 /* Add any deferred stack adjustment. */
13602 if (unwind
.pending_offset
)
13603 flush_pending_unwind ();
13605 unwind
.sp_restored
= 0;
13607 if (unwind
.opcode_count
+ length
> unwind
.opcode_alloc
)
13609 unwind
.opcode_alloc
+= ARM_OPCODE_CHUNK_SIZE
;
13610 if (unwind
.opcodes
)
13611 unwind
.opcodes
= xrealloc (unwind
.opcodes
,
13612 unwind
.opcode_alloc
);
13614 unwind
.opcodes
= xmalloc (unwind
.opcode_alloc
);
13619 unwind
.opcodes
[unwind
.opcode_count
] = op
& 0xff;
13621 unwind
.opcode_count
++;
13625 /* Add unwind opcodes to adjust the stack pointer. */
13628 add_unwind_adjustsp (offsetT offset
)
13632 if (offset
> 0x200)
13634 /* We need at most 5 bytes to hold a 32-bit value in a uleb128. */
13639 /* Long form: 0xb2, uleb128. */
13640 /* This might not fit in a word so add the individual bytes,
13641 remembering the list is built in reverse order. */
13642 o
= (valueT
) ((offset
- 0x204) >> 2);
13644 add_unwind_opcode (0, 1);
13646 /* Calculate the uleb128 encoding of the offset. */
13650 bytes
[n
] = o
& 0x7f;
13656 /* Add the insn. */
13658 add_unwind_opcode (bytes
[n
- 1], 1);
13659 add_unwind_opcode (0xb2, 1);
13661 else if (offset
> 0x100)
13663 /* Two short opcodes. */
13664 add_unwind_opcode (0x3f, 1);
13665 op
= (offset
- 0x104) >> 2;
13666 add_unwind_opcode (op
, 1);
13668 else if (offset
> 0)
13670 /* Short opcode. */
13671 op
= (offset
- 4) >> 2;
13672 add_unwind_opcode (op
, 1);
13674 else if (offset
< 0)
13677 while (offset
> 0x100)
13679 add_unwind_opcode (0x7f, 1);
13682 op
= ((offset
- 4) >> 2) | 0x40;
13683 add_unwind_opcode (op
, 1);
13687 /* Finish the list of unwind opcodes for this function. */
13689 finish_unwind_opcodes (void)
13693 if (unwind
.fp_used
)
13695 /* Adjust sp as neccessary. */
13696 unwind
.pending_offset
+= unwind
.fp_offset
- unwind
.frame_size
;
13697 flush_pending_unwind ();
13699 /* After restoring sp from the frame pointer. */
13700 op
= 0x90 | unwind
.fp_reg
;
13701 add_unwind_opcode (op
, 1);
13704 flush_pending_unwind ();
13708 /* Start an exception table entry. If idx is nonzero this is an index table
13712 start_unwind_section (const segT text_seg
, int idx
)
13714 const char * text_name
;
13715 const char * prefix
;
13716 const char * prefix_once
;
13720 size_t sec_name_len
;
13724 prefix
= ELF_STRING_ARM_unwind
;
13725 prefix_once
= ELF_STRING_ARM_unwind_once
;
13729 prefix
= ELF_STRING_ARM_unwind_info
;
13730 prefix_once
= ELF_STRING_ARM_unwind_info_once
;
13733 text_name
= segment_name (text_seg
);
13734 if (streq (text_name
, ".text"))
13737 if (strncmp (text_name
, ".gnu.linkonce.t.",
13738 strlen (".gnu.linkonce.t.")) == 0)
13740 prefix
= prefix_once
;
13741 text_name
+= strlen (".gnu.linkonce.t.");
13744 prefix_len
= strlen (prefix
);
13745 text_len
= strlen (text_name
);
13746 sec_name_len
= prefix_len
+ text_len
;
13747 sec_name
= alloca (sec_name_len
+ 1);
13748 memcpy (sec_name
, prefix
, prefix_len
);
13749 memcpy (sec_name
+ prefix_len
, text_name
, text_len
);
13750 sec_name
[prefix_len
+ text_len
] = '\0';
13752 /* Handle COMDAT group. */
13753 if (prefix
!= prefix_once
&& (text_seg
->flags
& SEC_LINK_ONCE
) != 0)
13756 size_t len
, group_name_len
;
13757 const char *group_name
= elf_group_name (text_seg
);
13759 if (group_name
== NULL
)
13761 as_bad ("Group section `%s' has no group signature",
13762 segment_name (text_seg
));
13763 ignore_rest_of_line ();
13766 /* We have to construct a fake section directive. */
13767 group_name_len
= strlen (group_name
);
13773 len
= (sec_name_len
13774 + prefix_len
/* ,"aG",%sectiontype, */
13775 + group_name_len
/* ,group_name */
13776 + 7); /* ,comdat */
13778 section
= alloca (len
+ 1);
13779 memcpy (section
, sec_name
, sec_name_len
);
13781 memcpy (section
+ sec_name_len
, ",\"aG\",%exidx,", 13);
13783 memcpy (section
+ sec_name_len
, ",\"aG\",%progbits,", 16);
13784 memcpy (section
+ sec_name_len
+ prefix_len
, group_name
, group_name_len
);
13785 memcpy (section
+ len
- 7, ",comdat", 7);
13786 section
[len
] = '\0';
13787 set_section (section
);
13791 set_section (sec_name
);
13792 bfd_set_section_flags (stdoutput
, now_seg
,
13793 SEC_LOAD
| SEC_ALLOC
| SEC_READONLY
);
13796 /* Set the setion link for index tables. */
13798 elf_linked_to_section (now_seg
) = text_seg
;
13802 /* Start an unwind table entry. HAVE_DATA is nonzero if we have additional
13803 personality routine data. Returns zero, or the index table value for
13804 and inline entry. */
13807 create_unwind_entry (int have_data
)
13811 unsigned char *ptr
;
13812 /* The current word of data. */
13814 /* The number of bytes left in this word. */
13817 finish_unwind_opcodes ();
13819 /* Remember the current text section. */
13820 unwind
.saved_seg
= now_seg
;
13821 unwind
.saved_subseg
= now_subseg
;
13823 start_unwind_section (now_seg
, 0);
13825 if (unwind
.personality_routine
== NULL
)
13827 if (unwind
.personality_index
== -2)
13830 as_bad (_("handerdata in cantunwind frame"));
13831 return 1; /* EXIDX_CANTUNWIND. */
13834 /* Use a default personality routine if none is specified. */
13835 if (unwind
.personality_index
== -1)
13837 if (unwind
.opcode_count
> 3)
13838 unwind
.personality_index
= 1;
13840 unwind
.personality_index
= 0;
13843 /* Space for the personality routine entry. */
13844 if (unwind
.personality_index
== 0)
13846 if (unwind
.opcode_count
> 3)
13847 as_bad (_("too many unwind opcodes for personality routine 0"));
13851 /* All the data is inline in the index table. */
13854 while (unwind
.opcode_count
> 0)
13856 unwind
.opcode_count
--;
13857 data
= (data
<< 8) | unwind
.opcodes
[unwind
.opcode_count
];
13861 /* Pad with "finish" opcodes. */
13863 data
= (data
<< 8) | 0xb0;
13870 /* We get two opcodes "free" in the first word. */
13871 size
= unwind
.opcode_count
- 2;
13874 /* An extra byte is required for the opcode count. */
13875 size
= unwind
.opcode_count
+ 1;
13877 size
= (size
+ 3) >> 2;
13879 as_bad (_("too many unwind opcodes"));
13881 frag_align (2, 0, 0);
13882 record_alignment (now_seg
, 2);
13883 unwind
.table_entry
= expr_build_dot ();
13885 /* Allocate the table entry. */
13886 ptr
= frag_more ((size
<< 2) + 4);
13887 where
= frag_now_fix () - ((size
<< 2) + 4);
13889 switch (unwind
.personality_index
)
13892 /* ??? Should this be a PLT generating relocation? */
13893 /* Custom personality routine. */
13894 fix_new (frag_now
, where
, 4, unwind
.personality_routine
, 0, 1,
13895 BFD_RELOC_ARM_PREL31
);
13899 /* Set the first byte to the number of additional words. */
13904 /* ABI defined personality routines. */
13905 /* TODO: Emit R_ARM_NONE to the personality routine. */
13907 /* Three opcodes bytes are packed into the first word. */
13914 /* The size and first two opcode bytes go in the first word. */
13915 data
= ((0x80 + unwind
.personality_index
) << 8) | size
;
13920 /* Should never happen. */
13924 /* Pack the opcodes into words (MSB first), reversing the list at the same
13926 while (unwind
.opcode_count
> 0)
13930 md_number_to_chars (ptr
, data
, 4);
13935 unwind
.opcode_count
--;
13937 data
= (data
<< 8) | unwind
.opcodes
[unwind
.opcode_count
];
13940 /* Finish off the last word. */
13943 /* Pad with "finish" opcodes. */
13945 data
= (data
<< 8) | 0xb0;
13947 md_number_to_chars (ptr
, data
, 4);
13952 /* Add an empty descriptor if there is no user-specified data. */
13953 ptr
= frag_more (4);
13954 md_number_to_chars (ptr
, 0, 4);
13961 /* Parse an unwind_fnstart directive. Simply records the current location. */
13964 s_arm_unwind_fnstart (int ignored ATTRIBUTE_UNUSED
)
13966 demand_empty_rest_of_line ();
13967 /* Mark the start of the function. */
13968 unwind
.proc_start
= expr_build_dot ();
13970 /* Reset the rest of the unwind info. */
13971 unwind
.opcode_count
= 0;
13972 unwind
.table_entry
= NULL
;
13973 unwind
.personality_routine
= NULL
;
13974 unwind
.personality_index
= -1;
13975 unwind
.frame_size
= 0;
13976 unwind
.fp_offset
= 0;
13977 unwind
.fp_reg
= 13;
13978 unwind
.fp_used
= 0;
13979 unwind
.sp_restored
= 0;
13983 /* Parse a handlerdata directive. Creates the exception handling table entry
13984 for the function. */
13987 s_arm_unwind_handlerdata (int ignored ATTRIBUTE_UNUSED
)
13989 demand_empty_rest_of_line ();
13990 if (unwind
.table_entry
)
13991 as_bad (_("dupicate .handlerdata directive"));
13993 create_unwind_entry (1);
13996 /* Parse an unwind_fnend directive. Generates the index table entry. */
13999 s_arm_unwind_fnend (int ignored ATTRIBUTE_UNUSED
)
14002 unsigned char *ptr
;
14005 demand_empty_rest_of_line ();
14007 /* Add eh table entry. */
14008 if (unwind
.table_entry
== NULL
)
14009 val
= create_unwind_entry (0);
14013 /* Add index table entry. This is two words. */
14014 start_unwind_section (unwind
.saved_seg
, 1);
14015 frag_align (2, 0, 0);
14016 record_alignment (now_seg
, 2);
14018 ptr
= frag_more (8);
14019 where
= frag_now_fix () - 8;
14021 /* Self relative offset of the function start. */
14022 fix_new (frag_now
, where
, 4, unwind
.proc_start
, 0, 1,
14023 BFD_RELOC_ARM_PREL31
);
14026 /* Inline exception table entry. */
14027 md_number_to_chars (ptr
+ 4, val
, 4);
14029 /* Self relative offset of the table entry. */
14030 fix_new (frag_now
, where
+ 4, 4, unwind
.table_entry
, 0, 1,
14031 BFD_RELOC_ARM_PREL31
);
14033 /* Restore the original section. */
14034 subseg_set (unwind
.saved_seg
, unwind
.saved_subseg
);
14038 /* Parse an unwind_cantunwind directive. */
14041 s_arm_unwind_cantunwind (int ignored ATTRIBUTE_UNUSED
)
14043 demand_empty_rest_of_line ();
14044 if (unwind
.personality_routine
|| unwind
.personality_index
!= -1)
14045 as_bad (_("personality routine specified for cantunwind frame"));
14047 unwind
.personality_index
= -2;
14051 /* Parse a personalityindex directive. */
14054 s_arm_unwind_personalityindex (int ignored ATTRIBUTE_UNUSED
)
14058 if (unwind
.personality_routine
|| unwind
.personality_index
!= -1)
14059 as_bad (_("duplicate .personalityindex directive"));
14061 SKIP_WHITESPACE ();
14065 if (exp
.X_op
!= O_constant
14066 || exp
.X_add_number
< 0 || exp
.X_add_number
> 15)
14068 as_bad (_("bad personality routine number"));
14069 ignore_rest_of_line ();
14073 unwind
.personality_index
= exp
.X_add_number
;
14075 demand_empty_rest_of_line ();
14079 /* Parse a personality directive. */
14082 s_arm_unwind_personality (int ignored ATTRIBUTE_UNUSED
)
14086 if (unwind
.personality_routine
|| unwind
.personality_index
!= -1)
14087 as_bad (_("duplicate .personality directive"));
14089 SKIP_WHITESPACE ();
14090 name
= input_line_pointer
;
14091 c
= get_symbol_end ();
14092 p
= input_line_pointer
;
14093 unwind
.personality_routine
= symbol_find_or_make (name
);
14095 SKIP_WHITESPACE ();
14096 demand_empty_rest_of_line ();
14100 /* Parse a directive saving core registers. */
14103 s_arm_unwind_save_core (void)
14109 SKIP_WHITESPACE ();
14110 range
= reg_list (&input_line_pointer
);
14113 as_bad (_("expected register list"));
14114 ignore_rest_of_line ();
14118 demand_empty_rest_of_line ();
14120 /* Turn .unwind_movsp ip followed by .unwind_save {..., ip, ...}
14121 into .unwind_save {..., sp...}. We aren't bothered about the value of
14122 ip because it is clobbered by calls. */
14123 if (unwind
.sp_restored
&& unwind
.fp_reg
== 12
14124 && (range
& 0x3000) == 0x1000)
14126 unwind
.opcode_count
--;
14127 unwind
.sp_restored
= 0;
14128 range
= (range
| 0x2000) & ~0x1000;
14129 unwind
.pending_offset
= 0;
14132 /* See if we can use the short opcodes. These pop a block of upto 8
14133 registers starting with r4, plus maybe r14. */
14134 for (n
= 0; n
< 8; n
++)
14136 /* Break at the first non-saved register. */
14137 if ((range
& (1 << (n
+ 4))) == 0)
14140 /* See if there are any other bits set. */
14141 if (n
== 0 || (range
& (0xfff0 << n
) & 0xbff0) != 0)
14143 /* Use the long form. */
14144 op
= 0x8000 | ((range
>> 4) & 0xfff);
14145 add_unwind_opcode (op
, 2);
14149 /* Use the short form. */
14150 if (range
& 0x4000)
14151 op
= 0xa8; /* Pop r14. */
14153 op
= 0xa0; /* Do not pop r14. */
14155 add_unwind_opcode (op
, 1);
14161 op
= 0xb100 | (range
& 0xf);
14162 add_unwind_opcode (op
, 2);
14165 /* Record the number of bytes pushed. */
14166 for (n
= 0; n
< 16; n
++)
14168 if (range
& (1 << n
))
14169 unwind
.frame_size
+= 4;
14174 /* Parse a directive saving FPA registers. */
14177 s_arm_unwind_save_fpa (int reg
)
14183 /* Get Number of registers to transfer. */
14184 if (skip_past_comma (&input_line_pointer
) != FAIL
)
14187 exp
.X_op
= O_illegal
;
14189 if (exp
.X_op
!= O_constant
)
14191 as_bad (_("expected , <constant>"));
14192 ignore_rest_of_line ();
14196 num_regs
= exp
.X_add_number
;
14198 if (num_regs
< 1 || num_regs
> 4)
14200 as_bad (_("number of registers must be in the range [1:4]"));
14201 ignore_rest_of_line ();
14205 demand_empty_rest_of_line ();
14210 op
= 0xb4 | (num_regs
- 1);
14211 add_unwind_opcode (op
, 1);
14216 op
= 0xc800 | (reg
<< 4) | (num_regs
- 1);
14217 add_unwind_opcode (op
, 2);
14219 unwind
.frame_size
+= num_regs
* 12;
14223 /* Parse a directive saving VFP registers. */
14226 s_arm_unwind_save_vfp (void)
14232 count
= vfp_parse_reg_list (&input_line_pointer
, ®
, 1);
14235 as_bad (_("expected register list"));
14236 ignore_rest_of_line ();
14240 demand_empty_rest_of_line ();
14245 op
= 0xb8 | (count
- 1);
14246 add_unwind_opcode (op
, 1);
14251 op
= 0xb300 | (reg
<< 4) | (count
- 1);
14252 add_unwind_opcode (op
, 2);
14254 unwind
.frame_size
+= count
* 8 + 4;
14258 /* Parse a directive saving iWMMXt registers. */
14261 s_arm_unwind_save_wmmx (void)
14270 if (*input_line_pointer
== '{')
14271 input_line_pointer
++;
14277 reg
= arm_reg_parse (&input_line_pointer
,
14278 all_reg_maps
[REG_TYPE_IWMMXT
].htab
);
14280 if (wr_register (reg
))
14282 i
= reg
& ~WR_PREFIX
;
14284 as_tsktsk (_("register list not in ascending order"));
14287 else if (wcg_register (reg
))
14289 i
= (reg
& ~WC_PREFIX
) - 8;
14291 as_tsktsk (_("register list not in ascending order"));
14292 wcg_mask
|= 1 << i
;
14296 as_bad (_("expected wr or wcgr"));
14300 SKIP_WHITESPACE ();
14301 if (*input_line_pointer
== '-')
14303 hi_reg
= arm_reg_parse (&input_line_pointer
,
14304 all_reg_maps
[REG_TYPE_IWMMXT
].htab
);
14305 if (wr_register (reg
) && wr_register (hi_reg
))
14307 for (; reg
< hi_reg
; reg
++)
14308 wr_mask
|= 1 << (reg
& ~WR_PREFIX
);
14310 else if (wcg_register (reg
) && wcg_register (hi_reg
))
14312 for (; reg
< hi_reg
; reg
++)
14313 wcg_mask
|= 1 << ((reg
& ~WC_PREFIX
) - 8);
14317 as_bad (_("bad register range"));
14322 while (skip_past_comma (&input_line_pointer
) != FAIL
);
14324 SKIP_WHITESPACE ();
14325 if (*input_line_pointer
== '}')
14326 input_line_pointer
++;
14328 demand_empty_rest_of_line ();
14330 if (wr_mask
&& wcg_mask
)
14332 as_bad (_("inconsistent register types"));
14336 /* Generate any deferred opcodes becuuse we're going to be looking at
14338 flush_pending_unwind ();
14342 for (i
= 0; i
< 16; i
++)
14344 if (wcg_mask
& (1 << i
))
14345 unwind
.frame_size
+= 4;
14347 op
= 0xc700 | wcg_mask
;
14348 add_unwind_opcode (op
, 2);
14352 for (i
= 0; i
< 16; i
++)
14354 if (wr_mask
& (1 << i
))
14355 unwind
.frame_size
+= 8;
14357 /* Attempt to combine with a previous opcode. We do this because gcc
14358 likes to output separate unwind directives for a single block of
14360 if (unwind
.opcode_count
> 0)
14362 i
= unwind
.opcodes
[unwind
.opcode_count
- 1];
14363 if ((i
& 0xf8) == 0xc0)
14366 /* Only merge if the blocks are contiguous. */
14369 if ((wr_mask
& 0xfe00) == (1 << 9))
14371 wr_mask
|= ((1 << (i
+ 11)) - 1) & 0xfc00;
14372 unwind
.opcode_count
--;
14375 else if (i
== 6 && unwind
.opcode_count
>= 2)
14377 i
= unwind
.opcodes
[unwind
.opcode_count
- 2];
14381 op
= 0xffff << (reg
- 1);
14383 || ((wr_mask
& op
) == (1u << (reg
- 1))))
14385 op
= (1 << (reg
+ i
+ 1)) - 1;
14386 op
&= ~((1 << reg
) - 1);
14388 unwind
.opcode_count
-= 2;
14395 /* We want to generate opcodes in the order the registers have been
14396 saved, ie. descending order. */
14397 for (reg
= 15; reg
>= -1; reg
--)
14399 /* Save registers in blocks. */
14401 || !(wr_mask
& (1 << reg
)))
14403 /* We found an unsaved reg. Generate opcodes to save the
14404 preceeding block. */
14410 op
= 0xc0 | (hi_reg
- 10);
14411 add_unwind_opcode (op
, 1);
14416 op
= 0xc600 | ((reg
+ 1) << 4) | ((hi_reg
- reg
) - 1);
14417 add_unwind_opcode (op
, 2);
14426 ignore_rest_of_line ();
14430 /* Parse an unwind_save directive. */
14433 s_arm_unwind_save (int ignored ATTRIBUTE_UNUSED
)
14438 /* Figure out what sort of save we have. */
14439 SKIP_WHITESPACE ();
14440 saved_ptr
= input_line_pointer
;
14442 reg
= arm_reg_parse (&input_line_pointer
, all_reg_maps
[REG_TYPE_FN
].htab
);
14445 s_arm_unwind_save_fpa (reg
);
14449 if (*input_line_pointer
== '{')
14450 input_line_pointer
++;
14452 SKIP_WHITESPACE ();
14454 reg
= arm_reg_parse (&input_line_pointer
, all_reg_maps
[REG_TYPE_RN
].htab
);
14457 input_line_pointer
= saved_ptr
;
14458 s_arm_unwind_save_core ();
14462 reg
= arm_reg_parse (&input_line_pointer
, all_reg_maps
[REG_TYPE_DN
].htab
);
14465 input_line_pointer
= saved_ptr
;
14466 s_arm_unwind_save_vfp ();
14470 reg
= arm_reg_parse (&input_line_pointer
,
14471 all_reg_maps
[REG_TYPE_IWMMXT
].htab
);
14474 input_line_pointer
= saved_ptr
;
14475 s_arm_unwind_save_wmmx ();
14479 /* TODO: Maverick registers. */
14480 as_bad (_("unrecognised register"));
14484 /* Parse an unwind_movsp directive. */
14487 s_arm_unwind_movsp (int ignored ATTRIBUTE_UNUSED
)
14492 SKIP_WHITESPACE ();
14493 reg
= reg_required_here (&input_line_pointer
, -1);
14496 as_bad (_("ARM register expected"));
14497 ignore_rest_of_line ();
14501 if (reg
== 13 || reg
== 15)
14503 as_bad (_("r%d not permitted in .unwind_movsp directive"), reg
);
14504 ignore_rest_of_line ();
14508 if (unwind
.fp_reg
!= 13)
14509 as_bad (_("unexpected .unwind_movsp directive"));
14511 /* Generate opcode to restore the value. */
14513 add_unwind_opcode (op
, 1);
14515 /* Record the information for later. */
14516 unwind
.fp_reg
= reg
;
14517 unwind
.fp_offset
= unwind
.frame_size
;
14518 unwind
.sp_restored
= 1;
14519 demand_empty_rest_of_line ();
14523 /* Parse #<number>. */
14526 require_hashconst (int * val
)
14530 SKIP_WHITESPACE ();
14531 if (*input_line_pointer
== '#')
14533 input_line_pointer
++;
14537 exp
.X_op
= O_illegal
;
14539 if (exp
.X_op
!= O_constant
)
14541 as_bad (_("expected #constant"));
14542 ignore_rest_of_line ();
14545 *val
= exp
.X_add_number
;
14549 /* Parse an unwind_pad directive. */
14552 s_arm_unwind_pad (int ignored ATTRIBUTE_UNUSED
)
14556 if (require_hashconst (&offset
) == FAIL
)
14561 as_bad (_("stack increment must be multiple of 4"));
14562 ignore_rest_of_line ();
14566 /* Don't generate any opcodes, just record the details for later. */
14567 unwind
.frame_size
+= offset
;
14568 unwind
.pending_offset
+= offset
;
14570 demand_empty_rest_of_line ();
14573 /* Parse an unwind_setfp directive. */
14576 s_arm_unwind_setfp (int ignored ATTRIBUTE_UNUSED
)
14582 fp_reg
= reg_required_here (&input_line_pointer
, -1);
14583 if (skip_past_comma (&input_line_pointer
) == FAIL
)
14586 sp_reg
= reg_required_here (&input_line_pointer
, -1);
14588 if (fp_reg
== FAIL
|| sp_reg
== FAIL
)
14590 as_bad (_("expected <reg>, <reg>"));
14591 ignore_rest_of_line ();
14595 /* Optonal constant. */
14596 if (skip_past_comma (&input_line_pointer
) != FAIL
)
14598 if (require_hashconst (&offset
) == FAIL
)
14604 demand_empty_rest_of_line ();
14606 if (sp_reg
!= 13 && sp_reg
!= unwind
.fp_reg
)
14608 as_bad (_("register must be either sp or set by a previous"
14609 "unwind_movsp directive"));
14613 /* Don't generate any opcodes, just record the information for later. */
14614 unwind
.fp_reg
= fp_reg
;
14615 unwind
.fp_used
= 1;
14617 unwind
.fp_offset
= unwind
.frame_size
- offset
;
14619 unwind
.fp_offset
-= offset
;
14622 /* Parse an unwind_raw directive. */
14625 s_arm_unwind_raw (int ignored ATTRIBUTE_UNUSED
)
14628 /* This is an arbitary limit. */
14629 unsigned char op
[16];
14632 SKIP_WHITESPACE ();
14634 if (exp
.X_op
== O_constant
14635 && skip_past_comma (&input_line_pointer
) != FAIL
)
14637 unwind
.frame_size
+= exp
.X_add_number
;
14641 exp
.X_op
= O_illegal
;
14643 if (exp
.X_op
!= O_constant
)
14645 as_bad (_("expected <offset>, <opcode>"));
14646 ignore_rest_of_line ();
14652 /* Parse the opcode. */
14657 as_bad (_("unwind opcode too long"));
14658 ignore_rest_of_line ();
14660 if (exp
.X_op
!= O_constant
|| exp
.X_add_number
& ~0xff)
14662 as_bad (_("invalid unwind opcode"));
14663 ignore_rest_of_line ();
14666 op
[count
++] = exp
.X_add_number
;
14668 /* Parse the next byte. */
14669 if (skip_past_comma (&input_line_pointer
) == FAIL
)
14675 /* Add the opcode bytes in reverse order. */
14677 add_unwind_opcode (op
[count
], 1);
14679 demand_empty_rest_of_line ();
14682 #endif /* OBJ_ELF */
14684 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
14685 of an rs_align_code fragment. */
14688 arm_handle_align (fragS
* fragP
)
14690 static char const arm_noop
[4] = { 0x00, 0x00, 0xa0, 0xe1 };
14691 static char const thumb_noop
[2] = { 0xc0, 0x46 };
14692 static char const arm_bigend_noop
[4] = { 0xe1, 0xa0, 0x00, 0x00 };
14693 static char const thumb_bigend_noop
[2] = { 0x46, 0xc0 };
14695 int bytes
, fix
, noop_size
;
14699 if (fragP
->fr_type
!= rs_align_code
)
14702 bytes
= fragP
->fr_next
->fr_address
- fragP
->fr_address
- fragP
->fr_fix
;
14703 p
= fragP
->fr_literal
+ fragP
->fr_fix
;
14706 if (bytes
> MAX_MEM_FOR_RS_ALIGN_CODE
)
14707 bytes
&= MAX_MEM_FOR_RS_ALIGN_CODE
;
14709 if (fragP
->tc_frag_data
)
14711 if (target_big_endian
)
14712 noop
= thumb_bigend_noop
;
14715 noop_size
= sizeof (thumb_noop
);
14719 if (target_big_endian
)
14720 noop
= arm_bigend_noop
;
14723 noop_size
= sizeof (arm_noop
);
14726 if (bytes
& (noop_size
- 1))
14728 fix
= bytes
& (noop_size
- 1);
14729 memset (p
, 0, fix
);
14734 while (bytes
>= noop_size
)
14736 memcpy (p
, noop
, noop_size
);
14738 bytes
-= noop_size
;
14742 fragP
->fr_fix
+= fix
;
14743 fragP
->fr_var
= noop_size
;
14746 /* Called from md_do_align. Used to create an alignment
14747 frag in a code section. */
14750 arm_frag_align_code (int n
, int max
)
14754 /* We assume that there will never be a requirement
14755 to support alignments greater than 32 bytes. */
14756 if (max
> MAX_MEM_FOR_RS_ALIGN_CODE
)
14757 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
14759 p
= frag_var (rs_align_code
,
14760 MAX_MEM_FOR_RS_ALIGN_CODE
,
14762 (relax_substateT
) max
,
14769 /* Perform target specific initialisation of a frag. */
14772 arm_init_frag (fragS
* fragP
)
14774 /* Record whether this frag is in an ARM or a THUMB area. */
14775 fragP
->tc_frag_data
= thumb_mode
;
14780 /* Convert REGNAME to a DWARF-2 register number. */
14783 tc_arm_regname_to_dw2regnum (const char *regname
)
14787 for (i
= 0; rn_table
[i
].name
; i
++)
14788 if (streq (regname
, rn_table
[i
].name
))
14789 return rn_table
[i
].number
;
14794 /* Initialize the DWARF-2 unwind information for this procedure. */
14797 tc_arm_frame_initial_instructions (void)
14799 cfi_add_CFA_def_cfa (REG_SP
, 0);
14803 /* This table describes all the machine specific pseudo-ops the assembler
14804 has to support. The fields are:
14805 pseudo-op name without dot
14806 function to call to execute this pseudo-op
14807 Integer arg to pass to the function. */
14809 const pseudo_typeS md_pseudo_table
[] =
14811 /* Never called because '.req' does not start a line. */
14812 { "req", s_req
, 0 },
14813 { "unreq", s_unreq
, 0 },
14814 { "bss", s_bss
, 0 },
14815 { "align", s_align
, 0 },
14816 { "arm", s_arm
, 0 },
14817 { "thumb", s_thumb
, 0 },
14818 { "code", s_code
, 0 },
14819 { "force_thumb", s_force_thumb
, 0 },
14820 { "thumb_func", s_thumb_func
, 0 },
14821 { "thumb_set", s_thumb_set
, 0 },
14822 { "even", s_even
, 0 },
14823 { "ltorg", s_ltorg
, 0 },
14824 { "pool", s_ltorg
, 0 },
14826 { "word", s_arm_elf_cons
, 4 },
14827 { "long", s_arm_elf_cons
, 4 },
14828 { "rel31", s_arm_rel31
, 0 },
14829 { "fnstart", s_arm_unwind_fnstart
, 0 },
14830 { "fnend", s_arm_unwind_fnend
, 0 },
14831 { "cantunwind", s_arm_unwind_cantunwind
, 0 },
14832 { "personality", s_arm_unwind_personality
, 0 },
14833 { "personalityindex", s_arm_unwind_personalityindex
, 0 },
14834 { "handlerdata", s_arm_unwind_handlerdata
, 0 },
14835 { "save", s_arm_unwind_save
, 0 },
14836 { "movsp", s_arm_unwind_movsp
, 0 },
14837 { "pad", s_arm_unwind_pad
, 0 },
14838 { "setfp", s_arm_unwind_setfp
, 0 },
14839 { "unwind_raw", s_arm_unwind_raw
, 0 },
14841 { "word", cons
, 4},
14843 { "extend", float_cons
, 'x' },
14844 { "ldouble", float_cons
, 'x' },
14845 { "packed", float_cons
, 'p' },