1 /* tc-arm.c -- Assemble for the ARM
2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
4 Free Software Foundation, Inc.
5 Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
6 Modified by David Taylor (dtaylor@armltd.co.uk)
7 Cirrus coprocessor mods by Aldy Hernandez (aldyh@redhat.com)
8 Cirrus coprocessor fixes by Petko Manolov (petkan@nucleusys.com)
9 Cirrus coprocessor fixes by Vladimir Ivanov (vladitx@nucleusys.com)
11 This file is part of GAS, the GNU Assembler.
13 GAS is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 2, or (at your option)
18 GAS is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with GAS; see the file COPYING. If not, write to the Free
25 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
31 #include "safe-ctype.h"
33 /* Need TARGET_CPU. */
40 #include "opcode/arm.h"
44 #include "dwarf2dbg.h"
45 #include "dw2gencfi.h"
48 /* XXX Set this to 1 after the next binutils release. */
49 #define WARN_DEPRECATED 0
52 /* Must be at least the size of the largest unwind opcode (currently two). */
53 #define ARM_OPCODE_CHUNK_SIZE 8
55 /* This structure holds the unwinding state. */
60 symbolS
* table_entry
;
61 symbolS
* personality_routine
;
62 int personality_index
;
63 /* The segment containing the function. */
66 /* Opcodes generated from this function. */
67 unsigned char * opcodes
;
70 /* The number of bytes pushed to the stack. */
72 /* We don't add stack adjustment opcodes immediately so that we can merge
73 multiple adjustments. We can also omit the final adjustment
74 when using a frame pointer. */
75 offsetT pending_offset
;
76 /* These two fields are set by both unwind_movsp and unwind_setfp. They
77 hold the reg+offset to use when restoring sp from a frame pointer. */
80 /* Nonzero if an unwind_setfp directive has been seen. */
82 /* Nonzero if the last opcode restores sp from fp_reg. */
83 unsigned sp_restored
:1;
95 /* Types of processor to assemble for. */
96 #define ARM_1 ARM_ARCH_V1
97 #define ARM_2 ARM_ARCH_V2
98 #define ARM_3 ARM_ARCH_V2S
99 #define ARM_250 ARM_ARCH_V2S
100 #define ARM_6 ARM_ARCH_V3
101 #define ARM_7 ARM_ARCH_V3
102 #define ARM_8 ARM_ARCH_V4
103 #define ARM_9 ARM_ARCH_V4T
104 #define ARM_STRONG ARM_ARCH_V4
105 #define ARM_CPU_MASK 0x0000000f /* XXX? */
108 #if defined __XSCALE__
109 #define CPU_DEFAULT (ARM_ARCH_XSCALE)
111 #if defined __thumb__
112 #define CPU_DEFAULT (ARM_ARCH_V5T)
114 #define CPU_DEFAULT ARM_ANY
121 # define FPU_DEFAULT FPU_ARCH_FPA
122 # elif defined (TE_NetBSD)
124 # define FPU_DEFAULT FPU_ARCH_VFP /* Soft-float, but VFP order. */
126 /* Legacy a.out format. */
127 # define FPU_DEFAULT FPU_ARCH_FPA /* Soft-float, but FPA order. */
129 # elif defined (TE_VXWORKS)
130 # define FPU_DEFAULT FPU_ARCH_VFP /* Soft-float, VFP order. */
132 /* For backwards compatibility, default to FPA. */
133 # define FPU_DEFAULT FPU_ARCH_FPA
135 #endif /* ifndef FPU_DEFAULT */
137 #define streq(a, b) (strcmp (a, b) == 0)
138 #define skip_whitespace(str) while (*(str) == ' ') ++(str)
140 static unsigned long cpu_variant
;
142 /* Flags stored in private area of BFD structure. */
143 static int uses_apcs_26
= FALSE
;
144 static int atpcs
= FALSE
;
145 static int support_interwork
= FALSE
;
146 static int uses_apcs_float
= FALSE
;
147 static int pic_code
= FALSE
;
149 /* Variables that we set while parsing command-line options. Once all
150 options have been read we re-process these values to set the real
152 static int legacy_cpu
= -1;
153 static int legacy_fpu
= -1;
155 static int mcpu_cpu_opt
= -1;
156 static int mcpu_fpu_opt
= -1;
157 static int march_cpu_opt
= -1;
158 static int march_fpu_opt
= -1;
159 static int mfpu_opt
= -1;
160 static int mfloat_abi_opt
= -1;
162 static int meabi_flags
= EF_ARM_EABI_UNKNOWN
;
165 /* This array holds the chars that always start a comment. If the
166 pre-processor is disabled, these aren't very useful. */
167 const char comment_chars
[] = "@";
169 /* This array holds the chars that only start a comment at the beginning of
170 a line. If the line seems to have the form '# 123 filename'
171 .line and .file directives will appear in the pre-processed output. */
172 /* Note that input_file.c hand checks for '#' at the beginning of the
173 first line of the input file. This is because the compiler outputs
174 #NO_APP at the beginning of its output. */
175 /* Also note that comments like this one will always work. */
176 const char line_comment_chars
[] = "#";
178 const char line_separator_chars
[] = ";";
180 /* Chars that can be used to separate mant
181 from exp in floating point numbers. */
182 const char EXP_CHARS
[] = "eE";
184 /* Chars that mean this number is a floating point constant. */
188 const char FLT_CHARS
[] = "rRsSfFdDxXeEpP";
190 /* Prefix characters that indicate the start of an immediate
192 #define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
195 /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
196 symbolS
* GOT_symbol
;
199 /* Size of relocation record. */
200 const int md_reloc_size
= 8;
202 /* 0: assemble for ARM,
203 1: assemble for Thumb,
204 2: assemble for Thumb even though target CPU does not support thumb
206 static int thumb_mode
= 0;
208 typedef struct arm_fix
216 unsigned long instruction
;
220 bfd_reloc_code_real_type type
;
237 struct asm_shift_properties
239 enum asm_shift_index index
;
240 unsigned long bit_field
;
241 unsigned int allows_0
: 1;
242 unsigned int allows_32
: 1;
245 static const struct asm_shift_properties shift_properties
[] =
247 { SHIFT_LSL
, 0, 1, 0},
248 { SHIFT_LSR
, 0x20, 0, 1},
249 { SHIFT_ASR
, 0x40, 0, 1},
250 { SHIFT_ROR
, 0x60, 0, 0},
251 { SHIFT_RRX
, 0x60, 0, 0}
254 struct asm_shift_name
257 const struct asm_shift_properties
* properties
;
260 static const struct asm_shift_name shift_names
[] =
262 { "asl", shift_properties
+ SHIFT_LSL
},
263 { "lsl", shift_properties
+ SHIFT_LSL
},
264 { "lsr", shift_properties
+ SHIFT_LSR
},
265 { "asr", shift_properties
+ SHIFT_ASR
},
266 { "ror", shift_properties
+ SHIFT_ROR
},
267 { "rrx", shift_properties
+ SHIFT_RRX
},
268 { "ASL", shift_properties
+ SHIFT_LSL
},
269 { "LSL", shift_properties
+ SHIFT_LSL
},
270 { "LSR", shift_properties
+ SHIFT_LSR
},
271 { "ASR", shift_properties
+ SHIFT_ASR
},
272 { "ROR", shift_properties
+ SHIFT_ROR
},
273 { "RRX", shift_properties
+ SHIFT_RRX
}
276 /* Any kind of shift is accepted. */
277 #define NO_SHIFT_RESTRICT 1
278 /* The shift operand must be an immediate value, not a register. */
279 #define SHIFT_IMMEDIATE 0
280 /* The shift must be LSL or ASR and the operand must be an immediate. */
281 #define SHIFT_LSL_OR_ASR_IMMEDIATE 2
282 /* The shift must be ASR and the operand must be an immediate. */
283 #define SHIFT_ASR_IMMEDIATE 3
284 /* The shift must be LSL and the operand must be an immediate. */
285 #define SHIFT_LSL_IMMEDIATE 4
287 #define NUM_FLOAT_VALS 8
289 const char * fp_const
[] =
291 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
294 /* Number of littlenums required to hold an extended precision number. */
295 #define MAX_LITTLENUMS 6
297 LITTLENUM_TYPE fp_values
[NUM_FLOAT_VALS
][MAX_LITTLENUMS
];
302 /* Whether a Co-processor load/store operation accepts write-back forms. */
311 #define CP_T_X 0x00008000
312 #define CP_T_Y 0x00400000
313 #define CP_T_Pre 0x01000000
314 #define CP_T_UD 0x00800000
315 #define CP_T_WB 0x00200000
317 #define CONDS_BIT 0x00100000
318 #define LOAD_BIT 0x00100000
320 #define DOUBLE_LOAD_FLAG 0x00000001
324 const char * template;
328 #define COND_ALWAYS 0xe0000000
329 #define COND_MASK 0xf0000000
331 static const struct asm_cond conds
[] =
335 {"cs", 0x20000000}, {"hs", 0x20000000},
336 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
353 const char *template;
358 /* The bit that distinguishes CPSR and SPSR. */
359 #define SPSR_BIT (1 << 22)
361 /* How many bits to shift the PSR_xxx bits up by. */
364 #define PSR_c (1 << 0)
365 #define PSR_x (1 << 1)
366 #define PSR_s (1 << 2)
367 #define PSR_f (1 << 3)
369 static const struct asm_psr psrs
[] =
371 {"CPSR", TRUE
, PSR_c
| PSR_f
},
372 {"CPSR_all", TRUE
, PSR_c
| PSR_f
},
373 {"SPSR", FALSE
, PSR_c
| PSR_f
},
374 {"SPSR_all", FALSE
, PSR_c
| PSR_f
},
375 {"CPSR_flg", TRUE
, PSR_f
},
376 {"CPSR_f", TRUE
, PSR_f
},
377 {"SPSR_flg", FALSE
, PSR_f
},
378 {"SPSR_f", FALSE
, PSR_f
},
379 {"CPSR_c", TRUE
, PSR_c
},
380 {"CPSR_ctl", TRUE
, PSR_c
},
381 {"SPSR_c", FALSE
, PSR_c
},
382 {"SPSR_ctl", FALSE
, PSR_c
},
383 {"CPSR_x", TRUE
, PSR_x
},
384 {"CPSR_s", TRUE
, PSR_s
},
385 {"SPSR_x", FALSE
, PSR_x
},
386 {"SPSR_s", FALSE
, PSR_s
},
387 /* Combinations of flags. */
388 {"CPSR_fs", TRUE
, PSR_f
| PSR_s
},
389 {"CPSR_fx", TRUE
, PSR_f
| PSR_x
},
390 {"CPSR_fc", TRUE
, PSR_f
| PSR_c
},
391 {"CPSR_sf", TRUE
, PSR_s
| PSR_f
},
392 {"CPSR_sx", TRUE
, PSR_s
| PSR_x
},
393 {"CPSR_sc", TRUE
, PSR_s
| PSR_c
},
394 {"CPSR_xf", TRUE
, PSR_x
| PSR_f
},
395 {"CPSR_xs", TRUE
, PSR_x
| PSR_s
},
396 {"CPSR_xc", TRUE
, PSR_x
| PSR_c
},
397 {"CPSR_cf", TRUE
, PSR_c
| PSR_f
},
398 {"CPSR_cs", TRUE
, PSR_c
| PSR_s
},
399 {"CPSR_cx", TRUE
, PSR_c
| PSR_x
},
400 {"CPSR_fsx", TRUE
, PSR_f
| PSR_s
| PSR_x
},
401 {"CPSR_fsc", TRUE
, PSR_f
| PSR_s
| PSR_c
},
402 {"CPSR_fxs", TRUE
, PSR_f
| PSR_x
| PSR_s
},
403 {"CPSR_fxc", TRUE
, PSR_f
| PSR_x
| PSR_c
},
404 {"CPSR_fcs", TRUE
, PSR_f
| PSR_c
| PSR_s
},
405 {"CPSR_fcx", TRUE
, PSR_f
| PSR_c
| PSR_x
},
406 {"CPSR_sfx", TRUE
, PSR_s
| PSR_f
| PSR_x
},
407 {"CPSR_sfc", TRUE
, PSR_s
| PSR_f
| PSR_c
},
408 {"CPSR_sxf", TRUE
, PSR_s
| PSR_x
| PSR_f
},
409 {"CPSR_sxc", TRUE
, PSR_s
| PSR_x
| PSR_c
},
410 {"CPSR_scf", TRUE
, PSR_s
| PSR_c
| PSR_f
},
411 {"CPSR_scx", TRUE
, PSR_s
| PSR_c
| PSR_x
},
412 {"CPSR_xfs", TRUE
, PSR_x
| PSR_f
| PSR_s
},
413 {"CPSR_xfc", TRUE
, PSR_x
| PSR_f
| PSR_c
},
414 {"CPSR_xsf", TRUE
, PSR_x
| PSR_s
| PSR_f
},
415 {"CPSR_xsc", TRUE
, PSR_x
| PSR_s
| PSR_c
},
416 {"CPSR_xcf", TRUE
, PSR_x
| PSR_c
| PSR_f
},
417 {"CPSR_xcs", TRUE
, PSR_x
| PSR_c
| PSR_s
},
418 {"CPSR_cfs", TRUE
, PSR_c
| PSR_f
| PSR_s
},
419 {"CPSR_cfx", TRUE
, PSR_c
| PSR_f
| PSR_x
},
420 {"CPSR_csf", TRUE
, PSR_c
| PSR_s
| PSR_f
},
421 {"CPSR_csx", TRUE
, PSR_c
| PSR_s
| PSR_x
},
422 {"CPSR_cxf", TRUE
, PSR_c
| PSR_x
| PSR_f
},
423 {"CPSR_cxs", TRUE
, PSR_c
| PSR_x
| PSR_s
},
424 {"CPSR_fsxc", TRUE
, PSR_f
| PSR_s
| PSR_x
| PSR_c
},
425 {"CPSR_fscx", TRUE
, PSR_f
| PSR_s
| PSR_c
| PSR_x
},
426 {"CPSR_fxsc", TRUE
, PSR_f
| PSR_x
| PSR_s
| PSR_c
},
427 {"CPSR_fxcs", TRUE
, PSR_f
| PSR_x
| PSR_c
| PSR_s
},
428 {"CPSR_fcsx", TRUE
, PSR_f
| PSR_c
| PSR_s
| PSR_x
},
429 {"CPSR_fcxs", TRUE
, PSR_f
| PSR_c
| PSR_x
| PSR_s
},
430 {"CPSR_sfxc", TRUE
, PSR_s
| PSR_f
| PSR_x
| PSR_c
},
431 {"CPSR_sfcx", TRUE
, PSR_s
| PSR_f
| PSR_c
| PSR_x
},
432 {"CPSR_sxfc", TRUE
, PSR_s
| PSR_x
| PSR_f
| PSR_c
},
433 {"CPSR_sxcf", TRUE
, PSR_s
| PSR_x
| PSR_c
| PSR_f
},
434 {"CPSR_scfx", TRUE
, PSR_s
| PSR_c
| PSR_f
| PSR_x
},
435 {"CPSR_scxf", TRUE
, PSR_s
| PSR_c
| PSR_x
| PSR_f
},
436 {"CPSR_xfsc", TRUE
, PSR_x
| PSR_f
| PSR_s
| PSR_c
},
437 {"CPSR_xfcs", TRUE
, PSR_x
| PSR_f
| PSR_c
| PSR_s
},
438 {"CPSR_xsfc", TRUE
, PSR_x
| PSR_s
| PSR_f
| PSR_c
},
439 {"CPSR_xscf", TRUE
, PSR_x
| PSR_s
| PSR_c
| PSR_f
},
440 {"CPSR_xcfs", TRUE
, PSR_x
| PSR_c
| PSR_f
| PSR_s
},
441 {"CPSR_xcsf", TRUE
, PSR_x
| PSR_c
| PSR_s
| PSR_f
},
442 {"CPSR_cfsx", TRUE
, PSR_c
| PSR_f
| PSR_s
| PSR_x
},
443 {"CPSR_cfxs", TRUE
, PSR_c
| PSR_f
| PSR_x
| PSR_s
},
444 {"CPSR_csfx", TRUE
, PSR_c
| PSR_s
| PSR_f
| PSR_x
},
445 {"CPSR_csxf", TRUE
, PSR_c
| PSR_s
| PSR_x
| PSR_f
},
446 {"CPSR_cxfs", TRUE
, PSR_c
| PSR_x
| PSR_f
| PSR_s
},
447 {"CPSR_cxsf", TRUE
, PSR_c
| PSR_x
| PSR_s
| PSR_f
},
448 {"SPSR_fs", FALSE
, PSR_f
| PSR_s
},
449 {"SPSR_fx", FALSE
, PSR_f
| PSR_x
},
450 {"SPSR_fc", FALSE
, PSR_f
| PSR_c
},
451 {"SPSR_sf", FALSE
, PSR_s
| PSR_f
},
452 {"SPSR_sx", FALSE
, PSR_s
| PSR_x
},
453 {"SPSR_sc", FALSE
, PSR_s
| PSR_c
},
454 {"SPSR_xf", FALSE
, PSR_x
| PSR_f
},
455 {"SPSR_xs", FALSE
, PSR_x
| PSR_s
},
456 {"SPSR_xc", FALSE
, PSR_x
| PSR_c
},
457 {"SPSR_cf", FALSE
, PSR_c
| PSR_f
},
458 {"SPSR_cs", FALSE
, PSR_c
| PSR_s
},
459 {"SPSR_cx", FALSE
, PSR_c
| PSR_x
},
460 {"SPSR_fsx", FALSE
, PSR_f
| PSR_s
| PSR_x
},
461 {"SPSR_fsc", FALSE
, PSR_f
| PSR_s
| PSR_c
},
462 {"SPSR_fxs", FALSE
, PSR_f
| PSR_x
| PSR_s
},
463 {"SPSR_fxc", FALSE
, PSR_f
| PSR_x
| PSR_c
},
464 {"SPSR_fcs", FALSE
, PSR_f
| PSR_c
| PSR_s
},
465 {"SPSR_fcx", FALSE
, PSR_f
| PSR_c
| PSR_x
},
466 {"SPSR_sfx", FALSE
, PSR_s
| PSR_f
| PSR_x
},
467 {"SPSR_sfc", FALSE
, PSR_s
| PSR_f
| PSR_c
},
468 {"SPSR_sxf", FALSE
, PSR_s
| PSR_x
| PSR_f
},
469 {"SPSR_sxc", FALSE
, PSR_s
| PSR_x
| PSR_c
},
470 {"SPSR_scf", FALSE
, PSR_s
| PSR_c
| PSR_f
},
471 {"SPSR_scx", FALSE
, PSR_s
| PSR_c
| PSR_x
},
472 {"SPSR_xfs", FALSE
, PSR_x
| PSR_f
| PSR_s
},
473 {"SPSR_xfc", FALSE
, PSR_x
| PSR_f
| PSR_c
},
474 {"SPSR_xsf", FALSE
, PSR_x
| PSR_s
| PSR_f
},
475 {"SPSR_xsc", FALSE
, PSR_x
| PSR_s
| PSR_c
},
476 {"SPSR_xcf", FALSE
, PSR_x
| PSR_c
| PSR_f
},
477 {"SPSR_xcs", FALSE
, PSR_x
| PSR_c
| PSR_s
},
478 {"SPSR_cfs", FALSE
, PSR_c
| PSR_f
| PSR_s
},
479 {"SPSR_cfx", FALSE
, PSR_c
| PSR_f
| PSR_x
},
480 {"SPSR_csf", FALSE
, PSR_c
| PSR_s
| PSR_f
},
481 {"SPSR_csx", FALSE
, PSR_c
| PSR_s
| PSR_x
},
482 {"SPSR_cxf", FALSE
, PSR_c
| PSR_x
| PSR_f
},
483 {"SPSR_cxs", FALSE
, PSR_c
| PSR_x
| PSR_s
},
484 {"SPSR_fsxc", FALSE
, PSR_f
| PSR_s
| PSR_x
| PSR_c
},
485 {"SPSR_fscx", FALSE
, PSR_f
| PSR_s
| PSR_c
| PSR_x
},
486 {"SPSR_fxsc", FALSE
, PSR_f
| PSR_x
| PSR_s
| PSR_c
},
487 {"SPSR_fxcs", FALSE
, PSR_f
| PSR_x
| PSR_c
| PSR_s
},
488 {"SPSR_fcsx", FALSE
, PSR_f
| PSR_c
| PSR_s
| PSR_x
},
489 {"SPSR_fcxs", FALSE
, PSR_f
| PSR_c
| PSR_x
| PSR_s
},
490 {"SPSR_sfxc", FALSE
, PSR_s
| PSR_f
| PSR_x
| PSR_c
},
491 {"SPSR_sfcx", FALSE
, PSR_s
| PSR_f
| PSR_c
| PSR_x
},
492 {"SPSR_sxfc", FALSE
, PSR_s
| PSR_x
| PSR_f
| PSR_c
},
493 {"SPSR_sxcf", FALSE
, PSR_s
| PSR_x
| PSR_c
| PSR_f
},
494 {"SPSR_scfx", FALSE
, PSR_s
| PSR_c
| PSR_f
| PSR_x
},
495 {"SPSR_scxf", FALSE
, PSR_s
| PSR_c
| PSR_x
| PSR_f
},
496 {"SPSR_xfsc", FALSE
, PSR_x
| PSR_f
| PSR_s
| PSR_c
},
497 {"SPSR_xfcs", FALSE
, PSR_x
| PSR_f
| PSR_c
| PSR_s
},
498 {"SPSR_xsfc", FALSE
, PSR_x
| PSR_s
| PSR_f
| PSR_c
},
499 {"SPSR_xscf", FALSE
, PSR_x
| PSR_s
| PSR_c
| PSR_f
},
500 {"SPSR_xcfs", FALSE
, PSR_x
| PSR_c
| PSR_f
| PSR_s
},
501 {"SPSR_xcsf", FALSE
, PSR_x
| PSR_c
| PSR_s
| PSR_f
},
502 {"SPSR_cfsx", FALSE
, PSR_c
| PSR_f
| PSR_s
| PSR_x
},
503 {"SPSR_cfxs", FALSE
, PSR_c
| PSR_f
| PSR_x
| PSR_s
},
504 {"SPSR_csfx", FALSE
, PSR_c
| PSR_s
| PSR_f
| PSR_x
},
505 {"SPSR_csxf", FALSE
, PSR_c
| PSR_s
| PSR_x
| PSR_f
},
506 {"SPSR_cxfs", FALSE
, PSR_c
| PSR_x
| PSR_f
| PSR_s
},
507 {"SPSR_cxsf", FALSE
, PSR_c
| PSR_x
| PSR_s
| PSR_f
},
514 IWMMXT_REG_WR_OR_WC
= 2,
518 enum iwmmxt_insn_type
541 VFP_REG_Dd
, VFP_REG_Dm
, VFP_REG_Dn
546 VFP_REG_Sd
, VFP_REG_Sm
, VFP_REG_Sn
551 VFP_LDSTMIA
, VFP_LDSTMDB
, VFP_LDSTMIAX
, VFP_LDSTMDBX
554 /* VFP system registers. */
561 static const struct vfp_reg vfp_regs
[] =
563 {"fpsid", 0x00000000},
564 {"FPSID", 0x00000000},
565 {"fpscr", 0x00010000},
566 {"FPSCR", 0x00010000},
567 {"fpexc", 0x00080000},
568 {"FPEXC", 0x00080000}
571 /* Structure for a hash table entry for a register. */
579 /* Some well known registers that we refer to directly elsewhere. */
584 #define wr_register(reg) ((reg ^ WR_PREFIX) >= 0 && (reg ^ WR_PREFIX) <= 15)
585 #define wc_register(reg) ((reg ^ WC_PREFIX) >= 0 && (reg ^ WC_PREFIX) <= 15)
586 #define wcg_register(reg) ((reg ^ WC_PREFIX) >= 8 && (reg ^ WC_PREFIX) <= 11)
588 /* These are the standard names. Users can add aliases with .req.
589 and delete them with .unreq. */
591 /* Integer Register Numbers. */
592 static const struct reg_entry rn_table
[] =
594 {"r0", 0, TRUE
}, {"r1", 1, TRUE
}, {"r2", 2, TRUE
}, {"r3", 3, TRUE
},
595 {"r4", 4, TRUE
}, {"r5", 5, TRUE
}, {"r6", 6, TRUE
}, {"r7", 7, TRUE
},
596 {"r8", 8, TRUE
}, {"r9", 9, TRUE
}, {"r10", 10, TRUE
}, {"r11", 11, TRUE
},
597 {"r12", 12, TRUE
}, {"r13", REG_SP
, TRUE
}, {"r14", REG_LR
, TRUE
}, {"r15", REG_PC
, TRUE
},
598 /* ATPCS Synonyms. */
599 {"a1", 0, TRUE
}, {"a2", 1, TRUE
}, {"a3", 2, TRUE
}, {"a4", 3, TRUE
},
600 {"v1", 4, TRUE
}, {"v2", 5, TRUE
}, {"v3", 6, TRUE
}, {"v4", 7, TRUE
},
601 {"v5", 8, TRUE
}, {"v6", 9, TRUE
}, {"v7", 10, TRUE
}, {"v8", 11, TRUE
},
602 /* Well-known aliases. */
603 {"wr", 7, TRUE
}, {"sb", 9, TRUE
}, {"sl", 10, TRUE
}, {"fp", 11, TRUE
},
604 {"ip", 12, TRUE
}, {"sp", REG_SP
, TRUE
}, {"lr", REG_LR
, TRUE
}, {"pc", REG_PC
, TRUE
},
608 #define WR_PREFIX 0x200
609 #define WC_PREFIX 0x400
611 static const struct reg_entry iwmmxt_table
[] =
613 /* Intel Wireless MMX technology register names. */
614 { "wr0", 0x0 | WR_PREFIX
, TRUE
}, {"wr1", 0x1 | WR_PREFIX
, TRUE
},
615 { "wr2", 0x2 | WR_PREFIX
, TRUE
}, {"wr3", 0x3 | WR_PREFIX
, TRUE
},
616 { "wr4", 0x4 | WR_PREFIX
, TRUE
}, {"wr5", 0x5 | WR_PREFIX
, TRUE
},
617 { "wr6", 0x6 | WR_PREFIX
, TRUE
}, {"wr7", 0x7 | WR_PREFIX
, TRUE
},
618 { "wr8", 0x8 | WR_PREFIX
, TRUE
}, {"wr9", 0x9 | WR_PREFIX
, TRUE
},
619 { "wr10", 0xa | WR_PREFIX
, TRUE
}, {"wr11", 0xb | WR_PREFIX
, TRUE
},
620 { "wr12", 0xc | WR_PREFIX
, TRUE
}, {"wr13", 0xd | WR_PREFIX
, TRUE
},
621 { "wr14", 0xe | WR_PREFIX
, TRUE
}, {"wr15", 0xf | WR_PREFIX
, TRUE
},
622 { "wcid", 0x0 | WC_PREFIX
, TRUE
}, {"wcon", 0x1 | WC_PREFIX
, TRUE
},
623 {"wcssf", 0x2 | WC_PREFIX
, TRUE
}, {"wcasf", 0x3 | WC_PREFIX
, TRUE
},
624 {"wcgr0", 0x8 | WC_PREFIX
, TRUE
}, {"wcgr1", 0x9 | WC_PREFIX
, TRUE
},
625 {"wcgr2", 0xa | WC_PREFIX
, TRUE
}, {"wcgr3", 0xb | WC_PREFIX
, TRUE
},
627 { "wR0", 0x0 | WR_PREFIX
, TRUE
}, {"wR1", 0x1 | WR_PREFIX
, TRUE
},
628 { "wR2", 0x2 | WR_PREFIX
, TRUE
}, {"wR3", 0x3 | WR_PREFIX
, TRUE
},
629 { "wR4", 0x4 | WR_PREFIX
, TRUE
}, {"wR5", 0x5 | WR_PREFIX
, TRUE
},
630 { "wR6", 0x6 | WR_PREFIX
, TRUE
}, {"wR7", 0x7 | WR_PREFIX
, TRUE
},
631 { "wR8", 0x8 | WR_PREFIX
, TRUE
}, {"wR9", 0x9 | WR_PREFIX
, TRUE
},
632 { "wR10", 0xa | WR_PREFIX
, TRUE
}, {"wR11", 0xb | WR_PREFIX
, TRUE
},
633 { "wR12", 0xc | WR_PREFIX
, TRUE
}, {"wR13", 0xd | WR_PREFIX
, TRUE
},
634 { "wR14", 0xe | WR_PREFIX
, TRUE
}, {"wR15", 0xf | WR_PREFIX
, TRUE
},
635 { "wCID", 0x0 | WC_PREFIX
, TRUE
}, {"wCon", 0x1 | WC_PREFIX
, TRUE
},
636 {"wCSSF", 0x2 | WC_PREFIX
, TRUE
}, {"wCASF", 0x3 | WC_PREFIX
, TRUE
},
637 {"wCGR0", 0x8 | WC_PREFIX
, TRUE
}, {"wCGR1", 0x9 | WC_PREFIX
, TRUE
},
638 {"wCGR2", 0xa | WC_PREFIX
, TRUE
}, {"wCGR3", 0xb | WC_PREFIX
, TRUE
},
642 /* Co-processor Numbers. */
643 static const struct reg_entry cp_table
[] =
645 {"p0", 0, TRUE
}, {"p1", 1, TRUE
}, {"p2", 2, TRUE
}, {"p3", 3, TRUE
},
646 {"p4", 4, TRUE
}, {"p5", 5, TRUE
}, {"p6", 6, TRUE
}, {"p7", 7, TRUE
},
647 {"p8", 8, TRUE
}, {"p9", 9, TRUE
}, {"p10", 10, TRUE
}, {"p11", 11, TRUE
},
648 {"p12", 12, TRUE
}, {"p13", 13, TRUE
}, {"p14", 14, TRUE
}, {"p15", 15, TRUE
},
652 /* Co-processor Register Numbers. */
653 static const struct reg_entry cn_table
[] =
655 {"c0", 0, TRUE
}, {"c1", 1, TRUE
}, {"c2", 2, TRUE
}, {"c3", 3, TRUE
},
656 {"c4", 4, TRUE
}, {"c5", 5, TRUE
}, {"c6", 6, TRUE
}, {"c7", 7, TRUE
},
657 {"c8", 8, TRUE
}, {"c9", 9, TRUE
}, {"c10", 10, TRUE
}, {"c11", 11, TRUE
},
658 {"c12", 12, TRUE
}, {"c13", 13, TRUE
}, {"c14", 14, TRUE
}, {"c15", 15, TRUE
},
659 /* Not really valid, but kept for back-wards compatibility. */
660 {"cr0", 0, TRUE
}, {"cr1", 1, TRUE
}, {"cr2", 2, TRUE
}, {"cr3", 3, TRUE
},
661 {"cr4", 4, TRUE
}, {"cr5", 5, TRUE
}, {"cr6", 6, TRUE
}, {"cr7", 7, TRUE
},
662 {"cr8", 8, TRUE
}, {"cr9", 9, TRUE
}, {"cr10", 10, TRUE
}, {"cr11", 11, TRUE
},
663 {"cr12", 12, TRUE
}, {"cr13", 13, TRUE
}, {"cr14", 14, TRUE
}, {"cr15", 15, TRUE
},
668 static const struct reg_entry fn_table
[] =
670 {"f0", 0, TRUE
}, {"f1", 1, TRUE
}, {"f2", 2, TRUE
}, {"f3", 3, TRUE
},
671 {"f4", 4, TRUE
}, {"f5", 5, TRUE
}, {"f6", 6, TRUE
}, {"f7", 7, TRUE
},
675 /* VFP SP Registers. */
676 static const struct reg_entry sn_table
[] =
678 {"s0", 0, TRUE
}, {"s1", 1, TRUE
}, {"s2", 2, TRUE
}, {"s3", 3, TRUE
},
679 {"s4", 4, TRUE
}, {"s5", 5, TRUE
}, {"s6", 6, TRUE
}, {"s7", 7, TRUE
},
680 {"s8", 8, TRUE
}, {"s9", 9, TRUE
}, {"s10", 10, TRUE
}, {"s11", 11, TRUE
},
681 {"s12", 12, TRUE
}, {"s13", 13, TRUE
}, {"s14", 14, TRUE
}, {"s15", 15, TRUE
},
682 {"s16", 16, TRUE
}, {"s17", 17, TRUE
}, {"s18", 18, TRUE
}, {"s19", 19, TRUE
},
683 {"s20", 20, TRUE
}, {"s21", 21, TRUE
}, {"s22", 22, TRUE
}, {"s23", 23, TRUE
},
684 {"s24", 24, TRUE
}, {"s25", 25, TRUE
}, {"s26", 26, TRUE
}, {"s27", 27, TRUE
},
685 {"s28", 28, TRUE
}, {"s29", 29, TRUE
}, {"s30", 30, TRUE
}, {"s31", 31, TRUE
},
689 /* VFP DP Registers. */
690 static const struct reg_entry dn_table
[] =
692 {"d0", 0, TRUE
}, {"d1", 1, TRUE
}, {"d2", 2, TRUE
}, {"d3", 3, TRUE
},
693 {"d4", 4, TRUE
}, {"d5", 5, TRUE
}, {"d6", 6, TRUE
}, {"d7", 7, TRUE
},
694 {"d8", 8, TRUE
}, {"d9", 9, TRUE
}, {"d10", 10, TRUE
}, {"d11", 11, TRUE
},
695 {"d12", 12, TRUE
}, {"d13", 13, TRUE
}, {"d14", 14, TRUE
}, {"d15", 15, TRUE
},
699 /* Maverick DSP coprocessor registers. */
700 static const struct reg_entry mav_mvf_table
[] =
702 {"mvf0", 0, TRUE
}, {"mvf1", 1, TRUE
}, {"mvf2", 2, TRUE
}, {"mvf3", 3, TRUE
},
703 {"mvf4", 4, TRUE
}, {"mvf5", 5, TRUE
}, {"mvf6", 6, TRUE
}, {"mvf7", 7, TRUE
},
704 {"mvf8", 8, TRUE
}, {"mvf9", 9, TRUE
}, {"mvf10", 10, TRUE
}, {"mvf11", 11, TRUE
},
705 {"mvf12", 12, TRUE
}, {"mvf13", 13, TRUE
}, {"mvf14", 14, TRUE
}, {"mvf15", 15, TRUE
},
709 static const struct reg_entry mav_mvd_table
[] =
711 {"mvd0", 0, TRUE
}, {"mvd1", 1, TRUE
}, {"mvd2", 2, TRUE
}, {"mvd3", 3, TRUE
},
712 {"mvd4", 4, TRUE
}, {"mvd5", 5, TRUE
}, {"mvd6", 6, TRUE
}, {"mvd7", 7, TRUE
},
713 {"mvd8", 8, TRUE
}, {"mvd9", 9, TRUE
}, {"mvd10", 10, TRUE
}, {"mvd11", 11, TRUE
},
714 {"mvd12", 12, TRUE
}, {"mvd13", 13, TRUE
}, {"mvd14", 14, TRUE
}, {"mvd15", 15, TRUE
},
718 static const struct reg_entry mav_mvfx_table
[] =
720 {"mvfx0", 0, TRUE
}, {"mvfx1", 1, TRUE
}, {"mvfx2", 2, TRUE
}, {"mvfx3", 3, TRUE
},
721 {"mvfx4", 4, TRUE
}, {"mvfx5", 5, TRUE
}, {"mvfx6", 6, TRUE
}, {"mvfx7", 7, TRUE
},
722 {"mvfx8", 8, TRUE
}, {"mvfx9", 9, TRUE
}, {"mvfx10", 10, TRUE
}, {"mvfx11", 11, TRUE
},
723 {"mvfx12", 12, TRUE
}, {"mvfx13", 13, TRUE
}, {"mvfx14", 14, TRUE
}, {"mvfx15", 15, TRUE
},
727 static const struct reg_entry mav_mvdx_table
[] =
729 {"mvdx0", 0, TRUE
}, {"mvdx1", 1, TRUE
}, {"mvdx2", 2, TRUE
}, {"mvdx3", 3, TRUE
},
730 {"mvdx4", 4, TRUE
}, {"mvdx5", 5, TRUE
}, {"mvdx6", 6, TRUE
}, {"mvdx7", 7, TRUE
},
731 {"mvdx8", 8, TRUE
}, {"mvdx9", 9, TRUE
}, {"mvdx10", 10, TRUE
}, {"mvdx11", 11, TRUE
},
732 {"mvdx12", 12, TRUE
}, {"mvdx13", 13, TRUE
}, {"mvdx14", 14, TRUE
}, {"mvdx15", 15, TRUE
},
736 static const struct reg_entry mav_mvax_table
[] =
738 {"mvax0", 0, TRUE
}, {"mvax1", 1, TRUE
}, {"mvax2", 2, TRUE
}, {"mvax3", 3, TRUE
},
742 static const struct reg_entry mav_dspsc_table
[] =
750 const struct reg_entry
* names
;
752 struct hash_control
* htab
;
753 const char * expected
;
756 struct reg_map all_reg_maps
[] =
758 {rn_table
, 15, NULL
, N_("ARM register expected")},
759 {cp_table
, 15, NULL
, N_("bad or missing co-processor number")},
760 {cn_table
, 15, NULL
, N_("co-processor register expected")},
761 {fn_table
, 7, NULL
, N_("FPA register expected")},
762 {sn_table
, 31, NULL
, N_("VFP single precision register expected")},
763 {dn_table
, 15, NULL
, N_("VFP double precision register expected")},
764 {mav_mvf_table
, 15, NULL
, N_("Maverick MVF register expected")},
765 {mav_mvd_table
, 15, NULL
, N_("Maverick MVD register expected")},
766 {mav_mvfx_table
, 15, NULL
, N_("Maverick MVFX register expected")},
767 {mav_mvdx_table
, 15, NULL
, N_("Maverick MVDX register expected")},
768 {mav_mvax_table
, 3, NULL
, N_("Maverick MVAX register expected")},
769 {mav_dspsc_table
, 0, NULL
, N_("Maverick DSPSC register expected")},
770 {iwmmxt_table
, 23, NULL
, N_("Intel Wireless MMX technology register expected")},
773 /* Enumeration matching entries in table above. */
777 #define REG_TYPE_FIRST REG_TYPE_RN
789 REG_TYPE_IWMMXT
= 12,
794 /* ARM instructions take 4bytes in the object file, Thumb instructions
798 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
799 #define MAV_MODE1 0x100c
801 /* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
802 #define MAV_MODE2 0x0c10
804 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
805 #define MAV_MODE3 0x100c
807 /* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
808 #define MAV_MODE4 0x0c0010
810 /* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
811 #define MAV_MODE5 0x00100c
813 /* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
814 #define MAV_MODE6 0x00100c05
818 /* Basic string to match. */
819 const char * template;
821 /* Basic instruction code. */
824 /* Offset into the template where the condition code (if any) will be.
825 If zero, then the instruction is never conditional. */
826 unsigned cond_offset
;
828 /* Which architecture variant provides this instruction. */
829 unsigned long variant
;
831 /* Function to call to parse args. */
832 void (* parms
) (char *);
835 /* Defines for various bits that we will want to toggle. */
836 #define INST_IMMEDIATE 0x02000000
837 #define OFFSET_REG 0x02000000
838 #define HWOFFSET_IMM 0x00400000
839 #define SHIFT_BY_REG 0x00000010
840 #define PRE_INDEX 0x01000000
841 #define INDEX_UP 0x00800000
842 #define WRITE_BACK 0x00200000
843 #define LDM_TYPE_2_OR_3 0x00400000
845 #define LITERAL_MASK 0xf000f000
846 #define OPCODE_MASK 0xfe1fffff
847 #define V4_STR_BIT 0x00000020
849 #define DATA_OP_SHIFT 21
851 /* Codes to distinguish the arithmetic instructions. */
862 #define OPCODE_CMP 10
863 #define OPCODE_CMN 11
864 #define OPCODE_ORR 12
865 #define OPCODE_MOV 13
866 #define OPCODE_BIC 14
867 #define OPCODE_MVN 15
869 #define T_OPCODE_MUL 0x4340
870 #define T_OPCODE_TST 0x4200
871 #define T_OPCODE_CMN 0x42c0
872 #define T_OPCODE_NEG 0x4240
873 #define T_OPCODE_MVN 0x43c0
875 #define T_OPCODE_ADD_R3 0x1800
876 #define T_OPCODE_SUB_R3 0x1a00
877 #define T_OPCODE_ADD_HI 0x4400
878 #define T_OPCODE_ADD_ST 0xb000
879 #define T_OPCODE_SUB_ST 0xb080
880 #define T_OPCODE_ADD_SP 0xa800
881 #define T_OPCODE_ADD_PC 0xa000
882 #define T_OPCODE_ADD_I8 0x3000
883 #define T_OPCODE_SUB_I8 0x3800
884 #define T_OPCODE_ADD_I3 0x1c00
885 #define T_OPCODE_SUB_I3 0x1e00
887 #define T_OPCODE_ASR_R 0x4100
888 #define T_OPCODE_LSL_R 0x4080
889 #define T_OPCODE_LSR_R 0x40c0
890 #define T_OPCODE_ASR_I 0x1000
891 #define T_OPCODE_LSL_I 0x0000
892 #define T_OPCODE_LSR_I 0x0800
894 #define T_OPCODE_MOV_I8 0x2000
895 #define T_OPCODE_CMP_I8 0x2800
896 #define T_OPCODE_CMP_LR 0x4280
897 #define T_OPCODE_MOV_HR 0x4600
898 #define T_OPCODE_CMP_HR 0x4500
900 #define T_OPCODE_LDR_PC 0x4800
901 #define T_OPCODE_LDR_SP 0x9800
902 #define T_OPCODE_STR_SP 0x9000
903 #define T_OPCODE_LDR_IW 0x6800
904 #define T_OPCODE_STR_IW 0x6000
905 #define T_OPCODE_LDR_IH 0x8800
906 #define T_OPCODE_STR_IH 0x8000
907 #define T_OPCODE_LDR_IB 0x7800
908 #define T_OPCODE_STR_IB 0x7000
909 #define T_OPCODE_LDR_RW 0x5800
910 #define T_OPCODE_STR_RW 0x5000
911 #define T_OPCODE_LDR_RH 0x5a00
912 #define T_OPCODE_STR_RH 0x5200
913 #define T_OPCODE_LDR_RB 0x5c00
914 #define T_OPCODE_STR_RB 0x5400
916 #define T_OPCODE_PUSH 0xb400
917 #define T_OPCODE_POP 0xbc00
919 #define T_OPCODE_BRANCH 0xe7fe
921 #define THUMB_SIZE 2 /* Size of thumb instruction. */
922 #define THUMB_REG_LO 0x1
923 #define THUMB_REG_HI 0x2
924 #define THUMB_REG_ANY 0x3
926 #define THUMB_H1 0x0080
927 #define THUMB_H2 0x0040
934 #define THUMB_COMPARE 1
938 #define THUMB_STORE 1
940 #define THUMB_PP_PC_LR 0x0100
942 /* These three are used for immediate shifts, do not alter. */
944 #define THUMB_HALFWORD 1
949 /* Basic string to match. */
950 const char * template;
952 /* Basic instruction code. */
957 /* Which CPU variants this exists for. */
958 unsigned long variant
;
960 /* Function to call to parse args. */
961 void (* parms
) (char *);
964 #define BAD_ARGS _("bad arguments to instruction")
965 #define BAD_PC _("r15 not allowed here")
966 #define BAD_COND _("instruction is not conditional")
967 #define ERR_NO_ACCUM _("acc0 expected")
969 static struct hash_control
* arm_ops_hsh
= NULL
;
970 static struct hash_control
* arm_tops_hsh
= NULL
;
971 static struct hash_control
* arm_cond_hsh
= NULL
;
972 static struct hash_control
* arm_shift_hsh
= NULL
;
973 static struct hash_control
* arm_psr_hsh
= NULL
;
975 /* Stuff needed to resolve the label ambiguity
985 symbolS
* last_label_seen
;
986 static int label_is_thumb_function_name
= FALSE
;
988 /* Literal Pool stuff. */
990 #define MAX_LITERAL_POOL_SIZE 1024
992 /* Literal pool structure. Held on a per-section
993 and per-sub-section basis. */
995 typedef struct literal_pool
997 expressionS literals
[MAX_LITERAL_POOL_SIZE
];
998 unsigned int next_free_entry
;
1002 subsegT sub_section
;
1003 struct literal_pool
* next
;
1006 /* Pointer to a linked list of literal pools. */
1007 literal_pool
* list_of_pools
= NULL
;
1009 static literal_pool
*
1010 find_literal_pool (void)
1012 literal_pool
* pool
;
1014 for (pool
= list_of_pools
; pool
!= NULL
; pool
= pool
->next
)
1016 if (pool
->section
== now_seg
1017 && pool
->sub_section
== now_subseg
)
1024 static literal_pool
*
1025 find_or_make_literal_pool (void)
1027 /* Next literal pool ID number. */
1028 static unsigned int latest_pool_num
= 1;
1029 literal_pool
* pool
;
1031 pool
= find_literal_pool ();
1035 /* Create a new pool. */
1036 pool
= xmalloc (sizeof (* pool
));
1040 pool
->next_free_entry
= 0;
1041 pool
->section
= now_seg
;
1042 pool
->sub_section
= now_subseg
;
1043 pool
->next
= list_of_pools
;
1044 pool
->symbol
= NULL
;
1046 /* Add it to the list. */
1047 list_of_pools
= pool
;
1050 /* New pools, and emptied pools, will have a NULL symbol. */
1051 if (pool
->symbol
== NULL
)
1053 pool
->symbol
= symbol_create (FAKE_LABEL_NAME
, undefined_section
,
1054 (valueT
) 0, &zero_address_frag
);
1055 pool
->id
= latest_pool_num
++;
1062 /* Add the literal in the global 'inst'
1063 structure to the relevent literal pool. */
1066 add_to_lit_pool (void)
1068 literal_pool
* pool
;
1071 pool
= find_or_make_literal_pool ();
1073 /* Check if this literal value is already in the pool. */
1074 for (entry
= 0; entry
< pool
->next_free_entry
; entry
++)
1076 if ((pool
->literals
[entry
].X_op
== inst
.reloc
.exp
.X_op
)
1077 && (inst
.reloc
.exp
.X_op
== O_constant
)
1078 && (pool
->literals
[entry
].X_add_number
1079 == inst
.reloc
.exp
.X_add_number
)
1080 && (pool
->literals
[entry
].X_unsigned
1081 == inst
.reloc
.exp
.X_unsigned
))
1084 if ((pool
->literals
[entry
].X_op
== inst
.reloc
.exp
.X_op
)
1085 && (inst
.reloc
.exp
.X_op
== O_symbol
)
1086 && (pool
->literals
[entry
].X_add_number
1087 == inst
.reloc
.exp
.X_add_number
)
1088 && (pool
->literals
[entry
].X_add_symbol
1089 == inst
.reloc
.exp
.X_add_symbol
)
1090 && (pool
->literals
[entry
].X_op_symbol
1091 == inst
.reloc
.exp
.X_op_symbol
))
1095 /* Do we need to create a new entry? */
1096 if (entry
== pool
->next_free_entry
)
1098 if (entry
>= MAX_LITERAL_POOL_SIZE
)
1100 inst
.error
= _("literal pool overflow");
1104 pool
->literals
[entry
] = inst
.reloc
.exp
;
1105 pool
->next_free_entry
+= 1;
1108 inst
.reloc
.exp
.X_op
= O_symbol
;
1109 inst
.reloc
.exp
.X_add_number
= ((int) entry
) * 4 - 8;
1110 inst
.reloc
.exp
.X_add_symbol
= pool
->symbol
;
1115 /* Can't use symbol_new here, so have to create a symbol and then at
1116 a later date assign it a value. Thats what these functions do. */
1119 symbol_locate (symbolS
* symbolP
,
1120 const char * name
, /* It is copied, the caller can modify. */
1121 segT segment
, /* Segment identifier (SEG_<something>). */
1122 valueT valu
, /* Symbol value. */
1123 fragS
* frag
) /* Associated fragment. */
1125 unsigned int name_length
;
1126 char * preserved_copy_of_name
;
1128 name_length
= strlen (name
) + 1; /* +1 for \0. */
1129 obstack_grow (¬es
, name
, name_length
);
1130 preserved_copy_of_name
= obstack_finish (¬es
);
1131 #ifdef STRIP_UNDERSCORE
1132 if (preserved_copy_of_name
[0] == '_')
1133 preserved_copy_of_name
++;
1136 #ifdef tc_canonicalize_symbol_name
1137 preserved_copy_of_name
=
1138 tc_canonicalize_symbol_name (preserved_copy_of_name
);
1141 S_SET_NAME (symbolP
, preserved_copy_of_name
);
1143 S_SET_SEGMENT (symbolP
, segment
);
1144 S_SET_VALUE (symbolP
, valu
);
1145 symbol_clear_list_pointers (symbolP
);
1147 symbol_set_frag (symbolP
, frag
);
1149 /* Link to end of symbol chain. */
1151 extern int symbol_table_frozen
;
1153 if (symbol_table_frozen
)
1157 symbol_append (symbolP
, symbol_lastP
, & symbol_rootP
, & symbol_lastP
);
1159 obj_symbol_new_hook (symbolP
);
1161 #ifdef tc_symbol_new_hook
1162 tc_symbol_new_hook (symbolP
);
1166 verify_symbol_chain (symbol_rootP
, symbol_lastP
);
1167 #endif /* DEBUG_SYMS */
1170 /* Check that an immediate is valid.
1171 If so, convert it to the right format. */
1174 validate_immediate (unsigned int val
)
1179 #define rotate_left(v, n) (v << n | v >> (32 - n))
1181 for (i
= 0; i
< 32; i
+= 2)
1182 if ((a
= rotate_left (val
, i
)) <= 0xff)
1183 return a
| (i
<< 7); /* 12-bit pack: [shift-cnt,const]. */
1188 /* Check to see if an immediate can be computed as two separate immediate
1189 values, added together. We already know that this value cannot be
1190 computed by just one ARM instruction. */
1193 validate_immediate_twopart (unsigned int val
,
1194 unsigned int * highpart
)
1199 for (i
= 0; i
< 32; i
+= 2)
1200 if (((a
= rotate_left (val
, i
)) & 0xff) != 0)
1206 * highpart
= (a
>> 8) | ((i
+ 24) << 7);
1208 else if (a
& 0xff0000)
1212 * highpart
= (a
>> 16) | ((i
+ 16) << 7);
1216 assert (a
& 0xff000000);
1217 * highpart
= (a
>> 24) | ((i
+ 8) << 7);
1220 return (a
& 0xff) | (i
<< 7);
1227 validate_offset_imm (unsigned int val
, int hwse
)
1229 if ((hwse
&& val
> 255) || val
> 4095)
1236 /* This code is to handle mapping symbols as defined in the ARM ELF spec.
1237 (This text is taken from version B-02 of the spec):
1239 4.4.7 Mapping and tagging symbols
1241 A section of an ARM ELF file can contain a mixture of ARM code,
1242 Thumb code, and data. There are inline transitions between code
1243 and data at literal pool boundaries. There can also be inline
1244 transitions between ARM code and Thumb code, for example in
1245 ARM-Thumb inter-working veneers. Linkers, machine-level
1246 debuggers, profiling tools, and disassembly tools need to map
1247 images accurately. For example, setting an ARM breakpoint on a
1248 Thumb location, or in a literal pool, can crash the program
1249 being debugged, ruining the debugging session.
1251 ARM ELF entities are mapped (see section 4.4.7.1 below) and
1252 tagged (see section 4.4.7.2 below) using local symbols (with
1253 binding STB_LOCAL). To assist consumers, mapping and tagging
1254 symbols should be collated first in the symbol table, before
1255 other symbols with binding STB_LOCAL.
1257 To allow properly collated mapping and tagging symbols to be
1258 skipped by consumers that have no interest in them, the first
1259 such symbol should have the name $m and its st_value field equal
1260 to the total number of mapping and tagging symbols (including
1261 the $m) in the symbol table.
1263 4.4.7.1 Mapping symbols
1265 $a Labels the first byte of a sequence of ARM instructions.
1266 Its type is STT_FUNC.
1268 $d Labels the first byte of a sequence of data items.
1269 Its type is STT_OBJECT.
1271 $t Labels the first byte of a sequence of Thumb instructions.
1272 Its type is STT_FUNC.
1274 This list of mapping symbols may be extended in the future.
1276 Section-relative mapping symbols
1278 Mapping symbols defined in a section define a sequence of
1279 half-open address intervals that cover the address range of the
1280 section. Each interval starts at the address defined by a
1281 mapping symbol, and continues up to, but not including, the
1282 address defined by the next (in address order) mapping symbol or
1283 the end of the section. A corollary is that there must be a
1284 mapping symbol defined at the beginning of each section.
1285 Consumers can ignore the size of a section-relative mapping
1286 symbol. Producers can set it to 0.
1288 Absolute mapping symbols
1290 Because of the need to crystallize a Thumb address with the
1291 Thumb-bit set, absolute symbol of type STT_FUNC (symbols of type
1292 STT_FUNC defined in section SHN_ABS) need to be mapped with $a
1295 The extent of a mapping symbol defined in SHN_ABS is [st_value,
1296 st_value + st_size), or [st_value, st_value + 1) if st_size = 0,
1297 where [x, y) denotes the half-open address range from x,
1298 inclusive, to y, exclusive.
1300 In the absence of a mapping symbol, a consumer can interpret a
1301 function symbol with an odd value as the Thumb code address
1302 obtained by clearing the least significant bit of the
1303 value. This interpretation is deprecated, and it may not work in
1306 Note - the Tagging symbols ($b, $f, $p $m) have been dropped from
1307 the EABI (which is still under development), so they are not
1308 implemented here. */
1310 static enum mstate mapstate
= MAP_UNDEFINED
;
1313 mapping_state (enum mstate state
)
1316 const char * symname
;
1319 if (mapstate
== state
)
1320 /* The mapping symbol has already been emitted.
1321 There is nothing else to do. */
1334 type
= BSF_FUNCTION
;
1338 type
= BSF_FUNCTION
;
1346 seg_info (now_seg
)->tc_segment_info_data
= state
;
1348 symbolP
= symbol_new (symname
, now_seg
, (valueT
) frag_now_fix (), frag_now
);
1349 symbol_table_insert (symbolP
);
1350 symbol_get_bfdsym (symbolP
)->flags
|= type
| BSF_LOCAL
;
1355 THUMB_SET_FUNC (symbolP
, 0);
1356 ARM_SET_THUMB (symbolP
, 0);
1357 ARM_SET_INTERWORK (symbolP
, support_interwork
);
1361 THUMB_SET_FUNC (symbolP
, 1);
1362 ARM_SET_THUMB (symbolP
, 1);
1363 ARM_SET_INTERWORK (symbolP
, support_interwork
);
1372 /* When we change sections we need to issue a new mapping symbol. */
1375 arm_elf_change_section (void)
1379 /* Link an unlinked unwind index table section to the .text section. */
1380 if (elf_section_type (now_seg
) == SHT_ARM_EXIDX
1381 && elf_linked_to_section (now_seg
) == NULL
)
1382 elf_linked_to_section (now_seg
) = text_section
;
1384 if (!SEG_NORMAL (now_seg
))
1387 flags
= bfd_get_section_flags (stdoutput
, now_seg
);
1389 /* We can ignore sections that only contain debug info. */
1390 if ((flags
& SEC_ALLOC
) == 0)
1393 mapstate
= seg_info (now_seg
)->tc_segment_info_data
;
1397 arm_elf_section_type (const char * str
, size_t len
)
1399 if (len
== 5 && strncmp (str
, "exidx", 5) == 0)
1400 return SHT_ARM_EXIDX
;
1405 #define mapping_state(a)
1406 #endif /* OBJ_ELF */
1408 /* arm_reg_parse () := if it looks like a register, return its token and
1409 advance the pointer. */
1412 arm_reg_parse (char ** ccp
, struct hash_control
* htab
)
1414 char * start
= * ccp
;
1417 struct reg_entry
* reg
;
1419 #ifdef REGISTER_PREFIX
1420 if (*start
!= REGISTER_PREFIX
)
1425 #ifdef OPTIONAL_REGISTER_PREFIX
1426 if (*p
== OPTIONAL_REGISTER_PREFIX
)
1430 if (!ISALPHA (*p
) || !is_name_beginner (*p
))
1434 while (ISALPHA (c
) || ISDIGIT (c
) || c
== '_')
1438 reg
= (struct reg_entry
*) hash_find (htab
, start
);
1450 /* Search for the following register name in each of the possible reg name
1451 tables. Return the classification if found, or REG_TYPE_MAX if not
1454 static enum arm_reg_type
1455 arm_reg_parse_any (char *cp
)
1459 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
1460 if (arm_reg_parse (&cp
, all_reg_maps
[i
].htab
) != FAIL
)
1461 return (enum arm_reg_type
) i
;
1463 return REG_TYPE_MAX
;
1467 opcode_select (int width
)
1474 if (! (cpu_variant
& ARM_EXT_V4T
))
1475 as_bad (_("selected processor does not support THUMB opcodes"));
1478 /* No need to force the alignment, since we will have been
1479 coming from ARM mode, which is word-aligned. */
1480 record_alignment (now_seg
, 1);
1482 mapping_state (MAP_THUMB
);
1488 if ((cpu_variant
& ARM_ALL
) == ARM_EXT_V4T
)
1489 as_bad (_("selected processor does not support ARM opcodes"));
1494 frag_align (2, 0, 0);
1496 record_alignment (now_seg
, 1);
1498 mapping_state (MAP_ARM
);
1502 as_bad (_("invalid instruction size selected (%d)"), width
);
1507 s_req (int a ATTRIBUTE_UNUSED
)
1509 as_bad (_("invalid syntax for .req directive"));
1512 /* The .unreq directive deletes an alias which was previously defined
1513 by .req. For example:
1519 s_unreq (int a ATTRIBUTE_UNUSED
)
1524 skip_whitespace (input_line_pointer
);
1525 name
= input_line_pointer
;
1527 while (*input_line_pointer
!= 0
1528 && *input_line_pointer
!= ' '
1529 && *input_line_pointer
!= '\n')
1530 ++input_line_pointer
;
1532 saved_char
= *input_line_pointer
;
1533 *input_line_pointer
= 0;
1537 enum arm_reg_type req_type
= arm_reg_parse_any (name
);
1539 if (req_type
!= REG_TYPE_MAX
)
1541 char *temp_name
= name
;
1542 int req_no
= arm_reg_parse (&temp_name
, all_reg_maps
[req_type
].htab
);
1546 struct reg_entry
*req_entry
;
1548 /* Check to see if this alias is a builtin one. */
1549 req_entry
= hash_delete (all_reg_maps
[req_type
].htab
, name
);
1552 as_bad (_("unreq: missing hash entry for \"%s\""), name
);
1553 else if (req_entry
->builtin
)
1554 /* FIXME: We are deleting a built in register alias which
1555 points to a const data structure, so we only need to
1556 free up the memory used by the key in the hash table.
1557 Unfortunately we have not recorded this value, so this
1558 is a memory leak. */
1559 /* FIXME: Should we issue a warning message ? */
1563 /* Deleting a user defined alias. We need to free the
1564 key and the value, but fortunately the key is the same
1565 as the value->name field. */
1566 free ((char *) req_entry
->name
);
1571 as_bad (_(".unreq: unrecognized symbol \"%s\""), name
);
1574 as_bad (_(".unreq: unrecognized symbol \"%s\""), name
);
1577 as_bad (_("invalid syntax for .unreq directive"));
1579 *input_line_pointer
= saved_char
;
1580 demand_empty_rest_of_line ();
1584 s_bss (int ignore ATTRIBUTE_UNUSED
)
1586 /* We don't support putting frags in the BSS segment, we fake it by
1587 marking in_bss, then looking at s_skip for clues. */
1588 subseg_set (bss_section
, 0);
1589 demand_empty_rest_of_line ();
1590 mapping_state (MAP_DATA
);
1594 s_even (int ignore ATTRIBUTE_UNUSED
)
1596 /* Never make frag if expect extra pass. */
1598 frag_align (1, 0, 0);
1600 record_alignment (now_seg
, 1);
1602 demand_empty_rest_of_line ();
1606 s_ltorg (int ignored ATTRIBUTE_UNUSED
)
1609 literal_pool
* pool
;
1612 pool
= find_literal_pool ();
1614 || pool
->symbol
== NULL
1615 || pool
->next_free_entry
== 0)
1618 mapping_state (MAP_DATA
);
1620 /* Align pool as you have word accesses.
1621 Only make a frag if we have to. */
1623 frag_align (2, 0, 0);
1625 record_alignment (now_seg
, 2);
1627 sprintf (sym_name
, "$$lit_\002%x", pool
->id
);
1629 symbol_locate (pool
->symbol
, sym_name
, now_seg
,
1630 (valueT
) frag_now_fix (), frag_now
);
1631 symbol_table_insert (pool
->symbol
);
1633 ARM_SET_THUMB (pool
->symbol
, thumb_mode
);
1635 #if defined OBJ_COFF || defined OBJ_ELF
1636 ARM_SET_INTERWORK (pool
->symbol
, support_interwork
);
1639 for (entry
= 0; entry
< pool
->next_free_entry
; entry
++)
1640 /* First output the expression in the instruction to the pool. */
1641 emit_expr (&(pool
->literals
[entry
]), 4); /* .word */
1643 /* Mark the pool as empty. */
1644 pool
->next_free_entry
= 0;
1645 pool
->symbol
= NULL
;
1648 /* Same as s_align_ptwo but align 0 => align 2. */
1651 s_align (int unused ATTRIBUTE_UNUSED
)
1655 long max_alignment
= 15;
1657 temp
= get_absolute_expression ();
1658 if (temp
> max_alignment
)
1659 as_bad (_("alignment too large: %d assumed"), temp
= max_alignment
);
1662 as_bad (_("alignment negative. 0 assumed."));
1666 if (*input_line_pointer
== ',')
1668 input_line_pointer
++;
1669 temp_fill
= get_absolute_expression ();
1677 /* Only make a frag if we HAVE to. */
1678 if (temp
&& !need_pass_2
)
1679 frag_align (temp
, (int) temp_fill
, 0);
1680 demand_empty_rest_of_line ();
1682 record_alignment (now_seg
, temp
);
1686 s_force_thumb (int ignore ATTRIBUTE_UNUSED
)
1688 /* If we are not already in thumb mode go into it, EVEN if
1689 the target processor does not support thumb instructions.
1690 This is used by gcc/config/arm/lib1funcs.asm for example
1691 to compile interworking support functions even if the
1692 target processor should not support interworking. */
1697 record_alignment (now_seg
, 1);
1700 demand_empty_rest_of_line ();
1704 s_thumb_func (int ignore ATTRIBUTE_UNUSED
)
1709 /* The following label is the name/address of the start of a Thumb function.
1710 We need to know this for the interworking support. */
1711 label_is_thumb_function_name
= TRUE
;
1713 demand_empty_rest_of_line ();
1716 /* Perform a .set directive, but also mark the alias as
1717 being a thumb function. */
1720 s_thumb_set (int equiv
)
1722 /* XXX the following is a duplicate of the code for s_set() in read.c
1723 We cannot just call that code as we need to get at the symbol that
1730 /* Especial apologies for the random logic:
1731 This just grew, and could be parsed much more simply!
1733 name
= input_line_pointer
;
1734 delim
= get_symbol_end ();
1735 end_name
= input_line_pointer
;
1740 if (*input_line_pointer
!= ',')
1743 as_bad (_("expected comma after name \"%s\""), name
);
1745 ignore_rest_of_line ();
1749 input_line_pointer
++;
1752 if (name
[0] == '.' && name
[1] == '\0')
1754 /* XXX - this should not happen to .thumb_set. */
1758 if ((symbolP
= symbol_find (name
)) == NULL
1759 && (symbolP
= md_undefined_symbol (name
)) == NULL
)
1762 /* When doing symbol listings, play games with dummy fragments living
1763 outside the normal fragment chain to record the file and line info
1765 if (listing
& LISTING_SYMBOLS
)
1767 extern struct list_info_struct
* listing_tail
;
1768 fragS
* dummy_frag
= xmalloc (sizeof (fragS
));
1770 memset (dummy_frag
, 0, sizeof (fragS
));
1771 dummy_frag
->fr_type
= rs_fill
;
1772 dummy_frag
->line
= listing_tail
;
1773 symbolP
= symbol_new (name
, undefined_section
, 0, dummy_frag
);
1774 dummy_frag
->fr_symbol
= symbolP
;
1778 symbolP
= symbol_new (name
, undefined_section
, 0, &zero_address_frag
);
1781 /* "set" symbols are local unless otherwise specified. */
1782 SF_SET_LOCAL (symbolP
);
1783 #endif /* OBJ_COFF */
1784 } /* Make a new symbol. */
1786 symbol_table_insert (symbolP
);
1791 && S_IS_DEFINED (symbolP
)
1792 && S_GET_SEGMENT (symbolP
) != reg_section
)
1793 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP
));
1795 pseudo_set (symbolP
);
1797 demand_empty_rest_of_line ();
1799 /* XXX Now we come to the Thumb specific bit of code. */
1801 THUMB_SET_FUNC (symbolP
, 1);
1802 ARM_SET_THUMB (symbolP
, 1);
1803 #if defined OBJ_ELF || defined OBJ_COFF
1804 ARM_SET_INTERWORK (symbolP
, support_interwork
);
1809 s_arm (int ignore ATTRIBUTE_UNUSED
)
1812 demand_empty_rest_of_line ();
1816 s_thumb (int ignore ATTRIBUTE_UNUSED
)
1819 demand_empty_rest_of_line ();
1823 s_code (int unused ATTRIBUTE_UNUSED
)
1827 temp
= get_absolute_expression ();
1832 opcode_select (temp
);
1836 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp
);
1841 end_of_line (char * str
)
1843 skip_whitespace (str
);
1845 if (*str
!= '\0' && !inst
.error
)
1846 inst
.error
= _("garbage following instruction");
1850 skip_past_comma (char ** str
)
1852 char * p
= * str
, c
;
1855 while ((c
= *p
) == ' ' || c
== ',')
1858 if (c
== ',' && comma
++)
1866 return comma
? SUCCESS
: FAIL
;
1869 /* Return TRUE if anything in the expression is a bignum. */
1872 walk_no_bignums (symbolS
* sp
)
1874 if (symbol_get_value_expression (sp
)->X_op
== O_big
)
1877 if (symbol_get_value_expression (sp
)->X_add_symbol
)
1879 return (walk_no_bignums (symbol_get_value_expression (sp
)->X_add_symbol
)
1880 || (symbol_get_value_expression (sp
)->X_op_symbol
1881 && walk_no_bignums (symbol_get_value_expression (sp
)->X_op_symbol
)));
1887 static int in_my_get_expression
= 0;
1890 my_get_expression (expressionS
* ep
, char ** str
)
1895 save_in
= input_line_pointer
;
1896 input_line_pointer
= *str
;
1897 in_my_get_expression
= 1;
1898 seg
= expression (ep
);
1899 in_my_get_expression
= 0;
1901 if (ep
->X_op
== O_illegal
)
1903 /* We found a bad expression in md_operand(). */
1904 *str
= input_line_pointer
;
1905 input_line_pointer
= save_in
;
1910 if (seg
!= absolute_section
1911 && seg
!= text_section
1912 && seg
!= data_section
1913 && seg
!= bss_section
1914 && seg
!= undefined_section
)
1916 inst
.error
= _("bad_segment");
1917 *str
= input_line_pointer
;
1918 input_line_pointer
= save_in
;
1923 /* Get rid of any bignums now, so that we don't generate an error for which
1924 we can't establish a line number later on. Big numbers are never valid
1925 in instructions, which is where this routine is always called. */
1926 if (ep
->X_op
== O_big
1927 || (ep
->X_add_symbol
1928 && (walk_no_bignums (ep
->X_add_symbol
)
1930 && walk_no_bignums (ep
->X_op_symbol
)))))
1932 inst
.error
= _("invalid constant");
1933 *str
= input_line_pointer
;
1934 input_line_pointer
= save_in
;
1938 *str
= input_line_pointer
;
1939 input_line_pointer
= save_in
;
1943 /* A standard register must be given at this point.
1944 SHIFT is the place to put it in inst.instruction.
1945 Restores input start point on error.
1946 Returns the reg#, or FAIL. */
1949 reg_required_here (char ** str
, int shift
)
1951 static char buff
[128]; /* XXX */
1953 char * start
= * str
;
1955 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_RN
].htab
)) != FAIL
)
1958 inst
.instruction
|= reg
<< shift
;
1962 /* Restore the start point, we may have got a reg of the wrong class. */
1965 /* In the few cases where we might be able to accept something else
1966 this error can be overridden. */
1967 sprintf (buff
, _("register expected, not '%.100s'"), start
);
1973 /* A Intel Wireless MMX technology register
1974 must be given at this point.
1975 Shift is the place to put it in inst.instruction.
1976 Restores input start point on err.
1977 Returns the reg#, or FAIL. */
1980 wreg_required_here (char ** str
,
1982 enum wreg_type reg_type
)
1984 static char buff
[128];
1986 char * start
= *str
;
1988 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_IWMMXT
].htab
)) != FAIL
)
1990 if (wr_register (reg
)
1991 && (reg_type
== IWMMXT_REG_WR
|| reg_type
== IWMMXT_REG_WR_OR_WC
))
1994 inst
.instruction
|= (reg
^ WR_PREFIX
) << shift
;
1997 else if (wc_register (reg
)
1998 && (reg_type
== IWMMXT_REG_WC
|| reg_type
== IWMMXT_REG_WR_OR_WC
))
2001 inst
.instruction
|= (reg
^ WC_PREFIX
) << shift
;
2004 else if ((wcg_register (reg
) && reg_type
== IWMMXT_REG_WCG
))
2007 inst
.instruction
|= ((reg
^ WC_PREFIX
) - 8) << shift
;
2012 /* Restore the start point, we may have got a reg of the wrong class. */
2015 /* In the few cases where we might be able to accept
2016 something else this error can be overridden. */
2017 sprintf (buff
, _("Intel Wireless MMX technology register expected, not '%.100s'"), start
);
2023 static const struct asm_psr
*
2024 arm_psr_parse (char ** ccp
)
2026 char * start
= * ccp
;
2029 const struct asm_psr
* psr
;
2033 /* Skip to the end of the next word in the input stream. */
2038 while (ISALPHA (c
) || c
== '_');
2040 /* Terminate the word. */
2043 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
2044 feature for ease of use and backwards compatibility. */
2045 if (!strncmp (start
, "cpsr", 4))
2046 strncpy (start
, "CPSR", 4);
2047 else if (!strncmp (start
, "spsr", 4))
2048 strncpy (start
, "SPSR", 4);
2050 /* Now locate the word in the psr hash table. */
2051 psr
= (const struct asm_psr
*) hash_find (arm_psr_hsh
, start
);
2053 /* Restore the input stream. */
2056 /* If we found a valid match, advance the
2057 stream pointer past the end of the word. */
2063 /* Parse the input looking for a PSR flag. */
2066 psr_required_here (char ** str
)
2068 char * start
= * str
;
2069 const struct asm_psr
* psr
;
2071 psr
= arm_psr_parse (str
);
2075 /* If this is the SPSR that is being modified, set the R bit. */
2077 inst
.instruction
|= SPSR_BIT
;
2079 /* Set the psr flags in the MSR instruction. */
2080 inst
.instruction
|= psr
->field
<< PSR_SHIFT
;
2085 /* In the few cases where we might be able to accept
2086 something else this error can be overridden. */
2087 inst
.error
= _("flag for {c}psr instruction expected");
2089 /* Restore the start point. */
2095 co_proc_number (char ** str
)
2097 int processor
, pchar
;
2100 skip_whitespace (*str
);
2103 /* The data sheet seems to imply that just a number on its own is valid
2104 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
2106 if ((processor
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CP
].htab
))
2112 if (pchar
>= '0' && pchar
<= '9')
2114 processor
= pchar
- '0';
2115 if (**str
>= '0' && **str
<= '9')
2117 processor
= processor
* 10 + *(*str
)++ - '0';
2120 inst
.error
= _("illegal co-processor number");
2127 inst
.error
= all_reg_maps
[REG_TYPE_CP
].expected
;
2132 inst
.instruction
|= processor
<< 8;
2137 cp_opc_expr (char ** str
, int where
, int length
)
2141 skip_whitespace (* str
);
2143 memset (&expr
, '\0', sizeof (expr
));
2145 if (my_get_expression (&expr
, str
))
2147 if (expr
.X_op
!= O_constant
)
2149 inst
.error
= _("bad or missing expression");
2153 if ((expr
.X_add_number
& ((1 << length
) - 1)) != expr
.X_add_number
)
2155 inst
.error
= _("immediate co-processor expression too large");
2159 inst
.instruction
|= expr
.X_add_number
<< where
;
2164 cp_reg_required_here (char ** str
, int where
)
2167 char * start
= *str
;
2169 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CN
].htab
)) != FAIL
)
2171 inst
.instruction
|= reg
<< where
;
2175 /* In the few cases where we might be able to accept something else
2176 this error can be overridden. */
2177 inst
.error
= all_reg_maps
[REG_TYPE_CN
].expected
;
2179 /* Restore the start point. */
2185 fp_reg_required_here (char ** str
, int where
)
2188 char * start
= * str
;
2190 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_FN
].htab
)) != FAIL
)
2192 inst
.instruction
|= reg
<< where
;
2196 /* In the few cases where we might be able to accept something else
2197 this error can be overridden. */
2198 inst
.error
= all_reg_maps
[REG_TYPE_FN
].expected
;
2200 /* Restore the start point. */
2206 cp_address_offset (char ** str
)
2210 skip_whitespace (* str
);
2212 if (! is_immediate_prefix (**str
))
2214 inst
.error
= _("immediate expression expected");
2220 if (my_get_expression (& inst
.reloc
.exp
, str
))
2223 if (inst
.reloc
.exp
.X_op
== O_constant
)
2225 offset
= inst
.reloc
.exp
.X_add_number
;
2229 inst
.error
= _("co-processor address must be word aligned");
2233 if (offset
> 1023 || offset
< -1023)
2235 inst
.error
= _("offset too large");
2240 inst
.instruction
|= INDEX_UP
;
2244 inst
.instruction
|= offset
>> 2;
2247 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
2253 cp_address_required_here (char ** str
, int wb_ok
)
2264 skip_whitespace (p
);
2266 if ((reg
= reg_required_here (& p
, 16)) == FAIL
)
2269 skip_whitespace (p
);
2275 skip_whitespace (p
);
2279 /* As an extension to the official ARM syntax we allow:
2281 as a short hand for:
2283 inst
.instruction
|= PRE_INDEX
| INDEX_UP
;
2288 if (skip_past_comma (& p
) == FAIL
)
2290 inst
.error
= _("comma expected after closing square bracket");
2294 skip_whitespace (p
);
2301 write_back
= WRITE_BACK
;
2305 inst
.error
= _("pc may not be used in post-increment");
2309 if (cp_address_offset (& p
) == FAIL
)
2313 pre_inc
= PRE_INDEX
| INDEX_UP
;
2319 /* [Rn], {<expr>} */
2322 skip_whitespace (p
);
2324 if (my_get_expression (& inst
.reloc
.exp
, & p
))
2327 if (inst
.reloc
.exp
.X_op
== O_constant
)
2329 option
= inst
.reloc
.exp
.X_add_number
;
2331 if (option
> 255 || option
< 0)
2333 inst
.error
= _("'option' field too large");
2337 skip_whitespace (p
);
2341 inst
.error
= _("'}' expected at end of 'option' field");
2347 inst
.instruction
|= option
;
2348 inst
.instruction
|= INDEX_UP
;
2353 inst
.error
= _("non-constant expressions for 'option' field not supported");
2359 inst
.error
= _("# or { expected after comma");
2365 /* '['Rn, #expr']'[!] */
2367 if (skip_past_comma (& p
) == FAIL
)
2369 inst
.error
= _("pre-indexed expression expected");
2373 pre_inc
= PRE_INDEX
;
2375 if (cp_address_offset (& p
) == FAIL
)
2378 skip_whitespace (p
);
2382 inst
.error
= _("missing ]");
2386 skip_whitespace (p
);
2388 if (wb_ok
&& *p
== '!')
2392 inst
.error
= _("pc may not be used with write-back");
2397 write_back
= WRITE_BACK
;
2403 if (my_get_expression (&inst
.reloc
.exp
, &p
))
2406 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
2407 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
2408 inst
.reloc
.pc_rel
= 1;
2409 inst
.instruction
|= (REG_PC
<< 16);
2410 pre_inc
= PRE_INDEX
;
2413 inst
.instruction
|= write_back
| pre_inc
;
2419 cp_byte_address_offset (char ** str
)
2423 skip_whitespace (* str
);
2425 if (! is_immediate_prefix (**str
))
2427 inst
.error
= _("immediate expression expected");
2433 if (my_get_expression (& inst
.reloc
.exp
, str
))
2436 if (inst
.reloc
.exp
.X_op
== O_constant
)
2438 offset
= inst
.reloc
.exp
.X_add_number
;
2440 if (offset
> 255 || offset
< -255)
2442 inst
.error
= _("offset too large");
2447 inst
.instruction
|= INDEX_UP
;
2451 inst
.instruction
|= offset
;
2454 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM_S2
;
2460 cp_byte_address_required_here (char ** str
)
2471 skip_whitespace (p
);
2473 if ((reg
= reg_required_here (& p
, 16)) == FAIL
)
2476 skip_whitespace (p
);
2482 if (skip_past_comma (& p
) == SUCCESS
)
2485 write_back
= WRITE_BACK
;
2489 inst
.error
= _("pc may not be used in post-increment");
2493 if (cp_byte_address_offset (& p
) == FAIL
)
2497 pre_inc
= PRE_INDEX
| INDEX_UP
;
2501 /* '['Rn, #expr']'[!] */
2503 if (skip_past_comma (& p
) == FAIL
)
2505 inst
.error
= _("pre-indexed expression expected");
2509 pre_inc
= PRE_INDEX
;
2511 if (cp_byte_address_offset (& p
) == FAIL
)
2514 skip_whitespace (p
);
2518 inst
.error
= _("missing ]");
2522 skip_whitespace (p
);
2528 inst
.error
= _("pc may not be used with write-back");
2533 write_back
= WRITE_BACK
;
2539 if (my_get_expression (&inst
.reloc
.exp
, &p
))
2542 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM_S2
;
2543 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
2544 inst
.reloc
.pc_rel
= 1;
2545 inst
.instruction
|= (REG_PC
<< 16);
2546 pre_inc
= PRE_INDEX
;
2549 inst
.instruction
|= write_back
| pre_inc
;
2557 skip_whitespace (str
);
2562 if (my_get_expression (&inst
.reloc
.exp
, &str
))
2563 inst
.reloc
.exp
.X_op
= O_illegal
;
2566 skip_whitespace (str
);
2570 inst
.reloc
.exp
.X_op
= O_illegal
;
2573 if (inst
.reloc
.exp
.X_op
!= O_constant
2574 || inst
.reloc
.exp
.X_add_number
> 255
2575 || inst
.reloc
.exp
.X_add_number
< 0)
2577 inst
.error
= _("Invalid NOP hint");
2581 /* Arcitectural NOP hints are CPSR sets with no bits selected. */
2582 inst
.instruction
&= 0xf0000000;
2583 inst
.instruction
|= 0x0320f000 + inst
.reloc
.exp
.X_add_number
;
2590 do_empty (char * str
)
2592 /* Do nothing really. */
2601 /* Only one syntax. */
2602 skip_whitespace (str
);
2604 if (reg_required_here (&str
, 12) == FAIL
)
2606 inst
.error
= BAD_ARGS
;
2610 if (skip_past_comma (&str
) == FAIL
)
2612 inst
.error
= _("comma expected after register name");
2616 skip_whitespace (str
);
2618 if ( streq (str
, "CPSR")
2619 || streq (str
, "SPSR")
2620 /* Lower case versions for backwards compatibility. */
2621 || streq (str
, "cpsr")
2622 || streq (str
, "spsr"))
2625 /* This is for backwards compatibility with older toolchains. */
2626 else if ( streq (str
, "cpsr_all")
2627 || streq (str
, "spsr_all"))
2631 inst
.error
= _("CPSR or SPSR expected");
2635 if (* str
== 's' || * str
== 'S')
2636 inst
.instruction
|= SPSR_BIT
;
2642 /* Two possible forms:
2643 "{C|S}PSR_<field>, Rm",
2644 "{C|S}PSR_f, #expression". */
2649 skip_whitespace (str
);
2651 if (psr_required_here (& str
) == FAIL
)
2654 if (skip_past_comma (& str
) == FAIL
)
2656 inst
.error
= _("comma missing after psr flags");
2660 skip_whitespace (str
);
2662 if (reg_required_here (& str
, 0) != FAIL
)
2669 if (! is_immediate_prefix (* str
))
2672 _("only a register or immediate value can follow a psr flag");
2679 if (my_get_expression (& inst
.reloc
.exp
, & str
))
2682 _("only a register or immediate value can follow a psr flag");
2686 #if 0 /* The first edition of the ARM architecture manual stated that
2687 writing anything other than the flags with an immediate operation
2688 had UNPREDICTABLE effects. This constraint was removed in the
2689 second edition of the specification. */
2690 if ((cpu_variant
& ARM_EXT_V5
) != ARM_EXT_V5
2691 && inst
.instruction
& ((PSR_c
| PSR_x
| PSR_s
) << PSR_SHIFT
))
2693 inst
.error
= _("immediate value cannot be used to set this field");
2698 inst
.instruction
|= INST_IMMEDIATE
;
2700 if (inst
.reloc
.exp
.X_add_symbol
)
2702 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
2703 inst
.reloc
.pc_rel
= 0;
2707 unsigned value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
2709 if (value
== (unsigned) FAIL
)
2711 inst
.error
= _("invalid constant");
2715 inst
.instruction
|= value
;
2722 /* Long Multiply Parser
2723 UMULL RdLo, RdHi, Rm, Rs
2724 SMULL RdLo, RdHi, Rm, Rs
2725 UMLAL RdLo, RdHi, Rm, Rs
2726 SMLAL RdLo, RdHi, Rm, Rs. */
2729 do_mull (char * str
)
2731 int rdlo
, rdhi
, rm
, rs
;
2733 /* Only one format "rdlo, rdhi, rm, rs". */
2734 skip_whitespace (str
);
2736 if ((rdlo
= reg_required_here (&str
, 12)) == FAIL
)
2738 inst
.error
= BAD_ARGS
;
2742 if (skip_past_comma (&str
) == FAIL
2743 || (rdhi
= reg_required_here (&str
, 16)) == FAIL
)
2745 inst
.error
= BAD_ARGS
;
2749 if (skip_past_comma (&str
) == FAIL
2750 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
2752 inst
.error
= BAD_ARGS
;
2756 /* rdhi, rdlo and rm must all be different. */
2757 if (rdlo
== rdhi
|| rdlo
== rm
|| rdhi
== rm
)
2758 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
2760 if (skip_past_comma (&str
) == FAIL
2761 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
2763 inst
.error
= BAD_ARGS
;
2767 if (rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
)
2769 inst
.error
= BAD_PC
;
2781 /* Only one format "rd, rm, rs". */
2782 skip_whitespace (str
);
2784 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
2786 inst
.error
= BAD_ARGS
;
2792 inst
.error
= BAD_PC
;
2796 if (skip_past_comma (&str
) == FAIL
2797 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
2799 inst
.error
= BAD_ARGS
;
2805 inst
.error
= BAD_PC
;
2810 as_tsktsk (_("rd and rm should be different in mul"));
2812 if (skip_past_comma (&str
) == FAIL
2813 || (rm
= reg_required_here (&str
, 8)) == FAIL
)
2815 inst
.error
= BAD_ARGS
;
2821 inst
.error
= BAD_PC
;
2833 /* Only one format "rd, rm, rs, rn". */
2834 skip_whitespace (str
);
2836 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
2838 inst
.error
= BAD_ARGS
;
2844 inst
.error
= BAD_PC
;
2848 if (skip_past_comma (&str
) == FAIL
2849 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
2851 inst
.error
= BAD_ARGS
;
2857 inst
.error
= BAD_PC
;
2862 as_tsktsk (_("rd and rm should be different in mla"));
2864 if (skip_past_comma (&str
) == FAIL
2865 || (rd
= reg_required_here (&str
, 8)) == FAIL
2866 || skip_past_comma (&str
) == FAIL
2867 || (rm
= reg_required_here (&str
, 12)) == FAIL
)
2869 inst
.error
= BAD_ARGS
;
2873 if (rd
== REG_PC
|| rm
== REG_PC
)
2875 inst
.error
= BAD_PC
;
2882 /* Expects *str -> the characters "acc0", possibly with leading blanks.
2883 Advances *str to the next non-alphanumeric.
2884 Returns 0, or else FAIL (in which case sets inst.error).
2886 (In a future XScale, there may be accumulators other than zero.
2887 At that time this routine and its callers can be upgraded to suit.) */
2890 accum0_required_here (char ** str
)
2892 static char buff
[128]; /* Note the address is taken. Hence, static. */
2895 int result
= 0; /* The accum number. */
2897 skip_whitespace (p
);
2899 *str
= p
; /* Advance caller's string pointer too. */
2904 *--p
= 0; /* Aap nul into input buffer at non-alnum. */
2906 if (! ( streq (*str
, "acc0") || streq (*str
, "ACC0")))
2908 sprintf (buff
, _("acc0 expected, not '%.100s'"), *str
);
2913 *p
= c
; /* Unzap. */
2914 *str
= p
; /* Caller's string pointer to after match. */
2919 ldst_extend_v4 (char ** str
)
2928 if (my_get_expression (& inst
.reloc
.exp
, str
))
2931 if (inst
.reloc
.exp
.X_op
== O_constant
)
2933 int value
= inst
.reloc
.exp
.X_add_number
;
2935 if (value
< -255 || value
> 255)
2937 inst
.error
= _("address offset too large");
2947 /* Halfword and signextension instructions have the
2948 immediate value split across bits 11..8 and bits 3..0. */
2949 inst
.instruction
|= (add
| HWOFFSET_IMM
2950 | ((value
>> 4) << 8) | (value
& 0xF));
2954 inst
.instruction
|= HWOFFSET_IMM
;
2955 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
2956 inst
.reloc
.pc_rel
= 0;
2969 if (reg_required_here (str
, 0) == FAIL
)
2972 inst
.instruction
|= add
;
2977 /* Expects **str -> after a comma. May be leading blanks.
2978 Advances *str, recognizing a load mode, and setting inst.instruction.
2979 Returns rn, or else FAIL (in which case may set inst.error
2980 and not advance str)
2982 Note: doesn't know Rd, so no err checks that require such knowledge. */
2985 ld_mode_required_here (char ** string
)
2987 char * str
= * string
;
2991 skip_whitespace (str
);
2997 skip_whitespace (str
);
2999 if ((rn
= reg_required_here (& str
, 16)) == FAIL
)
3002 skip_whitespace (str
);
3008 if (skip_past_comma (& str
) == SUCCESS
)
3010 /* [Rn],... (post inc) */
3011 if (ldst_extend_v4 (&str
) == FAIL
)
3016 skip_whitespace (str
);
3021 inst
.instruction
|= WRITE_BACK
;
3024 inst
.instruction
|= INDEX_UP
| HWOFFSET_IMM
;
3030 if (skip_past_comma (& str
) == FAIL
)
3032 inst
.error
= _("pre-indexed expression expected");
3038 if (ldst_extend_v4 (&str
) == FAIL
)
3041 skip_whitespace (str
);
3043 if (* str
++ != ']')
3045 inst
.error
= _("missing ]");
3049 skip_whitespace (str
);
3054 inst
.instruction
|= WRITE_BACK
;
3058 else if (* str
== '=') /* ldr's "r,=label" syntax */
3059 /* We should never reach here, because <text> = <expression> is
3060 caught gas/read.c read_a_source_file() as a .set operation. */
3062 else /* PC +- 8 bit immediate offset. */
3064 if (my_get_expression (& inst
.reloc
.exp
, & str
))
3067 inst
.instruction
|= HWOFFSET_IMM
; /* The I bit. */
3068 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
3069 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
3070 inst
.reloc
.pc_rel
= 1;
3071 inst
.instruction
|= (REG_PC
<< 16);
3077 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
3083 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
3084 SMLAxy{cond} Rd,Rm,Rs,Rn
3085 SMLAWy{cond} Rd,Rm,Rs,Rn
3086 Error if any register is R15. */
3089 do_smla (char * str
)
3093 skip_whitespace (str
);
3095 if ((rd
= reg_required_here (& str
, 16)) == FAIL
3096 || skip_past_comma (& str
) == FAIL
3097 || (rm
= reg_required_here (& str
, 0)) == FAIL
3098 || skip_past_comma (& str
) == FAIL
3099 || (rs
= reg_required_here (& str
, 8)) == FAIL
3100 || skip_past_comma (& str
) == FAIL
3101 || (rn
= reg_required_here (& str
, 12)) == FAIL
)
3102 inst
.error
= BAD_ARGS
;
3104 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
|| rn
== REG_PC
)
3105 inst
.error
= BAD_PC
;
3111 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
3112 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
3113 Error if any register is R15.
3114 Warning if Rdlo == Rdhi. */
3117 do_smlal (char * str
)
3119 int rdlo
, rdhi
, rm
, rs
;
3121 skip_whitespace (str
);
3123 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
3124 || skip_past_comma (& str
) == FAIL
3125 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
3126 || skip_past_comma (& str
) == FAIL
3127 || (rm
= reg_required_here (& str
, 0)) == FAIL
3128 || skip_past_comma (& str
) == FAIL
3129 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
3131 inst
.error
= BAD_ARGS
;
3135 if (rdlo
== REG_PC
|| rdhi
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
3137 inst
.error
= BAD_PC
;
3142 as_tsktsk (_("rdhi and rdlo must be different"));
3147 /* ARM V5E (El Segundo) signed-multiply (argument parse)
3148 SMULxy{cond} Rd,Rm,Rs
3149 Error if any register is R15. */
3152 do_smul (char * str
)
3156 skip_whitespace (str
);
3158 if ((rd
= reg_required_here (& str
, 16)) == FAIL
3159 || skip_past_comma (& str
) == FAIL
3160 || (rm
= reg_required_here (& str
, 0)) == FAIL
3161 || skip_past_comma (& str
) == FAIL
3162 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
3163 inst
.error
= BAD_ARGS
;
3165 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
3166 inst
.error
= BAD_PC
;
3172 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
3173 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
3174 Error if any register is R15. */
3177 do_qadd (char * str
)
3181 skip_whitespace (str
);
3183 if ((rd
= reg_required_here (& str
, 12)) == FAIL
3184 || skip_past_comma (& str
) == FAIL
3185 || (rm
= reg_required_here (& str
, 0)) == FAIL
3186 || skip_past_comma (& str
) == FAIL
3187 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
3188 inst
.error
= BAD_ARGS
;
3190 else if (rd
== REG_PC
|| rm
== REG_PC
|| rn
== REG_PC
)
3191 inst
.error
= BAD_PC
;
3197 /* ARM V5E (el Segundo)
3198 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3199 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3201 These are equivalent to the XScale instructions MAR and MRA,
3202 respectively, when coproc == 0, opcode == 0, and CRm == 0.
3204 Result unpredicatable if Rd or Rn is R15. */
3207 do_co_reg2c (char * str
)
3211 skip_whitespace (str
);
3213 if (co_proc_number (& str
) == FAIL
)
3216 inst
.error
= BAD_ARGS
;
3220 if (skip_past_comma (& str
) == FAIL
3221 || cp_opc_expr (& str
, 4, 4) == FAIL
)
3224 inst
.error
= BAD_ARGS
;
3228 if (skip_past_comma (& str
) == FAIL
3229 || (rd
= reg_required_here (& str
, 12)) == FAIL
)
3232 inst
.error
= BAD_ARGS
;
3236 if (skip_past_comma (& str
) == FAIL
3237 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
3240 inst
.error
= BAD_ARGS
;
3244 /* Unpredictable result if rd or rn is R15. */
3245 if (rd
== REG_PC
|| rn
== REG_PC
)
3247 (_("Warning: instruction unpredictable when using r15"));
3249 if (skip_past_comma (& str
) == FAIL
3250 || cp_reg_required_here (& str
, 0) == FAIL
)
3253 inst
.error
= BAD_ARGS
;
3260 /* ARM V5 count-leading-zeroes instruction (argument parse)
3261 CLZ{<cond>} <Rd>, <Rm>
3262 Condition defaults to COND_ALWAYS.
3263 Error if Rd or Rm are R15. */
3270 skip_whitespace (str
);
3272 if (((rd
= reg_required_here (& str
, 12)) == FAIL
)
3273 || (skip_past_comma (& str
) == FAIL
)
3274 || ((rm
= reg_required_here (& str
, 0)) == FAIL
))
3275 inst
.error
= BAD_ARGS
;
3277 else if (rd
== REG_PC
|| rm
== REG_PC
)
3278 inst
.error
= BAD_PC
;
3284 /* ARM V5 (argument parse)
3285 LDC2{L} <coproc>, <CRd>, <addressing mode>
3286 STC2{L} <coproc>, <CRd>, <addressing mode>
3287 Instruction is not conditional, and has 0xf in the condition field.
3288 Otherwise, it's the same as LDC/STC. */
3291 do_lstc2 (char * str
)
3293 skip_whitespace (str
);
3295 if (co_proc_number (& str
) == FAIL
)
3298 inst
.error
= BAD_ARGS
;
3300 else if (skip_past_comma (& str
) == FAIL
3301 || cp_reg_required_here (& str
, 12) == FAIL
)
3304 inst
.error
= BAD_ARGS
;
3306 else if (skip_past_comma (& str
) == FAIL
3307 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
3310 inst
.error
= BAD_ARGS
;
3316 /* ARM V5 (argument parse)
3317 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
3318 Instruction is not conditional, and has 0xf in the condition field.
3319 Otherwise, it's the same as CDP. */
3322 do_cdp2 (char * str
)
3324 skip_whitespace (str
);
3326 if (co_proc_number (& str
) == FAIL
)
3329 inst
.error
= BAD_ARGS
;
3333 if (skip_past_comma (& str
) == FAIL
3334 || cp_opc_expr (& str
, 20,4) == FAIL
)
3337 inst
.error
= BAD_ARGS
;
3341 if (skip_past_comma (& str
) == FAIL
3342 || cp_reg_required_here (& str
, 12) == FAIL
)
3345 inst
.error
= BAD_ARGS
;
3349 if (skip_past_comma (& str
) == FAIL
3350 || cp_reg_required_here (& str
, 16) == FAIL
)
3353 inst
.error
= BAD_ARGS
;
3357 if (skip_past_comma (& str
) == FAIL
3358 || cp_reg_required_here (& str
, 0) == FAIL
)
3361 inst
.error
= BAD_ARGS
;
3365 if (skip_past_comma (& str
) == SUCCESS
)
3367 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
3370 inst
.error
= BAD_ARGS
;
3378 /* ARM V5 (argument parse)
3379 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3380 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3381 Instruction is not conditional, and has 0xf in the condition field.
3382 Otherwise, it's the same as MCR/MRC. */
3385 do_co_reg2 (char * str
)
3387 skip_whitespace (str
);
3389 if (co_proc_number (& str
) == FAIL
)
3392 inst
.error
= BAD_ARGS
;
3396 if (skip_past_comma (& str
) == FAIL
3397 || cp_opc_expr (& str
, 21, 3) == FAIL
)
3400 inst
.error
= BAD_ARGS
;
3404 if (skip_past_comma (& str
) == FAIL
3405 || reg_required_here (& str
, 12) == FAIL
)
3408 inst
.error
= BAD_ARGS
;
3412 if (skip_past_comma (& str
) == FAIL
3413 || cp_reg_required_here (& str
, 16) == FAIL
)
3416 inst
.error
= BAD_ARGS
;
3420 if (skip_past_comma (& str
) == FAIL
3421 || cp_reg_required_here (& str
, 0) == FAIL
)
3424 inst
.error
= BAD_ARGS
;
3428 if (skip_past_comma (& str
) == SUCCESS
)
3430 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
3433 inst
.error
= BAD_ARGS
;
3446 skip_whitespace (str
);
3448 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
3450 inst
.error
= BAD_ARGS
;
3454 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
3456 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
3461 /* ARM v5TEJ. Jump to Jazelle code. */
3468 skip_whitespace (str
);
3470 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
3472 inst
.error
= BAD_ARGS
;
3476 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
3478 as_tsktsk (_("use of r15 in bxj is not really useful"));
3483 /* ARM V6 umaal (argument parse). */
3486 do_umaal (char * str
)
3488 int rdlo
, rdhi
, rm
, rs
;
3490 skip_whitespace (str
);
3491 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
3492 || skip_past_comma (& str
) == FAIL
3493 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
3494 || skip_past_comma (& str
) == FAIL
3495 || (rm
= reg_required_here (& str
, 0)) == FAIL
3496 || skip_past_comma (& str
) == FAIL
3497 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
3499 inst
.error
= BAD_ARGS
;
3503 if (rdlo
== REG_PC
|| rdhi
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
3505 inst
.error
= BAD_PC
;
3512 /* ARM V6 strex (argument parse). */
3515 do_strex (char * str
)
3519 /* Parse Rd, Rm,. */
3520 skip_whitespace (str
);
3521 if ((rd
= reg_required_here (& str
, 12)) == FAIL
3522 || skip_past_comma (& str
) == FAIL
3523 || (rm
= reg_required_here (& str
, 0)) == FAIL
3524 || skip_past_comma (& str
) == FAIL
)
3526 inst
.error
= BAD_ARGS
;
3529 if (rd
== REG_PC
|| rm
== REG_PC
)
3531 inst
.error
= BAD_PC
;
3536 inst
.error
= _("Rd equal to Rm or Rn yields unpredictable results");
3540 /* Skip past '['. */
3541 if ((strlen (str
) >= 1)
3542 && strncmp (str
, "[", 1) == 0)
3545 skip_whitespace (str
);
3548 if ((rn
= reg_required_here (& str
, 16)) == FAIL
)
3550 inst
.error
= BAD_ARGS
;
3553 else if (rn
== REG_PC
)
3555 inst
.error
= BAD_PC
;
3560 inst
.error
= _("Rd equal to Rm or Rn yields unpredictable results");
3563 skip_whitespace (str
);
3565 /* Skip past ']'. */
3566 if ((strlen (str
) >= 1)
3567 && strncmp (str
, "]", 1) == 0)
3573 /* KIND indicates what kind of shifts are accepted. */
3576 decode_shift (char ** str
, int kind
)
3578 const struct asm_shift_name
* shift
;
3582 skip_whitespace (* str
);
3584 for (p
= * str
; ISALPHA (* p
); p
++)
3589 inst
.error
= _("shift expression expected");
3595 shift
= (const struct asm_shift_name
*) hash_find (arm_shift_hsh
, * str
);
3600 inst
.error
= _("shift expression expected");
3604 assert (shift
->properties
->index
== shift_properties
[shift
->properties
->index
].index
);
3606 if (kind
== SHIFT_LSL_OR_ASR_IMMEDIATE
3607 && shift
->properties
->index
!= SHIFT_LSL
3608 && shift
->properties
->index
!= SHIFT_ASR
)
3610 inst
.error
= _("'LSL' or 'ASR' required");
3613 else if (kind
== SHIFT_LSL_IMMEDIATE
3614 && shift
->properties
->index
!= SHIFT_LSL
)
3616 inst
.error
= _("'LSL' required");
3619 else if (kind
== SHIFT_ASR_IMMEDIATE
3620 && shift
->properties
->index
!= SHIFT_ASR
)
3622 inst
.error
= _("'ASR' required");
3626 if (shift
->properties
->index
== SHIFT_RRX
)
3629 inst
.instruction
|= shift
->properties
->bit_field
;
3633 skip_whitespace (p
);
3635 if (kind
== NO_SHIFT_RESTRICT
&& reg_required_here (& p
, 8) != FAIL
)
3637 inst
.instruction
|= shift
->properties
->bit_field
| SHIFT_BY_REG
;
3641 else if (! is_immediate_prefix (* p
))
3643 inst
.error
= (NO_SHIFT_RESTRICT
3644 ? _("shift requires register or #expression")
3645 : _("shift requires #expression"));
3653 if (my_get_expression (& inst
.reloc
.exp
, & p
))
3656 /* Validate some simple #expressions. */
3657 if (inst
.reloc
.exp
.X_op
== O_constant
)
3659 unsigned num
= inst
.reloc
.exp
.X_add_number
;
3661 /* Reject operations greater than 32. */
3663 /* Reject a shift of 0 unless the mode allows it. */
3664 || (num
== 0 && shift
->properties
->allows_0
== 0)
3665 /* Reject a shift of 32 unless the mode allows it. */
3666 || (num
== 32 && shift
->properties
->allows_32
== 0)
3669 /* As a special case we allow a shift of zero for
3670 modes that do not support it to be recoded as an
3671 logical shift left of zero (ie nothing). We warn
3672 about this though. */
3675 as_warn (_("shift of 0 ignored."));
3676 shift
= & shift_names
[0];
3677 assert (shift
->properties
->index
== SHIFT_LSL
);
3681 inst
.error
= _("invalid immediate shift");
3686 /* Shifts of 32 are encoded as 0, for those shifts that
3691 inst
.instruction
|= (num
<< 7) | shift
->properties
->bit_field
;
3695 inst
.reloc
.type
= BFD_RELOC_ARM_SHIFT_IMM
;
3696 inst
.reloc
.pc_rel
= 0;
3697 inst
.instruction
|= shift
->properties
->bit_field
;
3705 do_sat (char ** str
, int bias
)
3710 skip_whitespace (*str
);
3712 /* Parse <Rd>, field. */
3713 if ((rd
= reg_required_here (str
, 12)) == FAIL
3714 || skip_past_comma (str
) == FAIL
)
3716 inst
.error
= BAD_ARGS
;
3721 inst
.error
= BAD_PC
;
3725 /* Parse #<immed>, field. */
3726 if (is_immediate_prefix (**str
))
3730 inst
.error
= _("immediate expression expected");
3733 if (my_get_expression (&expr
, str
))
3735 inst
.error
= _("bad expression");
3738 if (expr
.X_op
!= O_constant
)
3740 inst
.error
= _("constant expression expected");
3743 if (expr
.X_add_number
+ bias
< 0
3744 || expr
.X_add_number
+ bias
> 31)
3746 inst
.error
= _("immediate value out of range");
3749 inst
.instruction
|= (expr
.X_add_number
+ bias
) << 16;
3750 if (skip_past_comma (str
) == FAIL
)
3752 inst
.error
= BAD_ARGS
;
3756 /* Parse <Rm> field. */
3757 if ((rm
= reg_required_here (str
, 0)) == FAIL
)
3759 inst
.error
= BAD_ARGS
;
3764 inst
.error
= BAD_PC
;
3768 if (skip_past_comma (str
) == SUCCESS
)
3769 decode_shift (str
, SHIFT_LSL_OR_ASR_IMMEDIATE
);
3772 /* ARM V6 ssat (argument parse). */
3775 do_ssat (char * str
)
3777 do_sat (&str
, /*bias=*/-1);
3781 /* ARM V6 usat (argument parse). */
3784 do_usat (char * str
)
3786 do_sat (&str
, /*bias=*/0);
3791 do_sat16 (char ** str
, int bias
)
3796 skip_whitespace (*str
);
3798 /* Parse the <Rd> field. */
3799 if ((rd
= reg_required_here (str
, 12)) == FAIL
3800 || skip_past_comma (str
) == FAIL
)
3802 inst
.error
= BAD_ARGS
;
3807 inst
.error
= BAD_PC
;
3811 /* Parse #<immed>, field. */
3812 if (is_immediate_prefix (**str
))
3816 inst
.error
= _("immediate expression expected");
3819 if (my_get_expression (&expr
, str
))
3821 inst
.error
= _("bad expression");
3824 if (expr
.X_op
!= O_constant
)
3826 inst
.error
= _("constant expression expected");
3829 if (expr
.X_add_number
+ bias
< 0
3830 || expr
.X_add_number
+ bias
> 15)
3832 inst
.error
= _("immediate value out of range");
3835 inst
.instruction
|= (expr
.X_add_number
+ bias
) << 16;
3836 if (skip_past_comma (str
) == FAIL
)
3838 inst
.error
= BAD_ARGS
;
3842 /* Parse <Rm> field. */
3843 if ((rm
= reg_required_here (str
, 0)) == FAIL
)
3845 inst
.error
= BAD_ARGS
;
3850 inst
.error
= BAD_PC
;
3855 /* ARM V6 ssat16 (argument parse). */
3858 do_ssat16 (char * str
)
3860 do_sat16 (&str
, /*bias=*/-1);
3865 do_usat16 (char * str
)
3867 do_sat16 (&str
, /*bias=*/0);
3872 do_cps_mode (char ** str
)
3876 skip_whitespace (*str
);
3878 if (! is_immediate_prefix (**str
))
3880 inst
.error
= _("immediate expression expected");
3884 (*str
)++; /* Strip off the immediate signifier. */
3885 if (my_get_expression (&expr
, str
))
3887 inst
.error
= _("bad expression");
3891 if (expr
.X_op
!= O_constant
)
3893 inst
.error
= _("constant expression expected");
3897 /* The mode is a 5 bit field. Valid values are 0-31. */
3898 if (((unsigned) expr
.X_add_number
) > 31
3899 || (inst
.reloc
.exp
.X_add_number
) < 0)
3901 inst
.error
= _("invalid constant");
3905 inst
.instruction
|= expr
.X_add_number
;
3908 /* ARM V6 srs (argument parse). */
3914 skip_whitespace (str
);
3915 exclam
= strchr (str
, '!');
3923 inst
.instruction
|= WRITE_BACK
;
3929 /* ARM V6 SMMUL (argument parse). */
3932 do_smmul (char * str
)
3936 skip_whitespace (str
);
3937 if ((rd
= reg_required_here (&str
, 16)) == FAIL
3938 || skip_past_comma (&str
) == FAIL
3939 || (rm
= reg_required_here (&str
, 0)) == FAIL
3940 || skip_past_comma (&str
) == FAIL
3941 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
3943 inst
.error
= BAD_ARGS
;
3951 inst
.error
= BAD_PC
;
3958 /* ARM V6 SMLALD (argument parse). */
3961 do_smlald (char * str
)
3963 int rdlo
, rdhi
, rm
, rs
;
3965 skip_whitespace (str
);
3966 if ((rdlo
= reg_required_here (&str
, 12)) == FAIL
3967 || skip_past_comma (&str
) == FAIL
3968 || (rdhi
= reg_required_here (&str
, 16)) == FAIL
3969 || skip_past_comma (&str
) == FAIL
3970 || (rm
= reg_required_here (&str
, 0)) == FAIL
3971 || skip_past_comma (&str
) == FAIL
3972 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
3974 inst
.error
= BAD_ARGS
;
3983 inst
.error
= BAD_PC
;
3990 /* ARM V6 SMLAD (argument parse). Signed multiply accumulate dual.
3991 smlad{x}{<cond>} Rd, Rm, Rs, Rn */
3994 do_smlad (char * str
)
3998 skip_whitespace (str
);
3999 if ((rd
= reg_required_here (&str
, 16)) == FAIL
4000 || skip_past_comma (&str
) == FAIL
4001 || (rm
= reg_required_here (&str
, 0)) == FAIL
4002 || skip_past_comma (&str
) == FAIL
4003 || (rs
= reg_required_here (&str
, 8)) == FAIL
4004 || skip_past_comma (&str
) == FAIL
4005 || (rn
= reg_required_here (&str
, 12)) == FAIL
)
4007 inst
.error
= BAD_ARGS
;
4016 inst
.error
= BAD_PC
;
4023 /* Returns true if the endian-specifier indicates big-endianness. */
4026 do_endian_specifier (char * str
)
4030 skip_whitespace (str
);
4031 if (strlen (str
) < 2)
4032 inst
.error
= _("missing endian specifier");
4033 else if (strncasecmp (str
, "BE", 2) == 0)
4038 else if (strncasecmp (str
, "LE", 2) == 0)
4041 inst
.error
= _("valid endian specifiers are be or le");
4048 /* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
4049 preserving the other bits.
4051 setend <endian_specifier>, where <endian_specifier> is either
4055 do_setend (char * str
)
4057 if (do_endian_specifier (str
))
4058 inst
.instruction
|= 0x200;
4063 SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
4064 Condition defaults to COND_ALWAYS.
4065 Error if any register uses R15. */
4068 do_sxth (char * str
)
4072 int rotation_clear_mask
= 0xfffff3ff;
4073 int rotation_eight_mask
= 0x00000400;
4074 int rotation_sixteen_mask
= 0x00000800;
4075 int rotation_twenty_four_mask
= 0x00000c00;
4077 skip_whitespace (str
);
4078 if ((rd
= reg_required_here (&str
, 12)) == FAIL
4079 || skip_past_comma (&str
) == FAIL
4080 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4082 inst
.error
= BAD_ARGS
;
4086 else if (rd
== REG_PC
|| rm
== REG_PC
)
4088 inst
.error
= BAD_PC
;
4092 /* Zero out the rotation field. */
4093 inst
.instruction
&= rotation_clear_mask
;
4095 /* Check for lack of optional rotation field. */
4096 if (skip_past_comma (&str
) == FAIL
)
4102 /* Move past 'ROR'. */
4103 skip_whitespace (str
);
4104 if (strncasecmp (str
, "ROR", 3) == 0)
4108 inst
.error
= _("missing rotation field after comma");
4112 /* Get the immediate constant. */
4113 skip_whitespace (str
);
4114 if (is_immediate_prefix (* str
))
4118 inst
.error
= _("immediate expression expected");
4122 if (my_get_expression (&expr
, &str
))
4124 inst
.error
= _("bad expression");
4128 if (expr
.X_op
!= O_constant
)
4130 inst
.error
= _("constant expression expected");
4134 switch (expr
.X_add_number
)
4137 /* Rotation field has already been zeroed. */
4140 inst
.instruction
|= rotation_eight_mask
;
4144 inst
.instruction
|= rotation_sixteen_mask
;
4148 inst
.instruction
|= rotation_twenty_four_mask
;
4152 inst
.error
= _("rotation can be 8, 16, 24 or 0 when field is ommited");
4159 /* ARM V6 SXTAH extracts a 16-bit value from a register, sign
4160 extends it to 32-bits, and adds the result to a value in another
4161 register. You can specify a rotation by 0, 8, 16, or 24 bits
4162 before extracting the 16-bit value.
4163 SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
4164 Condition defaults to COND_ALWAYS.
4165 Error if any register uses R15. */
4168 do_sxtah (char * str
)
4172 int rotation_clear_mask
= 0xfffff3ff;
4173 int rotation_eight_mask
= 0x00000400;
4174 int rotation_sixteen_mask
= 0x00000800;
4175 int rotation_twenty_four_mask
= 0x00000c00;
4177 skip_whitespace (str
);
4178 if ((rd
= reg_required_here (&str
, 12)) == FAIL
4179 || skip_past_comma (&str
) == FAIL
4180 || (rn
= reg_required_here (&str
, 16)) == FAIL
4181 || skip_past_comma (&str
) == FAIL
4182 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4184 inst
.error
= BAD_ARGS
;
4188 else if (rd
== REG_PC
|| rn
== REG_PC
|| rm
== REG_PC
)
4190 inst
.error
= BAD_PC
;
4194 /* Zero out the rotation field. */
4195 inst
.instruction
&= rotation_clear_mask
;
4197 /* Check for lack of optional rotation field. */
4198 if (skip_past_comma (&str
) == FAIL
)
4204 /* Move past 'ROR'. */
4205 skip_whitespace (str
);
4206 if (strncasecmp (str
, "ROR", 3) == 0)
4210 inst
.error
= _("missing rotation field after comma");
4214 /* Get the immediate constant. */
4215 skip_whitespace (str
);
4216 if (is_immediate_prefix (* str
))
4220 inst
.error
= _("immediate expression expected");
4224 if (my_get_expression (&expr
, &str
))
4226 inst
.error
= _("bad expression");
4230 if (expr
.X_op
!= O_constant
)
4232 inst
.error
= _("constant expression expected");
4236 switch (expr
.X_add_number
)
4239 /* Rotation field has already been zeroed. */
4243 inst
.instruction
|= rotation_eight_mask
;
4247 inst
.instruction
|= rotation_sixteen_mask
;
4251 inst
.instruction
|= rotation_twenty_four_mask
;
4255 inst
.error
= _("rotation can be 8, 16, 24 or 0 when field is ommited");
4263 /* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
4264 word at the specified address and the following word
4266 Unconditionally executed.
4267 Error if Rn is R15. */
4274 skip_whitespace (str
);
4276 if ((rn
= reg_required_here (&str
, 16)) == FAIL
)
4281 inst
.error
= BAD_PC
;
4285 skip_whitespace (str
);
4289 inst
.instruction
|= WRITE_BACK
;
4295 /* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
4296 register (argument parse).
4298 Condition defaults to COND_ALWAYS.
4299 Error if Rd or Rm are R15. */
4306 skip_whitespace (str
);
4308 if ((rd
= reg_required_here (&str
, 12)) == FAIL
4309 || skip_past_comma (&str
) == FAIL
4310 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4311 inst
.error
= BAD_ARGS
;
4313 else if (rd
== REG_PC
|| rm
== REG_PC
)
4314 inst
.error
= BAD_PC
;
4320 /* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
4321 QADD16{<cond>} <Rd>, <Rn>, <Rm>
4322 Condition defaults to COND_ALWAYS.
4323 Error if Rd, Rn or Rm are R15. */
4326 do_qadd16 (char * str
)
4330 skip_whitespace (str
);
4332 if ((rd
= reg_required_here (&str
, 12)) == FAIL
4333 || skip_past_comma (&str
) == FAIL
4334 || (rn
= reg_required_here (&str
, 16)) == FAIL
4335 || skip_past_comma (&str
) == FAIL
4336 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4337 inst
.error
= BAD_ARGS
;
4339 else if (rd
== REG_PC
|| rm
== REG_PC
|| rn
== REG_PC
)
4340 inst
.error
= BAD_PC
;
4347 do_pkh_core (char * str
, int shift
)
4351 skip_whitespace (str
);
4352 if (((rd
= reg_required_here (&str
, 12)) == FAIL
)
4353 || (skip_past_comma (&str
) == FAIL
)
4354 || ((rn
= reg_required_here (&str
, 16)) == FAIL
)
4355 || (skip_past_comma (&str
) == FAIL
)
4356 || ((rm
= reg_required_here (&str
, 0)) == FAIL
))
4358 inst
.error
= BAD_ARGS
;
4362 else if (rd
== REG_PC
|| rn
== REG_PC
|| rm
== REG_PC
)
4364 inst
.error
= BAD_PC
;
4368 /* Check for optional shift immediate constant. */
4369 if (skip_past_comma (&str
) == FAIL
)
4371 if (shift
== SHIFT_ASR_IMMEDIATE
)
4373 /* If the shift specifier is ommited, turn the instruction
4374 into pkhbt rd, rm, rn. First, switch the instruction
4375 code, and clear the rn and rm fields. */
4376 inst
.instruction
&= 0xfff0f010;
4377 /* Now, re-encode the registers. */
4378 inst
.instruction
|= (rm
<< 16) | rn
;
4383 decode_shift (&str
, shift
);
4386 /* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
4387 PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
4388 Condition defaults to COND_ALWAYS.
4389 Error if Rd, Rn or Rm are R15. */
4392 do_pkhbt (char * str
)
4394 do_pkh_core (str
, SHIFT_LSL_IMMEDIATE
);
4397 /* ARM V6 PKHTB (Argument Parse). */
4400 do_pkhtb (char * str
)
4402 do_pkh_core (str
, SHIFT_ASR_IMMEDIATE
);
4405 /* ARM V6 Load Register Exclusive instruction (argument parse).
4406 LDREX{,B,D,H}{<cond>} <Rd, [<Rn>]
4407 Condition defaults to COND_ALWAYS.
4408 Error if Rd or Rn are R15.
4409 See ARMARMv6 A4.1.27: LDREX. */
4412 do_ldrex (char * str
)
4416 skip_whitespace (str
);
4419 if (((rd
= reg_required_here (&str
, 12)) == FAIL
)
4420 || (skip_past_comma (&str
) == FAIL
))
4422 inst
.error
= BAD_ARGS
;
4425 else if (rd
== REG_PC
)
4427 inst
.error
= BAD_PC
;
4430 skip_whitespace (str
);
4432 /* Skip past '['. */
4433 if ((strlen (str
) >= 1)
4434 &&strncmp (str
, "[", 1) == 0)
4436 skip_whitespace (str
);
4439 if ((rn
= reg_required_here (&str
, 16)) == FAIL
)
4441 inst
.error
= BAD_ARGS
;
4444 else if (rn
== REG_PC
)
4446 inst
.error
= BAD_PC
;
4449 skip_whitespace (str
);
4451 /* Skip past ']'. */
4452 if ((strlen (str
) >= 1)
4453 && strncmp (str
, "]", 1) == 0)
4459 /* ARM V6 change processor state instruction (argument parse)
4460 CPS, CPSIE, CSPID . */
4470 do_cps_flags (char ** str
, int thumb_p
)
4475 unsigned long arm_value
;
4476 unsigned long thumb_value
;
4478 static struct cps_flag flag_table
[] =
4487 skip_whitespace (*str
);
4489 /* Get the a, f and i flags. */
4490 while (**str
&& **str
!= ',')
4493 struct cps_flag
*q
= flag_table
+ sizeof (flag_table
)/sizeof (*p
);
4495 for (p
= flag_table
; p
< q
; ++p
)
4496 if (strncasecmp (*str
, &p
->character
, 1) == 0)
4498 inst
.instruction
|= (thumb_p
? p
->thumb_value
: p
->arm_value
);
4504 inst
.error
= _("unrecognized flag");
4511 inst
.error
= _("no 'a', 'i', or 'f' flags for 'cps'");
4515 do_cpsi (char * str
)
4517 do_cps_flags (&str
, /*thumb_p=*/0);
4519 if (skip_past_comma (&str
) == SUCCESS
)
4521 skip_whitespace (str
);
4527 /* THUMB V5 breakpoint instruction (argument parse)
4531 do_t_bkpt (char * str
)
4534 unsigned long number
;
4536 skip_whitespace (str
);
4538 /* Allow optional leading '#'. */
4539 if (is_immediate_prefix (*str
))
4542 memset (& expr
, '\0', sizeof (expr
));
4543 if (my_get_expression (& expr
, & str
)
4544 || (expr
.X_op
!= O_constant
4545 /* As a convenience we allow 'bkpt' without an operand. */
4546 && expr
.X_op
!= O_absent
))
4548 inst
.error
= _("bad expression");
4552 number
= expr
.X_add_number
;
4554 /* Check it fits an 8 bit unsigned. */
4555 if (number
!= (number
& 0xff))
4557 inst
.error
= _("immediate value out of range");
4561 inst
.instruction
|= number
;
4566 static bfd_reloc_code_real_type
4567 arm_parse_reloc (void)
4576 bfd_reloc_code_real_type reloc
;
4580 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
4581 MAP ("(got)", BFD_RELOC_ARM_GOT32
),
4582 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF
),
4583 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
4584 branch instructions generated by GCC for PLT relocs. */
4585 MAP ("(plt)", BFD_RELOC_ARM_PLT32
),
4586 MAP ("(target1)", BFD_RELOC_ARM_TARGET1
),
4587 MAP ("(sbrel)", BFD_RELOC_ARM_SBREL32
),
4588 MAP ("(target2)", BFD_RELOC_ARM_TARGET2
),
4589 { NULL
, 0, BFD_RELOC_UNUSED
}
4593 for (i
= 0, ip
= input_line_pointer
;
4594 i
< sizeof (id
) && (ISALNUM (*ip
) || ISPUNCT (*ip
));
4596 id
[i
] = TOLOWER (*ip
);
4598 for (i
= 0; reloc_map
[i
].str
; i
++)
4599 if (strncmp (id
, reloc_map
[i
].str
, reloc_map
[i
].len
) == 0)
4602 input_line_pointer
+= reloc_map
[i
].len
;
4604 return reloc_map
[i
].reloc
;
4607 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
4608 Expects inst.instruction is set for BLX(1).
4609 Note: this is cloned from do_branch, and the reloc changed to be a
4610 new one that can cope with setting one extra bit (the H bit). */
4613 do_branch25 (char * str
)
4615 if (my_get_expression (& inst
.reloc
.exp
, & str
))
4622 /* ScottB: February 5, 1998 */
4623 /* Check to see of PLT32 reloc required for the instruction. */
4625 /* arm_parse_reloc() works on input_line_pointer.
4626 We actually want to parse the operands to the branch instruction
4627 passed in 'str'. Save the input pointer and restore it later. */
4628 save_in
= input_line_pointer
;
4629 input_line_pointer
= str
;
4631 if (inst
.reloc
.exp
.X_op
== O_symbol
4633 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
4635 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
4636 inst
.reloc
.pc_rel
= 0;
4637 /* Modify str to point to after parsed operands, otherwise
4638 end_of_line() will complain about the (PLT) left in str. */
4639 str
= input_line_pointer
;
4643 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
4644 inst
.reloc
.pc_rel
= 1;
4647 input_line_pointer
= save_in
;
4650 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
4651 inst
.reloc
.pc_rel
= 1;
4652 #endif /* OBJ_ELF */
4657 /* ARM V5 branch-link-exchange instruction (argument parse)
4658 BLX <target_addr> ie BLX(1)
4659 BLX{<condition>} <Rm> ie BLX(2)
4660 Unfortunately, there are two different opcodes for this mnemonic.
4661 So, the insns[].value is not used, and the code here zaps values
4662 into inst.instruction.
4663 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
4671 skip_whitespace (mystr
);
4672 rm
= reg_required_here (& mystr
, 0);
4674 /* The above may set inst.error. Ignore his opinion. */
4679 /* Arg is a register.
4680 Use the condition code our caller put in inst.instruction.
4681 Pass ourselves off as a BX with a funny opcode. */
4682 inst
.instruction
|= 0x012fff30;
4687 /* This must be is BLX <target address>, no condition allowed. */
4688 if (inst
.instruction
!= COND_ALWAYS
)
4690 inst
.error
= BAD_COND
;
4694 inst
.instruction
= 0xfafffffe;
4696 /* Process like a B/BL, but with a different reloc.
4697 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
4702 /* ARM V5 Thumb BLX (argument parse)
4703 BLX <target_addr> which is BLX(1)
4704 BLX <Rm> which is BLX(2)
4705 Unfortunately, there are two different opcodes for this mnemonic.
4706 So, the tinsns[].value is not used, and the code here zaps values
4707 into inst.instruction. */
4710 do_t_blx (char * str
)
4715 skip_whitespace (mystr
);
4716 inst
.instruction
= 0x4780;
4718 /* Note that this call is to the ARM register recognizer. BLX(2)
4719 uses the ARM register space, not the Thumb one, so a call to
4720 thumb_reg() would be wrong. */
4721 rm
= reg_required_here (& mystr
, 3);
4726 /* It's BLX(2). The .instruction was zapped with rm & is final. */
4731 /* No ARM register. This must be BLX(1). Change the .instruction. */
4732 inst
.instruction
= 0xf7ffeffe;
4735 if (my_get_expression (& inst
.reloc
.exp
, & mystr
))
4738 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BLX
;
4739 inst
.reloc
.pc_rel
= 1;
4742 end_of_line (mystr
);
4745 /* ARM V5 breakpoint instruction (argument parse)
4746 BKPT <16 bit unsigned immediate>
4747 Instruction is not conditional.
4748 The bit pattern given in insns[] has the COND_ALWAYS condition,
4749 and it is an error if the caller tried to override that. */
4752 do_bkpt (char * str
)
4755 unsigned long number
;
4757 skip_whitespace (str
);
4759 /* Allow optional leading '#'. */
4760 if (is_immediate_prefix (* str
))
4763 memset (& expr
, '\0', sizeof (expr
));
4765 if (my_get_expression (& expr
, & str
)
4766 || (expr
.X_op
!= O_constant
4767 /* As a convenience we allow 'bkpt' without an operand. */
4768 && expr
.X_op
!= O_absent
))
4770 inst
.error
= _("bad expression");
4774 number
= expr
.X_add_number
;
4776 /* Check it fits a 16 bit unsigned. */
4777 if (number
!= (number
& 0xffff))
4779 inst
.error
= _("immediate value out of range");
4783 /* Top 12 of 16 bits to bits 19:8. */
4784 inst
.instruction
|= (number
& 0xfff0) << 4;
4786 /* Bottom 4 of 16 bits to bits 3:0. */
4787 inst
.instruction
|= number
& 0xf;
4792 /* THUMB CPS instruction (argument parse). */
4795 do_t_cps (char * str
)
4797 do_cps_flags (&str
, /*thumb_p=*/1);
4801 /* Parse and validate that a register is of the right form, this saves
4802 repeated checking of this information in many similar cases.
4803 Unlike the 32-bit case we do not insert the register into the opcode
4804 here, since the position is often unknown until the full instruction
4808 thumb_reg (char ** strp
, int hi_lo
)
4812 if ((reg
= reg_required_here (strp
, -1)) == FAIL
)
4820 inst
.error
= _("lo register required");
4828 inst
.error
= _("hi register required");
4841 thumb_mov_compare (char * str
, int move
)
4845 skip_whitespace (str
);
4847 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
4848 || skip_past_comma (&str
) == FAIL
)
4851 inst
.error
= BAD_ARGS
;
4855 if (move
!= THUMB_CPY
&& is_immediate_prefix (*str
))
4858 if (my_get_expression (&inst
.reloc
.exp
, &str
))
4861 else if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
4866 if (move
!= THUMB_CPY
&& Rs
< 8 && Rd
< 8)
4868 if (move
== THUMB_MOVE
)
4869 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
4870 since a MOV instruction produces unpredictable results. */
4871 inst
.instruction
= T_OPCODE_ADD_I3
;
4873 inst
.instruction
= T_OPCODE_CMP_LR
;
4874 inst
.instruction
|= Rd
| (Rs
<< 3);
4878 if (move
== THUMB_MOVE
)
4879 inst
.instruction
= T_OPCODE_MOV_HR
;
4880 else if (move
!= THUMB_CPY
)
4881 inst
.instruction
= T_OPCODE_CMP_HR
;
4884 inst
.instruction
|= THUMB_H1
;
4887 inst
.instruction
|= THUMB_H2
;
4889 inst
.instruction
|= (Rd
& 7) | ((Rs
& 7) << 3);
4896 inst
.error
= _("only lo regs allowed with immediate");
4900 if (move
== THUMB_MOVE
)
4901 inst
.instruction
= T_OPCODE_MOV_I8
;
4903 inst
.instruction
= T_OPCODE_CMP_I8
;
4905 inst
.instruction
|= Rd
<< 8;
4907 if (inst
.reloc
.exp
.X_op
!= O_constant
)
4908 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_IMM
;
4911 unsigned value
= inst
.reloc
.exp
.X_add_number
;
4915 inst
.error
= _("invalid immediate");
4919 inst
.instruction
|= value
;
4926 /* THUMB CPY instruction (argument parse). */
4929 do_t_cpy (char * str
)
4931 thumb_mov_compare (str
, THUMB_CPY
);
4934 /* THUMB SETEND instruction (argument parse). */
4937 do_t_setend (char * str
)
4939 if (do_endian_specifier (str
))
4940 inst
.instruction
|= 0x8;
4943 /* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
4945 static unsigned long
4946 check_iwmmxt_insn (char * str
,
4947 enum iwmmxt_insn_type insn_type
,
4951 const char * inst_error
;
4953 unsigned long number
;
4955 inst_error
= inst
.error
;
4957 inst
.error
= BAD_ARGS
;
4958 skip_whitespace (str
);
4963 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
4968 if ((wreg_required_here (&str
, 0, IWMMXT_REG_WR
)) == FAIL
)
4973 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
4974 || skip_past_comma (&str
) == FAIL
4975 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
))
4980 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
4981 || skip_past_comma (&str
) == FAIL
4982 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4983 || skip_past_comma (&str
) == FAIL
4984 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
))
4989 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
4990 || skip_past_comma (&str
) == FAIL
4991 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4992 || skip_past_comma (&str
) == FAIL
4993 || wreg_required_here (&str
, 0, IWMMXT_REG_WCG
) == FAIL
))
4998 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4999 || skip_past_comma (&str
) == FAIL
5000 || reg_required_here (&str
, 12) == FAIL
))
5005 if ((reg_required_here (&str
, 12) == FAIL
5006 || skip_past_comma (&str
) == FAIL
5007 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
))
5012 if ((wreg_required_here (&str
, 5, IWMMXT_REG_WR
) == FAIL
5013 || skip_past_comma (&str
) == FAIL
5014 || reg_required_here (&str
, 0) == FAIL
5015 || skip_past_comma (&str
) == FAIL
5016 || reg_required_here (&str
, 12) == FAIL
))
5021 if ((wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
5022 || skip_past_comma (&str
) == FAIL
5023 || reg_required_here (&str
, 12) == FAIL
5024 || skip_past_comma (&str
) == FAIL
5025 || reg_required_here (&str
, 16) == FAIL
))
5030 if ((reg_required_here (&str
, 12) == FAIL
5031 || skip_past_comma (&str
) == FAIL
5032 || reg_required_here (&str
, 16) == FAIL
5033 || skip_past_comma (&str
) == FAIL
5034 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
))
5039 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WC
) == FAIL
5040 || skip_past_comma (&str
) == FAIL
5041 || reg_required_here (&str
, 12) == FAIL
))
5046 if ((reg_required_here (&str
, 12) == FAIL
5047 || skip_past_comma (&str
) == FAIL
5048 || wreg_required_here (&str
, 16, IWMMXT_REG_WC
) == FAIL
))
5053 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5054 || skip_past_comma (&str
) == FAIL
5055 || reg_required_here (&str
, 12) == FAIL
5056 || skip_past_comma (&str
) == FAIL
))
5061 if ((reg_required_here (&str
, 12) == FAIL
5062 || skip_past_comma (&str
) == FAIL
))
5067 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
5068 || skip_past_comma (&str
) == FAIL
5069 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5070 || skip_past_comma (&str
) == FAIL
5071 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
5072 || skip_past_comma (&str
) == FAIL
))
5077 if ((reg_required_here (&str
, 12) == FAIL
5078 || skip_past_comma (&str
) == FAIL
5079 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5080 || skip_past_comma (&str
) == FAIL
))
5085 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
5086 || skip_past_comma (&str
) == FAIL
5087 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5088 || skip_past_comma (&str
) == FAIL
))
5093 if (immediate_size
== 0)
5096 inst
.error
= inst_error
;
5101 skip_whitespace (str
);
5103 /* Allow optional leading '#'. */
5104 if (is_immediate_prefix (* str
))
5107 memset (& expr
, '\0', sizeof (expr
));
5109 if (my_get_expression (& expr
, & str
) || (expr
.X_op
!= O_constant
))
5111 inst
.error
= _("bad or missing expression");
5115 number
= expr
.X_add_number
;
5117 if (number
!= (number
& immediate_size
))
5119 inst
.error
= _("immediate value out of range");
5123 inst
.error
= inst_error
;
5129 do_iwmmxt_byte_addr (char * str
)
5131 int op
= (inst
.instruction
& 0x300) >> 8;
5134 inst
.instruction
&= ~0x300;
5135 inst
.instruction
|= (op
& 1) << 22 | (op
& 2) << 7;
5137 skip_whitespace (str
);
5139 if ((reg
= wreg_required_here (&str
, 12, IWMMXT_REG_WR_OR_WC
)) == FAIL
5140 || skip_past_comma (& str
) == FAIL
5141 || cp_byte_address_required_here (&str
) == FAIL
)
5144 inst
.error
= BAD_ARGS
;
5149 if (wc_register (reg
))
5151 as_bad (_("non-word size not supported with control register"));
5152 inst
.instruction
|= 0xf0000100;
5153 inst
.instruction
&= ~0x00400000;
5158 do_iwmmxt_tandc (char * str
)
5162 reg
= check_iwmmxt_insn (str
, check_rd
, 0);
5164 if (reg
!= REG_PC
&& !inst
.error
)
5165 inst
.error
= _("only r15 allowed here");
5169 do_iwmmxt_tbcst (char * str
)
5171 check_iwmmxt_insn (str
, check_tbcst
, 0);
5175 do_iwmmxt_textrc (char * str
)
5177 unsigned long number
;
5179 if ((number
= check_iwmmxt_insn (str
, check_textrc
, 7)) == (unsigned long) FAIL
)
5182 inst
.instruction
|= number
& 0x7;
5186 do_iwmmxt_textrm (char * str
)
5188 unsigned long number
;
5190 if ((number
= check_iwmmxt_insn (str
, check_textrm
, 7)) == (unsigned long) FAIL
)
5193 inst
.instruction
|= number
& 0x7;
5197 do_iwmmxt_tinsr (char * str
)
5199 unsigned long number
;
5201 if ((number
= check_iwmmxt_insn (str
, check_tinsr
, 7)) == (unsigned long) FAIL
)
5204 inst
.instruction
|= number
& 0x7;
5208 do_iwmmxt_tmcr (char * str
)
5210 check_iwmmxt_insn (str
, check_tmcr
, 0);
5214 do_iwmmxt_tmcrr (char * str
)
5216 check_iwmmxt_insn (str
, check_tmcrr
, 0);
5220 do_iwmmxt_tmia (char * str
)
5222 check_iwmmxt_insn (str
, check_tmia
, 0);
5226 do_iwmmxt_tmovmsk (char * str
)
5228 check_iwmmxt_insn (str
, check_tmovmsk
, 0);
5232 do_iwmmxt_tmrc (char * str
)
5234 check_iwmmxt_insn (str
, check_tmrc
, 0);
5238 do_iwmmxt_tmrrc (char * str
)
5240 check_iwmmxt_insn (str
, check_tmrrc
, 0);
5244 do_iwmmxt_torc (char * str
)
5246 check_iwmmxt_insn (str
, check_rd
, 0);
5250 do_iwmmxt_waligni (char * str
)
5252 unsigned long number
;
5254 if ((number
= check_iwmmxt_insn (str
, check_waligni
, 7)) == (unsigned long) FAIL
)
5257 inst
.instruction
|= ((number
& 0x7) << 20);
5261 do_iwmmxt_wmov (char * str
)
5263 if (check_iwmmxt_insn (str
, check_wrwr
, 0) == (unsigned long) FAIL
)
5266 inst
.instruction
|= ((inst
.instruction
>> 16) & 0xf);
5270 do_iwmmxt_word_addr (char * str
)
5272 int op
= (inst
.instruction
& 0x300) >> 8;
5275 inst
.instruction
&= ~0x300;
5276 inst
.instruction
|= (op
& 1) << 22 | (op
& 2) << 7;
5278 skip_whitespace (str
);
5280 if ((reg
= wreg_required_here (&str
, 12, IWMMXT_REG_WR_OR_WC
)) == FAIL
5281 || skip_past_comma (& str
) == FAIL
5282 || cp_address_required_here (& str
, CP_WB_OK
) == FAIL
)
5285 inst
.error
= BAD_ARGS
;
5290 if (wc_register (reg
))
5292 if ((inst
.instruction
& COND_MASK
) != COND_ALWAYS
)
5293 as_bad (_("conditional execution not supported with control register"));
5295 as_bad (_("non-word size not supported with control register"));
5296 inst
.instruction
|= 0xf0000100;
5297 inst
.instruction
&= ~0x00400000;
5302 do_iwmmxt_wrwr (char * str
)
5304 check_iwmmxt_insn (str
, check_wrwr
, 0);
5308 do_iwmmxt_wrwrwcg (char * str
)
5310 check_iwmmxt_insn (str
, check_wrwrwcg
, 0);
5314 do_iwmmxt_wrwrwr (char * str
)
5316 check_iwmmxt_insn (str
, check_wrwrwr
, 0);
5320 do_iwmmxt_wshufh (char * str
)
5322 unsigned long number
;
5324 if ((number
= check_iwmmxt_insn (str
, check_wshufh
, 0xff)) == (unsigned long) FAIL
)
5327 inst
.instruction
|= ((number
& 0xf0) << 16) | (number
& 0xf);
5331 do_iwmmxt_wzero (char * str
)
5333 if (check_iwmmxt_insn (str
, check_wr
, 0) == (unsigned long) FAIL
)
5336 inst
.instruction
|= ((inst
.instruction
& 0xf) << 12) | ((inst
.instruction
& 0xf) << 16);
5339 /* Xscale multiply-accumulate (argument parse)
5342 MIAxycc acc0,Rm,Rs. */
5345 do_xsc_mia (char * str
)
5350 if (accum0_required_here (& str
) == FAIL
)
5351 inst
.error
= ERR_NO_ACCUM
;
5353 else if (skip_past_comma (& str
) == FAIL
5354 || (rm
= reg_required_here (& str
, 0)) == FAIL
)
5355 inst
.error
= BAD_ARGS
;
5357 else if (skip_past_comma (& str
) == FAIL
5358 || (rs
= reg_required_here (& str
, 12)) == FAIL
)
5359 inst
.error
= BAD_ARGS
;
5361 /* inst.instruction has now been zapped with both rm and rs. */
5362 else if (rm
== REG_PC
|| rs
== REG_PC
)
5363 inst
.error
= BAD_PC
; /* Undefined result if rm or rs is R15. */
5369 /* Xscale move-accumulator-register (argument parse)
5371 MARcc acc0,RdLo,RdHi. */
5374 do_xsc_mar (char * str
)
5378 if (accum0_required_here (& str
) == FAIL
)
5379 inst
.error
= ERR_NO_ACCUM
;
5381 else if (skip_past_comma (& str
) == FAIL
5382 || (rdlo
= reg_required_here (& str
, 12)) == FAIL
)
5383 inst
.error
= BAD_ARGS
;
5385 else if (skip_past_comma (& str
) == FAIL
5386 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
5387 inst
.error
= BAD_ARGS
;
5389 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5390 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
5391 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
5397 /* Xscale move-register-accumulator (argument parse)
5399 MRAcc RdLo,RdHi,acc0. */
5402 do_xsc_mra (char * str
)
5407 skip_whitespace (str
);
5409 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
)
5410 inst
.error
= BAD_ARGS
;
5412 else if (skip_past_comma (& str
) == FAIL
5413 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
5414 inst
.error
= BAD_ARGS
;
5416 else if (skip_past_comma (& str
) == FAIL
5417 || accum0_required_here (& str
) == FAIL
)
5418 inst
.error
= ERR_NO_ACCUM
;
5420 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5421 else if (rdlo
== rdhi
)
5422 inst
.error
= BAD_ARGS
; /* Undefined result if 2 writes to same reg. */
5424 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
5425 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
5431 ldst_extend (char ** str
)
5440 if (my_get_expression (& inst
.reloc
.exp
, str
))
5443 if (inst
.reloc
.exp
.X_op
== O_constant
)
5445 int value
= inst
.reloc
.exp
.X_add_number
;
5447 if (value
< -4095 || value
> 4095)
5449 inst
.error
= _("address offset too large");
5459 inst
.instruction
|= add
| value
;
5463 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
5464 inst
.reloc
.pc_rel
= 0;
5477 if (reg_required_here (str
, 0) == FAIL
)
5480 inst
.instruction
|= add
| OFFSET_REG
;
5481 if (skip_past_comma (str
) == SUCCESS
)
5482 return decode_shift (str
, SHIFT_IMMEDIATE
);
5488 /* ARMv5TE: Preload-Cache
5492 Syntactically, like LDR with B=1, W=0, L=1. */
5499 skip_whitespace (str
);
5503 inst
.error
= _("'[' expected after PLD mnemonic");
5508 skip_whitespace (str
);
5510 if ((rd
= reg_required_here (& str
, 16)) == FAIL
)
5513 skip_whitespace (str
);
5519 skip_whitespace (str
);
5521 /* Post-indexed addressing is not allowed with PLD. */
5522 if (skip_past_comma (&str
) == SUCCESS
)
5525 = _("post-indexed expression used in preload instruction");
5528 else if (*str
== '!') /* [Rn]! */
5530 inst
.error
= _("writeback used in preload instruction");
5534 inst
.instruction
|= INDEX_UP
| PRE_INDEX
;
5536 else /* [Rn, ...] */
5538 if (skip_past_comma (& str
) == FAIL
)
5540 inst
.error
= _("pre-indexed expression expected");
5544 if (ldst_extend (&str
) == FAIL
)
5547 skip_whitespace (str
);
5551 inst
.error
= _("missing ]");
5556 skip_whitespace (str
);
5558 if (* str
== '!') /* [Rn]! */
5560 inst
.error
= _("writeback used in preload instruction");
5564 inst
.instruction
|= PRE_INDEX
;
5570 /* ARMv5TE load-consecutive (argument parse)
5577 do_ldrd (char * str
)
5582 skip_whitespace (str
);
5584 if ((rd
= reg_required_here (& str
, 12)) == FAIL
)
5586 inst
.error
= BAD_ARGS
;
5590 if (skip_past_comma (& str
) == FAIL
5591 || (rn
= ld_mode_required_here (& str
)) == FAIL
)
5594 inst
.error
= BAD_ARGS
;
5598 /* inst.instruction has now been zapped with Rd and the addressing mode. */
5599 if (rd
& 1) /* Unpredictable result if Rd is odd. */
5601 inst
.error
= _("destination register must be even");
5607 inst
.error
= _("r14 not allowed here");
5611 if (((rd
== rn
) || (rd
+ 1 == rn
))
5612 && ((inst
.instruction
& WRITE_BACK
)
5613 || (!(inst
.instruction
& PRE_INDEX
))))
5614 as_warn (_("pre/post-indexing used when modified address register is destination"));
5616 /* For an index-register load, the index register must not overlap the
5617 destination (even if not write-back). */
5618 if ((inst
.instruction
& V4_STR_BIT
) == 0
5619 && (inst
.instruction
& HWOFFSET_IMM
) == 0)
5621 int rm
= inst
.instruction
& 0x0000000f;
5623 if (rm
== rd
|| (rm
== rd
+ 1))
5624 as_warn (_("ldrd destination registers must not overlap index register"));
5630 /* Returns the index into fp_values of a floating point number,
5631 or -1 if not in the table. */
5634 my_get_float_expression (char ** str
)
5636 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
5642 memset (words
, 0, MAX_LITTLENUMS
* sizeof (LITTLENUM_TYPE
));
5644 /* Look for a raw floating point number. */
5645 if ((save_in
= atof_ieee (*str
, 'x', words
)) != NULL
5646 && is_end_of_line
[(unsigned char) *save_in
])
5648 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
5650 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
5652 if (words
[j
] != fp_values
[i
][j
])
5656 if (j
== MAX_LITTLENUMS
)
5664 /* Try and parse a more complex expression, this will probably fail
5665 unless the code uses a floating point prefix (eg "0f"). */
5666 save_in
= input_line_pointer
;
5667 input_line_pointer
= *str
;
5668 if (expression (&exp
) == absolute_section
5669 && exp
.X_op
== O_big
5670 && exp
.X_add_number
< 0)
5672 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
5674 if (gen_to_words (words
, 5, (long) 15) == 0)
5676 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
5678 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
5680 if (words
[j
] != fp_values
[i
][j
])
5684 if (j
== MAX_LITTLENUMS
)
5686 *str
= input_line_pointer
;
5687 input_line_pointer
= save_in
;
5694 *str
= input_line_pointer
;
5695 input_line_pointer
= save_in
;
5699 /* We handle all bad expressions here, so that we can report the faulty
5700 instruction in the error message. */
5702 md_operand (expressionS
* expr
)
5704 if (in_my_get_expression
)
5706 expr
->X_op
= O_illegal
;
5707 if (inst
.error
== NULL
)
5708 inst
.error
= _("bad expression");
5712 /* Do those data_ops which can take a negative immediate constant
5713 by altering the instruction. A bit of a hack really.
5717 by inverting the second operand, and
5720 by negating the second operand. */
5723 negate_data_op (unsigned long * instruction
,
5724 unsigned long value
)
5727 unsigned long negated
, inverted
;
5729 negated
= validate_immediate (-value
);
5730 inverted
= validate_immediate (~value
);
5732 op
= (*instruction
>> DATA_OP_SHIFT
) & 0xf;
5735 /* First negates. */
5736 case OPCODE_SUB
: /* ADD <-> SUB */
5737 new_inst
= OPCODE_ADD
;
5742 new_inst
= OPCODE_SUB
;
5746 case OPCODE_CMP
: /* CMP <-> CMN */
5747 new_inst
= OPCODE_CMN
;
5752 new_inst
= OPCODE_CMP
;
5756 /* Now Inverted ops. */
5757 case OPCODE_MOV
: /* MOV <-> MVN */
5758 new_inst
= OPCODE_MVN
;
5763 new_inst
= OPCODE_MOV
;
5767 case OPCODE_AND
: /* AND <-> BIC */
5768 new_inst
= OPCODE_BIC
;
5773 new_inst
= OPCODE_AND
;
5777 case OPCODE_ADC
: /* ADC <-> SBC */
5778 new_inst
= OPCODE_SBC
;
5783 new_inst
= OPCODE_ADC
;
5787 /* We cannot do anything. */
5792 if (value
== (unsigned) FAIL
)
5795 *instruction
&= OPCODE_MASK
;
5796 *instruction
|= new_inst
<< DATA_OP_SHIFT
;
5801 data_op2 (char ** str
)
5806 skip_whitespace (* str
);
5808 if (reg_required_here (str
, 0) != FAIL
)
5810 if (skip_past_comma (str
) == SUCCESS
)
5811 /* Shift operation on register. */
5812 return decode_shift (str
, NO_SHIFT_RESTRICT
);
5818 /* Immediate expression. */
5819 if (is_immediate_prefix (**str
))
5824 if (my_get_expression (&inst
.reloc
.exp
, str
))
5827 if (inst
.reloc
.exp
.X_add_symbol
)
5829 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
5830 inst
.reloc
.pc_rel
= 0;
5834 if (skip_past_comma (str
) == SUCCESS
)
5836 /* #x, y -- ie explicit rotation by Y. */
5837 if (my_get_expression (&expr
, str
))
5840 if (expr
.X_op
!= O_constant
)
5842 inst
.error
= _("constant expression expected");
5846 /* Rotate must be a multiple of 2. */
5847 if (((unsigned) expr
.X_add_number
) > 30
5848 || (expr
.X_add_number
& 1) != 0
5849 || ((unsigned) inst
.reloc
.exp
.X_add_number
) > 255)
5851 inst
.error
= _("invalid constant");
5854 inst
.instruction
|= INST_IMMEDIATE
;
5855 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
5856 inst
.instruction
|= expr
.X_add_number
<< 7;
5860 /* Implicit rotation, select a suitable one. */
5861 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
5865 /* Can't be done. Perhaps the code reads something like
5866 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
5867 if ((value
= negate_data_op (&inst
.instruction
,
5868 inst
.reloc
.exp
.X_add_number
))
5871 inst
.error
= _("invalid constant");
5876 inst
.instruction
|= value
;
5879 inst
.instruction
|= INST_IMMEDIATE
;
5884 inst
.error
= _("register or shift expression expected");
5890 fp_op2 (char ** str
)
5892 skip_whitespace (* str
);
5894 if (fp_reg_required_here (str
, 0) != FAIL
)
5898 /* Immediate expression. */
5899 if (*((*str
)++) == '#')
5905 skip_whitespace (* str
);
5907 /* First try and match exact strings, this is to guarantee
5908 that some formats will work even for cross assembly. */
5910 for (i
= 0; fp_const
[i
]; i
++)
5912 if (strncmp (*str
, fp_const
[i
], strlen (fp_const
[i
])) == 0)
5916 *str
+= strlen (fp_const
[i
]);
5917 if (is_end_of_line
[(unsigned char) **str
])
5919 inst
.instruction
|= i
+ 8;
5926 /* Just because we didn't get a match doesn't mean that the
5927 constant isn't valid, just that it is in a format that we
5928 don't automatically recognize. Try parsing it with
5929 the standard expression routines. */
5930 if ((i
= my_get_float_expression (str
)) >= 0)
5932 inst
.instruction
|= i
+ 8;
5936 inst
.error
= _("invalid floating point immediate expression");
5940 _("floating point register or immediate expression expected");
5946 do_arit (char * str
)
5948 skip_whitespace (str
);
5950 if (reg_required_here (&str
, 12) == FAIL
5951 || skip_past_comma (&str
) == FAIL
5952 || reg_required_here (&str
, 16) == FAIL
5953 || skip_past_comma (&str
) == FAIL
5954 || data_op2 (&str
) == FAIL
)
5957 inst
.error
= BAD_ARGS
;
5967 /* This is a pseudo-op of the form "adr rd, label" to be converted
5968 into a relative address of the form "add rd, pc, #label-.-8". */
5969 skip_whitespace (str
);
5971 if (reg_required_here (&str
, 12) == FAIL
5972 || skip_past_comma (&str
) == FAIL
5973 || my_get_expression (&inst
.reloc
.exp
, &str
))
5976 inst
.error
= BAD_ARGS
;
5980 /* Frag hacking will turn this into a sub instruction if the offset turns
5981 out to be negative. */
5982 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
5984 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust. */
5986 inst
.reloc
.pc_rel
= 1;
5992 do_adrl (char * str
)
5994 /* This is a pseudo-op of the form "adrl rd, label" to be converted
5995 into a relative address of the form:
5996 add rd, pc, #low(label-.-8)"
5997 add rd, rd, #high(label-.-8)" */
5999 skip_whitespace (str
);
6001 if (reg_required_here (&str
, 12) == FAIL
6002 || skip_past_comma (&str
) == FAIL
6003 || my_get_expression (&inst
.reloc
.exp
, &str
))
6006 inst
.error
= BAD_ARGS
;
6012 /* Frag hacking will turn this into a sub instruction if the offset turns
6013 out to be negative. */
6014 inst
.reloc
.type
= BFD_RELOC_ARM_ADRL_IMMEDIATE
;
6016 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust */
6018 inst
.reloc
.pc_rel
= 1;
6019 inst
.size
= INSN_SIZE
* 2;
6025 skip_whitespace (str
);
6027 if (reg_required_here (&str
, 16) == FAIL
)
6030 inst
.error
= BAD_ARGS
;
6034 if (skip_past_comma (&str
) == FAIL
6035 || data_op2 (&str
) == FAIL
)
6038 inst
.error
= BAD_ARGS
;
6048 skip_whitespace (str
);
6050 if (reg_required_here (&str
, 12) == FAIL
)
6053 inst
.error
= BAD_ARGS
;
6057 if (skip_past_comma (&str
) == FAIL
6058 || data_op2 (&str
) == FAIL
)
6061 inst
.error
= BAD_ARGS
;
6069 do_ldst (char * str
)
6075 skip_whitespace (str
);
6077 if ((conflict_reg
= reg_required_here (&str
, 12)) == FAIL
)
6080 inst
.error
= BAD_ARGS
;
6084 if (skip_past_comma (&str
) == FAIL
)
6086 inst
.error
= _("address expected");
6096 skip_whitespace (str
);
6098 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6101 /* Conflicts can occur on stores as well as loads. */
6102 conflict_reg
= (conflict_reg
== reg
);
6104 skip_whitespace (str
);
6110 if (skip_past_comma (&str
) == SUCCESS
)
6112 /* [Rn],... (post inc) */
6113 if (ldst_extend (&str
) == FAIL
)
6116 as_warn (_("%s register same as write-back base"),
6117 ((inst
.instruction
& LOAD_BIT
)
6118 ? _("destination") : _("source")));
6123 skip_whitespace (str
);
6128 as_warn (_("%s register same as write-back base"),
6129 ((inst
.instruction
& LOAD_BIT
)
6130 ? _("destination") : _("source")));
6132 inst
.instruction
|= WRITE_BACK
;
6135 inst
.instruction
|= INDEX_UP
;
6142 if (skip_past_comma (&str
) == FAIL
)
6144 inst
.error
= _("pre-indexed expression expected");
6149 if (ldst_extend (&str
) == FAIL
)
6152 skip_whitespace (str
);
6156 inst
.error
= _("missing ]");
6160 skip_whitespace (str
);
6165 as_warn (_("%s register same as write-back base"),
6166 ((inst
.instruction
& LOAD_BIT
)
6167 ? _("destination") : _("source")));
6169 inst
.instruction
|= WRITE_BACK
;
6173 else if (*str
== '=')
6175 if ((inst
.instruction
& LOAD_BIT
) == 0)
6177 inst
.error
= _("invalid pseudo operation");
6181 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6184 skip_whitespace (str
);
6186 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6189 if (inst
.reloc
.exp
.X_op
!= O_constant
6190 && inst
.reloc
.exp
.X_op
!= O_symbol
)
6192 inst
.error
= _("constant expression expected");
6196 if (inst
.reloc
.exp
.X_op
== O_constant
)
6198 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
6202 /* This can be done with a mov instruction. */
6203 inst
.instruction
&= LITERAL_MASK
;
6204 inst
.instruction
|= (INST_IMMEDIATE
6205 | (OPCODE_MOV
<< DATA_OP_SHIFT
));
6206 inst
.instruction
|= value
& 0xfff;
6211 value
= validate_immediate (~inst
.reloc
.exp
.X_add_number
);
6215 /* This can be done with a mvn instruction. */
6216 inst
.instruction
&= LITERAL_MASK
;
6217 inst
.instruction
|= (INST_IMMEDIATE
6218 | (OPCODE_MVN
<< DATA_OP_SHIFT
));
6219 inst
.instruction
|= value
& 0xfff;
6225 /* Insert into literal pool. */
6226 if (add_to_lit_pool () == FAIL
)
6229 inst
.error
= _("literal pool insertion failed");
6233 /* Change the instruction exp to point to the pool. */
6234 inst
.reloc
.type
= BFD_RELOC_ARM_LITERAL
;
6235 inst
.reloc
.pc_rel
= 1;
6236 inst
.instruction
|= (REG_PC
<< 16);
6241 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6244 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
6246 /* PC rel adjust. */
6247 inst
.reloc
.exp
.X_add_number
-= 8;
6249 inst
.reloc
.pc_rel
= 1;
6250 inst
.instruction
|= (REG_PC
<< 16);
6254 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
6259 do_ldstt (char * str
)
6263 skip_whitespace (str
);
6265 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
6268 inst
.error
= BAD_ARGS
;
6272 if (skip_past_comma (& str
) == FAIL
)
6274 inst
.error
= _("address expected");
6284 skip_whitespace (str
);
6286 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6289 /* ldrt/strt always use post-indexed addressing, so if the base is
6290 the same as Rd, we warn. */
6291 if (conflict_reg
== reg
)
6292 as_warn (_("%s register same as write-back base"),
6293 ((inst
.instruction
& LOAD_BIT
)
6294 ? _("destination") : _("source")));
6296 skip_whitespace (str
);
6302 if (skip_past_comma (&str
) == SUCCESS
)
6304 /* [Rn],... (post inc) */
6305 if (ldst_extend (&str
) == FAIL
)
6311 skip_whitespace (str
);
6313 /* Skip a write-back '!'. */
6317 inst
.instruction
|= INDEX_UP
;
6322 inst
.error
= _("post-indexed expression expected");
6328 inst
.error
= _("post-indexed expression expected");
6335 /* Halfword and signed-byte load/store operations. */
6338 do_ldstv4 (char * str
)
6344 skip_whitespace (str
);
6346 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
6349 inst
.error
= BAD_ARGS
;
6353 if (skip_past_comma (& str
) == FAIL
)
6355 inst
.error
= _("address expected");
6365 skip_whitespace (str
);
6367 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6370 /* Conflicts can occur on stores as well as loads. */
6371 conflict_reg
= (conflict_reg
== reg
);
6373 skip_whitespace (str
);
6379 if (skip_past_comma (&str
) == SUCCESS
)
6381 /* [Rn],... (post inc) */
6382 if (ldst_extend_v4 (&str
) == FAIL
)
6385 as_warn (_("%s register same as write-back base"),
6386 ((inst
.instruction
& LOAD_BIT
)
6387 ? _("destination") : _("source")));
6392 inst
.instruction
|= HWOFFSET_IMM
;
6394 skip_whitespace (str
);
6399 as_warn (_("%s register same as write-back base"),
6400 ((inst
.instruction
& LOAD_BIT
)
6401 ? _("destination") : _("source")));
6403 inst
.instruction
|= WRITE_BACK
;
6406 inst
.instruction
|= INDEX_UP
;
6413 if (skip_past_comma (&str
) == FAIL
)
6415 inst
.error
= _("pre-indexed expression expected");
6420 if (ldst_extend_v4 (&str
) == FAIL
)
6423 skip_whitespace (str
);
6427 inst
.error
= _("missing ]");
6431 skip_whitespace (str
);
6436 as_warn (_("%s register same as write-back base"),
6437 ((inst
.instruction
& LOAD_BIT
)
6438 ? _("destination") : _("source")));
6440 inst
.instruction
|= WRITE_BACK
;
6444 else if (*str
== '=')
6446 if ((inst
.instruction
& LOAD_BIT
) == 0)
6448 inst
.error
= _("invalid pseudo operation");
6452 /* XXX Does this work correctly for half-word/byte ops? */
6453 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6456 skip_whitespace (str
);
6458 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6461 if (inst
.reloc
.exp
.X_op
!= O_constant
6462 && inst
.reloc
.exp
.X_op
!= O_symbol
)
6464 inst
.error
= _("constant expression expected");
6468 if (inst
.reloc
.exp
.X_op
== O_constant
)
6470 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
6474 /* This can be done with a mov instruction. */
6475 inst
.instruction
&= LITERAL_MASK
;
6476 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MOV
<< DATA_OP_SHIFT
);
6477 inst
.instruction
|= value
& 0xfff;
6482 value
= validate_immediate (~ inst
.reloc
.exp
.X_add_number
);
6486 /* This can be done with a mvn instruction. */
6487 inst
.instruction
&= LITERAL_MASK
;
6488 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MVN
<< DATA_OP_SHIFT
);
6489 inst
.instruction
|= value
& 0xfff;
6495 /* Insert into literal pool. */
6496 if (add_to_lit_pool () == FAIL
)
6499 inst
.error
= _("literal pool insertion failed");
6503 /* Change the instruction exp to point to the pool. */
6504 inst
.instruction
|= HWOFFSET_IMM
;
6505 inst
.reloc
.type
= BFD_RELOC_ARM_HWLITERAL
;
6506 inst
.reloc
.pc_rel
= 1;
6507 inst
.instruction
|= (REG_PC
<< 16);
6512 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6515 inst
.instruction
|= HWOFFSET_IMM
;
6516 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
6518 /* PC rel adjust. */
6519 inst
.reloc
.exp
.X_add_number
-= 8;
6521 inst
.reloc
.pc_rel
= 1;
6522 inst
.instruction
|= (REG_PC
<< 16);
6526 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
6531 reg_list (char ** strp
)
6533 char * str
= * strp
;
6537 /* We come back here if we get ranges concatenated by '+' or '|'. */
6552 skip_whitespace (str
);
6554 if ((reg
= reg_required_here (& str
, -1)) == FAIL
)
6563 inst
.error
= _("bad range in register list");
6567 for (i
= cur_reg
+ 1; i
< reg
; i
++)
6569 if (range
& (1 << i
))
6571 (_("Warning: duplicated register (r%d) in register list"),
6579 if (range
& (1 << reg
))
6580 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
6582 else if (reg
<= cur_reg
)
6583 as_tsktsk (_("Warning: register range not in ascending order"));
6588 while (skip_past_comma (&str
) != FAIL
6589 || (in_range
= 1, *str
++ == '-'));
6591 skip_whitespace (str
);
6595 inst
.error
= _("missing `}'");
6603 if (my_get_expression (&expr
, &str
))
6606 if (expr
.X_op
== O_constant
)
6608 if (expr
.X_add_number
6609 != (expr
.X_add_number
& 0x0000ffff))
6611 inst
.error
= _("invalid register mask");
6615 if ((range
& expr
.X_add_number
) != 0)
6617 int regno
= range
& expr
.X_add_number
;
6620 regno
= (1 << regno
) - 1;
6622 (_("Warning: duplicated register (r%d) in register list"),
6626 range
|= expr
.X_add_number
;
6630 if (inst
.reloc
.type
!= 0)
6632 inst
.error
= _("expression too complex");
6636 memcpy (&inst
.reloc
.exp
, &expr
, sizeof (expressionS
));
6637 inst
.reloc
.type
= BFD_RELOC_ARM_MULTI
;
6638 inst
.reloc
.pc_rel
= 0;
6642 skip_whitespace (str
);
6644 if (*str
== '|' || *str
== '+')
6650 while (another_range
);
6657 do_ldmstm (char * str
)
6662 skip_whitespace (str
);
6664 if ((base_reg
= reg_required_here (&str
, 16)) == FAIL
)
6667 if (base_reg
== REG_PC
)
6669 inst
.error
= _("r15 not allowed as base register");
6673 skip_whitespace (str
);
6677 inst
.instruction
|= WRITE_BACK
;
6681 if (skip_past_comma (&str
) == FAIL
6682 || (range
= reg_list (&str
)) == FAIL
)
6685 inst
.error
= BAD_ARGS
;
6692 inst
.instruction
|= LDM_TYPE_2_OR_3
;
6695 if (inst
.instruction
& WRITE_BACK
)
6697 /* Check for unpredictable uses of writeback. */
6698 if (inst
.instruction
& LOAD_BIT
)
6700 /* Not allowed in LDM type 2. */
6701 if ((inst
.instruction
& LDM_TYPE_2_OR_3
)
6702 && ((range
& (1 << REG_PC
)) == 0))
6703 as_warn (_("writeback of base register is UNPREDICTABLE"));
6704 /* Only allowed if base reg not in list for other types. */
6705 else if (range
& (1 << base_reg
))
6706 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
6710 /* Not allowed for type 2. */
6711 if (inst
.instruction
& LDM_TYPE_2_OR_3
)
6712 as_warn (_("writeback of base register is UNPREDICTABLE"));
6713 /* Only allowed if base reg not in list, or first in list. */
6714 else if ((range
& (1 << base_reg
))
6715 && (range
& ((1 << base_reg
) - 1)))
6716 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
6720 inst
.instruction
|= range
;
6727 skip_whitespace (str
);
6729 /* Allow optional leading '#'. */
6730 if (is_immediate_prefix (*str
))
6733 if (my_get_expression (& inst
.reloc
.exp
, & str
))
6736 inst
.reloc
.type
= BFD_RELOC_ARM_SMI
;
6737 inst
.reloc
.pc_rel
= 0;
6744 skip_whitespace (str
);
6746 /* Allow optional leading '#'. */
6747 if (is_immediate_prefix (*str
))
6750 if (my_get_expression (& inst
.reloc
.exp
, & str
))
6753 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
6754 inst
.reloc
.pc_rel
= 0;
6759 do_swap (char * str
)
6763 skip_whitespace (str
);
6765 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
6770 inst
.error
= _("r15 not allowed in swap");
6774 if (skip_past_comma (&str
) == FAIL
6775 || (reg
= reg_required_here (&str
, 0)) == FAIL
)
6778 inst
.error
= BAD_ARGS
;
6784 inst
.error
= _("r15 not allowed in swap");
6788 if (skip_past_comma (&str
) == FAIL
6791 inst
.error
= BAD_ARGS
;
6795 skip_whitespace (str
);
6797 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6802 inst
.error
= BAD_PC
;
6806 skip_whitespace (str
);
6810 inst
.error
= _("missing ]");
6818 do_branch (char * str
)
6820 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6827 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
6828 required for the instruction. */
6830 /* arm_parse_reloc () works on input_line_pointer.
6831 We actually want to parse the operands to the branch instruction
6832 passed in 'str'. Save the input pointer and restore it later. */
6833 save_in
= input_line_pointer
;
6834 input_line_pointer
= str
;
6835 if (inst
.reloc
.exp
.X_op
== O_symbol
6837 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
6839 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
6840 inst
.reloc
.pc_rel
= 0;
6841 /* Modify str to point to after parsed operands, otherwise
6842 end_of_line() will complain about the (PLT) left in str. */
6843 str
= input_line_pointer
;
6847 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
6848 inst
.reloc
.pc_rel
= 1;
6850 input_line_pointer
= save_in
;
6853 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
6854 inst
.reloc
.pc_rel
= 1;
6855 #endif /* OBJ_ELF */
6863 /* Co-processor data operation.
6864 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
6865 skip_whitespace (str
);
6867 if (co_proc_number (&str
) == FAIL
)
6870 inst
.error
= BAD_ARGS
;
6874 if (skip_past_comma (&str
) == FAIL
6875 || cp_opc_expr (&str
, 20,4) == FAIL
)
6878 inst
.error
= BAD_ARGS
;
6882 if (skip_past_comma (&str
) == FAIL
6883 || cp_reg_required_here (&str
, 12) == FAIL
)
6886 inst
.error
= BAD_ARGS
;
6890 if (skip_past_comma (&str
) == FAIL
6891 || cp_reg_required_here (&str
, 16) == FAIL
)
6894 inst
.error
= BAD_ARGS
;
6898 if (skip_past_comma (&str
) == FAIL
6899 || cp_reg_required_here (&str
, 0) == FAIL
)
6902 inst
.error
= BAD_ARGS
;
6906 if (skip_past_comma (&str
) == SUCCESS
)
6908 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
6911 inst
.error
= BAD_ARGS
;
6920 do_lstc (char * str
)
6922 /* Co-processor register load/store.
6923 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
6925 skip_whitespace (str
);
6927 if (co_proc_number (&str
) == FAIL
)
6930 inst
.error
= BAD_ARGS
;
6934 if (skip_past_comma (&str
) == FAIL
6935 || cp_reg_required_here (&str
, 12) == FAIL
)
6938 inst
.error
= BAD_ARGS
;
6942 if (skip_past_comma (&str
) == FAIL
6943 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
6946 inst
.error
= BAD_ARGS
;
6954 do_co_reg (char * str
)
6956 /* Co-processor register transfer.
6957 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
6959 skip_whitespace (str
);
6961 if (co_proc_number (&str
) == FAIL
)
6964 inst
.error
= BAD_ARGS
;
6968 if (skip_past_comma (&str
) == FAIL
6969 || cp_opc_expr (&str
, 21, 3) == FAIL
)
6972 inst
.error
= BAD_ARGS
;
6976 if (skip_past_comma (&str
) == FAIL
6977 || reg_required_here (&str
, 12) == FAIL
)
6980 inst
.error
= BAD_ARGS
;
6984 if (skip_past_comma (&str
) == FAIL
6985 || cp_reg_required_here (&str
, 16) == FAIL
)
6988 inst
.error
= BAD_ARGS
;
6992 if (skip_past_comma (&str
) == FAIL
6993 || cp_reg_required_here (&str
, 0) == FAIL
)
6996 inst
.error
= BAD_ARGS
;
7000 if (skip_past_comma (&str
) == SUCCESS
)
7002 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
7005 inst
.error
= BAD_ARGS
;
7014 do_fpa_ctrl (char * str
)
7016 /* FP control registers.
7017 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
7019 skip_whitespace (str
);
7021 if (reg_required_here (&str
, 12) == FAIL
)
7024 inst
.error
= BAD_ARGS
;
7032 do_fpa_ldst (char * str
)
7034 skip_whitespace (str
);
7036 if (fp_reg_required_here (&str
, 12) == FAIL
)
7039 inst
.error
= BAD_ARGS
;
7043 if (skip_past_comma (&str
) == FAIL
7044 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
7047 inst
.error
= BAD_ARGS
;
7055 do_fpa_ldmstm (char * str
)
7059 skip_whitespace (str
);
7061 if (fp_reg_required_here (&str
, 12) == FAIL
)
7064 inst
.error
= BAD_ARGS
;
7068 /* Get Number of registers to transfer. */
7069 if (skip_past_comma (&str
) == FAIL
7070 || my_get_expression (&inst
.reloc
.exp
, &str
))
7073 inst
.error
= _("constant expression expected");
7077 if (inst
.reloc
.exp
.X_op
!= O_constant
)
7079 inst
.error
= _("constant value required for number of registers");
7083 num_regs
= inst
.reloc
.exp
.X_add_number
;
7085 if (num_regs
< 1 || num_regs
> 4)
7087 inst
.error
= _("number of registers must be in the range [1:4]");
7094 inst
.instruction
|= CP_T_X
;
7097 inst
.instruction
|= CP_T_Y
;
7100 inst
.instruction
|= CP_T_Y
| CP_T_X
;
7108 if (inst
.instruction
& (CP_T_Pre
| CP_T_UD
)) /* ea/fd format. */
7114 /* The instruction specified "ea" or "fd", so we can only accept
7115 [Rn]{!}. The instruction does not really support stacking or
7116 unstacking, so we have to emulate these by setting appropriate
7117 bits and offsets. */
7118 if (skip_past_comma (&str
) == FAIL
7122 inst
.error
= BAD_ARGS
;
7127 skip_whitespace (str
);
7129 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
7132 skip_whitespace (str
);
7136 inst
.error
= BAD_ARGS
;
7148 _("r15 not allowed as base register with write-back");
7155 if (inst
.instruction
& CP_T_Pre
)
7157 /* Pre-decrement. */
7158 offset
= 3 * num_regs
;
7160 inst
.instruction
|= CP_T_WB
;
7164 /* Post-increment. */
7167 inst
.instruction
|= CP_T_WB
;
7168 offset
= 3 * num_regs
;
7172 /* No write-back, so convert this into a standard pre-increment
7173 instruction -- aesthetically more pleasing. */
7174 inst
.instruction
|= CP_T_Pre
| CP_T_UD
;
7179 inst
.instruction
|= offset
;
7181 else if (skip_past_comma (&str
) == FAIL
7182 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
7185 inst
.error
= BAD_ARGS
;
7193 do_fpa_dyadic (char * str
)
7195 skip_whitespace (str
);
7197 if (fp_reg_required_here (&str
, 12) == FAIL
)
7200 inst
.error
= BAD_ARGS
;
7204 if (skip_past_comma (&str
) == FAIL
7205 || fp_reg_required_here (&str
, 16) == FAIL
)
7208 inst
.error
= BAD_ARGS
;
7212 if (skip_past_comma (&str
) == FAIL
7213 || fp_op2 (&str
) == FAIL
)
7216 inst
.error
= BAD_ARGS
;
7224 do_fpa_monadic (char * str
)
7226 skip_whitespace (str
);
7228 if (fp_reg_required_here (&str
, 12) == FAIL
)
7231 inst
.error
= BAD_ARGS
;
7235 if (skip_past_comma (&str
) == FAIL
7236 || fp_op2 (&str
) == FAIL
)
7239 inst
.error
= BAD_ARGS
;
7247 do_fpa_cmp (char * str
)
7249 skip_whitespace (str
);
7251 if (fp_reg_required_here (&str
, 16) == FAIL
)
7254 inst
.error
= BAD_ARGS
;
7258 if (skip_past_comma (&str
) == FAIL
7259 || fp_op2 (&str
) == FAIL
)
7262 inst
.error
= BAD_ARGS
;
7270 do_fpa_from_reg (char * str
)
7272 skip_whitespace (str
);
7274 if (fp_reg_required_here (&str
, 16) == FAIL
)
7277 inst
.error
= BAD_ARGS
;
7281 if (skip_past_comma (&str
) == FAIL
7282 || reg_required_here (&str
, 12) == FAIL
)
7285 inst
.error
= BAD_ARGS
;
7293 do_fpa_to_reg (char * str
)
7295 skip_whitespace (str
);
7297 if (reg_required_here (&str
, 12) == FAIL
)
7300 if (skip_past_comma (&str
) == FAIL
7301 || fp_reg_required_here (&str
, 0) == FAIL
)
7304 inst
.error
= BAD_ARGS
;
7311 /* Encode a VFP SP register number. */
7314 vfp_sp_encode_reg (int reg
, enum vfp_sp_reg_pos pos
)
7319 inst
.instruction
|= ((reg
>> 1) << 12) | ((reg
& 1) << 22);
7323 inst
.instruction
|= ((reg
>> 1) << 16) | ((reg
& 1) << 7);
7327 inst
.instruction
|= ((reg
>> 1) << 0) | ((reg
& 1) << 5);
7336 vfp_sp_reg_required_here (char ** str
,
7337 enum vfp_sp_reg_pos pos
)
7340 char * start
= *str
;
7342 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_SN
].htab
)) != FAIL
)
7344 vfp_sp_encode_reg (reg
, pos
);
7348 /* In the few cases where we might be able to accept something else
7349 this error can be overridden. */
7350 inst
.error
= _(all_reg_maps
[REG_TYPE_SN
].expected
);
7352 /* Restore the start point. */
7358 vfp_dp_reg_required_here (char ** str
,
7359 enum vfp_dp_reg_pos pos
)
7362 char * start
= *str
;
7364 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_DN
].htab
)) != FAIL
)
7369 inst
.instruction
|= reg
<< 12;
7373 inst
.instruction
|= reg
<< 16;
7377 inst
.instruction
|= reg
<< 0;
7386 /* In the few cases where we might be able to accept something else
7387 this error can be overridden. */
7388 inst
.error
= _(all_reg_maps
[REG_TYPE_DN
].expected
);
7390 /* Restore the start point. */
7396 do_vfp_sp_monadic (char * str
)
7398 skip_whitespace (str
);
7400 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7403 if (skip_past_comma (&str
) == FAIL
7404 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
7407 inst
.error
= BAD_ARGS
;
7415 do_vfp_dp_monadic (char * str
)
7417 skip_whitespace (str
);
7419 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7422 if (skip_past_comma (&str
) == FAIL
7423 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7426 inst
.error
= BAD_ARGS
;
7434 do_vfp_sp_dyadic (char * str
)
7436 skip_whitespace (str
);
7438 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7441 if (skip_past_comma (&str
) == FAIL
7442 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
7443 || skip_past_comma (&str
) == FAIL
7444 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
7447 inst
.error
= BAD_ARGS
;
7455 do_vfp_dp_dyadic (char * str
)
7457 skip_whitespace (str
);
7459 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7462 if (skip_past_comma (&str
) == FAIL
7463 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
7464 || skip_past_comma (&str
) == FAIL
7465 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7468 inst
.error
= BAD_ARGS
;
7476 do_vfp_reg_from_sp (char * str
)
7478 skip_whitespace (str
);
7480 if (reg_required_here (&str
, 12) == FAIL
)
7483 if (skip_past_comma (&str
) == FAIL
7484 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
7487 inst
.error
= BAD_ARGS
;
7494 /* Parse a VFP register list. If the string is invalid return FAIL.
7495 Otherwise return the number of registers, and set PBASE to the first
7496 register. Double precision registers are matched if DP is nonzero. */
7499 vfp_parse_reg_list (char **str
, int *pbase
, int dp
)
7507 unsigned long mask
= 0;
7514 skip_whitespace (*str
);
7518 regtype
= REG_TYPE_DN
;
7523 regtype
= REG_TYPE_SN
;
7527 base_reg
= max_regs
;
7531 new_base
= arm_reg_parse (str
, all_reg_maps
[regtype
].htab
);
7532 if (new_base
== FAIL
)
7534 inst
.error
= _(all_reg_maps
[regtype
].expected
);
7538 if (new_base
< base_reg
)
7539 base_reg
= new_base
;
7541 if (mask
& (1 << new_base
))
7543 inst
.error
= _("invalid register list");
7547 if ((mask
>> new_base
) != 0 && ! warned
)
7549 as_tsktsk (_("register list not in ascending order"));
7553 mask
|= 1 << new_base
;
7556 skip_whitespace (*str
);
7558 if (**str
== '-') /* We have the start of a range expression */
7565 = arm_reg_parse (str
, all_reg_maps
[regtype
].htab
))
7568 inst
.error
= _(all_reg_maps
[regtype
].expected
);
7572 if (high_range
<= new_base
)
7574 inst
.error
= _("register range not in ascending order");
7578 for (new_base
++; new_base
<= high_range
; new_base
++)
7580 if (mask
& (1 << new_base
))
7582 inst
.error
= _("invalid register list");
7586 mask
|= 1 << new_base
;
7591 while (skip_past_comma (str
) != FAIL
);
7595 /* Sanity check -- should have raised a parse error above. */
7596 if (count
== 0 || count
> max_regs
)
7601 /* Final test -- the registers must be consecutive. */
7603 for (i
= 0; i
< count
; i
++)
7605 if ((mask
& (1u << i
)) == 0)
7607 inst
.error
= _("non-contiguous register range");
7616 do_vfp_reg2_from_sp2 (char * str
)
7620 skip_whitespace (str
);
7622 if (reg_required_here (&str
, 12) == FAIL
7623 || skip_past_comma (&str
) == FAIL
7624 || reg_required_here (&str
, 16) == FAIL
7625 || skip_past_comma (&str
) == FAIL
)
7628 inst
.error
= BAD_ARGS
;
7632 /* We require exactly two consecutive SP registers. */
7633 if (vfp_parse_reg_list (&str
, ®
, 0) != 2)
7636 inst
.error
= _("only two consecutive VFP SP registers allowed here");
7638 vfp_sp_encode_reg (reg
, VFP_REG_Sm
);
7644 do_vfp_sp_from_reg (char * str
)
7646 skip_whitespace (str
);
7648 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
7651 if (skip_past_comma (&str
) == FAIL
7652 || reg_required_here (&str
, 12) == FAIL
)
7655 inst
.error
= BAD_ARGS
;
7663 do_vfp_sp2_from_reg2 (char * str
)
7667 skip_whitespace (str
);
7669 /* We require exactly two consecutive SP registers. */
7670 if (vfp_parse_reg_list (&str
, ®
, 0) != 2)
7673 inst
.error
= _("only two consecutive VFP SP registers allowed here");
7675 vfp_sp_encode_reg (reg
, VFP_REG_Sm
);
7677 if (skip_past_comma (&str
) == FAIL
7678 || reg_required_here (&str
, 12) == FAIL
7679 || skip_past_comma (&str
) == FAIL
7680 || reg_required_here (&str
, 16) == FAIL
)
7683 inst
.error
= BAD_ARGS
;
7691 do_vfp_reg_from_dp (char * str
)
7693 skip_whitespace (str
);
7695 if (reg_required_here (&str
, 12) == FAIL
)
7698 if (skip_past_comma (&str
) == FAIL
7699 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
7702 inst
.error
= BAD_ARGS
;
7710 do_vfp_reg2_from_dp (char * str
)
7712 skip_whitespace (str
);
7714 if (reg_required_here (&str
, 12) == FAIL
)
7717 if (skip_past_comma (&str
) == FAIL
7718 || reg_required_here (&str
, 16) == FAIL
7719 || skip_past_comma (&str
) == FAIL
7720 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7723 inst
.error
= BAD_ARGS
;
7731 do_vfp_dp_from_reg (char * str
)
7733 skip_whitespace (str
);
7735 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
7738 if (skip_past_comma (&str
) == FAIL
7739 || reg_required_here (&str
, 12) == FAIL
)
7742 inst
.error
= BAD_ARGS
;
7750 do_vfp_dp_from_reg2 (char * str
)
7752 skip_whitespace (str
);
7754 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7757 if (skip_past_comma (&str
) == FAIL
7758 || reg_required_here (&str
, 12) == FAIL
7759 || skip_past_comma (&str
) == FAIL
7760 || reg_required_here (&str
, 16) == FAIL
)
7763 inst
.error
= BAD_ARGS
;
7770 static const struct vfp_reg
*
7771 vfp_psr_parse (char ** str
)
7776 const struct vfp_reg
*vreg
;
7780 /* Find the end of the current token. */
7785 while (ISALPHA (c
));
7790 for (vreg
= vfp_regs
+ 0;
7791 vreg
< vfp_regs
+ sizeof (vfp_regs
) / sizeof (struct vfp_reg
);
7794 if (streq (start
, vreg
->name
))
7807 vfp_psr_required_here (char ** str
)
7810 const struct vfp_reg
*vreg
;
7812 vreg
= vfp_psr_parse (str
);
7816 inst
.instruction
|= vreg
->regno
;
7820 inst
.error
= _("VFP system register expected");
7827 do_vfp_reg_from_ctrl (char * str
)
7829 skip_whitespace (str
);
7831 if (reg_required_here (&str
, 12) == FAIL
)
7834 if (skip_past_comma (&str
) == FAIL
7835 || vfp_psr_required_here (&str
) == FAIL
)
7838 inst
.error
= BAD_ARGS
;
7846 do_vfp_ctrl_from_reg (char * str
)
7848 skip_whitespace (str
);
7850 if (vfp_psr_required_here (&str
) == FAIL
)
7853 if (skip_past_comma (&str
) == FAIL
7854 || reg_required_here (&str
, 12) == FAIL
)
7857 inst
.error
= BAD_ARGS
;
7865 do_vfp_sp_ldst (char * str
)
7867 skip_whitespace (str
);
7869 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7872 inst
.error
= BAD_ARGS
;
7876 if (skip_past_comma (&str
) == FAIL
7877 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
7880 inst
.error
= BAD_ARGS
;
7888 do_vfp_dp_ldst (char * str
)
7890 skip_whitespace (str
);
7892 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7895 inst
.error
= BAD_ARGS
;
7899 if (skip_past_comma (&str
) == FAIL
7900 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
7903 inst
.error
= BAD_ARGS
;
7912 vfp_sp_ldstm (char * str
, enum vfp_ldstm_type ldstm_type
)
7917 skip_whitespace (str
);
7919 if (reg_required_here (&str
, 16) == FAIL
)
7922 skip_whitespace (str
);
7926 inst
.instruction
|= WRITE_BACK
;
7929 else if (ldstm_type
!= VFP_LDSTMIA
)
7931 inst
.error
= _("this addressing mode requires base-register writeback");
7935 if (skip_past_comma (&str
) == FAIL
7936 || (count
= vfp_parse_reg_list (&str
, ®
, 0)) == FAIL
)
7939 inst
.error
= BAD_ARGS
;
7942 vfp_sp_encode_reg (reg
, VFP_REG_Sd
);
7944 inst
.instruction
|= count
;
7949 vfp_dp_ldstm (char * str
, enum vfp_ldstm_type ldstm_type
)
7954 skip_whitespace (str
);
7956 if (reg_required_here (&str
, 16) == FAIL
)
7959 skip_whitespace (str
);
7963 inst
.instruction
|= WRITE_BACK
;
7966 else if (ldstm_type
!= VFP_LDSTMIA
&& ldstm_type
!= VFP_LDSTMIAX
)
7968 inst
.error
= _("this addressing mode requires base-register writeback");
7972 if (skip_past_comma (&str
) == FAIL
7973 || (count
= vfp_parse_reg_list (&str
, ®
, 1)) == FAIL
)
7976 inst
.error
= BAD_ARGS
;
7981 if (ldstm_type
== VFP_LDSTMIAX
|| ldstm_type
== VFP_LDSTMDBX
)
7984 inst
.instruction
|= (reg
<< 12) | count
;
7989 do_vfp_sp_ldstmia (char * str
)
7991 vfp_sp_ldstm (str
, VFP_LDSTMIA
);
7995 do_vfp_sp_ldstmdb (char * str
)
7997 vfp_sp_ldstm (str
, VFP_LDSTMDB
);
8001 do_vfp_dp_ldstmia (char * str
)
8003 vfp_dp_ldstm (str
, VFP_LDSTMIA
);
8007 do_vfp_dp_ldstmdb (char * str
)
8009 vfp_dp_ldstm (str
, VFP_LDSTMDB
);
8013 do_vfp_xp_ldstmia (char *str
)
8015 vfp_dp_ldstm (str
, VFP_LDSTMIAX
);
8019 do_vfp_xp_ldstmdb (char * str
)
8021 vfp_dp_ldstm (str
, VFP_LDSTMDBX
);
8025 do_vfp_sp_compare_z (char * str
)
8027 skip_whitespace (str
);
8029 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8032 inst
.error
= BAD_ARGS
;
8040 do_vfp_dp_compare_z (char * str
)
8042 skip_whitespace (str
);
8044 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8047 inst
.error
= BAD_ARGS
;
8055 do_vfp_dp_sp_cvt (char * str
)
8057 skip_whitespace (str
);
8059 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8062 if (skip_past_comma (&str
) == FAIL
8063 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
8066 inst
.error
= BAD_ARGS
;
8074 do_vfp_sp_dp_cvt (char * str
)
8076 skip_whitespace (str
);
8078 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8081 if (skip_past_comma (&str
) == FAIL
8082 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
8085 inst
.error
= BAD_ARGS
;
8092 /* Thumb specific routines. */
8094 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
8098 thumb_add_sub (char * str
, int subtract
)
8100 int Rd
, Rs
, Rn
= FAIL
;
8102 skip_whitespace (str
);
8104 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
8105 || skip_past_comma (&str
) == FAIL
)
8108 inst
.error
= BAD_ARGS
;
8112 if (is_immediate_prefix (*str
))
8116 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8121 if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8124 if (skip_past_comma (&str
) == FAIL
)
8126 /* Two operand format, shuffle the registers
8127 and pretend there are 3. */
8131 else if (is_immediate_prefix (*str
))
8134 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8137 else if ((Rn
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8141 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8142 for the latter case, EXPR contains the immediate that was found. */
8145 /* All register format. */
8146 if (Rd
> 7 || Rs
> 7 || Rn
> 7)
8150 inst
.error
= _("dest and source1 must be the same register");
8154 /* Can't do this for SUB. */
8157 inst
.error
= _("subtract valid only on lo regs");
8161 inst
.instruction
= (T_OPCODE_ADD_HI
8162 | (Rd
> 7 ? THUMB_H1
: 0)
8163 | (Rn
> 7 ? THUMB_H2
: 0));
8164 inst
.instruction
|= (Rd
& 7) | ((Rn
& 7) << 3);
8168 inst
.instruction
= subtract
? T_OPCODE_SUB_R3
: T_OPCODE_ADD_R3
;
8169 inst
.instruction
|= Rd
| (Rs
<< 3) | (Rn
<< 6);
8174 /* Immediate expression, now things start to get nasty. */
8176 /* First deal with HI regs, only very restricted cases allowed:
8177 Adjusting SP, and using PC or SP to get an address. */
8178 if ((Rd
> 7 && (Rd
!= REG_SP
|| Rs
!= REG_SP
))
8179 || (Rs
> 7 && Rs
!= REG_SP
&& Rs
!= REG_PC
))
8181 inst
.error
= _("invalid Hi register with immediate");
8185 if (inst
.reloc
.exp
.X_op
!= O_constant
)
8187 /* Value isn't known yet, all we can do is store all the fragments
8188 we know about in the instruction and let the reloc hacking
8190 inst
.instruction
= (subtract
? 0x8000 : 0) | (Rd
<< 4) | Rs
;
8191 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
8195 int offset
= inst
.reloc
.exp
.X_add_number
;
8205 /* Quick check, in case offset is MIN_INT. */
8208 inst
.error
= _("immediate value out of range");
8212 /* Note - you cannot convert a subtract of 0 into an
8213 add of 0 because the carry flag is set differently. */
8214 else if (offset
> 0)
8219 if (offset
& ~0x1fc)
8221 inst
.error
= _("invalid immediate value for stack adjust");
8224 inst
.instruction
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
8225 inst
.instruction
|= offset
>> 2;
8227 else if (Rs
== REG_PC
|| Rs
== REG_SP
)
8230 || (offset
& ~0x3fc))
8232 inst
.error
= _("invalid immediate for address calculation");
8235 inst
.instruction
= (Rs
== REG_PC
? T_OPCODE_ADD_PC
8237 inst
.instruction
|= (Rd
<< 8) | (offset
>> 2);
8243 inst
.error
= _("immediate value out of range");
8246 inst
.instruction
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
8247 inst
.instruction
|= (Rd
<< 8) | offset
;
8253 inst
.error
= _("immediate value out of range");
8256 inst
.instruction
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
8257 inst
.instruction
|= Rd
| (Rs
<< 3) | (offset
<< 6);
8266 thumb_shift (char * str
, int shift
)
8268 int Rd
, Rs
, Rn
= FAIL
;
8270 skip_whitespace (str
);
8272 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
8273 || skip_past_comma (&str
) == FAIL
)
8276 inst
.error
= BAD_ARGS
;
8280 if (is_immediate_prefix (*str
))
8282 /* Two operand immediate format, set Rs to Rd. */
8285 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8290 if ((Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8293 if (skip_past_comma (&str
) == FAIL
)
8295 /* Two operand format, shuffle the registers
8296 and pretend there are 3. */
8300 else if (is_immediate_prefix (*str
))
8303 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8306 else if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8310 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8311 for the latter case, EXPR contains the immediate that was found. */
8317 inst
.error
= _("source1 and dest must be same register");
8323 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_R
; break;
8324 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_R
; break;
8325 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_R
; break;
8328 inst
.instruction
|= Rd
| (Rn
<< 3);
8334 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_I
; break;
8335 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_I
; break;
8336 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_I
; break;
8339 if (inst
.reloc
.exp
.X_op
!= O_constant
)
8341 /* Value isn't known yet, create a dummy reloc and let reloc
8342 hacking fix it up. */
8343 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_SHIFT
;
8347 unsigned shift_value
= inst
.reloc
.exp
.X_add_number
;
8349 if (shift_value
> 32 || (shift_value
== 32 && shift
== THUMB_LSL
))
8351 inst
.error
= _("invalid immediate for shift");
8355 /* Shifts of zero are handled by converting to LSL. */
8356 if (shift_value
== 0)
8357 inst
.instruction
= T_OPCODE_LSL_I
;
8359 /* Shifts of 32 are encoded as a shift of zero. */
8360 if (shift_value
== 32)
8363 inst
.instruction
|= shift_value
<< 6;
8366 inst
.instruction
|= Rd
| (Rs
<< 3);
8373 thumb_load_store (char * str
, int load_store
, int size
)
8375 int Rd
, Rb
, Ro
= FAIL
;
8377 skip_whitespace (str
);
8379 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
8380 || skip_past_comma (&str
) == FAIL
)
8383 inst
.error
= BAD_ARGS
;
8390 if ((Rb
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8393 if (skip_past_comma (&str
) != FAIL
)
8395 if (is_immediate_prefix (*str
))
8398 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8401 else if ((Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8406 inst
.reloc
.exp
.X_op
= O_constant
;
8407 inst
.reloc
.exp
.X_add_number
= 0;
8412 inst
.error
= _("expected ']'");
8417 else if (*str
== '=')
8419 if (load_store
!= THUMB_LOAD
)
8421 inst
.error
= _("invalid pseudo operation");
8425 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
8428 skip_whitespace (str
);
8430 if (my_get_expression (& inst
.reloc
.exp
, & str
))
8435 if ( inst
.reloc
.exp
.X_op
!= O_constant
8436 && inst
.reloc
.exp
.X_op
!= O_symbol
)
8438 inst
.error
= "Constant expression expected";
8442 if (inst
.reloc
.exp
.X_op
== O_constant
8443 && ((inst
.reloc
.exp
.X_add_number
& ~0xFF) == 0))
8445 /* This can be done with a mov instruction. */
8447 inst
.instruction
= T_OPCODE_MOV_I8
| (Rd
<< 8);
8448 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
8452 /* Insert into literal pool. */
8453 if (add_to_lit_pool () == FAIL
)
8456 inst
.error
= "literal pool insertion failed";
8460 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8461 inst
.reloc
.pc_rel
= 1;
8462 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
8463 /* Adjust ARM pipeline offset to Thumb. */
8464 inst
.reloc
.exp
.X_add_number
+= 4;
8470 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8473 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
8474 inst
.reloc
.pc_rel
= 1;
8475 inst
.reloc
.exp
.X_add_number
-= 4; /* Pipeline offset. */
8476 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8481 if (Rb
== REG_PC
|| Rb
== REG_SP
)
8483 if (size
!= THUMB_WORD
)
8485 inst
.error
= _("byte or halfword not valid for base register");
8488 else if (Rb
== REG_PC
&& load_store
!= THUMB_LOAD
)
8490 inst
.error
= _("r15 based store not allowed");
8493 else if (Ro
!= FAIL
)
8495 inst
.error
= _("invalid base register for register offset");
8500 inst
.instruction
= T_OPCODE_LDR_PC
;
8501 else if (load_store
== THUMB_LOAD
)
8502 inst
.instruction
= T_OPCODE_LDR_SP
;
8504 inst
.instruction
= T_OPCODE_STR_SP
;
8506 inst
.instruction
|= Rd
<< 8;
8507 if (inst
.reloc
.exp
.X_op
== O_constant
)
8509 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
8511 if (offset
& ~0x3fc)
8513 inst
.error
= _("invalid offset");
8517 inst
.instruction
|= offset
>> 2;
8520 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8524 inst
.error
= _("invalid base register in load/store");
8527 else if (Ro
== FAIL
)
8529 /* Immediate offset. */
8530 if (size
== THUMB_WORD
)
8531 inst
.instruction
= (load_store
== THUMB_LOAD
8532 ? T_OPCODE_LDR_IW
: T_OPCODE_STR_IW
);
8533 else if (size
== THUMB_HALFWORD
)
8534 inst
.instruction
= (load_store
== THUMB_LOAD
8535 ? T_OPCODE_LDR_IH
: T_OPCODE_STR_IH
);
8537 inst
.instruction
= (load_store
== THUMB_LOAD
8538 ? T_OPCODE_LDR_IB
: T_OPCODE_STR_IB
);
8540 inst
.instruction
|= Rd
| (Rb
<< 3);
8542 if (inst
.reloc
.exp
.X_op
== O_constant
)
8544 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
8546 if (offset
& ~(0x1f << size
))
8548 inst
.error
= _("invalid offset");
8551 inst
.instruction
|= (offset
>> size
) << 6;
8554 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8558 /* Register offset. */
8559 if (size
== THUMB_WORD
)
8560 inst
.instruction
= (load_store
== THUMB_LOAD
8561 ? T_OPCODE_LDR_RW
: T_OPCODE_STR_RW
);
8562 else if (size
== THUMB_HALFWORD
)
8563 inst
.instruction
= (load_store
== THUMB_LOAD
8564 ? T_OPCODE_LDR_RH
: T_OPCODE_STR_RH
);
8566 inst
.instruction
= (load_store
== THUMB_LOAD
8567 ? T_OPCODE_LDR_RB
: T_OPCODE_STR_RB
);
8569 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
8575 /* A register must be given at this point.
8577 Shift is the place to put it in inst.instruction.
8579 Restores input start point on err.
8580 Returns the reg#, or FAIL. */
8583 mav_reg_required_here (char ** str
, int shift
, enum arm_reg_type regtype
)
8588 if ((reg
= arm_reg_parse (str
, all_reg_maps
[regtype
].htab
)) != FAIL
)
8591 inst
.instruction
|= reg
<< shift
;
8596 /* Restore the start point. */
8599 /* Try generic coprocessor name if applicable. */
8600 if (regtype
== REG_TYPE_MVF
||
8601 regtype
== REG_TYPE_MVD
||
8602 regtype
== REG_TYPE_MVFX
||
8603 regtype
== REG_TYPE_MVDX
)
8605 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CN
].htab
)) != FAIL
)
8608 inst
.instruction
|= reg
<< shift
;
8613 /* Restore the start point. */
8617 /* In the few cases where we might be able to accept something else
8618 this error can be overridden. */
8619 inst
.error
= _(all_reg_maps
[regtype
].expected
);
8624 /* Cirrus Maverick Instructions. */
8626 /* Isnsn like "foo X,Y". */
8629 do_mav_binops (char * str
,
8631 enum arm_reg_type reg0
,
8632 enum arm_reg_type reg1
)
8636 shift0
= mode
& 0xff;
8637 shift1
= (mode
>> 8) & 0xff;
8639 skip_whitespace (str
);
8641 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
8642 || skip_past_comma (&str
) == FAIL
8643 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
)
8646 inst
.error
= BAD_ARGS
;
8652 /* Isnsn like "foo X,Y,Z". */
8655 do_mav_triple (char * str
,
8657 enum arm_reg_type reg0
,
8658 enum arm_reg_type reg1
,
8659 enum arm_reg_type reg2
)
8661 int shift0
, shift1
, shift2
;
8663 shift0
= mode
& 0xff;
8664 shift1
= (mode
>> 8) & 0xff;
8665 shift2
= (mode
>> 16) & 0xff;
8667 skip_whitespace (str
);
8669 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
8670 || skip_past_comma (&str
) == FAIL
8671 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
8672 || skip_past_comma (&str
) == FAIL
8673 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
)
8676 inst
.error
= BAD_ARGS
;
8682 /* Wrapper functions. */
8685 do_mav_binops_1a (char * str
)
8687 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVF
);
8691 do_mav_binops_1b (char * str
)
8693 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVD
);
8697 do_mav_binops_1c (char * str
)
8699 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVDX
);
8703 do_mav_binops_1d (char * str
)
8705 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVF
);
8709 do_mav_binops_1e (char * str
)
8711 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVD
);
8715 do_mav_binops_1f (char * str
)
8717 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVF
);
8721 do_mav_binops_1g (char * str
)
8723 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVD
);
8727 do_mav_binops_1h (char * str
)
8729 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVFX
);
8733 do_mav_binops_1i (char * str
)
8735 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVFX
);
8739 do_mav_binops_1j (char * str
)
8741 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVDX
);
8745 do_mav_binops_1k (char * str
)
8747 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVDX
);
8751 do_mav_binops_1l (char * str
)
8753 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVF
);
8757 do_mav_binops_1m (char * str
)
8759 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVD
);
8763 do_mav_binops_1n (char * str
)
8765 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
8769 do_mav_binops_1o (char * str
)
8771 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
8775 do_mav_binops_2a (char * str
)
8777 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVF
, REG_TYPE_RN
);
8781 do_mav_binops_2b (char * str
)
8783 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVD
, REG_TYPE_RN
);
8787 do_mav_binops_2c (char * str
)
8789 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVDX
, REG_TYPE_RN
);
8793 do_mav_binops_3a (char * str
)
8795 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVFX
);
8799 do_mav_binops_3b (char * str
)
8801 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVFX
, REG_TYPE_MVAX
);
8805 do_mav_binops_3c (char * str
)
8807 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVDX
);
8811 do_mav_binops_3d (char * str
)
8813 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVDX
, REG_TYPE_MVAX
);
8817 do_mav_triple_4a (char * str
)
8819 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_RN
);
8823 do_mav_triple_4b (char * str
)
8825 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_RN
);
8829 do_mav_triple_5a (char * str
)
8831 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVF
, REG_TYPE_MVF
);
8835 do_mav_triple_5b (char * str
)
8837 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVD
, REG_TYPE_MVD
);
8841 do_mav_triple_5c (char * str
)
8843 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
8847 do_mav_triple_5d (char * str
)
8849 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
8853 do_mav_triple_5e (char * str
)
8855 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVF
, REG_TYPE_MVF
, REG_TYPE_MVF
);
8859 do_mav_triple_5f (char * str
)
8861 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVD
, REG_TYPE_MVD
, REG_TYPE_MVD
);
8865 do_mav_triple_5g (char * str
)
8867 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
8871 do_mav_triple_5h (char * str
)
8873 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
8876 /* Isnsn like "foo W,X,Y,Z".
8877 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
8880 do_mav_quad (char * str
,
8882 enum arm_reg_type reg0
,
8883 enum arm_reg_type reg1
,
8884 enum arm_reg_type reg2
,
8885 enum arm_reg_type reg3
)
8887 int shift0
, shift1
, shift2
, shift3
;
8889 shift0
= mode
& 0xff;
8890 shift1
= (mode
>> 8) & 0xff;
8891 shift2
= (mode
>> 16) & 0xff;
8892 shift3
= (mode
>> 24) & 0xff;
8894 skip_whitespace (str
);
8896 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
8897 || skip_past_comma (&str
) == FAIL
8898 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
8899 || skip_past_comma (&str
) == FAIL
8900 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
8901 || skip_past_comma (&str
) == FAIL
8902 || mav_reg_required_here (&str
, shift3
, reg3
) == FAIL
)
8905 inst
.error
= BAD_ARGS
;
8912 do_mav_quad_6a (char * str
)
8914 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
,
8919 do_mav_quad_6b (char * str
)
8921 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVAX
, REG_TYPE_MVFX
,
8925 /* cfmvsc32<cond> DSPSC,MVDX[15:0]. */
8927 do_mav_dspsc_1 (char * str
)
8929 skip_whitespace (str
);
8932 if (mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
8933 || skip_past_comma (&str
) == FAIL
8934 || mav_reg_required_here (&str
, 12, REG_TYPE_MVDX
) == FAIL
)
8937 inst
.error
= BAD_ARGS
;
8945 /* cfmv32sc<cond> MVDX[15:0],DSPSC. */
8947 do_mav_dspsc_2 (char * str
)
8949 skip_whitespace (str
);
8952 if (mav_reg_required_here (&str
, 12, REG_TYPE_MVDX
) == FAIL
8953 || skip_past_comma (&str
) == FAIL
8954 || mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
)
8957 inst
.error
= BAD_ARGS
;
8965 /* Maverick shift immediate instructions.
8966 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
8967 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
8970 do_mav_shift (char * str
,
8971 enum arm_reg_type reg0
,
8972 enum arm_reg_type reg1
)
8977 skip_whitespace (str
);
8981 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
8982 || skip_past_comma (&str
) == FAIL
8983 || mav_reg_required_here (&str
, 16, reg1
) == FAIL
8984 || skip_past_comma (&str
) == FAIL
)
8987 inst
.error
= BAD_ARGS
;
8991 /* Calculate the immediate operand.
8992 The operand is a 7bit signed number. */
8993 skip_whitespace (str
);
8998 if (!ISDIGIT (*str
) && *str
!= '-')
9000 inst
.error
= _("expecting immediate, 7bit operand");
9010 for (imm
= 0; *str
&& ISDIGIT (*str
); ++str
)
9011 imm
= imm
* 10 + *str
- '0';
9015 inst
.error
= _("immediate out of range");
9019 /* Make negative imm's into 7bit signed numbers. */
9026 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
9027 Bits 5-7 of the insn should have bits 4-6 of the immediate.
9028 Bit 4 should be 0. */
9029 imm
= (imm
& 0xf) | ((imm
& 0x70) << 1);
9031 inst
.instruction
|= imm
;
9036 do_mav_shift_1 (char * str
)
9038 do_mav_shift (str
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
9042 do_mav_shift_2 (char * str
)
9044 do_mav_shift (str
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
9048 mav_parse_offset (char ** str
, int * negative
)
9055 skip_whitespace (p
);
9068 inst
.error
= _("offset expected");
9072 for (offset
= 0; *p
&& ISDIGIT (*p
); ++p
)
9073 offset
= offset
* 10 + *p
- '0';
9077 inst
.error
= _("offset out of range");
9082 inst
.error
= _("offset not a multiple of 4");
9088 return *negative
? -offset
: offset
;
9091 /* Maverick load/store instructions.
9092 <insn><cond> CRd,[Rn,<offset>]{!}.
9093 <insn><cond> CRd,[Rn],<offset>. */
9096 do_mav_ldst (char * str
, enum arm_reg_type reg0
)
9098 int offset
, negative
;
9100 skip_whitespace (str
);
9102 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
9103 || skip_past_comma (&str
) == FAIL
9105 || reg_required_here (&str
, 16) == FAIL
)
9108 if (skip_past_comma (&str
) == SUCCESS
)
9110 /* You are here: "<offset>]{!}". */
9111 inst
.instruction
|= PRE_INDEX
;
9113 offset
= mav_parse_offset (&str
, &negative
);
9120 inst
.error
= _("missing ]");
9126 inst
.instruction
|= WRITE_BACK
;
9132 /* You are here: "], <offset>". */
9135 inst
.error
= _("missing ]");
9139 if (skip_past_comma (&str
) == FAIL
9140 || (offset
= mav_parse_offset (&str
, &negative
), inst
.error
))
9143 inst
.instruction
|= CP_T_WB
; /* Post indexed, set bit W. */
9149 inst
.instruction
|= CP_T_UD
; /* Positive, so set bit U. */
9151 inst
.instruction
|= offset
>> 2;
9157 inst
.error
= BAD_ARGS
;
9161 do_mav_ldst_1 (char * str
)
9163 do_mav_ldst (str
, REG_TYPE_MVF
);
9167 do_mav_ldst_2 (char * str
)
9169 do_mav_ldst (str
, REG_TYPE_MVD
);
9173 do_mav_ldst_3 (char * str
)
9175 do_mav_ldst (str
, REG_TYPE_MVFX
);
9179 do_mav_ldst_4 (char * str
)
9181 do_mav_ldst (str
, REG_TYPE_MVDX
);
9185 do_t_nop (char * str
)
9191 /* Handle the Format 4 instructions that do not have equivalents in other
9192 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
9196 do_t_arit (char * str
)
9200 skip_whitespace (str
);
9202 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9203 || skip_past_comma (&str
) == FAIL
9204 || (Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9206 inst
.error
= BAD_ARGS
;
9210 if (skip_past_comma (&str
) != FAIL
)
9212 /* Three operand format not allowed for TST, CMN, NEG and MVN.
9213 (It isn't allowed for CMP either, but that isn't handled by this
9215 if (inst
.instruction
== T_OPCODE_TST
9216 || inst
.instruction
== T_OPCODE_CMN
9217 || inst
.instruction
== T_OPCODE_NEG
9218 || inst
.instruction
== T_OPCODE_MVN
)
9220 inst
.error
= BAD_ARGS
;
9224 if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9229 inst
.error
= _("dest and source1 must be the same register");
9235 if (inst
.instruction
== T_OPCODE_MUL
9237 as_tsktsk (_("Rs and Rd must be different in MUL"));
9239 inst
.instruction
|= Rd
| (Rs
<< 3);
9244 do_t_add (char * str
)
9246 thumb_add_sub (str
, 0);
9250 do_t_asr (char * str
)
9252 thumb_shift (str
, THUMB_ASR
);
9256 do_t_branch9 (char * str
)
9258 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9260 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH9
;
9261 inst
.reloc
.pc_rel
= 1;
9266 do_t_branch12 (char * str
)
9268 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9270 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH12
;
9271 inst
.reloc
.pc_rel
= 1;
9275 /* Find the real, Thumb encoded start of a Thumb function. */
9278 find_real_start (symbolS
* symbolP
)
9281 const char * name
= S_GET_NAME (symbolP
);
9282 symbolS
* new_target
;
9284 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
9285 #define STUB_NAME ".real_start_of"
9290 /* Names that start with '.' are local labels, not function entry points.
9291 The compiler may generate BL instructions to these labels because it
9292 needs to perform a branch to a far away location. */
9296 real_start
= malloc (strlen (name
) + strlen (STUB_NAME
) + 1);
9297 sprintf (real_start
, "%s%s", STUB_NAME
, name
);
9299 new_target
= symbol_find (real_start
);
9301 if (new_target
== NULL
)
9303 as_warn ("Failed to find real start of function: %s\n", name
);
9304 new_target
= symbolP
;
9313 do_t_branch23 (char * str
)
9315 if (my_get_expression (& inst
.reloc
.exp
, & str
))
9318 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH23
;
9319 inst
.reloc
.pc_rel
= 1;
9322 /* If the destination of the branch is a defined symbol which does not have
9323 the THUMB_FUNC attribute, then we must be calling a function which has
9324 the (interfacearm) attribute. We look for the Thumb entry point to that
9325 function and change the branch to refer to that function instead. */
9326 if ( inst
.reloc
.exp
.X_op
== O_symbol
9327 && inst
.reloc
.exp
.X_add_symbol
!= NULL
9328 && S_IS_DEFINED (inst
.reloc
.exp
.X_add_symbol
)
9329 && ! THUMB_IS_FUNC (inst
.reloc
.exp
.X_add_symbol
))
9330 inst
.reloc
.exp
.X_add_symbol
=
9331 find_real_start (inst
.reloc
.exp
.X_add_symbol
);
9335 do_t_bx (char * str
)
9339 skip_whitespace (str
);
9341 if ((reg
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
9344 /* This sets THUMB_H2 from the top bit of reg. */
9345 inst
.instruction
|= reg
<< 3;
9347 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
9348 should cause the alignment to be checked once it is known. This is
9349 because BX PC only works if the instruction is word aligned. */
9355 do_t_compare (char * str
)
9357 thumb_mov_compare (str
, THUMB_COMPARE
);
9361 do_t_ldmstm (char * str
)
9366 skip_whitespace (str
);
9368 if ((Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9372 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
9376 if (skip_past_comma (&str
) == FAIL
9377 || (range
= reg_list (&str
)) == FAIL
)
9380 inst
.error
= BAD_ARGS
;
9384 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
9386 /* This really doesn't seem worth it. */
9387 inst
.reloc
.type
= BFD_RELOC_NONE
;
9388 inst
.error
= _("expression too complex");
9394 inst
.error
= _("only lo-regs valid in load/store multiple");
9398 inst
.instruction
|= (Rb
<< 8) | range
;
9403 do_t_ldr (char * str
)
9405 thumb_load_store (str
, THUMB_LOAD
, THUMB_WORD
);
9409 do_t_ldrb (char * str
)
9411 thumb_load_store (str
, THUMB_LOAD
, THUMB_BYTE
);
9415 do_t_ldrh (char * str
)
9417 thumb_load_store (str
, THUMB_LOAD
, THUMB_HALFWORD
);
9421 do_t_lds (char * str
)
9425 skip_whitespace (str
);
9427 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9428 || skip_past_comma (&str
) == FAIL
9430 || (Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9431 || skip_past_comma (&str
) == FAIL
9432 || (Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9436 inst
.error
= _("syntax: ldrs[b] Rd, [Rb, Ro]");
9440 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
9445 do_t_lsl (char * str
)
9447 thumb_shift (str
, THUMB_LSL
);
9451 do_t_lsr (char * str
)
9453 thumb_shift (str
, THUMB_LSR
);
9457 do_t_mov (char * str
)
9459 thumb_mov_compare (str
, THUMB_MOVE
);
9463 do_t_push_pop (char * str
)
9467 skip_whitespace (str
);
9469 if ((range
= reg_list (&str
)) == FAIL
)
9472 inst
.error
= BAD_ARGS
;
9476 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
9478 /* This really doesn't seem worth it. */
9479 inst
.reloc
.type
= BFD_RELOC_NONE
;
9480 inst
.error
= _("expression too complex");
9486 if ((inst
.instruction
== T_OPCODE_PUSH
9487 && (range
& ~0xff) == 1 << REG_LR
)
9488 || (inst
.instruction
== T_OPCODE_POP
9489 && (range
& ~0xff) == 1 << REG_PC
))
9491 inst
.instruction
|= THUMB_PP_PC_LR
;
9496 inst
.error
= _("invalid register list to push/pop instruction");
9501 inst
.instruction
|= range
;
9506 do_t_str (char * str
)
9508 thumb_load_store (str
, THUMB_STORE
, THUMB_WORD
);
9512 do_t_strb (char * str
)
9514 thumb_load_store (str
, THUMB_STORE
, THUMB_BYTE
);
9518 do_t_strh (char * str
)
9520 thumb_load_store (str
, THUMB_STORE
, THUMB_HALFWORD
);
9524 do_t_sub (char * str
)
9526 thumb_add_sub (str
, 1);
9530 do_t_swi (char * str
)
9532 skip_whitespace (str
);
9534 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9537 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
9542 do_t_adr (char * str
)
9546 /* This is a pseudo-op of the form "adr rd, label" to be converted
9547 into a relative address of the form "add rd, pc, #label-.-4". */
9548 skip_whitespace (str
);
9550 /* Store Rd in temporary location inside instruction. */
9551 if ((reg
= reg_required_here (&str
, 4)) == FAIL
9552 || (reg
> 7) /* For Thumb reg must be r0..r7. */
9553 || skip_past_comma (&str
) == FAIL
9554 || my_get_expression (&inst
.reloc
.exp
, &str
))
9557 inst
.error
= BAD_ARGS
;
9561 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
9562 inst
.reloc
.exp
.X_add_number
-= 4; /* PC relative adjust. */
9563 inst
.reloc
.pc_rel
= 1;
9564 inst
.instruction
|= REG_PC
; /* Rd is already placed into the instruction. */
9570 insert_reg (const struct reg_entry
* r
,
9571 struct hash_control
* htab
)
9573 int len
= strlen (r
->name
) + 2;
9574 char * buf
= xmalloc (len
);
9575 char * buf2
= xmalloc (len
);
9578 #ifdef REGISTER_PREFIX
9579 buf
[i
++] = REGISTER_PREFIX
;
9582 strcpy (buf
+ i
, r
->name
);
9584 for (i
= 0; buf
[i
]; i
++)
9585 buf2
[i
] = TOUPPER (buf
[i
]);
9589 hash_insert (htab
, buf
, (PTR
) r
);
9590 hash_insert (htab
, buf2
, (PTR
) r
);
9594 build_reg_hsh (struct reg_map
* map
)
9596 const struct reg_entry
*r
;
9598 if ((map
->htab
= hash_new ()) == NULL
)
9599 as_fatal (_("virtual memory exhausted"));
9601 for (r
= map
->names
; r
->name
!= NULL
; r
++)
9602 insert_reg (r
, map
->htab
);
9606 insert_reg_alias (char * str
,
9608 struct hash_control
*htab
)
9611 struct reg_entry
* new = xmalloc (sizeof (struct reg_entry
));
9612 const char * name
= xmalloc (strlen (str
) + 1);
9614 strcpy ((char *) name
, str
);
9617 new->number
= regnum
;
9618 new->builtin
= FALSE
;
9620 error
= hash_insert (htab
, name
, (PTR
) new);
9623 as_bad (_("failed to create an alias for %s, reason: %s"),
9625 free ((char *) name
);
9630 /* Look for the .req directive. This is of the form:
9632 new_register_name .req existing_register_name
9634 If we find one, or if it looks sufficiently like one that we want to
9635 handle any error here, return non-zero. Otherwise return zero. */
9638 create_register_alias (char * newname
, char * p
)
9644 skip_whitespace (q
);
9649 if (*q
&& !strncmp (q
, ".req ", 5))
9654 #ifndef IGNORE_OPCODE_CASE
9655 newname
= original_case_string
;
9657 copy_of_str
= newname
;
9660 skip_whitespace (q
);
9662 for (r
= q
; *r
!= '\0'; r
++)
9668 enum arm_reg_type new_type
, old_type
;
9673 old_type
= arm_reg_parse_any (q
);
9676 new_type
= arm_reg_parse_any (newname
);
9678 if (new_type
== REG_TYPE_MAX
)
9680 if (old_type
!= REG_TYPE_MAX
)
9682 old_regno
= arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
);
9683 insert_reg_alias (newname
, old_regno
,
9684 all_reg_maps
[old_type
].htab
);
9687 as_warn (_("register '%s' does not exist\n"), q
);
9689 else if (old_type
== REG_TYPE_MAX
)
9691 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
9696 /* Do not warn about redefinitions to the same alias. */
9697 if (new_type
!= old_type
9698 || (arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
)
9699 != arm_reg_parse (&q
, all_reg_maps
[new_type
].htab
)))
9700 as_warn (_("ignoring redefinition of register alias '%s'"),
9706 as_warn (_("ignoring incomplete .req pseuso op"));
9717 set_constant_flonums (void)
9721 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
9722 if (atof_ieee ((char *) fp_const
[i
], 'x', fp_values
[i
]) == NULL
)
9727 static const struct asm_opcode insns
[] =
9729 /* Core ARM Instructions. */
9730 {"and", 0xe0000000, 3, ARM_EXT_V1
, do_arit
},
9731 {"ands", 0xe0100000, 3, ARM_EXT_V1
, do_arit
},
9732 {"eor", 0xe0200000, 3, ARM_EXT_V1
, do_arit
},
9733 {"eors", 0xe0300000, 3, ARM_EXT_V1
, do_arit
},
9734 {"sub", 0xe0400000, 3, ARM_EXT_V1
, do_arit
},
9735 {"subs", 0xe0500000, 3, ARM_EXT_V1
, do_arit
},
9736 {"rsb", 0xe0600000, 3, ARM_EXT_V1
, do_arit
},
9737 {"rsbs", 0xe0700000, 3, ARM_EXT_V1
, do_arit
},
9738 {"add", 0xe0800000, 3, ARM_EXT_V1
, do_arit
},
9739 {"adds", 0xe0900000, 3, ARM_EXT_V1
, do_arit
},
9740 {"adc", 0xe0a00000, 3, ARM_EXT_V1
, do_arit
},
9741 {"adcs", 0xe0b00000, 3, ARM_EXT_V1
, do_arit
},
9742 {"sbc", 0xe0c00000, 3, ARM_EXT_V1
, do_arit
},
9743 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1
, do_arit
},
9744 {"rsc", 0xe0e00000, 3, ARM_EXT_V1
, do_arit
},
9745 {"rscs", 0xe0f00000, 3, ARM_EXT_V1
, do_arit
},
9746 {"orr", 0xe1800000, 3, ARM_EXT_V1
, do_arit
},
9747 {"orrs", 0xe1900000, 3, ARM_EXT_V1
, do_arit
},
9748 {"bic", 0xe1c00000, 3, ARM_EXT_V1
, do_arit
},
9749 {"bics", 0xe1d00000, 3, ARM_EXT_V1
, do_arit
},
9751 {"tst", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
9752 {"tsts", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
9753 {"tstp", 0xe110f000, 3, ARM_EXT_V1
, do_cmp
},
9754 {"teq", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
9755 {"teqs", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
9756 {"teqp", 0xe130f000, 3, ARM_EXT_V1
, do_cmp
},
9757 {"cmp", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
9758 {"cmps", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
9759 {"cmpp", 0xe150f000, 3, ARM_EXT_V1
, do_cmp
},
9760 {"cmn", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
9761 {"cmns", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
9762 {"cmnp", 0xe170f000, 3, ARM_EXT_V1
, do_cmp
},
9764 {"mov", 0xe1a00000, 3, ARM_EXT_V1
, do_mov
},
9765 {"movs", 0xe1b00000, 3, ARM_EXT_V1
, do_mov
},
9766 {"mvn", 0xe1e00000, 3, ARM_EXT_V1
, do_mov
},
9767 {"mvns", 0xe1f00000, 3, ARM_EXT_V1
, do_mov
},
9769 {"ldr", 0xe4100000, 3, ARM_EXT_V1
, do_ldst
},
9770 {"ldrb", 0xe4500000, 3, ARM_EXT_V1
, do_ldst
},
9771 {"ldrt", 0xe4300000, 3, ARM_EXT_V1
, do_ldstt
},
9772 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1
, do_ldstt
},
9773 {"str", 0xe4000000, 3, ARM_EXT_V1
, do_ldst
},
9774 {"strb", 0xe4400000, 3, ARM_EXT_V1
, do_ldst
},
9775 {"strt", 0xe4200000, 3, ARM_EXT_V1
, do_ldstt
},
9776 {"strbt", 0xe4600000, 3, ARM_EXT_V1
, do_ldstt
},
9778 {"stmia", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
9779 {"stmib", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
9780 {"stmda", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
9781 {"stmdb", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
9782 {"stmfd", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
9783 {"stmfa", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
9784 {"stmea", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
9785 {"stmed", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
9787 {"ldmia", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
9788 {"ldmib", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
9789 {"ldmda", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
9790 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
9791 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
9792 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
9793 {"ldmea", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
9794 {"ldmed", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
9796 {"swi", 0xef000000, 3, ARM_EXT_V1
, do_swi
},
9798 /* XXX This is the wrong place to do this. Think multi-arch. */
9799 {"bl", 0xeb000000, 2, ARM_EXT_V1
, do_branch
},
9800 {"b", 0xea000000, 1, ARM_EXT_V1
, do_branch
},
9802 {"bl", 0xebfffffe, 2, ARM_EXT_V1
, do_branch
},
9803 {"b", 0xeafffffe, 1, ARM_EXT_V1
, do_branch
},
9807 {"adr", 0xe28f0000, 3, ARM_EXT_V1
, do_adr
},
9808 {"adrl", 0xe28f0000, 3, ARM_EXT_V1
, do_adrl
},
9809 {"nop", 0xe1a00000, 3, ARM_EXT_V1
, do_nop
},
9811 /* ARM 2 multiplies. */
9812 {"mul", 0xe0000090, 3, ARM_EXT_V2
, do_mul
},
9813 {"muls", 0xe0100090, 3, ARM_EXT_V2
, do_mul
},
9814 {"mla", 0xe0200090, 3, ARM_EXT_V2
, do_mla
},
9815 {"mlas", 0xe0300090, 3, ARM_EXT_V2
, do_mla
},
9817 /* Generic coprocessor instructions. */
9818 {"cdp", 0xee000000, 3, ARM_EXT_V2
, do_cdp
},
9819 {"ldc", 0xec100000, 3, ARM_EXT_V2
, do_lstc
},
9820 {"ldcl", 0xec500000, 3, ARM_EXT_V2
, do_lstc
},
9821 {"stc", 0xec000000, 3, ARM_EXT_V2
, do_lstc
},
9822 {"stcl", 0xec400000, 3, ARM_EXT_V2
, do_lstc
},
9823 {"mcr", 0xee000010, 3, ARM_EXT_V2
, do_co_reg
},
9824 {"mrc", 0xee100010, 3, ARM_EXT_V2
, do_co_reg
},
9826 /* ARM 3 - swp instructions. */
9827 {"swp", 0xe1000090, 3, ARM_EXT_V2S
, do_swap
},
9828 {"swpb", 0xe1400090, 3, ARM_EXT_V2S
, do_swap
},
9830 /* ARM 6 Status register instructions. */
9831 {"mrs", 0xe10f0000, 3, ARM_EXT_V3
, do_mrs
},
9832 {"msr", 0xe120f000, 3, ARM_EXT_V3
, do_msr
},
9833 /* ScottB: our code uses 0xe128f000 for msr.
9834 NickC: but this is wrong because the bits 16 through 19 are
9835 handled by the PSR_xxx defines above. */
9837 /* ARM 7M long multiplies. */
9838 {"smull", 0xe0c00090, 5, ARM_EXT_V3M
, do_mull
},
9839 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M
, do_mull
},
9840 {"umull", 0xe0800090, 5, ARM_EXT_V3M
, do_mull
},
9841 {"umulls", 0xe0900090, 5, ARM_EXT_V3M
, do_mull
},
9842 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M
, do_mull
},
9843 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M
, do_mull
},
9844 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M
, do_mull
},
9845 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M
, do_mull
},
9847 /* ARM Architecture 4. */
9848 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4
, do_ldstv4
},
9849 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4
, do_ldstv4
},
9850 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4
, do_ldstv4
},
9851 {"strh", 0xe00000b0, 3, ARM_EXT_V4
, do_ldstv4
},
9853 /* ARM Architecture 4T. */
9854 /* Note: bx (and blx) are required on V5, even if the processor does
9855 not support Thumb. */
9856 {"bx", 0xe12fff10, 2, ARM_EXT_V4T
| ARM_EXT_V5
, do_bx
},
9858 /* ARM Architecture 5T. */
9859 /* Note: blx has 2 variants, so the .value is set dynamically.
9860 Only one of the variants has conditional execution. */
9861 {"blx", 0xe0000000, 3, ARM_EXT_V5
, do_blx
},
9862 {"clz", 0xe16f0f10, 3, ARM_EXT_V5
, do_clz
},
9863 {"bkpt", 0xe1200070, 0, ARM_EXT_V5
, do_bkpt
},
9864 {"ldc2", 0xfc100000, 0, ARM_EXT_V5
, do_lstc2
},
9865 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5
, do_lstc2
},
9866 {"stc2", 0xfc000000, 0, ARM_EXT_V5
, do_lstc2
},
9867 {"stc2l", 0xfc400000, 0, ARM_EXT_V5
, do_lstc2
},
9868 {"cdp2", 0xfe000000, 0, ARM_EXT_V5
, do_cdp2
},
9869 {"mcr2", 0xfe000010, 0, ARM_EXT_V5
, do_co_reg2
},
9870 {"mrc2", 0xfe100010, 0, ARM_EXT_V5
, do_co_reg2
},
9872 /* ARM Architecture 5TExP. */
9873 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP
, do_smla
},
9874 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP
, do_smla
},
9875 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP
, do_smla
},
9876 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP
, do_smla
},
9878 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP
, do_smla
},
9879 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP
, do_smla
},
9881 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP
, do_smlal
},
9882 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP
, do_smlal
},
9883 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP
, do_smlal
},
9884 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP
, do_smlal
},
9886 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP
, do_smul
},
9887 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP
, do_smul
},
9888 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP
, do_smul
},
9889 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP
, do_smul
},
9891 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP
, do_smul
},
9892 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP
, do_smul
},
9894 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP
, do_qadd
},
9895 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP
, do_qadd
},
9896 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP
, do_qadd
},
9897 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP
, do_qadd
},
9899 /* ARM Architecture 5TE. */
9900 {"pld", 0xf450f000, 0, ARM_EXT_V5E
, do_pld
},
9901 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E
, do_ldrd
},
9902 {"strd", 0xe00000f0, 3, ARM_EXT_V5E
, do_ldrd
},
9904 {"mcrr", 0xec400000, 4, ARM_EXT_V5E
, do_co_reg2c
},
9905 {"mrrc", 0xec500000, 4, ARM_EXT_V5E
, do_co_reg2c
},
9907 /* ARM Architecture 5TEJ. */
9908 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J
, do_bxj
},
9911 { "cps", 0xf1020000, 0, ARM_EXT_V6
, do_cps
},
9912 { "cpsie", 0xf1080000, 0, ARM_EXT_V6
, do_cpsi
},
9913 { "cpsid", 0xf10C0000, 0, ARM_EXT_V6
, do_cpsi
},
9914 { "ldrex", 0xe1900f9f, 5, ARM_EXT_V6
, do_ldrex
},
9915 { "mcrr2", 0xfc400000, 0, ARM_EXT_V6
, do_co_reg2c
},
9916 { "mrrc2", 0xfc500000, 0, ARM_EXT_V6
, do_co_reg2c
},
9917 { "pkhbt", 0xe6800010, 5, ARM_EXT_V6
, do_pkhbt
},
9918 { "pkhtb", 0xe6800050, 5, ARM_EXT_V6
, do_pkhtb
},
9919 { "qadd16", 0xe6200f10, 6, ARM_EXT_V6
, do_qadd16
},
9920 { "qadd8", 0xe6200f90, 5, ARM_EXT_V6
, do_qadd16
},
9921 { "qaddsubx", 0xe6200f30, 8, ARM_EXT_V6
, do_qadd16
},
9922 { "qsub16", 0xe6200f70, 6, ARM_EXT_V6
, do_qadd16
},
9923 { "qsub8", 0xe6200ff0, 5, ARM_EXT_V6
, do_qadd16
},
9924 { "qsubaddx", 0xe6200f50, 8, ARM_EXT_V6
, do_qadd16
},
9925 { "sadd16", 0xe6100f10, 6, ARM_EXT_V6
, do_qadd16
},
9926 { "sadd8", 0xe6100f90, 5, ARM_EXT_V6
, do_qadd16
},
9927 { "saddsubx", 0xe6100f30, 8, ARM_EXT_V6
, do_qadd16
},
9928 { "shadd16", 0xe6300f10, 7, ARM_EXT_V6
, do_qadd16
},
9929 { "shadd8", 0xe6300f90, 6, ARM_EXT_V6
, do_qadd16
},
9930 { "shaddsubx", 0xe6300f30, 9, ARM_EXT_V6
, do_qadd16
},
9931 { "shsub16", 0xe6300f70, 7, ARM_EXT_V6
, do_qadd16
},
9932 { "shsub8", 0xe6300ff0, 6, ARM_EXT_V6
, do_qadd16
},
9933 { "shsubaddx", 0xe6300f50, 9, ARM_EXT_V6
, do_qadd16
},
9934 { "ssub16", 0xe6100f70, 6, ARM_EXT_V6
, do_qadd16
},
9935 { "ssub8", 0xe6100ff0, 5, ARM_EXT_V6
, do_qadd16
},
9936 { "ssubaddx", 0xe6100f50, 8, ARM_EXT_V6
, do_qadd16
},
9937 { "uadd16", 0xe6500f10, 6, ARM_EXT_V6
, do_qadd16
},
9938 { "uadd8", 0xe6500f90, 5, ARM_EXT_V6
, do_qadd16
},
9939 { "uaddsubx", 0xe6500f30, 8, ARM_EXT_V6
, do_qadd16
},
9940 { "uhadd16", 0xe6700f10, 7, ARM_EXT_V6
, do_qadd16
},
9941 { "uhadd8", 0xe6700f90, 6, ARM_EXT_V6
, do_qadd16
},
9942 { "uhaddsubx", 0xe6700f30, 9, ARM_EXT_V6
, do_qadd16
},
9943 { "uhsub16", 0xe6700f70, 7, ARM_EXT_V6
, do_qadd16
},
9944 { "uhsub8", 0xe6700ff0, 6, ARM_EXT_V6
, do_qadd16
},
9945 { "uhsubaddx", 0xe6700f50, 9, ARM_EXT_V6
, do_qadd16
},
9946 { "uqadd16", 0xe6600f10, 7, ARM_EXT_V6
, do_qadd16
},
9947 { "uqadd8", 0xe6600f90, 6, ARM_EXT_V6
, do_qadd16
},
9948 { "uqaddsubx", 0xe6600f30, 9, ARM_EXT_V6
, do_qadd16
},
9949 { "uqsub16", 0xe6600f70, 7, ARM_EXT_V6
, do_qadd16
},
9950 { "uqsub8", 0xe6600ff0, 6, ARM_EXT_V6
, do_qadd16
},
9951 { "uqsubaddx", 0xe6600f50, 9, ARM_EXT_V6
, do_qadd16
},
9952 { "usub16", 0xe6500f70, 6, ARM_EXT_V6
, do_qadd16
},
9953 { "usub8", 0xe6500ff0, 5, ARM_EXT_V6
, do_qadd16
},
9954 { "usubaddx", 0xe6500f50, 8, ARM_EXT_V6
, do_qadd16
},
9955 { "rev", 0xe6bf0f30, 3, ARM_EXT_V6
, do_rev
},
9956 { "rev16", 0xe6bf0fb0, 5, ARM_EXT_V6
, do_rev
},
9957 { "revsh", 0xe6ff0fb0, 5, ARM_EXT_V6
, do_rev
},
9958 { "rfeia", 0xf8900a00, 0, ARM_EXT_V6
, do_rfe
},
9959 { "rfeib", 0xf9900a00, 0, ARM_EXT_V6
, do_rfe
},
9960 { "rfeda", 0xf8100a00, 0, ARM_EXT_V6
, do_rfe
},
9961 { "rfedb", 0xf9100a00, 0, ARM_EXT_V6
, do_rfe
},
9962 { "rfefd", 0xf8900a00, 0, ARM_EXT_V6
, do_rfe
},
9963 { "rfefa", 0xf9900a00, 0, ARM_EXT_V6
, do_rfe
},
9964 { "rfeea", 0xf8100a00, 0, ARM_EXT_V6
, do_rfe
},
9965 { "rfeed", 0xf9100a00, 0, ARM_EXT_V6
, do_rfe
},
9966 { "sxtah", 0xe6b00070, 5, ARM_EXT_V6
, do_sxtah
},
9967 { "sxtab16", 0xe6800070, 7, ARM_EXT_V6
, do_sxtah
},
9968 { "sxtab", 0xe6a00070, 5, ARM_EXT_V6
, do_sxtah
},
9969 { "sxth", 0xe6bf0070, 4, ARM_EXT_V6
, do_sxth
},
9970 { "sxtb16", 0xe68f0070, 6, ARM_EXT_V6
, do_sxth
},
9971 { "sxtb", 0xe6af0070, 4, ARM_EXT_V6
, do_sxth
},
9972 { "uxtah", 0xe6f00070, 5, ARM_EXT_V6
, do_sxtah
},
9973 { "uxtab16", 0xe6c00070, 7, ARM_EXT_V6
, do_sxtah
},
9974 { "uxtab", 0xe6e00070, 5, ARM_EXT_V6
, do_sxtah
},
9975 { "uxth", 0xe6ff0070, 4, ARM_EXT_V6
, do_sxth
},
9976 { "uxtb16", 0xe6cf0070, 6, ARM_EXT_V6
, do_sxth
},
9977 { "uxtb", 0xe6ef0070, 4, ARM_EXT_V6
, do_sxth
},
9978 { "sel", 0xe68000b0, 3, ARM_EXT_V6
, do_qadd16
},
9979 { "setend", 0xf1010000, 0, ARM_EXT_V6
, do_setend
},
9980 { "smlad", 0xe7000010, 5, ARM_EXT_V6
, do_smlad
},
9981 { "smladx", 0xe7000030, 6, ARM_EXT_V6
, do_smlad
},
9982 { "smlald", 0xe7400010, 6, ARM_EXT_V6
, do_smlald
},
9983 { "smlaldx", 0xe7400030, 7, ARM_EXT_V6
, do_smlald
},
9984 { "smlsd", 0xe7000050, 5, ARM_EXT_V6
, do_smlad
},
9985 { "smlsdx", 0xe7000070, 6, ARM_EXT_V6
, do_smlad
},
9986 { "smlsld", 0xe7400050, 6, ARM_EXT_V6
, do_smlald
},
9987 { "smlsldx", 0xe7400070, 7, ARM_EXT_V6
, do_smlald
},
9988 { "smmla", 0xe7500010, 5, ARM_EXT_V6
, do_smlad
},
9989 { "smmlar", 0xe7500030, 6, ARM_EXT_V6
, do_smlad
},
9990 { "smmls", 0xe75000d0, 5, ARM_EXT_V6
, do_smlad
},
9991 { "smmlsr", 0xe75000f0, 6, ARM_EXT_V6
, do_smlad
},
9992 { "smmul", 0xe750f010, 5, ARM_EXT_V6
, do_smmul
},
9993 { "smmulr", 0xe750f030, 6, ARM_EXT_V6
, do_smmul
},
9994 { "smuad", 0xe700f010, 5, ARM_EXT_V6
, do_smmul
},
9995 { "smuadx", 0xe700f030, 6, ARM_EXT_V6
, do_smmul
},
9996 { "smusd", 0xe700f050, 5, ARM_EXT_V6
, do_smmul
},
9997 { "smusdx", 0xe700f070, 6, ARM_EXT_V6
, do_smmul
},
9998 { "srsia", 0xf8cd0500, 0, ARM_EXT_V6
, do_srs
},
9999 { "srsib", 0xf9cd0500, 0, ARM_EXT_V6
, do_srs
},
10000 { "srsda", 0xf84d0500, 0, ARM_EXT_V6
, do_srs
},
10001 { "srsdb", 0xf94d0500, 0, ARM_EXT_V6
, do_srs
},
10002 { "ssat", 0xe6a00010, 4, ARM_EXT_V6
, do_ssat
},
10003 { "ssat16", 0xe6a00f30, 6, ARM_EXT_V6
, do_ssat16
},
10004 { "strex", 0xe1800f90, 5, ARM_EXT_V6
, do_strex
},
10005 { "umaal", 0xe0400090, 5, ARM_EXT_V6
, do_umaal
},
10006 { "usad8", 0xe780f010, 5, ARM_EXT_V6
, do_smmul
},
10007 { "usada8", 0xe7800010, 6, ARM_EXT_V6
, do_smlad
},
10008 { "usat", 0xe6e00010, 4, ARM_EXT_V6
, do_usat
},
10009 { "usat16", 0xe6e00f30, 6, ARM_EXT_V6
, do_usat16
},
10012 { "clrex", 0xf57ff01f, 0, ARM_EXT_V6K
, do_empty
},
10013 { "ldrexb", 0xe1d00f9f, 6, ARM_EXT_V6K
, do_ldrex
},
10014 { "ldrexd", 0xe1b00f9f, 6, ARM_EXT_V6K
, do_ldrex
},
10015 { "ldrexh", 0xe1f00f9f, 6, ARM_EXT_V6K
, do_ldrex
},
10016 { "sev", 0xe320f004, 3, ARM_EXT_V6K
, do_empty
},
10017 { "strexb", 0xe1c00f90, 6, ARM_EXT_V6K
, do_strex
},
10018 { "strexd", 0xe1a00f90, 6, ARM_EXT_V6K
, do_strex
},
10019 { "strexh", 0xe1e00f90, 6, ARM_EXT_V6K
, do_strex
},
10020 { "wfe", 0xe320f002, 3, ARM_EXT_V6K
, do_empty
},
10021 { "wfi", 0xe320f003, 3, ARM_EXT_V6K
, do_empty
},
10022 { "yield", 0xe320f001, 5, ARM_EXT_V6K
, do_empty
},
10025 { "smi", 0xe1600070, 3, ARM_EXT_V6Z
, do_smi
},
10027 /* Core FPA instruction set (V1). */
10028 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
10029 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
10030 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
10031 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
10033 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10034 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10035 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10036 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10038 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10039 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10040 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10041 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10043 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10044 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10045 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10046 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10047 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10048 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10049 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10050 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10051 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10052 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10053 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10054 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10056 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10057 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10058 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10059 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10060 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10061 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10062 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10063 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10064 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10065 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10066 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10067 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10069 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10070 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10071 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10072 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10073 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10074 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10075 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10076 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10077 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10078 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10079 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10080 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10082 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10083 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10084 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10085 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10086 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10087 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10088 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10089 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10090 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10091 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10092 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10093 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10095 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10096 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10097 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10098 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10099 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10100 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10101 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10102 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10103 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10104 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10105 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10106 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10108 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10109 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10110 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10111 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10112 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10113 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10114 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10115 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10116 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10117 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10118 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10119 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10121 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10122 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10123 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10124 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10125 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10126 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10127 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10128 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10129 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10130 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10131 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10132 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10134 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10135 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10136 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10137 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10138 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10139 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10140 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10141 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10142 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10143 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10144 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10145 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10147 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10148 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10149 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10150 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10151 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10152 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10153 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10154 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10155 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10156 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10157 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10158 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10160 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10161 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10162 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10163 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10164 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10165 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10166 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10167 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10168 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10169 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10170 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10171 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10173 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10174 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10175 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10176 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10177 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10178 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10179 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10180 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10181 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10182 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10183 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10184 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10186 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10187 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10188 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10189 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10190 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10191 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10192 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10193 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10194 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10195 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10196 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10197 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10199 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10200 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10201 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10202 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10203 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10204 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10205 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10206 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10207 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10208 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10209 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10210 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10212 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10213 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10214 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10215 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10216 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10217 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10218 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10219 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10220 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10221 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10222 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10223 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10225 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10226 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10227 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10228 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10229 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10230 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10231 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10232 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10233 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10234 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10235 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10236 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10238 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10239 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10240 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10241 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10242 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10243 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10244 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10245 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10246 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10247 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10248 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10249 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10251 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10252 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10253 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10254 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10255 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10256 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10257 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10258 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10259 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10260 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10261 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10262 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10264 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10265 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10266 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10267 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10268 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10269 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10270 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10271 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10272 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10273 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10274 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10275 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10277 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10278 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10279 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10280 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10281 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10282 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10283 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10284 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10285 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10286 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10287 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10288 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10290 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10291 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10292 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10293 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10294 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10295 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10296 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10297 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10298 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10299 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10300 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10301 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10303 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10304 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10305 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10306 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10307 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10308 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10309 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10310 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10311 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10312 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10313 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10314 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10316 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10317 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10318 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10319 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10320 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10321 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10322 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10323 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10324 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10325 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10326 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10327 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10329 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10330 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10331 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10332 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10333 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10334 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10335 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10336 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10337 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10338 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10339 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10340 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10342 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10343 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10344 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10345 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10346 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10347 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10348 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10349 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10350 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10351 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10352 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10353 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10355 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10356 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10357 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10358 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10359 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10360 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10361 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10362 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10363 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10364 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10365 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10366 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10368 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10369 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10370 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10371 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10372 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10373 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10374 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10375 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10376 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10377 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10378 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10379 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10381 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10382 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10383 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10384 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10385 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10386 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10387 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10388 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10389 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10390 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10391 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10392 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10394 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10395 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10396 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10397 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10398 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10399 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10400 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10401 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10402 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10403 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10404 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10405 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10407 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10408 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10409 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10410 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10411 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10412 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10413 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10414 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10415 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10416 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10417 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10418 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10420 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10421 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10422 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10423 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10424 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
10425 not be an optional suffix, but part of the instruction. To be
10426 compatible, we accept either. */
10427 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10428 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10430 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10431 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10432 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10433 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10434 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10435 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10436 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10437 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10438 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10439 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10440 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10441 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10443 /* The implementation of the FIX instruction is broken on some
10444 assemblers, in that it accepts a precision specifier as well as a
10445 rounding specifier, despite the fact that this is meaningless.
10446 To be more compatible, we accept it as well, though of course it
10447 does not set any bits. */
10448 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10449 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10450 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10451 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10452 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10453 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10454 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10455 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10456 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10457 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10458 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10459 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10460 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10462 /* Instructions that were new with the real FPA, call them V2. */
10463 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10464 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10465 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10466 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10467 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10468 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10470 /* VFP V1xD (single precision). */
10471 /* Moves and type conversions. */
10472 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10473 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_reg_from_sp
},
10474 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_from_reg
},
10475 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD
, do_empty
},
10476 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10477 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10478 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10479 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10480 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10481 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10482 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_reg_from_ctrl
},
10483 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_ctrl_from_reg
},
10485 /* Memory operations. */
10486 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldst
},
10487 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldst
},
10488 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
10489 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
10490 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
10491 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
10492 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
10493 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
10494 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
10495 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
10496 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
10497 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
10498 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
10499 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
10500 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
10501 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
10502 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
10503 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
10505 /* Monadic operations. */
10506 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10507 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10508 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10510 /* Dyadic operations. */
10511 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10512 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10513 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10514 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10515 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10516 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10517 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10518 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10519 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10522 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10523 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_compare_z
},
10524 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10525 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_compare_z
},
10527 /* VFP V1 (Double precision). */
10528 /* Moves and type conversions. */
10529 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10530 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
10531 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10532 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1
, do_vfp_dp_from_reg
},
10533 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1
, do_vfp_dp_from_reg
},
10534 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1
, do_vfp_reg_from_dp
},
10535 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1
, do_vfp_reg_from_dp
},
10536 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
10537 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
10538 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10539 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10540 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10541 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10543 /* Memory operations. */
10544 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1
, do_vfp_dp_ldst
},
10545 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1
, do_vfp_dp_ldst
},
10546 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
10547 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
10548 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
10549 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
10550 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
10551 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
10552 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
10553 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
10555 /* Monadic operations. */
10556 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10557 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10558 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10560 /* Dyadic operations. */
10561 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10562 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10563 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10564 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10565 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10566 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10567 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10568 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10569 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10572 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10573 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_compare_z
},
10574 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10575 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1
, do_vfp_dp_compare_z
},
10578 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2
, do_vfp_sp2_from_reg2
},
10579 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2
, do_vfp_reg2_from_sp2
},
10580 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2
, do_vfp_dp_from_reg2
},
10581 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2
, do_vfp_reg2_from_dp
},
10583 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
10584 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE
, do_xsc_mia
},
10585 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10586 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10587 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10588 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10589 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10590 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE
, do_xsc_mar
},
10591 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE
, do_xsc_mra
},
10593 /* Intel Wireless MMX technology instructions. */
10594 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
10595 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
10596 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
10597 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
10598 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
10599 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
10600 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
10601 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
10602 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
10603 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10604 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10605 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10606 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10607 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10608 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10609 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
10610 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
10611 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
10612 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmcr
},
10613 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_tmcrr
},
10614 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10615 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10616 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10617 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10618 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10619 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10620 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
10621 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
10622 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
10623 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmrc
},
10624 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_tmrrc
},
10625 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
10626 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
10627 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
10628 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10629 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10630 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10631 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10632 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10633 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10634 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10635 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10636 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10637 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10638 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10639 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10640 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_waligni
},
10641 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10642 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10643 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10644 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10645 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10646 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10647 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10648 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10649 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10650 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10651 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10652 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10653 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10654 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10655 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10656 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10657 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10658 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10659 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10660 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
10661 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
10662 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
10663 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
10664 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10665 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10666 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10667 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10668 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10669 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10670 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10671 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10672 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10673 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10674 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10675 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10676 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10677 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10678 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10679 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10680 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10681 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10682 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wmov
},
10683 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10684 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10685 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10686 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10687 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10688 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10689 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10690 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10691 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10692 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10693 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10694 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10695 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10696 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10697 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10698 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10699 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10700 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10701 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10702 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10703 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10704 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wshufh
},
10705 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10706 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10707 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10708 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10709 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10710 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10711 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10712 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10713 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10714 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10715 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10716 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10717 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10718 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10719 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10720 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10721 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10722 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10723 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
10724 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
10725 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
10726 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
10727 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10728 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10729 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10730 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10731 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10732 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10733 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10734 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10735 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10736 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10737 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10738 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10739 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10740 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10741 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10742 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10743 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10744 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10745 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10746 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10747 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10748 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10749 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10750 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10751 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10752 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10753 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10754 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10755 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wzero
},
10757 /* Cirrus Maverick instructions. */
10758 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_1
},
10759 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_2
},
10760 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_3
},
10761 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_4
},
10762 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_1
},
10763 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_2
},
10764 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_3
},
10765 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_4
},
10766 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK
, do_mav_binops_2a
},
10767 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1a
},
10768 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK
, do_mav_binops_2b
},
10769 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1b
},
10770 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK
, do_mav_binops_2b
},
10771 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1b
},
10772 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK
, do_mav_binops_2c
},
10773 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1c
},
10774 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK
, do_mav_binops_2c
},
10775 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1c
},
10776 {"cfmval32", 0xee200440, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
10777 {"cfmv32al", 0xee100440, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
10778 {"cfmvam32", 0xee200460, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
10779 {"cfmv32am", 0xee100460, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
10780 {"cfmvah32", 0xee200480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
10781 {"cfmv32ah", 0xee100480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
10782 {"cfmva32", 0xee2004a0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
10783 {"cfmv32a", 0xee1004a0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
10784 {"cfmva64", 0xee2004c0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3c
},
10785 {"cfmv64a", 0xee1004c0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3d
},
10786 {"cfmvsc32", 0xee2004e0, 8, ARM_CEXT_MAVERICK
, do_mav_dspsc_1
},
10787 {"cfmv32sc", 0xee1004e0, 8, ARM_CEXT_MAVERICK
, do_mav_dspsc_2
},
10788 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
10789 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
10790 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1f
},
10791 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1g
},
10792 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1h
},
10793 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1i
},
10794 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1j
},
10795 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1k
},
10796 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1l
},
10797 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1m
},
10798 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK
, do_mav_binops_1l
},
10799 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK
, do_mav_binops_1m
},
10800 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK
, do_mav_triple_4a
},
10801 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK
, do_mav_triple_4b
},
10802 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK
, do_mav_shift_1
},
10803 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK
, do_mav_shift_2
},
10804 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5a
},
10805 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5b
},
10806 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5c
},
10807 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5d
},
10808 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
10809 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
10810 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
10811 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
10812 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
10813 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
10814 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
10815 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
10816 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
10817 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
10818 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1n
},
10819 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1o
},
10820 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1n
},
10821 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1o
},
10822 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
10823 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
10824 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
10825 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
10826 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
10827 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
10828 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
10829 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
10830 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK
, do_mav_quad_6a
},
10831 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK
, do_mav_quad_6a
},
10832 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK
, do_mav_quad_6b
},
10833 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK
, do_mav_quad_6b
},
10836 /* Iterate over the base tables to create the instruction patterns. */
10839 build_arm_ops_hsh (void)
10843 static struct obstack insn_obstack
;
10845 obstack_begin (&insn_obstack
, 4000);
10847 for (i
= 0; i
< sizeof (insns
) / sizeof (struct asm_opcode
); i
++)
10849 const struct asm_opcode
*insn
= insns
+ i
;
10851 if (insn
->cond_offset
!= 0)
10853 /* Insn supports conditional execution. Build the varaints
10854 and insert them in the hash table. */
10855 for (j
= 0; j
< sizeof (conds
) / sizeof (struct asm_cond
); j
++)
10857 unsigned len
= strlen (insn
->template);
10858 struct asm_opcode
*new;
10861 new = obstack_alloc (&insn_obstack
, sizeof (struct asm_opcode
));
10862 /* All condition codes are two characters. */
10863 template = obstack_alloc (&insn_obstack
, len
+ 3);
10865 strncpy (template, insn
->template, insn
->cond_offset
);
10866 strcpy (template + insn
->cond_offset
, conds
[j
].template);
10867 if (len
> insn
->cond_offset
)
10868 strcpy (template + insn
->cond_offset
+ 2,
10869 insn
->template + insn
->cond_offset
);
10870 new->template = template;
10871 new->cond_offset
= 0;
10872 new->variant
= insn
->variant
;
10873 new->parms
= insn
->parms
;
10874 new->value
= (insn
->value
& ~COND_MASK
) | conds
[j
].value
;
10876 hash_insert (arm_ops_hsh
, new->template, (PTR
) new);
10879 /* Finally, insert the unconditional insn in the table directly;
10880 no need to build a copy. */
10881 hash_insert (arm_ops_hsh
, insn
->template, (PTR
) insn
);
10885 #if 0 /* Suppressed - for now. */
10886 #if defined OBJ_ELF || defined OBJ_COFF
10889 #define arm_Note Elf_External_Note
10893 unsigned char namesz
[4]; /* Size of entry's owner string. */
10894 unsigned char descsz
[4]; /* Size of the note descriptor. */
10895 unsigned char type
[4]; /* Interpretation of the descriptor. */
10896 char name
[1]; /* Start of the name+desc data. */
10900 /* The description is kept to a fix sized in order to make updating
10901 it and merging it easier. */
10902 #define ARM_NOTE_DESCRIPTION_LENGTH 8
10905 arm_add_note (const char * name
,
10906 const char * description
,
10909 arm_Note note ATTRIBUTE_UNUSED
;
10911 unsigned int name_len
;
10913 name_len
= (strlen (name
) + 1 + 3) & ~3;
10915 p
= frag_more (sizeof (note
.namesz
));
10916 md_number_to_chars (p
, (valueT
) name_len
, sizeof (note
.namesz
));
10918 p
= frag_more (sizeof (note
.descsz
));
10919 md_number_to_chars (p
, (valueT
) ARM_NOTE_DESCRIPTION_LENGTH
, sizeof (note
.descsz
));
10921 p
= frag_more (sizeof (note
.type
));
10922 md_number_to_chars (p
, (valueT
) type
, sizeof (note
.type
));
10924 p
= frag_more (name_len
);
10927 p
= frag_more (ARM_NOTE_DESCRIPTION_LENGTH
);
10928 strncpy (p
, description
, ARM_NOTE_DESCRIPTION_LENGTH
);
10929 frag_align (2, 0, 0);
10935 static const struct thumb_opcode tinsns
[] =
10937 /* Thumb v1 (ARMv4T). */
10938 {"adc", 0x4140, 2, ARM_EXT_V4T
, do_t_arit
},
10939 {"add", 0x0000, 2, ARM_EXT_V4T
, do_t_add
},
10940 {"and", 0x4000, 2, ARM_EXT_V4T
, do_t_arit
},
10941 {"asr", 0x0000, 2, ARM_EXT_V4T
, do_t_asr
},
10942 {"b", T_OPCODE_BRANCH
, 2, ARM_EXT_V4T
, do_t_branch12
},
10943 {"beq", 0xd0fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10944 {"bne", 0xd1fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10945 {"bcs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10946 {"bhs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10947 {"bcc", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10948 {"bul", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10949 {"blo", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10950 {"bmi", 0xd4fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10951 {"bpl", 0xd5fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10952 {"bvs", 0xd6fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10953 {"bvc", 0xd7fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10954 {"bhi", 0xd8fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10955 {"bls", 0xd9fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10956 {"bge", 0xdafe, 2, ARM_EXT_V4T
, do_t_branch9
},
10957 {"blt", 0xdbfe, 2, ARM_EXT_V4T
, do_t_branch9
},
10958 {"bgt", 0xdcfe, 2, ARM_EXT_V4T
, do_t_branch9
},
10959 {"ble", 0xddfe, 2, ARM_EXT_V4T
, do_t_branch9
},
10960 {"bal", 0xdefe, 2, ARM_EXT_V4T
, do_t_branch9
},
10961 {"bic", 0x4380, 2, ARM_EXT_V4T
, do_t_arit
},
10962 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T
, do_t_branch23
},
10963 {"bx", 0x4700, 2, ARM_EXT_V4T
, do_t_bx
},
10964 {"cmn", T_OPCODE_CMN
, 2, ARM_EXT_V4T
, do_t_arit
},
10965 {"cmp", 0x0000, 2, ARM_EXT_V4T
, do_t_compare
},
10966 {"eor", 0x4040, 2, ARM_EXT_V4T
, do_t_arit
},
10967 {"ldmia", 0xc800, 2, ARM_EXT_V4T
, do_t_ldmstm
},
10968 {"ldr", 0x0000, 2, ARM_EXT_V4T
, do_t_ldr
},
10969 {"ldrb", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrb
},
10970 {"ldrh", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrh
},
10971 {"ldrsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
10972 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
10973 {"ldsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
10974 {"ldsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
10975 {"lsl", 0x0000, 2, ARM_EXT_V4T
, do_t_lsl
},
10976 {"lsr", 0x0000, 2, ARM_EXT_V4T
, do_t_lsr
},
10977 {"mov", 0x0000, 2, ARM_EXT_V4T
, do_t_mov
},
10978 {"mul", T_OPCODE_MUL
, 2, ARM_EXT_V4T
, do_t_arit
},
10979 {"mvn", T_OPCODE_MVN
, 2, ARM_EXT_V4T
, do_t_arit
},
10980 {"neg", T_OPCODE_NEG
, 2, ARM_EXT_V4T
, do_t_arit
},
10981 {"orr", 0x4300, 2, ARM_EXT_V4T
, do_t_arit
},
10982 {"pop", 0xbc00, 2, ARM_EXT_V4T
, do_t_push_pop
},
10983 {"push", 0xb400, 2, ARM_EXT_V4T
, do_t_push_pop
},
10984 {"ror", 0x41c0, 2, ARM_EXT_V4T
, do_t_arit
},
10985 {"sbc", 0x4180, 2, ARM_EXT_V4T
, do_t_arit
},
10986 {"stmia", 0xc000, 2, ARM_EXT_V4T
, do_t_ldmstm
},
10987 {"str", 0x0000, 2, ARM_EXT_V4T
, do_t_str
},
10988 {"strb", 0x0000, 2, ARM_EXT_V4T
, do_t_strb
},
10989 {"strh", 0x0000, 2, ARM_EXT_V4T
, do_t_strh
},
10990 {"swi", 0xdf00, 2, ARM_EXT_V4T
, do_t_swi
},
10991 {"sub", 0x0000, 2, ARM_EXT_V4T
, do_t_sub
},
10992 {"tst", T_OPCODE_TST
, 2, ARM_EXT_V4T
, do_t_arit
},
10994 {"adr", 0x0000, 2, ARM_EXT_V4T
, do_t_adr
},
10995 {"nop", 0x46C0, 2, ARM_EXT_V4T
, do_t_nop
}, /* mov r8,r8 */
10996 /* Thumb v2 (ARMv5T). */
10997 {"blx", 0, 0, ARM_EXT_V5T
, do_t_blx
},
10998 {"bkpt", 0xbe00, 2, ARM_EXT_V5T
, do_t_bkpt
},
11001 {"cpsie", 0xb660, 2, ARM_EXT_V6
, do_t_cps
},
11002 {"cpsid", 0xb670, 2, ARM_EXT_V6
, do_t_cps
},
11003 {"cpy", 0x4600, 2, ARM_EXT_V6
, do_t_cpy
},
11004 {"rev", 0xba00, 2, ARM_EXT_V6
, do_t_arit
},
11005 {"rev16", 0xba40, 2, ARM_EXT_V6
, do_t_arit
},
11006 {"revsh", 0xbac0, 2, ARM_EXT_V6
, do_t_arit
},
11007 {"setend", 0xb650, 2, ARM_EXT_V6
, do_t_setend
},
11008 {"sxth", 0xb200, 2, ARM_EXT_V6
, do_t_arit
},
11009 {"sxtb", 0xb240, 2, ARM_EXT_V6
, do_t_arit
},
11010 {"uxth", 0xb280, 2, ARM_EXT_V6
, do_t_arit
},
11011 {"uxtb", 0xb2c0, 2, ARM_EXT_V6
, do_t_arit
},
11020 if ( (arm_ops_hsh
= hash_new ()) == NULL
11021 || (arm_tops_hsh
= hash_new ()) == NULL
11022 || (arm_cond_hsh
= hash_new ()) == NULL
11023 || (arm_shift_hsh
= hash_new ()) == NULL
11024 || (arm_psr_hsh
= hash_new ()) == NULL
)
11025 as_fatal (_("virtual memory exhausted"));
11027 build_arm_ops_hsh ();
11028 for (i
= 0; i
< sizeof (tinsns
) / sizeof (struct thumb_opcode
); i
++)
11029 hash_insert (arm_tops_hsh
, tinsns
[i
].template, (PTR
) (tinsns
+ i
));
11030 for (i
= 0; i
< sizeof (conds
) / sizeof (struct asm_cond
); i
++)
11031 hash_insert (arm_cond_hsh
, conds
[i
].template, (PTR
) (conds
+ i
));
11032 for (i
= 0; i
< sizeof (shift_names
) / sizeof (struct asm_shift_name
); i
++)
11033 hash_insert (arm_shift_hsh
, shift_names
[i
].name
, (PTR
) (shift_names
+ i
));
11034 for (i
= 0; i
< sizeof (psrs
) / sizeof (struct asm_psr
); i
++)
11035 hash_insert (arm_psr_hsh
, psrs
[i
].template, (PTR
) (psrs
+ i
));
11037 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
11038 build_reg_hsh (all_reg_maps
+ i
);
11040 set_constant_flonums ();
11042 /* Set the cpu variant based on the command-line options. We prefer
11043 -mcpu= over -march= if both are set (as for GCC); and we prefer
11044 -mfpu= over any other way of setting the floating point unit.
11045 Use of legacy options with new options are faulted. */
11046 if (legacy_cpu
!= -1)
11048 if (mcpu_cpu_opt
!= -1 || march_cpu_opt
!= -1)
11049 as_bad (_("use of old and new-style options to set CPU type"));
11051 mcpu_cpu_opt
= legacy_cpu
;
11053 else if (mcpu_cpu_opt
== -1)
11054 mcpu_cpu_opt
= march_cpu_opt
;
11056 if (legacy_fpu
!= -1)
11058 if (mfpu_opt
!= -1)
11059 as_bad (_("use of old and new-style options to set FPU type"));
11061 mfpu_opt
= legacy_fpu
;
11063 else if (mfpu_opt
== -1)
11065 #if !(defined (TE_LINUX) || defined (TE_NetBSD) || defined (TE_VXWORKS))
11066 /* Some environments specify a default FPU. If they don't, infer it
11067 from the processor. */
11068 if (mcpu_fpu_opt
!= -1)
11069 mfpu_opt
= mcpu_fpu_opt
;
11071 mfpu_opt
= march_fpu_opt
;
11073 mfpu_opt
= FPU_DEFAULT
;
11077 if (mfpu_opt
== -1)
11079 if (mcpu_cpu_opt
== -1)
11080 mfpu_opt
= FPU_DEFAULT
;
11081 else if (mcpu_cpu_opt
& ARM_EXT_V5
)
11082 mfpu_opt
= FPU_ARCH_VFP_V2
;
11084 mfpu_opt
= FPU_ARCH_FPA
;
11087 if (mcpu_cpu_opt
== -1)
11088 mcpu_cpu_opt
= CPU_DEFAULT
;
11090 cpu_variant
= mcpu_cpu_opt
| mfpu_opt
;
11093 unsigned int flags
= 0;
11095 #if defined OBJ_ELF
11096 flags
= meabi_flags
;
11098 switch (meabi_flags
)
11100 case EF_ARM_EABI_UNKNOWN
:
11102 #if defined OBJ_COFF || defined OBJ_ELF
11103 /* Set the flags in the private structure. */
11104 if (uses_apcs_26
) flags
|= F_APCS26
;
11105 if (support_interwork
) flags
|= F_INTERWORK
;
11106 if (uses_apcs_float
) flags
|= F_APCS_FLOAT
;
11107 if (pic_code
) flags
|= F_PIC
;
11108 if ((cpu_variant
& FPU_ANY
) == FPU_NONE
11109 || (cpu_variant
& FPU_ANY
) == FPU_ARCH_VFP
) /* VFP layout only. */
11110 flags
|= F_SOFT_FLOAT
;
11112 switch (mfloat_abi_opt
)
11114 case ARM_FLOAT_ABI_SOFT
:
11115 case ARM_FLOAT_ABI_SOFTFP
:
11116 flags
|= F_SOFT_FLOAT
;
11119 case ARM_FLOAT_ABI_HARD
:
11120 if (flags
& F_SOFT_FLOAT
)
11121 as_bad (_("hard-float conflicts with specified fpu"));
11125 /* Using VFP conventions (even if soft-float). */
11126 if (cpu_variant
& FPU_VFP_EXT_NONE
)
11127 flags
|= F_VFP_FLOAT
;
11129 #if defined OBJ_ELF
11130 if (cpu_variant
& FPU_ARCH_MAVERICK
)
11131 flags
|= EF_ARM_MAVERICK_FLOAT
;
11134 case EF_ARM_EABI_VER4
:
11135 /* No additional flags to set. */
11142 #if defined OBJ_COFF || defined OBJ_ELF
11143 bfd_set_private_flags (stdoutput
, flags
);
11145 /* We have run out flags in the COFF header to encode the
11146 status of ATPCS support, so instead we create a dummy,
11147 empty, debug section called .arm.atpcs. */
11152 sec
= bfd_make_section (stdoutput
, ".arm.atpcs");
11156 bfd_set_section_flags
11157 (stdoutput
, sec
, SEC_READONLY
| SEC_DEBUGGING
/* | SEC_HAS_CONTENTS */);
11158 bfd_set_section_size (stdoutput
, sec
, 0);
11159 bfd_set_section_contents (stdoutput
, sec
, NULL
, 0, 0);
11165 /* Record the CPU type as well. */
11166 switch (cpu_variant
& ARM_CPU_MASK
)
11169 mach
= bfd_mach_arm_2
;
11172 case ARM_3
: /* Also ARM_250. */
11173 mach
= bfd_mach_arm_2a
;
11176 case ARM_6
: /* Also ARM_7. */
11177 mach
= bfd_mach_arm_3
;
11181 mach
= bfd_mach_arm_unknown
;
11185 /* Catch special cases. */
11186 if (cpu_variant
& ARM_CEXT_IWMMXT
)
11187 mach
= bfd_mach_arm_iWMMXt
;
11188 else if (cpu_variant
& ARM_CEXT_XSCALE
)
11189 mach
= bfd_mach_arm_XScale
;
11190 else if (cpu_variant
& ARM_CEXT_MAVERICK
)
11191 mach
= bfd_mach_arm_ep9312
;
11192 else if (cpu_variant
& ARM_EXT_V5E
)
11193 mach
= bfd_mach_arm_5TE
;
11194 else if (cpu_variant
& ARM_EXT_V5
)
11196 if (cpu_variant
& ARM_EXT_V4T
)
11197 mach
= bfd_mach_arm_5T
;
11199 mach
= bfd_mach_arm_5
;
11201 else if (cpu_variant
& ARM_EXT_V4
)
11203 if (cpu_variant
& ARM_EXT_V4T
)
11204 mach
= bfd_mach_arm_4T
;
11206 mach
= bfd_mach_arm_4
;
11208 else if (cpu_variant
& ARM_EXT_V3M
)
11209 mach
= bfd_mach_arm_3M
;
11211 #if 0 /* Suppressed - for now. */
11212 #if defined (OBJ_ELF) || defined (OBJ_COFF)
11214 /* Create a .note section to fully identify this arm binary. */
11216 #define NOTE_ARCH_STRING "arch: "
11218 #if defined OBJ_COFF && ! defined NT_VERSION
11219 #define NT_VERSION 1
11224 segT current_seg
= now_seg
;
11225 subsegT current_subseg
= now_subseg
;
11226 asection
* arm_arch
;
11227 const char * arch_string
;
11229 arm_arch
= bfd_make_section_old_way (stdoutput
, ARM_NOTE_SECTION
);
11232 bfd_set_section_flags (stdoutput
, arm_arch
,
11233 SEC_DATA
| SEC_ALLOC
| SEC_LOAD
| SEC_LINK_ONCE \
11234 | SEC_HAS_CONTENTS
);
11236 bfd_set_section_flags (stdoutput
, arm_arch
,
11237 SEC_READONLY
| SEC_HAS_CONTENTS
);
11239 arm_arch
->output_section
= arm_arch
;
11240 subseg_set (arm_arch
, 0);
11245 case bfd_mach_arm_unknown
: arch_string
= "unknown"; break;
11246 case bfd_mach_arm_2
: arch_string
= "armv2"; break;
11247 case bfd_mach_arm_2a
: arch_string
= "armv2a"; break;
11248 case bfd_mach_arm_3
: arch_string
= "armv3"; break;
11249 case bfd_mach_arm_3M
: arch_string
= "armv3M"; break;
11250 case bfd_mach_arm_4
: arch_string
= "armv4"; break;
11251 case bfd_mach_arm_4T
: arch_string
= "armv4t"; break;
11252 case bfd_mach_arm_5
: arch_string
= "armv5"; break;
11253 case bfd_mach_arm_5T
: arch_string
= "armv5t"; break;
11254 case bfd_mach_arm_5TE
: arch_string
= "armv5te"; break;
11255 case bfd_mach_arm_XScale
: arch_string
= "XScale"; break;
11256 case bfd_mach_arm_ep9312
: arch_string
= "ep9312"; break;
11257 case bfd_mach_arm_iWMMXt
: arch_string
= "iWMMXt"; break;
11260 arm_add_note (NOTE_ARCH_STRING
, arch_string
, NT_ARCH
);
11262 subseg_set (current_seg
, current_subseg
);
11265 #endif /* Suppressed code. */
11267 bfd_set_arch_mach (stdoutput
, TARGET_ARCH
, mach
);
11270 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11271 for use in the a.out file, and stores them in the array pointed to by buf.
11272 This knows about the endian-ness of the target machine and does
11273 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11274 2 (short) and 4 (long) Floating numbers are put out as a series of
11275 LITTLENUMS (shorts, here at least). */
11278 md_number_to_chars (char * buf
, valueT val
, int n
)
11280 if (target_big_endian
)
11281 number_to_chars_bigendian (buf
, val
, n
);
11283 number_to_chars_littleendian (buf
, val
, n
);
11287 md_chars_to_number (char * buf
, int n
)
11290 unsigned char * where
= (unsigned char *) buf
;
11292 if (target_big_endian
)
11297 result
|= (*where
++ & 255);
11305 result
|= (where
[n
] & 255);
11312 /* Turn a string in input_line_pointer into a floating point constant
11313 of type TYPE, and store the appropriate bytes in *LITP. The number
11314 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11315 returned, or NULL on OK.
11317 Note that fp constants aren't represent in the normal way on the ARM.
11318 In big endian mode, things are as expected. However, in little endian
11319 mode fp constants are big-endian word-wise, and little-endian byte-wise
11320 within the words. For example, (double) 1.1 in big endian mode is
11321 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11322 the byte sequence 99 99 f1 3f 9a 99 99 99.
11324 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11327 md_atof (int type
, char * litP
, int * sizeP
)
11330 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
11362 return _("bad call to MD_ATOF()");
11365 t
= atof_ieee (input_line_pointer
, type
, words
);
11367 input_line_pointer
= t
;
11370 if (target_big_endian
)
11372 for (i
= 0; i
< prec
; i
++)
11374 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
11380 if (cpu_variant
& FPU_ARCH_VFP
)
11381 for (i
= prec
- 1; i
>= 0; i
--)
11383 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
11387 /* For a 4 byte float the order of elements in `words' is 1 0.
11388 For an 8 byte float the order is 1 0 3 2. */
11389 for (i
= 0; i
< prec
; i
+= 2)
11391 md_number_to_chars (litP
, (valueT
) words
[i
+ 1], 2);
11392 md_number_to_chars (litP
+ 2, (valueT
) words
[i
], 2);
11400 /* The knowledge of the PC's pipeline offset is built into the insns
11404 md_pcrel_from (fixS
* fixP
)
11407 && S_GET_SEGMENT (fixP
->fx_addsy
) == undefined_section
11408 && fixP
->fx_subsy
== NULL
)
11411 if (fixP
->fx_pcrel
&& (fixP
->fx_r_type
== BFD_RELOC_ARM_THUMB_ADD
))
11413 /* PC relative addressing on the Thumb is slightly odd
11414 as the bottom two bits of the PC are forced to zero
11415 for the calculation. */
11416 return (fixP
->fx_where
+ fixP
->fx_frag
->fr_address
) & ~3;
11420 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
11421 so we un-adjust here to compensate for the accommodation. */
11422 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
+ 8;
11424 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
11428 /* Round up a section size to the appropriate boundary. */
11431 md_section_align (segT segment ATTRIBUTE_UNUSED
,
11437 /* Round all sects to multiple of 4. */
11438 return (size
+ 3) & ~3;
11442 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
11443 Otherwise we have no need to default values of symbols. */
11446 md_undefined_symbol (char * name ATTRIBUTE_UNUSED
)
11449 if (name
[0] == '_' && name
[1] == 'G'
11450 && streq (name
, GLOBAL_OFFSET_TABLE_NAME
))
11454 if (symbol_find (name
))
11455 as_bad ("GOT already in the symbol table");
11457 GOT_symbol
= symbol_new (name
, undefined_section
,
11458 (valueT
) 0, & zero_address_frag
);
11469 md_apply_fix3 (fixS
* fixP
,
11473 offsetT value
= * valP
;
11475 unsigned int newimm
;
11476 unsigned long temp
;
11478 char * buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
11479 arm_fix_data
* arm_data
= (arm_fix_data
*) fixP
->tc_fix_data
;
11481 assert (fixP
->fx_r_type
< BFD_RELOC_UNUSED
);
11483 /* Note whether this will delete the relocation. */
11485 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
11486 doesn't work fully.) */
11487 if ((fixP
->fx_addsy
== 0 || symbol_constant_p (fixP
->fx_addsy
))
11488 && !fixP
->fx_pcrel
)
11490 if (fixP
->fx_addsy
== 0 && !fixP
->fx_pcrel
)
11494 /* If this symbol is in a different section then we need to leave it for
11495 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
11496 so we have to undo it's effects here. */
11497 if (fixP
->fx_pcrel
)
11499 if (fixP
->fx_addsy
!= NULL
11500 && S_IS_DEFINED (fixP
->fx_addsy
)
11501 && S_GET_SEGMENT (fixP
->fx_addsy
) != seg
)
11502 value
+= md_pcrel_from (fixP
);
11505 /* Remember value for emit_reloc. */
11506 fixP
->fx_addnumber
= value
;
11508 switch (fixP
->fx_r_type
)
11510 case BFD_RELOC_ARM_IMMEDIATE
:
11511 /* We claim that this fixup has been processed here,
11512 even if in fact we generate an error because we do
11513 not have a reloc for it, so tc_gen_reloc will reject it. */
11517 && ! S_IS_DEFINED (fixP
->fx_addsy
))
11519 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11520 _("undefined symbol %s used as an immediate value"),
11521 S_GET_NAME (fixP
->fx_addsy
));
11525 newimm
= validate_immediate (value
);
11526 temp
= md_chars_to_number (buf
, INSN_SIZE
);
11528 /* If the instruction will fail, see if we can fix things up by
11529 changing the opcode. */
11530 if (newimm
== (unsigned int) FAIL
11531 && (newimm
= negate_data_op (&temp
, value
)) == (unsigned int) FAIL
)
11533 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11534 _("invalid constant (%lx) after fixup"),
11535 (unsigned long) value
);
11539 newimm
|= (temp
& 0xfffff000);
11540 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
11543 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
11545 unsigned int highpart
= 0;
11546 unsigned int newinsn
= 0xe1a00000; /* nop. */
11548 newimm
= validate_immediate (value
);
11549 temp
= md_chars_to_number (buf
, INSN_SIZE
);
11551 /* If the instruction will fail, see if we can fix things up by
11552 changing the opcode. */
11553 if (newimm
== (unsigned int) FAIL
11554 && (newimm
= negate_data_op (& temp
, value
)) == (unsigned int) FAIL
)
11556 /* No ? OK - try using two ADD instructions to generate
11558 newimm
= validate_immediate_twopart (value
, & highpart
);
11560 /* Yes - then make sure that the second instruction is
11562 if (newimm
!= (unsigned int) FAIL
)
11564 /* Still No ? Try using a negated value. */
11565 else if ((newimm
= validate_immediate_twopart (- value
, & highpart
)) != (unsigned int) FAIL
)
11566 temp
= newinsn
= (temp
& OPCODE_MASK
) | OPCODE_SUB
<< DATA_OP_SHIFT
;
11567 /* Otherwise - give up. */
11570 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11571 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
11576 /* Replace the first operand in the 2nd instruction (which
11577 is the PC) with the destination register. We have
11578 already added in the PC in the first instruction and we
11579 do not want to do it again. */
11580 newinsn
&= ~ 0xf0000;
11581 newinsn
|= ((newinsn
& 0x0f000) << 4);
11584 newimm
|= (temp
& 0xfffff000);
11585 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
11587 highpart
|= (newinsn
& 0xfffff000);
11588 md_number_to_chars (buf
+ INSN_SIZE
, (valueT
) highpart
, INSN_SIZE
);
11592 case BFD_RELOC_ARM_OFFSET_IMM
:
11598 if (validate_offset_imm (value
, 0) == FAIL
)
11600 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11601 _("bad immediate value for offset (%ld)"),
11606 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11607 newval
&= 0xff7ff000;
11608 newval
|= value
| (sign
? INDEX_UP
: 0);
11609 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11612 case BFD_RELOC_ARM_OFFSET_IMM8
:
11613 case BFD_RELOC_ARM_HWLITERAL
:
11619 if (validate_offset_imm (value
, 1) == FAIL
)
11621 if (fixP
->fx_r_type
== BFD_RELOC_ARM_HWLITERAL
)
11622 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11623 _("invalid literal constant: pool needs to be closer"));
11625 as_bad (_("bad immediate value for half-word offset (%ld)"),
11630 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11631 newval
&= 0xff7ff0f0;
11632 newval
|= ((value
>> 4) << 8) | (value
& 0xf) | (sign
? INDEX_UP
: 0);
11633 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11636 case BFD_RELOC_ARM_LITERAL
:
11642 if (validate_offset_imm (value
, 0) == FAIL
)
11644 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11645 _("invalid literal constant: pool needs to be closer"));
11649 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11650 newval
&= 0xff7ff000;
11651 newval
|= value
| (sign
? INDEX_UP
: 0);
11652 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11655 case BFD_RELOC_ARM_SHIFT_IMM
:
11656 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11657 if (((unsigned long) value
) > 32
11659 && (((newval
& 0x60) == 0) || (newval
& 0x60) == 0x60)))
11661 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11662 _("shift expression is too large"));
11667 /* Shifts of zero must be done as lsl. */
11669 else if (value
== 32)
11671 newval
&= 0xfffff07f;
11672 newval
|= (value
& 0x1f) << 7;
11673 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11676 case BFD_RELOC_ARM_SMI
:
11677 if (((unsigned long) value
) > 0xffff)
11678 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11679 _("invalid smi expression"));
11680 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xfff000f0;
11681 newval
|= (value
& 0xf) | ((value
& 0xfff0) << 4);
11682 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11685 case BFD_RELOC_ARM_SWI
:
11686 if (arm_data
->thumb_mode
)
11688 if (((unsigned long) value
) > 0xff)
11689 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11690 _("invalid swi expression"));
11691 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xff00;
11693 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11697 if (((unsigned long) value
) > 0x00ffffff)
11698 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11699 _("invalid swi expression"));
11700 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff000000;
11702 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11706 case BFD_RELOC_ARM_MULTI
:
11707 if (((unsigned long) value
) > 0xffff)
11708 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11709 _("invalid expression in load/store multiple"));
11710 newval
= value
| md_chars_to_number (buf
, INSN_SIZE
);
11711 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11714 case BFD_RELOC_ARM_PCREL_BRANCH
:
11715 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11717 /* Sign-extend a 24-bit number. */
11718 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
11721 value
= fixP
->fx_offset
;
11724 /* We are going to store value (shifted right by two) in the
11725 instruction, in a 24 bit, signed field. Thus we need to check
11726 that none of the top 8 bits of the shifted value (top 7 bits of
11727 the unshifted, unsigned value) are set, or that they are all set. */
11728 if ((value
& ~ ((offsetT
) 0x1ffffff)) != 0
11729 && ((value
& ~ ((offsetT
) 0x1ffffff)) != ~ ((offsetT
) 0x1ffffff)))
11732 /* Normally we would be stuck at this point, since we cannot store
11733 the absolute address that is the destination of the branch in the
11734 24 bits of the branch instruction. If however, we happen to know
11735 that the destination of the branch is in the same section as the
11736 branch instruction itself, then we can compute the relocation for
11737 ourselves and not have to bother the linker with it.
11739 FIXME: The test for OBJ_ELF is only here because I have not
11740 worked out how to do this for OBJ_COFF. */
11741 if (fixP
->fx_addsy
!= NULL
11742 && S_IS_DEFINED (fixP
->fx_addsy
)
11743 && S_GET_SEGMENT (fixP
->fx_addsy
) == seg
)
11745 /* Get pc relative value to go into the branch. */
11748 /* Permit a backward branch provided that enough bits
11749 are set. Allow a forwards branch, provided that
11750 enough bits are clear. */
11751 if ( (value
& ~ ((offsetT
) 0x1ffffff)) == ~ ((offsetT
) 0x1ffffff)
11752 || (value
& ~ ((offsetT
) 0x1ffffff)) == 0)
11756 if (! fixP
->fx_done
)
11758 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11759 _("GAS can't handle same-section branch dest >= 0x04000000"));
11763 value
+= SEXT24 (newval
);
11765 if ( (value
& ~ ((offsetT
) 0xffffff)) != 0
11766 && ((value
& ~ ((offsetT
) 0xffffff)) != ~ ((offsetT
) 0xffffff)))
11767 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11768 _("out of range branch"));
11770 if (seg
->use_rela_p
&& !fixP
->fx_done
)
11772 /* Must unshift the value before storing it in the addend. */
11775 fixP
->fx_offset
= value
;
11777 fixP
->fx_addnumber
= value
;
11778 newval
= newval
& 0xff000000;
11781 newval
= (value
& 0x00ffffff) | (newval
& 0xff000000);
11782 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11785 case BFD_RELOC_ARM_PCREL_BLX
:
11788 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11791 value
= fixP
->fx_offset
;
11793 hbit
= (value
>> 1) & 1;
11794 value
= (value
>> 2) & 0x00ffffff;
11795 value
= (value
+ (newval
& 0x00ffffff)) & 0x00ffffff;
11797 if (seg
->use_rela_p
&& !fixP
->fx_done
)
11799 /* Must sign-extend and unshift the value before storing
11800 it in the addend. */
11801 value
= SEXT24 (value
);
11802 value
= (value
<< 2) | hbit
;
11804 fixP
->fx_offset
= value
;
11806 fixP
->fx_addnumber
= value
;
11807 newval
= newval
& 0xfe000000;
11810 newval
= value
| (newval
& 0xfe000000) | (hbit
<< 24);
11811 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11815 case BFD_RELOC_THUMB_PCREL_BRANCH9
: /* Conditional branch. */
11816 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11818 addressT diff
= (newval
& 0xff) << 1;
11823 if ((value
& ~0xff) && ((value
& ~0xff) != ~0xff))
11824 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11825 _("branch out of range"));
11826 if (seg
->use_rela_p
&& !fixP
->fx_done
)
11829 fixP
->fx_offset
= value
;
11831 fixP
->fx_addnumber
= value
;
11832 newval
= newval
& 0xff00;
11835 newval
= (newval
& 0xff00) | ((value
& 0x1ff) >> 1);
11837 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11840 case BFD_RELOC_THUMB_PCREL_BRANCH12
: /* Unconditional branch. */
11841 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11843 addressT diff
= (newval
& 0x7ff) << 1;
11848 if ((value
& ~0x7ff) && ((value
& ~0x7ff) != ~0x7ff))
11849 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11850 _("branch out of range"));
11851 if (seg
->use_rela_p
&& !fixP
->fx_done
)
11854 fixP
->fx_offset
= value
;
11856 fixP
->fx_addnumber
= value
;
11857 newval
= newval
& 0xf800;
11860 newval
= (newval
& 0xf800) | ((value
& 0xfff) >> 1);
11862 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11865 case BFD_RELOC_THUMB_PCREL_BLX
:
11866 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
11871 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11872 newval2
= md_chars_to_number (buf
+ THUMB_SIZE
, THUMB_SIZE
);
11873 diff
= ((newval
& 0x7ff) << 12) | ((newval2
& 0x7ff) << 1);
11874 if (diff
& 0x400000)
11877 value
= fixP
->fx_offset
;
11881 if ((value
& ~0x3fffff) && ((value
& ~0x3fffff) != ~0x3fffff))
11882 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11883 _("branch with link out of range"));
11885 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
)
11886 /* For a BLX instruction, make sure that the relocation is rounded up
11887 to a word boundary. This follows the semantics of the instruction
11888 which specifies that bit 1 of the target address will come from bit
11889 1 of the base address. */
11890 value
= (value
+ 1) & ~ 1;
11892 if (seg
->use_rela_p
&& !fixP
->fx_done
)
11895 fixP
->fx_offset
= value
;
11897 fixP
->fx_addnumber
= value
;
11898 newval
= newval
& 0xf800;
11899 newval2
= newval2
& 0xf800;
11903 newval
= (newval
& 0xf800) | ((value
& 0x7fffff) >> 12);
11904 newval2
= (newval2
& 0xf800) | ((value
& 0xfff) >> 1);
11906 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11907 md_number_to_chars (buf
+ THUMB_SIZE
, newval2
, THUMB_SIZE
);
11912 if (seg
->use_rela_p
&& !fixP
->fx_done
)
11914 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11915 md_number_to_chars (buf
, value
, 1);
11919 value
= fixP
->fx_offset
;
11920 md_number_to_chars (buf
, value
, 1);
11926 if (seg
->use_rela_p
&& !fixP
->fx_done
)
11928 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11929 md_number_to_chars (buf
, value
, 2);
11933 value
= fixP
->fx_offset
;
11934 md_number_to_chars (buf
, value
, 2);
11940 case BFD_RELOC_ARM_GOT32
:
11941 case BFD_RELOC_ARM_GOTOFF
:
11942 case BFD_RELOC_ARM_TARGET2
:
11943 if (seg
->use_rela_p
&& !fixP
->fx_done
)
11945 md_number_to_chars (buf
, 0, 4);
11949 case BFD_RELOC_RVA
:
11951 case BFD_RELOC_ARM_TARGET1
:
11952 case BFD_RELOC_ARM_ROSEGREL32
:
11953 case BFD_RELOC_ARM_SBREL32
:
11954 case BFD_RELOC_32_PCREL
:
11955 if (seg
->use_rela_p
&& !fixP
->fx_done
)
11957 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11958 md_number_to_chars (buf
, value
, 4);
11962 value
= fixP
->fx_offset
;
11963 md_number_to_chars (buf
, value
, 4);
11969 case BFD_RELOC_ARM_PREL31
:
11970 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11972 newval
= md_chars_to_number (buf
, 4) & 0x80000000;
11973 if ((value
^ (value
>> 1)) & 0x40000000)
11975 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11976 _("rel31 relocation overflow"));
11978 newval
|= value
& 0x7fffffff;
11979 md_number_to_chars (buf
, newval
, 4);
11983 case BFD_RELOC_ARM_PLT32
:
11984 /* It appears the instruction is fully prepared at this point. */
11988 case BFD_RELOC_ARM_CP_OFF_IMM
:
11990 if (value
< -1023 || value
> 1023 || (value
& 3))
11991 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11992 _("illegal value for co-processor offset"));
11995 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
11996 newval
|= (value
>> 2) | (sign
? INDEX_UP
: 0);
11997 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12000 case BFD_RELOC_ARM_CP_OFF_IMM_S2
:
12002 if (value
< -255 || value
> 255)
12003 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12004 _("Illegal value for co-processor offset"));
12007 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
12008 newval
|= value
| (sign
? INDEX_UP
: 0);
12009 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12012 case BFD_RELOC_ARM_THUMB_OFFSET
:
12013 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12014 /* Exactly what ranges, and where the offset is inserted depends
12015 on the type of instruction, we can establish this from the
12017 switch (newval
>> 12)
12019 case 4: /* PC load. */
12020 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
12021 forced to zero for these loads, so we will need to round
12022 up the offset if the instruction address is not word
12023 aligned (since the final address produced must be, and
12024 we can only describe word-aligned immediate offsets). */
12026 if ((fixP
->fx_frag
->fr_address
+ fixP
->fx_where
+ value
) & 3)
12027 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12028 _("invalid offset, target not word aligned (0x%08X)"),
12029 (unsigned int) (fixP
->fx_frag
->fr_address
12030 + fixP
->fx_where
+ value
));
12032 if ((value
+ 2) & ~0x3fe)
12033 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12034 _("invalid offset, value too big (0x%08lX)"),
12037 /* Round up, since pc will be rounded down. */
12038 newval
|= (value
+ 2) >> 2;
12041 case 9: /* SP load/store. */
12042 if (value
& ~0x3fc)
12043 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12044 _("invalid offset, value too big (0x%08lX)"),
12046 newval
|= value
>> 2;
12049 case 6: /* Word load/store. */
12051 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12052 _("invalid offset, value too big (0x%08lX)"),
12054 newval
|= value
<< 4; /* 6 - 2. */
12057 case 7: /* Byte load/store. */
12059 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12060 _("invalid offset, value too big (0x%08lX)"),
12062 newval
|= value
<< 6;
12065 case 8: /* Halfword load/store. */
12067 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12068 _("invalid offset, value too big (0x%08lX)"),
12070 newval
|= value
<< 5; /* 6 - 1. */
12074 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12075 "Unable to process relocation for thumb opcode: %lx",
12076 (unsigned long) newval
);
12079 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12082 case BFD_RELOC_ARM_THUMB_ADD
:
12083 /* This is a complicated relocation, since we use it for all of
12084 the following immediate relocations:
12088 9bit ADD/SUB SP word-aligned
12089 10bit ADD PC/SP word-aligned
12091 The type of instruction being processed is encoded in the
12098 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12100 int rd
= (newval
>> 4) & 0xf;
12101 int rs
= newval
& 0xf;
12102 int subtract
= newval
& 0x8000;
12106 if (value
& ~0x1fc)
12107 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12108 _("invalid immediate for stack address calculation"));
12109 newval
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
12110 newval
|= value
>> 2;
12112 else if (rs
== REG_PC
|| rs
== REG_SP
)
12116 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12117 _("invalid immediate for address calculation (value = 0x%08lX)"),
12118 (unsigned long) value
);
12119 newval
= (rs
== REG_PC
? T_OPCODE_ADD_PC
: T_OPCODE_ADD_SP
);
12121 newval
|= value
>> 2;
12126 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12127 _("invalid 8bit immediate"));
12128 newval
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
12129 newval
|= (rd
<< 8) | value
;
12134 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12135 _("invalid 3bit immediate"));
12136 newval
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
12137 newval
|= rd
| (rs
<< 3) | (value
<< 6);
12140 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12143 case BFD_RELOC_ARM_THUMB_IMM
:
12144 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12145 switch (newval
>> 11)
12147 case 0x04: /* 8bit immediate MOV. */
12148 case 0x05: /* 8bit immediate CMP. */
12149 if (value
< 0 || value
> 255)
12150 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12151 _("invalid immediate: %ld is too large"),
12159 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12162 case BFD_RELOC_ARM_THUMB_SHIFT
:
12163 /* 5bit shift value (0..31). */
12164 if (value
< 0 || value
> 31)
12165 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12166 _("illegal Thumb shift value: %ld"), (long) value
);
12167 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xf03f;
12168 newval
|= value
<< 6;
12169 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12172 case BFD_RELOC_VTABLE_INHERIT
:
12173 case BFD_RELOC_VTABLE_ENTRY
:
12177 case BFD_RELOC_NONE
:
12179 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12180 _("bad relocation fixup type (%d)"), fixP
->fx_r_type
);
12184 /* Translate internal representation of relocation info to BFD target
12188 tc_gen_reloc (asection
* section ATTRIBUTE_UNUSED
,
12192 bfd_reloc_code_real_type code
;
12194 reloc
= xmalloc (sizeof (arelent
));
12196 reloc
->sym_ptr_ptr
= xmalloc (sizeof (asymbol
*));
12197 *reloc
->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
12198 reloc
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
12200 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12202 if (fixp
->fx_pcrel
== 0)
12203 reloc
->addend
= fixp
->fx_offset
;
12205 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
12206 #else /* OBJ_ELF */
12207 reloc
->addend
= fixp
->fx_offset
;
12210 switch (fixp
->fx_r_type
)
12213 if (fixp
->fx_pcrel
)
12215 code
= BFD_RELOC_8_PCREL
;
12220 if (fixp
->fx_pcrel
)
12222 code
= BFD_RELOC_16_PCREL
;
12227 if (fixp
->fx_pcrel
)
12229 code
= BFD_RELOC_32_PCREL
;
12233 case BFD_RELOC_ARM_PCREL_BRANCH
:
12234 case BFD_RELOC_ARM_PCREL_BLX
:
12235 case BFD_RELOC_RVA
:
12236 case BFD_RELOC_THUMB_PCREL_BRANCH9
:
12237 case BFD_RELOC_THUMB_PCREL_BRANCH12
:
12238 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
12239 case BFD_RELOC_THUMB_PCREL_BLX
:
12240 case BFD_RELOC_VTABLE_ENTRY
:
12241 case BFD_RELOC_VTABLE_INHERIT
:
12242 code
= fixp
->fx_r_type
;
12245 case BFD_RELOC_ARM_LITERAL
:
12246 case BFD_RELOC_ARM_HWLITERAL
:
12247 /* If this is called then the a literal has
12248 been referenced across a section boundary. */
12249 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12250 _("literal referenced across section boundary"));
12254 case BFD_RELOC_ARM_GOT32
:
12255 case BFD_RELOC_ARM_GOTOFF
:
12256 case BFD_RELOC_ARM_PLT32
:
12257 case BFD_RELOC_ARM_TARGET1
:
12258 case BFD_RELOC_ARM_ROSEGREL32
:
12259 case BFD_RELOC_ARM_SBREL32
:
12260 case BFD_RELOC_ARM_PREL31
:
12261 case BFD_RELOC_ARM_TARGET2
:
12262 code
= fixp
->fx_r_type
;
12266 case BFD_RELOC_ARM_IMMEDIATE
:
12267 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12268 _("internal relocation (type: IMMEDIATE) not fixed up"));
12271 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
12272 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12273 _("ADRL used for a symbol not defined in the same file"));
12276 case BFD_RELOC_ARM_OFFSET_IMM
:
12277 if (fixp
->fx_addsy
!= NULL
12278 && !S_IS_DEFINED (fixp
->fx_addsy
)
12279 && S_IS_LOCAL (fixp
->fx_addsy
))
12281 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12282 _("undefined local label `%s'"),
12283 S_GET_NAME (fixp
->fx_addsy
));
12287 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12288 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
12295 switch (fixp
->fx_r_type
)
12297 case BFD_RELOC_ARM_OFFSET_IMM8
: type
= "OFFSET_IMM8"; break;
12298 case BFD_RELOC_ARM_SHIFT_IMM
: type
= "SHIFT_IMM"; break;
12299 case BFD_RELOC_ARM_SMI
: type
= "SMI"; break;
12300 case BFD_RELOC_ARM_SWI
: type
= "SWI"; break;
12301 case BFD_RELOC_ARM_MULTI
: type
= "MULTI"; break;
12302 case BFD_RELOC_ARM_CP_OFF_IMM
: type
= "CP_OFF_IMM"; break;
12303 case BFD_RELOC_ARM_THUMB_ADD
: type
= "THUMB_ADD"; break;
12304 case BFD_RELOC_ARM_THUMB_SHIFT
: type
= "THUMB_SHIFT"; break;
12305 case BFD_RELOC_ARM_THUMB_IMM
: type
= "THUMB_IMM"; break;
12306 case BFD_RELOC_ARM_THUMB_OFFSET
: type
= "THUMB_OFFSET"; break;
12307 default: type
= _("<unknown>"); break;
12309 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12310 _("cannot represent %s relocation in this object file format"),
12317 if ((code
== BFD_RELOC_32_PCREL
|| code
== BFD_RELOC_32
)
12319 && fixp
->fx_addsy
== GOT_symbol
)
12321 code
= BFD_RELOC_ARM_GOTPC
;
12322 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
12326 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, code
);
12328 if (reloc
->howto
== NULL
)
12330 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12331 _("cannot represent %s relocation in this object file format"),
12332 bfd_get_reloc_code_name (code
));
12336 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12337 vtable entry to be used in the relocation's section offset. */
12338 if (fixp
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
12339 reloc
->address
= fixp
->fx_offset
;
12345 md_estimate_size_before_relax (fragS
* fragP ATTRIBUTE_UNUSED
,
12346 segT segtype ATTRIBUTE_UNUSED
)
12348 as_fatal (_("md_estimate_size_before_relax\n"));
12352 /* We need to be able to fix up arbitrary expressions in some statements.
12353 This is so that we can handle symbols that are an arbitrary distance from
12354 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
12355 which returns part of an address in a form which will be valid for
12356 a data instruction. We do this by pushing the expression into a symbol
12357 in the expr_section, and creating a fix for that. */
12360 fix_new_arm (fragS
* frag
,
12368 arm_fix_data
* arm_data
;
12376 new_fix
= fix_new_exp (frag
, where
, size
, exp
, pc_rel
, reloc
);
12380 new_fix
= fix_new (frag
, where
, size
, make_expr_symbol (exp
), 0,
12385 /* Mark whether the fix is to a THUMB instruction, or an ARM
12387 arm_data
= obstack_alloc (& notes
, sizeof (arm_fix_data
));
12388 new_fix
->tc_fix_data
= (PTR
) arm_data
;
12389 arm_data
->thumb_mode
= thumb_mode
;
12393 output_inst (const char * str
)
12399 as_bad ("%s -- `%s'", inst
.error
, str
);
12403 to
= frag_more (inst
.size
);
12405 if (thumb_mode
&& (inst
.size
> THUMB_SIZE
))
12407 assert (inst
.size
== (2 * THUMB_SIZE
));
12408 md_number_to_chars (to
, inst
.instruction
>> 16, THUMB_SIZE
);
12409 md_number_to_chars (to
+ THUMB_SIZE
, inst
.instruction
, THUMB_SIZE
);
12411 else if (inst
.size
> INSN_SIZE
)
12413 assert (inst
.size
== (2 * INSN_SIZE
));
12414 md_number_to_chars (to
, inst
.instruction
, INSN_SIZE
);
12415 md_number_to_chars (to
+ INSN_SIZE
, inst
.instruction
, INSN_SIZE
);
12418 md_number_to_chars (to
, inst
.instruction
, inst
.size
);
12420 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
12421 fix_new_arm (frag_now
, to
- frag_now
->fr_literal
,
12422 inst
.size
, & inst
.reloc
.exp
, inst
.reloc
.pc_rel
,
12426 dwarf2_emit_insn (inst
.size
);
12431 md_assemble (char * str
)
12437 /* Align the instruction.
12438 This may not be the right thing to do but ... */
12443 /* Align the previous label if needed. */
12444 if (last_label_seen
!= NULL
)
12446 symbol_set_frag (last_label_seen
, frag_now
);
12447 S_SET_VALUE (last_label_seen
, (valueT
) frag_now_fix ());
12448 S_SET_SEGMENT (last_label_seen
, now_seg
);
12451 memset (&inst
, '\0', sizeof (inst
));
12452 inst
.reloc
.type
= BFD_RELOC_NONE
;
12454 skip_whitespace (str
);
12456 /* Scan up to the end of the op-code, which must end in white space or
12458 for (start
= p
= str
; *p
!= '\0'; p
++)
12464 as_bad (_("no operator -- statement `%s'\n"), str
);
12470 const struct thumb_opcode
* opcode
;
12474 opcode
= (const struct thumb_opcode
*) hash_find (arm_tops_hsh
, str
);
12479 /* Check that this instruction is supported for this CPU. */
12480 if (thumb_mode
== 1 && (opcode
->variant
& cpu_variant
) == 0)
12482 as_bad (_("selected processor does not support `%s'"), str
);
12486 mapping_state (MAP_THUMB
);
12487 inst
.instruction
= opcode
->value
;
12488 inst
.size
= opcode
->size
;
12496 const struct asm_opcode
* opcode
;
12500 opcode
= (const struct asm_opcode
*) hash_find (arm_ops_hsh
, str
);
12505 /* Check that this instruction is supported for this CPU. */
12506 if ((opcode
->variant
& cpu_variant
) == 0)
12508 as_bad (_("selected processor does not support `%s'"), str
);
12512 mapping_state (MAP_ARM
);
12513 inst
.instruction
= opcode
->value
;
12514 inst
.size
= INSN_SIZE
;
12521 /* It wasn't an instruction, but it might be a register alias of the form
12523 if (create_register_alias (str
, p
))
12526 as_bad (_("bad instruction `%s'"), start
);
12530 Invocation line includes a switch not recognized by the base assembler.
12531 See if it's a processor-specific option.
12533 This routine is somewhat complicated by the need for backwards
12534 compatibility (since older releases of gcc can't be changed).
12535 The new options try to make the interface as compatible as
12538 New options (supported) are:
12540 -mcpu=<cpu name> Assemble for selected processor
12541 -march=<architecture name> Assemble for selected architecture
12542 -mfpu=<fpu architecture> Assemble for selected FPU.
12543 -EB/-mbig-endian Big-endian
12544 -EL/-mlittle-endian Little-endian
12545 -k Generate PIC code
12546 -mthumb Start in Thumb mode
12547 -mthumb-interwork Code supports ARM/Thumb interworking
12549 For now we will also provide support for:
12551 -mapcs-32 32-bit Program counter
12552 -mapcs-26 26-bit Program counter
12553 -macps-float Floats passed in FP registers
12554 -mapcs-reentrant Reentrant code
12556 (sometime these will probably be replaced with -mapcs=<list of options>
12557 and -matpcs=<list of options>)
12559 The remaining options are only supported for back-wards compatibility.
12560 Cpu variants, the arm part is optional:
12561 -m[arm]1 Currently not supported.
12562 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
12563 -m[arm]3 Arm 3 processor
12564 -m[arm]6[xx], Arm 6 processors
12565 -m[arm]7[xx][t][[d]m] Arm 7 processors
12566 -m[arm]8[10] Arm 8 processors
12567 -m[arm]9[20][tdmi] Arm 9 processors
12568 -mstrongarm[110[0]] StrongARM processors
12569 -mxscale XScale processors
12570 -m[arm]v[2345[t[e]]] Arm architectures
12571 -mall All (except the ARM1)
12573 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
12574 -mfpe-old (No float load/store multiples)
12575 -mvfpxd VFP Single precision
12577 -mno-fpu Disable all floating point instructions
12579 The following CPU names are recognized:
12580 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
12581 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
12582 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
12583 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
12584 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
12585 arm10t arm10e, arm1020t, arm1020e, arm10200e,
12586 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
12590 const char * md_shortopts
= "m:k";
12592 #ifdef ARM_BI_ENDIAN
12593 #define OPTION_EB (OPTION_MD_BASE + 0)
12594 #define OPTION_EL (OPTION_MD_BASE + 1)
12596 #if TARGET_BYTES_BIG_ENDIAN
12597 #define OPTION_EB (OPTION_MD_BASE + 0)
12599 #define OPTION_EL (OPTION_MD_BASE + 1)
12603 struct option md_longopts
[] =
12606 {"EB", no_argument
, NULL
, OPTION_EB
},
12609 {"EL", no_argument
, NULL
, OPTION_EL
},
12611 {NULL
, no_argument
, NULL
, 0}
12614 size_t md_longopts_size
= sizeof (md_longopts
);
12616 struct arm_option_table
12618 char *option
; /* Option name to match. */
12619 char *help
; /* Help information. */
12620 int *var
; /* Variable to change. */
12621 int value
; /* What to change it to. */
12622 char *deprecated
; /* If non-null, print this message. */
12625 struct arm_option_table arm_opts
[] =
12627 {"k", N_("generate PIC code"), &pic_code
, 1, NULL
},
12628 {"mthumb", N_("assemble Thumb code"), &thumb_mode
, 1, NULL
},
12629 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
12630 &support_interwork
, 1, NULL
},
12631 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26
, 0, NULL
},
12632 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26
, 1, NULL
},
12633 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float
,
12635 {"mapcs-reentrant", N_("re-entrant code"), &pic_code
, 1, NULL
},
12636 {"matpcs", N_("code is ATPCS conformant"), &atpcs
, 1, NULL
},
12637 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian
, 1, NULL
},
12638 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian
, 1,
12641 /* These are recognized by the assembler, but have no affect on code. */
12642 {"mapcs-frame", N_("use frame pointer"), NULL
, 0, NULL
},
12643 {"mapcs-stack-check", N_("use stack size checking"), NULL
, 0, NULL
},
12645 /* DON'T add any new processors to this list -- we want the whole list
12646 to go away... Add them to the processors table instead. */
12647 {"marm1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
12648 {"m1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
12649 {"marm2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
12650 {"m2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
12651 {"marm250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
12652 {"m250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
12653 {"marm3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
12654 {"m3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
12655 {"marm6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
12656 {"m6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
12657 {"marm600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
12658 {"m600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
12659 {"marm610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
12660 {"m610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
12661 {"marm620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
12662 {"m620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
12663 {"marm7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
12664 {"m7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
12665 {"marm70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
12666 {"m70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
12667 {"marm700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
12668 {"m700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
12669 {"marm700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
12670 {"m700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
12671 {"marm710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
12672 {"m710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
12673 {"marm710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
12674 {"m710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
12675 {"marm720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
12676 {"m720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
12677 {"marm7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
12678 {"m7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
12679 {"marm7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
12680 {"m7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
12681 {"marm7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
12682 {"m7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
12683 {"marm7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
12684 {"m7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
12685 {"marm7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
12686 {"m7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
12687 {"marm7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
12688 {"m7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
12689 {"marm7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
12690 {"m7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
12691 {"marm7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
12692 {"m7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
12693 {"marm7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12694 {"m7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12695 {"marm7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12696 {"m7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12697 {"marm710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
12698 {"m710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
12699 {"marm720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
12700 {"m720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
12701 {"marm740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
12702 {"m740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
12703 {"marm8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
12704 {"m8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
12705 {"marm810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
12706 {"m810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
12707 {"marm9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
12708 {"m9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
12709 {"marm9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
12710 {"m9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
12711 {"marm920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
12712 {"m920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
12713 {"marm940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
12714 {"m940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
12715 {"mstrongarm", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=strongarm")},
12716 {"mstrongarm110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
12717 N_("use -mcpu=strongarm110")},
12718 {"mstrongarm1100", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
12719 N_("use -mcpu=strongarm1100")},
12720 {"mstrongarm1110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
12721 N_("use -mcpu=strongarm1110")},
12722 {"mxscale", NULL
, &legacy_cpu
, ARM_ARCH_XSCALE
, N_("use -mcpu=xscale")},
12723 {"miwmmxt", NULL
, &legacy_cpu
, ARM_ARCH_IWMMXT
, N_("use -mcpu=iwmmxt")},
12724 {"mall", NULL
, &legacy_cpu
, ARM_ANY
, N_("use -mcpu=all")},
12726 /* Architecture variants -- don't add any more to this list either. */
12727 {"mv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
12728 {"marmv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
12729 {"mv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
12730 {"marmv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
12731 {"mv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
12732 {"marmv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
12733 {"mv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
12734 {"marmv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
12735 {"mv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
12736 {"marmv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
12737 {"mv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
12738 {"marmv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
12739 {"mv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
12740 {"marmv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
12741 {"mv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
12742 {"marmv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
12743 {"mv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
12744 {"marmv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
12746 /* Floating point variants -- don't add any more to this list either. */
12747 {"mfpe-old", NULL
, &legacy_fpu
, FPU_ARCH_FPE
, N_("use -mfpu=fpe")},
12748 {"mfpa10", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa10")},
12749 {"mfpa11", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa11")},
12750 {"mno-fpu", NULL
, &legacy_fpu
, 0,
12751 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
12753 {NULL
, NULL
, NULL
, 0, NULL
}
12756 struct arm_cpu_option_table
12760 /* For some CPUs we assume an FPU unless the user explicitly sets
12765 /* This list should, at a minimum, contain all the cpu names
12766 recognized by GCC. */
12767 static struct arm_cpu_option_table arm_cpus
[] =
12769 {"all", ARM_ANY
, FPU_ARCH_FPA
},
12770 {"arm1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
12771 {"arm2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
12772 {"arm250", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
12773 {"arm3", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
12774 {"arm6", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12775 {"arm60", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12776 {"arm600", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12777 {"arm610", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12778 {"arm620", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12779 {"arm7", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12780 {"arm7m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
12781 {"arm7d", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12782 {"arm7dm", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
12783 {"arm7di", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12784 {"arm7dmi", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
12785 {"arm70", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12786 {"arm700", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12787 {"arm700i", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12788 {"arm710", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12789 {"arm710t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12790 {"arm720", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12791 {"arm720t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12792 {"arm740t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12793 {"arm710c", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12794 {"arm7100", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12795 {"arm7500", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12796 {"arm7500fe", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12797 {"arm7t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12798 {"arm7tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12799 {"arm7tdmi-s", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12800 {"arm8", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12801 {"arm810", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12802 {"strongarm", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12803 {"strongarm1", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12804 {"strongarm110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12805 {"strongarm1100", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12806 {"strongarm1110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12807 {"arm9", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12808 {"arm920", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12809 {"arm920t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12810 {"arm922t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12811 {"arm940t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12812 {"arm9tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12813 /* For V5 or later processors we default to using VFP; but the user
12814 should really set the FPU type explicitly. */
12815 {"arm9e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
12816 {"arm9e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12817 {"arm926ej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
12818 {"arm926ejs", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
12819 {"arm926ej-s", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
12820 {"arm946e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
12821 {"arm946e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12822 {"arm966e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
12823 {"arm966e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12824 {"arm10t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
12825 {"arm10e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12826 {"arm1020", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12827 {"arm1020t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
12828 {"arm1020e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12829 {"arm1026ejs", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
12830 {"arm1026ej-s", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
12831 {"arm1136js", ARM_ARCH_V6
, FPU_NONE
},
12832 {"arm1136j-s", ARM_ARCH_V6
, FPU_NONE
},
12833 {"arm1136jfs", ARM_ARCH_V6
, FPU_ARCH_VFP_V2
},
12834 {"arm1136jf-s", ARM_ARCH_V6
, FPU_ARCH_VFP_V2
},
12835 {"mpcore", ARM_ARCH_V6K
, FPU_ARCH_VFP_V2
},
12836 {"mpcorenovfp", ARM_ARCH_V6K
, FPU_NONE
},
12837 {"arm1176jz-s", ARM_ARCH_V6ZK
, FPU_NONE
},
12838 {"arm1176jzf-s", ARM_ARCH_V6ZK
, FPU_ARCH_VFP_V2
},
12839 /* ??? XSCALE is really an architecture. */
12840 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
12841 /* ??? iwmmxt is not a processor. */
12842 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP_V2
},
12843 {"i80200", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
12845 {"ep9312", ARM_ARCH_V4T
| ARM_CEXT_MAVERICK
, FPU_ARCH_MAVERICK
},
12849 struct arm_arch_option_table
12856 /* This list should, at a minimum, contain all the architecture names
12857 recognized by GCC. */
12858 static struct arm_arch_option_table arm_archs
[] =
12860 {"all", ARM_ANY
, FPU_ARCH_FPA
},
12861 {"armv1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
12862 {"armv2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
12863 {"armv2a", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
12864 {"armv2s", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
12865 {"armv3", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12866 {"armv3m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
12867 {"armv4", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12868 {"armv4xm", ARM_ARCH_V4xM
, FPU_ARCH_FPA
},
12869 {"armv4t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12870 {"armv4txm", ARM_ARCH_V4TxM
, FPU_ARCH_FPA
},
12871 {"armv5", ARM_ARCH_V5
, FPU_ARCH_VFP
},
12872 {"armv5t", ARM_ARCH_V5T
, FPU_ARCH_VFP
},
12873 {"armv5txm", ARM_ARCH_V5TxM
, FPU_ARCH_VFP
},
12874 {"armv5te", ARM_ARCH_V5TE
, FPU_ARCH_VFP
},
12875 {"armv5texp", ARM_ARCH_V5TExP
, FPU_ARCH_VFP
},
12876 {"armv5tej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP
},
12877 {"armv6", ARM_ARCH_V6
, FPU_ARCH_VFP
},
12878 {"armv6j", ARM_ARCH_V6
, FPU_ARCH_VFP
},
12879 {"armv6k", ARM_ARCH_V6K
, FPU_ARCH_VFP
},
12880 {"armv6z", ARM_ARCH_V6Z
, FPU_ARCH_VFP
},
12881 {"armv6zk", ARM_ARCH_V6ZK
, FPU_ARCH_VFP
},
12882 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP
},
12883 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP
},
12887 /* ISA extensions in the co-processor space. */
12888 struct arm_arch_extension_table
12894 static struct arm_arch_extension_table arm_extensions
[] =
12896 {"maverick", ARM_CEXT_MAVERICK
},
12897 {"xscale", ARM_CEXT_XSCALE
},
12898 {"iwmmxt", ARM_CEXT_IWMMXT
},
12902 struct arm_fpu_option_table
12908 /* This list should, at a minimum, contain all the fpu names
12909 recognized by GCC. */
12910 static struct arm_fpu_option_table arm_fpus
[] =
12912 {"softfpa", FPU_NONE
},
12913 {"fpe", FPU_ARCH_FPE
},
12914 {"fpe2", FPU_ARCH_FPE
},
12915 {"fpe3", FPU_ARCH_FPA
}, /* Third release supports LFM/SFM. */
12916 {"fpa", FPU_ARCH_FPA
},
12917 {"fpa10", FPU_ARCH_FPA
},
12918 {"fpa11", FPU_ARCH_FPA
},
12919 {"arm7500fe", FPU_ARCH_FPA
},
12920 {"softvfp", FPU_ARCH_VFP
},
12921 {"softvfp+vfp", FPU_ARCH_VFP_V2
},
12922 {"vfp", FPU_ARCH_VFP_V2
},
12923 {"vfp9", FPU_ARCH_VFP_V2
},
12924 {"vfp10", FPU_ARCH_VFP_V2
},
12925 {"vfp10-r0", FPU_ARCH_VFP_V1
},
12926 {"vfpxd", FPU_ARCH_VFP_V1xD
},
12927 {"arm1020t", FPU_ARCH_VFP_V1
},
12928 {"arm1020e", FPU_ARCH_VFP_V2
},
12929 {"arm1136jfs", FPU_ARCH_VFP_V2
},
12930 {"arm1136jf-s", FPU_ARCH_VFP_V2
},
12931 {"maverick", FPU_ARCH_MAVERICK
},
12935 struct arm_float_abi_option_table
12941 static struct arm_float_abi_option_table arm_float_abis
[] =
12943 {"hard", ARM_FLOAT_ABI_HARD
},
12944 {"softfp", ARM_FLOAT_ABI_SOFTFP
},
12945 {"soft", ARM_FLOAT_ABI_SOFT
},
12949 struct arm_eabi_option_table
12952 unsigned int value
;
12956 /* We only know how to output GNU and ver 4 (AAELF) formats. */
12957 static struct arm_eabi_option_table arm_eabis
[] =
12959 {"gnu", EF_ARM_EABI_UNKNOWN
},
12960 {"4", EF_ARM_EABI_VER4
},
12965 struct arm_long_option_table
12967 char * option
; /* Substring to match. */
12968 char * help
; /* Help information. */
12969 int (* func
) (char * subopt
); /* Function to decode sub-option. */
12970 char * deprecated
; /* If non-null, print this message. */
12974 arm_parse_extension (char * str
, int * opt_p
)
12976 while (str
!= NULL
&& *str
!= 0)
12978 struct arm_arch_extension_table
* opt
;
12984 as_bad (_("invalid architectural extension"));
12989 ext
= strchr (str
, '+');
12992 optlen
= ext
- str
;
12994 optlen
= strlen (str
);
12998 as_bad (_("missing architectural extension"));
13002 for (opt
= arm_extensions
; opt
->name
!= NULL
; opt
++)
13003 if (strncmp (opt
->name
, str
, optlen
) == 0)
13005 *opt_p
|= opt
->value
;
13009 if (opt
->name
== NULL
)
13011 as_bad (_("unknown architectural extnsion `%s'"), str
);
13022 arm_parse_cpu (char * str
)
13024 struct arm_cpu_option_table
* opt
;
13025 char * ext
= strchr (str
, '+');
13029 optlen
= ext
- str
;
13031 optlen
= strlen (str
);
13035 as_bad (_("missing cpu name `%s'"), str
);
13039 for (opt
= arm_cpus
; opt
->name
!= NULL
; opt
++)
13040 if (strncmp (opt
->name
, str
, optlen
) == 0)
13042 mcpu_cpu_opt
= opt
->value
;
13043 mcpu_fpu_opt
= opt
->default_fpu
;
13046 return arm_parse_extension (ext
, &mcpu_cpu_opt
);
13051 as_bad (_("unknown cpu `%s'"), str
);
13056 arm_parse_arch (char * str
)
13058 struct arm_arch_option_table
*opt
;
13059 char *ext
= strchr (str
, '+');
13063 optlen
= ext
- str
;
13065 optlen
= strlen (str
);
13069 as_bad (_("missing architecture name `%s'"), str
);
13074 for (opt
= arm_archs
; opt
->name
!= NULL
; opt
++)
13075 if (streq (opt
->name
, str
))
13077 march_cpu_opt
= opt
->value
;
13078 march_fpu_opt
= opt
->default_fpu
;
13081 return arm_parse_extension (ext
, &march_cpu_opt
);
13086 as_bad (_("unknown architecture `%s'\n"), str
);
13091 arm_parse_fpu (char * str
)
13093 struct arm_fpu_option_table
* opt
;
13095 for (opt
= arm_fpus
; opt
->name
!= NULL
; opt
++)
13096 if (streq (opt
->name
, str
))
13098 mfpu_opt
= opt
->value
;
13102 as_bad (_("unknown floating point format `%s'\n"), str
);
13107 arm_parse_float_abi (char * str
)
13109 struct arm_float_abi_option_table
* opt
;
13111 for (opt
= arm_float_abis
; opt
->name
!= NULL
; opt
++)
13112 if (streq (opt
->name
, str
))
13114 mfloat_abi_opt
= opt
->value
;
13118 as_bad (_("unknown floating point abi `%s'\n"), str
);
13124 arm_parse_eabi (char * str
)
13126 struct arm_eabi_option_table
*opt
;
13128 for (opt
= arm_eabis
; opt
->name
!= NULL
; opt
++)
13129 if (streq (opt
->name
, str
))
13131 meabi_flags
= opt
->value
;
13134 as_bad (_("unknown EABI `%s'\n"), str
);
13139 struct arm_long_option_table arm_long_opts
[] =
13141 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13142 arm_parse_cpu
, NULL
},
13143 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13144 arm_parse_arch
, NULL
},
13145 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13146 arm_parse_fpu
, NULL
},
13147 {"mfloat-abi=", N_("<abi>\t assemble for floating point ABI <abi>"),
13148 arm_parse_float_abi
, NULL
},
13150 {"meabi=", N_("<ver>\t assemble for eabi version <ver>"),
13151 arm_parse_eabi
, NULL
},
13153 {NULL
, NULL
, 0, NULL
}
13157 md_parse_option (int c
, char * arg
)
13159 struct arm_option_table
*opt
;
13160 struct arm_long_option_table
*lopt
;
13166 target_big_endian
= 1;
13172 target_big_endian
= 0;
13177 /* Listing option. Just ignore these, we don't support additional
13182 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
13184 if (c
== opt
->option
[0]
13185 && ((arg
== NULL
&& opt
->option
[1] == 0)
13186 || streq (arg
, opt
->option
+ 1)))
13188 #if WARN_DEPRECATED
13189 /* If the option is deprecated, tell the user. */
13190 if (opt
->deprecated
!= NULL
)
13191 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
,
13192 arg
? arg
: "", _(opt
->deprecated
));
13195 if (opt
->var
!= NULL
)
13196 *opt
->var
= opt
->value
;
13202 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
13204 /* These options are expected to have an argument. */
13205 if (c
== lopt
->option
[0]
13207 && strncmp (arg
, lopt
->option
+ 1,
13208 strlen (lopt
->option
+ 1)) == 0)
13210 #if WARN_DEPRECATED
13211 /* If the option is deprecated, tell the user. */
13212 if (lopt
->deprecated
!= NULL
)
13213 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
, arg
,
13214 _(lopt
->deprecated
));
13217 /* Call the sup-option parser. */
13218 return lopt
->func (arg
+ strlen (lopt
->option
) - 1);
13229 md_show_usage (FILE * fp
)
13231 struct arm_option_table
*opt
;
13232 struct arm_long_option_table
*lopt
;
13234 fprintf (fp
, _(" ARM-specific assembler options:\n"));
13236 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
13237 if (opt
->help
!= NULL
)
13238 fprintf (fp
, " -%-23s%s\n", opt
->option
, _(opt
->help
));
13240 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
13241 if (lopt
->help
!= NULL
)
13242 fprintf (fp
, " -%s%s\n", lopt
->option
, _(lopt
->help
));
13246 -EB assemble code for a big-endian cpu\n"));
13251 -EL assemble code for a little-endian cpu\n"));
13255 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13258 cons_fix_new_arm (fragS
* frag
,
13263 bfd_reloc_code_real_type type
;
13267 FIXME: @@ Should look at CPU word size. */
13271 type
= BFD_RELOC_8
;
13274 type
= BFD_RELOC_16
;
13278 type
= BFD_RELOC_32
;
13281 type
= BFD_RELOC_64
;
13285 fix_new_exp (frag
, where
, (int) size
, exp
, pcrel
, type
);
13288 /* A good place to do this, although this was probably not intended
13289 for this kind of use. We need to dump the literal pool before
13290 references are made to a null symbol pointer. */
13295 literal_pool
* pool
;
13297 for (pool
= list_of_pools
; pool
; pool
= pool
->next
)
13299 /* Put it at the end of the relevent section. */
13300 subseg_set (pool
->section
, pool
->sub_section
);
13302 arm_elf_change_section ();
13309 arm_start_line_hook (void)
13311 last_label_seen
= NULL
;
13315 arm_frob_label (symbolS
* sym
)
13317 last_label_seen
= sym
;
13319 ARM_SET_THUMB (sym
, thumb_mode
);
13321 #if defined OBJ_COFF || defined OBJ_ELF
13322 ARM_SET_INTERWORK (sym
, support_interwork
);
13325 /* Note - do not allow local symbols (.Lxxx) to be labeled
13326 as Thumb functions. This is because these labels, whilst
13327 they exist inside Thumb code, are not the entry points for
13328 possible ARM->Thumb calls. Also, these labels can be used
13329 as part of a computed goto or switch statement. eg gcc
13330 can generate code that looks like this:
13332 ldr r2, [pc, .Laaa]
13342 The first instruction loads the address of the jump table.
13343 The second instruction converts a table index into a byte offset.
13344 The third instruction gets the jump address out of the table.
13345 The fourth instruction performs the jump.
13347 If the address stored at .Laaa is that of a symbol which has the
13348 Thumb_Func bit set, then the linker will arrange for this address
13349 to have the bottom bit set, which in turn would mean that the
13350 address computation performed by the third instruction would end
13351 up with the bottom bit set. Since the ARM is capable of unaligned
13352 word loads, the instruction would then load the incorrect address
13353 out of the jump table, and chaos would ensue. */
13354 if (label_is_thumb_function_name
13355 && (S_GET_NAME (sym
)[0] != '.' || S_GET_NAME (sym
)[1] != 'L')
13356 && (bfd_get_section_flags (stdoutput
, now_seg
) & SEC_CODE
) != 0)
13358 /* When the address of a Thumb function is taken the bottom
13359 bit of that address should be set. This will allow
13360 interworking between Arm and Thumb functions to work
13363 THUMB_SET_FUNC (sym
, 1);
13365 label_is_thumb_function_name
= FALSE
;
13369 /* Adjust the symbol table. This marks Thumb symbols as distinct from
13373 arm_adjust_symtab (void)
13378 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
13380 if (ARM_IS_THUMB (sym
))
13382 if (THUMB_IS_FUNC (sym
))
13384 /* Mark the symbol as a Thumb function. */
13385 if ( S_GET_STORAGE_CLASS (sym
) == C_STAT
13386 || S_GET_STORAGE_CLASS (sym
) == C_LABEL
) /* This can happen! */
13387 S_SET_STORAGE_CLASS (sym
, C_THUMBSTATFUNC
);
13389 else if (S_GET_STORAGE_CLASS (sym
) == C_EXT
)
13390 S_SET_STORAGE_CLASS (sym
, C_THUMBEXTFUNC
);
13392 as_bad (_("%s: unexpected function type: %d"),
13393 S_GET_NAME (sym
), S_GET_STORAGE_CLASS (sym
));
13395 else switch (S_GET_STORAGE_CLASS (sym
))
13398 S_SET_STORAGE_CLASS (sym
, C_THUMBEXT
);
13401 S_SET_STORAGE_CLASS (sym
, C_THUMBSTAT
);
13404 S_SET_STORAGE_CLASS (sym
, C_THUMBLABEL
);
13412 if (ARM_IS_INTERWORK (sym
))
13413 coffsymbol (symbol_get_bfdsym (sym
))->native
->u
.syment
.n_flags
= 0xFF;
13420 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
13422 if (ARM_IS_THUMB (sym
))
13424 elf_symbol_type
* elf_sym
;
13426 elf_sym
= elf_symbol (symbol_get_bfdsym (sym
));
13427 bind
= ELF_ST_BIND (elf_sym
);
13429 /* If it's a .thumb_func, declare it as so,
13430 otherwise tag label as .code 16. */
13431 if (THUMB_IS_FUNC (sym
))
13432 elf_sym
->internal_elf_sym
.st_info
=
13433 ELF_ST_INFO (bind
, STT_ARM_TFUNC
);
13435 elf_sym
->internal_elf_sym
.st_info
=
13436 ELF_ST_INFO (bind
, STT_ARM_16BIT
);
13443 arm_data_in_code (void)
13445 if (thumb_mode
&& ! strncmp (input_line_pointer
+ 1, "data:", 5))
13447 *input_line_pointer
= '/';
13448 input_line_pointer
+= 5;
13449 *input_line_pointer
= 0;
13457 arm_canonicalize_symbol_name (char * name
)
13461 if (thumb_mode
&& (len
= strlen (name
)) > 5
13462 && streq (name
+ len
- 5, "/data"))
13463 *(name
+ len
- 5) = 0;
13468 #if defined OBJ_COFF || defined OBJ_ELF
13470 arm_validate_fix (fixS
* fixP
)
13472 /* If the destination of the branch is a defined symbol which does not have
13473 the THUMB_FUNC attribute, then we must be calling a function which has
13474 the (interfacearm) attribute. We look for the Thumb entry point to that
13475 function and change the branch to refer to that function instead. */
13476 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
13477 && fixP
->fx_addsy
!= NULL
13478 && S_IS_DEFINED (fixP
->fx_addsy
)
13479 && ! THUMB_IS_FUNC (fixP
->fx_addsy
))
13481 fixP
->fx_addsy
= find_real_start (fixP
->fx_addsy
);
13487 arm_force_relocation (struct fix
* fixp
)
13489 #if defined (OBJ_COFF) && defined (TE_PE)
13490 if (fixp
->fx_r_type
== BFD_RELOC_RVA
)
13494 if (fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
13495 || fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
13496 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
13497 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
)
13501 /* Resolve these relocations even if the symbol is extern or weak. */
13502 if (fixp
->fx_r_type
== BFD_RELOC_ARM_IMMEDIATE
13503 || fixp
->fx_r_type
== BFD_RELOC_ARM_OFFSET_IMM
13504 || fixp
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
13507 return generic_force_reloc (fixp
);
13511 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
13512 local labels from being added to the output symbol table when they
13513 are used with the ADRL pseudo op. The ADRL relocation should always
13514 be resolved before the binbary is emitted, so it is safe to say that
13515 it is adjustable. */
13518 arm_fix_adjustable (fixS
* fixP
)
13520 if (fixP
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
13527 /* Relocations against Thumb function names must be left unadjusted,
13528 so that the linker can use this information to correctly set the
13529 bottom bit of their addresses. The MIPS version of this function
13530 also prevents relocations that are mips-16 specific, but I do not
13531 know why it does this.
13534 There is one other problem that ought to be addressed here, but
13535 which currently is not: Taking the address of a label (rather
13536 than a function) and then later jumping to that address. Such
13537 addresses also ought to have their bottom bit set (assuming that
13538 they reside in Thumb code), but at the moment they will not. */
13541 arm_fix_adjustable (fixS
* fixP
)
13543 if (fixP
->fx_addsy
== NULL
)
13546 if (THUMB_IS_FUNC (fixP
->fx_addsy
)
13547 && fixP
->fx_subsy
== NULL
)
13550 /* We need the symbol name for the VTABLE entries. */
13551 if ( fixP
->fx_r_type
== BFD_RELOC_VTABLE_INHERIT
13552 || fixP
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
13555 /* Don't allow symbols to be discarded on GOT related relocs. */
13556 if (fixP
->fx_r_type
== BFD_RELOC_ARM_PLT32
13557 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOT32
13558 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOTOFF
13559 || fixP
->fx_r_type
== BFD_RELOC_ARM_TARGET2
)
13566 elf32_arm_target_format (void)
13569 return (target_big_endian
13570 ? "elf32-bigarm-symbian"
13571 : "elf32-littlearm-symbian");
13572 #elif defined (TE_VXWORKS)
13573 return (target_big_endian
13574 ? "elf32-bigarm-vxworks"
13575 : "elf32-littlearm-vxworks");
13577 if (target_big_endian
)
13578 return "elf32-bigarm";
13580 return "elf32-littlearm";
13585 armelf_frob_symbol (symbolS
* symp
,
13588 elf_frob_symbol (symp
, puntp
);
13592 s_arm_elf_cons (int nbytes
)
13596 #ifdef md_flush_pending_output
13597 md_flush_pending_output ();
13600 if (is_it_end_of_statement ())
13602 demand_empty_rest_of_line ();
13606 #ifdef md_cons_align
13607 md_cons_align (nbytes
);
13610 mapping_state (MAP_DATA
);
13613 bfd_reloc_code_real_type reloc
;
13615 expression (& exp
);
13617 if (exp
.X_op
== O_symbol
13618 && * input_line_pointer
== '('
13619 && (reloc
= arm_parse_reloc ()) != BFD_RELOC_UNUSED
)
13621 reloc_howto_type
*howto
= bfd_reloc_type_lookup (stdoutput
, reloc
);
13622 int size
= bfd_get_reloc_size (howto
);
13625 as_bad ("%s relocations do not fit in %d bytes",
13626 howto
->name
, nbytes
);
13629 char *p
= frag_more ((int) nbytes
);
13630 int offset
= nbytes
- size
;
13632 fix_new_exp (frag_now
, p
- frag_now
->fr_literal
+ offset
, size
,
13637 emit_expr (&exp
, (unsigned int) nbytes
);
13639 while (*input_line_pointer
++ == ',');
13641 /* Put terminator back into stream. */
13642 input_line_pointer
--;
13643 demand_empty_rest_of_line ();
13647 /* Parse a .rel31 directive. */
13650 s_arm_rel31 (int ignored ATTRIBUTE_UNUSED
)
13656 SKIP_WHITESPACE ();
13659 if (*input_line_pointer
== '1')
13660 highbit
= 0x80000000;
13661 else if (*input_line_pointer
!= '0')
13662 as_bad (_("expected 0 or 1"));
13664 input_line_pointer
++;
13665 SKIP_WHITESPACE ();
13666 if (*input_line_pointer
!= ',')
13667 as_bad (_("missing comma"));
13668 input_line_pointer
++;
13670 #ifdef md_flush_pending_output
13671 md_flush_pending_output ();
13674 #ifdef md_cons_align
13678 mapping_state (MAP_DATA
);
13683 md_number_to_chars (p
, highbit
, 4);
13684 fix_new_arm (frag_now
, p
- frag_now
->fr_literal
, 4, &exp
, 1,
13685 BFD_RELOC_ARM_PREL31
);
13687 demand_empty_rest_of_line ();
13690 /* Code to deal with unwinding tables. */
13692 static void add_unwind_adjustsp (offsetT
);
13694 /* Switch to section NAME and create section if necessary. It's
13695 rather ugly that we have to manipulate input_line_pointer but I
13696 don't see any other way to accomplish the same thing without
13697 changing obj-elf.c (which may be the Right Thing, in the end).
13698 Copied from tc-ia64.c. */
13701 set_section (char *name
)
13703 char *saved_input_line_pointer
;
13705 saved_input_line_pointer
= input_line_pointer
;
13706 input_line_pointer
= name
;
13707 obj_elf_section (0);
13708 input_line_pointer
= saved_input_line_pointer
;
13711 /* Cenerate and deferred unwind frame offset. */
13714 flush_pending_unwind (void)
13718 offset
= unwind
.pending_offset
;
13719 unwind
.pending_offset
= 0;
13721 add_unwind_adjustsp (offset
);
13724 /* Add an opcode to this list for this function. Two-byte opcodes should
13725 be passed as op[0] << 8 | op[1]. The list of opcodes is built in reverse
13729 add_unwind_opcode (valueT op
, int length
)
13731 /* Add any deferred stack adjustment. */
13732 if (unwind
.pending_offset
)
13733 flush_pending_unwind ();
13735 unwind
.sp_restored
= 0;
13737 if (unwind
.opcode_count
+ length
> unwind
.opcode_alloc
)
13739 unwind
.opcode_alloc
+= ARM_OPCODE_CHUNK_SIZE
;
13740 if (unwind
.opcodes
)
13741 unwind
.opcodes
= xrealloc (unwind
.opcodes
,
13742 unwind
.opcode_alloc
);
13744 unwind
.opcodes
= xmalloc (unwind
.opcode_alloc
);
13749 unwind
.opcodes
[unwind
.opcode_count
] = op
& 0xff;
13751 unwind
.opcode_count
++;
13755 /* Add unwind opcodes to adjust the stack pointer. */
13758 add_unwind_adjustsp (offsetT offset
)
13762 if (offset
> 0x200)
13764 /* We need at most 5 bytes to hold a 32-bit value in a uleb128. */
13769 /* Long form: 0xb2, uleb128. */
13770 /* This might not fit in a word so add the individual bytes,
13771 remembering the list is built in reverse order. */
13772 o
= (valueT
) ((offset
- 0x204) >> 2);
13774 add_unwind_opcode (0, 1);
13776 /* Calculate the uleb128 encoding of the offset. */
13780 bytes
[n
] = o
& 0x7f;
13786 /* Add the insn. */
13788 add_unwind_opcode (bytes
[n
- 1], 1);
13789 add_unwind_opcode (0xb2, 1);
13791 else if (offset
> 0x100)
13793 /* Two short opcodes. */
13794 add_unwind_opcode (0x3f, 1);
13795 op
= (offset
- 0x104) >> 2;
13796 add_unwind_opcode (op
, 1);
13798 else if (offset
> 0)
13800 /* Short opcode. */
13801 op
= (offset
- 4) >> 2;
13802 add_unwind_opcode (op
, 1);
13804 else if (offset
< 0)
13807 while (offset
> 0x100)
13809 add_unwind_opcode (0x7f, 1);
13812 op
= ((offset
- 4) >> 2) | 0x40;
13813 add_unwind_opcode (op
, 1);
13817 /* Finish the list of unwind opcodes for this function. */
13819 finish_unwind_opcodes (void)
13823 if (unwind
.fp_used
)
13825 /* Adjust sp as neccessary. */
13826 unwind
.pending_offset
+= unwind
.fp_offset
- unwind
.frame_size
;
13827 flush_pending_unwind ();
13829 /* After restoring sp from the frame pointer. */
13830 op
= 0x90 | unwind
.fp_reg
;
13831 add_unwind_opcode (op
, 1);
13834 flush_pending_unwind ();
13838 /* Start an exception table entry. If idx is nonzero this is an index table
13842 start_unwind_section (const segT text_seg
, int idx
)
13844 const char * text_name
;
13845 const char * prefix
;
13846 const char * prefix_once
;
13850 size_t sec_name_len
;
13854 prefix
= ELF_STRING_ARM_unwind
;
13855 prefix_once
= ELF_STRING_ARM_unwind_once
;
13859 prefix
= ELF_STRING_ARM_unwind_info
;
13860 prefix_once
= ELF_STRING_ARM_unwind_info_once
;
13863 text_name
= segment_name (text_seg
);
13864 if (streq (text_name
, ".text"))
13867 if (strncmp (text_name
, ".gnu.linkonce.t.",
13868 strlen (".gnu.linkonce.t.")) == 0)
13870 prefix
= prefix_once
;
13871 text_name
+= strlen (".gnu.linkonce.t.");
13874 prefix_len
= strlen (prefix
);
13875 text_len
= strlen (text_name
);
13876 sec_name_len
= prefix_len
+ text_len
;
13877 sec_name
= alloca (sec_name_len
+ 1);
13878 memcpy (sec_name
, prefix
, prefix_len
);
13879 memcpy (sec_name
+ prefix_len
, text_name
, text_len
);
13880 sec_name
[prefix_len
+ text_len
] = '\0';
13882 /* Handle COMDAT group. */
13883 if (prefix
!= prefix_once
&& (text_seg
->flags
& SEC_LINK_ONCE
) != 0)
13886 size_t len
, group_name_len
;
13887 const char *group_name
= elf_group_name (text_seg
);
13889 if (group_name
== NULL
)
13891 as_bad ("Group section `%s' has no group signature",
13892 segment_name (text_seg
));
13893 ignore_rest_of_line ();
13896 /* We have to construct a fake section directive. */
13897 group_name_len
= strlen (group_name
);
13903 len
= (sec_name_len
13904 + prefix_len
/* ,"aG",%sectiontype, */
13905 + group_name_len
/* ,group_name */
13906 + 7); /* ,comdat */
13908 section
= alloca (len
+ 1);
13909 memcpy (section
, sec_name
, sec_name_len
);
13911 memcpy (section
+ sec_name_len
, ",\"aG\",%exidx,", 13);
13913 memcpy (section
+ sec_name_len
, ",\"aG\",%progbits,", 16);
13914 memcpy (section
+ sec_name_len
+ prefix_len
, group_name
, group_name_len
);
13915 memcpy (section
+ len
- 7, ",comdat", 7);
13916 section
[len
] = '\0';
13917 set_section (section
);
13921 set_section (sec_name
);
13922 bfd_set_section_flags (stdoutput
, now_seg
,
13923 SEC_LOAD
| SEC_ALLOC
| SEC_READONLY
);
13926 /* Set the setion link for index tables. */
13928 elf_linked_to_section (now_seg
) = text_seg
;
13932 /* Start an unwind table entry. HAVE_DATA is nonzero if we have additional
13933 personality routine data. Returns zero, or the index table value for
13934 and inline entry. */
13937 create_unwind_entry (int have_data
)
13941 unsigned char *ptr
;
13942 /* The current word of data. */
13944 /* The number of bytes left in this word. */
13947 finish_unwind_opcodes ();
13949 /* Remember the current text section. */
13950 unwind
.saved_seg
= now_seg
;
13951 unwind
.saved_subseg
= now_subseg
;
13953 start_unwind_section (now_seg
, 0);
13955 if (unwind
.personality_routine
== NULL
)
13957 if (unwind
.personality_index
== -2)
13960 as_bad (_("handerdata in cantunwind frame"));
13961 return 1; /* EXIDX_CANTUNWIND. */
13964 /* Use a default personality routine if none is specified. */
13965 if (unwind
.personality_index
== -1)
13967 if (unwind
.opcode_count
> 3)
13968 unwind
.personality_index
= 1;
13970 unwind
.personality_index
= 0;
13973 /* Space for the personality routine entry. */
13974 if (unwind
.personality_index
== 0)
13976 if (unwind
.opcode_count
> 3)
13977 as_bad (_("too many unwind opcodes for personality routine 0"));
13981 /* All the data is inline in the index table. */
13984 while (unwind
.opcode_count
> 0)
13986 unwind
.opcode_count
--;
13987 data
= (data
<< 8) | unwind
.opcodes
[unwind
.opcode_count
];
13991 /* Pad with "finish" opcodes. */
13993 data
= (data
<< 8) | 0xb0;
14000 /* We get two opcodes "free" in the first word. */
14001 size
= unwind
.opcode_count
- 2;
14004 /* An extra byte is required for the opcode count. */
14005 size
= unwind
.opcode_count
+ 1;
14007 size
= (size
+ 3) >> 2;
14009 as_bad (_("too many unwind opcodes"));
14011 frag_align (2, 0, 0);
14012 record_alignment (now_seg
, 2);
14013 unwind
.table_entry
= expr_build_dot ();
14015 /* Allocate the table entry. */
14016 ptr
= frag_more ((size
<< 2) + 4);
14017 where
= frag_now_fix () - ((size
<< 2) + 4);
14019 switch (unwind
.personality_index
)
14022 /* ??? Should this be a PLT generating relocation? */
14023 /* Custom personality routine. */
14024 fix_new (frag_now
, where
, 4, unwind
.personality_routine
, 0, 1,
14025 BFD_RELOC_ARM_PREL31
);
14029 /* Set the first byte to the number of additional words. */
14034 /* ABI defined personality routines. */
14035 /* TODO: Emit R_ARM_NONE to the personality routine. */
14037 /* Three opcodes bytes are packed into the first word. */
14044 /* The size and first two opcode bytes go in the first word. */
14045 data
= ((0x80 + unwind
.personality_index
) << 8) | size
;
14050 /* Should never happen. */
14054 /* Pack the opcodes into words (MSB first), reversing the list at the same
14056 while (unwind
.opcode_count
> 0)
14060 md_number_to_chars (ptr
, data
, 4);
14065 unwind
.opcode_count
--;
14067 data
= (data
<< 8) | unwind
.opcodes
[unwind
.opcode_count
];
14070 /* Finish off the last word. */
14073 /* Pad with "finish" opcodes. */
14075 data
= (data
<< 8) | 0xb0;
14077 md_number_to_chars (ptr
, data
, 4);
14082 /* Add an empty descriptor if there is no user-specified data. */
14083 ptr
= frag_more (4);
14084 md_number_to_chars (ptr
, 0, 4);
14091 /* Parse an unwind_fnstart directive. Simply records the current location. */
14094 s_arm_unwind_fnstart (int ignored ATTRIBUTE_UNUSED
)
14096 demand_empty_rest_of_line ();
14097 /* Mark the start of the function. */
14098 unwind
.proc_start
= expr_build_dot ();
14100 /* Reset the rest of the unwind info. */
14101 unwind
.opcode_count
= 0;
14102 unwind
.table_entry
= NULL
;
14103 unwind
.personality_routine
= NULL
;
14104 unwind
.personality_index
= -1;
14105 unwind
.frame_size
= 0;
14106 unwind
.fp_offset
= 0;
14107 unwind
.fp_reg
= 13;
14108 unwind
.fp_used
= 0;
14109 unwind
.sp_restored
= 0;
14113 /* Parse a handlerdata directive. Creates the exception handling table entry
14114 for the function. */
14117 s_arm_unwind_handlerdata (int ignored ATTRIBUTE_UNUSED
)
14119 demand_empty_rest_of_line ();
14120 if (unwind
.table_entry
)
14121 as_bad (_("dupicate .handlerdata directive"));
14123 create_unwind_entry (1);
14126 /* Parse an unwind_fnend directive. Generates the index table entry. */
14129 s_arm_unwind_fnend (int ignored ATTRIBUTE_UNUSED
)
14132 unsigned char *ptr
;
14135 demand_empty_rest_of_line ();
14137 /* Add eh table entry. */
14138 if (unwind
.table_entry
== NULL
)
14139 val
= create_unwind_entry (0);
14143 /* Add index table entry. This is two words. */
14144 start_unwind_section (unwind
.saved_seg
, 1);
14145 frag_align (2, 0, 0);
14146 record_alignment (now_seg
, 2);
14148 ptr
= frag_more (8);
14149 where
= frag_now_fix () - 8;
14151 /* Self relative offset of the function start. */
14152 fix_new (frag_now
, where
, 4, unwind
.proc_start
, 0, 1,
14153 BFD_RELOC_ARM_PREL31
);
14156 /* Inline exception table entry. */
14157 md_number_to_chars (ptr
+ 4, val
, 4);
14159 /* Self relative offset of the table entry. */
14160 fix_new (frag_now
, where
+ 4, 4, unwind
.table_entry
, 0, 1,
14161 BFD_RELOC_ARM_PREL31
);
14163 /* Restore the original section. */
14164 subseg_set (unwind
.saved_seg
, unwind
.saved_subseg
);
14168 /* Parse an unwind_cantunwind directive. */
14171 s_arm_unwind_cantunwind (int ignored ATTRIBUTE_UNUSED
)
14173 demand_empty_rest_of_line ();
14174 if (unwind
.personality_routine
|| unwind
.personality_index
!= -1)
14175 as_bad (_("personality routine specified for cantunwind frame"));
14177 unwind
.personality_index
= -2;
14181 /* Parse a personalityindex directive. */
14184 s_arm_unwind_personalityindex (int ignored ATTRIBUTE_UNUSED
)
14188 if (unwind
.personality_routine
|| unwind
.personality_index
!= -1)
14189 as_bad (_("duplicate .personalityindex directive"));
14191 SKIP_WHITESPACE ();
14195 if (exp
.X_op
!= O_constant
14196 || exp
.X_add_number
< 0 || exp
.X_add_number
> 15)
14198 as_bad (_("bad personality routine number"));
14199 ignore_rest_of_line ();
14203 unwind
.personality_index
= exp
.X_add_number
;
14205 demand_empty_rest_of_line ();
14209 /* Parse a personality directive. */
14212 s_arm_unwind_personality (int ignored ATTRIBUTE_UNUSED
)
14216 if (unwind
.personality_routine
|| unwind
.personality_index
!= -1)
14217 as_bad (_("duplicate .personality directive"));
14219 SKIP_WHITESPACE ();
14220 name
= input_line_pointer
;
14221 c
= get_symbol_end ();
14222 p
= input_line_pointer
;
14223 unwind
.personality_routine
= symbol_find_or_make (name
);
14225 SKIP_WHITESPACE ();
14226 demand_empty_rest_of_line ();
14230 /* Parse a directive saving core registers. */
14233 s_arm_unwind_save_core (void)
14239 SKIP_WHITESPACE ();
14240 range
= reg_list (&input_line_pointer
);
14243 as_bad (_("expected register list"));
14244 ignore_rest_of_line ();
14248 demand_empty_rest_of_line ();
14250 /* Turn .unwind_movsp ip followed by .unwind_save {..., ip, ...}
14251 into .unwind_save {..., sp...}. We aren't bothered about the value of
14252 ip because it is clobbered by calls. */
14253 if (unwind
.sp_restored
&& unwind
.fp_reg
== 12
14254 && (range
& 0x3000) == 0x1000)
14256 unwind
.opcode_count
--;
14257 unwind
.sp_restored
= 0;
14258 range
= (range
| 0x2000) & ~0x1000;
14259 unwind
.pending_offset
= 0;
14262 /* See if we can use the short opcodes. These pop a block of upto 8
14263 registers starting with r4, plus maybe r14. */
14264 for (n
= 0; n
< 8; n
++)
14266 /* Break at the first non-saved register. */
14267 if ((range
& (1 << (n
+ 4))) == 0)
14270 /* See if there are any other bits set. */
14271 if (n
== 0 || (range
& (0xfff0 << n
) & 0xbff0) != 0)
14273 /* Use the long form. */
14274 op
= 0x8000 | ((range
>> 4) & 0xfff);
14275 add_unwind_opcode (op
, 2);
14279 /* Use the short form. */
14280 if (range
& 0x4000)
14281 op
= 0xa8; /* Pop r14. */
14283 op
= 0xa0; /* Do not pop r14. */
14285 add_unwind_opcode (op
, 1);
14291 op
= 0xb100 | (range
& 0xf);
14292 add_unwind_opcode (op
, 2);
14295 /* Record the number of bytes pushed. */
14296 for (n
= 0; n
< 16; n
++)
14298 if (range
& (1 << n
))
14299 unwind
.frame_size
+= 4;
14304 /* Parse a directive saving FPA registers. */
14307 s_arm_unwind_save_fpa (int reg
)
14313 /* Get Number of registers to transfer. */
14314 if (skip_past_comma (&input_line_pointer
) != FAIL
)
14317 exp
.X_op
= O_illegal
;
14319 if (exp
.X_op
!= O_constant
)
14321 as_bad (_("expected , <constant>"));
14322 ignore_rest_of_line ();
14326 num_regs
= exp
.X_add_number
;
14328 if (num_regs
< 1 || num_regs
> 4)
14330 as_bad (_("number of registers must be in the range [1:4]"));
14331 ignore_rest_of_line ();
14335 demand_empty_rest_of_line ();
14340 op
= 0xb4 | (num_regs
- 1);
14341 add_unwind_opcode (op
, 1);
14346 op
= 0xc800 | (reg
<< 4) | (num_regs
- 1);
14347 add_unwind_opcode (op
, 2);
14349 unwind
.frame_size
+= num_regs
* 12;
14353 /* Parse a directive saving VFP registers. */
14356 s_arm_unwind_save_vfp (void)
14362 count
= vfp_parse_reg_list (&input_line_pointer
, ®
, 1);
14365 as_bad (_("expected register list"));
14366 ignore_rest_of_line ();
14370 demand_empty_rest_of_line ();
14375 op
= 0xb8 | (count
- 1);
14376 add_unwind_opcode (op
, 1);
14381 op
= 0xb300 | (reg
<< 4) | (count
- 1);
14382 add_unwind_opcode (op
, 2);
14384 unwind
.frame_size
+= count
* 8 + 4;
14388 /* Parse a directive saving iWMMXt registers. */
14391 s_arm_unwind_save_wmmx (void)
14400 if (*input_line_pointer
== '{')
14401 input_line_pointer
++;
14407 reg
= arm_reg_parse (&input_line_pointer
,
14408 all_reg_maps
[REG_TYPE_IWMMXT
].htab
);
14410 if (wr_register (reg
))
14412 i
= reg
& ~WR_PREFIX
;
14414 as_tsktsk (_("register list not in ascending order"));
14417 else if (wcg_register (reg
))
14419 i
= (reg
& ~WC_PREFIX
) - 8;
14421 as_tsktsk (_("register list not in ascending order"));
14422 wcg_mask
|= 1 << i
;
14426 as_bad (_("expected wr or wcgr"));
14430 SKIP_WHITESPACE ();
14431 if (*input_line_pointer
== '-')
14433 hi_reg
= arm_reg_parse (&input_line_pointer
,
14434 all_reg_maps
[REG_TYPE_IWMMXT
].htab
);
14435 if (wr_register (reg
) && wr_register (hi_reg
))
14437 for (; reg
< hi_reg
; reg
++)
14438 wr_mask
|= 1 << (reg
& ~WR_PREFIX
);
14440 else if (wcg_register (reg
) && wcg_register (hi_reg
))
14442 for (; reg
< hi_reg
; reg
++)
14443 wcg_mask
|= 1 << ((reg
& ~WC_PREFIX
) - 8);
14447 as_bad (_("bad register range"));
14452 while (skip_past_comma (&input_line_pointer
) != FAIL
);
14454 SKIP_WHITESPACE ();
14455 if (*input_line_pointer
== '}')
14456 input_line_pointer
++;
14458 demand_empty_rest_of_line ();
14460 if (wr_mask
&& wcg_mask
)
14462 as_bad (_("inconsistent register types"));
14466 /* Generate any deferred opcodes becuuse we're going to be looking at
14468 flush_pending_unwind ();
14472 for (i
= 0; i
< 16; i
++)
14474 if (wcg_mask
& (1 << i
))
14475 unwind
.frame_size
+= 4;
14477 op
= 0xc700 | wcg_mask
;
14478 add_unwind_opcode (op
, 2);
14482 for (i
= 0; i
< 16; i
++)
14484 if (wr_mask
& (1 << i
))
14485 unwind
.frame_size
+= 8;
14487 /* Attempt to combine with a previous opcode. We do this because gcc
14488 likes to output separate unwind directives for a single block of
14490 if (unwind
.opcode_count
> 0)
14492 i
= unwind
.opcodes
[unwind
.opcode_count
- 1];
14493 if ((i
& 0xf8) == 0xc0)
14496 /* Only merge if the blocks are contiguous. */
14499 if ((wr_mask
& 0xfe00) == (1 << 9))
14501 wr_mask
|= ((1 << (i
+ 11)) - 1) & 0xfc00;
14502 unwind
.opcode_count
--;
14505 else if (i
== 6 && unwind
.opcode_count
>= 2)
14507 i
= unwind
.opcodes
[unwind
.opcode_count
- 2];
14511 op
= 0xffff << (reg
- 1);
14513 || ((wr_mask
& op
) == (1u << (reg
- 1))))
14515 op
= (1 << (reg
+ i
+ 1)) - 1;
14516 op
&= ~((1 << reg
) - 1);
14518 unwind
.opcode_count
-= 2;
14525 /* We want to generate opcodes in the order the registers have been
14526 saved, ie. descending order. */
14527 for (reg
= 15; reg
>= -1; reg
--)
14529 /* Save registers in blocks. */
14531 || !(wr_mask
& (1 << reg
)))
14533 /* We found an unsaved reg. Generate opcodes to save the
14534 preceeding block. */
14540 op
= 0xc0 | (hi_reg
- 10);
14541 add_unwind_opcode (op
, 1);
14546 op
= 0xc600 | ((reg
+ 1) << 4) | ((hi_reg
- reg
) - 1);
14547 add_unwind_opcode (op
, 2);
14556 ignore_rest_of_line ();
14560 /* Parse an unwind_save directive. */
14563 s_arm_unwind_save (int ignored ATTRIBUTE_UNUSED
)
14568 /* Figure out what sort of save we have. */
14569 SKIP_WHITESPACE ();
14570 saved_ptr
= input_line_pointer
;
14572 reg
= arm_reg_parse (&input_line_pointer
, all_reg_maps
[REG_TYPE_FN
].htab
);
14575 s_arm_unwind_save_fpa (reg
);
14579 if (*input_line_pointer
== '{')
14580 input_line_pointer
++;
14582 SKIP_WHITESPACE ();
14584 reg
= arm_reg_parse (&input_line_pointer
, all_reg_maps
[REG_TYPE_RN
].htab
);
14587 input_line_pointer
= saved_ptr
;
14588 s_arm_unwind_save_core ();
14592 reg
= arm_reg_parse (&input_line_pointer
, all_reg_maps
[REG_TYPE_DN
].htab
);
14595 input_line_pointer
= saved_ptr
;
14596 s_arm_unwind_save_vfp ();
14600 reg
= arm_reg_parse (&input_line_pointer
,
14601 all_reg_maps
[REG_TYPE_IWMMXT
].htab
);
14604 input_line_pointer
= saved_ptr
;
14605 s_arm_unwind_save_wmmx ();
14609 /* TODO: Maverick registers. */
14610 as_bad (_("unrecognised register"));
14614 /* Parse an unwind_movsp directive. */
14617 s_arm_unwind_movsp (int ignored ATTRIBUTE_UNUSED
)
14622 SKIP_WHITESPACE ();
14623 reg
= reg_required_here (&input_line_pointer
, -1);
14626 as_bad (_("ARM register expected"));
14627 ignore_rest_of_line ();
14631 if (reg
== 13 || reg
== 15)
14633 as_bad (_("r%d not permitted in .unwind_movsp directive"), reg
);
14634 ignore_rest_of_line ();
14638 if (unwind
.fp_reg
!= 13)
14639 as_bad (_("unexpected .unwind_movsp directive"));
14641 /* Generate opcode to restore the value. */
14643 add_unwind_opcode (op
, 1);
14645 /* Record the information for later. */
14646 unwind
.fp_reg
= reg
;
14647 unwind
.fp_offset
= unwind
.frame_size
;
14648 unwind
.sp_restored
= 1;
14649 demand_empty_rest_of_line ();
14653 /* Parse #<number>. */
14656 require_hashconst (int * val
)
14660 SKIP_WHITESPACE ();
14661 if (*input_line_pointer
== '#')
14663 input_line_pointer
++;
14667 exp
.X_op
= O_illegal
;
14669 if (exp
.X_op
!= O_constant
)
14671 as_bad (_("expected #constant"));
14672 ignore_rest_of_line ();
14675 *val
= exp
.X_add_number
;
14679 /* Parse an unwind_pad directive. */
14682 s_arm_unwind_pad (int ignored ATTRIBUTE_UNUSED
)
14686 if (require_hashconst (&offset
) == FAIL
)
14691 as_bad (_("stack increment must be multiple of 4"));
14692 ignore_rest_of_line ();
14696 /* Don't generate any opcodes, just record the details for later. */
14697 unwind
.frame_size
+= offset
;
14698 unwind
.pending_offset
+= offset
;
14700 demand_empty_rest_of_line ();
14703 /* Parse an unwind_setfp directive. */
14706 s_arm_unwind_setfp (int ignored ATTRIBUTE_UNUSED
)
14712 fp_reg
= reg_required_here (&input_line_pointer
, -1);
14713 if (skip_past_comma (&input_line_pointer
) == FAIL
)
14716 sp_reg
= reg_required_here (&input_line_pointer
, -1);
14718 if (fp_reg
== FAIL
|| sp_reg
== FAIL
)
14720 as_bad (_("expected <reg>, <reg>"));
14721 ignore_rest_of_line ();
14725 /* Optonal constant. */
14726 if (skip_past_comma (&input_line_pointer
) != FAIL
)
14728 if (require_hashconst (&offset
) == FAIL
)
14734 demand_empty_rest_of_line ();
14736 if (sp_reg
!= 13 && sp_reg
!= unwind
.fp_reg
)
14738 as_bad (_("register must be either sp or set by a previous"
14739 "unwind_movsp directive"));
14743 /* Don't generate any opcodes, just record the information for later. */
14744 unwind
.fp_reg
= fp_reg
;
14745 unwind
.fp_used
= 1;
14747 unwind
.fp_offset
= unwind
.frame_size
- offset
;
14749 unwind
.fp_offset
-= offset
;
14752 /* Parse an unwind_raw directive. */
14755 s_arm_unwind_raw (int ignored ATTRIBUTE_UNUSED
)
14758 /* This is an arbitary limit. */
14759 unsigned char op
[16];
14762 SKIP_WHITESPACE ();
14764 if (exp
.X_op
== O_constant
14765 && skip_past_comma (&input_line_pointer
) != FAIL
)
14767 unwind
.frame_size
+= exp
.X_add_number
;
14771 exp
.X_op
= O_illegal
;
14773 if (exp
.X_op
!= O_constant
)
14775 as_bad (_("expected <offset>, <opcode>"));
14776 ignore_rest_of_line ();
14782 /* Parse the opcode. */
14787 as_bad (_("unwind opcode too long"));
14788 ignore_rest_of_line ();
14790 if (exp
.X_op
!= O_constant
|| exp
.X_add_number
& ~0xff)
14792 as_bad (_("invalid unwind opcode"));
14793 ignore_rest_of_line ();
14796 op
[count
++] = exp
.X_add_number
;
14798 /* Parse the next byte. */
14799 if (skip_past_comma (&input_line_pointer
) == FAIL
)
14805 /* Add the opcode bytes in reverse order. */
14807 add_unwind_opcode (op
[count
], 1);
14809 demand_empty_rest_of_line ();
14812 #endif /* OBJ_ELF */
14814 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
14815 of an rs_align_code fragment. */
14818 arm_handle_align (fragS
* fragP
)
14820 static char const arm_noop
[4] = { 0x00, 0x00, 0xa0, 0xe1 };
14821 static char const thumb_noop
[2] = { 0xc0, 0x46 };
14822 static char const arm_bigend_noop
[4] = { 0xe1, 0xa0, 0x00, 0x00 };
14823 static char const thumb_bigend_noop
[2] = { 0x46, 0xc0 };
14825 int bytes
, fix
, noop_size
;
14829 if (fragP
->fr_type
!= rs_align_code
)
14832 bytes
= fragP
->fr_next
->fr_address
- fragP
->fr_address
- fragP
->fr_fix
;
14833 p
= fragP
->fr_literal
+ fragP
->fr_fix
;
14836 if (bytes
> MAX_MEM_FOR_RS_ALIGN_CODE
)
14837 bytes
&= MAX_MEM_FOR_RS_ALIGN_CODE
;
14839 if (fragP
->tc_frag_data
)
14841 if (target_big_endian
)
14842 noop
= thumb_bigend_noop
;
14845 noop_size
= sizeof (thumb_noop
);
14849 if (target_big_endian
)
14850 noop
= arm_bigend_noop
;
14853 noop_size
= sizeof (arm_noop
);
14856 if (bytes
& (noop_size
- 1))
14858 fix
= bytes
& (noop_size
- 1);
14859 memset (p
, 0, fix
);
14864 while (bytes
>= noop_size
)
14866 memcpy (p
, noop
, noop_size
);
14868 bytes
-= noop_size
;
14872 fragP
->fr_fix
+= fix
;
14873 fragP
->fr_var
= noop_size
;
14876 /* Called from md_do_align. Used to create an alignment
14877 frag in a code section. */
14880 arm_frag_align_code (int n
, int max
)
14884 /* We assume that there will never be a requirement
14885 to support alignments greater than 32 bytes. */
14886 if (max
> MAX_MEM_FOR_RS_ALIGN_CODE
)
14887 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
14889 p
= frag_var (rs_align_code
,
14890 MAX_MEM_FOR_RS_ALIGN_CODE
,
14892 (relax_substateT
) max
,
14899 /* Perform target specific initialisation of a frag. */
14902 arm_init_frag (fragS
* fragP
)
14904 /* Record whether this frag is in an ARM or a THUMB area. */
14905 fragP
->tc_frag_data
= thumb_mode
;
14910 /* Convert REGNAME to a DWARF-2 register number. */
14913 tc_arm_regname_to_dw2regnum (const char *regname
)
14917 for (i
= 0; rn_table
[i
].name
; i
++)
14918 if (streq (regname
, rn_table
[i
].name
))
14919 return rn_table
[i
].number
;
14924 /* Initialize the DWARF-2 unwind information for this procedure. */
14927 tc_arm_frame_initial_instructions (void)
14929 cfi_add_CFA_def_cfa (REG_SP
, 0);
14933 /* This table describes all the machine specific pseudo-ops the assembler
14934 has to support. The fields are:
14935 pseudo-op name without dot
14936 function to call to execute this pseudo-op
14937 Integer arg to pass to the function. */
14939 const pseudo_typeS md_pseudo_table
[] =
14941 /* Never called because '.req' does not start a line. */
14942 { "req", s_req
, 0 },
14943 { "unreq", s_unreq
, 0 },
14944 { "bss", s_bss
, 0 },
14945 { "align", s_align
, 0 },
14946 { "arm", s_arm
, 0 },
14947 { "thumb", s_thumb
, 0 },
14948 { "code", s_code
, 0 },
14949 { "force_thumb", s_force_thumb
, 0 },
14950 { "thumb_func", s_thumb_func
, 0 },
14951 { "thumb_set", s_thumb_set
, 0 },
14952 { "even", s_even
, 0 },
14953 { "ltorg", s_ltorg
, 0 },
14954 { "pool", s_ltorg
, 0 },
14956 { "word", s_arm_elf_cons
, 4 },
14957 { "long", s_arm_elf_cons
, 4 },
14958 { "rel31", s_arm_rel31
, 0 },
14959 { "fnstart", s_arm_unwind_fnstart
, 0 },
14960 { "fnend", s_arm_unwind_fnend
, 0 },
14961 { "cantunwind", s_arm_unwind_cantunwind
, 0 },
14962 { "personality", s_arm_unwind_personality
, 0 },
14963 { "personalityindex", s_arm_unwind_personalityindex
, 0 },
14964 { "handlerdata", s_arm_unwind_handlerdata
, 0 },
14965 { "save", s_arm_unwind_save
, 0 },
14966 { "movsp", s_arm_unwind_movsp
, 0 },
14967 { "pad", s_arm_unwind_pad
, 0 },
14968 { "setfp", s_arm_unwind_setfp
, 0 },
14969 { "unwind_raw", s_arm_unwind_raw
, 0 },
14971 { "word", cons
, 4},
14973 { "extend", float_cons
, 'x' },
14974 { "ldouble", float_cons
, 'x' },
14975 { "packed", float_cons
, 'p' },