1 /* tc-arm.c -- Assemble for the ARM
2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
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
;
4555 static bfd_reloc_code_real_type
4556 arm_parse_reloc (void)
4565 bfd_reloc_code_real_type reloc
;
4569 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
4570 MAP ("(got)", BFD_RELOC_ARM_GOT32
),
4571 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF
),
4572 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
4573 branch instructions generated by GCC for PLT relocs. */
4574 MAP ("(plt)", BFD_RELOC_ARM_PLT32
),
4575 MAP ("(target1)", BFD_RELOC_ARM_TARGET1
),
4576 MAP ("(sbrel)", BFD_RELOC_ARM_SBREL32
),
4577 MAP ("(target2)", BFD_RELOC_ARM_TARGET2
),
4578 { NULL
, 0, BFD_RELOC_UNUSED
}
4582 for (i
= 0, ip
= input_line_pointer
;
4583 i
< sizeof (id
) && (ISALNUM (*ip
) || ISPUNCT (*ip
));
4585 id
[i
] = TOLOWER (*ip
);
4587 for (i
= 0; reloc_map
[i
].str
; i
++)
4588 if (strncmp (id
, reloc_map
[i
].str
, reloc_map
[i
].len
) == 0)
4591 input_line_pointer
+= reloc_map
[i
].len
;
4593 return reloc_map
[i
].reloc
;
4597 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
4598 Expects inst.instruction is set for BLX(1).
4599 Note: this is cloned from do_branch, and the reloc changed to be a
4600 new one that can cope with setting one extra bit (the H bit). */
4603 do_branch25 (char * str
)
4605 if (my_get_expression (& inst
.reloc
.exp
, & str
))
4612 /* ScottB: February 5, 1998 */
4613 /* Check to see of PLT32 reloc required for the instruction. */
4615 /* arm_parse_reloc() works on input_line_pointer.
4616 We actually want to parse the operands to the branch instruction
4617 passed in 'str'. Save the input pointer and restore it later. */
4618 save_in
= input_line_pointer
;
4619 input_line_pointer
= str
;
4621 if (inst
.reloc
.exp
.X_op
== O_symbol
4623 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
4625 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
4626 inst
.reloc
.pc_rel
= 0;
4627 /* Modify str to point to after parsed operands, otherwise
4628 end_of_line() will complain about the (PLT) left in str. */
4629 str
= input_line_pointer
;
4633 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
4634 inst
.reloc
.pc_rel
= 1;
4637 input_line_pointer
= save_in
;
4640 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
4641 inst
.reloc
.pc_rel
= 1;
4642 #endif /* OBJ_ELF */
4647 /* ARM V5 branch-link-exchange instruction (argument parse)
4648 BLX <target_addr> ie BLX(1)
4649 BLX{<condition>} <Rm> ie BLX(2)
4650 Unfortunately, there are two different opcodes for this mnemonic.
4651 So, the insns[].value is not used, and the code here zaps values
4652 into inst.instruction.
4653 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
4661 skip_whitespace (mystr
);
4662 rm
= reg_required_here (& mystr
, 0);
4664 /* The above may set inst.error. Ignore his opinion. */
4669 /* Arg is a register.
4670 Use the condition code our caller put in inst.instruction.
4671 Pass ourselves off as a BX with a funny opcode. */
4672 inst
.instruction
|= 0x012fff30;
4677 /* This must be is BLX <target address>, no condition allowed. */
4678 if (inst
.instruction
!= COND_ALWAYS
)
4680 inst
.error
= BAD_COND
;
4684 inst
.instruction
= 0xfafffffe;
4686 /* Process like a B/BL, but with a different reloc.
4687 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
4692 /* ARM V5 Thumb BLX (argument parse)
4693 BLX <target_addr> which is BLX(1)
4694 BLX <Rm> which is BLX(2)
4695 Unfortunately, there are two different opcodes for this mnemonic.
4696 So, the tinsns[].value is not used, and the code here zaps values
4697 into inst.instruction. */
4700 do_t_blx (char * str
)
4705 skip_whitespace (mystr
);
4706 inst
.instruction
= 0x4780;
4708 /* Note that this call is to the ARM register recognizer. BLX(2)
4709 uses the ARM register space, not the Thumb one, so a call to
4710 thumb_reg() would be wrong. */
4711 rm
= reg_required_here (& mystr
, 3);
4716 /* It's BLX(2). The .instruction was zapped with rm & is final. */
4721 /* No ARM register. This must be BLX(1). Change the .instruction. */
4722 inst
.instruction
= 0xf7ffeffe;
4725 if (my_get_expression (& inst
.reloc
.exp
, & mystr
))
4728 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BLX
;
4729 inst
.reloc
.pc_rel
= 1;
4732 end_of_line (mystr
);
4735 /* ARM V5 breakpoint instruction (argument parse)
4736 BKPT <16 bit unsigned immediate>
4737 Instruction is not conditional.
4738 The bit pattern given in insns[] has the COND_ALWAYS condition,
4739 and it is an error if the caller tried to override that. */
4742 do_bkpt (char * str
)
4745 unsigned long number
;
4747 skip_whitespace (str
);
4749 /* Allow optional leading '#'. */
4750 if (is_immediate_prefix (* str
))
4753 memset (& expr
, '\0', sizeof (expr
));
4755 if (my_get_expression (& expr
, & str
)
4756 || (expr
.X_op
!= O_constant
4757 /* As a convenience we allow 'bkpt' without an operand. */
4758 && expr
.X_op
!= O_absent
))
4760 inst
.error
= _("bad expression");
4764 number
= expr
.X_add_number
;
4766 /* Check it fits a 16 bit unsigned. */
4767 if (number
!= (number
& 0xffff))
4769 inst
.error
= _("immediate value out of range");
4773 /* Top 12 of 16 bits to bits 19:8. */
4774 inst
.instruction
|= (number
& 0xfff0) << 4;
4776 /* Bottom 4 of 16 bits to bits 3:0. */
4777 inst
.instruction
|= number
& 0xf;
4782 /* THUMB CPS instruction (argument parse). */
4785 do_t_cps (char * str
)
4787 do_cps_flags (&str
, /*thumb_p=*/1);
4791 /* Parse and validate that a register is of the right form, this saves
4792 repeated checking of this information in many similar cases.
4793 Unlike the 32-bit case we do not insert the register into the opcode
4794 here, since the position is often unknown until the full instruction
4798 thumb_reg (char ** strp
, int hi_lo
)
4802 if ((reg
= reg_required_here (strp
, -1)) == FAIL
)
4810 inst
.error
= _("lo register required");
4818 inst
.error
= _("hi register required");
4831 thumb_mov_compare (char * str
, int move
)
4835 skip_whitespace (str
);
4837 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
4838 || skip_past_comma (&str
) == FAIL
)
4841 inst
.error
= BAD_ARGS
;
4845 if (move
!= THUMB_CPY
&& is_immediate_prefix (*str
))
4848 if (my_get_expression (&inst
.reloc
.exp
, &str
))
4851 else if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
4856 if (move
!= THUMB_CPY
&& Rs
< 8 && Rd
< 8)
4858 if (move
== THUMB_MOVE
)
4859 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
4860 since a MOV instruction produces unpredictable results. */
4861 inst
.instruction
= T_OPCODE_ADD_I3
;
4863 inst
.instruction
= T_OPCODE_CMP_LR
;
4864 inst
.instruction
|= Rd
| (Rs
<< 3);
4868 if (move
== THUMB_MOVE
)
4869 inst
.instruction
= T_OPCODE_MOV_HR
;
4870 else if (move
!= THUMB_CPY
)
4871 inst
.instruction
= T_OPCODE_CMP_HR
;
4874 inst
.instruction
|= THUMB_H1
;
4877 inst
.instruction
|= THUMB_H2
;
4879 inst
.instruction
|= (Rd
& 7) | ((Rs
& 7) << 3);
4886 inst
.error
= _("only lo regs allowed with immediate");
4890 if (move
== THUMB_MOVE
)
4891 inst
.instruction
= T_OPCODE_MOV_I8
;
4893 inst
.instruction
= T_OPCODE_CMP_I8
;
4895 inst
.instruction
|= Rd
<< 8;
4897 if (inst
.reloc
.exp
.X_op
!= O_constant
)
4898 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_IMM
;
4901 unsigned value
= inst
.reloc
.exp
.X_add_number
;
4905 inst
.error
= _("invalid immediate");
4909 inst
.instruction
|= value
;
4916 /* THUMB CPY instruction (argument parse). */
4919 do_t_cpy (char * str
)
4921 thumb_mov_compare (str
, THUMB_CPY
);
4924 /* THUMB SETEND instruction (argument parse). */
4927 do_t_setend (char * str
)
4929 if (do_endian_specifier (str
))
4930 inst
.instruction
|= 0x8;
4933 /* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
4935 static unsigned long
4936 check_iwmmxt_insn (char * str
,
4937 enum iwmmxt_insn_type insn_type
,
4941 const char * inst_error
;
4943 unsigned long number
;
4945 inst_error
= inst
.error
;
4947 inst
.error
= BAD_ARGS
;
4948 skip_whitespace (str
);
4953 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
4958 if ((wreg_required_here (&str
, 0, IWMMXT_REG_WR
)) == FAIL
)
4963 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
4964 || skip_past_comma (&str
) == FAIL
4965 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
))
4970 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
4971 || skip_past_comma (&str
) == FAIL
4972 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4973 || skip_past_comma (&str
) == FAIL
4974 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
))
4979 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
4980 || skip_past_comma (&str
) == FAIL
4981 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4982 || skip_past_comma (&str
) == FAIL
4983 || wreg_required_here (&str
, 0, IWMMXT_REG_WCG
) == FAIL
))
4988 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4989 || skip_past_comma (&str
) == FAIL
4990 || reg_required_here (&str
, 12) == FAIL
))
4995 if ((reg_required_here (&str
, 12) == FAIL
4996 || skip_past_comma (&str
) == FAIL
4997 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
))
5002 if ((wreg_required_here (&str
, 5, IWMMXT_REG_WR
) == FAIL
5003 || skip_past_comma (&str
) == FAIL
5004 || reg_required_here (&str
, 0) == FAIL
5005 || skip_past_comma (&str
) == FAIL
5006 || reg_required_here (&str
, 12) == FAIL
))
5011 if ((wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
5012 || skip_past_comma (&str
) == FAIL
5013 || reg_required_here (&str
, 12) == FAIL
5014 || skip_past_comma (&str
) == FAIL
5015 || reg_required_here (&str
, 16) == FAIL
))
5020 if ((reg_required_here (&str
, 12) == FAIL
5021 || skip_past_comma (&str
) == FAIL
5022 || reg_required_here (&str
, 16) == FAIL
5023 || skip_past_comma (&str
) == FAIL
5024 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
))
5029 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WC
) == FAIL
5030 || skip_past_comma (&str
) == FAIL
5031 || reg_required_here (&str
, 12) == FAIL
))
5036 if ((reg_required_here (&str
, 12) == FAIL
5037 || skip_past_comma (&str
) == FAIL
5038 || wreg_required_here (&str
, 16, IWMMXT_REG_WC
) == FAIL
))
5043 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5044 || skip_past_comma (&str
) == FAIL
5045 || reg_required_here (&str
, 12) == FAIL
5046 || skip_past_comma (&str
) == FAIL
))
5051 if ((reg_required_here (&str
, 12) == FAIL
5052 || skip_past_comma (&str
) == FAIL
))
5057 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
5058 || skip_past_comma (&str
) == FAIL
5059 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5060 || skip_past_comma (&str
) == FAIL
5061 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
5062 || skip_past_comma (&str
) == FAIL
))
5067 if ((reg_required_here (&str
, 12) == FAIL
5068 || skip_past_comma (&str
) == FAIL
5069 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5070 || skip_past_comma (&str
) == FAIL
))
5075 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
5076 || skip_past_comma (&str
) == FAIL
5077 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5078 || skip_past_comma (&str
) == FAIL
))
5083 if (immediate_size
== 0)
5086 inst
.error
= inst_error
;
5091 skip_whitespace (str
);
5093 /* Allow optional leading '#'. */
5094 if (is_immediate_prefix (* str
))
5097 memset (& expr
, '\0', sizeof (expr
));
5099 if (my_get_expression (& expr
, & str
) || (expr
.X_op
!= O_constant
))
5101 inst
.error
= _("bad or missing expression");
5105 number
= expr
.X_add_number
;
5107 if (number
!= (number
& immediate_size
))
5109 inst
.error
= _("immediate value out of range");
5113 inst
.error
= inst_error
;
5119 do_iwmmxt_byte_addr (char * str
)
5121 int op
= (inst
.instruction
& 0x300) >> 8;
5124 inst
.instruction
&= ~0x300;
5125 inst
.instruction
|= (op
& 1) << 22 | (op
& 2) << 7;
5127 skip_whitespace (str
);
5129 if ((reg
= wreg_required_here (&str
, 12, IWMMXT_REG_WR_OR_WC
)) == FAIL
5130 || skip_past_comma (& str
) == FAIL
5131 || cp_byte_address_required_here (&str
) == FAIL
)
5134 inst
.error
= BAD_ARGS
;
5139 if (wc_register (reg
))
5141 as_bad (_("non-word size not supported with control register"));
5142 inst
.instruction
|= 0xf0000100;
5143 inst
.instruction
&= ~0x00400000;
5148 do_iwmmxt_tandc (char * str
)
5152 reg
= check_iwmmxt_insn (str
, check_rd
, 0);
5154 if (reg
!= REG_PC
&& !inst
.error
)
5155 inst
.error
= _("only r15 allowed here");
5159 do_iwmmxt_tbcst (char * str
)
5161 check_iwmmxt_insn (str
, check_tbcst
, 0);
5165 do_iwmmxt_textrc (char * str
)
5167 unsigned long number
;
5169 if ((number
= check_iwmmxt_insn (str
, check_textrc
, 7)) == (unsigned long) FAIL
)
5172 inst
.instruction
|= number
& 0x7;
5176 do_iwmmxt_textrm (char * str
)
5178 unsigned long number
;
5180 if ((number
= check_iwmmxt_insn (str
, check_textrm
, 7)) == (unsigned long) FAIL
)
5183 inst
.instruction
|= number
& 0x7;
5187 do_iwmmxt_tinsr (char * str
)
5189 unsigned long number
;
5191 if ((number
= check_iwmmxt_insn (str
, check_tinsr
, 7)) == (unsigned long) FAIL
)
5194 inst
.instruction
|= number
& 0x7;
5198 do_iwmmxt_tmcr (char * str
)
5200 check_iwmmxt_insn (str
, check_tmcr
, 0);
5204 do_iwmmxt_tmcrr (char * str
)
5206 check_iwmmxt_insn (str
, check_tmcrr
, 0);
5210 do_iwmmxt_tmia (char * str
)
5212 check_iwmmxt_insn (str
, check_tmia
, 0);
5216 do_iwmmxt_tmovmsk (char * str
)
5218 check_iwmmxt_insn (str
, check_tmovmsk
, 0);
5222 do_iwmmxt_tmrc (char * str
)
5224 check_iwmmxt_insn (str
, check_tmrc
, 0);
5228 do_iwmmxt_tmrrc (char * str
)
5230 check_iwmmxt_insn (str
, check_tmrrc
, 0);
5234 do_iwmmxt_torc (char * str
)
5236 check_iwmmxt_insn (str
, check_rd
, 0);
5240 do_iwmmxt_waligni (char * str
)
5242 unsigned long number
;
5244 if ((number
= check_iwmmxt_insn (str
, check_waligni
, 7)) == (unsigned long) FAIL
)
5247 inst
.instruction
|= ((number
& 0x7) << 20);
5251 do_iwmmxt_wmov (char * str
)
5253 if (check_iwmmxt_insn (str
, check_wrwr
, 0) == (unsigned long) FAIL
)
5256 inst
.instruction
|= ((inst
.instruction
>> 16) & 0xf);
5260 do_iwmmxt_word_addr (char * str
)
5262 int op
= (inst
.instruction
& 0x300) >> 8;
5265 inst
.instruction
&= ~0x300;
5266 inst
.instruction
|= (op
& 1) << 22 | (op
& 2) << 7;
5268 skip_whitespace (str
);
5270 if ((reg
= wreg_required_here (&str
, 12, IWMMXT_REG_WR_OR_WC
)) == FAIL
5271 || skip_past_comma (& str
) == FAIL
5272 || cp_address_required_here (& str
, CP_WB_OK
) == FAIL
)
5275 inst
.error
= BAD_ARGS
;
5280 if (wc_register (reg
))
5282 if ((inst
.instruction
& COND_MASK
) != COND_ALWAYS
)
5283 as_bad (_("conditional execution not supported with control register"));
5285 as_bad (_("non-word size not supported with control register"));
5286 inst
.instruction
|= 0xf0000100;
5287 inst
.instruction
&= ~0x00400000;
5292 do_iwmmxt_wrwr (char * str
)
5294 check_iwmmxt_insn (str
, check_wrwr
, 0);
5298 do_iwmmxt_wrwrwcg (char * str
)
5300 check_iwmmxt_insn (str
, check_wrwrwcg
, 0);
5304 do_iwmmxt_wrwrwr (char * str
)
5306 check_iwmmxt_insn (str
, check_wrwrwr
, 0);
5310 do_iwmmxt_wshufh (char * str
)
5312 unsigned long number
;
5314 if ((number
= check_iwmmxt_insn (str
, check_wshufh
, 0xff)) == (unsigned long) FAIL
)
5317 inst
.instruction
|= ((number
& 0xf0) << 16) | (number
& 0xf);
5321 do_iwmmxt_wzero (char * str
)
5323 if (check_iwmmxt_insn (str
, check_wr
, 0) == (unsigned long) FAIL
)
5326 inst
.instruction
|= ((inst
.instruction
& 0xf) << 12) | ((inst
.instruction
& 0xf) << 16);
5329 /* Xscale multiply-accumulate (argument parse)
5332 MIAxycc acc0,Rm,Rs. */
5335 do_xsc_mia (char * str
)
5340 if (accum0_required_here (& str
) == FAIL
)
5341 inst
.error
= ERR_NO_ACCUM
;
5343 else if (skip_past_comma (& str
) == FAIL
5344 || (rm
= reg_required_here (& str
, 0)) == FAIL
)
5345 inst
.error
= BAD_ARGS
;
5347 else if (skip_past_comma (& str
) == FAIL
5348 || (rs
= reg_required_here (& str
, 12)) == FAIL
)
5349 inst
.error
= BAD_ARGS
;
5351 /* inst.instruction has now been zapped with both rm and rs. */
5352 else if (rm
== REG_PC
|| rs
== REG_PC
)
5353 inst
.error
= BAD_PC
; /* Undefined result if rm or rs is R15. */
5359 /* Xscale move-accumulator-register (argument parse)
5361 MARcc acc0,RdLo,RdHi. */
5364 do_xsc_mar (char * str
)
5368 if (accum0_required_here (& str
) == FAIL
)
5369 inst
.error
= ERR_NO_ACCUM
;
5371 else if (skip_past_comma (& str
) == FAIL
5372 || (rdlo
= reg_required_here (& str
, 12)) == FAIL
)
5373 inst
.error
= BAD_ARGS
;
5375 else if (skip_past_comma (& str
) == FAIL
5376 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
5377 inst
.error
= BAD_ARGS
;
5379 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5380 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
5381 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
5387 /* Xscale move-register-accumulator (argument parse)
5389 MRAcc RdLo,RdHi,acc0. */
5392 do_xsc_mra (char * str
)
5397 skip_whitespace (str
);
5399 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
)
5400 inst
.error
= BAD_ARGS
;
5402 else if (skip_past_comma (& str
) == FAIL
5403 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
5404 inst
.error
= BAD_ARGS
;
5406 else if (skip_past_comma (& str
) == FAIL
5407 || accum0_required_here (& str
) == FAIL
)
5408 inst
.error
= ERR_NO_ACCUM
;
5410 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5411 else if (rdlo
== rdhi
)
5412 inst
.error
= BAD_ARGS
; /* Undefined result if 2 writes to same reg. */
5414 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
5415 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
5421 ldst_extend (char ** str
)
5430 if (my_get_expression (& inst
.reloc
.exp
, str
))
5433 if (inst
.reloc
.exp
.X_op
== O_constant
)
5435 int value
= inst
.reloc
.exp
.X_add_number
;
5437 if (value
< -4095 || value
> 4095)
5439 inst
.error
= _("address offset too large");
5449 inst
.instruction
|= add
| value
;
5453 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
5454 inst
.reloc
.pc_rel
= 0;
5467 if (reg_required_here (str
, 0) == FAIL
)
5470 inst
.instruction
|= add
| OFFSET_REG
;
5471 if (skip_past_comma (str
) == SUCCESS
)
5472 return decode_shift (str
, SHIFT_IMMEDIATE
);
5478 /* ARMv5TE: Preload-Cache
5482 Syntactically, like LDR with B=1, W=0, L=1. */
5489 skip_whitespace (str
);
5493 inst
.error
= _("'[' expected after PLD mnemonic");
5498 skip_whitespace (str
);
5500 if ((rd
= reg_required_here (& str
, 16)) == FAIL
)
5503 skip_whitespace (str
);
5509 skip_whitespace (str
);
5511 /* Post-indexed addressing is not allowed with PLD. */
5512 if (skip_past_comma (&str
) == SUCCESS
)
5515 = _("post-indexed expression used in preload instruction");
5518 else if (*str
== '!') /* [Rn]! */
5520 inst
.error
= _("writeback used in preload instruction");
5524 inst
.instruction
|= INDEX_UP
| PRE_INDEX
;
5526 else /* [Rn, ...] */
5528 if (skip_past_comma (& str
) == FAIL
)
5530 inst
.error
= _("pre-indexed expression expected");
5534 if (ldst_extend (&str
) == FAIL
)
5537 skip_whitespace (str
);
5541 inst
.error
= _("missing ]");
5546 skip_whitespace (str
);
5548 if (* str
== '!') /* [Rn]! */
5550 inst
.error
= _("writeback used in preload instruction");
5554 inst
.instruction
|= PRE_INDEX
;
5560 /* ARMv5TE load-consecutive (argument parse)
5567 do_ldrd (char * str
)
5572 skip_whitespace (str
);
5574 if ((rd
= reg_required_here (& str
, 12)) == FAIL
)
5576 inst
.error
= BAD_ARGS
;
5580 if (skip_past_comma (& str
) == FAIL
5581 || (rn
= ld_mode_required_here (& str
)) == FAIL
)
5584 inst
.error
= BAD_ARGS
;
5588 /* inst.instruction has now been zapped with Rd and the addressing mode. */
5589 if (rd
& 1) /* Unpredictable result if Rd is odd. */
5591 inst
.error
= _("destination register must be even");
5597 inst
.error
= _("r14 not allowed here");
5601 if (((rd
== rn
) || (rd
+ 1 == rn
))
5602 && ((inst
.instruction
& WRITE_BACK
)
5603 || (!(inst
.instruction
& PRE_INDEX
))))
5604 as_warn (_("pre/post-indexing used when modified address register is destination"));
5606 /* For an index-register load, the index register must not overlap the
5607 destination (even if not write-back). */
5608 if ((inst
.instruction
& V4_STR_BIT
) == 0
5609 && (inst
.instruction
& HWOFFSET_IMM
) == 0)
5611 int rm
= inst
.instruction
& 0x0000000f;
5613 if (rm
== rd
|| (rm
== rd
+ 1))
5614 as_warn (_("ldrd destination registers must not overlap index register"));
5620 /* Returns the index into fp_values of a floating point number,
5621 or -1 if not in the table. */
5624 my_get_float_expression (char ** str
)
5626 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
5632 memset (words
, 0, MAX_LITTLENUMS
* sizeof (LITTLENUM_TYPE
));
5634 /* Look for a raw floating point number. */
5635 if ((save_in
= atof_ieee (*str
, 'x', words
)) != NULL
5636 && is_end_of_line
[(unsigned char) *save_in
])
5638 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
5640 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
5642 if (words
[j
] != fp_values
[i
][j
])
5646 if (j
== MAX_LITTLENUMS
)
5654 /* Try and parse a more complex expression, this will probably fail
5655 unless the code uses a floating point prefix (eg "0f"). */
5656 save_in
= input_line_pointer
;
5657 input_line_pointer
= *str
;
5658 if (expression (&exp
) == absolute_section
5659 && exp
.X_op
== O_big
5660 && exp
.X_add_number
< 0)
5662 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
5664 if (gen_to_words (words
, 5, (long) 15) == 0)
5666 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
5668 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
5670 if (words
[j
] != fp_values
[i
][j
])
5674 if (j
== MAX_LITTLENUMS
)
5676 *str
= input_line_pointer
;
5677 input_line_pointer
= save_in
;
5684 *str
= input_line_pointer
;
5685 input_line_pointer
= save_in
;
5689 /* We handle all bad expressions here, so that we can report the faulty
5690 instruction in the error message. */
5692 md_operand (expressionS
* expr
)
5694 if (in_my_get_expression
)
5696 expr
->X_op
= O_illegal
;
5697 if (inst
.error
== NULL
)
5698 inst
.error
= _("bad expression");
5702 /* Do those data_ops which can take a negative immediate constant
5703 by altering the instruction. A bit of a hack really.
5707 by inverting the second operand, and
5710 by negating the second operand. */
5713 negate_data_op (unsigned long * instruction
,
5714 unsigned long value
)
5717 unsigned long negated
, inverted
;
5719 negated
= validate_immediate (-value
);
5720 inverted
= validate_immediate (~value
);
5722 op
= (*instruction
>> DATA_OP_SHIFT
) & 0xf;
5725 /* First negates. */
5726 case OPCODE_SUB
: /* ADD <-> SUB */
5727 new_inst
= OPCODE_ADD
;
5732 new_inst
= OPCODE_SUB
;
5736 case OPCODE_CMP
: /* CMP <-> CMN */
5737 new_inst
= OPCODE_CMN
;
5742 new_inst
= OPCODE_CMP
;
5746 /* Now Inverted ops. */
5747 case OPCODE_MOV
: /* MOV <-> MVN */
5748 new_inst
= OPCODE_MVN
;
5753 new_inst
= OPCODE_MOV
;
5757 case OPCODE_AND
: /* AND <-> BIC */
5758 new_inst
= OPCODE_BIC
;
5763 new_inst
= OPCODE_AND
;
5767 case OPCODE_ADC
: /* ADC <-> SBC */
5768 new_inst
= OPCODE_SBC
;
5773 new_inst
= OPCODE_ADC
;
5777 /* We cannot do anything. */
5782 if (value
== (unsigned) FAIL
)
5785 *instruction
&= OPCODE_MASK
;
5786 *instruction
|= new_inst
<< DATA_OP_SHIFT
;
5791 data_op2 (char ** str
)
5796 skip_whitespace (* str
);
5798 if (reg_required_here (str
, 0) != FAIL
)
5800 if (skip_past_comma (str
) == SUCCESS
)
5801 /* Shift operation on register. */
5802 return decode_shift (str
, NO_SHIFT_RESTRICT
);
5808 /* Immediate expression. */
5809 if (is_immediate_prefix (**str
))
5814 if (my_get_expression (&inst
.reloc
.exp
, str
))
5817 if (inst
.reloc
.exp
.X_add_symbol
)
5819 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
5820 inst
.reloc
.pc_rel
= 0;
5824 if (skip_past_comma (str
) == SUCCESS
)
5826 /* #x, y -- ie explicit rotation by Y. */
5827 if (my_get_expression (&expr
, str
))
5830 if (expr
.X_op
!= O_constant
)
5832 inst
.error
= _("constant expression expected");
5836 /* Rotate must be a multiple of 2. */
5837 if (((unsigned) expr
.X_add_number
) > 30
5838 || (expr
.X_add_number
& 1) != 0
5839 || ((unsigned) inst
.reloc
.exp
.X_add_number
) > 255)
5841 inst
.error
= _("invalid constant");
5844 inst
.instruction
|= INST_IMMEDIATE
;
5845 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
5846 inst
.instruction
|= expr
.X_add_number
<< 7;
5850 /* Implicit rotation, select a suitable one. */
5851 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
5855 /* Can't be done. Perhaps the code reads something like
5856 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
5857 if ((value
= negate_data_op (&inst
.instruction
,
5858 inst
.reloc
.exp
.X_add_number
))
5861 inst
.error
= _("invalid constant");
5866 inst
.instruction
|= value
;
5869 inst
.instruction
|= INST_IMMEDIATE
;
5874 inst
.error
= _("register or shift expression expected");
5880 fp_op2 (char ** str
)
5882 skip_whitespace (* str
);
5884 if (fp_reg_required_here (str
, 0) != FAIL
)
5888 /* Immediate expression. */
5889 if (*((*str
)++) == '#')
5895 skip_whitespace (* str
);
5897 /* First try and match exact strings, this is to guarantee
5898 that some formats will work even for cross assembly. */
5900 for (i
= 0; fp_const
[i
]; i
++)
5902 if (strncmp (*str
, fp_const
[i
], strlen (fp_const
[i
])) == 0)
5906 *str
+= strlen (fp_const
[i
]);
5907 if (is_end_of_line
[(unsigned char) **str
])
5909 inst
.instruction
|= i
+ 8;
5916 /* Just because we didn't get a match doesn't mean that the
5917 constant isn't valid, just that it is in a format that we
5918 don't automatically recognize. Try parsing it with
5919 the standard expression routines. */
5920 if ((i
= my_get_float_expression (str
)) >= 0)
5922 inst
.instruction
|= i
+ 8;
5926 inst
.error
= _("invalid floating point immediate expression");
5930 _("floating point register or immediate expression expected");
5936 do_arit (char * str
)
5938 skip_whitespace (str
);
5940 if (reg_required_here (&str
, 12) == FAIL
5941 || skip_past_comma (&str
) == FAIL
5942 || reg_required_here (&str
, 16) == FAIL
5943 || skip_past_comma (&str
) == FAIL
5944 || data_op2 (&str
) == FAIL
)
5947 inst
.error
= BAD_ARGS
;
5957 /* This is a pseudo-op of the form "adr rd, label" to be converted
5958 into a relative address of the form "add rd, pc, #label-.-8". */
5959 skip_whitespace (str
);
5961 if (reg_required_here (&str
, 12) == FAIL
5962 || skip_past_comma (&str
) == FAIL
5963 || my_get_expression (&inst
.reloc
.exp
, &str
))
5966 inst
.error
= BAD_ARGS
;
5970 /* Frag hacking will turn this into a sub instruction if the offset turns
5971 out to be negative. */
5972 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
5974 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust. */
5976 inst
.reloc
.pc_rel
= 1;
5982 do_adrl (char * str
)
5984 /* This is a pseudo-op of the form "adrl rd, label" to be converted
5985 into a relative address of the form:
5986 add rd, pc, #low(label-.-8)"
5987 add rd, rd, #high(label-.-8)" */
5989 skip_whitespace (str
);
5991 if (reg_required_here (&str
, 12) == FAIL
5992 || skip_past_comma (&str
) == FAIL
5993 || my_get_expression (&inst
.reloc
.exp
, &str
))
5996 inst
.error
= BAD_ARGS
;
6002 /* Frag hacking will turn this into a sub instruction if the offset turns
6003 out to be negative. */
6004 inst
.reloc
.type
= BFD_RELOC_ARM_ADRL_IMMEDIATE
;
6006 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust */
6008 inst
.reloc
.pc_rel
= 1;
6009 inst
.size
= INSN_SIZE
* 2;
6015 skip_whitespace (str
);
6017 if (reg_required_here (&str
, 16) == FAIL
)
6020 inst
.error
= BAD_ARGS
;
6024 if (skip_past_comma (&str
) == FAIL
6025 || data_op2 (&str
) == FAIL
)
6028 inst
.error
= BAD_ARGS
;
6038 skip_whitespace (str
);
6040 if (reg_required_here (&str
, 12) == FAIL
)
6043 inst
.error
= BAD_ARGS
;
6047 if (skip_past_comma (&str
) == FAIL
6048 || data_op2 (&str
) == FAIL
)
6051 inst
.error
= BAD_ARGS
;
6059 do_ldst (char * str
)
6065 skip_whitespace (str
);
6067 if ((conflict_reg
= reg_required_here (&str
, 12)) == FAIL
)
6070 inst
.error
= BAD_ARGS
;
6074 if (skip_past_comma (&str
) == FAIL
)
6076 inst
.error
= _("address expected");
6086 skip_whitespace (str
);
6088 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6091 /* Conflicts can occur on stores as well as loads. */
6092 conflict_reg
= (conflict_reg
== reg
);
6094 skip_whitespace (str
);
6100 if (skip_past_comma (&str
) == SUCCESS
)
6102 /* [Rn],... (post inc) */
6103 if (ldst_extend (&str
) == FAIL
)
6106 as_warn (_("%s register same as write-back base"),
6107 ((inst
.instruction
& LOAD_BIT
)
6108 ? _("destination") : _("source")));
6113 skip_whitespace (str
);
6118 as_warn (_("%s register same as write-back base"),
6119 ((inst
.instruction
& LOAD_BIT
)
6120 ? _("destination") : _("source")));
6122 inst
.instruction
|= WRITE_BACK
;
6125 inst
.instruction
|= INDEX_UP
;
6132 if (skip_past_comma (&str
) == FAIL
)
6134 inst
.error
= _("pre-indexed expression expected");
6139 if (ldst_extend (&str
) == FAIL
)
6142 skip_whitespace (str
);
6146 inst
.error
= _("missing ]");
6150 skip_whitespace (str
);
6155 as_warn (_("%s register same as write-back base"),
6156 ((inst
.instruction
& LOAD_BIT
)
6157 ? _("destination") : _("source")));
6159 inst
.instruction
|= WRITE_BACK
;
6163 else if (*str
== '=')
6165 if ((inst
.instruction
& LOAD_BIT
) == 0)
6167 inst
.error
= _("invalid pseudo operation");
6171 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6174 skip_whitespace (str
);
6176 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6179 if (inst
.reloc
.exp
.X_op
!= O_constant
6180 && inst
.reloc
.exp
.X_op
!= O_symbol
)
6182 inst
.error
= _("constant expression expected");
6186 if (inst
.reloc
.exp
.X_op
== O_constant
)
6188 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
6192 /* This can be done with a mov instruction. */
6193 inst
.instruction
&= LITERAL_MASK
;
6194 inst
.instruction
|= (INST_IMMEDIATE
6195 | (OPCODE_MOV
<< DATA_OP_SHIFT
));
6196 inst
.instruction
|= value
& 0xfff;
6201 value
= validate_immediate (~inst
.reloc
.exp
.X_add_number
);
6205 /* This can be done with a mvn instruction. */
6206 inst
.instruction
&= LITERAL_MASK
;
6207 inst
.instruction
|= (INST_IMMEDIATE
6208 | (OPCODE_MVN
<< DATA_OP_SHIFT
));
6209 inst
.instruction
|= value
& 0xfff;
6215 /* Insert into literal pool. */
6216 if (add_to_lit_pool () == FAIL
)
6219 inst
.error
= _("literal pool insertion failed");
6223 /* Change the instruction exp to point to the pool. */
6224 inst
.reloc
.type
= BFD_RELOC_ARM_LITERAL
;
6225 inst
.reloc
.pc_rel
= 1;
6226 inst
.instruction
|= (REG_PC
<< 16);
6231 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6234 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
6236 /* PC rel adjust. */
6237 inst
.reloc
.exp
.X_add_number
-= 8;
6239 inst
.reloc
.pc_rel
= 1;
6240 inst
.instruction
|= (REG_PC
<< 16);
6244 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
6249 do_ldstt (char * str
)
6253 skip_whitespace (str
);
6255 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
6258 inst
.error
= BAD_ARGS
;
6262 if (skip_past_comma (& str
) == FAIL
)
6264 inst
.error
= _("address expected");
6274 skip_whitespace (str
);
6276 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6279 /* ldrt/strt always use post-indexed addressing, so if the base is
6280 the same as Rd, we warn. */
6281 if (conflict_reg
== reg
)
6282 as_warn (_("%s register same as write-back base"),
6283 ((inst
.instruction
& LOAD_BIT
)
6284 ? _("destination") : _("source")));
6286 skip_whitespace (str
);
6292 if (skip_past_comma (&str
) == SUCCESS
)
6294 /* [Rn],... (post inc) */
6295 if (ldst_extend (&str
) == FAIL
)
6301 skip_whitespace (str
);
6303 /* Skip a write-back '!'. */
6307 inst
.instruction
|= INDEX_UP
;
6312 inst
.error
= _("post-indexed expression expected");
6318 inst
.error
= _("post-indexed expression expected");
6325 /* Halfword and signed-byte load/store operations. */
6328 do_ldstv4 (char * str
)
6334 skip_whitespace (str
);
6336 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
6339 inst
.error
= BAD_ARGS
;
6343 if (skip_past_comma (& str
) == FAIL
)
6345 inst
.error
= _("address expected");
6355 skip_whitespace (str
);
6357 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6360 /* Conflicts can occur on stores as well as loads. */
6361 conflict_reg
= (conflict_reg
== reg
);
6363 skip_whitespace (str
);
6369 if (skip_past_comma (&str
) == SUCCESS
)
6371 /* [Rn],... (post inc) */
6372 if (ldst_extend_v4 (&str
) == FAIL
)
6375 as_warn (_("%s register same as write-back base"),
6376 ((inst
.instruction
& LOAD_BIT
)
6377 ? _("destination") : _("source")));
6382 inst
.instruction
|= HWOFFSET_IMM
;
6384 skip_whitespace (str
);
6389 as_warn (_("%s register same as write-back base"),
6390 ((inst
.instruction
& LOAD_BIT
)
6391 ? _("destination") : _("source")));
6393 inst
.instruction
|= WRITE_BACK
;
6396 inst
.instruction
|= INDEX_UP
;
6403 if (skip_past_comma (&str
) == FAIL
)
6405 inst
.error
= _("pre-indexed expression expected");
6410 if (ldst_extend_v4 (&str
) == FAIL
)
6413 skip_whitespace (str
);
6417 inst
.error
= _("missing ]");
6421 skip_whitespace (str
);
6426 as_warn (_("%s register same as write-back base"),
6427 ((inst
.instruction
& LOAD_BIT
)
6428 ? _("destination") : _("source")));
6430 inst
.instruction
|= WRITE_BACK
;
6434 else if (*str
== '=')
6436 if ((inst
.instruction
& LOAD_BIT
) == 0)
6438 inst
.error
= _("invalid pseudo operation");
6442 /* XXX Does this work correctly for half-word/byte ops? */
6443 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6446 skip_whitespace (str
);
6448 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6451 if (inst
.reloc
.exp
.X_op
!= O_constant
6452 && inst
.reloc
.exp
.X_op
!= O_symbol
)
6454 inst
.error
= _("constant expression expected");
6458 if (inst
.reloc
.exp
.X_op
== O_constant
)
6460 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
6464 /* This can be done with a mov instruction. */
6465 inst
.instruction
&= LITERAL_MASK
;
6466 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MOV
<< DATA_OP_SHIFT
);
6467 inst
.instruction
|= value
& 0xfff;
6472 value
= validate_immediate (~ inst
.reloc
.exp
.X_add_number
);
6476 /* This can be done with a mvn instruction. */
6477 inst
.instruction
&= LITERAL_MASK
;
6478 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MVN
<< DATA_OP_SHIFT
);
6479 inst
.instruction
|= value
& 0xfff;
6485 /* Insert into literal pool. */
6486 if (add_to_lit_pool () == FAIL
)
6489 inst
.error
= _("literal pool insertion failed");
6493 /* Change the instruction exp to point to the pool. */
6494 inst
.instruction
|= HWOFFSET_IMM
;
6495 inst
.reloc
.type
= BFD_RELOC_ARM_HWLITERAL
;
6496 inst
.reloc
.pc_rel
= 1;
6497 inst
.instruction
|= (REG_PC
<< 16);
6502 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6505 inst
.instruction
|= HWOFFSET_IMM
;
6506 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
6508 /* PC rel adjust. */
6509 inst
.reloc
.exp
.X_add_number
-= 8;
6511 inst
.reloc
.pc_rel
= 1;
6512 inst
.instruction
|= (REG_PC
<< 16);
6516 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
6521 reg_list (char ** strp
)
6523 char * str
= * strp
;
6527 /* We come back here if we get ranges concatenated by '+' or '|'. */
6542 skip_whitespace (str
);
6544 if ((reg
= reg_required_here (& str
, -1)) == FAIL
)
6553 inst
.error
= _("bad range in register list");
6557 for (i
= cur_reg
+ 1; i
< reg
; i
++)
6559 if (range
& (1 << i
))
6561 (_("Warning: duplicated register (r%d) in register list"),
6569 if (range
& (1 << reg
))
6570 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
6572 else if (reg
<= cur_reg
)
6573 as_tsktsk (_("Warning: register range not in ascending order"));
6578 while (skip_past_comma (&str
) != FAIL
6579 || (in_range
= 1, *str
++ == '-'));
6581 skip_whitespace (str
);
6585 inst
.error
= _("missing `}'");
6593 if (my_get_expression (&expr
, &str
))
6596 if (expr
.X_op
== O_constant
)
6598 if (expr
.X_add_number
6599 != (expr
.X_add_number
& 0x0000ffff))
6601 inst
.error
= _("invalid register mask");
6605 if ((range
& expr
.X_add_number
) != 0)
6607 int regno
= range
& expr
.X_add_number
;
6610 regno
= (1 << regno
) - 1;
6612 (_("Warning: duplicated register (r%d) in register list"),
6616 range
|= expr
.X_add_number
;
6620 if (inst
.reloc
.type
!= 0)
6622 inst
.error
= _("expression too complex");
6626 memcpy (&inst
.reloc
.exp
, &expr
, sizeof (expressionS
));
6627 inst
.reloc
.type
= BFD_RELOC_ARM_MULTI
;
6628 inst
.reloc
.pc_rel
= 0;
6632 skip_whitespace (str
);
6634 if (*str
== '|' || *str
== '+')
6640 while (another_range
);
6647 do_ldmstm (char * str
)
6652 skip_whitespace (str
);
6654 if ((base_reg
= reg_required_here (&str
, 16)) == FAIL
)
6657 if (base_reg
== REG_PC
)
6659 inst
.error
= _("r15 not allowed as base register");
6663 skip_whitespace (str
);
6667 inst
.instruction
|= WRITE_BACK
;
6671 if (skip_past_comma (&str
) == FAIL
6672 || (range
= reg_list (&str
)) == FAIL
)
6675 inst
.error
= BAD_ARGS
;
6682 inst
.instruction
|= LDM_TYPE_2_OR_3
;
6685 if (inst
.instruction
& WRITE_BACK
)
6687 /* Check for unpredictable uses of writeback. */
6688 if (inst
.instruction
& LOAD_BIT
)
6690 /* Not allowed in LDM type 2. */
6691 if ((inst
.instruction
& LDM_TYPE_2_OR_3
)
6692 && ((range
& (1 << REG_PC
)) == 0))
6693 as_warn (_("writeback of base register is UNPREDICTABLE"));
6694 /* Only allowed if base reg not in list for other types. */
6695 else if (range
& (1 << base_reg
))
6696 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
6700 /* Not allowed for type 2. */
6701 if (inst
.instruction
& LDM_TYPE_2_OR_3
)
6702 as_warn (_("writeback of base register is UNPREDICTABLE"));
6703 /* Only allowed if base reg not in list, or first in list. */
6704 else if ((range
& (1 << base_reg
))
6705 && (range
& ((1 << base_reg
) - 1)))
6706 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
6710 inst
.instruction
|= range
;
6717 skip_whitespace (str
);
6719 /* Allow optional leading '#'. */
6720 if (is_immediate_prefix (*str
))
6723 if (my_get_expression (& inst
.reloc
.exp
, & str
))
6726 inst
.reloc
.type
= BFD_RELOC_ARM_SMI
;
6727 inst
.reloc
.pc_rel
= 0;
6734 skip_whitespace (str
);
6736 /* Allow optional leading '#'. */
6737 if (is_immediate_prefix (*str
))
6740 if (my_get_expression (& inst
.reloc
.exp
, & str
))
6743 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
6744 inst
.reloc
.pc_rel
= 0;
6749 do_swap (char * str
)
6753 skip_whitespace (str
);
6755 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
6760 inst
.error
= _("r15 not allowed in swap");
6764 if (skip_past_comma (&str
) == FAIL
6765 || (reg
= reg_required_here (&str
, 0)) == FAIL
)
6768 inst
.error
= BAD_ARGS
;
6774 inst
.error
= _("r15 not allowed in swap");
6778 if (skip_past_comma (&str
) == FAIL
6781 inst
.error
= BAD_ARGS
;
6785 skip_whitespace (str
);
6787 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6792 inst
.error
= BAD_PC
;
6796 skip_whitespace (str
);
6800 inst
.error
= _("missing ]");
6808 do_branch (char * str
)
6810 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6817 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
6818 required for the instruction. */
6820 /* arm_parse_reloc () works on input_line_pointer.
6821 We actually want to parse the operands to the branch instruction
6822 passed in 'str'. Save the input pointer and restore it later. */
6823 save_in
= input_line_pointer
;
6824 input_line_pointer
= str
;
6825 if (inst
.reloc
.exp
.X_op
== O_symbol
6827 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
6829 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
6830 inst
.reloc
.pc_rel
= 0;
6831 /* Modify str to point to after parsed operands, otherwise
6832 end_of_line() will complain about the (PLT) left in str. */
6833 str
= input_line_pointer
;
6837 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
6838 inst
.reloc
.pc_rel
= 1;
6840 input_line_pointer
= save_in
;
6843 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
6844 inst
.reloc
.pc_rel
= 1;
6845 #endif /* OBJ_ELF */
6853 /* Co-processor data operation.
6854 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
6855 skip_whitespace (str
);
6857 if (co_proc_number (&str
) == FAIL
)
6860 inst
.error
= BAD_ARGS
;
6864 if (skip_past_comma (&str
) == FAIL
6865 || cp_opc_expr (&str
, 20,4) == FAIL
)
6868 inst
.error
= BAD_ARGS
;
6872 if (skip_past_comma (&str
) == FAIL
6873 || cp_reg_required_here (&str
, 12) == FAIL
)
6876 inst
.error
= BAD_ARGS
;
6880 if (skip_past_comma (&str
) == FAIL
6881 || cp_reg_required_here (&str
, 16) == FAIL
)
6884 inst
.error
= BAD_ARGS
;
6888 if (skip_past_comma (&str
) == FAIL
6889 || cp_reg_required_here (&str
, 0) == FAIL
)
6892 inst
.error
= BAD_ARGS
;
6896 if (skip_past_comma (&str
) == SUCCESS
)
6898 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
6901 inst
.error
= BAD_ARGS
;
6910 do_lstc (char * str
)
6912 /* Co-processor register load/store.
6913 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
6915 skip_whitespace (str
);
6917 if (co_proc_number (&str
) == FAIL
)
6920 inst
.error
= BAD_ARGS
;
6924 if (skip_past_comma (&str
) == FAIL
6925 || cp_reg_required_here (&str
, 12) == FAIL
)
6928 inst
.error
= BAD_ARGS
;
6932 if (skip_past_comma (&str
) == FAIL
6933 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
6936 inst
.error
= BAD_ARGS
;
6944 do_co_reg (char * str
)
6946 /* Co-processor register transfer.
6947 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
6949 skip_whitespace (str
);
6951 if (co_proc_number (&str
) == FAIL
)
6954 inst
.error
= BAD_ARGS
;
6958 if (skip_past_comma (&str
) == FAIL
6959 || cp_opc_expr (&str
, 21, 3) == FAIL
)
6962 inst
.error
= BAD_ARGS
;
6966 if (skip_past_comma (&str
) == FAIL
6967 || reg_required_here (&str
, 12) == FAIL
)
6970 inst
.error
= BAD_ARGS
;
6974 if (skip_past_comma (&str
) == FAIL
6975 || cp_reg_required_here (&str
, 16) == FAIL
)
6978 inst
.error
= BAD_ARGS
;
6982 if (skip_past_comma (&str
) == FAIL
6983 || cp_reg_required_here (&str
, 0) == FAIL
)
6986 inst
.error
= BAD_ARGS
;
6990 if (skip_past_comma (&str
) == SUCCESS
)
6992 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
6995 inst
.error
= BAD_ARGS
;
7004 do_fpa_ctrl (char * str
)
7006 /* FP control registers.
7007 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
7009 skip_whitespace (str
);
7011 if (reg_required_here (&str
, 12) == FAIL
)
7014 inst
.error
= BAD_ARGS
;
7022 do_fpa_ldst (char * str
)
7024 skip_whitespace (str
);
7026 if (fp_reg_required_here (&str
, 12) == FAIL
)
7029 inst
.error
= BAD_ARGS
;
7033 if (skip_past_comma (&str
) == FAIL
7034 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
7037 inst
.error
= BAD_ARGS
;
7045 do_fpa_ldmstm (char * str
)
7049 skip_whitespace (str
);
7051 if (fp_reg_required_here (&str
, 12) == FAIL
)
7054 inst
.error
= BAD_ARGS
;
7058 /* Get Number of registers to transfer. */
7059 if (skip_past_comma (&str
) == FAIL
7060 || my_get_expression (&inst
.reloc
.exp
, &str
))
7063 inst
.error
= _("constant expression expected");
7067 if (inst
.reloc
.exp
.X_op
!= O_constant
)
7069 inst
.error
= _("constant value required for number of registers");
7073 num_regs
= inst
.reloc
.exp
.X_add_number
;
7075 if (num_regs
< 1 || num_regs
> 4)
7077 inst
.error
= _("number of registers must be in the range [1:4]");
7084 inst
.instruction
|= CP_T_X
;
7087 inst
.instruction
|= CP_T_Y
;
7090 inst
.instruction
|= CP_T_Y
| CP_T_X
;
7098 if (inst
.instruction
& (CP_T_Pre
| CP_T_UD
)) /* ea/fd format. */
7104 /* The instruction specified "ea" or "fd", so we can only accept
7105 [Rn]{!}. The instruction does not really support stacking or
7106 unstacking, so we have to emulate these by setting appropriate
7107 bits and offsets. */
7108 if (skip_past_comma (&str
) == FAIL
7112 inst
.error
= BAD_ARGS
;
7117 skip_whitespace (str
);
7119 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
7122 skip_whitespace (str
);
7126 inst
.error
= BAD_ARGS
;
7138 _("r15 not allowed as base register with write-back");
7145 if (inst
.instruction
& CP_T_Pre
)
7147 /* Pre-decrement. */
7148 offset
= 3 * num_regs
;
7150 inst
.instruction
|= CP_T_WB
;
7154 /* Post-increment. */
7157 inst
.instruction
|= CP_T_WB
;
7158 offset
= 3 * num_regs
;
7162 /* No write-back, so convert this into a standard pre-increment
7163 instruction -- aesthetically more pleasing. */
7164 inst
.instruction
|= CP_T_Pre
| CP_T_UD
;
7169 inst
.instruction
|= offset
;
7171 else if (skip_past_comma (&str
) == FAIL
7172 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
7175 inst
.error
= BAD_ARGS
;
7183 do_fpa_dyadic (char * str
)
7185 skip_whitespace (str
);
7187 if (fp_reg_required_here (&str
, 12) == FAIL
)
7190 inst
.error
= BAD_ARGS
;
7194 if (skip_past_comma (&str
) == FAIL
7195 || fp_reg_required_here (&str
, 16) == FAIL
)
7198 inst
.error
= BAD_ARGS
;
7202 if (skip_past_comma (&str
) == FAIL
7203 || fp_op2 (&str
) == FAIL
)
7206 inst
.error
= BAD_ARGS
;
7214 do_fpa_monadic (char * str
)
7216 skip_whitespace (str
);
7218 if (fp_reg_required_here (&str
, 12) == FAIL
)
7221 inst
.error
= BAD_ARGS
;
7225 if (skip_past_comma (&str
) == FAIL
7226 || fp_op2 (&str
) == FAIL
)
7229 inst
.error
= BAD_ARGS
;
7237 do_fpa_cmp (char * str
)
7239 skip_whitespace (str
);
7241 if (fp_reg_required_here (&str
, 16) == FAIL
)
7244 inst
.error
= BAD_ARGS
;
7248 if (skip_past_comma (&str
) == FAIL
7249 || fp_op2 (&str
) == FAIL
)
7252 inst
.error
= BAD_ARGS
;
7260 do_fpa_from_reg (char * str
)
7262 skip_whitespace (str
);
7264 if (fp_reg_required_here (&str
, 16) == FAIL
)
7267 inst
.error
= BAD_ARGS
;
7271 if (skip_past_comma (&str
) == FAIL
7272 || reg_required_here (&str
, 12) == FAIL
)
7275 inst
.error
= BAD_ARGS
;
7283 do_fpa_to_reg (char * str
)
7285 skip_whitespace (str
);
7287 if (reg_required_here (&str
, 12) == FAIL
)
7290 if (skip_past_comma (&str
) == FAIL
7291 || fp_reg_required_here (&str
, 0) == FAIL
)
7294 inst
.error
= BAD_ARGS
;
7301 /* Encode a VFP SP register number. */
7304 vfp_sp_encode_reg (int reg
, enum vfp_sp_reg_pos pos
)
7309 inst
.instruction
|= ((reg
>> 1) << 12) | ((reg
& 1) << 22);
7313 inst
.instruction
|= ((reg
>> 1) << 16) | ((reg
& 1) << 7);
7317 inst
.instruction
|= ((reg
>> 1) << 0) | ((reg
& 1) << 5);
7326 vfp_sp_reg_required_here (char ** str
,
7327 enum vfp_sp_reg_pos pos
)
7330 char * start
= *str
;
7332 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_SN
].htab
)) != FAIL
)
7334 vfp_sp_encode_reg (reg
, pos
);
7338 /* In the few cases where we might be able to accept something else
7339 this error can be overridden. */
7340 inst
.error
= _(all_reg_maps
[REG_TYPE_SN
].expected
);
7342 /* Restore the start point. */
7348 vfp_dp_reg_required_here (char ** str
,
7349 enum vfp_dp_reg_pos pos
)
7352 char * start
= *str
;
7354 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_DN
].htab
)) != FAIL
)
7359 inst
.instruction
|= reg
<< 12;
7363 inst
.instruction
|= reg
<< 16;
7367 inst
.instruction
|= reg
<< 0;
7376 /* In the few cases where we might be able to accept something else
7377 this error can be overridden. */
7378 inst
.error
= _(all_reg_maps
[REG_TYPE_DN
].expected
);
7380 /* Restore the start point. */
7386 do_vfp_sp_monadic (char * str
)
7388 skip_whitespace (str
);
7390 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7393 if (skip_past_comma (&str
) == FAIL
7394 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
7397 inst
.error
= BAD_ARGS
;
7405 do_vfp_dp_monadic (char * str
)
7407 skip_whitespace (str
);
7409 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7412 if (skip_past_comma (&str
) == FAIL
7413 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7416 inst
.error
= BAD_ARGS
;
7424 do_vfp_sp_dyadic (char * str
)
7426 skip_whitespace (str
);
7428 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7431 if (skip_past_comma (&str
) == FAIL
7432 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
7433 || skip_past_comma (&str
) == FAIL
7434 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
7437 inst
.error
= BAD_ARGS
;
7445 do_vfp_dp_dyadic (char * str
)
7447 skip_whitespace (str
);
7449 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7452 if (skip_past_comma (&str
) == FAIL
7453 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
7454 || skip_past_comma (&str
) == FAIL
7455 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7458 inst
.error
= BAD_ARGS
;
7466 do_vfp_reg_from_sp (char * str
)
7468 skip_whitespace (str
);
7470 if (reg_required_here (&str
, 12) == FAIL
)
7473 if (skip_past_comma (&str
) == FAIL
7474 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
7477 inst
.error
= BAD_ARGS
;
7484 /* Parse a VFP register list. If the string is invalid return FAIL.
7485 Otherwise return the number of registers, and set PBASE to the first
7486 register. Double precision registers are matched if DP is nonzero. */
7489 vfp_parse_reg_list (char **str
, int *pbase
, int dp
)
7497 unsigned long mask
= 0;
7504 skip_whitespace (*str
);
7508 regtype
= REG_TYPE_DN
;
7513 regtype
= REG_TYPE_SN
;
7517 base_reg
= max_regs
;
7521 new_base
= arm_reg_parse (str
, all_reg_maps
[regtype
].htab
);
7522 if (new_base
== FAIL
)
7524 inst
.error
= _(all_reg_maps
[regtype
].expected
);
7528 if (new_base
< base_reg
)
7529 base_reg
= new_base
;
7531 if (mask
& (1 << new_base
))
7533 inst
.error
= _("invalid register list");
7537 if ((mask
>> new_base
) != 0 && ! warned
)
7539 as_tsktsk (_("register list not in ascending order"));
7543 mask
|= 1 << new_base
;
7546 skip_whitespace (*str
);
7548 if (**str
== '-') /* We have the start of a range expression */
7555 = arm_reg_parse (str
, all_reg_maps
[regtype
].htab
))
7558 inst
.error
= _(all_reg_maps
[regtype
].expected
);
7562 if (high_range
<= new_base
)
7564 inst
.error
= _("register range not in ascending order");
7568 for (new_base
++; new_base
<= high_range
; new_base
++)
7570 if (mask
& (1 << new_base
))
7572 inst
.error
= _("invalid register list");
7576 mask
|= 1 << new_base
;
7581 while (skip_past_comma (str
) != FAIL
);
7585 /* Sanity check -- should have raised a parse error above. */
7586 if (count
== 0 || count
> max_regs
)
7591 /* Final test -- the registers must be consecutive. */
7593 for (i
= 0; i
< count
; i
++)
7595 if ((mask
& (1u << i
)) == 0)
7597 inst
.error
= _("non-contiguous register range");
7606 do_vfp_reg2_from_sp2 (char * str
)
7610 skip_whitespace (str
);
7612 if (reg_required_here (&str
, 12) == FAIL
7613 || skip_past_comma (&str
) == FAIL
7614 || reg_required_here (&str
, 16) == FAIL
7615 || skip_past_comma (&str
) == FAIL
)
7618 inst
.error
= BAD_ARGS
;
7622 /* We require exactly two consecutive SP registers. */
7623 if (vfp_parse_reg_list (&str
, ®
, 0) != 2)
7626 inst
.error
= _("only two consecutive VFP SP registers allowed here");
7628 vfp_sp_encode_reg (reg
, VFP_REG_Sm
);
7634 do_vfp_sp_from_reg (char * str
)
7636 skip_whitespace (str
);
7638 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
7641 if (skip_past_comma (&str
) == FAIL
7642 || reg_required_here (&str
, 12) == FAIL
)
7645 inst
.error
= BAD_ARGS
;
7653 do_vfp_sp2_from_reg2 (char * str
)
7657 skip_whitespace (str
);
7659 /* We require exactly two consecutive SP registers. */
7660 if (vfp_parse_reg_list (&str
, ®
, 0) != 2)
7663 inst
.error
= _("only two consecutive VFP SP registers allowed here");
7665 vfp_sp_encode_reg (reg
, VFP_REG_Sm
);
7667 if (skip_past_comma (&str
) == FAIL
7668 || reg_required_here (&str
, 12) == FAIL
7669 || skip_past_comma (&str
) == FAIL
7670 || reg_required_here (&str
, 16) == FAIL
)
7673 inst
.error
= BAD_ARGS
;
7681 do_vfp_reg_from_dp (char * str
)
7683 skip_whitespace (str
);
7685 if (reg_required_here (&str
, 12) == FAIL
)
7688 if (skip_past_comma (&str
) == FAIL
7689 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
7692 inst
.error
= BAD_ARGS
;
7700 do_vfp_reg2_from_dp (char * str
)
7702 skip_whitespace (str
);
7704 if (reg_required_here (&str
, 12) == FAIL
)
7707 if (skip_past_comma (&str
) == FAIL
7708 || reg_required_here (&str
, 16) == FAIL
7709 || skip_past_comma (&str
) == FAIL
7710 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7713 inst
.error
= BAD_ARGS
;
7721 do_vfp_dp_from_reg (char * str
)
7723 skip_whitespace (str
);
7725 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
7728 if (skip_past_comma (&str
) == FAIL
7729 || reg_required_here (&str
, 12) == FAIL
)
7732 inst
.error
= BAD_ARGS
;
7740 do_vfp_dp_from_reg2 (char * str
)
7742 skip_whitespace (str
);
7744 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7747 if (skip_past_comma (&str
) == FAIL
7748 || reg_required_here (&str
, 12) == FAIL
7749 || skip_past_comma (&str
) == FAIL
7750 || reg_required_here (&str
, 16) == FAIL
)
7753 inst
.error
= BAD_ARGS
;
7760 static const struct vfp_reg
*
7761 vfp_psr_parse (char ** str
)
7766 const struct vfp_reg
*vreg
;
7770 /* Find the end of the current token. */
7775 while (ISALPHA (c
));
7780 for (vreg
= vfp_regs
+ 0;
7781 vreg
< vfp_regs
+ sizeof (vfp_regs
) / sizeof (struct vfp_reg
);
7784 if (streq (start
, vreg
->name
))
7797 vfp_psr_required_here (char ** str
)
7800 const struct vfp_reg
*vreg
;
7802 vreg
= vfp_psr_parse (str
);
7806 inst
.instruction
|= vreg
->regno
;
7810 inst
.error
= _("VFP system register expected");
7817 do_vfp_reg_from_ctrl (char * str
)
7819 skip_whitespace (str
);
7821 if (reg_required_here (&str
, 12) == FAIL
)
7824 if (skip_past_comma (&str
) == FAIL
7825 || vfp_psr_required_here (&str
) == FAIL
)
7828 inst
.error
= BAD_ARGS
;
7836 do_vfp_ctrl_from_reg (char * str
)
7838 skip_whitespace (str
);
7840 if (vfp_psr_required_here (&str
) == FAIL
)
7843 if (skip_past_comma (&str
) == FAIL
7844 || reg_required_here (&str
, 12) == FAIL
)
7847 inst
.error
= BAD_ARGS
;
7855 do_vfp_sp_ldst (char * str
)
7857 skip_whitespace (str
);
7859 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7862 inst
.error
= BAD_ARGS
;
7866 if (skip_past_comma (&str
) == FAIL
7867 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
7870 inst
.error
= BAD_ARGS
;
7878 do_vfp_dp_ldst (char * str
)
7880 skip_whitespace (str
);
7882 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7885 inst
.error
= BAD_ARGS
;
7889 if (skip_past_comma (&str
) == FAIL
7890 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
7893 inst
.error
= BAD_ARGS
;
7902 vfp_sp_ldstm (char * str
, enum vfp_ldstm_type ldstm_type
)
7907 skip_whitespace (str
);
7909 if (reg_required_here (&str
, 16) == FAIL
)
7912 skip_whitespace (str
);
7916 inst
.instruction
|= WRITE_BACK
;
7919 else if (ldstm_type
!= VFP_LDSTMIA
)
7921 inst
.error
= _("this addressing mode requires base-register writeback");
7925 if (skip_past_comma (&str
) == FAIL
7926 || (count
= vfp_parse_reg_list (&str
, ®
, 0)) == FAIL
)
7929 inst
.error
= BAD_ARGS
;
7932 vfp_sp_encode_reg (reg
, VFP_REG_Sd
);
7934 inst
.instruction
|= count
;
7939 vfp_dp_ldstm (char * str
, enum vfp_ldstm_type ldstm_type
)
7944 skip_whitespace (str
);
7946 if (reg_required_here (&str
, 16) == FAIL
)
7949 skip_whitespace (str
);
7953 inst
.instruction
|= WRITE_BACK
;
7956 else if (ldstm_type
!= VFP_LDSTMIA
&& ldstm_type
!= VFP_LDSTMIAX
)
7958 inst
.error
= _("this addressing mode requires base-register writeback");
7962 if (skip_past_comma (&str
) == FAIL
7963 || (count
= vfp_parse_reg_list (&str
, ®
, 1)) == FAIL
)
7966 inst
.error
= BAD_ARGS
;
7971 if (ldstm_type
== VFP_LDSTMIAX
|| ldstm_type
== VFP_LDSTMDBX
)
7974 inst
.instruction
|= (reg
<< 12) | count
;
7979 do_vfp_sp_ldstmia (char * str
)
7981 vfp_sp_ldstm (str
, VFP_LDSTMIA
);
7985 do_vfp_sp_ldstmdb (char * str
)
7987 vfp_sp_ldstm (str
, VFP_LDSTMDB
);
7991 do_vfp_dp_ldstmia (char * str
)
7993 vfp_dp_ldstm (str
, VFP_LDSTMIA
);
7997 do_vfp_dp_ldstmdb (char * str
)
7999 vfp_dp_ldstm (str
, VFP_LDSTMDB
);
8003 do_vfp_xp_ldstmia (char *str
)
8005 vfp_dp_ldstm (str
, VFP_LDSTMIAX
);
8009 do_vfp_xp_ldstmdb (char * str
)
8011 vfp_dp_ldstm (str
, VFP_LDSTMDBX
);
8015 do_vfp_sp_compare_z (char * str
)
8017 skip_whitespace (str
);
8019 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8022 inst
.error
= BAD_ARGS
;
8030 do_vfp_dp_compare_z (char * str
)
8032 skip_whitespace (str
);
8034 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8037 inst
.error
= BAD_ARGS
;
8045 do_vfp_dp_sp_cvt (char * str
)
8047 skip_whitespace (str
);
8049 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8052 if (skip_past_comma (&str
) == FAIL
8053 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
8056 inst
.error
= BAD_ARGS
;
8064 do_vfp_sp_dp_cvt (char * str
)
8066 skip_whitespace (str
);
8068 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8071 if (skip_past_comma (&str
) == FAIL
8072 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
8075 inst
.error
= BAD_ARGS
;
8082 /* Thumb specific routines. */
8084 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
8088 thumb_add_sub (char * str
, int subtract
)
8090 int Rd
, Rs
, Rn
= FAIL
;
8092 skip_whitespace (str
);
8094 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
8095 || skip_past_comma (&str
) == FAIL
)
8098 inst
.error
= BAD_ARGS
;
8102 if (is_immediate_prefix (*str
))
8106 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8111 if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8114 if (skip_past_comma (&str
) == FAIL
)
8116 /* Two operand format, shuffle the registers
8117 and pretend there are 3. */
8121 else if (is_immediate_prefix (*str
))
8124 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8127 else if ((Rn
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8131 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8132 for the latter case, EXPR contains the immediate that was found. */
8135 /* All register format. */
8136 if (Rd
> 7 || Rs
> 7 || Rn
> 7)
8140 inst
.error
= _("dest and source1 must be the same register");
8144 /* Can't do this for SUB. */
8147 inst
.error
= _("subtract valid only on lo regs");
8151 inst
.instruction
= (T_OPCODE_ADD_HI
8152 | (Rd
> 7 ? THUMB_H1
: 0)
8153 | (Rn
> 7 ? THUMB_H2
: 0));
8154 inst
.instruction
|= (Rd
& 7) | ((Rn
& 7) << 3);
8158 inst
.instruction
= subtract
? T_OPCODE_SUB_R3
: T_OPCODE_ADD_R3
;
8159 inst
.instruction
|= Rd
| (Rs
<< 3) | (Rn
<< 6);
8164 /* Immediate expression, now things start to get nasty. */
8166 /* First deal with HI regs, only very restricted cases allowed:
8167 Adjusting SP, and using PC or SP to get an address. */
8168 if ((Rd
> 7 && (Rd
!= REG_SP
|| Rs
!= REG_SP
))
8169 || (Rs
> 7 && Rs
!= REG_SP
&& Rs
!= REG_PC
))
8171 inst
.error
= _("invalid Hi register with immediate");
8175 if (inst
.reloc
.exp
.X_op
!= O_constant
)
8177 /* Value isn't known yet, all we can do is store all the fragments
8178 we know about in the instruction and let the reloc hacking
8180 inst
.instruction
= (subtract
? 0x8000 : 0) | (Rd
<< 4) | Rs
;
8181 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
8185 int offset
= inst
.reloc
.exp
.X_add_number
;
8195 /* Quick check, in case offset is MIN_INT. */
8198 inst
.error
= _("immediate value out of range");
8202 /* Note - you cannot convert a subtract of 0 into an
8203 add of 0 because the carry flag is set differently. */
8204 else if (offset
> 0)
8209 if (offset
& ~0x1fc)
8211 inst
.error
= _("invalid immediate value for stack adjust");
8214 inst
.instruction
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
8215 inst
.instruction
|= offset
>> 2;
8217 else if (Rs
== REG_PC
|| Rs
== REG_SP
)
8220 || (offset
& ~0x3fc))
8222 inst
.error
= _("invalid immediate for address calculation");
8225 inst
.instruction
= (Rs
== REG_PC
? T_OPCODE_ADD_PC
8227 inst
.instruction
|= (Rd
<< 8) | (offset
>> 2);
8233 inst
.error
= _("immediate value out of range");
8236 inst
.instruction
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
8237 inst
.instruction
|= (Rd
<< 8) | offset
;
8243 inst
.error
= _("immediate value out of range");
8246 inst
.instruction
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
8247 inst
.instruction
|= Rd
| (Rs
<< 3) | (offset
<< 6);
8256 thumb_shift (char * str
, int shift
)
8258 int Rd
, Rs
, Rn
= FAIL
;
8260 skip_whitespace (str
);
8262 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
8263 || skip_past_comma (&str
) == FAIL
)
8266 inst
.error
= BAD_ARGS
;
8270 if (is_immediate_prefix (*str
))
8272 /* Two operand immediate format, set Rs to Rd. */
8275 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8280 if ((Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8283 if (skip_past_comma (&str
) == FAIL
)
8285 /* Two operand format, shuffle the registers
8286 and pretend there are 3. */
8290 else if (is_immediate_prefix (*str
))
8293 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8296 else if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8300 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8301 for the latter case, EXPR contains the immediate that was found. */
8307 inst
.error
= _("source1 and dest must be same register");
8313 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_R
; break;
8314 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_R
; break;
8315 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_R
; break;
8318 inst
.instruction
|= Rd
| (Rn
<< 3);
8324 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_I
; break;
8325 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_I
; break;
8326 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_I
; break;
8329 if (inst
.reloc
.exp
.X_op
!= O_constant
)
8331 /* Value isn't known yet, create a dummy reloc and let reloc
8332 hacking fix it up. */
8333 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_SHIFT
;
8337 unsigned shift_value
= inst
.reloc
.exp
.X_add_number
;
8339 if (shift_value
> 32 || (shift_value
== 32 && shift
== THUMB_LSL
))
8341 inst
.error
= _("invalid immediate for shift");
8345 /* Shifts of zero are handled by converting to LSL. */
8346 if (shift_value
== 0)
8347 inst
.instruction
= T_OPCODE_LSL_I
;
8349 /* Shifts of 32 are encoded as a shift of zero. */
8350 if (shift_value
== 32)
8353 inst
.instruction
|= shift_value
<< 6;
8356 inst
.instruction
|= Rd
| (Rs
<< 3);
8363 thumb_load_store (char * str
, int load_store
, int size
)
8365 int Rd
, Rb
, Ro
= FAIL
;
8367 skip_whitespace (str
);
8369 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
8370 || skip_past_comma (&str
) == FAIL
)
8373 inst
.error
= BAD_ARGS
;
8380 if ((Rb
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8383 if (skip_past_comma (&str
) != FAIL
)
8385 if (is_immediate_prefix (*str
))
8388 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8391 else if ((Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8396 inst
.reloc
.exp
.X_op
= O_constant
;
8397 inst
.reloc
.exp
.X_add_number
= 0;
8402 inst
.error
= _("expected ']'");
8407 else if (*str
== '=')
8409 if (load_store
!= THUMB_LOAD
)
8411 inst
.error
= _("invalid pseudo operation");
8415 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
8418 skip_whitespace (str
);
8420 if (my_get_expression (& inst
.reloc
.exp
, & str
))
8425 if ( inst
.reloc
.exp
.X_op
!= O_constant
8426 && inst
.reloc
.exp
.X_op
!= O_symbol
)
8428 inst
.error
= "Constant expression expected";
8432 if (inst
.reloc
.exp
.X_op
== O_constant
8433 && ((inst
.reloc
.exp
.X_add_number
& ~0xFF) == 0))
8435 /* This can be done with a mov instruction. */
8437 inst
.instruction
= T_OPCODE_MOV_I8
| (Rd
<< 8);
8438 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
8442 /* Insert into literal pool. */
8443 if (add_to_lit_pool () == FAIL
)
8446 inst
.error
= "literal pool insertion failed";
8450 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8451 inst
.reloc
.pc_rel
= 1;
8452 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
8453 /* Adjust ARM pipeline offset to Thumb. */
8454 inst
.reloc
.exp
.X_add_number
+= 4;
8460 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8463 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
8464 inst
.reloc
.pc_rel
= 1;
8465 inst
.reloc
.exp
.X_add_number
-= 4; /* Pipeline offset. */
8466 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8471 if (Rb
== REG_PC
|| Rb
== REG_SP
)
8473 if (size
!= THUMB_WORD
)
8475 inst
.error
= _("byte or halfword not valid for base register");
8478 else if (Rb
== REG_PC
&& load_store
!= THUMB_LOAD
)
8480 inst
.error
= _("r15 based store not allowed");
8483 else if (Ro
!= FAIL
)
8485 inst
.error
= _("invalid base register for register offset");
8490 inst
.instruction
= T_OPCODE_LDR_PC
;
8491 else if (load_store
== THUMB_LOAD
)
8492 inst
.instruction
= T_OPCODE_LDR_SP
;
8494 inst
.instruction
= T_OPCODE_STR_SP
;
8496 inst
.instruction
|= Rd
<< 8;
8497 if (inst
.reloc
.exp
.X_op
== O_constant
)
8499 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
8501 if (offset
& ~0x3fc)
8503 inst
.error
= _("invalid offset");
8507 inst
.instruction
|= offset
>> 2;
8510 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8514 inst
.error
= _("invalid base register in load/store");
8517 else if (Ro
== FAIL
)
8519 /* Immediate offset. */
8520 if (size
== THUMB_WORD
)
8521 inst
.instruction
= (load_store
== THUMB_LOAD
8522 ? T_OPCODE_LDR_IW
: T_OPCODE_STR_IW
);
8523 else if (size
== THUMB_HALFWORD
)
8524 inst
.instruction
= (load_store
== THUMB_LOAD
8525 ? T_OPCODE_LDR_IH
: T_OPCODE_STR_IH
);
8527 inst
.instruction
= (load_store
== THUMB_LOAD
8528 ? T_OPCODE_LDR_IB
: T_OPCODE_STR_IB
);
8530 inst
.instruction
|= Rd
| (Rb
<< 3);
8532 if (inst
.reloc
.exp
.X_op
== O_constant
)
8534 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
8536 if (offset
& ~(0x1f << size
))
8538 inst
.error
= _("invalid offset");
8541 inst
.instruction
|= (offset
>> size
) << 6;
8544 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8548 /* Register offset. */
8549 if (size
== THUMB_WORD
)
8550 inst
.instruction
= (load_store
== THUMB_LOAD
8551 ? T_OPCODE_LDR_RW
: T_OPCODE_STR_RW
);
8552 else if (size
== THUMB_HALFWORD
)
8553 inst
.instruction
= (load_store
== THUMB_LOAD
8554 ? T_OPCODE_LDR_RH
: T_OPCODE_STR_RH
);
8556 inst
.instruction
= (load_store
== THUMB_LOAD
8557 ? T_OPCODE_LDR_RB
: T_OPCODE_STR_RB
);
8559 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
8565 /* A register must be given at this point.
8567 Shift is the place to put it in inst.instruction.
8569 Restores input start point on err.
8570 Returns the reg#, or FAIL. */
8573 mav_reg_required_here (char ** str
, int shift
, enum arm_reg_type regtype
)
8578 if ((reg
= arm_reg_parse (str
, all_reg_maps
[regtype
].htab
)) != FAIL
)
8581 inst
.instruction
|= reg
<< shift
;
8586 /* Restore the start point. */
8589 /* Try generic coprocessor name if applicable. */
8590 if (regtype
== REG_TYPE_MVF
||
8591 regtype
== REG_TYPE_MVD
||
8592 regtype
== REG_TYPE_MVFX
||
8593 regtype
== REG_TYPE_MVDX
)
8595 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CN
].htab
)) != FAIL
)
8598 inst
.instruction
|= reg
<< shift
;
8603 /* Restore the start point. */
8607 /* In the few cases where we might be able to accept something else
8608 this error can be overridden. */
8609 inst
.error
= _(all_reg_maps
[regtype
].expected
);
8614 /* Cirrus Maverick Instructions. */
8616 /* Isnsn like "foo X,Y". */
8619 do_mav_binops (char * str
,
8621 enum arm_reg_type reg0
,
8622 enum arm_reg_type reg1
)
8626 shift0
= mode
& 0xff;
8627 shift1
= (mode
>> 8) & 0xff;
8629 skip_whitespace (str
);
8631 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
8632 || skip_past_comma (&str
) == FAIL
8633 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
)
8636 inst
.error
= BAD_ARGS
;
8642 /* Isnsn like "foo X,Y,Z". */
8645 do_mav_triple (char * str
,
8647 enum arm_reg_type reg0
,
8648 enum arm_reg_type reg1
,
8649 enum arm_reg_type reg2
)
8651 int shift0
, shift1
, shift2
;
8653 shift0
= mode
& 0xff;
8654 shift1
= (mode
>> 8) & 0xff;
8655 shift2
= (mode
>> 16) & 0xff;
8657 skip_whitespace (str
);
8659 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
8660 || skip_past_comma (&str
) == FAIL
8661 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
8662 || skip_past_comma (&str
) == FAIL
8663 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
)
8666 inst
.error
= BAD_ARGS
;
8672 /* Wrapper functions. */
8675 do_mav_binops_1a (char * str
)
8677 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVF
);
8681 do_mav_binops_1b (char * str
)
8683 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVD
);
8687 do_mav_binops_1c (char * str
)
8689 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVDX
);
8693 do_mav_binops_1d (char * str
)
8695 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVF
);
8699 do_mav_binops_1e (char * str
)
8701 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVD
);
8705 do_mav_binops_1f (char * str
)
8707 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVF
);
8711 do_mav_binops_1g (char * str
)
8713 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVD
);
8717 do_mav_binops_1h (char * str
)
8719 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVFX
);
8723 do_mav_binops_1i (char * str
)
8725 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVFX
);
8729 do_mav_binops_1j (char * str
)
8731 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVDX
);
8735 do_mav_binops_1k (char * str
)
8737 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVDX
);
8741 do_mav_binops_1l (char * str
)
8743 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVF
);
8747 do_mav_binops_1m (char * str
)
8749 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVD
);
8753 do_mav_binops_1n (char * str
)
8755 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
8759 do_mav_binops_1o (char * str
)
8761 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
8765 do_mav_binops_2a (char * str
)
8767 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVF
, REG_TYPE_RN
);
8771 do_mav_binops_2b (char * str
)
8773 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVD
, REG_TYPE_RN
);
8777 do_mav_binops_2c (char * str
)
8779 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVDX
, REG_TYPE_RN
);
8783 do_mav_binops_3a (char * str
)
8785 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVFX
);
8789 do_mav_binops_3b (char * str
)
8791 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVFX
, REG_TYPE_MVAX
);
8795 do_mav_binops_3c (char * str
)
8797 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVDX
);
8801 do_mav_binops_3d (char * str
)
8803 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVDX
, REG_TYPE_MVAX
);
8807 do_mav_triple_4a (char * str
)
8809 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_RN
);
8813 do_mav_triple_4b (char * str
)
8815 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_RN
);
8819 do_mav_triple_5a (char * str
)
8821 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVF
, REG_TYPE_MVF
);
8825 do_mav_triple_5b (char * str
)
8827 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVD
, REG_TYPE_MVD
);
8831 do_mav_triple_5c (char * str
)
8833 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
8837 do_mav_triple_5d (char * str
)
8839 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
8843 do_mav_triple_5e (char * str
)
8845 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVF
, REG_TYPE_MVF
, REG_TYPE_MVF
);
8849 do_mav_triple_5f (char * str
)
8851 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVD
, REG_TYPE_MVD
, REG_TYPE_MVD
);
8855 do_mav_triple_5g (char * str
)
8857 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
8861 do_mav_triple_5h (char * str
)
8863 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
8866 /* Isnsn like "foo W,X,Y,Z".
8867 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
8870 do_mav_quad (char * str
,
8872 enum arm_reg_type reg0
,
8873 enum arm_reg_type reg1
,
8874 enum arm_reg_type reg2
,
8875 enum arm_reg_type reg3
)
8877 int shift0
, shift1
, shift2
, shift3
;
8879 shift0
= mode
& 0xff;
8880 shift1
= (mode
>> 8) & 0xff;
8881 shift2
= (mode
>> 16) & 0xff;
8882 shift3
= (mode
>> 24) & 0xff;
8884 skip_whitespace (str
);
8886 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
8887 || skip_past_comma (&str
) == FAIL
8888 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
8889 || skip_past_comma (&str
) == FAIL
8890 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
8891 || skip_past_comma (&str
) == FAIL
8892 || mav_reg_required_here (&str
, shift3
, reg3
) == FAIL
)
8895 inst
.error
= BAD_ARGS
;
8902 do_mav_quad_6a (char * str
)
8904 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
,
8909 do_mav_quad_6b (char * str
)
8911 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVAX
, REG_TYPE_MVFX
,
8915 /* cfmvsc32<cond> DSPSC,MVDX[15:0]. */
8917 do_mav_dspsc_1 (char * str
)
8919 skip_whitespace (str
);
8922 if (mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
8923 || skip_past_comma (&str
) == FAIL
8924 || mav_reg_required_here (&str
, 12, REG_TYPE_MVDX
) == FAIL
)
8927 inst
.error
= BAD_ARGS
;
8935 /* cfmv32sc<cond> MVDX[15:0],DSPSC. */
8937 do_mav_dspsc_2 (char * str
)
8939 skip_whitespace (str
);
8942 if (mav_reg_required_here (&str
, 12, REG_TYPE_MVDX
) == FAIL
8943 || skip_past_comma (&str
) == FAIL
8944 || mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
)
8947 inst
.error
= BAD_ARGS
;
8955 /* Maverick shift immediate instructions.
8956 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
8957 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
8960 do_mav_shift (char * str
,
8961 enum arm_reg_type reg0
,
8962 enum arm_reg_type reg1
)
8967 skip_whitespace (str
);
8971 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
8972 || skip_past_comma (&str
) == FAIL
8973 || mav_reg_required_here (&str
, 16, reg1
) == FAIL
8974 || skip_past_comma (&str
) == FAIL
)
8977 inst
.error
= BAD_ARGS
;
8981 /* Calculate the immediate operand.
8982 The operand is a 7bit signed number. */
8983 skip_whitespace (str
);
8988 if (!ISDIGIT (*str
) && *str
!= '-')
8990 inst
.error
= _("expecting immediate, 7bit operand");
9000 for (imm
= 0; *str
&& ISDIGIT (*str
); ++str
)
9001 imm
= imm
* 10 + *str
- '0';
9005 inst
.error
= _("immediate out of range");
9009 /* Make negative imm's into 7bit signed numbers. */
9016 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
9017 Bits 5-7 of the insn should have bits 4-6 of the immediate.
9018 Bit 4 should be 0. */
9019 imm
= (imm
& 0xf) | ((imm
& 0x70) << 1);
9021 inst
.instruction
|= imm
;
9026 do_mav_shift_1 (char * str
)
9028 do_mav_shift (str
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
9032 do_mav_shift_2 (char * str
)
9034 do_mav_shift (str
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
9038 mav_parse_offset (char ** str
, int * negative
)
9045 skip_whitespace (p
);
9058 inst
.error
= _("offset expected");
9062 for (offset
= 0; *p
&& ISDIGIT (*p
); ++p
)
9063 offset
= offset
* 10 + *p
- '0';
9067 inst
.error
= _("offset out of range");
9072 inst
.error
= _("offset not a multiple of 4");
9078 return *negative
? -offset
: offset
;
9081 /* Maverick load/store instructions.
9082 <insn><cond> CRd,[Rn,<offset>]{!}.
9083 <insn><cond> CRd,[Rn],<offset>. */
9086 do_mav_ldst (char * str
, enum arm_reg_type reg0
)
9088 int offset
, negative
;
9090 skip_whitespace (str
);
9092 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
9093 || skip_past_comma (&str
) == FAIL
9095 || reg_required_here (&str
, 16) == FAIL
)
9098 if (skip_past_comma (&str
) == SUCCESS
)
9100 /* You are here: "<offset>]{!}". */
9101 inst
.instruction
|= PRE_INDEX
;
9103 offset
= mav_parse_offset (&str
, &negative
);
9110 inst
.error
= _("missing ]");
9116 inst
.instruction
|= WRITE_BACK
;
9122 /* You are here: "], <offset>". */
9125 inst
.error
= _("missing ]");
9129 if (skip_past_comma (&str
) == FAIL
9130 || (offset
= mav_parse_offset (&str
, &negative
), inst
.error
))
9133 inst
.instruction
|= CP_T_WB
; /* Post indexed, set bit W. */
9139 inst
.instruction
|= CP_T_UD
; /* Positive, so set bit U. */
9141 inst
.instruction
|= offset
>> 2;
9147 inst
.error
= BAD_ARGS
;
9151 do_mav_ldst_1 (char * str
)
9153 do_mav_ldst (str
, REG_TYPE_MVF
);
9157 do_mav_ldst_2 (char * str
)
9159 do_mav_ldst (str
, REG_TYPE_MVD
);
9163 do_mav_ldst_3 (char * str
)
9165 do_mav_ldst (str
, REG_TYPE_MVFX
);
9169 do_mav_ldst_4 (char * str
)
9171 do_mav_ldst (str
, REG_TYPE_MVDX
);
9175 do_t_nop (char * str
)
9181 /* Handle the Format 4 instructions that do not have equivalents in other
9182 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
9186 do_t_arit (char * str
)
9190 skip_whitespace (str
);
9192 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9193 || skip_past_comma (&str
) == FAIL
9194 || (Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9196 inst
.error
= BAD_ARGS
;
9200 if (skip_past_comma (&str
) != FAIL
)
9202 /* Three operand format not allowed for TST, CMN, NEG and MVN.
9203 (It isn't allowed for CMP either, but that isn't handled by this
9205 if (inst
.instruction
== T_OPCODE_TST
9206 || inst
.instruction
== T_OPCODE_CMN
9207 || inst
.instruction
== T_OPCODE_NEG
9208 || inst
.instruction
== T_OPCODE_MVN
)
9210 inst
.error
= BAD_ARGS
;
9214 if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9219 inst
.error
= _("dest and source1 must be the same register");
9225 if (inst
.instruction
== T_OPCODE_MUL
9227 as_tsktsk (_("Rs and Rd must be different in MUL"));
9229 inst
.instruction
|= Rd
| (Rs
<< 3);
9234 do_t_add (char * str
)
9236 thumb_add_sub (str
, 0);
9240 do_t_asr (char * str
)
9242 thumb_shift (str
, THUMB_ASR
);
9246 do_t_branch9 (char * str
)
9248 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9250 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH9
;
9251 inst
.reloc
.pc_rel
= 1;
9256 do_t_branch12 (char * str
)
9258 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9260 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH12
;
9261 inst
.reloc
.pc_rel
= 1;
9265 /* Find the real, Thumb encoded start of a Thumb function. */
9268 find_real_start (symbolS
* symbolP
)
9271 const char * name
= S_GET_NAME (symbolP
);
9272 symbolS
* new_target
;
9274 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
9275 #define STUB_NAME ".real_start_of"
9280 /* Names that start with '.' are local labels, not function entry points.
9281 The compiler may generate BL instructions to these labels because it
9282 needs to perform a branch to a far away location. */
9286 real_start
= malloc (strlen (name
) + strlen (STUB_NAME
) + 1);
9287 sprintf (real_start
, "%s%s", STUB_NAME
, name
);
9289 new_target
= symbol_find (real_start
);
9291 if (new_target
== NULL
)
9293 as_warn ("Failed to find real start of function: %s\n", name
);
9294 new_target
= symbolP
;
9303 do_t_branch23 (char * str
)
9305 if (my_get_expression (& inst
.reloc
.exp
, & str
))
9308 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH23
;
9309 inst
.reloc
.pc_rel
= 1;
9312 /* If the destination of the branch is a defined symbol which does not have
9313 the THUMB_FUNC attribute, then we must be calling a function which has
9314 the (interfacearm) attribute. We look for the Thumb entry point to that
9315 function and change the branch to refer to that function instead. */
9316 if ( inst
.reloc
.exp
.X_op
== O_symbol
9317 && inst
.reloc
.exp
.X_add_symbol
!= NULL
9318 && S_IS_DEFINED (inst
.reloc
.exp
.X_add_symbol
)
9319 && ! THUMB_IS_FUNC (inst
.reloc
.exp
.X_add_symbol
))
9320 inst
.reloc
.exp
.X_add_symbol
=
9321 find_real_start (inst
.reloc
.exp
.X_add_symbol
);
9325 do_t_bx (char * str
)
9329 skip_whitespace (str
);
9331 if ((reg
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
9334 /* This sets THUMB_H2 from the top bit of reg. */
9335 inst
.instruction
|= reg
<< 3;
9337 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
9338 should cause the alignment to be checked once it is known. This is
9339 because BX PC only works if the instruction is word aligned. */
9345 do_t_compare (char * str
)
9347 thumb_mov_compare (str
, THUMB_COMPARE
);
9351 do_t_ldmstm (char * str
)
9356 skip_whitespace (str
);
9358 if ((Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9362 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
9366 if (skip_past_comma (&str
) == FAIL
9367 || (range
= reg_list (&str
)) == FAIL
)
9370 inst
.error
= BAD_ARGS
;
9374 if (inst
.reloc
.type
!= BFD_RELOC_UNUSED
)
9376 /* This really doesn't seem worth it. */
9377 inst
.reloc
.type
= BFD_RELOC_UNUSED
;
9378 inst
.error
= _("expression too complex");
9384 inst
.error
= _("only lo-regs valid in load/store multiple");
9388 inst
.instruction
|= (Rb
<< 8) | range
;
9393 do_t_ldr (char * str
)
9395 thumb_load_store (str
, THUMB_LOAD
, THUMB_WORD
);
9399 do_t_ldrb (char * str
)
9401 thumb_load_store (str
, THUMB_LOAD
, THUMB_BYTE
);
9405 do_t_ldrh (char * str
)
9407 thumb_load_store (str
, THUMB_LOAD
, THUMB_HALFWORD
);
9411 do_t_lds (char * str
)
9415 skip_whitespace (str
);
9417 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9418 || skip_past_comma (&str
) == FAIL
9420 || (Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9421 || skip_past_comma (&str
) == FAIL
9422 || (Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9426 inst
.error
= _("syntax: ldrs[b] Rd, [Rb, Ro]");
9430 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
9435 do_t_lsl (char * str
)
9437 thumb_shift (str
, THUMB_LSL
);
9441 do_t_lsr (char * str
)
9443 thumb_shift (str
, THUMB_LSR
);
9447 do_t_mov (char * str
)
9449 thumb_mov_compare (str
, THUMB_MOVE
);
9453 do_t_push_pop (char * str
)
9457 skip_whitespace (str
);
9459 if ((range
= reg_list (&str
)) == FAIL
)
9462 inst
.error
= BAD_ARGS
;
9466 if (inst
.reloc
.type
!= BFD_RELOC_UNUSED
)
9468 /* This really doesn't seem worth it. */
9469 inst
.reloc
.type
= BFD_RELOC_UNUSED
;
9470 inst
.error
= _("expression too complex");
9476 if ((inst
.instruction
== T_OPCODE_PUSH
9477 && (range
& ~0xff) == 1 << REG_LR
)
9478 || (inst
.instruction
== T_OPCODE_POP
9479 && (range
& ~0xff) == 1 << REG_PC
))
9481 inst
.instruction
|= THUMB_PP_PC_LR
;
9486 inst
.error
= _("invalid register list to push/pop instruction");
9491 inst
.instruction
|= range
;
9496 do_t_str (char * str
)
9498 thumb_load_store (str
, THUMB_STORE
, THUMB_WORD
);
9502 do_t_strb (char * str
)
9504 thumb_load_store (str
, THUMB_STORE
, THUMB_BYTE
);
9508 do_t_strh (char * str
)
9510 thumb_load_store (str
, THUMB_STORE
, THUMB_HALFWORD
);
9514 do_t_sub (char * str
)
9516 thumb_add_sub (str
, 1);
9520 do_t_swi (char * str
)
9522 skip_whitespace (str
);
9524 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9527 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
9532 do_t_adr (char * str
)
9536 /* This is a pseudo-op of the form "adr rd, label" to be converted
9537 into a relative address of the form "add rd, pc, #label-.-4". */
9538 skip_whitespace (str
);
9540 /* Store Rd in temporary location inside instruction. */
9541 if ((reg
= reg_required_here (&str
, 4)) == FAIL
9542 || (reg
> 7) /* For Thumb reg must be r0..r7. */
9543 || skip_past_comma (&str
) == FAIL
9544 || my_get_expression (&inst
.reloc
.exp
, &str
))
9547 inst
.error
= BAD_ARGS
;
9551 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
9552 inst
.reloc
.exp
.X_add_number
-= 4; /* PC relative adjust. */
9553 inst
.reloc
.pc_rel
= 1;
9554 inst
.instruction
|= REG_PC
; /* Rd is already placed into the instruction. */
9560 insert_reg (const struct reg_entry
* r
,
9561 struct hash_control
* htab
)
9563 int len
= strlen (r
->name
) + 2;
9564 char * buf
= xmalloc (len
);
9565 char * buf2
= xmalloc (len
);
9568 #ifdef REGISTER_PREFIX
9569 buf
[i
++] = REGISTER_PREFIX
;
9572 strcpy (buf
+ i
, r
->name
);
9574 for (i
= 0; buf
[i
]; i
++)
9575 buf2
[i
] = TOUPPER (buf
[i
]);
9579 hash_insert (htab
, buf
, (PTR
) r
);
9580 hash_insert (htab
, buf2
, (PTR
) r
);
9584 build_reg_hsh (struct reg_map
* map
)
9586 const struct reg_entry
*r
;
9588 if ((map
->htab
= hash_new ()) == NULL
)
9589 as_fatal (_("virtual memory exhausted"));
9591 for (r
= map
->names
; r
->name
!= NULL
; r
++)
9592 insert_reg (r
, map
->htab
);
9596 insert_reg_alias (char * str
,
9598 struct hash_control
*htab
)
9601 struct reg_entry
* new = xmalloc (sizeof (struct reg_entry
));
9602 const char * name
= xmalloc (strlen (str
) + 1);
9604 strcpy ((char *) name
, str
);
9607 new->number
= regnum
;
9608 new->builtin
= FALSE
;
9610 error
= hash_insert (htab
, name
, (PTR
) new);
9613 as_bad (_("failed to create an alias for %s, reason: %s"),
9615 free ((char *) name
);
9620 /* Look for the .req directive. This is of the form:
9622 new_register_name .req existing_register_name
9624 If we find one, or if it looks sufficiently like one that we want to
9625 handle any error here, return non-zero. Otherwise return zero. */
9628 create_register_alias (char * newname
, char * p
)
9634 skip_whitespace (q
);
9639 if (*q
&& !strncmp (q
, ".req ", 5))
9644 #ifndef IGNORE_OPCODE_CASE
9645 newname
= original_case_string
;
9647 copy_of_str
= newname
;
9650 skip_whitespace (q
);
9652 for (r
= q
; *r
!= '\0'; r
++)
9658 enum arm_reg_type new_type
, old_type
;
9663 old_type
= arm_reg_parse_any (q
);
9666 new_type
= arm_reg_parse_any (newname
);
9668 if (new_type
== REG_TYPE_MAX
)
9670 if (old_type
!= REG_TYPE_MAX
)
9672 old_regno
= arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
);
9673 insert_reg_alias (newname
, old_regno
,
9674 all_reg_maps
[old_type
].htab
);
9677 as_warn (_("register '%s' does not exist\n"), q
);
9679 else if (old_type
== REG_TYPE_MAX
)
9681 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
9686 /* Do not warn about redefinitions to the same alias. */
9687 if (new_type
!= old_type
9688 || (arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
)
9689 != arm_reg_parse (&q
, all_reg_maps
[new_type
].htab
)))
9690 as_warn (_("ignoring redefinition of register alias '%s'"),
9696 as_warn (_("ignoring incomplete .req pseuso op"));
9707 set_constant_flonums (void)
9711 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
9712 if (atof_ieee ((char *) fp_const
[i
], 'x', fp_values
[i
]) == NULL
)
9717 static const struct asm_opcode insns
[] =
9719 /* Core ARM Instructions. */
9720 {"and", 0xe0000000, 3, ARM_EXT_V1
, do_arit
},
9721 {"ands", 0xe0100000, 3, ARM_EXT_V1
, do_arit
},
9722 {"eor", 0xe0200000, 3, ARM_EXT_V1
, do_arit
},
9723 {"eors", 0xe0300000, 3, ARM_EXT_V1
, do_arit
},
9724 {"sub", 0xe0400000, 3, ARM_EXT_V1
, do_arit
},
9725 {"subs", 0xe0500000, 3, ARM_EXT_V1
, do_arit
},
9726 {"rsb", 0xe0600000, 3, ARM_EXT_V1
, do_arit
},
9727 {"rsbs", 0xe0700000, 3, ARM_EXT_V1
, do_arit
},
9728 {"add", 0xe0800000, 3, ARM_EXT_V1
, do_arit
},
9729 {"adds", 0xe0900000, 3, ARM_EXT_V1
, do_arit
},
9730 {"adc", 0xe0a00000, 3, ARM_EXT_V1
, do_arit
},
9731 {"adcs", 0xe0b00000, 3, ARM_EXT_V1
, do_arit
},
9732 {"sbc", 0xe0c00000, 3, ARM_EXT_V1
, do_arit
},
9733 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1
, do_arit
},
9734 {"rsc", 0xe0e00000, 3, ARM_EXT_V1
, do_arit
},
9735 {"rscs", 0xe0f00000, 3, ARM_EXT_V1
, do_arit
},
9736 {"orr", 0xe1800000, 3, ARM_EXT_V1
, do_arit
},
9737 {"orrs", 0xe1900000, 3, ARM_EXT_V1
, do_arit
},
9738 {"bic", 0xe1c00000, 3, ARM_EXT_V1
, do_arit
},
9739 {"bics", 0xe1d00000, 3, ARM_EXT_V1
, do_arit
},
9741 {"tst", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
9742 {"tsts", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
9743 {"tstp", 0xe110f000, 3, ARM_EXT_V1
, do_cmp
},
9744 {"teq", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
9745 {"teqs", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
9746 {"teqp", 0xe130f000, 3, ARM_EXT_V1
, do_cmp
},
9747 {"cmp", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
9748 {"cmps", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
9749 {"cmpp", 0xe150f000, 3, ARM_EXT_V1
, do_cmp
},
9750 {"cmn", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
9751 {"cmns", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
9752 {"cmnp", 0xe170f000, 3, ARM_EXT_V1
, do_cmp
},
9754 {"mov", 0xe1a00000, 3, ARM_EXT_V1
, do_mov
},
9755 {"movs", 0xe1b00000, 3, ARM_EXT_V1
, do_mov
},
9756 {"mvn", 0xe1e00000, 3, ARM_EXT_V1
, do_mov
},
9757 {"mvns", 0xe1f00000, 3, ARM_EXT_V1
, do_mov
},
9759 {"ldr", 0xe4100000, 3, ARM_EXT_V1
, do_ldst
},
9760 {"ldrb", 0xe4500000, 3, ARM_EXT_V1
, do_ldst
},
9761 {"ldrt", 0xe4300000, 3, ARM_EXT_V1
, do_ldstt
},
9762 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1
, do_ldstt
},
9763 {"str", 0xe4000000, 3, ARM_EXT_V1
, do_ldst
},
9764 {"strb", 0xe4400000, 3, ARM_EXT_V1
, do_ldst
},
9765 {"strt", 0xe4200000, 3, ARM_EXT_V1
, do_ldstt
},
9766 {"strbt", 0xe4600000, 3, ARM_EXT_V1
, do_ldstt
},
9768 {"stmia", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
9769 {"stmib", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
9770 {"stmda", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
9771 {"stmdb", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
9772 {"stmfd", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
9773 {"stmfa", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
9774 {"stmea", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
9775 {"stmed", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
9777 {"ldmia", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
9778 {"ldmib", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
9779 {"ldmda", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
9780 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
9781 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
9782 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
9783 {"ldmea", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
9784 {"ldmed", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
9786 {"swi", 0xef000000, 3, ARM_EXT_V1
, do_swi
},
9788 /* XXX This is the wrong place to do this. Think multi-arch. */
9789 {"bl", 0xeb000000, 2, ARM_EXT_V1
, do_branch
},
9790 {"b", 0xea000000, 1, ARM_EXT_V1
, do_branch
},
9792 {"bl", 0xebfffffe, 2, ARM_EXT_V1
, do_branch
},
9793 {"b", 0xeafffffe, 1, ARM_EXT_V1
, do_branch
},
9797 {"adr", 0xe28f0000, 3, ARM_EXT_V1
, do_adr
},
9798 {"adrl", 0xe28f0000, 3, ARM_EXT_V1
, do_adrl
},
9799 {"nop", 0xe1a00000, 3, ARM_EXT_V1
, do_nop
},
9801 /* ARM 2 multiplies. */
9802 {"mul", 0xe0000090, 3, ARM_EXT_V2
, do_mul
},
9803 {"muls", 0xe0100090, 3, ARM_EXT_V2
, do_mul
},
9804 {"mla", 0xe0200090, 3, ARM_EXT_V2
, do_mla
},
9805 {"mlas", 0xe0300090, 3, ARM_EXT_V2
, do_mla
},
9807 /* Generic coprocessor instructions. */
9808 {"cdp", 0xee000000, 3, ARM_EXT_V2
, do_cdp
},
9809 {"ldc", 0xec100000, 3, ARM_EXT_V2
, do_lstc
},
9810 {"ldcl", 0xec500000, 3, ARM_EXT_V2
, do_lstc
},
9811 {"stc", 0xec000000, 3, ARM_EXT_V2
, do_lstc
},
9812 {"stcl", 0xec400000, 3, ARM_EXT_V2
, do_lstc
},
9813 {"mcr", 0xee000010, 3, ARM_EXT_V2
, do_co_reg
},
9814 {"mrc", 0xee100010, 3, ARM_EXT_V2
, do_co_reg
},
9816 /* ARM 3 - swp instructions. */
9817 {"swp", 0xe1000090, 3, ARM_EXT_V2S
, do_swap
},
9818 {"swpb", 0xe1400090, 3, ARM_EXT_V2S
, do_swap
},
9820 /* ARM 6 Status register instructions. */
9821 {"mrs", 0xe10f0000, 3, ARM_EXT_V3
, do_mrs
},
9822 {"msr", 0xe120f000, 3, ARM_EXT_V3
, do_msr
},
9823 /* ScottB: our code uses 0xe128f000 for msr.
9824 NickC: but this is wrong because the bits 16 through 19 are
9825 handled by the PSR_xxx defines above. */
9827 /* ARM 7M long multiplies. */
9828 {"smull", 0xe0c00090, 5, ARM_EXT_V3M
, do_mull
},
9829 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M
, do_mull
},
9830 {"umull", 0xe0800090, 5, ARM_EXT_V3M
, do_mull
},
9831 {"umulls", 0xe0900090, 5, ARM_EXT_V3M
, do_mull
},
9832 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M
, do_mull
},
9833 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M
, do_mull
},
9834 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M
, do_mull
},
9835 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M
, do_mull
},
9837 /* ARM Architecture 4. */
9838 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4
, do_ldstv4
},
9839 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4
, do_ldstv4
},
9840 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4
, do_ldstv4
},
9841 {"strh", 0xe00000b0, 3, ARM_EXT_V4
, do_ldstv4
},
9843 /* ARM Architecture 4T. */
9844 /* Note: bx (and blx) are required on V5, even if the processor does
9845 not support Thumb. */
9846 {"bx", 0xe12fff10, 2, ARM_EXT_V4T
| ARM_EXT_V5
, do_bx
},
9848 /* ARM Architecture 5T. */
9849 /* Note: blx has 2 variants, so the .value is set dynamically.
9850 Only one of the variants has conditional execution. */
9851 {"blx", 0xe0000000, 3, ARM_EXT_V5
, do_blx
},
9852 {"clz", 0xe16f0f10, 3, ARM_EXT_V5
, do_clz
},
9853 {"bkpt", 0xe1200070, 0, ARM_EXT_V5
, do_bkpt
},
9854 {"ldc2", 0xfc100000, 0, ARM_EXT_V5
, do_lstc2
},
9855 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5
, do_lstc2
},
9856 {"stc2", 0xfc000000, 0, ARM_EXT_V5
, do_lstc2
},
9857 {"stc2l", 0xfc400000, 0, ARM_EXT_V5
, do_lstc2
},
9858 {"cdp2", 0xfe000000, 0, ARM_EXT_V5
, do_cdp2
},
9859 {"mcr2", 0xfe000010, 0, ARM_EXT_V5
, do_co_reg2
},
9860 {"mrc2", 0xfe100010, 0, ARM_EXT_V5
, do_co_reg2
},
9862 /* ARM Architecture 5TExP. */
9863 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP
, do_smla
},
9864 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP
, do_smla
},
9865 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP
, do_smla
},
9866 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP
, do_smla
},
9868 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP
, do_smla
},
9869 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP
, do_smla
},
9871 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP
, do_smlal
},
9872 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP
, do_smlal
},
9873 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP
, do_smlal
},
9874 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP
, do_smlal
},
9876 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP
, do_smul
},
9877 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP
, do_smul
},
9878 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP
, do_smul
},
9879 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP
, do_smul
},
9881 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP
, do_smul
},
9882 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP
, do_smul
},
9884 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP
, do_qadd
},
9885 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP
, do_qadd
},
9886 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP
, do_qadd
},
9887 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP
, do_qadd
},
9889 /* ARM Architecture 5TE. */
9890 {"pld", 0xf450f000, 0, ARM_EXT_V5E
, do_pld
},
9891 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E
, do_ldrd
},
9892 {"strd", 0xe00000f0, 3, ARM_EXT_V5E
, do_ldrd
},
9894 {"mcrr", 0xec400000, 4, ARM_EXT_V5E
, do_co_reg2c
},
9895 {"mrrc", 0xec500000, 4, ARM_EXT_V5E
, do_co_reg2c
},
9897 /* ARM Architecture 5TEJ. */
9898 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J
, do_bxj
},
9901 { "cps", 0xf1020000, 0, ARM_EXT_V6
, do_cps
},
9902 { "cpsie", 0xf1080000, 0, ARM_EXT_V6
, do_cpsi
},
9903 { "cpsid", 0xf10C0000, 0, ARM_EXT_V6
, do_cpsi
},
9904 { "ldrex", 0xe1900f9f, 5, ARM_EXT_V6
, do_ldrex
},
9905 { "mcrr2", 0xfc400000, 0, ARM_EXT_V6
, do_co_reg2c
},
9906 { "mrrc2", 0xfc500000, 0, ARM_EXT_V6
, do_co_reg2c
},
9907 { "pkhbt", 0xe6800010, 5, ARM_EXT_V6
, do_pkhbt
},
9908 { "pkhtb", 0xe6800050, 5, ARM_EXT_V6
, do_pkhtb
},
9909 { "qadd16", 0xe6200f10, 6, ARM_EXT_V6
, do_qadd16
},
9910 { "qadd8", 0xe6200f90, 5, ARM_EXT_V6
, do_qadd16
},
9911 { "qaddsubx", 0xe6200f30, 8, ARM_EXT_V6
, do_qadd16
},
9912 { "qsub16", 0xe6200f70, 6, ARM_EXT_V6
, do_qadd16
},
9913 { "qsub8", 0xe6200ff0, 5, ARM_EXT_V6
, do_qadd16
},
9914 { "qsubaddx", 0xe6200f50, 8, ARM_EXT_V6
, do_qadd16
},
9915 { "sadd16", 0xe6100f10, 6, ARM_EXT_V6
, do_qadd16
},
9916 { "sadd8", 0xe6100f90, 5, ARM_EXT_V6
, do_qadd16
},
9917 { "saddsubx", 0xe6100f30, 8, ARM_EXT_V6
, do_qadd16
},
9918 { "shadd16", 0xe6300f10, 7, ARM_EXT_V6
, do_qadd16
},
9919 { "shadd8", 0xe6300f90, 6, ARM_EXT_V6
, do_qadd16
},
9920 { "shaddsubx", 0xe6300f30, 9, ARM_EXT_V6
, do_qadd16
},
9921 { "shsub16", 0xe6300f70, 7, ARM_EXT_V6
, do_qadd16
},
9922 { "shsub8", 0xe6300ff0, 6, ARM_EXT_V6
, do_qadd16
},
9923 { "shsubaddx", 0xe6300f50, 9, ARM_EXT_V6
, do_qadd16
},
9924 { "ssub16", 0xe6100f70, 6, ARM_EXT_V6
, do_qadd16
},
9925 { "ssub8", 0xe6100ff0, 5, ARM_EXT_V6
, do_qadd16
},
9926 { "ssubaddx", 0xe6100f50, 8, ARM_EXT_V6
, do_qadd16
},
9927 { "uadd16", 0xe6500f10, 6, ARM_EXT_V6
, do_qadd16
},
9928 { "uadd8", 0xe6500f90, 5, ARM_EXT_V6
, do_qadd16
},
9929 { "uaddsubx", 0xe6500f30, 8, ARM_EXT_V6
, do_qadd16
},
9930 { "uhadd16", 0xe6700f10, 7, ARM_EXT_V6
, do_qadd16
},
9931 { "uhadd8", 0xe6700f90, 6, ARM_EXT_V6
, do_qadd16
},
9932 { "uhaddsubx", 0xe6700f30, 9, ARM_EXT_V6
, do_qadd16
},
9933 { "uhsub16", 0xe6700f70, 7, ARM_EXT_V6
, do_qadd16
},
9934 { "uhsub8", 0xe6700ff0, 6, ARM_EXT_V6
, do_qadd16
},
9935 { "uhsubaddx", 0xe6700f50, 9, ARM_EXT_V6
, do_qadd16
},
9936 { "uqadd16", 0xe6600f10, 7, ARM_EXT_V6
, do_qadd16
},
9937 { "uqadd8", 0xe6600f90, 6, ARM_EXT_V6
, do_qadd16
},
9938 { "uqaddsubx", 0xe6600f30, 9, ARM_EXT_V6
, do_qadd16
},
9939 { "uqsub16", 0xe6600f70, 7, ARM_EXT_V6
, do_qadd16
},
9940 { "uqsub8", 0xe6600ff0, 6, ARM_EXT_V6
, do_qadd16
},
9941 { "uqsubaddx", 0xe6600f50, 9, ARM_EXT_V6
, do_qadd16
},
9942 { "usub16", 0xe6500f70, 6, ARM_EXT_V6
, do_qadd16
},
9943 { "usub8", 0xe6500ff0, 5, ARM_EXT_V6
, do_qadd16
},
9944 { "usubaddx", 0xe6500f50, 8, ARM_EXT_V6
, do_qadd16
},
9945 { "rev", 0xe6bf0f30, 3, ARM_EXT_V6
, do_rev
},
9946 { "rev16", 0xe6bf0fb0, 5, ARM_EXT_V6
, do_rev
},
9947 { "revsh", 0xe6ff0fb0, 5, ARM_EXT_V6
, do_rev
},
9948 { "rfeia", 0xf8900a00, 0, ARM_EXT_V6
, do_rfe
},
9949 { "rfeib", 0xf9900a00, 0, ARM_EXT_V6
, do_rfe
},
9950 { "rfeda", 0xf8100a00, 0, ARM_EXT_V6
, do_rfe
},
9951 { "rfedb", 0xf9100a00, 0, ARM_EXT_V6
, do_rfe
},
9952 { "rfefd", 0xf8900a00, 0, ARM_EXT_V6
, do_rfe
},
9953 { "rfefa", 0xf9900a00, 0, ARM_EXT_V6
, do_rfe
},
9954 { "rfeea", 0xf8100a00, 0, ARM_EXT_V6
, do_rfe
},
9955 { "rfeed", 0xf9100a00, 0, ARM_EXT_V6
, do_rfe
},
9956 { "sxtah", 0xe6b00070, 5, ARM_EXT_V6
, do_sxtah
},
9957 { "sxtab16", 0xe6800070, 7, ARM_EXT_V6
, do_sxtah
},
9958 { "sxtab", 0xe6a00070, 5, ARM_EXT_V6
, do_sxtah
},
9959 { "sxth", 0xe6bf0070, 4, ARM_EXT_V6
, do_sxth
},
9960 { "sxtb16", 0xe68f0070, 6, ARM_EXT_V6
, do_sxth
},
9961 { "sxtb", 0xe6af0070, 4, ARM_EXT_V6
, do_sxth
},
9962 { "uxtah", 0xe6f00070, 5, ARM_EXT_V6
, do_sxtah
},
9963 { "uxtab16", 0xe6c00070, 7, ARM_EXT_V6
, do_sxtah
},
9964 { "uxtab", 0xe6e00070, 5, ARM_EXT_V6
, do_sxtah
},
9965 { "uxth", 0xe6ff0070, 4, ARM_EXT_V6
, do_sxth
},
9966 { "uxtb16", 0xe6cf0070, 6, ARM_EXT_V6
, do_sxth
},
9967 { "uxtb", 0xe6ef0070, 4, ARM_EXT_V6
, do_sxth
},
9968 { "sel", 0xe68000b0, 3, ARM_EXT_V6
, do_qadd16
},
9969 { "setend", 0xf1010000, 0, ARM_EXT_V6
, do_setend
},
9970 { "smlad", 0xe7000010, 5, ARM_EXT_V6
, do_smlad
},
9971 { "smladx", 0xe7000030, 6, ARM_EXT_V6
, do_smlad
},
9972 { "smlald", 0xe7400010, 6, ARM_EXT_V6
, do_smlald
},
9973 { "smlaldx", 0xe7400030, 7, ARM_EXT_V6
, do_smlald
},
9974 { "smlsd", 0xe7000050, 5, ARM_EXT_V6
, do_smlad
},
9975 { "smlsdx", 0xe7000070, 6, ARM_EXT_V6
, do_smlad
},
9976 { "smlsld", 0xe7400050, 6, ARM_EXT_V6
, do_smlald
},
9977 { "smlsldx", 0xe7400070, 7, ARM_EXT_V6
, do_smlald
},
9978 { "smmla", 0xe7500010, 5, ARM_EXT_V6
, do_smlad
},
9979 { "smmlar", 0xe7500030, 6, ARM_EXT_V6
, do_smlad
},
9980 { "smmls", 0xe75000d0, 5, ARM_EXT_V6
, do_smlad
},
9981 { "smmlsr", 0xe75000f0, 6, ARM_EXT_V6
, do_smlad
},
9982 { "smmul", 0xe750f010, 5, ARM_EXT_V6
, do_smmul
},
9983 { "smmulr", 0xe750f030, 6, ARM_EXT_V6
, do_smmul
},
9984 { "smuad", 0xe700f010, 5, ARM_EXT_V6
, do_smmul
},
9985 { "smuadx", 0xe700f030, 6, ARM_EXT_V6
, do_smmul
},
9986 { "smusd", 0xe700f050, 5, ARM_EXT_V6
, do_smmul
},
9987 { "smusdx", 0xe700f070, 6, ARM_EXT_V6
, do_smmul
},
9988 { "srsia", 0xf8cd0500, 0, ARM_EXT_V6
, do_srs
},
9989 { "srsib", 0xf9cd0500, 0, ARM_EXT_V6
, do_srs
},
9990 { "srsda", 0xf84d0500, 0, ARM_EXT_V6
, do_srs
},
9991 { "srsdb", 0xf94d0500, 0, ARM_EXT_V6
, do_srs
},
9992 { "ssat", 0xe6a00010, 4, ARM_EXT_V6
, do_ssat
},
9993 { "ssat16", 0xe6a00f30, 6, ARM_EXT_V6
, do_ssat16
},
9994 { "strex", 0xe1800f90, 5, ARM_EXT_V6
, do_strex
},
9995 { "umaal", 0xe0400090, 5, ARM_EXT_V6
, do_umaal
},
9996 { "usad8", 0xe780f010, 5, ARM_EXT_V6
, do_smmul
},
9997 { "usada8", 0xe7800010, 6, ARM_EXT_V6
, do_smlad
},
9998 { "usat", 0xe6e00010, 4, ARM_EXT_V6
, do_usat
},
9999 { "usat16", 0xe6e00f30, 6, ARM_EXT_V6
, do_usat16
},
10002 { "clrex", 0xf57ff01f, 0, ARM_EXT_V6K
, do_empty
},
10003 { "ldrexb", 0xe1d00f9f, 6, ARM_EXT_V6K
, do_ldrex
},
10004 { "ldrexd", 0xe1b00f9f, 6, ARM_EXT_V6K
, do_ldrex
},
10005 { "ldrexh", 0xe1f00f9f, 6, ARM_EXT_V6K
, do_ldrex
},
10006 { "sev", 0xe320f004, 3, ARM_EXT_V6K
, do_empty
},
10007 { "strexb", 0xe1c00f90, 6, ARM_EXT_V6K
, do_strex
},
10008 { "strexd", 0xe1a00f90, 6, ARM_EXT_V6K
, do_strex
},
10009 { "strexh", 0xe1e00f90, 6, ARM_EXT_V6K
, do_strex
},
10010 { "wfe", 0xe320f002, 3, ARM_EXT_V6K
, do_empty
},
10011 { "wfi", 0xe320f003, 3, ARM_EXT_V6K
, do_empty
},
10012 { "yield", 0xe320f001, 5, ARM_EXT_V6K
, do_empty
},
10015 { "smi", 0xe1600070, 3, ARM_EXT_V6Z
, do_smi
},
10017 /* Core FPA instruction set (V1). */
10018 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
10019 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
10020 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
10021 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
10023 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10024 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10025 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10026 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10028 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10029 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10030 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10031 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10033 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10034 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10035 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10036 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10037 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10038 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10039 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10040 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10041 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10042 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10043 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10044 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10046 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10047 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10048 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10049 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10050 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10051 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10052 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10053 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10054 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10055 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10056 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10057 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10059 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10060 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10061 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10062 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10063 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10064 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10065 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10066 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10067 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10068 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10069 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10070 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10072 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10073 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10074 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10075 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10076 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10077 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10078 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10079 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10080 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10081 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10082 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10083 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10085 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10086 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10087 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10088 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10089 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10090 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10091 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10092 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10093 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10094 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10095 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10096 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10098 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10099 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10100 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10101 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10102 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10103 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10104 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10105 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10106 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10107 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10108 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10109 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10111 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10112 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10113 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10114 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10115 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10116 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10117 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10118 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10119 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10120 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10121 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10122 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10124 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10125 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10126 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10127 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10128 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10129 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10130 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10131 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10132 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10133 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10134 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10135 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10137 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10138 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10139 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10140 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10141 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10142 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10143 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10144 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10145 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10146 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10147 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10148 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10150 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10151 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10152 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10153 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10154 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10155 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10156 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10157 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10158 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10159 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10160 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10161 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10163 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10164 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10165 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10166 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10167 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10168 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10169 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10170 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10171 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10172 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10173 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10174 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10176 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10177 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10178 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10179 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10180 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10181 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10182 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10183 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10184 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10185 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10186 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10187 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10189 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10190 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10191 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10192 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10193 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10194 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10195 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10196 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10197 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10198 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10199 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10200 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10202 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10203 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10204 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10205 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10206 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10207 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10208 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10209 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10210 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10211 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10212 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10213 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10215 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10216 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10217 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10218 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10219 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10220 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10221 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10222 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10223 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10224 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10225 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10226 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10228 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10229 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10230 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10231 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10232 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10233 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10234 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10235 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10236 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10237 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10238 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10239 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10241 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10242 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10243 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10244 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10245 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10246 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10247 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10248 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10249 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10250 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10251 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10252 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10254 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10255 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10256 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10257 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10258 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10259 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10260 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10261 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10262 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10263 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10264 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10265 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10267 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10268 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10269 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10270 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10271 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10272 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10273 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10274 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10275 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10276 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10277 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10278 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10280 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10281 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10282 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10283 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10284 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10285 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10286 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10287 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10288 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10289 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10290 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10291 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10293 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10294 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10295 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10296 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10297 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10298 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10299 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10300 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10301 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10302 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10303 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10304 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10306 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10307 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10308 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10309 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10310 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10311 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10312 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10313 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10314 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10315 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10316 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10317 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10319 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10320 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10321 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10322 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10323 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10324 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10325 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10326 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10327 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10328 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10329 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10330 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10332 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10333 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10334 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10335 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10336 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10337 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10338 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10339 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10340 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10341 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10342 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10343 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10345 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10346 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10347 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10348 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10349 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10350 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10351 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10352 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10353 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10354 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10355 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10356 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10358 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10359 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10360 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10361 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10362 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10363 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10364 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10365 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10366 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10367 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10368 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10369 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10371 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10372 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10373 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10374 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10375 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10376 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10377 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10378 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10379 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10380 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10381 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10382 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10384 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10385 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10386 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10387 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10388 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10389 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10390 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10391 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10392 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10393 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10394 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10395 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10397 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10398 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10399 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10400 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10401 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10402 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10403 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10404 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10405 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10406 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10407 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10408 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10410 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10411 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10412 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10413 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10414 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
10415 not be an optional suffix, but part of the instruction. To be
10416 compatible, we accept either. */
10417 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10418 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10420 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10421 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10422 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10423 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10424 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10425 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10426 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10427 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10428 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10429 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10430 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10431 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10433 /* The implementation of the FIX instruction is broken on some
10434 assemblers, in that it accepts a precision specifier as well as a
10435 rounding specifier, despite the fact that this is meaningless.
10436 To be more compatible, we accept it as well, though of course it
10437 does not set any bits. */
10438 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10439 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10440 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10441 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10442 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10443 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10444 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10445 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10446 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10447 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10448 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10449 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10450 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10452 /* Instructions that were new with the real FPA, call them V2. */
10453 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10454 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10455 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10456 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10457 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10458 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10460 /* VFP V1xD (single precision). */
10461 /* Moves and type conversions. */
10462 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10463 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_reg_from_sp
},
10464 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_from_reg
},
10465 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD
, do_empty
},
10466 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10467 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10468 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10469 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10470 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10471 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10472 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_reg_from_ctrl
},
10473 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_ctrl_from_reg
},
10475 /* Memory operations. */
10476 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldst
},
10477 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldst
},
10478 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
10479 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
10480 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
10481 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
10482 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
10483 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
10484 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
10485 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
10486 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
10487 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
10488 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
10489 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
10490 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
10491 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
10492 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
10493 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
10495 /* Monadic operations. */
10496 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10497 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10498 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10500 /* Dyadic operations. */
10501 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10502 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10503 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10504 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10505 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10506 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10507 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10508 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10509 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10512 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10513 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_compare_z
},
10514 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10515 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_compare_z
},
10517 /* VFP V1 (Double precision). */
10518 /* Moves and type conversions. */
10519 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10520 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
10521 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10522 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1
, do_vfp_dp_from_reg
},
10523 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1
, do_vfp_dp_from_reg
},
10524 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1
, do_vfp_reg_from_dp
},
10525 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1
, do_vfp_reg_from_dp
},
10526 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
10527 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
10528 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10529 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10530 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10531 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10533 /* Memory operations. */
10534 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1
, do_vfp_dp_ldst
},
10535 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1
, do_vfp_dp_ldst
},
10536 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
10537 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
10538 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
10539 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
10540 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
10541 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
10542 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
10543 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
10545 /* Monadic operations. */
10546 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10547 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10548 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10550 /* Dyadic operations. */
10551 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10552 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10553 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10554 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10555 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10556 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10557 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10558 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10559 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10562 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10563 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_compare_z
},
10564 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10565 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1
, do_vfp_dp_compare_z
},
10568 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2
, do_vfp_sp2_from_reg2
},
10569 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2
, do_vfp_reg2_from_sp2
},
10570 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2
, do_vfp_dp_from_reg2
},
10571 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2
, do_vfp_reg2_from_dp
},
10573 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
10574 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE
, do_xsc_mia
},
10575 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10576 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10577 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10578 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10579 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10580 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE
, do_xsc_mar
},
10581 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE
, do_xsc_mra
},
10583 /* Intel Wireless MMX technology instructions. */
10584 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
10585 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
10586 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
10587 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
10588 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
10589 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
10590 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
10591 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
10592 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
10593 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10594 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10595 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10596 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10597 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10598 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10599 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
10600 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
10601 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
10602 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmcr
},
10603 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_tmcrr
},
10604 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10605 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10606 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10607 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10608 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10609 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10610 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
10611 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
10612 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
10613 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmrc
},
10614 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_tmrrc
},
10615 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
10616 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
10617 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
10618 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10619 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10620 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10621 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10622 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10623 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10624 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10625 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10626 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10627 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10628 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10629 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10630 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_waligni
},
10631 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10632 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10633 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10634 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10635 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10636 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10637 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10638 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10639 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10640 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10641 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10642 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10643 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10644 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10645 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10646 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10647 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10648 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10649 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10650 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
10651 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
10652 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
10653 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
10654 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10655 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10656 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10657 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10658 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10659 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10660 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10661 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10662 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10663 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10664 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10665 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10666 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10667 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10668 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10669 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10670 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10671 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10672 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wmov
},
10673 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10674 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10675 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10676 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10677 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10678 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10679 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10680 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10681 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10682 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10683 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10684 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10685 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10686 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10687 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10688 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10689 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10690 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10691 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10692 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10693 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10694 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wshufh
},
10695 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10696 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10697 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10698 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10699 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10700 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10701 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10702 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10703 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10704 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10705 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10706 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10707 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10708 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10709 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10710 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10711 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10712 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10713 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
10714 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
10715 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
10716 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
10717 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10718 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10719 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10720 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10721 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10722 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10723 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10724 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10725 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10726 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10727 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10728 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10729 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10730 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10731 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10732 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10733 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10734 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10735 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10736 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10737 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10738 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10739 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10740 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10741 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10742 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10743 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10744 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10745 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wzero
},
10747 /* Cirrus Maverick instructions. */
10748 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_1
},
10749 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_2
},
10750 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_3
},
10751 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_4
},
10752 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_1
},
10753 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_2
},
10754 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_3
},
10755 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_4
},
10756 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK
, do_mav_binops_2a
},
10757 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1a
},
10758 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK
, do_mav_binops_2b
},
10759 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1b
},
10760 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK
, do_mav_binops_2b
},
10761 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1b
},
10762 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK
, do_mav_binops_2c
},
10763 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1c
},
10764 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK
, do_mav_binops_2c
},
10765 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1c
},
10766 {"cfmval32", 0xee200440, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
10767 {"cfmv32al", 0xee100440, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
10768 {"cfmvam32", 0xee200460, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
10769 {"cfmv32am", 0xee100460, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
10770 {"cfmvah32", 0xee200480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
10771 {"cfmv32ah", 0xee100480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
10772 {"cfmva32", 0xee2004a0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
10773 {"cfmv32a", 0xee1004a0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
10774 {"cfmva64", 0xee2004c0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3c
},
10775 {"cfmv64a", 0xee1004c0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3d
},
10776 {"cfmvsc32", 0xee2004e0, 8, ARM_CEXT_MAVERICK
, do_mav_dspsc_1
},
10777 {"cfmv32sc", 0xee1004e0, 8, ARM_CEXT_MAVERICK
, do_mav_dspsc_2
},
10778 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
10779 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
10780 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1f
},
10781 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1g
},
10782 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1h
},
10783 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1i
},
10784 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1j
},
10785 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1k
},
10786 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1l
},
10787 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1m
},
10788 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK
, do_mav_binops_1l
},
10789 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK
, do_mav_binops_1m
},
10790 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK
, do_mav_triple_4a
},
10791 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK
, do_mav_triple_4b
},
10792 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK
, do_mav_shift_1
},
10793 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK
, do_mav_shift_2
},
10794 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5a
},
10795 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5b
},
10796 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5c
},
10797 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5d
},
10798 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
10799 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
10800 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
10801 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
10802 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
10803 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
10804 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
10805 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
10806 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
10807 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
10808 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1n
},
10809 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1o
},
10810 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1n
},
10811 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1o
},
10812 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
10813 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
10814 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
10815 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
10816 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
10817 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
10818 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
10819 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
10820 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK
, do_mav_quad_6a
},
10821 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK
, do_mav_quad_6a
},
10822 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK
, do_mav_quad_6b
},
10823 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK
, do_mav_quad_6b
},
10826 /* Iterate over the base tables to create the instruction patterns. */
10829 build_arm_ops_hsh (void)
10833 static struct obstack insn_obstack
;
10835 obstack_begin (&insn_obstack
, 4000);
10837 for (i
= 0; i
< sizeof (insns
) / sizeof (struct asm_opcode
); i
++)
10839 const struct asm_opcode
*insn
= insns
+ i
;
10841 if (insn
->cond_offset
!= 0)
10843 /* Insn supports conditional execution. Build the varaints
10844 and insert them in the hash table. */
10845 for (j
= 0; j
< sizeof (conds
) / sizeof (struct asm_cond
); j
++)
10847 unsigned len
= strlen (insn
->template);
10848 struct asm_opcode
*new;
10851 new = obstack_alloc (&insn_obstack
, sizeof (struct asm_opcode
));
10852 /* All condition codes are two characters. */
10853 template = obstack_alloc (&insn_obstack
, len
+ 3);
10855 strncpy (template, insn
->template, insn
->cond_offset
);
10856 strcpy (template + insn
->cond_offset
, conds
[j
].template);
10857 if (len
> insn
->cond_offset
)
10858 strcpy (template + insn
->cond_offset
+ 2,
10859 insn
->template + insn
->cond_offset
);
10860 new->template = template;
10861 new->cond_offset
= 0;
10862 new->variant
= insn
->variant
;
10863 new->parms
= insn
->parms
;
10864 new->value
= (insn
->value
& ~COND_MASK
) | conds
[j
].value
;
10866 hash_insert (arm_ops_hsh
, new->template, (PTR
) new);
10869 /* Finally, insert the unconditional insn in the table directly;
10870 no need to build a copy. */
10871 hash_insert (arm_ops_hsh
, insn
->template, (PTR
) insn
);
10876 static const struct thumb_opcode tinsns
[] =
10878 /* Thumb v1 (ARMv4T). */
10879 {"adc", 0x4140, 2, ARM_EXT_V4T
, do_t_arit
},
10880 {"add", 0x0000, 2, ARM_EXT_V4T
, do_t_add
},
10881 {"and", 0x4000, 2, ARM_EXT_V4T
, do_t_arit
},
10882 {"asr", 0x0000, 2, ARM_EXT_V4T
, do_t_asr
},
10883 {"b", T_OPCODE_BRANCH
, 2, ARM_EXT_V4T
, do_t_branch12
},
10884 {"beq", 0xd0fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10885 {"bne", 0xd1fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10886 {"bcs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10887 {"bhs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10888 {"bcc", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10889 {"bul", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10890 {"blo", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10891 {"bmi", 0xd4fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10892 {"bpl", 0xd5fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10893 {"bvs", 0xd6fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10894 {"bvc", 0xd7fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10895 {"bhi", 0xd8fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10896 {"bls", 0xd9fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10897 {"bge", 0xdafe, 2, ARM_EXT_V4T
, do_t_branch9
},
10898 {"blt", 0xdbfe, 2, ARM_EXT_V4T
, do_t_branch9
},
10899 {"bgt", 0xdcfe, 2, ARM_EXT_V4T
, do_t_branch9
},
10900 {"ble", 0xddfe, 2, ARM_EXT_V4T
, do_t_branch9
},
10901 {"bal", 0xdefe, 2, ARM_EXT_V4T
, do_t_branch9
},
10902 {"bic", 0x4380, 2, ARM_EXT_V4T
, do_t_arit
},
10903 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T
, do_t_branch23
},
10904 {"bx", 0x4700, 2, ARM_EXT_V4T
, do_t_bx
},
10905 {"cmn", T_OPCODE_CMN
, 2, ARM_EXT_V4T
, do_t_arit
},
10906 {"cmp", 0x0000, 2, ARM_EXT_V4T
, do_t_compare
},
10907 {"eor", 0x4040, 2, ARM_EXT_V4T
, do_t_arit
},
10908 {"ldmia", 0xc800, 2, ARM_EXT_V4T
, do_t_ldmstm
},
10909 {"ldr", 0x0000, 2, ARM_EXT_V4T
, do_t_ldr
},
10910 {"ldrb", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrb
},
10911 {"ldrh", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrh
},
10912 {"ldrsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
10913 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
10914 {"ldsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
10915 {"ldsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
10916 {"lsl", 0x0000, 2, ARM_EXT_V4T
, do_t_lsl
},
10917 {"lsr", 0x0000, 2, ARM_EXT_V4T
, do_t_lsr
},
10918 {"mov", 0x0000, 2, ARM_EXT_V4T
, do_t_mov
},
10919 {"mul", T_OPCODE_MUL
, 2, ARM_EXT_V4T
, do_t_arit
},
10920 {"mvn", T_OPCODE_MVN
, 2, ARM_EXT_V4T
, do_t_arit
},
10921 {"neg", T_OPCODE_NEG
, 2, ARM_EXT_V4T
, do_t_arit
},
10922 {"orr", 0x4300, 2, ARM_EXT_V4T
, do_t_arit
},
10923 {"pop", 0xbc00, 2, ARM_EXT_V4T
, do_t_push_pop
},
10924 {"push", 0xb400, 2, ARM_EXT_V4T
, do_t_push_pop
},
10925 {"ror", 0x41c0, 2, ARM_EXT_V4T
, do_t_arit
},
10926 {"sbc", 0x4180, 2, ARM_EXT_V4T
, do_t_arit
},
10927 {"stmia", 0xc000, 2, ARM_EXT_V4T
, do_t_ldmstm
},
10928 {"str", 0x0000, 2, ARM_EXT_V4T
, do_t_str
},
10929 {"strb", 0x0000, 2, ARM_EXT_V4T
, do_t_strb
},
10930 {"strh", 0x0000, 2, ARM_EXT_V4T
, do_t_strh
},
10931 {"swi", 0xdf00, 2, ARM_EXT_V4T
, do_t_swi
},
10932 {"sub", 0x0000, 2, ARM_EXT_V4T
, do_t_sub
},
10933 {"tst", T_OPCODE_TST
, 2, ARM_EXT_V4T
, do_t_arit
},
10935 {"adr", 0x0000, 2, ARM_EXT_V4T
, do_t_adr
},
10936 {"nop", 0x46C0, 2, ARM_EXT_V4T
, do_t_nop
}, /* mov r8,r8 */
10937 /* Thumb v2 (ARMv5T). */
10938 {"blx", 0, 0, ARM_EXT_V5T
, do_t_blx
},
10939 {"bkpt", 0xbe00, 2, ARM_EXT_V5T
, do_t_bkpt
},
10942 {"cpsie", 0xb660, 2, ARM_EXT_V6
, do_t_cps
},
10943 {"cpsid", 0xb670, 2, ARM_EXT_V6
, do_t_cps
},
10944 {"cpy", 0x4600, 2, ARM_EXT_V6
, do_t_cpy
},
10945 {"rev", 0xba00, 2, ARM_EXT_V6
, do_t_arit
},
10946 {"rev16", 0xba40, 2, ARM_EXT_V6
, do_t_arit
},
10947 {"revsh", 0xbac0, 2, ARM_EXT_V6
, do_t_arit
},
10948 {"setend", 0xb650, 2, ARM_EXT_V6
, do_t_setend
},
10949 {"sxth", 0xb200, 2, ARM_EXT_V6
, do_t_arit
},
10950 {"sxtb", 0xb240, 2, ARM_EXT_V6
, do_t_arit
},
10951 {"uxth", 0xb280, 2, ARM_EXT_V6
, do_t_arit
},
10952 {"uxtb", 0xb2c0, 2, ARM_EXT_V6
, do_t_arit
},
10955 {"sev", 0xbf40, 2, ARM_EXT_V6K
, do_empty
},
10956 {"wfe", 0xbf20, 2, ARM_EXT_V6K
, do_empty
},
10957 {"wfi", 0xbf30, 2, ARM_EXT_V6K
, do_empty
},
10958 {"yield", 0xbf10, 2, ARM_EXT_V6K
, do_empty
},
10967 if ( (arm_ops_hsh
= hash_new ()) == NULL
10968 || (arm_tops_hsh
= hash_new ()) == NULL
10969 || (arm_cond_hsh
= hash_new ()) == NULL
10970 || (arm_shift_hsh
= hash_new ()) == NULL
10971 || (arm_psr_hsh
= hash_new ()) == NULL
)
10972 as_fatal (_("virtual memory exhausted"));
10974 build_arm_ops_hsh ();
10975 for (i
= 0; i
< sizeof (tinsns
) / sizeof (struct thumb_opcode
); i
++)
10976 hash_insert (arm_tops_hsh
, tinsns
[i
].template, (PTR
) (tinsns
+ i
));
10977 for (i
= 0; i
< sizeof (conds
) / sizeof (struct asm_cond
); i
++)
10978 hash_insert (arm_cond_hsh
, conds
[i
].template, (PTR
) (conds
+ i
));
10979 for (i
= 0; i
< sizeof (shift_names
) / sizeof (struct asm_shift_name
); i
++)
10980 hash_insert (arm_shift_hsh
, shift_names
[i
].name
, (PTR
) (shift_names
+ i
));
10981 for (i
= 0; i
< sizeof (psrs
) / sizeof (struct asm_psr
); i
++)
10982 hash_insert (arm_psr_hsh
, psrs
[i
].template, (PTR
) (psrs
+ i
));
10984 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
10985 build_reg_hsh (all_reg_maps
+ i
);
10987 set_constant_flonums ();
10989 /* Set the cpu variant based on the command-line options. We prefer
10990 -mcpu= over -march= if both are set (as for GCC); and we prefer
10991 -mfpu= over any other way of setting the floating point unit.
10992 Use of legacy options with new options are faulted. */
10993 if (legacy_cpu
!= -1)
10995 if (mcpu_cpu_opt
!= -1 || march_cpu_opt
!= -1)
10996 as_bad (_("use of old and new-style options to set CPU type"));
10998 mcpu_cpu_opt
= legacy_cpu
;
11000 else if (mcpu_cpu_opt
== -1)
11001 mcpu_cpu_opt
= march_cpu_opt
;
11003 if (legacy_fpu
!= -1)
11005 if (mfpu_opt
!= -1)
11006 as_bad (_("use of old and new-style options to set FPU type"));
11008 mfpu_opt
= legacy_fpu
;
11010 else if (mfpu_opt
== -1)
11012 #if !(defined (TE_LINUX) || defined (TE_NetBSD) || defined (TE_VXWORKS))
11013 /* Some environments specify a default FPU. If they don't, infer it
11014 from the processor. */
11015 if (mcpu_fpu_opt
!= -1)
11016 mfpu_opt
= mcpu_fpu_opt
;
11018 mfpu_opt
= march_fpu_opt
;
11020 mfpu_opt
= FPU_DEFAULT
;
11024 if (mfpu_opt
== -1)
11026 if (mcpu_cpu_opt
== -1)
11027 mfpu_opt
= FPU_DEFAULT
;
11028 else if (mcpu_cpu_opt
& ARM_EXT_V5
)
11029 mfpu_opt
= FPU_ARCH_VFP_V2
;
11031 mfpu_opt
= FPU_ARCH_FPA
;
11034 if (mcpu_cpu_opt
== -1)
11035 mcpu_cpu_opt
= CPU_DEFAULT
;
11037 cpu_variant
= mcpu_cpu_opt
| mfpu_opt
;
11039 #if defined OBJ_COFF || defined OBJ_ELF
11041 unsigned int flags
= 0;
11043 #if defined OBJ_ELF
11044 flags
= meabi_flags
;
11046 switch (meabi_flags
)
11048 case EF_ARM_EABI_UNKNOWN
:
11050 /* Set the flags in the private structure. */
11051 if (uses_apcs_26
) flags
|= F_APCS26
;
11052 if (support_interwork
) flags
|= F_INTERWORK
;
11053 if (uses_apcs_float
) flags
|= F_APCS_FLOAT
;
11054 if (pic_code
) flags
|= F_PIC
;
11055 if ((cpu_variant
& FPU_ANY
) == FPU_NONE
11056 || (cpu_variant
& FPU_ANY
) == FPU_ARCH_VFP
) /* VFP layout only. */
11057 flags
|= F_SOFT_FLOAT
;
11059 switch (mfloat_abi_opt
)
11061 case ARM_FLOAT_ABI_SOFT
:
11062 case ARM_FLOAT_ABI_SOFTFP
:
11063 flags
|= F_SOFT_FLOAT
;
11066 case ARM_FLOAT_ABI_HARD
:
11067 if (flags
& F_SOFT_FLOAT
)
11068 as_bad (_("hard-float conflicts with specified fpu"));
11072 /* Using VFP conventions (even if soft-float). */
11073 if (cpu_variant
& FPU_VFP_EXT_NONE
)
11074 flags
|= F_VFP_FLOAT
;
11076 #if defined OBJ_ELF
11077 if (cpu_variant
& FPU_ARCH_MAVERICK
)
11078 flags
|= EF_ARM_MAVERICK_FLOAT
;
11081 case EF_ARM_EABI_VER4
:
11082 /* No additional flags to set. */
11089 bfd_set_private_flags (stdoutput
, flags
);
11091 /* We have run out flags in the COFF header to encode the
11092 status of ATPCS support, so instead we create a dummy,
11093 empty, debug section called .arm.atpcs. */
11098 sec
= bfd_make_section (stdoutput
, ".arm.atpcs");
11102 bfd_set_section_flags
11103 (stdoutput
, sec
, SEC_READONLY
| SEC_DEBUGGING
/* | SEC_HAS_CONTENTS */);
11104 bfd_set_section_size (stdoutput
, sec
, 0);
11105 bfd_set_section_contents (stdoutput
, sec
, NULL
, 0, 0);
11111 /* Record the CPU type as well. */
11112 switch (cpu_variant
& ARM_CPU_MASK
)
11115 mach
= bfd_mach_arm_2
;
11118 case ARM_3
: /* Also ARM_250. */
11119 mach
= bfd_mach_arm_2a
;
11122 case ARM_6
: /* Also ARM_7. */
11123 mach
= bfd_mach_arm_3
;
11127 mach
= bfd_mach_arm_unknown
;
11131 /* Catch special cases. */
11132 if (cpu_variant
& ARM_CEXT_IWMMXT
)
11133 mach
= bfd_mach_arm_iWMMXt
;
11134 else if (cpu_variant
& ARM_CEXT_XSCALE
)
11135 mach
= bfd_mach_arm_XScale
;
11136 else if (cpu_variant
& ARM_CEXT_MAVERICK
)
11137 mach
= bfd_mach_arm_ep9312
;
11138 else if (cpu_variant
& ARM_EXT_V5E
)
11139 mach
= bfd_mach_arm_5TE
;
11140 else if (cpu_variant
& ARM_EXT_V5
)
11142 if (cpu_variant
& ARM_EXT_V4T
)
11143 mach
= bfd_mach_arm_5T
;
11145 mach
= bfd_mach_arm_5
;
11147 else if (cpu_variant
& ARM_EXT_V4
)
11149 if (cpu_variant
& ARM_EXT_V4T
)
11150 mach
= bfd_mach_arm_4T
;
11152 mach
= bfd_mach_arm_4
;
11154 else if (cpu_variant
& ARM_EXT_V3M
)
11155 mach
= bfd_mach_arm_3M
;
11157 bfd_set_arch_mach (stdoutput
, TARGET_ARCH
, mach
);
11160 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11161 for use in the a.out file, and stores them in the array pointed to by buf.
11162 This knows about the endian-ness of the target machine and does
11163 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11164 2 (short) and 4 (long) Floating numbers are put out as a series of
11165 LITTLENUMS (shorts, here at least). */
11168 md_number_to_chars (char * buf
, valueT val
, int n
)
11170 if (target_big_endian
)
11171 number_to_chars_bigendian (buf
, val
, n
);
11173 number_to_chars_littleendian (buf
, val
, n
);
11177 md_chars_to_number (char * buf
, int n
)
11180 unsigned char * where
= (unsigned char *) buf
;
11182 if (target_big_endian
)
11187 result
|= (*where
++ & 255);
11195 result
|= (where
[n
] & 255);
11202 /* Turn a string in input_line_pointer into a floating point constant
11203 of type TYPE, and store the appropriate bytes in *LITP. The number
11204 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11205 returned, or NULL on OK.
11207 Note that fp constants aren't represent in the normal way on the ARM.
11208 In big endian mode, things are as expected. However, in little endian
11209 mode fp constants are big-endian word-wise, and little-endian byte-wise
11210 within the words. For example, (double) 1.1 in big endian mode is
11211 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11212 the byte sequence 99 99 f1 3f 9a 99 99 99.
11214 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11217 md_atof (int type
, char * litP
, int * sizeP
)
11220 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
11252 return _("bad call to MD_ATOF()");
11255 t
= atof_ieee (input_line_pointer
, type
, words
);
11257 input_line_pointer
= t
;
11260 if (target_big_endian
)
11262 for (i
= 0; i
< prec
; i
++)
11264 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
11270 if (cpu_variant
& FPU_ARCH_VFP
)
11271 for (i
= prec
- 1; i
>= 0; i
--)
11273 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
11277 /* For a 4 byte float the order of elements in `words' is 1 0.
11278 For an 8 byte float the order is 1 0 3 2. */
11279 for (i
= 0; i
< prec
; i
+= 2)
11281 md_number_to_chars (litP
, (valueT
) words
[i
+ 1], 2);
11282 md_number_to_chars (litP
+ 2, (valueT
) words
[i
], 2);
11290 /* The knowledge of the PC's pipeline offset is built into the insns
11294 md_pcrel_from (fixS
* fixP
)
11297 && S_GET_SEGMENT (fixP
->fx_addsy
) == undefined_section
11298 && fixP
->fx_subsy
== NULL
)
11301 if (fixP
->fx_pcrel
&& (fixP
->fx_r_type
== BFD_RELOC_ARM_THUMB_ADD
))
11303 /* PC relative addressing on the Thumb is slightly odd
11304 as the bottom two bits of the PC are forced to zero
11305 for the calculation. */
11306 return (fixP
->fx_where
+ fixP
->fx_frag
->fr_address
) & ~3;
11310 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
11311 so we un-adjust here to compensate for the accommodation. */
11312 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
+ 8;
11314 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
11318 /* Round up a section size to the appropriate boundary. */
11321 md_section_align (segT segment ATTRIBUTE_UNUSED
,
11327 /* Round all sects to multiple of 4. */
11328 return (size
+ 3) & ~3;
11332 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
11333 Otherwise we have no need to default values of symbols. */
11336 md_undefined_symbol (char * name ATTRIBUTE_UNUSED
)
11339 if (name
[0] == '_' && name
[1] == 'G'
11340 && streq (name
, GLOBAL_OFFSET_TABLE_NAME
))
11344 if (symbol_find (name
))
11345 as_bad ("GOT already in the symbol table");
11347 GOT_symbol
= symbol_new (name
, undefined_section
,
11348 (valueT
) 0, & zero_address_frag
);
11359 md_apply_fix3 (fixS
* fixP
,
11363 offsetT value
= * valP
;
11365 unsigned int newimm
;
11366 unsigned long temp
;
11368 char * buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
11369 arm_fix_data
* arm_data
= (arm_fix_data
*) fixP
->tc_fix_data
;
11371 assert (fixP
->fx_r_type
<= BFD_RELOC_UNUSED
);
11373 /* Note whether this will delete the relocation. */
11374 if (fixP
->fx_addsy
== 0 && !fixP
->fx_pcrel
)
11377 /* If this symbol is in a different section then we need to leave it for
11378 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
11379 so we have to undo it's effects here. */
11380 if (fixP
->fx_pcrel
)
11382 if (fixP
->fx_addsy
!= NULL
11383 && S_IS_DEFINED (fixP
->fx_addsy
)
11384 && S_GET_SEGMENT (fixP
->fx_addsy
) != seg
)
11385 value
+= md_pcrel_from (fixP
);
11388 /* Remember value for emit_reloc. */
11389 fixP
->fx_addnumber
= value
;
11391 switch (fixP
->fx_r_type
)
11393 case BFD_RELOC_NONE
:
11394 /* This will need to go in the object file. */
11398 case BFD_RELOC_ARM_IMMEDIATE
:
11399 /* We claim that this fixup has been processed here,
11400 even if in fact we generate an error because we do
11401 not have a reloc for it, so tc_gen_reloc will reject it. */
11405 && ! S_IS_DEFINED (fixP
->fx_addsy
))
11407 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11408 _("undefined symbol %s used as an immediate value"),
11409 S_GET_NAME (fixP
->fx_addsy
));
11413 newimm
= validate_immediate (value
);
11414 temp
= md_chars_to_number (buf
, INSN_SIZE
);
11416 /* If the instruction will fail, see if we can fix things up by
11417 changing the opcode. */
11418 if (newimm
== (unsigned int) FAIL
11419 && (newimm
= negate_data_op (&temp
, value
)) == (unsigned int) FAIL
)
11421 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11422 _("invalid constant (%lx) after fixup"),
11423 (unsigned long) value
);
11427 newimm
|= (temp
& 0xfffff000);
11428 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
11431 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
11433 unsigned int highpart
= 0;
11434 unsigned int newinsn
= 0xe1a00000; /* nop. */
11436 newimm
= validate_immediate (value
);
11437 temp
= md_chars_to_number (buf
, INSN_SIZE
);
11439 /* If the instruction will fail, see if we can fix things up by
11440 changing the opcode. */
11441 if (newimm
== (unsigned int) FAIL
11442 && (newimm
= negate_data_op (& temp
, value
)) == (unsigned int) FAIL
)
11444 /* No ? OK - try using two ADD instructions to generate
11446 newimm
= validate_immediate_twopart (value
, & highpart
);
11448 /* Yes - then make sure that the second instruction is
11450 if (newimm
!= (unsigned int) FAIL
)
11452 /* Still No ? Try using a negated value. */
11453 else if ((newimm
= validate_immediate_twopart (- value
, & highpart
)) != (unsigned int) FAIL
)
11454 temp
= newinsn
= (temp
& OPCODE_MASK
) | OPCODE_SUB
<< DATA_OP_SHIFT
;
11455 /* Otherwise - give up. */
11458 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11459 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
11464 /* Replace the first operand in the 2nd instruction (which
11465 is the PC) with the destination register. We have
11466 already added in the PC in the first instruction and we
11467 do not want to do it again. */
11468 newinsn
&= ~ 0xf0000;
11469 newinsn
|= ((newinsn
& 0x0f000) << 4);
11472 newimm
|= (temp
& 0xfffff000);
11473 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
11475 highpart
|= (newinsn
& 0xfffff000);
11476 md_number_to_chars (buf
+ INSN_SIZE
, (valueT
) highpart
, INSN_SIZE
);
11480 case BFD_RELOC_ARM_OFFSET_IMM
:
11486 if (validate_offset_imm (value
, 0) == FAIL
)
11488 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11489 _("bad immediate value for offset (%ld)"),
11494 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11495 newval
&= 0xff7ff000;
11496 newval
|= value
| (sign
? INDEX_UP
: 0);
11497 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11500 case BFD_RELOC_ARM_OFFSET_IMM8
:
11501 case BFD_RELOC_ARM_HWLITERAL
:
11507 if (validate_offset_imm (value
, 1) == FAIL
)
11509 if (fixP
->fx_r_type
== BFD_RELOC_ARM_HWLITERAL
)
11510 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11511 _("invalid literal constant: pool needs to be closer"));
11513 as_bad (_("bad immediate value for half-word offset (%ld)"),
11518 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11519 newval
&= 0xff7ff0f0;
11520 newval
|= ((value
>> 4) << 8) | (value
& 0xf) | (sign
? INDEX_UP
: 0);
11521 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11524 case BFD_RELOC_ARM_LITERAL
:
11530 if (validate_offset_imm (value
, 0) == FAIL
)
11532 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11533 _("invalid literal constant: pool needs to be closer"));
11537 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11538 newval
&= 0xff7ff000;
11539 newval
|= value
| (sign
? INDEX_UP
: 0);
11540 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11543 case BFD_RELOC_ARM_SHIFT_IMM
:
11544 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11545 if (((unsigned long) value
) > 32
11547 && (((newval
& 0x60) == 0) || (newval
& 0x60) == 0x60)))
11549 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11550 _("shift expression is too large"));
11555 /* Shifts of zero must be done as lsl. */
11557 else if (value
== 32)
11559 newval
&= 0xfffff07f;
11560 newval
|= (value
& 0x1f) << 7;
11561 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11564 case BFD_RELOC_ARM_SMI
:
11565 if (((unsigned long) value
) > 0xffff)
11566 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11567 _("invalid smi expression"));
11568 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xfff000f0;
11569 newval
|= (value
& 0xf) | ((value
& 0xfff0) << 4);
11570 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11573 case BFD_RELOC_ARM_SWI
:
11574 if (arm_data
->thumb_mode
)
11576 if (((unsigned long) value
) > 0xff)
11577 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11578 _("invalid swi expression"));
11579 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xff00;
11581 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11585 if (((unsigned long) value
) > 0x00ffffff)
11586 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11587 _("invalid swi expression"));
11588 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff000000;
11590 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11594 case BFD_RELOC_ARM_MULTI
:
11595 if (((unsigned long) value
) > 0xffff)
11596 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11597 _("invalid expression in load/store multiple"));
11598 newval
= value
| md_chars_to_number (buf
, INSN_SIZE
);
11599 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11602 case BFD_RELOC_ARM_PCREL_BRANCH
:
11603 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11605 /* Sign-extend a 24-bit number. */
11606 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
11609 value
= fixP
->fx_offset
;
11612 /* We are going to store value (shifted right by two) in the
11613 instruction, in a 24 bit, signed field. Thus we need to check
11614 that none of the top 8 bits of the shifted value (top 7 bits of
11615 the unshifted, unsigned value) are set, or that they are all set. */
11616 if ((value
& ~ ((offsetT
) 0x1ffffff)) != 0
11617 && ((value
& ~ ((offsetT
) 0x1ffffff)) != ~ ((offsetT
) 0x1ffffff)))
11620 /* Normally we would be stuck at this point, since we cannot store
11621 the absolute address that is the destination of the branch in the
11622 24 bits of the branch instruction. If however, we happen to know
11623 that the destination of the branch is in the same section as the
11624 branch instruction itself, then we can compute the relocation for
11625 ourselves and not have to bother the linker with it.
11627 FIXME: The test for OBJ_ELF is only here because I have not
11628 worked out how to do this for OBJ_COFF. */
11629 if (fixP
->fx_addsy
!= NULL
11630 && S_IS_DEFINED (fixP
->fx_addsy
)
11631 && S_GET_SEGMENT (fixP
->fx_addsy
) == seg
)
11633 /* Get pc relative value to go into the branch. */
11636 /* Permit a backward branch provided that enough bits
11637 are set. Allow a forwards branch, provided that
11638 enough bits are clear. */
11639 if ( (value
& ~ ((offsetT
) 0x1ffffff)) == ~ ((offsetT
) 0x1ffffff)
11640 || (value
& ~ ((offsetT
) 0x1ffffff)) == 0)
11644 if (! fixP
->fx_done
)
11646 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11647 _("GAS can't handle same-section branch dest >= 0x04000000"));
11651 value
+= SEXT24 (newval
);
11653 if ( (value
& ~ ((offsetT
) 0xffffff)) != 0
11654 && ((value
& ~ ((offsetT
) 0xffffff)) != ~ ((offsetT
) 0xffffff)))
11655 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11656 _("out of range branch"));
11658 if (seg
->use_rela_p
&& !fixP
->fx_done
)
11660 /* Must unshift the value before storing it in the addend. */
11663 fixP
->fx_offset
= value
;
11665 fixP
->fx_addnumber
= value
;
11666 newval
= newval
& 0xff000000;
11669 newval
= (value
& 0x00ffffff) | (newval
& 0xff000000);
11670 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11673 case BFD_RELOC_ARM_PCREL_BLX
:
11676 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11679 value
= fixP
->fx_offset
;
11681 hbit
= (value
>> 1) & 1;
11682 value
= (value
>> 2) & 0x00ffffff;
11683 value
= (value
+ (newval
& 0x00ffffff)) & 0x00ffffff;
11685 if (seg
->use_rela_p
&& !fixP
->fx_done
)
11687 /* Must sign-extend and unshift the value before storing
11688 it in the addend. */
11689 value
= SEXT24 (value
);
11690 value
= (value
<< 2) | hbit
;
11692 fixP
->fx_offset
= value
;
11694 fixP
->fx_addnumber
= value
;
11695 newval
= newval
& 0xfe000000;
11698 newval
= value
| (newval
& 0xfe000000) | (hbit
<< 24);
11699 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11703 case BFD_RELOC_THUMB_PCREL_BRANCH9
: /* Conditional branch. */
11704 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11706 addressT diff
= (newval
& 0xff) << 1;
11711 if ((value
& ~0xff) && ((value
& ~0xff) != ~0xff))
11712 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11713 _("branch out of range"));
11714 if (seg
->use_rela_p
&& !fixP
->fx_done
)
11717 fixP
->fx_offset
= value
;
11719 fixP
->fx_addnumber
= value
;
11720 newval
= newval
& 0xff00;
11723 newval
= (newval
& 0xff00) | ((value
& 0x1ff) >> 1);
11725 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11728 case BFD_RELOC_THUMB_PCREL_BRANCH12
: /* Unconditional branch. */
11729 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11731 addressT diff
= (newval
& 0x7ff) << 1;
11736 if ((value
& ~0x7ff) && ((value
& ~0x7ff) != ~0x7ff))
11737 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11738 _("branch out of range"));
11739 if (seg
->use_rela_p
&& !fixP
->fx_done
)
11742 fixP
->fx_offset
= value
;
11744 fixP
->fx_addnumber
= value
;
11745 newval
= newval
& 0xf800;
11748 newval
= (newval
& 0xf800) | ((value
& 0xfff) >> 1);
11750 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11753 case BFD_RELOC_THUMB_PCREL_BLX
:
11754 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
11759 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11760 newval2
= md_chars_to_number (buf
+ THUMB_SIZE
, THUMB_SIZE
);
11761 diff
= ((newval
& 0x7ff) << 12) | ((newval2
& 0x7ff) << 1);
11762 if (diff
& 0x400000)
11765 value
= fixP
->fx_offset
;
11769 if ((value
& ~0x3fffff) && ((value
& ~0x3fffff) != ~0x3fffff))
11770 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11771 _("branch with link out of range"));
11773 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
)
11774 /* For a BLX instruction, make sure that the relocation is rounded up
11775 to a word boundary. This follows the semantics of the instruction
11776 which specifies that bit 1 of the target address will come from bit
11777 1 of the base address. */
11778 value
= (value
+ 1) & ~ 1;
11780 if (seg
->use_rela_p
&& !fixP
->fx_done
)
11783 fixP
->fx_offset
= value
;
11785 fixP
->fx_addnumber
= value
;
11786 newval
= newval
& 0xf800;
11787 newval2
= newval2
& 0xf800;
11791 newval
= (newval
& 0xf800) | ((value
& 0x7fffff) >> 12);
11792 newval2
= (newval2
& 0xf800) | ((value
& 0xfff) >> 1);
11794 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11795 md_number_to_chars (buf
+ THUMB_SIZE
, newval2
, THUMB_SIZE
);
11800 if (seg
->use_rela_p
&& !fixP
->fx_done
)
11802 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11803 md_number_to_chars (buf
, value
, 1);
11807 value
= fixP
->fx_offset
;
11808 md_number_to_chars (buf
, value
, 1);
11814 if (seg
->use_rela_p
&& !fixP
->fx_done
)
11816 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11817 md_number_to_chars (buf
, value
, 2);
11821 value
= fixP
->fx_offset
;
11822 md_number_to_chars (buf
, value
, 2);
11828 case BFD_RELOC_ARM_GOT32
:
11829 case BFD_RELOC_ARM_GOTOFF
:
11830 case BFD_RELOC_ARM_TARGET2
:
11831 if (seg
->use_rela_p
&& !fixP
->fx_done
)
11833 md_number_to_chars (buf
, 0, 4);
11837 case BFD_RELOC_RVA
:
11839 case BFD_RELOC_ARM_TARGET1
:
11840 case BFD_RELOC_ARM_ROSEGREL32
:
11841 case BFD_RELOC_ARM_SBREL32
:
11842 case BFD_RELOC_32_PCREL
:
11843 if (seg
->use_rela_p
&& !fixP
->fx_done
)
11845 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11846 md_number_to_chars (buf
, value
, 4);
11850 value
= fixP
->fx_offset
;
11851 md_number_to_chars (buf
, value
, 4);
11857 case BFD_RELOC_ARM_PREL31
:
11858 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11860 newval
= md_chars_to_number (buf
, 4) & 0x80000000;
11861 if ((value
^ (value
>> 1)) & 0x40000000)
11863 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11864 _("rel31 relocation overflow"));
11866 newval
|= value
& 0x7fffffff;
11867 md_number_to_chars (buf
, newval
, 4);
11871 case BFD_RELOC_ARM_PLT32
:
11872 /* It appears the instruction is fully prepared at this point. */
11876 case BFD_RELOC_ARM_CP_OFF_IMM
:
11878 if (value
< -1023 || value
> 1023 || (value
& 3))
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
>> 2) | (sign
? INDEX_UP
: 0);
11885 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11888 case BFD_RELOC_ARM_CP_OFF_IMM_S2
:
11890 if (value
< -255 || value
> 255)
11891 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11892 _("Illegal value for co-processor offset"));
11895 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
11896 newval
|= value
| (sign
? INDEX_UP
: 0);
11897 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11900 case BFD_RELOC_ARM_THUMB_OFFSET
:
11901 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11902 /* Exactly what ranges, and where the offset is inserted depends
11903 on the type of instruction, we can establish this from the
11905 switch (newval
>> 12)
11907 case 4: /* PC load. */
11908 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
11909 forced to zero for these loads, so we will need to round
11910 up the offset if the instruction address is not word
11911 aligned (since the final address produced must be, and
11912 we can only describe word-aligned immediate offsets). */
11914 if ((fixP
->fx_frag
->fr_address
+ fixP
->fx_where
+ value
) & 3)
11915 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11916 _("invalid offset, target not word aligned (0x%08X)"),
11917 (unsigned int) (fixP
->fx_frag
->fr_address
11918 + fixP
->fx_where
+ value
));
11920 if ((value
+ 2) & ~0x3fe)
11921 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11922 _("invalid offset, value too big (0x%08lX)"),
11925 /* Round up, since pc will be rounded down. */
11926 newval
|= (value
+ 2) >> 2;
11929 case 9: /* SP load/store. */
11930 if (value
& ~0x3fc)
11931 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11932 _("invalid offset, value too big (0x%08lX)"),
11934 newval
|= value
>> 2;
11937 case 6: /* Word load/store. */
11939 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11940 _("invalid offset, value too big (0x%08lX)"),
11942 newval
|= value
<< 4; /* 6 - 2. */
11945 case 7: /* Byte load/store. */
11947 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11948 _("invalid offset, value too big (0x%08lX)"),
11950 newval
|= value
<< 6;
11953 case 8: /* Halfword load/store. */
11955 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11956 _("invalid offset, value too big (0x%08lX)"),
11958 newval
|= value
<< 5; /* 6 - 1. */
11962 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11963 "Unable to process relocation for thumb opcode: %lx",
11964 (unsigned long) newval
);
11967 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11970 case BFD_RELOC_ARM_THUMB_ADD
:
11971 /* This is a complicated relocation, since we use it for all of
11972 the following immediate relocations:
11976 9bit ADD/SUB SP word-aligned
11977 10bit ADD PC/SP word-aligned
11979 The type of instruction being processed is encoded in the
11986 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11988 int rd
= (newval
>> 4) & 0xf;
11989 int rs
= newval
& 0xf;
11990 int subtract
= newval
& 0x8000;
11994 if (value
& ~0x1fc)
11995 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11996 _("invalid immediate for stack address calculation"));
11997 newval
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
11998 newval
|= value
>> 2;
12000 else if (rs
== REG_PC
|| rs
== REG_SP
)
12004 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12005 _("invalid immediate for address calculation (value = 0x%08lX)"),
12006 (unsigned long) value
);
12007 newval
= (rs
== REG_PC
? T_OPCODE_ADD_PC
: T_OPCODE_ADD_SP
);
12009 newval
|= value
>> 2;
12014 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12015 _("invalid 8bit immediate"));
12016 newval
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
12017 newval
|= (rd
<< 8) | value
;
12022 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12023 _("invalid 3bit immediate"));
12024 newval
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
12025 newval
|= rd
| (rs
<< 3) | (value
<< 6);
12028 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12031 case BFD_RELOC_ARM_THUMB_IMM
:
12032 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12033 switch (newval
>> 11)
12035 case 0x04: /* 8bit immediate MOV. */
12036 case 0x05: /* 8bit immediate CMP. */
12037 if (value
< 0 || value
> 255)
12038 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12039 _("invalid immediate: %ld is too large"),
12047 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12050 case BFD_RELOC_ARM_THUMB_SHIFT
:
12051 /* 5bit shift value (0..31). */
12052 if (value
< 0 || value
> 31)
12053 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12054 _("illegal Thumb shift value: %ld"), (long) value
);
12055 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xf03f;
12056 newval
|= value
<< 6;
12057 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12060 case BFD_RELOC_VTABLE_INHERIT
:
12061 case BFD_RELOC_VTABLE_ENTRY
:
12065 case BFD_RELOC_UNUSED
:
12067 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12068 _("bad relocation fixup type (%d)"), fixP
->fx_r_type
);
12072 /* Translate internal representation of relocation info to BFD target
12076 tc_gen_reloc (asection
* section ATTRIBUTE_UNUSED
,
12080 bfd_reloc_code_real_type code
;
12082 reloc
= xmalloc (sizeof (arelent
));
12084 reloc
->sym_ptr_ptr
= xmalloc (sizeof (asymbol
*));
12085 *reloc
->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
12086 reloc
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
12088 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12090 if (fixp
->fx_pcrel
== 0)
12091 reloc
->addend
= fixp
->fx_offset
;
12093 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
12094 #else /* OBJ_ELF */
12095 reloc
->addend
= fixp
->fx_offset
;
12098 switch (fixp
->fx_r_type
)
12101 if (fixp
->fx_pcrel
)
12103 code
= BFD_RELOC_8_PCREL
;
12108 if (fixp
->fx_pcrel
)
12110 code
= BFD_RELOC_16_PCREL
;
12115 if (fixp
->fx_pcrel
)
12117 code
= BFD_RELOC_32_PCREL
;
12121 case BFD_RELOC_NONE
:
12122 case BFD_RELOC_ARM_PCREL_BRANCH
:
12123 case BFD_RELOC_ARM_PCREL_BLX
:
12124 case BFD_RELOC_RVA
:
12125 case BFD_RELOC_THUMB_PCREL_BRANCH9
:
12126 case BFD_RELOC_THUMB_PCREL_BRANCH12
:
12127 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
12128 case BFD_RELOC_THUMB_PCREL_BLX
:
12129 case BFD_RELOC_VTABLE_ENTRY
:
12130 case BFD_RELOC_VTABLE_INHERIT
:
12131 code
= fixp
->fx_r_type
;
12134 case BFD_RELOC_ARM_LITERAL
:
12135 case BFD_RELOC_ARM_HWLITERAL
:
12136 /* If this is called then the a literal has
12137 been referenced across a section boundary. */
12138 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12139 _("literal referenced across section boundary"));
12143 case BFD_RELOC_ARM_GOT32
:
12144 case BFD_RELOC_ARM_GOTOFF
:
12145 case BFD_RELOC_ARM_PLT32
:
12146 case BFD_RELOC_ARM_TARGET1
:
12147 case BFD_RELOC_ARM_ROSEGREL32
:
12148 case BFD_RELOC_ARM_SBREL32
:
12149 case BFD_RELOC_ARM_PREL31
:
12150 case BFD_RELOC_ARM_TARGET2
:
12151 code
= fixp
->fx_r_type
;
12155 case BFD_RELOC_ARM_IMMEDIATE
:
12156 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12157 _("internal relocation (type: IMMEDIATE) not fixed up"));
12160 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
12161 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12162 _("ADRL used for a symbol not defined in the same file"));
12165 case BFD_RELOC_ARM_OFFSET_IMM
:
12166 if (fixp
->fx_addsy
!= NULL
12167 && !S_IS_DEFINED (fixp
->fx_addsy
)
12168 && S_IS_LOCAL (fixp
->fx_addsy
))
12170 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12171 _("undefined local label `%s'"),
12172 S_GET_NAME (fixp
->fx_addsy
));
12176 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12177 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
12184 switch (fixp
->fx_r_type
)
12186 case BFD_RELOC_NONE
: type
= "NONE"; break;
12187 case BFD_RELOC_ARM_OFFSET_IMM8
: type
= "OFFSET_IMM8"; break;
12188 case BFD_RELOC_ARM_SHIFT_IMM
: type
= "SHIFT_IMM"; break;
12189 case BFD_RELOC_ARM_SMI
: type
= "SMI"; break;
12190 case BFD_RELOC_ARM_SWI
: type
= "SWI"; break;
12191 case BFD_RELOC_ARM_MULTI
: type
= "MULTI"; break;
12192 case BFD_RELOC_ARM_CP_OFF_IMM
: type
= "CP_OFF_IMM"; break;
12193 case BFD_RELOC_ARM_THUMB_ADD
: type
= "THUMB_ADD"; break;
12194 case BFD_RELOC_ARM_THUMB_SHIFT
: type
= "THUMB_SHIFT"; break;
12195 case BFD_RELOC_ARM_THUMB_IMM
: type
= "THUMB_IMM"; break;
12196 case BFD_RELOC_ARM_THUMB_OFFSET
: type
= "THUMB_OFFSET"; break;
12197 default: type
= _("<unknown>"); break;
12199 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12200 _("cannot represent %s relocation in this object file format"),
12207 if ((code
== BFD_RELOC_32_PCREL
|| code
== BFD_RELOC_32
)
12209 && fixp
->fx_addsy
== GOT_symbol
)
12211 code
= BFD_RELOC_ARM_GOTPC
;
12212 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
12216 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, code
);
12218 if (reloc
->howto
== NULL
)
12220 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12221 _("cannot represent %s relocation in this object file format"),
12222 bfd_get_reloc_code_name (code
));
12226 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12227 vtable entry to be used in the relocation's section offset. */
12228 if (fixp
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
12229 reloc
->address
= fixp
->fx_offset
;
12235 md_estimate_size_before_relax (fragS
* fragP ATTRIBUTE_UNUSED
,
12236 segT segtype ATTRIBUTE_UNUSED
)
12238 as_fatal (_("md_estimate_size_before_relax\n"));
12242 /* We need to be able to fix up arbitrary expressions in some statements.
12243 This is so that we can handle symbols that are an arbitrary distance from
12244 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
12245 which returns part of an address in a form which will be valid for
12246 a data instruction. We do this by pushing the expression into a symbol
12247 in the expr_section, and creating a fix for that. */
12250 fix_new_arm (fragS
* frag
,
12258 arm_fix_data
* arm_data
;
12266 new_fix
= fix_new_exp (frag
, where
, size
, exp
, pc_rel
, reloc
);
12270 new_fix
= fix_new (frag
, where
, size
, make_expr_symbol (exp
), 0,
12275 /* Mark whether the fix is to a THUMB instruction, or an ARM
12277 arm_data
= obstack_alloc (& notes
, sizeof (arm_fix_data
));
12278 new_fix
->tc_fix_data
= (PTR
) arm_data
;
12279 arm_data
->thumb_mode
= thumb_mode
;
12283 output_inst (const char * str
)
12289 as_bad ("%s -- `%s'", inst
.error
, str
);
12293 to
= frag_more (inst
.size
);
12295 if (thumb_mode
&& (inst
.size
> THUMB_SIZE
))
12297 assert (inst
.size
== (2 * THUMB_SIZE
));
12298 md_number_to_chars (to
, inst
.instruction
>> 16, THUMB_SIZE
);
12299 md_number_to_chars (to
+ THUMB_SIZE
, inst
.instruction
, THUMB_SIZE
);
12301 else if (inst
.size
> INSN_SIZE
)
12303 assert (inst
.size
== (2 * INSN_SIZE
));
12304 md_number_to_chars (to
, inst
.instruction
, INSN_SIZE
);
12305 md_number_to_chars (to
+ INSN_SIZE
, inst
.instruction
, INSN_SIZE
);
12308 md_number_to_chars (to
, inst
.instruction
, inst
.size
);
12310 if (inst
.reloc
.type
!= BFD_RELOC_UNUSED
)
12311 fix_new_arm (frag_now
, to
- frag_now
->fr_literal
,
12312 inst
.size
, & inst
.reloc
.exp
, inst
.reloc
.pc_rel
,
12316 dwarf2_emit_insn (inst
.size
);
12321 md_assemble (char * str
)
12327 /* Align the previous label if needed. */
12328 if (last_label_seen
!= NULL
)
12330 symbol_set_frag (last_label_seen
, frag_now
);
12331 S_SET_VALUE (last_label_seen
, (valueT
) frag_now_fix ());
12332 S_SET_SEGMENT (last_label_seen
, now_seg
);
12335 memset (&inst
, '\0', sizeof (inst
));
12336 inst
.reloc
.type
= BFD_RELOC_UNUSED
;
12338 skip_whitespace (str
);
12340 /* Scan up to the end of the op-code, which must end in white space or
12342 for (start
= p
= str
; *p
!= '\0'; p
++)
12348 as_bad (_("no operator -- statement `%s'\n"), str
);
12354 const struct thumb_opcode
* opcode
;
12358 opcode
= (const struct thumb_opcode
*) hash_find (arm_tops_hsh
, str
);
12363 /* Check that this instruction is supported for this CPU. */
12364 if (thumb_mode
== 1 && (opcode
->variant
& cpu_variant
) == 0)
12366 as_bad (_("selected processor does not support `%s'"), str
);
12370 mapping_state (MAP_THUMB
);
12371 inst
.instruction
= opcode
->value
;
12372 inst
.size
= opcode
->size
;
12380 const struct asm_opcode
* opcode
;
12384 opcode
= (const struct asm_opcode
*) hash_find (arm_ops_hsh
, str
);
12389 /* Check that this instruction is supported for this CPU. */
12390 if ((opcode
->variant
& cpu_variant
) == 0)
12392 as_bad (_("selected processor does not support `%s'"), str
);
12396 mapping_state (MAP_ARM
);
12397 inst
.instruction
= opcode
->value
;
12398 inst
.size
= INSN_SIZE
;
12405 /* It wasn't an instruction, but it might be a register alias of the form
12407 if (create_register_alias (str
, p
))
12410 as_bad (_("bad instruction `%s'"), start
);
12414 Invocation line includes a switch not recognized by the base assembler.
12415 See if it's a processor-specific option.
12417 This routine is somewhat complicated by the need for backwards
12418 compatibility (since older releases of gcc can't be changed).
12419 The new options try to make the interface as compatible as
12422 New options (supported) are:
12424 -mcpu=<cpu name> Assemble for selected processor
12425 -march=<architecture name> Assemble for selected architecture
12426 -mfpu=<fpu architecture> Assemble for selected FPU.
12427 -EB/-mbig-endian Big-endian
12428 -EL/-mlittle-endian Little-endian
12429 -k Generate PIC code
12430 -mthumb Start in Thumb mode
12431 -mthumb-interwork Code supports ARM/Thumb interworking
12433 For now we will also provide support for:
12435 -mapcs-32 32-bit Program counter
12436 -mapcs-26 26-bit Program counter
12437 -macps-float Floats passed in FP registers
12438 -mapcs-reentrant Reentrant code
12440 (sometime these will probably be replaced with -mapcs=<list of options>
12441 and -matpcs=<list of options>)
12443 The remaining options are only supported for back-wards compatibility.
12444 Cpu variants, the arm part is optional:
12445 -m[arm]1 Currently not supported.
12446 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
12447 -m[arm]3 Arm 3 processor
12448 -m[arm]6[xx], Arm 6 processors
12449 -m[arm]7[xx][t][[d]m] Arm 7 processors
12450 -m[arm]8[10] Arm 8 processors
12451 -m[arm]9[20][tdmi] Arm 9 processors
12452 -mstrongarm[110[0]] StrongARM processors
12453 -mxscale XScale processors
12454 -m[arm]v[2345[t[e]]] Arm architectures
12455 -mall All (except the ARM1)
12457 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
12458 -mfpe-old (No float load/store multiples)
12459 -mvfpxd VFP Single precision
12461 -mno-fpu Disable all floating point instructions
12463 The following CPU names are recognized:
12464 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
12465 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
12466 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
12467 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
12468 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
12469 arm10t arm10e, arm1020t, arm1020e, arm10200e,
12470 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
12474 const char * md_shortopts
= "m:k";
12476 #ifdef ARM_BI_ENDIAN
12477 #define OPTION_EB (OPTION_MD_BASE + 0)
12478 #define OPTION_EL (OPTION_MD_BASE + 1)
12480 #if TARGET_BYTES_BIG_ENDIAN
12481 #define OPTION_EB (OPTION_MD_BASE + 0)
12483 #define OPTION_EL (OPTION_MD_BASE + 1)
12487 struct option md_longopts
[] =
12490 {"EB", no_argument
, NULL
, OPTION_EB
},
12493 {"EL", no_argument
, NULL
, OPTION_EL
},
12495 {NULL
, no_argument
, NULL
, 0}
12498 size_t md_longopts_size
= sizeof (md_longopts
);
12500 struct arm_option_table
12502 char *option
; /* Option name to match. */
12503 char *help
; /* Help information. */
12504 int *var
; /* Variable to change. */
12505 int value
; /* What to change it to. */
12506 char *deprecated
; /* If non-null, print this message. */
12509 struct arm_option_table arm_opts
[] =
12511 {"k", N_("generate PIC code"), &pic_code
, 1, NULL
},
12512 {"mthumb", N_("assemble Thumb code"), &thumb_mode
, 1, NULL
},
12513 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
12514 &support_interwork
, 1, NULL
},
12515 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26
, 0, NULL
},
12516 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26
, 1, NULL
},
12517 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float
,
12519 {"mapcs-reentrant", N_("re-entrant code"), &pic_code
, 1, NULL
},
12520 {"matpcs", N_("code is ATPCS conformant"), &atpcs
, 1, NULL
},
12521 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian
, 1, NULL
},
12522 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian
, 1,
12525 /* These are recognized by the assembler, but have no affect on code. */
12526 {"mapcs-frame", N_("use frame pointer"), NULL
, 0, NULL
},
12527 {"mapcs-stack-check", N_("use stack size checking"), NULL
, 0, NULL
},
12529 /* DON'T add any new processors to this list -- we want the whole list
12530 to go away... Add them to the processors table instead. */
12531 {"marm1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
12532 {"m1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
12533 {"marm2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
12534 {"m2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
12535 {"marm250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
12536 {"m250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
12537 {"marm3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
12538 {"m3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
12539 {"marm6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
12540 {"m6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
12541 {"marm600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
12542 {"m600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
12543 {"marm610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
12544 {"m610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
12545 {"marm620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
12546 {"m620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
12547 {"marm7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
12548 {"m7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
12549 {"marm70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
12550 {"m70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
12551 {"marm700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
12552 {"m700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
12553 {"marm700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
12554 {"m700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
12555 {"marm710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
12556 {"m710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
12557 {"marm710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
12558 {"m710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
12559 {"marm720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
12560 {"m720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
12561 {"marm7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
12562 {"m7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
12563 {"marm7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
12564 {"m7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
12565 {"marm7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
12566 {"m7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
12567 {"marm7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
12568 {"m7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
12569 {"marm7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
12570 {"m7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
12571 {"marm7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
12572 {"m7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
12573 {"marm7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
12574 {"m7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
12575 {"marm7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
12576 {"m7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
12577 {"marm7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12578 {"m7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12579 {"marm7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12580 {"m7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12581 {"marm710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
12582 {"m710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
12583 {"marm720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
12584 {"m720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
12585 {"marm740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
12586 {"m740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
12587 {"marm8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
12588 {"m8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
12589 {"marm810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
12590 {"m810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
12591 {"marm9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
12592 {"m9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
12593 {"marm9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
12594 {"m9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
12595 {"marm920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
12596 {"m920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
12597 {"marm940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
12598 {"m940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
12599 {"mstrongarm", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=strongarm")},
12600 {"mstrongarm110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
12601 N_("use -mcpu=strongarm110")},
12602 {"mstrongarm1100", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
12603 N_("use -mcpu=strongarm1100")},
12604 {"mstrongarm1110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
12605 N_("use -mcpu=strongarm1110")},
12606 {"mxscale", NULL
, &legacy_cpu
, ARM_ARCH_XSCALE
, N_("use -mcpu=xscale")},
12607 {"miwmmxt", NULL
, &legacy_cpu
, ARM_ARCH_IWMMXT
, N_("use -mcpu=iwmmxt")},
12608 {"mall", NULL
, &legacy_cpu
, ARM_ANY
, N_("use -mcpu=all")},
12610 /* Architecture variants -- don't add any more to this list either. */
12611 {"mv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
12612 {"marmv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
12613 {"mv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
12614 {"marmv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
12615 {"mv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
12616 {"marmv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
12617 {"mv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
12618 {"marmv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
12619 {"mv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
12620 {"marmv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
12621 {"mv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
12622 {"marmv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
12623 {"mv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
12624 {"marmv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
12625 {"mv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
12626 {"marmv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
12627 {"mv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
12628 {"marmv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
12630 /* Floating point variants -- don't add any more to this list either. */
12631 {"mfpe-old", NULL
, &legacy_fpu
, FPU_ARCH_FPE
, N_("use -mfpu=fpe")},
12632 {"mfpa10", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa10")},
12633 {"mfpa11", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa11")},
12634 {"mno-fpu", NULL
, &legacy_fpu
, 0,
12635 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
12637 {NULL
, NULL
, NULL
, 0, NULL
}
12640 struct arm_cpu_option_table
12644 /* For some CPUs we assume an FPU unless the user explicitly sets
12649 /* This list should, at a minimum, contain all the cpu names
12650 recognized by GCC. */
12651 static struct arm_cpu_option_table arm_cpus
[] =
12653 {"all", ARM_ANY
, FPU_ARCH_FPA
},
12654 {"arm1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
12655 {"arm2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
12656 {"arm250", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
12657 {"arm3", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
12658 {"arm6", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12659 {"arm60", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12660 {"arm600", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12661 {"arm610", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12662 {"arm620", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12663 {"arm7", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12664 {"arm7m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
12665 {"arm7d", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12666 {"arm7dm", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
12667 {"arm7di", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12668 {"arm7dmi", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
12669 {"arm70", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12670 {"arm700", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12671 {"arm700i", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12672 {"arm710", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12673 {"arm710t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12674 {"arm720", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12675 {"arm720t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12676 {"arm740t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12677 {"arm710c", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12678 {"arm7100", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12679 {"arm7500", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12680 {"arm7500fe", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12681 {"arm7t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12682 {"arm7tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12683 {"arm7tdmi-s", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12684 {"arm8", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12685 {"arm810", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12686 {"strongarm", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12687 {"strongarm1", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12688 {"strongarm110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12689 {"strongarm1100", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12690 {"strongarm1110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12691 {"arm9", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12692 {"arm920", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12693 {"arm920t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12694 {"arm922t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12695 {"arm940t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12696 {"arm9tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12697 /* For V5 or later processors we default to using VFP; but the user
12698 should really set the FPU type explicitly. */
12699 {"arm9e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
12700 {"arm9e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12701 {"arm926ej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
12702 {"arm926ejs", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
12703 {"arm926ej-s", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
12704 {"arm946e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
12705 {"arm946e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12706 {"arm966e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
12707 {"arm966e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12708 {"arm10t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
12709 {"arm10e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12710 {"arm1020", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12711 {"arm1020t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
12712 {"arm1020e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12713 {"arm1026ejs", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
12714 {"arm1026ej-s", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
12715 {"arm1136js", ARM_ARCH_V6
, FPU_NONE
},
12716 {"arm1136j-s", ARM_ARCH_V6
, FPU_NONE
},
12717 {"arm1136jfs", ARM_ARCH_V6
, FPU_ARCH_VFP_V2
},
12718 {"arm1136jf-s", ARM_ARCH_V6
, FPU_ARCH_VFP_V2
},
12719 {"mpcore", ARM_ARCH_V6K
, FPU_ARCH_VFP_V2
},
12720 {"mpcorenovfp", ARM_ARCH_V6K
, FPU_NONE
},
12721 {"arm1176jz-s", ARM_ARCH_V6ZK
, FPU_NONE
},
12722 {"arm1176jzf-s", ARM_ARCH_V6ZK
, FPU_ARCH_VFP_V2
},
12723 /* ??? XSCALE is really an architecture. */
12724 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
12725 /* ??? iwmmxt is not a processor. */
12726 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP_V2
},
12727 {"i80200", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
12729 {"ep9312", ARM_ARCH_V4T
| ARM_CEXT_MAVERICK
, FPU_ARCH_MAVERICK
},
12733 struct arm_arch_option_table
12740 /* This list should, at a minimum, contain all the architecture names
12741 recognized by GCC. */
12742 static struct arm_arch_option_table arm_archs
[] =
12744 {"all", ARM_ANY
, FPU_ARCH_FPA
},
12745 {"armv1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
12746 {"armv2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
12747 {"armv2a", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
12748 {"armv2s", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
12749 {"armv3", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12750 {"armv3m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
12751 {"armv4", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12752 {"armv4xm", ARM_ARCH_V4xM
, FPU_ARCH_FPA
},
12753 {"armv4t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12754 {"armv4txm", ARM_ARCH_V4TxM
, FPU_ARCH_FPA
},
12755 {"armv5", ARM_ARCH_V5
, FPU_ARCH_VFP
},
12756 {"armv5t", ARM_ARCH_V5T
, FPU_ARCH_VFP
},
12757 {"armv5txm", ARM_ARCH_V5TxM
, FPU_ARCH_VFP
},
12758 {"armv5te", ARM_ARCH_V5TE
, FPU_ARCH_VFP
},
12759 {"armv5texp", ARM_ARCH_V5TExP
, FPU_ARCH_VFP
},
12760 {"armv5tej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP
},
12761 {"armv6", ARM_ARCH_V6
, FPU_ARCH_VFP
},
12762 {"armv6j", ARM_ARCH_V6
, FPU_ARCH_VFP
},
12763 {"armv6k", ARM_ARCH_V6K
, FPU_ARCH_VFP
},
12764 {"armv6z", ARM_ARCH_V6Z
, FPU_ARCH_VFP
},
12765 {"armv6zk", ARM_ARCH_V6ZK
, FPU_ARCH_VFP
},
12766 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP
},
12767 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP
},
12771 /* ISA extensions in the co-processor space. */
12772 struct arm_arch_extension_table
12778 static struct arm_arch_extension_table arm_extensions
[] =
12780 {"maverick", ARM_CEXT_MAVERICK
},
12781 {"xscale", ARM_CEXT_XSCALE
},
12782 {"iwmmxt", ARM_CEXT_IWMMXT
},
12786 struct arm_fpu_option_table
12792 /* This list should, at a minimum, contain all the fpu names
12793 recognized by GCC. */
12794 static struct arm_fpu_option_table arm_fpus
[] =
12796 {"softfpa", FPU_NONE
},
12797 {"fpe", FPU_ARCH_FPE
},
12798 {"fpe2", FPU_ARCH_FPE
},
12799 {"fpe3", FPU_ARCH_FPA
}, /* Third release supports LFM/SFM. */
12800 {"fpa", FPU_ARCH_FPA
},
12801 {"fpa10", FPU_ARCH_FPA
},
12802 {"fpa11", FPU_ARCH_FPA
},
12803 {"arm7500fe", FPU_ARCH_FPA
},
12804 {"softvfp", FPU_ARCH_VFP
},
12805 {"softvfp+vfp", FPU_ARCH_VFP_V2
},
12806 {"vfp", FPU_ARCH_VFP_V2
},
12807 {"vfp9", FPU_ARCH_VFP_V2
},
12808 {"vfp10", FPU_ARCH_VFP_V2
},
12809 {"vfp10-r0", FPU_ARCH_VFP_V1
},
12810 {"vfpxd", FPU_ARCH_VFP_V1xD
},
12811 {"arm1020t", FPU_ARCH_VFP_V1
},
12812 {"arm1020e", FPU_ARCH_VFP_V2
},
12813 {"arm1136jfs", FPU_ARCH_VFP_V2
},
12814 {"arm1136jf-s", FPU_ARCH_VFP_V2
},
12815 {"maverick", FPU_ARCH_MAVERICK
},
12819 struct arm_float_abi_option_table
12825 static struct arm_float_abi_option_table arm_float_abis
[] =
12827 {"hard", ARM_FLOAT_ABI_HARD
},
12828 {"softfp", ARM_FLOAT_ABI_SOFTFP
},
12829 {"soft", ARM_FLOAT_ABI_SOFT
},
12833 struct arm_eabi_option_table
12836 unsigned int value
;
12840 /* We only know how to output GNU and ver 4 (AAELF) formats. */
12841 static struct arm_eabi_option_table arm_eabis
[] =
12843 {"gnu", EF_ARM_EABI_UNKNOWN
},
12844 {"4", EF_ARM_EABI_VER4
},
12849 struct arm_long_option_table
12851 char * option
; /* Substring to match. */
12852 char * help
; /* Help information. */
12853 int (* func
) (char * subopt
); /* Function to decode sub-option. */
12854 char * deprecated
; /* If non-null, print this message. */
12858 arm_parse_extension (char * str
, int * opt_p
)
12860 while (str
!= NULL
&& *str
!= 0)
12862 struct arm_arch_extension_table
* opt
;
12868 as_bad (_("invalid architectural extension"));
12873 ext
= strchr (str
, '+');
12876 optlen
= ext
- str
;
12878 optlen
= strlen (str
);
12882 as_bad (_("missing architectural extension"));
12886 for (opt
= arm_extensions
; opt
->name
!= NULL
; opt
++)
12887 if (strncmp (opt
->name
, str
, optlen
) == 0)
12889 *opt_p
|= opt
->value
;
12893 if (opt
->name
== NULL
)
12895 as_bad (_("unknown architectural extnsion `%s'"), str
);
12906 arm_parse_cpu (char * str
)
12908 struct arm_cpu_option_table
* opt
;
12909 char * ext
= strchr (str
, '+');
12913 optlen
= ext
- str
;
12915 optlen
= strlen (str
);
12919 as_bad (_("missing cpu name `%s'"), str
);
12923 for (opt
= arm_cpus
; opt
->name
!= NULL
; opt
++)
12924 if (strncmp (opt
->name
, str
, optlen
) == 0)
12926 mcpu_cpu_opt
= opt
->value
;
12927 mcpu_fpu_opt
= opt
->default_fpu
;
12930 return arm_parse_extension (ext
, &mcpu_cpu_opt
);
12935 as_bad (_("unknown cpu `%s'"), str
);
12940 arm_parse_arch (char * str
)
12942 struct arm_arch_option_table
*opt
;
12943 char *ext
= strchr (str
, '+');
12947 optlen
= ext
- str
;
12949 optlen
= strlen (str
);
12953 as_bad (_("missing architecture name `%s'"), str
);
12958 for (opt
= arm_archs
; opt
->name
!= NULL
; opt
++)
12959 if (streq (opt
->name
, str
))
12961 march_cpu_opt
= opt
->value
;
12962 march_fpu_opt
= opt
->default_fpu
;
12965 return arm_parse_extension (ext
, &march_cpu_opt
);
12970 as_bad (_("unknown architecture `%s'\n"), str
);
12975 arm_parse_fpu (char * str
)
12977 struct arm_fpu_option_table
* opt
;
12979 for (opt
= arm_fpus
; opt
->name
!= NULL
; opt
++)
12980 if (streq (opt
->name
, str
))
12982 mfpu_opt
= opt
->value
;
12986 as_bad (_("unknown floating point format `%s'\n"), str
);
12991 arm_parse_float_abi (char * str
)
12993 struct arm_float_abi_option_table
* opt
;
12995 for (opt
= arm_float_abis
; opt
->name
!= NULL
; opt
++)
12996 if (streq (opt
->name
, str
))
12998 mfloat_abi_opt
= opt
->value
;
13002 as_bad (_("unknown floating point abi `%s'\n"), str
);
13008 arm_parse_eabi (char * str
)
13010 struct arm_eabi_option_table
*opt
;
13012 for (opt
= arm_eabis
; opt
->name
!= NULL
; opt
++)
13013 if (streq (opt
->name
, str
))
13015 meabi_flags
= opt
->value
;
13018 as_bad (_("unknown EABI `%s'\n"), str
);
13023 struct arm_long_option_table arm_long_opts
[] =
13025 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13026 arm_parse_cpu
, NULL
},
13027 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13028 arm_parse_arch
, NULL
},
13029 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13030 arm_parse_fpu
, NULL
},
13031 {"mfloat-abi=", N_("<abi>\t assemble for floating point ABI <abi>"),
13032 arm_parse_float_abi
, NULL
},
13034 {"meabi=", N_("<ver>\t assemble for eabi version <ver>"),
13035 arm_parse_eabi
, NULL
},
13037 {NULL
, NULL
, 0, NULL
}
13041 md_parse_option (int c
, char * arg
)
13043 struct arm_option_table
*opt
;
13044 struct arm_long_option_table
*lopt
;
13050 target_big_endian
= 1;
13056 target_big_endian
= 0;
13061 /* Listing option. Just ignore these, we don't support additional
13066 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
13068 if (c
== opt
->option
[0]
13069 && ((arg
== NULL
&& opt
->option
[1] == 0)
13070 || streq (arg
, opt
->option
+ 1)))
13072 #if WARN_DEPRECATED
13073 /* If the option is deprecated, tell the user. */
13074 if (opt
->deprecated
!= NULL
)
13075 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
,
13076 arg
? arg
: "", _(opt
->deprecated
));
13079 if (opt
->var
!= NULL
)
13080 *opt
->var
= opt
->value
;
13086 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
13088 /* These options are expected to have an argument. */
13089 if (c
== lopt
->option
[0]
13091 && strncmp (arg
, lopt
->option
+ 1,
13092 strlen (lopt
->option
+ 1)) == 0)
13094 #if WARN_DEPRECATED
13095 /* If the option is deprecated, tell the user. */
13096 if (lopt
->deprecated
!= NULL
)
13097 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
, arg
,
13098 _(lopt
->deprecated
));
13101 /* Call the sup-option parser. */
13102 return lopt
->func (arg
+ strlen (lopt
->option
) - 1);
13113 md_show_usage (FILE * fp
)
13115 struct arm_option_table
*opt
;
13116 struct arm_long_option_table
*lopt
;
13118 fprintf (fp
, _(" ARM-specific assembler options:\n"));
13120 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
13121 if (opt
->help
!= NULL
)
13122 fprintf (fp
, " -%-23s%s\n", opt
->option
, _(opt
->help
));
13124 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
13125 if (lopt
->help
!= NULL
)
13126 fprintf (fp
, " -%s%s\n", lopt
->option
, _(lopt
->help
));
13130 -EB assemble code for a big-endian cpu\n"));
13135 -EL assemble code for a little-endian cpu\n"));
13139 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13142 cons_fix_new_arm (fragS
* frag
,
13147 bfd_reloc_code_real_type type
;
13151 FIXME: @@ Should look at CPU word size. */
13155 type
= BFD_RELOC_8
;
13158 type
= BFD_RELOC_16
;
13162 type
= BFD_RELOC_32
;
13165 type
= BFD_RELOC_64
;
13169 fix_new_exp (frag
, where
, (int) size
, exp
, pcrel
, type
);
13172 /* A good place to do this, although this was probably not intended
13173 for this kind of use. We need to dump the literal pool before
13174 references are made to a null symbol pointer. */
13179 literal_pool
* pool
;
13181 for (pool
= list_of_pools
; pool
; pool
= pool
->next
)
13183 /* Put it at the end of the relevent section. */
13184 subseg_set (pool
->section
, pool
->sub_section
);
13186 arm_elf_change_section ();
13193 arm_start_line_hook (void)
13195 last_label_seen
= NULL
;
13199 arm_frob_label (symbolS
* sym
)
13201 last_label_seen
= sym
;
13203 ARM_SET_THUMB (sym
, thumb_mode
);
13205 #if defined OBJ_COFF || defined OBJ_ELF
13206 ARM_SET_INTERWORK (sym
, support_interwork
);
13209 /* Note - do not allow local symbols (.Lxxx) to be labeled
13210 as Thumb functions. This is because these labels, whilst
13211 they exist inside Thumb code, are not the entry points for
13212 possible ARM->Thumb calls. Also, these labels can be used
13213 as part of a computed goto or switch statement. eg gcc
13214 can generate code that looks like this:
13216 ldr r2, [pc, .Laaa]
13226 The first instruction loads the address of the jump table.
13227 The second instruction converts a table index into a byte offset.
13228 The third instruction gets the jump address out of the table.
13229 The fourth instruction performs the jump.
13231 If the address stored at .Laaa is that of a symbol which has the
13232 Thumb_Func bit set, then the linker will arrange for this address
13233 to have the bottom bit set, which in turn would mean that the
13234 address computation performed by the third instruction would end
13235 up with the bottom bit set. Since the ARM is capable of unaligned
13236 word loads, the instruction would then load the incorrect address
13237 out of the jump table, and chaos would ensue. */
13238 if (label_is_thumb_function_name
13239 && (S_GET_NAME (sym
)[0] != '.' || S_GET_NAME (sym
)[1] != 'L')
13240 && (bfd_get_section_flags (stdoutput
, now_seg
) & SEC_CODE
) != 0)
13242 /* When the address of a Thumb function is taken the bottom
13243 bit of that address should be set. This will allow
13244 interworking between Arm and Thumb functions to work
13247 THUMB_SET_FUNC (sym
, 1);
13249 label_is_thumb_function_name
= FALSE
;
13253 /* Adjust the symbol table. This marks Thumb symbols as distinct from
13257 arm_adjust_symtab (void)
13262 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
13264 if (ARM_IS_THUMB (sym
))
13266 if (THUMB_IS_FUNC (sym
))
13268 /* Mark the symbol as a Thumb function. */
13269 if ( S_GET_STORAGE_CLASS (sym
) == C_STAT
13270 || S_GET_STORAGE_CLASS (sym
) == C_LABEL
) /* This can happen! */
13271 S_SET_STORAGE_CLASS (sym
, C_THUMBSTATFUNC
);
13273 else if (S_GET_STORAGE_CLASS (sym
) == C_EXT
)
13274 S_SET_STORAGE_CLASS (sym
, C_THUMBEXTFUNC
);
13276 as_bad (_("%s: unexpected function type: %d"),
13277 S_GET_NAME (sym
), S_GET_STORAGE_CLASS (sym
));
13279 else switch (S_GET_STORAGE_CLASS (sym
))
13282 S_SET_STORAGE_CLASS (sym
, C_THUMBEXT
);
13285 S_SET_STORAGE_CLASS (sym
, C_THUMBSTAT
);
13288 S_SET_STORAGE_CLASS (sym
, C_THUMBLABEL
);
13296 if (ARM_IS_INTERWORK (sym
))
13297 coffsymbol (symbol_get_bfdsym (sym
))->native
->u
.syment
.n_flags
= 0xFF;
13304 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
13306 if (ARM_IS_THUMB (sym
))
13308 elf_symbol_type
* elf_sym
;
13310 elf_sym
= elf_symbol (symbol_get_bfdsym (sym
));
13311 bind
= ELF_ST_BIND (elf_sym
);
13313 /* If it's a .thumb_func, declare it as so,
13314 otherwise tag label as .code 16. */
13315 if (THUMB_IS_FUNC (sym
))
13316 elf_sym
->internal_elf_sym
.st_info
=
13317 ELF_ST_INFO (bind
, STT_ARM_TFUNC
);
13319 elf_sym
->internal_elf_sym
.st_info
=
13320 ELF_ST_INFO (bind
, STT_ARM_16BIT
);
13327 arm_data_in_code (void)
13329 if (thumb_mode
&& ! strncmp (input_line_pointer
+ 1, "data:", 5))
13331 *input_line_pointer
= '/';
13332 input_line_pointer
+= 5;
13333 *input_line_pointer
= 0;
13341 arm_canonicalize_symbol_name (char * name
)
13345 if (thumb_mode
&& (len
= strlen (name
)) > 5
13346 && streq (name
+ len
- 5, "/data"))
13347 *(name
+ len
- 5) = 0;
13352 #if defined OBJ_COFF || defined OBJ_ELF
13354 arm_validate_fix (fixS
* fixP
)
13356 /* If the destination of the branch is a defined symbol which does not have
13357 the THUMB_FUNC attribute, then we must be calling a function which has
13358 the (interfacearm) attribute. We look for the Thumb entry point to that
13359 function and change the branch to refer to that function instead. */
13360 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
13361 && fixP
->fx_addsy
!= NULL
13362 && S_IS_DEFINED (fixP
->fx_addsy
)
13363 && ! THUMB_IS_FUNC (fixP
->fx_addsy
))
13365 fixP
->fx_addsy
= find_real_start (fixP
->fx_addsy
);
13371 arm_force_relocation (struct fix
* fixp
)
13373 #if defined (OBJ_COFF) && defined (TE_PE)
13374 if (fixp
->fx_r_type
== BFD_RELOC_RVA
)
13378 if (fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
13379 || fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
13380 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
13381 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
)
13385 /* Resolve these relocations even if the symbol is extern or weak. */
13386 if (fixp
->fx_r_type
== BFD_RELOC_ARM_IMMEDIATE
13387 || fixp
->fx_r_type
== BFD_RELOC_ARM_OFFSET_IMM
13388 || fixp
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
13391 return generic_force_reloc (fixp
);
13395 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
13396 local labels from being added to the output symbol table when they
13397 are used with the ADRL pseudo op. The ADRL relocation should always
13398 be resolved before the binbary is emitted, so it is safe to say that
13399 it is adjustable. */
13402 arm_fix_adjustable (fixS
* fixP
)
13404 if (fixP
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
13411 /* Relocations against Thumb function names must be left unadjusted,
13412 so that the linker can use this information to correctly set the
13413 bottom bit of their addresses. The MIPS version of this function
13414 also prevents relocations that are mips-16 specific, but I do not
13415 know why it does this.
13418 There is one other problem that ought to be addressed here, but
13419 which currently is not: Taking the address of a label (rather
13420 than a function) and then later jumping to that address. Such
13421 addresses also ought to have their bottom bit set (assuming that
13422 they reside in Thumb code), but at the moment they will not. */
13425 arm_fix_adjustable (fixS
* fixP
)
13427 if (fixP
->fx_addsy
== NULL
)
13430 if (THUMB_IS_FUNC (fixP
->fx_addsy
)
13431 && fixP
->fx_subsy
== NULL
)
13434 /* We need the symbol name for the VTABLE entries. */
13435 if ( fixP
->fx_r_type
== BFD_RELOC_VTABLE_INHERIT
13436 || fixP
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
13439 /* Don't allow symbols to be discarded on GOT related relocs. */
13440 if (fixP
->fx_r_type
== BFD_RELOC_ARM_PLT32
13441 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOT32
13442 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOTOFF
13443 || fixP
->fx_r_type
== BFD_RELOC_ARM_TARGET2
)
13450 elf32_arm_target_format (void)
13453 return (target_big_endian
13454 ? "elf32-bigarm-symbian"
13455 : "elf32-littlearm-symbian");
13456 #elif defined (TE_VXWORKS)
13457 return (target_big_endian
13458 ? "elf32-bigarm-vxworks"
13459 : "elf32-littlearm-vxworks");
13461 if (target_big_endian
)
13462 return "elf32-bigarm";
13464 return "elf32-littlearm";
13469 armelf_frob_symbol (symbolS
* symp
,
13472 elf_frob_symbol (symp
, puntp
);
13476 s_arm_elf_cons (int nbytes
)
13480 #ifdef md_flush_pending_output
13481 md_flush_pending_output ();
13484 if (is_it_end_of_statement ())
13486 demand_empty_rest_of_line ();
13490 #ifdef md_cons_align
13491 md_cons_align (nbytes
);
13494 mapping_state (MAP_DATA
);
13497 bfd_reloc_code_real_type reloc
;
13499 expression (& exp
);
13501 if (exp
.X_op
== O_symbol
13502 && * input_line_pointer
== '('
13503 && (reloc
= arm_parse_reloc ()) != BFD_RELOC_UNUSED
)
13505 reloc_howto_type
*howto
= bfd_reloc_type_lookup (stdoutput
, reloc
);
13506 int size
= bfd_get_reloc_size (howto
);
13509 as_bad ("%s relocations do not fit in %d bytes",
13510 howto
->name
, nbytes
);
13513 char *p
= frag_more ((int) nbytes
);
13514 int offset
= nbytes
- size
;
13516 fix_new_exp (frag_now
, p
- frag_now
->fr_literal
+ offset
, size
,
13521 emit_expr (&exp
, (unsigned int) nbytes
);
13523 while (*input_line_pointer
++ == ',');
13525 /* Put terminator back into stream. */
13526 input_line_pointer
--;
13527 demand_empty_rest_of_line ();
13531 /* Parse a .rel31 directive. */
13534 s_arm_rel31 (int ignored ATTRIBUTE_UNUSED
)
13540 SKIP_WHITESPACE ();
13543 if (*input_line_pointer
== '1')
13544 highbit
= 0x80000000;
13545 else if (*input_line_pointer
!= '0')
13546 as_bad (_("expected 0 or 1"));
13548 input_line_pointer
++;
13549 SKIP_WHITESPACE ();
13550 if (*input_line_pointer
!= ',')
13551 as_bad (_("missing comma"));
13552 input_line_pointer
++;
13554 #ifdef md_flush_pending_output
13555 md_flush_pending_output ();
13558 #ifdef md_cons_align
13562 mapping_state (MAP_DATA
);
13567 md_number_to_chars (p
, highbit
, 4);
13568 fix_new_arm (frag_now
, p
- frag_now
->fr_literal
, 4, &exp
, 1,
13569 BFD_RELOC_ARM_PREL31
);
13571 demand_empty_rest_of_line ();
13574 /* Code to deal with unwinding tables. */
13576 static void add_unwind_adjustsp (offsetT
);
13578 /* Switch to section NAME and create section if necessary. It's
13579 rather ugly that we have to manipulate input_line_pointer but I
13580 don't see any other way to accomplish the same thing without
13581 changing obj-elf.c (which may be the Right Thing, in the end).
13582 Copied from tc-ia64.c. */
13585 set_section (char *name
)
13587 char *saved_input_line_pointer
;
13589 saved_input_line_pointer
= input_line_pointer
;
13590 input_line_pointer
= name
;
13591 obj_elf_section (0);
13592 input_line_pointer
= saved_input_line_pointer
;
13595 /* Cenerate and deferred unwind frame offset. */
13598 flush_pending_unwind (void)
13602 offset
= unwind
.pending_offset
;
13603 unwind
.pending_offset
= 0;
13605 add_unwind_adjustsp (offset
);
13608 /* Add an opcode to this list for this function. Two-byte opcodes should
13609 be passed as op[0] << 8 | op[1]. The list of opcodes is built in reverse
13613 add_unwind_opcode (valueT op
, int length
)
13615 /* Add any deferred stack adjustment. */
13616 if (unwind
.pending_offset
)
13617 flush_pending_unwind ();
13619 unwind
.sp_restored
= 0;
13621 if (unwind
.opcode_count
+ length
> unwind
.opcode_alloc
)
13623 unwind
.opcode_alloc
+= ARM_OPCODE_CHUNK_SIZE
;
13624 if (unwind
.opcodes
)
13625 unwind
.opcodes
= xrealloc (unwind
.opcodes
,
13626 unwind
.opcode_alloc
);
13628 unwind
.opcodes
= xmalloc (unwind
.opcode_alloc
);
13633 unwind
.opcodes
[unwind
.opcode_count
] = op
& 0xff;
13635 unwind
.opcode_count
++;
13639 /* Add unwind opcodes to adjust the stack pointer. */
13642 add_unwind_adjustsp (offsetT offset
)
13646 if (offset
> 0x200)
13648 /* We need at most 5 bytes to hold a 32-bit value in a uleb128. */
13653 /* Long form: 0xb2, uleb128. */
13654 /* This might not fit in a word so add the individual bytes,
13655 remembering the list is built in reverse order. */
13656 o
= (valueT
) ((offset
- 0x204) >> 2);
13658 add_unwind_opcode (0, 1);
13660 /* Calculate the uleb128 encoding of the offset. */
13664 bytes
[n
] = o
& 0x7f;
13670 /* Add the insn. */
13672 add_unwind_opcode (bytes
[n
- 1], 1);
13673 add_unwind_opcode (0xb2, 1);
13675 else if (offset
> 0x100)
13677 /* Two short opcodes. */
13678 add_unwind_opcode (0x3f, 1);
13679 op
= (offset
- 0x104) >> 2;
13680 add_unwind_opcode (op
, 1);
13682 else if (offset
> 0)
13684 /* Short opcode. */
13685 op
= (offset
- 4) >> 2;
13686 add_unwind_opcode (op
, 1);
13688 else if (offset
< 0)
13691 while (offset
> 0x100)
13693 add_unwind_opcode (0x7f, 1);
13696 op
= ((offset
- 4) >> 2) | 0x40;
13697 add_unwind_opcode (op
, 1);
13701 /* Finish the list of unwind opcodes for this function. */
13703 finish_unwind_opcodes (void)
13707 if (unwind
.fp_used
)
13709 /* Adjust sp as neccessary. */
13710 unwind
.pending_offset
+= unwind
.fp_offset
- unwind
.frame_size
;
13711 flush_pending_unwind ();
13713 /* After restoring sp from the frame pointer. */
13714 op
= 0x90 | unwind
.fp_reg
;
13715 add_unwind_opcode (op
, 1);
13718 flush_pending_unwind ();
13722 /* Start an exception table entry. If idx is nonzero this is an index table
13726 start_unwind_section (const segT text_seg
, int idx
)
13728 const char * text_name
;
13729 const char * prefix
;
13730 const char * prefix_once
;
13734 size_t sec_name_len
;
13738 prefix
= ELF_STRING_ARM_unwind
;
13739 prefix_once
= ELF_STRING_ARM_unwind_once
;
13743 prefix
= ELF_STRING_ARM_unwind_info
;
13744 prefix_once
= ELF_STRING_ARM_unwind_info_once
;
13747 text_name
= segment_name (text_seg
);
13748 if (streq (text_name
, ".text"))
13751 if (strncmp (text_name
, ".gnu.linkonce.t.",
13752 strlen (".gnu.linkonce.t.")) == 0)
13754 prefix
= prefix_once
;
13755 text_name
+= strlen (".gnu.linkonce.t.");
13758 prefix_len
= strlen (prefix
);
13759 text_len
= strlen (text_name
);
13760 sec_name_len
= prefix_len
+ text_len
;
13761 sec_name
= alloca (sec_name_len
+ 1);
13762 memcpy (sec_name
, prefix
, prefix_len
);
13763 memcpy (sec_name
+ prefix_len
, text_name
, text_len
);
13764 sec_name
[prefix_len
+ text_len
] = '\0';
13766 /* Handle COMDAT group. */
13767 if (prefix
!= prefix_once
&& (text_seg
->flags
& SEC_LINK_ONCE
) != 0)
13770 size_t len
, group_name_len
;
13771 const char *group_name
= elf_group_name (text_seg
);
13773 if (group_name
== NULL
)
13775 as_bad ("Group section `%s' has no group signature",
13776 segment_name (text_seg
));
13777 ignore_rest_of_line ();
13780 /* We have to construct a fake section directive. */
13781 group_name_len
= strlen (group_name
);
13787 len
= (sec_name_len
13788 + prefix_len
/* ,"aG",%sectiontype, */
13789 + group_name_len
/* ,group_name */
13790 + 7); /* ,comdat */
13792 section
= alloca (len
+ 1);
13793 memcpy (section
, sec_name
, sec_name_len
);
13795 memcpy (section
+ sec_name_len
, ",\"aG\",%exidx,", 13);
13797 memcpy (section
+ sec_name_len
, ",\"aG\",%progbits,", 16);
13798 memcpy (section
+ sec_name_len
+ prefix_len
, group_name
, group_name_len
);
13799 memcpy (section
+ len
- 7, ",comdat", 7);
13800 section
[len
] = '\0';
13801 set_section (section
);
13805 set_section (sec_name
);
13806 bfd_set_section_flags (stdoutput
, now_seg
,
13807 SEC_LOAD
| SEC_ALLOC
| SEC_READONLY
);
13810 /* Set the setion link for index tables. */
13812 elf_linked_to_section (now_seg
) = text_seg
;
13816 /* Start an unwind table entry. HAVE_DATA is nonzero if we have additional
13817 personality routine data. Returns zero, or the index table value for
13818 and inline entry. */
13821 create_unwind_entry (int have_data
)
13826 /* The current word of data. */
13828 /* The number of bytes left in this word. */
13831 finish_unwind_opcodes ();
13833 /* Remember the current text section. */
13834 unwind
.saved_seg
= now_seg
;
13835 unwind
.saved_subseg
= now_subseg
;
13837 start_unwind_section (now_seg
, 0);
13839 if (unwind
.personality_routine
== NULL
)
13841 if (unwind
.personality_index
== -2)
13844 as_bad (_("handerdata in cantunwind frame"));
13845 return 1; /* EXIDX_CANTUNWIND. */
13848 /* Use a default personality routine if none is specified. */
13849 if (unwind
.personality_index
== -1)
13851 if (unwind
.opcode_count
> 3)
13852 unwind
.personality_index
= 1;
13854 unwind
.personality_index
= 0;
13857 /* Space for the personality routine entry. */
13858 if (unwind
.personality_index
== 0)
13860 if (unwind
.opcode_count
> 3)
13861 as_bad (_("too many unwind opcodes for personality routine 0"));
13865 /* All the data is inline in the index table. */
13868 while (unwind
.opcode_count
> 0)
13870 unwind
.opcode_count
--;
13871 data
= (data
<< 8) | unwind
.opcodes
[unwind
.opcode_count
];
13875 /* Pad with "finish" opcodes. */
13877 data
= (data
<< 8) | 0xb0;
13884 /* We get two opcodes "free" in the first word. */
13885 size
= unwind
.opcode_count
- 2;
13888 /* An extra byte is required for the opcode count. */
13889 size
= unwind
.opcode_count
+ 1;
13891 size
= (size
+ 3) >> 2;
13893 as_bad (_("too many unwind opcodes"));
13895 frag_align (2, 0, 0);
13896 record_alignment (now_seg
, 2);
13897 unwind
.table_entry
= expr_build_dot ();
13899 /* Allocate the table entry. */
13900 ptr
= frag_more ((size
<< 2) + 4);
13901 where
= frag_now_fix () - ((size
<< 2) + 4);
13903 switch (unwind
.personality_index
)
13906 /* ??? Should this be a PLT generating relocation? */
13907 /* Custom personality routine. */
13908 fix_new (frag_now
, where
, 4, unwind
.personality_routine
, 0, 1,
13909 BFD_RELOC_ARM_PREL31
);
13911 /* Indicate dependency to linker. */
13913 char *name
= "__aeabi_unwind_cpp_pr0";
13914 symbolS
*pr
= symbol_find_or_make (name
);
13915 fix_new (frag_now
, where
, 4, pr
, 0, 1, BFD_RELOC_NONE
);
13921 /* Set the first byte to the number of additional words. */
13926 /* ABI defined personality routines. */
13928 /* Three opcodes bytes are packed into the first word. */
13935 /* The size and first two opcode bytes go in the first word. */
13936 data
= ((0x80 + unwind
.personality_index
) << 8) | size
;
13942 /* Indicate dependency to linker. */
13943 char *name
[] = { "__aeabi_unwind_cpp_pr0",
13944 "__aeabi_unwind_cpp_pr1",
13945 "__aeabi_unwind_cpp_pr2" };
13946 symbolS
*pr
= symbol_find_or_make (name
[unwind
.personality_index
]);
13947 fix_new (frag_now
, where
, 4, pr
, 0, 1, BFD_RELOC_NONE
);
13952 /* Should never happen. */
13956 /* Pack the opcodes into words (MSB first), reversing the list at the same
13958 while (unwind
.opcode_count
> 0)
13962 md_number_to_chars (ptr
, data
, 4);
13967 unwind
.opcode_count
--;
13969 data
= (data
<< 8) | unwind
.opcodes
[unwind
.opcode_count
];
13972 /* Finish off the last word. */
13975 /* Pad with "finish" opcodes. */
13977 data
= (data
<< 8) | 0xb0;
13979 md_number_to_chars (ptr
, data
, 4);
13984 /* Add an empty descriptor if there is no user-specified data. */
13985 ptr
= frag_more (4);
13986 md_number_to_chars (ptr
, 0, 4);
13993 /* Parse an unwind_fnstart directive. Simply records the current location. */
13996 s_arm_unwind_fnstart (int ignored ATTRIBUTE_UNUSED
)
13998 demand_empty_rest_of_line ();
13999 /* Mark the start of the function. */
14000 unwind
.proc_start
= expr_build_dot ();
14002 /* Reset the rest of the unwind info. */
14003 unwind
.opcode_count
= 0;
14004 unwind
.table_entry
= NULL
;
14005 unwind
.personality_routine
= NULL
;
14006 unwind
.personality_index
= -1;
14007 unwind
.frame_size
= 0;
14008 unwind
.fp_offset
= 0;
14009 unwind
.fp_reg
= 13;
14010 unwind
.fp_used
= 0;
14011 unwind
.sp_restored
= 0;
14015 /* Parse a handlerdata directive. Creates the exception handling table entry
14016 for the function. */
14019 s_arm_unwind_handlerdata (int ignored ATTRIBUTE_UNUSED
)
14021 demand_empty_rest_of_line ();
14022 if (unwind
.table_entry
)
14023 as_bad (_("dupicate .handlerdata directive"));
14025 create_unwind_entry (1);
14028 /* Parse an unwind_fnend directive. Generates the index table entry. */
14031 s_arm_unwind_fnend (int ignored ATTRIBUTE_UNUSED
)
14037 demand_empty_rest_of_line ();
14039 /* Add eh table entry. */
14040 if (unwind
.table_entry
== NULL
)
14041 val
= create_unwind_entry (0);
14045 /* Add index table entry. This is two words. */
14046 start_unwind_section (unwind
.saved_seg
, 1);
14047 frag_align (2, 0, 0);
14048 record_alignment (now_seg
, 2);
14050 ptr
= frag_more (8);
14051 where
= frag_now_fix () - 8;
14053 /* Self relative offset of the function start. */
14054 fix_new (frag_now
, where
, 4, unwind
.proc_start
, 0, 1,
14055 BFD_RELOC_ARM_PREL31
);
14058 /* Inline exception table entry. */
14059 md_number_to_chars (ptr
+ 4, val
, 4);
14061 /* Self relative offset of the table entry. */
14062 fix_new (frag_now
, where
+ 4, 4, unwind
.table_entry
, 0, 1,
14063 BFD_RELOC_ARM_PREL31
);
14065 /* Restore the original section. */
14066 subseg_set (unwind
.saved_seg
, unwind
.saved_subseg
);
14070 /* Parse an unwind_cantunwind directive. */
14073 s_arm_unwind_cantunwind (int ignored ATTRIBUTE_UNUSED
)
14075 demand_empty_rest_of_line ();
14076 if (unwind
.personality_routine
|| unwind
.personality_index
!= -1)
14077 as_bad (_("personality routine specified for cantunwind frame"));
14079 unwind
.personality_index
= -2;
14083 /* Parse a personalityindex directive. */
14086 s_arm_unwind_personalityindex (int ignored ATTRIBUTE_UNUSED
)
14090 if (unwind
.personality_routine
|| unwind
.personality_index
!= -1)
14091 as_bad (_("duplicate .personalityindex directive"));
14093 SKIP_WHITESPACE ();
14097 if (exp
.X_op
!= O_constant
14098 || exp
.X_add_number
< 0 || exp
.X_add_number
> 15)
14100 as_bad (_("bad personality routine number"));
14101 ignore_rest_of_line ();
14105 unwind
.personality_index
= exp
.X_add_number
;
14107 demand_empty_rest_of_line ();
14111 /* Parse a personality directive. */
14114 s_arm_unwind_personality (int ignored ATTRIBUTE_UNUSED
)
14118 if (unwind
.personality_routine
|| unwind
.personality_index
!= -1)
14119 as_bad (_("duplicate .personality directive"));
14121 SKIP_WHITESPACE ();
14122 name
= input_line_pointer
;
14123 c
= get_symbol_end ();
14124 p
= input_line_pointer
;
14125 unwind
.personality_routine
= symbol_find_or_make (name
);
14127 SKIP_WHITESPACE ();
14128 demand_empty_rest_of_line ();
14132 /* Parse a directive saving core registers. */
14135 s_arm_unwind_save_core (void)
14141 SKIP_WHITESPACE ();
14142 range
= reg_list (&input_line_pointer
);
14145 as_bad (_("expected register list"));
14146 ignore_rest_of_line ();
14150 demand_empty_rest_of_line ();
14152 /* Turn .unwind_movsp ip followed by .unwind_save {..., ip, ...}
14153 into .unwind_save {..., sp...}. We aren't bothered about the value of
14154 ip because it is clobbered by calls. */
14155 if (unwind
.sp_restored
&& unwind
.fp_reg
== 12
14156 && (range
& 0x3000) == 0x1000)
14158 unwind
.opcode_count
--;
14159 unwind
.sp_restored
= 0;
14160 range
= (range
| 0x2000) & ~0x1000;
14161 unwind
.pending_offset
= 0;
14164 /* See if we can use the short opcodes. These pop a block of upto 8
14165 registers starting with r4, plus maybe r14. */
14166 for (n
= 0; n
< 8; n
++)
14168 /* Break at the first non-saved register. */
14169 if ((range
& (1 << (n
+ 4))) == 0)
14172 /* See if there are any other bits set. */
14173 if (n
== 0 || (range
& (0xfff0 << n
) & 0xbff0) != 0)
14175 /* Use the long form. */
14176 op
= 0x8000 | ((range
>> 4) & 0xfff);
14177 add_unwind_opcode (op
, 2);
14181 /* Use the short form. */
14182 if (range
& 0x4000)
14183 op
= 0xa8; /* Pop r14. */
14185 op
= 0xa0; /* Do not pop r14. */
14187 add_unwind_opcode (op
, 1);
14193 op
= 0xb100 | (range
& 0xf);
14194 add_unwind_opcode (op
, 2);
14197 /* Record the number of bytes pushed. */
14198 for (n
= 0; n
< 16; n
++)
14200 if (range
& (1 << n
))
14201 unwind
.frame_size
+= 4;
14206 /* Parse a directive saving FPA registers. */
14209 s_arm_unwind_save_fpa (int reg
)
14215 /* Get Number of registers to transfer. */
14216 if (skip_past_comma (&input_line_pointer
) != FAIL
)
14219 exp
.X_op
= O_illegal
;
14221 if (exp
.X_op
!= O_constant
)
14223 as_bad (_("expected , <constant>"));
14224 ignore_rest_of_line ();
14228 num_regs
= exp
.X_add_number
;
14230 if (num_regs
< 1 || num_regs
> 4)
14232 as_bad (_("number of registers must be in the range [1:4]"));
14233 ignore_rest_of_line ();
14237 demand_empty_rest_of_line ();
14242 op
= 0xb4 | (num_regs
- 1);
14243 add_unwind_opcode (op
, 1);
14248 op
= 0xc800 | (reg
<< 4) | (num_regs
- 1);
14249 add_unwind_opcode (op
, 2);
14251 unwind
.frame_size
+= num_regs
* 12;
14255 /* Parse a directive saving VFP registers. */
14258 s_arm_unwind_save_vfp (void)
14264 count
= vfp_parse_reg_list (&input_line_pointer
, ®
, 1);
14267 as_bad (_("expected register list"));
14268 ignore_rest_of_line ();
14272 demand_empty_rest_of_line ();
14277 op
= 0xb8 | (count
- 1);
14278 add_unwind_opcode (op
, 1);
14283 op
= 0xb300 | (reg
<< 4) | (count
- 1);
14284 add_unwind_opcode (op
, 2);
14286 unwind
.frame_size
+= count
* 8 + 4;
14290 /* Parse a directive saving iWMMXt registers. */
14293 s_arm_unwind_save_wmmx (void)
14302 if (*input_line_pointer
== '{')
14303 input_line_pointer
++;
14309 reg
= arm_reg_parse (&input_line_pointer
,
14310 all_reg_maps
[REG_TYPE_IWMMXT
].htab
);
14312 if (wr_register (reg
))
14314 i
= reg
& ~WR_PREFIX
;
14316 as_tsktsk (_("register list not in ascending order"));
14319 else if (wcg_register (reg
))
14321 i
= (reg
& ~WC_PREFIX
) - 8;
14323 as_tsktsk (_("register list not in ascending order"));
14324 wcg_mask
|= 1 << i
;
14328 as_bad (_("expected wr or wcgr"));
14332 SKIP_WHITESPACE ();
14333 if (*input_line_pointer
== '-')
14335 hi_reg
= arm_reg_parse (&input_line_pointer
,
14336 all_reg_maps
[REG_TYPE_IWMMXT
].htab
);
14337 if (wr_register (reg
) && wr_register (hi_reg
))
14339 for (; reg
< hi_reg
; reg
++)
14340 wr_mask
|= 1 << (reg
& ~WR_PREFIX
);
14342 else if (wcg_register (reg
) && wcg_register (hi_reg
))
14344 for (; reg
< hi_reg
; reg
++)
14345 wcg_mask
|= 1 << ((reg
& ~WC_PREFIX
) - 8);
14349 as_bad (_("bad register range"));
14354 while (skip_past_comma (&input_line_pointer
) != FAIL
);
14356 SKIP_WHITESPACE ();
14357 if (*input_line_pointer
== '}')
14358 input_line_pointer
++;
14360 demand_empty_rest_of_line ();
14362 if (wr_mask
&& wcg_mask
)
14364 as_bad (_("inconsistent register types"));
14368 /* Generate any deferred opcodes becuuse we're going to be looking at
14370 flush_pending_unwind ();
14374 for (i
= 0; i
< 16; i
++)
14376 if (wcg_mask
& (1 << i
))
14377 unwind
.frame_size
+= 4;
14379 op
= 0xc700 | wcg_mask
;
14380 add_unwind_opcode (op
, 2);
14384 for (i
= 0; i
< 16; i
++)
14386 if (wr_mask
& (1 << i
))
14387 unwind
.frame_size
+= 8;
14389 /* Attempt to combine with a previous opcode. We do this because gcc
14390 likes to output separate unwind directives for a single block of
14392 if (unwind
.opcode_count
> 0)
14394 i
= unwind
.opcodes
[unwind
.opcode_count
- 1];
14395 if ((i
& 0xf8) == 0xc0)
14398 /* Only merge if the blocks are contiguous. */
14401 if ((wr_mask
& 0xfe00) == (1 << 9))
14403 wr_mask
|= ((1 << (i
+ 11)) - 1) & 0xfc00;
14404 unwind
.opcode_count
--;
14407 else if (i
== 6 && unwind
.opcode_count
>= 2)
14409 i
= unwind
.opcodes
[unwind
.opcode_count
- 2];
14413 op
= 0xffff << (reg
- 1);
14415 || ((wr_mask
& op
) == (1u << (reg
- 1))))
14417 op
= (1 << (reg
+ i
+ 1)) - 1;
14418 op
&= ~((1 << reg
) - 1);
14420 unwind
.opcode_count
-= 2;
14427 /* We want to generate opcodes in the order the registers have been
14428 saved, ie. descending order. */
14429 for (reg
= 15; reg
>= -1; reg
--)
14431 /* Save registers in blocks. */
14433 || !(wr_mask
& (1 << reg
)))
14435 /* We found an unsaved reg. Generate opcodes to save the
14436 preceeding block. */
14442 op
= 0xc0 | (hi_reg
- 10);
14443 add_unwind_opcode (op
, 1);
14448 op
= 0xc600 | ((reg
+ 1) << 4) | ((hi_reg
- reg
) - 1);
14449 add_unwind_opcode (op
, 2);
14458 ignore_rest_of_line ();
14462 /* Parse an unwind_save directive. */
14465 s_arm_unwind_save (int ignored ATTRIBUTE_UNUSED
)
14470 /* Figure out what sort of save we have. */
14471 SKIP_WHITESPACE ();
14472 saved_ptr
= input_line_pointer
;
14474 reg
= arm_reg_parse (&input_line_pointer
, all_reg_maps
[REG_TYPE_FN
].htab
);
14477 s_arm_unwind_save_fpa (reg
);
14481 if (*input_line_pointer
== '{')
14482 input_line_pointer
++;
14484 SKIP_WHITESPACE ();
14486 reg
= arm_reg_parse (&input_line_pointer
, all_reg_maps
[REG_TYPE_RN
].htab
);
14489 input_line_pointer
= saved_ptr
;
14490 s_arm_unwind_save_core ();
14494 reg
= arm_reg_parse (&input_line_pointer
, all_reg_maps
[REG_TYPE_DN
].htab
);
14497 input_line_pointer
= saved_ptr
;
14498 s_arm_unwind_save_vfp ();
14502 reg
= arm_reg_parse (&input_line_pointer
,
14503 all_reg_maps
[REG_TYPE_IWMMXT
].htab
);
14506 input_line_pointer
= saved_ptr
;
14507 s_arm_unwind_save_wmmx ();
14511 /* TODO: Maverick registers. */
14512 as_bad (_("unrecognised register"));
14516 /* Parse an unwind_movsp directive. */
14519 s_arm_unwind_movsp (int ignored ATTRIBUTE_UNUSED
)
14524 SKIP_WHITESPACE ();
14525 reg
= reg_required_here (&input_line_pointer
, -1);
14528 as_bad (_("ARM register expected"));
14529 ignore_rest_of_line ();
14533 if (reg
== 13 || reg
== 15)
14535 as_bad (_("r%d not permitted in .unwind_movsp directive"), reg
);
14536 ignore_rest_of_line ();
14540 if (unwind
.fp_reg
!= 13)
14541 as_bad (_("unexpected .unwind_movsp directive"));
14543 /* Generate opcode to restore the value. */
14545 add_unwind_opcode (op
, 1);
14547 /* Record the information for later. */
14548 unwind
.fp_reg
= reg
;
14549 unwind
.fp_offset
= unwind
.frame_size
;
14550 unwind
.sp_restored
= 1;
14551 demand_empty_rest_of_line ();
14555 /* Parse #<number>. */
14558 require_hashconst (int * val
)
14562 SKIP_WHITESPACE ();
14563 if (*input_line_pointer
== '#')
14565 input_line_pointer
++;
14569 exp
.X_op
= O_illegal
;
14571 if (exp
.X_op
!= O_constant
)
14573 as_bad (_("expected #constant"));
14574 ignore_rest_of_line ();
14577 *val
= exp
.X_add_number
;
14581 /* Parse an unwind_pad directive. */
14584 s_arm_unwind_pad (int ignored ATTRIBUTE_UNUSED
)
14588 if (require_hashconst (&offset
) == FAIL
)
14593 as_bad (_("stack increment must be multiple of 4"));
14594 ignore_rest_of_line ();
14598 /* Don't generate any opcodes, just record the details for later. */
14599 unwind
.frame_size
+= offset
;
14600 unwind
.pending_offset
+= offset
;
14602 demand_empty_rest_of_line ();
14605 /* Parse an unwind_setfp directive. */
14608 s_arm_unwind_setfp (int ignored ATTRIBUTE_UNUSED
)
14614 fp_reg
= reg_required_here (&input_line_pointer
, -1);
14615 if (skip_past_comma (&input_line_pointer
) == FAIL
)
14618 sp_reg
= reg_required_here (&input_line_pointer
, -1);
14620 if (fp_reg
== FAIL
|| sp_reg
== FAIL
)
14622 as_bad (_("expected <reg>, <reg>"));
14623 ignore_rest_of_line ();
14627 /* Optonal constant. */
14628 if (skip_past_comma (&input_line_pointer
) != FAIL
)
14630 if (require_hashconst (&offset
) == FAIL
)
14636 demand_empty_rest_of_line ();
14638 if (sp_reg
!= 13 && sp_reg
!= unwind
.fp_reg
)
14640 as_bad (_("register must be either sp or set by a previous"
14641 "unwind_movsp directive"));
14645 /* Don't generate any opcodes, just record the information for later. */
14646 unwind
.fp_reg
= fp_reg
;
14647 unwind
.fp_used
= 1;
14649 unwind
.fp_offset
= unwind
.frame_size
- offset
;
14651 unwind
.fp_offset
-= offset
;
14654 /* Parse an unwind_raw directive. */
14657 s_arm_unwind_raw (int ignored ATTRIBUTE_UNUSED
)
14660 /* This is an arbitary limit. */
14661 unsigned char op
[16];
14664 SKIP_WHITESPACE ();
14666 if (exp
.X_op
== O_constant
14667 && skip_past_comma (&input_line_pointer
) != FAIL
)
14669 unwind
.frame_size
+= exp
.X_add_number
;
14673 exp
.X_op
= O_illegal
;
14675 if (exp
.X_op
!= O_constant
)
14677 as_bad (_("expected <offset>, <opcode>"));
14678 ignore_rest_of_line ();
14684 /* Parse the opcode. */
14689 as_bad (_("unwind opcode too long"));
14690 ignore_rest_of_line ();
14692 if (exp
.X_op
!= O_constant
|| exp
.X_add_number
& ~0xff)
14694 as_bad (_("invalid unwind opcode"));
14695 ignore_rest_of_line ();
14698 op
[count
++] = exp
.X_add_number
;
14700 /* Parse the next byte. */
14701 if (skip_past_comma (&input_line_pointer
) == FAIL
)
14707 /* Add the opcode bytes in reverse order. */
14709 add_unwind_opcode (op
[count
], 1);
14711 demand_empty_rest_of_line ();
14714 #endif /* OBJ_ELF */
14716 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
14717 of an rs_align_code fragment. */
14720 arm_handle_align (fragS
* fragP
)
14722 static char const arm_noop
[4] = { 0x00, 0x00, 0xa0, 0xe1 };
14723 static char const thumb_noop
[2] = { 0xc0, 0x46 };
14724 static char const arm_bigend_noop
[4] = { 0xe1, 0xa0, 0x00, 0x00 };
14725 static char const thumb_bigend_noop
[2] = { 0x46, 0xc0 };
14727 int bytes
, fix
, noop_size
;
14731 if (fragP
->fr_type
!= rs_align_code
)
14734 bytes
= fragP
->fr_next
->fr_address
- fragP
->fr_address
- fragP
->fr_fix
;
14735 p
= fragP
->fr_literal
+ fragP
->fr_fix
;
14738 if (bytes
> MAX_MEM_FOR_RS_ALIGN_CODE
)
14739 bytes
&= MAX_MEM_FOR_RS_ALIGN_CODE
;
14741 if (fragP
->tc_frag_data
)
14743 if (target_big_endian
)
14744 noop
= thumb_bigend_noop
;
14747 noop_size
= sizeof (thumb_noop
);
14751 if (target_big_endian
)
14752 noop
= arm_bigend_noop
;
14755 noop_size
= sizeof (arm_noop
);
14758 if (bytes
& (noop_size
- 1))
14760 fix
= bytes
& (noop_size
- 1);
14761 memset (p
, 0, fix
);
14766 while (bytes
>= noop_size
)
14768 memcpy (p
, noop
, noop_size
);
14770 bytes
-= noop_size
;
14774 fragP
->fr_fix
+= fix
;
14775 fragP
->fr_var
= noop_size
;
14778 /* Called from md_do_align. Used to create an alignment
14779 frag in a code section. */
14782 arm_frag_align_code (int n
, int max
)
14786 /* We assume that there will never be a requirement
14787 to support alignments greater than 32 bytes. */
14788 if (max
> MAX_MEM_FOR_RS_ALIGN_CODE
)
14789 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
14791 p
= frag_var (rs_align_code
,
14792 MAX_MEM_FOR_RS_ALIGN_CODE
,
14794 (relax_substateT
) max
,
14801 /* Perform target specific initialisation of a frag. */
14804 arm_init_frag (fragS
* fragP
)
14806 /* Record whether this frag is in an ARM or a THUMB area. */
14807 fragP
->tc_frag_data
= thumb_mode
;
14812 /* Convert REGNAME to a DWARF-2 register number. */
14815 tc_arm_regname_to_dw2regnum (const char *regname
)
14819 for (i
= 0; rn_table
[i
].name
; i
++)
14820 if (streq (regname
, rn_table
[i
].name
))
14821 return rn_table
[i
].number
;
14826 /* Initialize the DWARF-2 unwind information for this procedure. */
14829 tc_arm_frame_initial_instructions (void)
14831 cfi_add_CFA_def_cfa (REG_SP
, 0);
14835 /* This table describes all the machine specific pseudo-ops the assembler
14836 has to support. The fields are:
14837 pseudo-op name without dot
14838 function to call to execute this pseudo-op
14839 Integer arg to pass to the function. */
14841 const pseudo_typeS md_pseudo_table
[] =
14843 /* Never called because '.req' does not start a line. */
14844 { "req", s_req
, 0 },
14845 { "unreq", s_unreq
, 0 },
14846 { "bss", s_bss
, 0 },
14847 { "align", s_align
, 0 },
14848 { "arm", s_arm
, 0 },
14849 { "thumb", s_thumb
, 0 },
14850 { "code", s_code
, 0 },
14851 { "force_thumb", s_force_thumb
, 0 },
14852 { "thumb_func", s_thumb_func
, 0 },
14853 { "thumb_set", s_thumb_set
, 0 },
14854 { "even", s_even
, 0 },
14855 { "ltorg", s_ltorg
, 0 },
14856 { "pool", s_ltorg
, 0 },
14858 { "word", s_arm_elf_cons
, 4 },
14859 { "long", s_arm_elf_cons
, 4 },
14860 { "rel31", s_arm_rel31
, 0 },
14861 { "fnstart", s_arm_unwind_fnstart
, 0 },
14862 { "fnend", s_arm_unwind_fnend
, 0 },
14863 { "cantunwind", s_arm_unwind_cantunwind
, 0 },
14864 { "personality", s_arm_unwind_personality
, 0 },
14865 { "personalityindex", s_arm_unwind_personalityindex
, 0 },
14866 { "handlerdata", s_arm_unwind_handlerdata
, 0 },
14867 { "save", s_arm_unwind_save
, 0 },
14868 { "movsp", s_arm_unwind_movsp
, 0 },
14869 { "pad", s_arm_unwind_pad
, 0 },
14870 { "setfp", s_arm_unwind_setfp
, 0 },
14871 { "unwind_raw", s_arm_unwind_raw
, 0 },
14873 { "word", cons
, 4},
14875 { "extend", float_cons
, 'x' },
14876 { "ldouble", float_cons
, 'x' },
14877 { "packed", float_cons
, 'p' },