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
},
10961 if ( (arm_ops_hsh
= hash_new ()) == NULL
10962 || (arm_tops_hsh
= hash_new ()) == NULL
10963 || (arm_cond_hsh
= hash_new ()) == NULL
10964 || (arm_shift_hsh
= hash_new ()) == NULL
10965 || (arm_psr_hsh
= hash_new ()) == NULL
)
10966 as_fatal (_("virtual memory exhausted"));
10968 build_arm_ops_hsh ();
10969 for (i
= 0; i
< sizeof (tinsns
) / sizeof (struct thumb_opcode
); i
++)
10970 hash_insert (arm_tops_hsh
, tinsns
[i
].template, (PTR
) (tinsns
+ i
));
10971 for (i
= 0; i
< sizeof (conds
) / sizeof (struct asm_cond
); i
++)
10972 hash_insert (arm_cond_hsh
, conds
[i
].template, (PTR
) (conds
+ i
));
10973 for (i
= 0; i
< sizeof (shift_names
) / sizeof (struct asm_shift_name
); i
++)
10974 hash_insert (arm_shift_hsh
, shift_names
[i
].name
, (PTR
) (shift_names
+ i
));
10975 for (i
= 0; i
< sizeof (psrs
) / sizeof (struct asm_psr
); i
++)
10976 hash_insert (arm_psr_hsh
, psrs
[i
].template, (PTR
) (psrs
+ i
));
10978 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
10979 build_reg_hsh (all_reg_maps
+ i
);
10981 set_constant_flonums ();
10983 /* Set the cpu variant based on the command-line options. We prefer
10984 -mcpu= over -march= if both are set (as for GCC); and we prefer
10985 -mfpu= over any other way of setting the floating point unit.
10986 Use of legacy options with new options are faulted. */
10987 if (legacy_cpu
!= -1)
10989 if (mcpu_cpu_opt
!= -1 || march_cpu_opt
!= -1)
10990 as_bad (_("use of old and new-style options to set CPU type"));
10992 mcpu_cpu_opt
= legacy_cpu
;
10994 else if (mcpu_cpu_opt
== -1)
10995 mcpu_cpu_opt
= march_cpu_opt
;
10997 if (legacy_fpu
!= -1)
10999 if (mfpu_opt
!= -1)
11000 as_bad (_("use of old and new-style options to set FPU type"));
11002 mfpu_opt
= legacy_fpu
;
11004 else if (mfpu_opt
== -1)
11006 #if !(defined (TE_LINUX) || defined (TE_NetBSD) || defined (TE_VXWORKS))
11007 /* Some environments specify a default FPU. If they don't, infer it
11008 from the processor. */
11009 if (mcpu_fpu_opt
!= -1)
11010 mfpu_opt
= mcpu_fpu_opt
;
11012 mfpu_opt
= march_fpu_opt
;
11014 mfpu_opt
= FPU_DEFAULT
;
11018 if (mfpu_opt
== -1)
11020 if (mcpu_cpu_opt
== -1)
11021 mfpu_opt
= FPU_DEFAULT
;
11022 else if (mcpu_cpu_opt
& ARM_EXT_V5
)
11023 mfpu_opt
= FPU_ARCH_VFP_V2
;
11025 mfpu_opt
= FPU_ARCH_FPA
;
11028 if (mcpu_cpu_opt
== -1)
11029 mcpu_cpu_opt
= CPU_DEFAULT
;
11031 cpu_variant
= mcpu_cpu_opt
| mfpu_opt
;
11033 #if defined OBJ_COFF || defined OBJ_ELF
11035 unsigned int flags
= 0;
11037 #if defined OBJ_ELF
11038 flags
= meabi_flags
;
11040 switch (meabi_flags
)
11042 case EF_ARM_EABI_UNKNOWN
:
11044 /* Set the flags in the private structure. */
11045 if (uses_apcs_26
) flags
|= F_APCS26
;
11046 if (support_interwork
) flags
|= F_INTERWORK
;
11047 if (uses_apcs_float
) flags
|= F_APCS_FLOAT
;
11048 if (pic_code
) flags
|= F_PIC
;
11049 if ((cpu_variant
& FPU_ANY
) == FPU_NONE
11050 || (cpu_variant
& FPU_ANY
) == FPU_ARCH_VFP
) /* VFP layout only. */
11051 flags
|= F_SOFT_FLOAT
;
11053 switch (mfloat_abi_opt
)
11055 case ARM_FLOAT_ABI_SOFT
:
11056 case ARM_FLOAT_ABI_SOFTFP
:
11057 flags
|= F_SOFT_FLOAT
;
11060 case ARM_FLOAT_ABI_HARD
:
11061 if (flags
& F_SOFT_FLOAT
)
11062 as_bad (_("hard-float conflicts with specified fpu"));
11066 /* Using VFP conventions (even if soft-float). */
11067 if (cpu_variant
& FPU_VFP_EXT_NONE
)
11068 flags
|= F_VFP_FLOAT
;
11070 #if defined OBJ_ELF
11071 if (cpu_variant
& FPU_ARCH_MAVERICK
)
11072 flags
|= EF_ARM_MAVERICK_FLOAT
;
11075 case EF_ARM_EABI_VER4
:
11076 /* No additional flags to set. */
11083 bfd_set_private_flags (stdoutput
, flags
);
11085 /* We have run out flags in the COFF header to encode the
11086 status of ATPCS support, so instead we create a dummy,
11087 empty, debug section called .arm.atpcs. */
11092 sec
= bfd_make_section (stdoutput
, ".arm.atpcs");
11096 bfd_set_section_flags
11097 (stdoutput
, sec
, SEC_READONLY
| SEC_DEBUGGING
/* | SEC_HAS_CONTENTS */);
11098 bfd_set_section_size (stdoutput
, sec
, 0);
11099 bfd_set_section_contents (stdoutput
, sec
, NULL
, 0, 0);
11105 /* Record the CPU type as well. */
11106 switch (cpu_variant
& ARM_CPU_MASK
)
11109 mach
= bfd_mach_arm_2
;
11112 case ARM_3
: /* Also ARM_250. */
11113 mach
= bfd_mach_arm_2a
;
11116 case ARM_6
: /* Also ARM_7. */
11117 mach
= bfd_mach_arm_3
;
11121 mach
= bfd_mach_arm_unknown
;
11125 /* Catch special cases. */
11126 if (cpu_variant
& ARM_CEXT_IWMMXT
)
11127 mach
= bfd_mach_arm_iWMMXt
;
11128 else if (cpu_variant
& ARM_CEXT_XSCALE
)
11129 mach
= bfd_mach_arm_XScale
;
11130 else if (cpu_variant
& ARM_CEXT_MAVERICK
)
11131 mach
= bfd_mach_arm_ep9312
;
11132 else if (cpu_variant
& ARM_EXT_V5E
)
11133 mach
= bfd_mach_arm_5TE
;
11134 else if (cpu_variant
& ARM_EXT_V5
)
11136 if (cpu_variant
& ARM_EXT_V4T
)
11137 mach
= bfd_mach_arm_5T
;
11139 mach
= bfd_mach_arm_5
;
11141 else if (cpu_variant
& ARM_EXT_V4
)
11143 if (cpu_variant
& ARM_EXT_V4T
)
11144 mach
= bfd_mach_arm_4T
;
11146 mach
= bfd_mach_arm_4
;
11148 else if (cpu_variant
& ARM_EXT_V3M
)
11149 mach
= bfd_mach_arm_3M
;
11151 bfd_set_arch_mach (stdoutput
, TARGET_ARCH
, mach
);
11154 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11155 for use in the a.out file, and stores them in the array pointed to by buf.
11156 This knows about the endian-ness of the target machine and does
11157 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11158 2 (short) and 4 (long) Floating numbers are put out as a series of
11159 LITTLENUMS (shorts, here at least). */
11162 md_number_to_chars (char * buf
, valueT val
, int n
)
11164 if (target_big_endian
)
11165 number_to_chars_bigendian (buf
, val
, n
);
11167 number_to_chars_littleendian (buf
, val
, n
);
11171 md_chars_to_number (char * buf
, int n
)
11174 unsigned char * where
= (unsigned char *) buf
;
11176 if (target_big_endian
)
11181 result
|= (*where
++ & 255);
11189 result
|= (where
[n
] & 255);
11196 /* Turn a string in input_line_pointer into a floating point constant
11197 of type TYPE, and store the appropriate bytes in *LITP. The number
11198 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11199 returned, or NULL on OK.
11201 Note that fp constants aren't represent in the normal way on the ARM.
11202 In big endian mode, things are as expected. However, in little endian
11203 mode fp constants are big-endian word-wise, and little-endian byte-wise
11204 within the words. For example, (double) 1.1 in big endian mode is
11205 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11206 the byte sequence 99 99 f1 3f 9a 99 99 99.
11208 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11211 md_atof (int type
, char * litP
, int * sizeP
)
11214 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
11246 return _("bad call to MD_ATOF()");
11249 t
= atof_ieee (input_line_pointer
, type
, words
);
11251 input_line_pointer
= t
;
11254 if (target_big_endian
)
11256 for (i
= 0; i
< prec
; i
++)
11258 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
11264 if (cpu_variant
& FPU_ARCH_VFP
)
11265 for (i
= prec
- 1; i
>= 0; i
--)
11267 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
11271 /* For a 4 byte float the order of elements in `words' is 1 0.
11272 For an 8 byte float the order is 1 0 3 2. */
11273 for (i
= 0; i
< prec
; i
+= 2)
11275 md_number_to_chars (litP
, (valueT
) words
[i
+ 1], 2);
11276 md_number_to_chars (litP
+ 2, (valueT
) words
[i
], 2);
11284 /* The knowledge of the PC's pipeline offset is built into the insns
11288 md_pcrel_from (fixS
* fixP
)
11291 && S_GET_SEGMENT (fixP
->fx_addsy
) == undefined_section
11292 && fixP
->fx_subsy
== NULL
)
11295 if (fixP
->fx_pcrel
&& (fixP
->fx_r_type
== BFD_RELOC_ARM_THUMB_ADD
))
11297 /* PC relative addressing on the Thumb is slightly odd
11298 as the bottom two bits of the PC are forced to zero
11299 for the calculation. */
11300 return (fixP
->fx_where
+ fixP
->fx_frag
->fr_address
) & ~3;
11304 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
11305 so we un-adjust here to compensate for the accommodation. */
11306 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
+ 8;
11308 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
11312 /* Round up a section size to the appropriate boundary. */
11315 md_section_align (segT segment ATTRIBUTE_UNUSED
,
11321 /* Round all sects to multiple of 4. */
11322 return (size
+ 3) & ~3;
11326 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
11327 Otherwise we have no need to default values of symbols. */
11330 md_undefined_symbol (char * name ATTRIBUTE_UNUSED
)
11333 if (name
[0] == '_' && name
[1] == 'G'
11334 && streq (name
, GLOBAL_OFFSET_TABLE_NAME
))
11338 if (symbol_find (name
))
11339 as_bad ("GOT already in the symbol table");
11341 GOT_symbol
= symbol_new (name
, undefined_section
,
11342 (valueT
) 0, & zero_address_frag
);
11353 md_apply_fix3 (fixS
* fixP
,
11357 offsetT value
= * valP
;
11359 unsigned int newimm
;
11360 unsigned long temp
;
11362 char * buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
11363 arm_fix_data
* arm_data
= (arm_fix_data
*) fixP
->tc_fix_data
;
11365 assert (fixP
->fx_r_type
<= BFD_RELOC_UNUSED
);
11367 /* Note whether this will delete the relocation. */
11368 if (fixP
->fx_addsy
== 0 && !fixP
->fx_pcrel
)
11371 /* If this symbol is in a different section then we need to leave it for
11372 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
11373 so we have to undo it's effects here. */
11374 if (fixP
->fx_pcrel
)
11376 if (fixP
->fx_addsy
!= NULL
11377 && S_IS_DEFINED (fixP
->fx_addsy
)
11378 && S_GET_SEGMENT (fixP
->fx_addsy
) != seg
)
11379 value
+= md_pcrel_from (fixP
);
11382 /* Remember value for emit_reloc. */
11383 fixP
->fx_addnumber
= value
;
11385 switch (fixP
->fx_r_type
)
11387 case BFD_RELOC_NONE
:
11388 /* This will need to go in the object file. */
11392 case BFD_RELOC_ARM_IMMEDIATE
:
11393 /* We claim that this fixup has been processed here,
11394 even if in fact we generate an error because we do
11395 not have a reloc for it, so tc_gen_reloc will reject it. */
11399 && ! S_IS_DEFINED (fixP
->fx_addsy
))
11401 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11402 _("undefined symbol %s used as an immediate value"),
11403 S_GET_NAME (fixP
->fx_addsy
));
11407 newimm
= validate_immediate (value
);
11408 temp
= md_chars_to_number (buf
, INSN_SIZE
);
11410 /* If the instruction will fail, see if we can fix things up by
11411 changing the opcode. */
11412 if (newimm
== (unsigned int) FAIL
11413 && (newimm
= negate_data_op (&temp
, value
)) == (unsigned int) FAIL
)
11415 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11416 _("invalid constant (%lx) after fixup"),
11417 (unsigned long) value
);
11421 newimm
|= (temp
& 0xfffff000);
11422 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
11425 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
11427 unsigned int highpart
= 0;
11428 unsigned int newinsn
= 0xe1a00000; /* nop. */
11430 newimm
= validate_immediate (value
);
11431 temp
= md_chars_to_number (buf
, INSN_SIZE
);
11433 /* If the instruction will fail, see if we can fix things up by
11434 changing the opcode. */
11435 if (newimm
== (unsigned int) FAIL
11436 && (newimm
= negate_data_op (& temp
, value
)) == (unsigned int) FAIL
)
11438 /* No ? OK - try using two ADD instructions to generate
11440 newimm
= validate_immediate_twopart (value
, & highpart
);
11442 /* Yes - then make sure that the second instruction is
11444 if (newimm
!= (unsigned int) FAIL
)
11446 /* Still No ? Try using a negated value. */
11447 else if ((newimm
= validate_immediate_twopart (- value
, & highpart
)) != (unsigned int) FAIL
)
11448 temp
= newinsn
= (temp
& OPCODE_MASK
) | OPCODE_SUB
<< DATA_OP_SHIFT
;
11449 /* Otherwise - give up. */
11452 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11453 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
11458 /* Replace the first operand in the 2nd instruction (which
11459 is the PC) with the destination register. We have
11460 already added in the PC in the first instruction and we
11461 do not want to do it again. */
11462 newinsn
&= ~ 0xf0000;
11463 newinsn
|= ((newinsn
& 0x0f000) << 4);
11466 newimm
|= (temp
& 0xfffff000);
11467 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
11469 highpart
|= (newinsn
& 0xfffff000);
11470 md_number_to_chars (buf
+ INSN_SIZE
, (valueT
) highpart
, INSN_SIZE
);
11474 case BFD_RELOC_ARM_OFFSET_IMM
:
11480 if (validate_offset_imm (value
, 0) == FAIL
)
11482 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11483 _("bad immediate value for offset (%ld)"),
11488 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11489 newval
&= 0xff7ff000;
11490 newval
|= value
| (sign
? INDEX_UP
: 0);
11491 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11494 case BFD_RELOC_ARM_OFFSET_IMM8
:
11495 case BFD_RELOC_ARM_HWLITERAL
:
11501 if (validate_offset_imm (value
, 1) == FAIL
)
11503 if (fixP
->fx_r_type
== BFD_RELOC_ARM_HWLITERAL
)
11504 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11505 _("invalid literal constant: pool needs to be closer"));
11507 as_bad (_("bad immediate value for half-word offset (%ld)"),
11512 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11513 newval
&= 0xff7ff0f0;
11514 newval
|= ((value
>> 4) << 8) | (value
& 0xf) | (sign
? INDEX_UP
: 0);
11515 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11518 case BFD_RELOC_ARM_LITERAL
:
11524 if (validate_offset_imm (value
, 0) == FAIL
)
11526 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11527 _("invalid literal constant: pool needs to be closer"));
11531 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11532 newval
&= 0xff7ff000;
11533 newval
|= value
| (sign
? INDEX_UP
: 0);
11534 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11537 case BFD_RELOC_ARM_SHIFT_IMM
:
11538 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11539 if (((unsigned long) value
) > 32
11541 && (((newval
& 0x60) == 0) || (newval
& 0x60) == 0x60)))
11543 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11544 _("shift expression is too large"));
11549 /* Shifts of zero must be done as lsl. */
11551 else if (value
== 32)
11553 newval
&= 0xfffff07f;
11554 newval
|= (value
& 0x1f) << 7;
11555 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11558 case BFD_RELOC_ARM_SMI
:
11559 if (((unsigned long) value
) > 0xffff)
11560 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11561 _("invalid smi expression"));
11562 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xfff000f0;
11563 newval
|= (value
& 0xf) | ((value
& 0xfff0) << 4);
11564 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11567 case BFD_RELOC_ARM_SWI
:
11568 if (arm_data
->thumb_mode
)
11570 if (((unsigned long) value
) > 0xff)
11571 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11572 _("invalid swi expression"));
11573 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xff00;
11575 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11579 if (((unsigned long) value
) > 0x00ffffff)
11580 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11581 _("invalid swi expression"));
11582 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff000000;
11584 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11588 case BFD_RELOC_ARM_MULTI
:
11589 if (((unsigned long) value
) > 0xffff)
11590 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11591 _("invalid expression in load/store multiple"));
11592 newval
= value
| md_chars_to_number (buf
, INSN_SIZE
);
11593 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11596 case BFD_RELOC_ARM_PCREL_BRANCH
:
11597 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11599 /* Sign-extend a 24-bit number. */
11600 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
11603 value
= fixP
->fx_offset
;
11606 /* We are going to store value (shifted right by two) in the
11607 instruction, in a 24 bit, signed field. Thus we need to check
11608 that none of the top 8 bits of the shifted value (top 7 bits of
11609 the unshifted, unsigned value) are set, or that they are all set. */
11610 if ((value
& ~ ((offsetT
) 0x1ffffff)) != 0
11611 && ((value
& ~ ((offsetT
) 0x1ffffff)) != ~ ((offsetT
) 0x1ffffff)))
11614 /* Normally we would be stuck at this point, since we cannot store
11615 the absolute address that is the destination of the branch in the
11616 24 bits of the branch instruction. If however, we happen to know
11617 that the destination of the branch is in the same section as the
11618 branch instruction itself, then we can compute the relocation for
11619 ourselves and not have to bother the linker with it.
11621 FIXME: The test for OBJ_ELF is only here because I have not
11622 worked out how to do this for OBJ_COFF. */
11623 if (fixP
->fx_addsy
!= NULL
11624 && S_IS_DEFINED (fixP
->fx_addsy
)
11625 && S_GET_SEGMENT (fixP
->fx_addsy
) == seg
)
11627 /* Get pc relative value to go into the branch. */
11630 /* Permit a backward branch provided that enough bits
11631 are set. Allow a forwards branch, provided that
11632 enough bits are clear. */
11633 if ( (value
& ~ ((offsetT
) 0x1ffffff)) == ~ ((offsetT
) 0x1ffffff)
11634 || (value
& ~ ((offsetT
) 0x1ffffff)) == 0)
11638 if (! fixP
->fx_done
)
11640 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11641 _("GAS can't handle same-section branch dest >= 0x04000000"));
11645 value
+= SEXT24 (newval
);
11647 if ( (value
& ~ ((offsetT
) 0xffffff)) != 0
11648 && ((value
& ~ ((offsetT
) 0xffffff)) != ~ ((offsetT
) 0xffffff)))
11649 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11650 _("out of range branch"));
11652 if (seg
->use_rela_p
&& !fixP
->fx_done
)
11654 /* Must unshift the value before storing it in the addend. */
11657 fixP
->fx_offset
= value
;
11659 fixP
->fx_addnumber
= value
;
11660 newval
= newval
& 0xff000000;
11663 newval
= (value
& 0x00ffffff) | (newval
& 0xff000000);
11664 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11667 case BFD_RELOC_ARM_PCREL_BLX
:
11670 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11673 value
= fixP
->fx_offset
;
11675 hbit
= (value
>> 1) & 1;
11676 value
= (value
>> 2) & 0x00ffffff;
11677 value
= (value
+ (newval
& 0x00ffffff)) & 0x00ffffff;
11679 if (seg
->use_rela_p
&& !fixP
->fx_done
)
11681 /* Must sign-extend and unshift the value before storing
11682 it in the addend. */
11683 value
= SEXT24 (value
);
11684 value
= (value
<< 2) | hbit
;
11686 fixP
->fx_offset
= value
;
11688 fixP
->fx_addnumber
= value
;
11689 newval
= newval
& 0xfe000000;
11692 newval
= value
| (newval
& 0xfe000000) | (hbit
<< 24);
11693 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11697 case BFD_RELOC_THUMB_PCREL_BRANCH9
: /* Conditional branch. */
11698 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11700 addressT diff
= (newval
& 0xff) << 1;
11705 if ((value
& ~0xff) && ((value
& ~0xff) != ~0xff))
11706 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11707 _("branch out of range"));
11708 if (seg
->use_rela_p
&& !fixP
->fx_done
)
11711 fixP
->fx_offset
= value
;
11713 fixP
->fx_addnumber
= value
;
11714 newval
= newval
& 0xff00;
11717 newval
= (newval
& 0xff00) | ((value
& 0x1ff) >> 1);
11719 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11722 case BFD_RELOC_THUMB_PCREL_BRANCH12
: /* Unconditional branch. */
11723 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11725 addressT diff
= (newval
& 0x7ff) << 1;
11730 if ((value
& ~0x7ff) && ((value
& ~0x7ff) != ~0x7ff))
11731 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11732 _("branch out of range"));
11733 if (seg
->use_rela_p
&& !fixP
->fx_done
)
11736 fixP
->fx_offset
= value
;
11738 fixP
->fx_addnumber
= value
;
11739 newval
= newval
& 0xf800;
11742 newval
= (newval
& 0xf800) | ((value
& 0xfff) >> 1);
11744 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11747 case BFD_RELOC_THUMB_PCREL_BLX
:
11748 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
11753 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11754 newval2
= md_chars_to_number (buf
+ THUMB_SIZE
, THUMB_SIZE
);
11755 diff
= ((newval
& 0x7ff) << 12) | ((newval2
& 0x7ff) << 1);
11756 if (diff
& 0x400000)
11759 value
= fixP
->fx_offset
;
11763 if ((value
& ~0x3fffff) && ((value
& ~0x3fffff) != ~0x3fffff))
11764 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11765 _("branch with link out of range"));
11767 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
)
11768 /* For a BLX instruction, make sure that the relocation is rounded up
11769 to a word boundary. This follows the semantics of the instruction
11770 which specifies that bit 1 of the target address will come from bit
11771 1 of the base address. */
11772 value
= (value
+ 1) & ~ 1;
11774 if (seg
->use_rela_p
&& !fixP
->fx_done
)
11777 fixP
->fx_offset
= value
;
11779 fixP
->fx_addnumber
= value
;
11780 newval
= newval
& 0xf800;
11781 newval2
= newval2
& 0xf800;
11785 newval
= (newval
& 0xf800) | ((value
& 0x7fffff) >> 12);
11786 newval2
= (newval2
& 0xf800) | ((value
& 0xfff) >> 1);
11788 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11789 md_number_to_chars (buf
+ THUMB_SIZE
, newval2
, THUMB_SIZE
);
11794 if (seg
->use_rela_p
&& !fixP
->fx_done
)
11796 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11797 md_number_to_chars (buf
, value
, 1);
11801 value
= fixP
->fx_offset
;
11802 md_number_to_chars (buf
, value
, 1);
11808 if (seg
->use_rela_p
&& !fixP
->fx_done
)
11810 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11811 md_number_to_chars (buf
, value
, 2);
11815 value
= fixP
->fx_offset
;
11816 md_number_to_chars (buf
, value
, 2);
11822 case BFD_RELOC_ARM_GOT32
:
11823 case BFD_RELOC_ARM_GOTOFF
:
11824 case BFD_RELOC_ARM_TARGET2
:
11825 if (seg
->use_rela_p
&& !fixP
->fx_done
)
11827 md_number_to_chars (buf
, 0, 4);
11831 case BFD_RELOC_RVA
:
11833 case BFD_RELOC_ARM_TARGET1
:
11834 case BFD_RELOC_ARM_ROSEGREL32
:
11835 case BFD_RELOC_ARM_SBREL32
:
11836 case BFD_RELOC_32_PCREL
:
11837 if (seg
->use_rela_p
&& !fixP
->fx_done
)
11839 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11840 md_number_to_chars (buf
, value
, 4);
11844 value
= fixP
->fx_offset
;
11845 md_number_to_chars (buf
, value
, 4);
11851 case BFD_RELOC_ARM_PREL31
:
11852 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11854 newval
= md_chars_to_number (buf
, 4) & 0x80000000;
11855 if ((value
^ (value
>> 1)) & 0x40000000)
11857 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11858 _("rel31 relocation overflow"));
11860 newval
|= value
& 0x7fffffff;
11861 md_number_to_chars (buf
, newval
, 4);
11865 case BFD_RELOC_ARM_PLT32
:
11866 /* It appears the instruction is fully prepared at this point. */
11870 case BFD_RELOC_ARM_CP_OFF_IMM
:
11872 if (value
< -1023 || value
> 1023 || (value
& 3))
11873 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11874 _("illegal value for co-processor offset"));
11877 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
11878 newval
|= (value
>> 2) | (sign
? INDEX_UP
: 0);
11879 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11882 case BFD_RELOC_ARM_CP_OFF_IMM_S2
:
11884 if (value
< -255 || value
> 255)
11885 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11886 _("Illegal value for co-processor offset"));
11889 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
11890 newval
|= value
| (sign
? INDEX_UP
: 0);
11891 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11894 case BFD_RELOC_ARM_THUMB_OFFSET
:
11895 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11896 /* Exactly what ranges, and where the offset is inserted depends
11897 on the type of instruction, we can establish this from the
11899 switch (newval
>> 12)
11901 case 4: /* PC load. */
11902 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
11903 forced to zero for these loads, so we will need to round
11904 up the offset if the instruction address is not word
11905 aligned (since the final address produced must be, and
11906 we can only describe word-aligned immediate offsets). */
11908 if ((fixP
->fx_frag
->fr_address
+ fixP
->fx_where
+ value
) & 3)
11909 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11910 _("invalid offset, target not word aligned (0x%08X)"),
11911 (unsigned int) (fixP
->fx_frag
->fr_address
11912 + fixP
->fx_where
+ value
));
11914 if ((value
+ 2) & ~0x3fe)
11915 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11916 _("invalid offset, value too big (0x%08lX)"),
11919 /* Round up, since pc will be rounded down. */
11920 newval
|= (value
+ 2) >> 2;
11923 case 9: /* SP load/store. */
11924 if (value
& ~0x3fc)
11925 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11926 _("invalid offset, value too big (0x%08lX)"),
11928 newval
|= value
>> 2;
11931 case 6: /* Word load/store. */
11933 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11934 _("invalid offset, value too big (0x%08lX)"),
11936 newval
|= value
<< 4; /* 6 - 2. */
11939 case 7: /* Byte load/store. */
11941 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11942 _("invalid offset, value too big (0x%08lX)"),
11944 newval
|= value
<< 6;
11947 case 8: /* Halfword load/store. */
11949 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11950 _("invalid offset, value too big (0x%08lX)"),
11952 newval
|= value
<< 5; /* 6 - 1. */
11956 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11957 "Unable to process relocation for thumb opcode: %lx",
11958 (unsigned long) newval
);
11961 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11964 case BFD_RELOC_ARM_THUMB_ADD
:
11965 /* This is a complicated relocation, since we use it for all of
11966 the following immediate relocations:
11970 9bit ADD/SUB SP word-aligned
11971 10bit ADD PC/SP word-aligned
11973 The type of instruction being processed is encoded in the
11980 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11982 int rd
= (newval
>> 4) & 0xf;
11983 int rs
= newval
& 0xf;
11984 int subtract
= newval
& 0x8000;
11988 if (value
& ~0x1fc)
11989 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11990 _("invalid immediate for stack address calculation"));
11991 newval
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
11992 newval
|= value
>> 2;
11994 else if (rs
== REG_PC
|| rs
== REG_SP
)
11998 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11999 _("invalid immediate for address calculation (value = 0x%08lX)"),
12000 (unsigned long) value
);
12001 newval
= (rs
== REG_PC
? T_OPCODE_ADD_PC
: T_OPCODE_ADD_SP
);
12003 newval
|= value
>> 2;
12008 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12009 _("invalid 8bit immediate"));
12010 newval
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
12011 newval
|= (rd
<< 8) | value
;
12016 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12017 _("invalid 3bit immediate"));
12018 newval
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
12019 newval
|= rd
| (rs
<< 3) | (value
<< 6);
12022 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12025 case BFD_RELOC_ARM_THUMB_IMM
:
12026 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12027 switch (newval
>> 11)
12029 case 0x04: /* 8bit immediate MOV. */
12030 case 0x05: /* 8bit immediate CMP. */
12031 if (value
< 0 || value
> 255)
12032 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12033 _("invalid immediate: %ld is too large"),
12041 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12044 case BFD_RELOC_ARM_THUMB_SHIFT
:
12045 /* 5bit shift value (0..31). */
12046 if (value
< 0 || value
> 31)
12047 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12048 _("illegal Thumb shift value: %ld"), (long) value
);
12049 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xf03f;
12050 newval
|= value
<< 6;
12051 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12054 case BFD_RELOC_VTABLE_INHERIT
:
12055 case BFD_RELOC_VTABLE_ENTRY
:
12059 case BFD_RELOC_UNUSED
:
12061 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12062 _("bad relocation fixup type (%d)"), fixP
->fx_r_type
);
12066 /* Translate internal representation of relocation info to BFD target
12070 tc_gen_reloc (asection
* section ATTRIBUTE_UNUSED
,
12074 bfd_reloc_code_real_type code
;
12076 reloc
= xmalloc (sizeof (arelent
));
12078 reloc
->sym_ptr_ptr
= xmalloc (sizeof (asymbol
*));
12079 *reloc
->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
12080 reloc
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
12082 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12084 if (fixp
->fx_pcrel
== 0)
12085 reloc
->addend
= fixp
->fx_offset
;
12087 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
12088 #else /* OBJ_ELF */
12089 reloc
->addend
= fixp
->fx_offset
;
12092 switch (fixp
->fx_r_type
)
12095 if (fixp
->fx_pcrel
)
12097 code
= BFD_RELOC_8_PCREL
;
12102 if (fixp
->fx_pcrel
)
12104 code
= BFD_RELOC_16_PCREL
;
12109 if (fixp
->fx_pcrel
)
12111 code
= BFD_RELOC_32_PCREL
;
12115 case BFD_RELOC_NONE
:
12116 case BFD_RELOC_ARM_PCREL_BRANCH
:
12117 case BFD_RELOC_ARM_PCREL_BLX
:
12118 case BFD_RELOC_RVA
:
12119 case BFD_RELOC_THUMB_PCREL_BRANCH9
:
12120 case BFD_RELOC_THUMB_PCREL_BRANCH12
:
12121 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
12122 case BFD_RELOC_THUMB_PCREL_BLX
:
12123 case BFD_RELOC_VTABLE_ENTRY
:
12124 case BFD_RELOC_VTABLE_INHERIT
:
12125 code
= fixp
->fx_r_type
;
12128 case BFD_RELOC_ARM_LITERAL
:
12129 case BFD_RELOC_ARM_HWLITERAL
:
12130 /* If this is called then the a literal has
12131 been referenced across a section boundary. */
12132 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12133 _("literal referenced across section boundary"));
12137 case BFD_RELOC_ARM_GOT32
:
12138 case BFD_RELOC_ARM_GOTOFF
:
12139 case BFD_RELOC_ARM_PLT32
:
12140 case BFD_RELOC_ARM_TARGET1
:
12141 case BFD_RELOC_ARM_ROSEGREL32
:
12142 case BFD_RELOC_ARM_SBREL32
:
12143 case BFD_RELOC_ARM_PREL31
:
12144 case BFD_RELOC_ARM_TARGET2
:
12145 code
= fixp
->fx_r_type
;
12149 case BFD_RELOC_ARM_IMMEDIATE
:
12150 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12151 _("internal relocation (type: IMMEDIATE) not fixed up"));
12154 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
12155 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12156 _("ADRL used for a symbol not defined in the same file"));
12159 case BFD_RELOC_ARM_OFFSET_IMM
:
12160 if (fixp
->fx_addsy
!= NULL
12161 && !S_IS_DEFINED (fixp
->fx_addsy
)
12162 && S_IS_LOCAL (fixp
->fx_addsy
))
12164 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12165 _("undefined local label `%s'"),
12166 S_GET_NAME (fixp
->fx_addsy
));
12170 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12171 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
12178 switch (fixp
->fx_r_type
)
12180 case BFD_RELOC_NONE
: type
= "NONE"; break;
12181 case BFD_RELOC_ARM_OFFSET_IMM8
: type
= "OFFSET_IMM8"; break;
12182 case BFD_RELOC_ARM_SHIFT_IMM
: type
= "SHIFT_IMM"; break;
12183 case BFD_RELOC_ARM_SMI
: type
= "SMI"; break;
12184 case BFD_RELOC_ARM_SWI
: type
= "SWI"; break;
12185 case BFD_RELOC_ARM_MULTI
: type
= "MULTI"; break;
12186 case BFD_RELOC_ARM_CP_OFF_IMM
: type
= "CP_OFF_IMM"; break;
12187 case BFD_RELOC_ARM_THUMB_ADD
: type
= "THUMB_ADD"; break;
12188 case BFD_RELOC_ARM_THUMB_SHIFT
: type
= "THUMB_SHIFT"; break;
12189 case BFD_RELOC_ARM_THUMB_IMM
: type
= "THUMB_IMM"; break;
12190 case BFD_RELOC_ARM_THUMB_OFFSET
: type
= "THUMB_OFFSET"; break;
12191 default: type
= _("<unknown>"); break;
12193 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12194 _("cannot represent %s relocation in this object file format"),
12201 if ((code
== BFD_RELOC_32_PCREL
|| code
== BFD_RELOC_32
)
12203 && fixp
->fx_addsy
== GOT_symbol
)
12205 code
= BFD_RELOC_ARM_GOTPC
;
12206 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
12210 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, code
);
12212 if (reloc
->howto
== NULL
)
12214 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12215 _("cannot represent %s relocation in this object file format"),
12216 bfd_get_reloc_code_name (code
));
12220 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12221 vtable entry to be used in the relocation's section offset. */
12222 if (fixp
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
12223 reloc
->address
= fixp
->fx_offset
;
12229 md_estimate_size_before_relax (fragS
* fragP ATTRIBUTE_UNUSED
,
12230 segT segtype ATTRIBUTE_UNUSED
)
12232 as_fatal (_("md_estimate_size_before_relax\n"));
12236 /* We need to be able to fix up arbitrary expressions in some statements.
12237 This is so that we can handle symbols that are an arbitrary distance from
12238 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
12239 which returns part of an address in a form which will be valid for
12240 a data instruction. We do this by pushing the expression into a symbol
12241 in the expr_section, and creating a fix for that. */
12244 fix_new_arm (fragS
* frag
,
12252 arm_fix_data
* arm_data
;
12260 new_fix
= fix_new_exp (frag
, where
, size
, exp
, pc_rel
, reloc
);
12264 new_fix
= fix_new (frag
, where
, size
, make_expr_symbol (exp
), 0,
12269 /* Mark whether the fix is to a THUMB instruction, or an ARM
12271 arm_data
= obstack_alloc (& notes
, sizeof (arm_fix_data
));
12272 new_fix
->tc_fix_data
= (PTR
) arm_data
;
12273 arm_data
->thumb_mode
= thumb_mode
;
12277 output_inst (const char * str
)
12283 as_bad ("%s -- `%s'", inst
.error
, str
);
12287 to
= frag_more (inst
.size
);
12289 if (thumb_mode
&& (inst
.size
> THUMB_SIZE
))
12291 assert (inst
.size
== (2 * THUMB_SIZE
));
12292 md_number_to_chars (to
, inst
.instruction
>> 16, THUMB_SIZE
);
12293 md_number_to_chars (to
+ THUMB_SIZE
, inst
.instruction
, THUMB_SIZE
);
12295 else if (inst
.size
> INSN_SIZE
)
12297 assert (inst
.size
== (2 * INSN_SIZE
));
12298 md_number_to_chars (to
, inst
.instruction
, INSN_SIZE
);
12299 md_number_to_chars (to
+ INSN_SIZE
, inst
.instruction
, INSN_SIZE
);
12302 md_number_to_chars (to
, inst
.instruction
, inst
.size
);
12304 if (inst
.reloc
.type
!= BFD_RELOC_UNUSED
)
12305 fix_new_arm (frag_now
, to
- frag_now
->fr_literal
,
12306 inst
.size
, & inst
.reloc
.exp
, inst
.reloc
.pc_rel
,
12310 dwarf2_emit_insn (inst
.size
);
12315 md_assemble (char * str
)
12321 /* Align the previous label if needed. */
12322 if (last_label_seen
!= NULL
)
12324 symbol_set_frag (last_label_seen
, frag_now
);
12325 S_SET_VALUE (last_label_seen
, (valueT
) frag_now_fix ());
12326 S_SET_SEGMENT (last_label_seen
, now_seg
);
12329 memset (&inst
, '\0', sizeof (inst
));
12330 inst
.reloc
.type
= BFD_RELOC_UNUSED
;
12332 skip_whitespace (str
);
12334 /* Scan up to the end of the op-code, which must end in white space or
12336 for (start
= p
= str
; *p
!= '\0'; p
++)
12342 as_bad (_("no operator -- statement `%s'\n"), str
);
12348 const struct thumb_opcode
* opcode
;
12352 opcode
= (const struct thumb_opcode
*) hash_find (arm_tops_hsh
, str
);
12357 /* Check that this instruction is supported for this CPU. */
12358 if (thumb_mode
== 1 && (opcode
->variant
& cpu_variant
) == 0)
12360 as_bad (_("selected processor does not support `%s'"), str
);
12364 mapping_state (MAP_THUMB
);
12365 inst
.instruction
= opcode
->value
;
12366 inst
.size
= opcode
->size
;
12374 const struct asm_opcode
* opcode
;
12378 opcode
= (const struct asm_opcode
*) hash_find (arm_ops_hsh
, str
);
12383 /* Check that this instruction is supported for this CPU. */
12384 if ((opcode
->variant
& cpu_variant
) == 0)
12386 as_bad (_("selected processor does not support `%s'"), str
);
12390 mapping_state (MAP_ARM
);
12391 inst
.instruction
= opcode
->value
;
12392 inst
.size
= INSN_SIZE
;
12399 /* It wasn't an instruction, but it might be a register alias of the form
12401 if (create_register_alias (str
, p
))
12404 as_bad (_("bad instruction `%s'"), start
);
12408 Invocation line includes a switch not recognized by the base assembler.
12409 See if it's a processor-specific option.
12411 This routine is somewhat complicated by the need for backwards
12412 compatibility (since older releases of gcc can't be changed).
12413 The new options try to make the interface as compatible as
12416 New options (supported) are:
12418 -mcpu=<cpu name> Assemble for selected processor
12419 -march=<architecture name> Assemble for selected architecture
12420 -mfpu=<fpu architecture> Assemble for selected FPU.
12421 -EB/-mbig-endian Big-endian
12422 -EL/-mlittle-endian Little-endian
12423 -k Generate PIC code
12424 -mthumb Start in Thumb mode
12425 -mthumb-interwork Code supports ARM/Thumb interworking
12427 For now we will also provide support for:
12429 -mapcs-32 32-bit Program counter
12430 -mapcs-26 26-bit Program counter
12431 -macps-float Floats passed in FP registers
12432 -mapcs-reentrant Reentrant code
12434 (sometime these will probably be replaced with -mapcs=<list of options>
12435 and -matpcs=<list of options>)
12437 The remaining options are only supported for back-wards compatibility.
12438 Cpu variants, the arm part is optional:
12439 -m[arm]1 Currently not supported.
12440 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
12441 -m[arm]3 Arm 3 processor
12442 -m[arm]6[xx], Arm 6 processors
12443 -m[arm]7[xx][t][[d]m] Arm 7 processors
12444 -m[arm]8[10] Arm 8 processors
12445 -m[arm]9[20][tdmi] Arm 9 processors
12446 -mstrongarm[110[0]] StrongARM processors
12447 -mxscale XScale processors
12448 -m[arm]v[2345[t[e]]] Arm architectures
12449 -mall All (except the ARM1)
12451 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
12452 -mfpe-old (No float load/store multiples)
12453 -mvfpxd VFP Single precision
12455 -mno-fpu Disable all floating point instructions
12457 The following CPU names are recognized:
12458 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
12459 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
12460 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
12461 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
12462 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
12463 arm10t arm10e, arm1020t, arm1020e, arm10200e,
12464 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
12468 const char * md_shortopts
= "m:k";
12470 #ifdef ARM_BI_ENDIAN
12471 #define OPTION_EB (OPTION_MD_BASE + 0)
12472 #define OPTION_EL (OPTION_MD_BASE + 1)
12474 #if TARGET_BYTES_BIG_ENDIAN
12475 #define OPTION_EB (OPTION_MD_BASE + 0)
12477 #define OPTION_EL (OPTION_MD_BASE + 1)
12481 struct option md_longopts
[] =
12484 {"EB", no_argument
, NULL
, OPTION_EB
},
12487 {"EL", no_argument
, NULL
, OPTION_EL
},
12489 {NULL
, no_argument
, NULL
, 0}
12492 size_t md_longopts_size
= sizeof (md_longopts
);
12494 struct arm_option_table
12496 char *option
; /* Option name to match. */
12497 char *help
; /* Help information. */
12498 int *var
; /* Variable to change. */
12499 int value
; /* What to change it to. */
12500 char *deprecated
; /* If non-null, print this message. */
12503 struct arm_option_table arm_opts
[] =
12505 {"k", N_("generate PIC code"), &pic_code
, 1, NULL
},
12506 {"mthumb", N_("assemble Thumb code"), &thumb_mode
, 1, NULL
},
12507 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
12508 &support_interwork
, 1, NULL
},
12509 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26
, 0, NULL
},
12510 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26
, 1, NULL
},
12511 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float
,
12513 {"mapcs-reentrant", N_("re-entrant code"), &pic_code
, 1, NULL
},
12514 {"matpcs", N_("code is ATPCS conformant"), &atpcs
, 1, NULL
},
12515 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian
, 1, NULL
},
12516 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian
, 1,
12519 /* These are recognized by the assembler, but have no affect on code. */
12520 {"mapcs-frame", N_("use frame pointer"), NULL
, 0, NULL
},
12521 {"mapcs-stack-check", N_("use stack size checking"), NULL
, 0, NULL
},
12523 /* DON'T add any new processors to this list -- we want the whole list
12524 to go away... Add them to the processors table instead. */
12525 {"marm1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
12526 {"m1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
12527 {"marm2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
12528 {"m2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
12529 {"marm250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
12530 {"m250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
12531 {"marm3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
12532 {"m3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
12533 {"marm6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
12534 {"m6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
12535 {"marm600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
12536 {"m600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
12537 {"marm610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
12538 {"m610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
12539 {"marm620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
12540 {"m620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
12541 {"marm7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
12542 {"m7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
12543 {"marm70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
12544 {"m70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
12545 {"marm700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
12546 {"m700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
12547 {"marm700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
12548 {"m700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
12549 {"marm710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
12550 {"m710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
12551 {"marm710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
12552 {"m710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
12553 {"marm720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
12554 {"m720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
12555 {"marm7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
12556 {"m7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
12557 {"marm7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
12558 {"m7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
12559 {"marm7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
12560 {"m7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
12561 {"marm7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
12562 {"m7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
12563 {"marm7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
12564 {"m7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
12565 {"marm7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
12566 {"m7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
12567 {"marm7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
12568 {"m7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
12569 {"marm7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
12570 {"m7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
12571 {"marm7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12572 {"m7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12573 {"marm7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12574 {"m7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12575 {"marm710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
12576 {"m710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
12577 {"marm720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
12578 {"m720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
12579 {"marm740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
12580 {"m740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
12581 {"marm8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
12582 {"m8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
12583 {"marm810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
12584 {"m810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
12585 {"marm9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
12586 {"m9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
12587 {"marm9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
12588 {"m9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
12589 {"marm920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
12590 {"m920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
12591 {"marm940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
12592 {"m940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
12593 {"mstrongarm", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=strongarm")},
12594 {"mstrongarm110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
12595 N_("use -mcpu=strongarm110")},
12596 {"mstrongarm1100", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
12597 N_("use -mcpu=strongarm1100")},
12598 {"mstrongarm1110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
12599 N_("use -mcpu=strongarm1110")},
12600 {"mxscale", NULL
, &legacy_cpu
, ARM_ARCH_XSCALE
, N_("use -mcpu=xscale")},
12601 {"miwmmxt", NULL
, &legacy_cpu
, ARM_ARCH_IWMMXT
, N_("use -mcpu=iwmmxt")},
12602 {"mall", NULL
, &legacy_cpu
, ARM_ANY
, N_("use -mcpu=all")},
12604 /* Architecture variants -- don't add any more to this list either. */
12605 {"mv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
12606 {"marmv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
12607 {"mv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
12608 {"marmv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
12609 {"mv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
12610 {"marmv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
12611 {"mv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
12612 {"marmv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
12613 {"mv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
12614 {"marmv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
12615 {"mv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
12616 {"marmv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
12617 {"mv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
12618 {"marmv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
12619 {"mv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
12620 {"marmv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
12621 {"mv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
12622 {"marmv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
12624 /* Floating point variants -- don't add any more to this list either. */
12625 {"mfpe-old", NULL
, &legacy_fpu
, FPU_ARCH_FPE
, N_("use -mfpu=fpe")},
12626 {"mfpa10", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa10")},
12627 {"mfpa11", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa11")},
12628 {"mno-fpu", NULL
, &legacy_fpu
, 0,
12629 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
12631 {NULL
, NULL
, NULL
, 0, NULL
}
12634 struct arm_cpu_option_table
12638 /* For some CPUs we assume an FPU unless the user explicitly sets
12643 /* This list should, at a minimum, contain all the cpu names
12644 recognized by GCC. */
12645 static struct arm_cpu_option_table arm_cpus
[] =
12647 {"all", ARM_ANY
, FPU_ARCH_FPA
},
12648 {"arm1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
12649 {"arm2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
12650 {"arm250", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
12651 {"arm3", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
12652 {"arm6", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12653 {"arm60", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12654 {"arm600", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12655 {"arm610", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12656 {"arm620", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12657 {"arm7", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12658 {"arm7m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
12659 {"arm7d", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12660 {"arm7dm", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
12661 {"arm7di", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12662 {"arm7dmi", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
12663 {"arm70", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12664 {"arm700", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12665 {"arm700i", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12666 {"arm710", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12667 {"arm710t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12668 {"arm720", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12669 {"arm720t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12670 {"arm740t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12671 {"arm710c", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12672 {"arm7100", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12673 {"arm7500", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12674 {"arm7500fe", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12675 {"arm7t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12676 {"arm7tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12677 {"arm7tdmi-s", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12678 {"arm8", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12679 {"arm810", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12680 {"strongarm", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12681 {"strongarm1", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12682 {"strongarm110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12683 {"strongarm1100", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12684 {"strongarm1110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12685 {"arm9", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12686 {"arm920", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12687 {"arm920t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12688 {"arm922t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12689 {"arm940t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12690 {"arm9tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12691 /* For V5 or later processors we default to using VFP; but the user
12692 should really set the FPU type explicitly. */
12693 {"arm9e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
12694 {"arm9e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12695 {"arm926ej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
12696 {"arm926ejs", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
12697 {"arm926ej-s", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
12698 {"arm946e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
12699 {"arm946e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12700 {"arm966e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
12701 {"arm966e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12702 {"arm10t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
12703 {"arm10e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12704 {"arm1020", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12705 {"arm1020t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
12706 {"arm1020e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12707 {"arm1026ejs", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
12708 {"arm1026ej-s", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
12709 {"arm1136js", ARM_ARCH_V6
, FPU_NONE
},
12710 {"arm1136j-s", ARM_ARCH_V6
, FPU_NONE
},
12711 {"arm1136jfs", ARM_ARCH_V6
, FPU_ARCH_VFP_V2
},
12712 {"arm1136jf-s", ARM_ARCH_V6
, FPU_ARCH_VFP_V2
},
12713 {"mpcore", ARM_ARCH_V6K
, FPU_ARCH_VFP_V2
},
12714 {"mpcorenovfp", ARM_ARCH_V6K
, FPU_NONE
},
12715 {"arm1176jz-s", ARM_ARCH_V6ZK
, FPU_NONE
},
12716 {"arm1176jzf-s", ARM_ARCH_V6ZK
, FPU_ARCH_VFP_V2
},
12717 /* ??? XSCALE is really an architecture. */
12718 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
12719 /* ??? iwmmxt is not a processor. */
12720 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP_V2
},
12721 {"i80200", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
12723 {"ep9312", ARM_ARCH_V4T
| ARM_CEXT_MAVERICK
, FPU_ARCH_MAVERICK
},
12727 struct arm_arch_option_table
12734 /* This list should, at a minimum, contain all the architecture names
12735 recognized by GCC. */
12736 static struct arm_arch_option_table arm_archs
[] =
12738 {"all", ARM_ANY
, FPU_ARCH_FPA
},
12739 {"armv1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
12740 {"armv2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
12741 {"armv2a", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
12742 {"armv2s", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
12743 {"armv3", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12744 {"armv3m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
12745 {"armv4", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12746 {"armv4xm", ARM_ARCH_V4xM
, FPU_ARCH_FPA
},
12747 {"armv4t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12748 {"armv4txm", ARM_ARCH_V4TxM
, FPU_ARCH_FPA
},
12749 {"armv5", ARM_ARCH_V5
, FPU_ARCH_VFP
},
12750 {"armv5t", ARM_ARCH_V5T
, FPU_ARCH_VFP
},
12751 {"armv5txm", ARM_ARCH_V5TxM
, FPU_ARCH_VFP
},
12752 {"armv5te", ARM_ARCH_V5TE
, FPU_ARCH_VFP
},
12753 {"armv5texp", ARM_ARCH_V5TExP
, FPU_ARCH_VFP
},
12754 {"armv5tej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP
},
12755 {"armv6", ARM_ARCH_V6
, FPU_ARCH_VFP
},
12756 {"armv6j", ARM_ARCH_V6
, FPU_ARCH_VFP
},
12757 {"armv6k", ARM_ARCH_V6K
, FPU_ARCH_VFP
},
12758 {"armv6z", ARM_ARCH_V6Z
, FPU_ARCH_VFP
},
12759 {"armv6zk", ARM_ARCH_V6ZK
, FPU_ARCH_VFP
},
12760 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP
},
12761 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP
},
12765 /* ISA extensions in the co-processor space. */
12766 struct arm_arch_extension_table
12772 static struct arm_arch_extension_table arm_extensions
[] =
12774 {"maverick", ARM_CEXT_MAVERICK
},
12775 {"xscale", ARM_CEXT_XSCALE
},
12776 {"iwmmxt", ARM_CEXT_IWMMXT
},
12780 struct arm_fpu_option_table
12786 /* This list should, at a minimum, contain all the fpu names
12787 recognized by GCC. */
12788 static struct arm_fpu_option_table arm_fpus
[] =
12790 {"softfpa", FPU_NONE
},
12791 {"fpe", FPU_ARCH_FPE
},
12792 {"fpe2", FPU_ARCH_FPE
},
12793 {"fpe3", FPU_ARCH_FPA
}, /* Third release supports LFM/SFM. */
12794 {"fpa", FPU_ARCH_FPA
},
12795 {"fpa10", FPU_ARCH_FPA
},
12796 {"fpa11", FPU_ARCH_FPA
},
12797 {"arm7500fe", FPU_ARCH_FPA
},
12798 {"softvfp", FPU_ARCH_VFP
},
12799 {"softvfp+vfp", FPU_ARCH_VFP_V2
},
12800 {"vfp", FPU_ARCH_VFP_V2
},
12801 {"vfp9", FPU_ARCH_VFP_V2
},
12802 {"vfp10", FPU_ARCH_VFP_V2
},
12803 {"vfp10-r0", FPU_ARCH_VFP_V1
},
12804 {"vfpxd", FPU_ARCH_VFP_V1xD
},
12805 {"arm1020t", FPU_ARCH_VFP_V1
},
12806 {"arm1020e", FPU_ARCH_VFP_V2
},
12807 {"arm1136jfs", FPU_ARCH_VFP_V2
},
12808 {"arm1136jf-s", FPU_ARCH_VFP_V2
},
12809 {"maverick", FPU_ARCH_MAVERICK
},
12813 struct arm_float_abi_option_table
12819 static struct arm_float_abi_option_table arm_float_abis
[] =
12821 {"hard", ARM_FLOAT_ABI_HARD
},
12822 {"softfp", ARM_FLOAT_ABI_SOFTFP
},
12823 {"soft", ARM_FLOAT_ABI_SOFT
},
12827 struct arm_eabi_option_table
12830 unsigned int value
;
12834 /* We only know how to output GNU and ver 4 (AAELF) formats. */
12835 static struct arm_eabi_option_table arm_eabis
[] =
12837 {"gnu", EF_ARM_EABI_UNKNOWN
},
12838 {"4", EF_ARM_EABI_VER4
},
12843 struct arm_long_option_table
12845 char * option
; /* Substring to match. */
12846 char * help
; /* Help information. */
12847 int (* func
) (char * subopt
); /* Function to decode sub-option. */
12848 char * deprecated
; /* If non-null, print this message. */
12852 arm_parse_extension (char * str
, int * opt_p
)
12854 while (str
!= NULL
&& *str
!= 0)
12856 struct arm_arch_extension_table
* opt
;
12862 as_bad (_("invalid architectural extension"));
12867 ext
= strchr (str
, '+');
12870 optlen
= ext
- str
;
12872 optlen
= strlen (str
);
12876 as_bad (_("missing architectural extension"));
12880 for (opt
= arm_extensions
; opt
->name
!= NULL
; opt
++)
12881 if (strncmp (opt
->name
, str
, optlen
) == 0)
12883 *opt_p
|= opt
->value
;
12887 if (opt
->name
== NULL
)
12889 as_bad (_("unknown architectural extnsion `%s'"), str
);
12900 arm_parse_cpu (char * str
)
12902 struct arm_cpu_option_table
* opt
;
12903 char * ext
= strchr (str
, '+');
12907 optlen
= ext
- str
;
12909 optlen
= strlen (str
);
12913 as_bad (_("missing cpu name `%s'"), str
);
12917 for (opt
= arm_cpus
; opt
->name
!= NULL
; opt
++)
12918 if (strncmp (opt
->name
, str
, optlen
) == 0)
12920 mcpu_cpu_opt
= opt
->value
;
12921 mcpu_fpu_opt
= opt
->default_fpu
;
12924 return arm_parse_extension (ext
, &mcpu_cpu_opt
);
12929 as_bad (_("unknown cpu `%s'"), str
);
12934 arm_parse_arch (char * str
)
12936 struct arm_arch_option_table
*opt
;
12937 char *ext
= strchr (str
, '+');
12941 optlen
= ext
- str
;
12943 optlen
= strlen (str
);
12947 as_bad (_("missing architecture name `%s'"), str
);
12952 for (opt
= arm_archs
; opt
->name
!= NULL
; opt
++)
12953 if (streq (opt
->name
, str
))
12955 march_cpu_opt
= opt
->value
;
12956 march_fpu_opt
= opt
->default_fpu
;
12959 return arm_parse_extension (ext
, &march_cpu_opt
);
12964 as_bad (_("unknown architecture `%s'\n"), str
);
12969 arm_parse_fpu (char * str
)
12971 struct arm_fpu_option_table
* opt
;
12973 for (opt
= arm_fpus
; opt
->name
!= NULL
; opt
++)
12974 if (streq (opt
->name
, str
))
12976 mfpu_opt
= opt
->value
;
12980 as_bad (_("unknown floating point format `%s'\n"), str
);
12985 arm_parse_float_abi (char * str
)
12987 struct arm_float_abi_option_table
* opt
;
12989 for (opt
= arm_float_abis
; opt
->name
!= NULL
; opt
++)
12990 if (streq (opt
->name
, str
))
12992 mfloat_abi_opt
= opt
->value
;
12996 as_bad (_("unknown floating point abi `%s'\n"), str
);
13002 arm_parse_eabi (char * str
)
13004 struct arm_eabi_option_table
*opt
;
13006 for (opt
= arm_eabis
; opt
->name
!= NULL
; opt
++)
13007 if (streq (opt
->name
, str
))
13009 meabi_flags
= opt
->value
;
13012 as_bad (_("unknown EABI `%s'\n"), str
);
13017 struct arm_long_option_table arm_long_opts
[] =
13019 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13020 arm_parse_cpu
, NULL
},
13021 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13022 arm_parse_arch
, NULL
},
13023 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13024 arm_parse_fpu
, NULL
},
13025 {"mfloat-abi=", N_("<abi>\t assemble for floating point ABI <abi>"),
13026 arm_parse_float_abi
, NULL
},
13028 {"meabi=", N_("<ver>\t assemble for eabi version <ver>"),
13029 arm_parse_eabi
, NULL
},
13031 {NULL
, NULL
, 0, NULL
}
13035 md_parse_option (int c
, char * arg
)
13037 struct arm_option_table
*opt
;
13038 struct arm_long_option_table
*lopt
;
13044 target_big_endian
= 1;
13050 target_big_endian
= 0;
13055 /* Listing option. Just ignore these, we don't support additional
13060 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
13062 if (c
== opt
->option
[0]
13063 && ((arg
== NULL
&& opt
->option
[1] == 0)
13064 || streq (arg
, opt
->option
+ 1)))
13066 #if WARN_DEPRECATED
13067 /* If the option is deprecated, tell the user. */
13068 if (opt
->deprecated
!= NULL
)
13069 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
,
13070 arg
? arg
: "", _(opt
->deprecated
));
13073 if (opt
->var
!= NULL
)
13074 *opt
->var
= opt
->value
;
13080 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
13082 /* These options are expected to have an argument. */
13083 if (c
== lopt
->option
[0]
13085 && strncmp (arg
, lopt
->option
+ 1,
13086 strlen (lopt
->option
+ 1)) == 0)
13088 #if WARN_DEPRECATED
13089 /* If the option is deprecated, tell the user. */
13090 if (lopt
->deprecated
!= NULL
)
13091 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
, arg
,
13092 _(lopt
->deprecated
));
13095 /* Call the sup-option parser. */
13096 return lopt
->func (arg
+ strlen (lopt
->option
) - 1);
13107 md_show_usage (FILE * fp
)
13109 struct arm_option_table
*opt
;
13110 struct arm_long_option_table
*lopt
;
13112 fprintf (fp
, _(" ARM-specific assembler options:\n"));
13114 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
13115 if (opt
->help
!= NULL
)
13116 fprintf (fp
, " -%-23s%s\n", opt
->option
, _(opt
->help
));
13118 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
13119 if (lopt
->help
!= NULL
)
13120 fprintf (fp
, " -%s%s\n", lopt
->option
, _(lopt
->help
));
13124 -EB assemble code for a big-endian cpu\n"));
13129 -EL assemble code for a little-endian cpu\n"));
13133 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13136 cons_fix_new_arm (fragS
* frag
,
13141 bfd_reloc_code_real_type type
;
13145 FIXME: @@ Should look at CPU word size. */
13149 type
= BFD_RELOC_8
;
13152 type
= BFD_RELOC_16
;
13156 type
= BFD_RELOC_32
;
13159 type
= BFD_RELOC_64
;
13163 fix_new_exp (frag
, where
, (int) size
, exp
, pcrel
, type
);
13166 /* A good place to do this, although this was probably not intended
13167 for this kind of use. We need to dump the literal pool before
13168 references are made to a null symbol pointer. */
13173 literal_pool
* pool
;
13175 for (pool
= list_of_pools
; pool
; pool
= pool
->next
)
13177 /* Put it at the end of the relevent section. */
13178 subseg_set (pool
->section
, pool
->sub_section
);
13180 arm_elf_change_section ();
13187 arm_start_line_hook (void)
13189 last_label_seen
= NULL
;
13193 arm_frob_label (symbolS
* sym
)
13195 last_label_seen
= sym
;
13197 ARM_SET_THUMB (sym
, thumb_mode
);
13199 #if defined OBJ_COFF || defined OBJ_ELF
13200 ARM_SET_INTERWORK (sym
, support_interwork
);
13203 /* Note - do not allow local symbols (.Lxxx) to be labeled
13204 as Thumb functions. This is because these labels, whilst
13205 they exist inside Thumb code, are not the entry points for
13206 possible ARM->Thumb calls. Also, these labels can be used
13207 as part of a computed goto or switch statement. eg gcc
13208 can generate code that looks like this:
13210 ldr r2, [pc, .Laaa]
13220 The first instruction loads the address of the jump table.
13221 The second instruction converts a table index into a byte offset.
13222 The third instruction gets the jump address out of the table.
13223 The fourth instruction performs the jump.
13225 If the address stored at .Laaa is that of a symbol which has the
13226 Thumb_Func bit set, then the linker will arrange for this address
13227 to have the bottom bit set, which in turn would mean that the
13228 address computation performed by the third instruction would end
13229 up with the bottom bit set. Since the ARM is capable of unaligned
13230 word loads, the instruction would then load the incorrect address
13231 out of the jump table, and chaos would ensue. */
13232 if (label_is_thumb_function_name
13233 && (S_GET_NAME (sym
)[0] != '.' || S_GET_NAME (sym
)[1] != 'L')
13234 && (bfd_get_section_flags (stdoutput
, now_seg
) & SEC_CODE
) != 0)
13236 /* When the address of a Thumb function is taken the bottom
13237 bit of that address should be set. This will allow
13238 interworking between Arm and Thumb functions to work
13241 THUMB_SET_FUNC (sym
, 1);
13243 label_is_thumb_function_name
= FALSE
;
13247 /* Adjust the symbol table. This marks Thumb symbols as distinct from
13251 arm_adjust_symtab (void)
13256 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
13258 if (ARM_IS_THUMB (sym
))
13260 if (THUMB_IS_FUNC (sym
))
13262 /* Mark the symbol as a Thumb function. */
13263 if ( S_GET_STORAGE_CLASS (sym
) == C_STAT
13264 || S_GET_STORAGE_CLASS (sym
) == C_LABEL
) /* This can happen! */
13265 S_SET_STORAGE_CLASS (sym
, C_THUMBSTATFUNC
);
13267 else if (S_GET_STORAGE_CLASS (sym
) == C_EXT
)
13268 S_SET_STORAGE_CLASS (sym
, C_THUMBEXTFUNC
);
13270 as_bad (_("%s: unexpected function type: %d"),
13271 S_GET_NAME (sym
), S_GET_STORAGE_CLASS (sym
));
13273 else switch (S_GET_STORAGE_CLASS (sym
))
13276 S_SET_STORAGE_CLASS (sym
, C_THUMBEXT
);
13279 S_SET_STORAGE_CLASS (sym
, C_THUMBSTAT
);
13282 S_SET_STORAGE_CLASS (sym
, C_THUMBLABEL
);
13290 if (ARM_IS_INTERWORK (sym
))
13291 coffsymbol (symbol_get_bfdsym (sym
))->native
->u
.syment
.n_flags
= 0xFF;
13298 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
13300 if (ARM_IS_THUMB (sym
))
13302 elf_symbol_type
* elf_sym
;
13304 elf_sym
= elf_symbol (symbol_get_bfdsym (sym
));
13305 bind
= ELF_ST_BIND (elf_sym
);
13307 /* If it's a .thumb_func, declare it as so,
13308 otherwise tag label as .code 16. */
13309 if (THUMB_IS_FUNC (sym
))
13310 elf_sym
->internal_elf_sym
.st_info
=
13311 ELF_ST_INFO (bind
, STT_ARM_TFUNC
);
13313 elf_sym
->internal_elf_sym
.st_info
=
13314 ELF_ST_INFO (bind
, STT_ARM_16BIT
);
13321 arm_data_in_code (void)
13323 if (thumb_mode
&& ! strncmp (input_line_pointer
+ 1, "data:", 5))
13325 *input_line_pointer
= '/';
13326 input_line_pointer
+= 5;
13327 *input_line_pointer
= 0;
13335 arm_canonicalize_symbol_name (char * name
)
13339 if (thumb_mode
&& (len
= strlen (name
)) > 5
13340 && streq (name
+ len
- 5, "/data"))
13341 *(name
+ len
- 5) = 0;
13346 #if defined OBJ_COFF || defined OBJ_ELF
13348 arm_validate_fix (fixS
* fixP
)
13350 /* If the destination of the branch is a defined symbol which does not have
13351 the THUMB_FUNC attribute, then we must be calling a function which has
13352 the (interfacearm) attribute. We look for the Thumb entry point to that
13353 function and change the branch to refer to that function instead. */
13354 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
13355 && fixP
->fx_addsy
!= NULL
13356 && S_IS_DEFINED (fixP
->fx_addsy
)
13357 && ! THUMB_IS_FUNC (fixP
->fx_addsy
))
13359 fixP
->fx_addsy
= find_real_start (fixP
->fx_addsy
);
13365 arm_force_relocation (struct fix
* fixp
)
13367 #if defined (OBJ_COFF) && defined (TE_PE)
13368 if (fixp
->fx_r_type
== BFD_RELOC_RVA
)
13372 if (fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
13373 || fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
13374 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
13375 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
)
13379 /* Resolve these relocations even if the symbol is extern or weak. */
13380 if (fixp
->fx_r_type
== BFD_RELOC_ARM_IMMEDIATE
13381 || fixp
->fx_r_type
== BFD_RELOC_ARM_OFFSET_IMM
13382 || fixp
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
13385 return generic_force_reloc (fixp
);
13389 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
13390 local labels from being added to the output symbol table when they
13391 are used with the ADRL pseudo op. The ADRL relocation should always
13392 be resolved before the binbary is emitted, so it is safe to say that
13393 it is adjustable. */
13396 arm_fix_adjustable (fixS
* fixP
)
13398 if (fixP
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
13405 /* Relocations against Thumb function names must be left unadjusted,
13406 so that the linker can use this information to correctly set the
13407 bottom bit of their addresses. The MIPS version of this function
13408 also prevents relocations that are mips-16 specific, but I do not
13409 know why it does this.
13412 There is one other problem that ought to be addressed here, but
13413 which currently is not: Taking the address of a label (rather
13414 than a function) and then later jumping to that address. Such
13415 addresses also ought to have their bottom bit set (assuming that
13416 they reside in Thumb code), but at the moment they will not. */
13419 arm_fix_adjustable (fixS
* fixP
)
13421 if (fixP
->fx_addsy
== NULL
)
13424 if (THUMB_IS_FUNC (fixP
->fx_addsy
)
13425 && fixP
->fx_subsy
== NULL
)
13428 /* We need the symbol name for the VTABLE entries. */
13429 if ( fixP
->fx_r_type
== BFD_RELOC_VTABLE_INHERIT
13430 || fixP
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
13433 /* Don't allow symbols to be discarded on GOT related relocs. */
13434 if (fixP
->fx_r_type
== BFD_RELOC_ARM_PLT32
13435 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOT32
13436 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOTOFF
13437 || fixP
->fx_r_type
== BFD_RELOC_ARM_TARGET2
)
13444 elf32_arm_target_format (void)
13447 return (target_big_endian
13448 ? "elf32-bigarm-symbian"
13449 : "elf32-littlearm-symbian");
13450 #elif defined (TE_VXWORKS)
13451 return (target_big_endian
13452 ? "elf32-bigarm-vxworks"
13453 : "elf32-littlearm-vxworks");
13455 if (target_big_endian
)
13456 return "elf32-bigarm";
13458 return "elf32-littlearm";
13463 armelf_frob_symbol (symbolS
* symp
,
13466 elf_frob_symbol (symp
, puntp
);
13470 s_arm_elf_cons (int nbytes
)
13474 #ifdef md_flush_pending_output
13475 md_flush_pending_output ();
13478 if (is_it_end_of_statement ())
13480 demand_empty_rest_of_line ();
13484 #ifdef md_cons_align
13485 md_cons_align (nbytes
);
13488 mapping_state (MAP_DATA
);
13491 bfd_reloc_code_real_type reloc
;
13493 expression (& exp
);
13495 if (exp
.X_op
== O_symbol
13496 && * input_line_pointer
== '('
13497 && (reloc
= arm_parse_reloc ()) != BFD_RELOC_UNUSED
)
13499 reloc_howto_type
*howto
= bfd_reloc_type_lookup (stdoutput
, reloc
);
13500 int size
= bfd_get_reloc_size (howto
);
13503 as_bad ("%s relocations do not fit in %d bytes",
13504 howto
->name
, nbytes
);
13507 char *p
= frag_more ((int) nbytes
);
13508 int offset
= nbytes
- size
;
13510 fix_new_exp (frag_now
, p
- frag_now
->fr_literal
+ offset
, size
,
13515 emit_expr (&exp
, (unsigned int) nbytes
);
13517 while (*input_line_pointer
++ == ',');
13519 /* Put terminator back into stream. */
13520 input_line_pointer
--;
13521 demand_empty_rest_of_line ();
13525 /* Parse a .rel31 directive. */
13528 s_arm_rel31 (int ignored ATTRIBUTE_UNUSED
)
13534 SKIP_WHITESPACE ();
13537 if (*input_line_pointer
== '1')
13538 highbit
= 0x80000000;
13539 else if (*input_line_pointer
!= '0')
13540 as_bad (_("expected 0 or 1"));
13542 input_line_pointer
++;
13543 SKIP_WHITESPACE ();
13544 if (*input_line_pointer
!= ',')
13545 as_bad (_("missing comma"));
13546 input_line_pointer
++;
13548 #ifdef md_flush_pending_output
13549 md_flush_pending_output ();
13552 #ifdef md_cons_align
13556 mapping_state (MAP_DATA
);
13561 md_number_to_chars (p
, highbit
, 4);
13562 fix_new_arm (frag_now
, p
- frag_now
->fr_literal
, 4, &exp
, 1,
13563 BFD_RELOC_ARM_PREL31
);
13565 demand_empty_rest_of_line ();
13568 /* Code to deal with unwinding tables. */
13570 static void add_unwind_adjustsp (offsetT
);
13572 /* Switch to section NAME and create section if necessary. It's
13573 rather ugly that we have to manipulate input_line_pointer but I
13574 don't see any other way to accomplish the same thing without
13575 changing obj-elf.c (which may be the Right Thing, in the end).
13576 Copied from tc-ia64.c. */
13579 set_section (char *name
)
13581 char *saved_input_line_pointer
;
13583 saved_input_line_pointer
= input_line_pointer
;
13584 input_line_pointer
= name
;
13585 obj_elf_section (0);
13586 input_line_pointer
= saved_input_line_pointer
;
13589 /* Cenerate and deferred unwind frame offset. */
13592 flush_pending_unwind (void)
13596 offset
= unwind
.pending_offset
;
13597 unwind
.pending_offset
= 0;
13599 add_unwind_adjustsp (offset
);
13602 /* Add an opcode to this list for this function. Two-byte opcodes should
13603 be passed as op[0] << 8 | op[1]. The list of opcodes is built in reverse
13607 add_unwind_opcode (valueT op
, int length
)
13609 /* Add any deferred stack adjustment. */
13610 if (unwind
.pending_offset
)
13611 flush_pending_unwind ();
13613 unwind
.sp_restored
= 0;
13615 if (unwind
.opcode_count
+ length
> unwind
.opcode_alloc
)
13617 unwind
.opcode_alloc
+= ARM_OPCODE_CHUNK_SIZE
;
13618 if (unwind
.opcodes
)
13619 unwind
.opcodes
= xrealloc (unwind
.opcodes
,
13620 unwind
.opcode_alloc
);
13622 unwind
.opcodes
= xmalloc (unwind
.opcode_alloc
);
13627 unwind
.opcodes
[unwind
.opcode_count
] = op
& 0xff;
13629 unwind
.opcode_count
++;
13633 /* Add unwind opcodes to adjust the stack pointer. */
13636 add_unwind_adjustsp (offsetT offset
)
13640 if (offset
> 0x200)
13642 /* We need at most 5 bytes to hold a 32-bit value in a uleb128. */
13647 /* Long form: 0xb2, uleb128. */
13648 /* This might not fit in a word so add the individual bytes,
13649 remembering the list is built in reverse order. */
13650 o
= (valueT
) ((offset
- 0x204) >> 2);
13652 add_unwind_opcode (0, 1);
13654 /* Calculate the uleb128 encoding of the offset. */
13658 bytes
[n
] = o
& 0x7f;
13664 /* Add the insn. */
13666 add_unwind_opcode (bytes
[n
- 1], 1);
13667 add_unwind_opcode (0xb2, 1);
13669 else if (offset
> 0x100)
13671 /* Two short opcodes. */
13672 add_unwind_opcode (0x3f, 1);
13673 op
= (offset
- 0x104) >> 2;
13674 add_unwind_opcode (op
, 1);
13676 else if (offset
> 0)
13678 /* Short opcode. */
13679 op
= (offset
- 4) >> 2;
13680 add_unwind_opcode (op
, 1);
13682 else if (offset
< 0)
13685 while (offset
> 0x100)
13687 add_unwind_opcode (0x7f, 1);
13690 op
= ((offset
- 4) >> 2) | 0x40;
13691 add_unwind_opcode (op
, 1);
13695 /* Finish the list of unwind opcodes for this function. */
13697 finish_unwind_opcodes (void)
13701 if (unwind
.fp_used
)
13703 /* Adjust sp as neccessary. */
13704 unwind
.pending_offset
+= unwind
.fp_offset
- unwind
.frame_size
;
13705 flush_pending_unwind ();
13707 /* After restoring sp from the frame pointer. */
13708 op
= 0x90 | unwind
.fp_reg
;
13709 add_unwind_opcode (op
, 1);
13712 flush_pending_unwind ();
13716 /* Start an exception table entry. If idx is nonzero this is an index table
13720 start_unwind_section (const segT text_seg
, int idx
)
13722 const char * text_name
;
13723 const char * prefix
;
13724 const char * prefix_once
;
13728 size_t sec_name_len
;
13732 prefix
= ELF_STRING_ARM_unwind
;
13733 prefix_once
= ELF_STRING_ARM_unwind_once
;
13737 prefix
= ELF_STRING_ARM_unwind_info
;
13738 prefix_once
= ELF_STRING_ARM_unwind_info_once
;
13741 text_name
= segment_name (text_seg
);
13742 if (streq (text_name
, ".text"))
13745 if (strncmp (text_name
, ".gnu.linkonce.t.",
13746 strlen (".gnu.linkonce.t.")) == 0)
13748 prefix
= prefix_once
;
13749 text_name
+= strlen (".gnu.linkonce.t.");
13752 prefix_len
= strlen (prefix
);
13753 text_len
= strlen (text_name
);
13754 sec_name_len
= prefix_len
+ text_len
;
13755 sec_name
= alloca (sec_name_len
+ 1);
13756 memcpy (sec_name
, prefix
, prefix_len
);
13757 memcpy (sec_name
+ prefix_len
, text_name
, text_len
);
13758 sec_name
[prefix_len
+ text_len
] = '\0';
13760 /* Handle COMDAT group. */
13761 if (prefix
!= prefix_once
&& (text_seg
->flags
& SEC_LINK_ONCE
) != 0)
13764 size_t len
, group_name_len
;
13765 const char *group_name
= elf_group_name (text_seg
);
13767 if (group_name
== NULL
)
13769 as_bad ("Group section `%s' has no group signature",
13770 segment_name (text_seg
));
13771 ignore_rest_of_line ();
13774 /* We have to construct a fake section directive. */
13775 group_name_len
= strlen (group_name
);
13781 len
= (sec_name_len
13782 + prefix_len
/* ,"aG",%sectiontype, */
13783 + group_name_len
/* ,group_name */
13784 + 7); /* ,comdat */
13786 section
= alloca (len
+ 1);
13787 memcpy (section
, sec_name
, sec_name_len
);
13789 memcpy (section
+ sec_name_len
, ",\"aG\",%exidx,", 13);
13791 memcpy (section
+ sec_name_len
, ",\"aG\",%progbits,", 16);
13792 memcpy (section
+ sec_name_len
+ prefix_len
, group_name
, group_name_len
);
13793 memcpy (section
+ len
- 7, ",comdat", 7);
13794 section
[len
] = '\0';
13795 set_section (section
);
13799 set_section (sec_name
);
13800 bfd_set_section_flags (stdoutput
, now_seg
,
13801 SEC_LOAD
| SEC_ALLOC
| SEC_READONLY
);
13804 /* Set the setion link for index tables. */
13806 elf_linked_to_section (now_seg
) = text_seg
;
13810 /* Start an unwind table entry. HAVE_DATA is nonzero if we have additional
13811 personality routine data. Returns zero, or the index table value for
13812 and inline entry. */
13815 create_unwind_entry (int have_data
)
13819 unsigned char *ptr
;
13820 /* The current word of data. */
13822 /* The number of bytes left in this word. */
13825 finish_unwind_opcodes ();
13827 /* Remember the current text section. */
13828 unwind
.saved_seg
= now_seg
;
13829 unwind
.saved_subseg
= now_subseg
;
13831 start_unwind_section (now_seg
, 0);
13833 if (unwind
.personality_routine
== NULL
)
13835 if (unwind
.personality_index
== -2)
13838 as_bad (_("handerdata in cantunwind frame"));
13839 return 1; /* EXIDX_CANTUNWIND. */
13842 /* Use a default personality routine if none is specified. */
13843 if (unwind
.personality_index
== -1)
13845 if (unwind
.opcode_count
> 3)
13846 unwind
.personality_index
= 1;
13848 unwind
.personality_index
= 0;
13851 /* Space for the personality routine entry. */
13852 if (unwind
.personality_index
== 0)
13854 if (unwind
.opcode_count
> 3)
13855 as_bad (_("too many unwind opcodes for personality routine 0"));
13859 /* All the data is inline in the index table. */
13862 while (unwind
.opcode_count
> 0)
13864 unwind
.opcode_count
--;
13865 data
= (data
<< 8) | unwind
.opcodes
[unwind
.opcode_count
];
13869 /* Pad with "finish" opcodes. */
13871 data
= (data
<< 8) | 0xb0;
13878 /* We get two opcodes "free" in the first word. */
13879 size
= unwind
.opcode_count
- 2;
13882 /* An extra byte is required for the opcode count. */
13883 size
= unwind
.opcode_count
+ 1;
13885 size
= (size
+ 3) >> 2;
13887 as_bad (_("too many unwind opcodes"));
13889 frag_align (2, 0, 0);
13890 record_alignment (now_seg
, 2);
13891 unwind
.table_entry
= expr_build_dot ();
13893 /* Allocate the table entry. */
13894 ptr
= frag_more ((size
<< 2) + 4);
13895 where
= frag_now_fix () - ((size
<< 2) + 4);
13897 switch (unwind
.personality_index
)
13900 /* ??? Should this be a PLT generating relocation? */
13901 /* Custom personality routine. */
13902 fix_new (frag_now
, where
, 4, unwind
.personality_routine
, 0, 1,
13903 BFD_RELOC_ARM_PREL31
);
13905 /* Indicate dependency to linker. */
13907 char *name
= "__aeabi_unwind_cpp_pr0";
13908 symbolS
*pr
= symbol_find_or_make (name
);
13909 fix_new (frag_now
, where
, 4, pr
, 0, 1, BFD_RELOC_NONE
);
13915 /* Set the first byte to the number of additional words. */
13920 /* ABI defined personality routines. */
13922 /* Three opcodes bytes are packed into the first word. */
13929 /* The size and first two opcode bytes go in the first word. */
13930 data
= ((0x80 + unwind
.personality_index
) << 8) | size
;
13936 /* Indicate dependency to linker. */
13937 char *name
[] = { "__aeabi_unwind_cpp_pr0",
13938 "__aeabi_unwind_cpp_pr1",
13939 "__aeabi_unwind_cpp_pr2" };
13940 symbolS
*pr
= symbol_find_or_make (name
[unwind
.personality_index
]);
13941 fix_new (frag_now
, where
, 4, pr
, 0, 1, BFD_RELOC_NONE
);
13946 /* Should never happen. */
13950 /* Pack the opcodes into words (MSB first), reversing the list at the same
13952 while (unwind
.opcode_count
> 0)
13956 md_number_to_chars (ptr
, data
, 4);
13961 unwind
.opcode_count
--;
13963 data
= (data
<< 8) | unwind
.opcodes
[unwind
.opcode_count
];
13966 /* Finish off the last word. */
13969 /* Pad with "finish" opcodes. */
13971 data
= (data
<< 8) | 0xb0;
13973 md_number_to_chars (ptr
, data
, 4);
13978 /* Add an empty descriptor if there is no user-specified data. */
13979 ptr
= frag_more (4);
13980 md_number_to_chars (ptr
, 0, 4);
13987 /* Parse an unwind_fnstart directive. Simply records the current location. */
13990 s_arm_unwind_fnstart (int ignored ATTRIBUTE_UNUSED
)
13992 demand_empty_rest_of_line ();
13993 /* Mark the start of the function. */
13994 unwind
.proc_start
= expr_build_dot ();
13996 /* Reset the rest of the unwind info. */
13997 unwind
.opcode_count
= 0;
13998 unwind
.table_entry
= NULL
;
13999 unwind
.personality_routine
= NULL
;
14000 unwind
.personality_index
= -1;
14001 unwind
.frame_size
= 0;
14002 unwind
.fp_offset
= 0;
14003 unwind
.fp_reg
= 13;
14004 unwind
.fp_used
= 0;
14005 unwind
.sp_restored
= 0;
14009 /* Parse a handlerdata directive. Creates the exception handling table entry
14010 for the function. */
14013 s_arm_unwind_handlerdata (int ignored ATTRIBUTE_UNUSED
)
14015 demand_empty_rest_of_line ();
14016 if (unwind
.table_entry
)
14017 as_bad (_("dupicate .handlerdata directive"));
14019 create_unwind_entry (1);
14022 /* Parse an unwind_fnend directive. Generates the index table entry. */
14025 s_arm_unwind_fnend (int ignored ATTRIBUTE_UNUSED
)
14028 unsigned char *ptr
;
14031 demand_empty_rest_of_line ();
14033 /* Add eh table entry. */
14034 if (unwind
.table_entry
== NULL
)
14035 val
= create_unwind_entry (0);
14039 /* Add index table entry. This is two words. */
14040 start_unwind_section (unwind
.saved_seg
, 1);
14041 frag_align (2, 0, 0);
14042 record_alignment (now_seg
, 2);
14044 ptr
= frag_more (8);
14045 where
= frag_now_fix () - 8;
14047 /* Self relative offset of the function start. */
14048 fix_new (frag_now
, where
, 4, unwind
.proc_start
, 0, 1,
14049 BFD_RELOC_ARM_PREL31
);
14052 /* Inline exception table entry. */
14053 md_number_to_chars (ptr
+ 4, val
, 4);
14055 /* Self relative offset of the table entry. */
14056 fix_new (frag_now
, where
+ 4, 4, unwind
.table_entry
, 0, 1,
14057 BFD_RELOC_ARM_PREL31
);
14059 /* Restore the original section. */
14060 subseg_set (unwind
.saved_seg
, unwind
.saved_subseg
);
14064 /* Parse an unwind_cantunwind directive. */
14067 s_arm_unwind_cantunwind (int ignored ATTRIBUTE_UNUSED
)
14069 demand_empty_rest_of_line ();
14070 if (unwind
.personality_routine
|| unwind
.personality_index
!= -1)
14071 as_bad (_("personality routine specified for cantunwind frame"));
14073 unwind
.personality_index
= -2;
14077 /* Parse a personalityindex directive. */
14080 s_arm_unwind_personalityindex (int ignored ATTRIBUTE_UNUSED
)
14084 if (unwind
.personality_routine
|| unwind
.personality_index
!= -1)
14085 as_bad (_("duplicate .personalityindex directive"));
14087 SKIP_WHITESPACE ();
14091 if (exp
.X_op
!= O_constant
14092 || exp
.X_add_number
< 0 || exp
.X_add_number
> 15)
14094 as_bad (_("bad personality routine number"));
14095 ignore_rest_of_line ();
14099 unwind
.personality_index
= exp
.X_add_number
;
14101 demand_empty_rest_of_line ();
14105 /* Parse a personality directive. */
14108 s_arm_unwind_personality (int ignored ATTRIBUTE_UNUSED
)
14112 if (unwind
.personality_routine
|| unwind
.personality_index
!= -1)
14113 as_bad (_("duplicate .personality directive"));
14115 SKIP_WHITESPACE ();
14116 name
= input_line_pointer
;
14117 c
= get_symbol_end ();
14118 p
= input_line_pointer
;
14119 unwind
.personality_routine
= symbol_find_or_make (name
);
14121 SKIP_WHITESPACE ();
14122 demand_empty_rest_of_line ();
14126 /* Parse a directive saving core registers. */
14129 s_arm_unwind_save_core (void)
14135 SKIP_WHITESPACE ();
14136 range
= reg_list (&input_line_pointer
);
14139 as_bad (_("expected register list"));
14140 ignore_rest_of_line ();
14144 demand_empty_rest_of_line ();
14146 /* Turn .unwind_movsp ip followed by .unwind_save {..., ip, ...}
14147 into .unwind_save {..., sp...}. We aren't bothered about the value of
14148 ip because it is clobbered by calls. */
14149 if (unwind
.sp_restored
&& unwind
.fp_reg
== 12
14150 && (range
& 0x3000) == 0x1000)
14152 unwind
.opcode_count
--;
14153 unwind
.sp_restored
= 0;
14154 range
= (range
| 0x2000) & ~0x1000;
14155 unwind
.pending_offset
= 0;
14158 /* See if we can use the short opcodes. These pop a block of upto 8
14159 registers starting with r4, plus maybe r14. */
14160 for (n
= 0; n
< 8; n
++)
14162 /* Break at the first non-saved register. */
14163 if ((range
& (1 << (n
+ 4))) == 0)
14166 /* See if there are any other bits set. */
14167 if (n
== 0 || (range
& (0xfff0 << n
) & 0xbff0) != 0)
14169 /* Use the long form. */
14170 op
= 0x8000 | ((range
>> 4) & 0xfff);
14171 add_unwind_opcode (op
, 2);
14175 /* Use the short form. */
14176 if (range
& 0x4000)
14177 op
= 0xa8; /* Pop r14. */
14179 op
= 0xa0; /* Do not pop r14. */
14181 add_unwind_opcode (op
, 1);
14187 op
= 0xb100 | (range
& 0xf);
14188 add_unwind_opcode (op
, 2);
14191 /* Record the number of bytes pushed. */
14192 for (n
= 0; n
< 16; n
++)
14194 if (range
& (1 << n
))
14195 unwind
.frame_size
+= 4;
14200 /* Parse a directive saving FPA registers. */
14203 s_arm_unwind_save_fpa (int reg
)
14209 /* Get Number of registers to transfer. */
14210 if (skip_past_comma (&input_line_pointer
) != FAIL
)
14213 exp
.X_op
= O_illegal
;
14215 if (exp
.X_op
!= O_constant
)
14217 as_bad (_("expected , <constant>"));
14218 ignore_rest_of_line ();
14222 num_regs
= exp
.X_add_number
;
14224 if (num_regs
< 1 || num_regs
> 4)
14226 as_bad (_("number of registers must be in the range [1:4]"));
14227 ignore_rest_of_line ();
14231 demand_empty_rest_of_line ();
14236 op
= 0xb4 | (num_regs
- 1);
14237 add_unwind_opcode (op
, 1);
14242 op
= 0xc800 | (reg
<< 4) | (num_regs
- 1);
14243 add_unwind_opcode (op
, 2);
14245 unwind
.frame_size
+= num_regs
* 12;
14249 /* Parse a directive saving VFP registers. */
14252 s_arm_unwind_save_vfp (void)
14258 count
= vfp_parse_reg_list (&input_line_pointer
, ®
, 1);
14261 as_bad (_("expected register list"));
14262 ignore_rest_of_line ();
14266 demand_empty_rest_of_line ();
14271 op
= 0xb8 | (count
- 1);
14272 add_unwind_opcode (op
, 1);
14277 op
= 0xb300 | (reg
<< 4) | (count
- 1);
14278 add_unwind_opcode (op
, 2);
14280 unwind
.frame_size
+= count
* 8 + 4;
14284 /* Parse a directive saving iWMMXt registers. */
14287 s_arm_unwind_save_wmmx (void)
14296 if (*input_line_pointer
== '{')
14297 input_line_pointer
++;
14303 reg
= arm_reg_parse (&input_line_pointer
,
14304 all_reg_maps
[REG_TYPE_IWMMXT
].htab
);
14306 if (wr_register (reg
))
14308 i
= reg
& ~WR_PREFIX
;
14310 as_tsktsk (_("register list not in ascending order"));
14313 else if (wcg_register (reg
))
14315 i
= (reg
& ~WC_PREFIX
) - 8;
14317 as_tsktsk (_("register list not in ascending order"));
14318 wcg_mask
|= 1 << i
;
14322 as_bad (_("expected wr or wcgr"));
14326 SKIP_WHITESPACE ();
14327 if (*input_line_pointer
== '-')
14329 hi_reg
= arm_reg_parse (&input_line_pointer
,
14330 all_reg_maps
[REG_TYPE_IWMMXT
].htab
);
14331 if (wr_register (reg
) && wr_register (hi_reg
))
14333 for (; reg
< hi_reg
; reg
++)
14334 wr_mask
|= 1 << (reg
& ~WR_PREFIX
);
14336 else if (wcg_register (reg
) && wcg_register (hi_reg
))
14338 for (; reg
< hi_reg
; reg
++)
14339 wcg_mask
|= 1 << ((reg
& ~WC_PREFIX
) - 8);
14343 as_bad (_("bad register range"));
14348 while (skip_past_comma (&input_line_pointer
) != FAIL
);
14350 SKIP_WHITESPACE ();
14351 if (*input_line_pointer
== '}')
14352 input_line_pointer
++;
14354 demand_empty_rest_of_line ();
14356 if (wr_mask
&& wcg_mask
)
14358 as_bad (_("inconsistent register types"));
14362 /* Generate any deferred opcodes becuuse we're going to be looking at
14364 flush_pending_unwind ();
14368 for (i
= 0; i
< 16; i
++)
14370 if (wcg_mask
& (1 << i
))
14371 unwind
.frame_size
+= 4;
14373 op
= 0xc700 | wcg_mask
;
14374 add_unwind_opcode (op
, 2);
14378 for (i
= 0; i
< 16; i
++)
14380 if (wr_mask
& (1 << i
))
14381 unwind
.frame_size
+= 8;
14383 /* Attempt to combine with a previous opcode. We do this because gcc
14384 likes to output separate unwind directives for a single block of
14386 if (unwind
.opcode_count
> 0)
14388 i
= unwind
.opcodes
[unwind
.opcode_count
- 1];
14389 if ((i
& 0xf8) == 0xc0)
14392 /* Only merge if the blocks are contiguous. */
14395 if ((wr_mask
& 0xfe00) == (1 << 9))
14397 wr_mask
|= ((1 << (i
+ 11)) - 1) & 0xfc00;
14398 unwind
.opcode_count
--;
14401 else if (i
== 6 && unwind
.opcode_count
>= 2)
14403 i
= unwind
.opcodes
[unwind
.opcode_count
- 2];
14407 op
= 0xffff << (reg
- 1);
14409 || ((wr_mask
& op
) == (1u << (reg
- 1))))
14411 op
= (1 << (reg
+ i
+ 1)) - 1;
14412 op
&= ~((1 << reg
) - 1);
14414 unwind
.opcode_count
-= 2;
14421 /* We want to generate opcodes in the order the registers have been
14422 saved, ie. descending order. */
14423 for (reg
= 15; reg
>= -1; reg
--)
14425 /* Save registers in blocks. */
14427 || !(wr_mask
& (1 << reg
)))
14429 /* We found an unsaved reg. Generate opcodes to save the
14430 preceeding block. */
14436 op
= 0xc0 | (hi_reg
- 10);
14437 add_unwind_opcode (op
, 1);
14442 op
= 0xc600 | ((reg
+ 1) << 4) | ((hi_reg
- reg
) - 1);
14443 add_unwind_opcode (op
, 2);
14452 ignore_rest_of_line ();
14456 /* Parse an unwind_save directive. */
14459 s_arm_unwind_save (int ignored ATTRIBUTE_UNUSED
)
14464 /* Figure out what sort of save we have. */
14465 SKIP_WHITESPACE ();
14466 saved_ptr
= input_line_pointer
;
14468 reg
= arm_reg_parse (&input_line_pointer
, all_reg_maps
[REG_TYPE_FN
].htab
);
14471 s_arm_unwind_save_fpa (reg
);
14475 if (*input_line_pointer
== '{')
14476 input_line_pointer
++;
14478 SKIP_WHITESPACE ();
14480 reg
= arm_reg_parse (&input_line_pointer
, all_reg_maps
[REG_TYPE_RN
].htab
);
14483 input_line_pointer
= saved_ptr
;
14484 s_arm_unwind_save_core ();
14488 reg
= arm_reg_parse (&input_line_pointer
, all_reg_maps
[REG_TYPE_DN
].htab
);
14491 input_line_pointer
= saved_ptr
;
14492 s_arm_unwind_save_vfp ();
14496 reg
= arm_reg_parse (&input_line_pointer
,
14497 all_reg_maps
[REG_TYPE_IWMMXT
].htab
);
14500 input_line_pointer
= saved_ptr
;
14501 s_arm_unwind_save_wmmx ();
14505 /* TODO: Maverick registers. */
14506 as_bad (_("unrecognised register"));
14510 /* Parse an unwind_movsp directive. */
14513 s_arm_unwind_movsp (int ignored ATTRIBUTE_UNUSED
)
14518 SKIP_WHITESPACE ();
14519 reg
= reg_required_here (&input_line_pointer
, -1);
14522 as_bad (_("ARM register expected"));
14523 ignore_rest_of_line ();
14527 if (reg
== 13 || reg
== 15)
14529 as_bad (_("r%d not permitted in .unwind_movsp directive"), reg
);
14530 ignore_rest_of_line ();
14534 if (unwind
.fp_reg
!= 13)
14535 as_bad (_("unexpected .unwind_movsp directive"));
14537 /* Generate opcode to restore the value. */
14539 add_unwind_opcode (op
, 1);
14541 /* Record the information for later. */
14542 unwind
.fp_reg
= reg
;
14543 unwind
.fp_offset
= unwind
.frame_size
;
14544 unwind
.sp_restored
= 1;
14545 demand_empty_rest_of_line ();
14549 /* Parse #<number>. */
14552 require_hashconst (int * val
)
14556 SKIP_WHITESPACE ();
14557 if (*input_line_pointer
== '#')
14559 input_line_pointer
++;
14563 exp
.X_op
= O_illegal
;
14565 if (exp
.X_op
!= O_constant
)
14567 as_bad (_("expected #constant"));
14568 ignore_rest_of_line ();
14571 *val
= exp
.X_add_number
;
14575 /* Parse an unwind_pad directive. */
14578 s_arm_unwind_pad (int ignored ATTRIBUTE_UNUSED
)
14582 if (require_hashconst (&offset
) == FAIL
)
14587 as_bad (_("stack increment must be multiple of 4"));
14588 ignore_rest_of_line ();
14592 /* Don't generate any opcodes, just record the details for later. */
14593 unwind
.frame_size
+= offset
;
14594 unwind
.pending_offset
+= offset
;
14596 demand_empty_rest_of_line ();
14599 /* Parse an unwind_setfp directive. */
14602 s_arm_unwind_setfp (int ignored ATTRIBUTE_UNUSED
)
14608 fp_reg
= reg_required_here (&input_line_pointer
, -1);
14609 if (skip_past_comma (&input_line_pointer
) == FAIL
)
14612 sp_reg
= reg_required_here (&input_line_pointer
, -1);
14614 if (fp_reg
== FAIL
|| sp_reg
== FAIL
)
14616 as_bad (_("expected <reg>, <reg>"));
14617 ignore_rest_of_line ();
14621 /* Optonal constant. */
14622 if (skip_past_comma (&input_line_pointer
) != FAIL
)
14624 if (require_hashconst (&offset
) == FAIL
)
14630 demand_empty_rest_of_line ();
14632 if (sp_reg
!= 13 && sp_reg
!= unwind
.fp_reg
)
14634 as_bad (_("register must be either sp or set by a previous"
14635 "unwind_movsp directive"));
14639 /* Don't generate any opcodes, just record the information for later. */
14640 unwind
.fp_reg
= fp_reg
;
14641 unwind
.fp_used
= 1;
14643 unwind
.fp_offset
= unwind
.frame_size
- offset
;
14645 unwind
.fp_offset
-= offset
;
14648 /* Parse an unwind_raw directive. */
14651 s_arm_unwind_raw (int ignored ATTRIBUTE_UNUSED
)
14654 /* This is an arbitary limit. */
14655 unsigned char op
[16];
14658 SKIP_WHITESPACE ();
14660 if (exp
.X_op
== O_constant
14661 && skip_past_comma (&input_line_pointer
) != FAIL
)
14663 unwind
.frame_size
+= exp
.X_add_number
;
14667 exp
.X_op
= O_illegal
;
14669 if (exp
.X_op
!= O_constant
)
14671 as_bad (_("expected <offset>, <opcode>"));
14672 ignore_rest_of_line ();
14678 /* Parse the opcode. */
14683 as_bad (_("unwind opcode too long"));
14684 ignore_rest_of_line ();
14686 if (exp
.X_op
!= O_constant
|| exp
.X_add_number
& ~0xff)
14688 as_bad (_("invalid unwind opcode"));
14689 ignore_rest_of_line ();
14692 op
[count
++] = exp
.X_add_number
;
14694 /* Parse the next byte. */
14695 if (skip_past_comma (&input_line_pointer
) == FAIL
)
14701 /* Add the opcode bytes in reverse order. */
14703 add_unwind_opcode (op
[count
], 1);
14705 demand_empty_rest_of_line ();
14708 #endif /* OBJ_ELF */
14710 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
14711 of an rs_align_code fragment. */
14714 arm_handle_align (fragS
* fragP
)
14716 static char const arm_noop
[4] = { 0x00, 0x00, 0xa0, 0xe1 };
14717 static char const thumb_noop
[2] = { 0xc0, 0x46 };
14718 static char const arm_bigend_noop
[4] = { 0xe1, 0xa0, 0x00, 0x00 };
14719 static char const thumb_bigend_noop
[2] = { 0x46, 0xc0 };
14721 int bytes
, fix
, noop_size
;
14725 if (fragP
->fr_type
!= rs_align_code
)
14728 bytes
= fragP
->fr_next
->fr_address
- fragP
->fr_address
- fragP
->fr_fix
;
14729 p
= fragP
->fr_literal
+ fragP
->fr_fix
;
14732 if (bytes
> MAX_MEM_FOR_RS_ALIGN_CODE
)
14733 bytes
&= MAX_MEM_FOR_RS_ALIGN_CODE
;
14735 if (fragP
->tc_frag_data
)
14737 if (target_big_endian
)
14738 noop
= thumb_bigend_noop
;
14741 noop_size
= sizeof (thumb_noop
);
14745 if (target_big_endian
)
14746 noop
= arm_bigend_noop
;
14749 noop_size
= sizeof (arm_noop
);
14752 if (bytes
& (noop_size
- 1))
14754 fix
= bytes
& (noop_size
- 1);
14755 memset (p
, 0, fix
);
14760 while (bytes
>= noop_size
)
14762 memcpy (p
, noop
, noop_size
);
14764 bytes
-= noop_size
;
14768 fragP
->fr_fix
+= fix
;
14769 fragP
->fr_var
= noop_size
;
14772 /* Called from md_do_align. Used to create an alignment
14773 frag in a code section. */
14776 arm_frag_align_code (int n
, int max
)
14780 /* We assume that there will never be a requirement
14781 to support alignments greater than 32 bytes. */
14782 if (max
> MAX_MEM_FOR_RS_ALIGN_CODE
)
14783 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
14785 p
= frag_var (rs_align_code
,
14786 MAX_MEM_FOR_RS_ALIGN_CODE
,
14788 (relax_substateT
) max
,
14795 /* Perform target specific initialisation of a frag. */
14798 arm_init_frag (fragS
* fragP
)
14800 /* Record whether this frag is in an ARM or a THUMB area. */
14801 fragP
->tc_frag_data
= thumb_mode
;
14806 /* Convert REGNAME to a DWARF-2 register number. */
14809 tc_arm_regname_to_dw2regnum (const char *regname
)
14813 for (i
= 0; rn_table
[i
].name
; i
++)
14814 if (streq (regname
, rn_table
[i
].name
))
14815 return rn_table
[i
].number
;
14820 /* Initialize the DWARF-2 unwind information for this procedure. */
14823 tc_arm_frame_initial_instructions (void)
14825 cfi_add_CFA_def_cfa (REG_SP
, 0);
14829 /* This table describes all the machine specific pseudo-ops the assembler
14830 has to support. The fields are:
14831 pseudo-op name without dot
14832 function to call to execute this pseudo-op
14833 Integer arg to pass to the function. */
14835 const pseudo_typeS md_pseudo_table
[] =
14837 /* Never called because '.req' does not start a line. */
14838 { "req", s_req
, 0 },
14839 { "unreq", s_unreq
, 0 },
14840 { "bss", s_bss
, 0 },
14841 { "align", s_align
, 0 },
14842 { "arm", s_arm
, 0 },
14843 { "thumb", s_thumb
, 0 },
14844 { "code", s_code
, 0 },
14845 { "force_thumb", s_force_thumb
, 0 },
14846 { "thumb_func", s_thumb_func
, 0 },
14847 { "thumb_set", s_thumb_set
, 0 },
14848 { "even", s_even
, 0 },
14849 { "ltorg", s_ltorg
, 0 },
14850 { "pool", s_ltorg
, 0 },
14852 { "word", s_arm_elf_cons
, 4 },
14853 { "long", s_arm_elf_cons
, 4 },
14854 { "rel31", s_arm_rel31
, 0 },
14855 { "fnstart", s_arm_unwind_fnstart
, 0 },
14856 { "fnend", s_arm_unwind_fnend
, 0 },
14857 { "cantunwind", s_arm_unwind_cantunwind
, 0 },
14858 { "personality", s_arm_unwind_personality
, 0 },
14859 { "personalityindex", s_arm_unwind_personalityindex
, 0 },
14860 { "handlerdata", s_arm_unwind_handlerdata
, 0 },
14861 { "save", s_arm_unwind_save
, 0 },
14862 { "movsp", s_arm_unwind_movsp
, 0 },
14863 { "pad", s_arm_unwind_pad
, 0 },
14864 { "setfp", s_arm_unwind_setfp
, 0 },
14865 { "unwind_raw", s_arm_unwind_raw
, 0 },
14867 { "word", cons
, 4},
14869 { "extend", float_cons
, 'x' },
14870 { "ldouble", float_cons
, 'x' },
14871 { "packed", float_cons
, 'p' },