1 /* tc-arm.c -- Assemble for the ARM
2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
3 Free Software Foundation, Inc.
4 Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
5 Modified by David Taylor (dtaylor@armltd.co.uk)
6 Cirrus coprocessor mods by Aldy Hernandez (aldyh@redhat.com)
7 Cirrus coprocessor fixes by Petko Manolov (petkan@nucleusys.com)
8 Cirrus coprocessor fixes by Vladimir Ivanov (vladitx@nucleusys.com)
10 This file is part of GAS, the GNU Assembler.
12 GAS is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2, or (at your option)
17 GAS is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with GAS; see the file COPYING. If not, write to the Free
24 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
30 #include "safe-ctype.h"
32 /* Need TARGET_CPU. */
39 #include "opcode/arm.h"
43 #include "dwarf2dbg.h"
44 #include "dw2gencfi.h"
47 /* XXX Set this to 1 after the next binutils release. */
48 #define WARN_DEPRECATED 0
51 /* Must be at least the size of the largest unwind opcode (currently two). */
52 #define ARM_OPCODE_CHUNK_SIZE 8
54 /* This structure holds the unwinding state. */
59 symbolS
* table_entry
;
60 symbolS
* personality_routine
;
61 int personality_index
;
62 /* The segment containing the function. */
65 /* Opcodes generated from this function. */
66 unsigned char * opcodes
;
69 /* The number of bytes pushed to the stack. */
71 /* We don't add stack adjustment opcodes immediately so that we can merge
72 multiple adjustments. We can also omit the final adjustment
73 when using a frame pointer. */
74 offsetT pending_offset
;
75 /* These two fields are set by both unwind_movsp and unwind_setfp. They
76 hold the reg+offset to use when restoring sp from a frame pointer. */
79 /* Nonzero if an unwind_setfp directive has been seen. */
81 /* Nonzero if the last opcode restores sp from fp_reg. */
82 unsigned sp_restored
:1;
94 /* Types of processor to assemble for. */
95 #define ARM_1 ARM_ARCH_V1
96 #define ARM_2 ARM_ARCH_V2
97 #define ARM_3 ARM_ARCH_V2S
98 #define ARM_250 ARM_ARCH_V2S
99 #define ARM_6 ARM_ARCH_V3
100 #define ARM_7 ARM_ARCH_V3
101 #define ARM_8 ARM_ARCH_V4
102 #define ARM_9 ARM_ARCH_V4T
103 #define ARM_STRONG ARM_ARCH_V4
104 #define ARM_CPU_MASK 0x0000000f /* XXX? */
107 #if defined __XSCALE__
108 #define CPU_DEFAULT (ARM_ARCH_XSCALE)
110 #if defined __thumb__
111 #define CPU_DEFAULT (ARM_ARCH_V5T)
113 #define CPU_DEFAULT ARM_ANY
120 # define FPU_DEFAULT FPU_ARCH_FPA
121 # elif defined (TE_NetBSD)
123 # define FPU_DEFAULT FPU_ARCH_VFP /* Soft-float, but VFP order. */
125 /* Legacy a.out format. */
126 # define FPU_DEFAULT FPU_ARCH_FPA /* Soft-float, but FPA order. */
129 /* For backwards compatibility, default to FPA. */
130 # define FPU_DEFAULT FPU_ARCH_FPA
132 #endif /* ifndef FPU_DEFAULT */
134 #define streq(a, b) (strcmp (a, b) == 0)
135 #define skip_whitespace(str) while (*(str) == ' ') ++(str)
137 static unsigned long cpu_variant
;
139 /* Flags stored in private area of BFD structure. */
140 static int uses_apcs_26
= FALSE
;
141 static int atpcs
= FALSE
;
142 static int support_interwork
= FALSE
;
143 static int uses_apcs_float
= FALSE
;
144 static int pic_code
= FALSE
;
146 /* Variables that we set while parsing command-line options. Once all
147 options have been read we re-process these values to set the real
149 static int legacy_cpu
= -1;
150 static int legacy_fpu
= -1;
152 static int mcpu_cpu_opt
= -1;
153 static int mcpu_fpu_opt
= -1;
154 static int march_cpu_opt
= -1;
155 static int march_fpu_opt
= -1;
156 static int mfpu_opt
= -1;
157 static int mfloat_abi_opt
= -1;
159 static int meabi_flags
= EF_ARM_EABI_UNKNOWN
;
162 /* This array holds the chars that always start a comment. If the
163 pre-processor is disabled, these aren't very useful. */
164 const char comment_chars
[] = "@";
166 /* This array holds the chars that only start a comment at the beginning of
167 a line. If the line seems to have the form '# 123 filename'
168 .line and .file directives will appear in the pre-processed output. */
169 /* Note that input_file.c hand checks for '#' at the beginning of the
170 first line of the input file. This is because the compiler outputs
171 #NO_APP at the beginning of its output. */
172 /* Also note that comments like this one will always work. */
173 const char line_comment_chars
[] = "#";
175 const char line_separator_chars
[] = ";";
177 /* Chars that can be used to separate mant
178 from exp in floating point numbers. */
179 const char EXP_CHARS
[] = "eE";
181 /* Chars that mean this number is a floating point constant. */
185 const char FLT_CHARS
[] = "rRsSfFdDxXeEpP";
187 /* Prefix characters that indicate the start of an immediate
189 #define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
192 /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
193 symbolS
* GOT_symbol
;
196 /* Size of relocation record. */
197 const int md_reloc_size
= 8;
199 /* 0: assemble for ARM,
200 1: assemble for Thumb,
201 2: assemble for Thumb even though target CPU does not support thumb
203 static int thumb_mode
= 0;
205 typedef struct arm_fix
213 unsigned long instruction
;
217 bfd_reloc_code_real_type type
;
234 struct asm_shift_properties
236 enum asm_shift_index index
;
237 unsigned long bit_field
;
238 unsigned int allows_0
: 1;
239 unsigned int allows_32
: 1;
242 static const struct asm_shift_properties shift_properties
[] =
244 { SHIFT_LSL
, 0, 1, 0},
245 { SHIFT_LSR
, 0x20, 0, 1},
246 { SHIFT_ASR
, 0x40, 0, 1},
247 { SHIFT_ROR
, 0x60, 0, 0},
248 { SHIFT_RRX
, 0x60, 0, 0}
251 struct asm_shift_name
254 const struct asm_shift_properties
* properties
;
257 static const struct asm_shift_name shift_names
[] =
259 { "asl", shift_properties
+ SHIFT_LSL
},
260 { "lsl", shift_properties
+ SHIFT_LSL
},
261 { "lsr", shift_properties
+ SHIFT_LSR
},
262 { "asr", shift_properties
+ SHIFT_ASR
},
263 { "ror", shift_properties
+ SHIFT_ROR
},
264 { "rrx", shift_properties
+ SHIFT_RRX
},
265 { "ASL", shift_properties
+ SHIFT_LSL
},
266 { "LSL", shift_properties
+ SHIFT_LSL
},
267 { "LSR", shift_properties
+ SHIFT_LSR
},
268 { "ASR", shift_properties
+ SHIFT_ASR
},
269 { "ROR", shift_properties
+ SHIFT_ROR
},
270 { "RRX", shift_properties
+ SHIFT_RRX
}
273 /* Any kind of shift is accepted. */
274 #define NO_SHIFT_RESTRICT 1
275 /* The shift operand must be an immediate value, not a register. */
276 #define SHIFT_IMMEDIATE 0
277 /* The shift must be LSL or ASR and the operand must be an immediate. */
278 #define SHIFT_LSL_OR_ASR_IMMEDIATE 2
279 /* The shift must be ASR and the operand must be an immediate. */
280 #define SHIFT_ASR_IMMEDIATE 3
281 /* The shift must be LSL and the operand must be an immediate. */
282 #define SHIFT_LSL_IMMEDIATE 4
284 #define NUM_FLOAT_VALS 8
286 const char * fp_const
[] =
288 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
291 /* Number of littlenums required to hold an extended precision number. */
292 #define MAX_LITTLENUMS 6
294 LITTLENUM_TYPE fp_values
[NUM_FLOAT_VALS
][MAX_LITTLENUMS
];
299 /* Whether a Co-processor load/store operation accepts write-back forms. */
308 #define CP_T_X 0x00008000
309 #define CP_T_Y 0x00400000
310 #define CP_T_Pre 0x01000000
311 #define CP_T_UD 0x00800000
312 #define CP_T_WB 0x00200000
314 #define CONDS_BIT 0x00100000
315 #define LOAD_BIT 0x00100000
317 #define DOUBLE_LOAD_FLAG 0x00000001
321 const char * template;
325 #define COND_ALWAYS 0xe0000000
326 #define COND_MASK 0xf0000000
328 static const struct asm_cond conds
[] =
332 {"cs", 0x20000000}, {"hs", 0x20000000},
333 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
350 const char *template;
355 /* The bit that distinguishes CPSR and SPSR. */
356 #define SPSR_BIT (1 << 22)
358 /* How many bits to shift the PSR_xxx bits up by. */
361 #define PSR_c (1 << 0)
362 #define PSR_x (1 << 1)
363 #define PSR_s (1 << 2)
364 #define PSR_f (1 << 3)
366 static const struct asm_psr psrs
[] =
368 {"CPSR", TRUE
, PSR_c
| PSR_f
},
369 {"CPSR_all", TRUE
, PSR_c
| PSR_f
},
370 {"SPSR", FALSE
, PSR_c
| PSR_f
},
371 {"SPSR_all", FALSE
, PSR_c
| PSR_f
},
372 {"CPSR_flg", TRUE
, PSR_f
},
373 {"CPSR_f", TRUE
, PSR_f
},
374 {"SPSR_flg", FALSE
, PSR_f
},
375 {"SPSR_f", FALSE
, PSR_f
},
376 {"CPSR_c", TRUE
, PSR_c
},
377 {"CPSR_ctl", TRUE
, PSR_c
},
378 {"SPSR_c", FALSE
, PSR_c
},
379 {"SPSR_ctl", FALSE
, PSR_c
},
380 {"CPSR_x", TRUE
, PSR_x
},
381 {"CPSR_s", TRUE
, PSR_s
},
382 {"SPSR_x", FALSE
, PSR_x
},
383 {"SPSR_s", FALSE
, PSR_s
},
384 /* Combinations of flags. */
385 {"CPSR_fs", TRUE
, PSR_f
| PSR_s
},
386 {"CPSR_fx", TRUE
, PSR_f
| PSR_x
},
387 {"CPSR_fc", TRUE
, PSR_f
| PSR_c
},
388 {"CPSR_sf", TRUE
, PSR_s
| PSR_f
},
389 {"CPSR_sx", TRUE
, PSR_s
| PSR_x
},
390 {"CPSR_sc", TRUE
, PSR_s
| PSR_c
},
391 {"CPSR_xf", TRUE
, PSR_x
| PSR_f
},
392 {"CPSR_xs", TRUE
, PSR_x
| PSR_s
},
393 {"CPSR_xc", TRUE
, PSR_x
| PSR_c
},
394 {"CPSR_cf", TRUE
, PSR_c
| PSR_f
},
395 {"CPSR_cs", TRUE
, PSR_c
| PSR_s
},
396 {"CPSR_cx", TRUE
, PSR_c
| PSR_x
},
397 {"CPSR_fsx", TRUE
, PSR_f
| PSR_s
| PSR_x
},
398 {"CPSR_fsc", TRUE
, PSR_f
| PSR_s
| PSR_c
},
399 {"CPSR_fxs", TRUE
, PSR_f
| PSR_x
| PSR_s
},
400 {"CPSR_fxc", TRUE
, PSR_f
| PSR_x
| PSR_c
},
401 {"CPSR_fcs", TRUE
, PSR_f
| PSR_c
| PSR_s
},
402 {"CPSR_fcx", TRUE
, PSR_f
| PSR_c
| PSR_x
},
403 {"CPSR_sfx", TRUE
, PSR_s
| PSR_f
| PSR_x
},
404 {"CPSR_sfc", TRUE
, PSR_s
| PSR_f
| PSR_c
},
405 {"CPSR_sxf", TRUE
, PSR_s
| PSR_x
| PSR_f
},
406 {"CPSR_sxc", TRUE
, PSR_s
| PSR_x
| PSR_c
},
407 {"CPSR_scf", TRUE
, PSR_s
| PSR_c
| PSR_f
},
408 {"CPSR_scx", TRUE
, PSR_s
| PSR_c
| PSR_x
},
409 {"CPSR_xfs", TRUE
, PSR_x
| PSR_f
| PSR_s
},
410 {"CPSR_xfc", TRUE
, PSR_x
| PSR_f
| PSR_c
},
411 {"CPSR_xsf", TRUE
, PSR_x
| PSR_s
| PSR_f
},
412 {"CPSR_xsc", TRUE
, PSR_x
| PSR_s
| PSR_c
},
413 {"CPSR_xcf", TRUE
, PSR_x
| PSR_c
| PSR_f
},
414 {"CPSR_xcs", TRUE
, PSR_x
| PSR_c
| PSR_s
},
415 {"CPSR_cfs", TRUE
, PSR_c
| PSR_f
| PSR_s
},
416 {"CPSR_cfx", TRUE
, PSR_c
| PSR_f
| PSR_x
},
417 {"CPSR_csf", TRUE
, PSR_c
| PSR_s
| PSR_f
},
418 {"CPSR_csx", TRUE
, PSR_c
| PSR_s
| PSR_x
},
419 {"CPSR_cxf", TRUE
, PSR_c
| PSR_x
| PSR_f
},
420 {"CPSR_cxs", TRUE
, PSR_c
| PSR_x
| PSR_s
},
421 {"CPSR_fsxc", TRUE
, PSR_f
| PSR_s
| PSR_x
| PSR_c
},
422 {"CPSR_fscx", TRUE
, PSR_f
| PSR_s
| PSR_c
| PSR_x
},
423 {"CPSR_fxsc", TRUE
, PSR_f
| PSR_x
| PSR_s
| PSR_c
},
424 {"CPSR_fxcs", TRUE
, PSR_f
| PSR_x
| PSR_c
| PSR_s
},
425 {"CPSR_fcsx", TRUE
, PSR_f
| PSR_c
| PSR_s
| PSR_x
},
426 {"CPSR_fcxs", TRUE
, PSR_f
| PSR_c
| PSR_x
| PSR_s
},
427 {"CPSR_sfxc", TRUE
, PSR_s
| PSR_f
| PSR_x
| PSR_c
},
428 {"CPSR_sfcx", TRUE
, PSR_s
| PSR_f
| PSR_c
| PSR_x
},
429 {"CPSR_sxfc", TRUE
, PSR_s
| PSR_x
| PSR_f
| PSR_c
},
430 {"CPSR_sxcf", TRUE
, PSR_s
| PSR_x
| PSR_c
| PSR_f
},
431 {"CPSR_scfx", TRUE
, PSR_s
| PSR_c
| PSR_f
| PSR_x
},
432 {"CPSR_scxf", TRUE
, PSR_s
| PSR_c
| PSR_x
| PSR_f
},
433 {"CPSR_xfsc", TRUE
, PSR_x
| PSR_f
| PSR_s
| PSR_c
},
434 {"CPSR_xfcs", TRUE
, PSR_x
| PSR_f
| PSR_c
| PSR_s
},
435 {"CPSR_xsfc", TRUE
, PSR_x
| PSR_s
| PSR_f
| PSR_c
},
436 {"CPSR_xscf", TRUE
, PSR_x
| PSR_s
| PSR_c
| PSR_f
},
437 {"CPSR_xcfs", TRUE
, PSR_x
| PSR_c
| PSR_f
| PSR_s
},
438 {"CPSR_xcsf", TRUE
, PSR_x
| PSR_c
| PSR_s
| PSR_f
},
439 {"CPSR_cfsx", TRUE
, PSR_c
| PSR_f
| PSR_s
| PSR_x
},
440 {"CPSR_cfxs", TRUE
, PSR_c
| PSR_f
| PSR_x
| PSR_s
},
441 {"CPSR_csfx", TRUE
, PSR_c
| PSR_s
| PSR_f
| PSR_x
},
442 {"CPSR_csxf", TRUE
, PSR_c
| PSR_s
| PSR_x
| PSR_f
},
443 {"CPSR_cxfs", TRUE
, PSR_c
| PSR_x
| PSR_f
| PSR_s
},
444 {"CPSR_cxsf", TRUE
, PSR_c
| PSR_x
| PSR_s
| PSR_f
},
445 {"SPSR_fs", FALSE
, PSR_f
| PSR_s
},
446 {"SPSR_fx", FALSE
, PSR_f
| PSR_x
},
447 {"SPSR_fc", FALSE
, PSR_f
| PSR_c
},
448 {"SPSR_sf", FALSE
, PSR_s
| PSR_f
},
449 {"SPSR_sx", FALSE
, PSR_s
| PSR_x
},
450 {"SPSR_sc", FALSE
, PSR_s
| PSR_c
},
451 {"SPSR_xf", FALSE
, PSR_x
| PSR_f
},
452 {"SPSR_xs", FALSE
, PSR_x
| PSR_s
},
453 {"SPSR_xc", FALSE
, PSR_x
| PSR_c
},
454 {"SPSR_cf", FALSE
, PSR_c
| PSR_f
},
455 {"SPSR_cs", FALSE
, PSR_c
| PSR_s
},
456 {"SPSR_cx", FALSE
, PSR_c
| PSR_x
},
457 {"SPSR_fsx", FALSE
, PSR_f
| PSR_s
| PSR_x
},
458 {"SPSR_fsc", FALSE
, PSR_f
| PSR_s
| PSR_c
},
459 {"SPSR_fxs", FALSE
, PSR_f
| PSR_x
| PSR_s
},
460 {"SPSR_fxc", FALSE
, PSR_f
| PSR_x
| PSR_c
},
461 {"SPSR_fcs", FALSE
, PSR_f
| PSR_c
| PSR_s
},
462 {"SPSR_fcx", FALSE
, PSR_f
| PSR_c
| PSR_x
},
463 {"SPSR_sfx", FALSE
, PSR_s
| PSR_f
| PSR_x
},
464 {"SPSR_sfc", FALSE
, PSR_s
| PSR_f
| PSR_c
},
465 {"SPSR_sxf", FALSE
, PSR_s
| PSR_x
| PSR_f
},
466 {"SPSR_sxc", FALSE
, PSR_s
| PSR_x
| PSR_c
},
467 {"SPSR_scf", FALSE
, PSR_s
| PSR_c
| PSR_f
},
468 {"SPSR_scx", FALSE
, PSR_s
| PSR_c
| PSR_x
},
469 {"SPSR_xfs", FALSE
, PSR_x
| PSR_f
| PSR_s
},
470 {"SPSR_xfc", FALSE
, PSR_x
| PSR_f
| PSR_c
},
471 {"SPSR_xsf", FALSE
, PSR_x
| PSR_s
| PSR_f
},
472 {"SPSR_xsc", FALSE
, PSR_x
| PSR_s
| PSR_c
},
473 {"SPSR_xcf", FALSE
, PSR_x
| PSR_c
| PSR_f
},
474 {"SPSR_xcs", FALSE
, PSR_x
| PSR_c
| PSR_s
},
475 {"SPSR_cfs", FALSE
, PSR_c
| PSR_f
| PSR_s
},
476 {"SPSR_cfx", FALSE
, PSR_c
| PSR_f
| PSR_x
},
477 {"SPSR_csf", FALSE
, PSR_c
| PSR_s
| PSR_f
},
478 {"SPSR_csx", FALSE
, PSR_c
| PSR_s
| PSR_x
},
479 {"SPSR_cxf", FALSE
, PSR_c
| PSR_x
| PSR_f
},
480 {"SPSR_cxs", FALSE
, PSR_c
| PSR_x
| PSR_s
},
481 {"SPSR_fsxc", FALSE
, PSR_f
| PSR_s
| PSR_x
| PSR_c
},
482 {"SPSR_fscx", FALSE
, PSR_f
| PSR_s
| PSR_c
| PSR_x
},
483 {"SPSR_fxsc", FALSE
, PSR_f
| PSR_x
| PSR_s
| PSR_c
},
484 {"SPSR_fxcs", FALSE
, PSR_f
| PSR_x
| PSR_c
| PSR_s
},
485 {"SPSR_fcsx", FALSE
, PSR_f
| PSR_c
| PSR_s
| PSR_x
},
486 {"SPSR_fcxs", FALSE
, PSR_f
| PSR_c
| PSR_x
| PSR_s
},
487 {"SPSR_sfxc", FALSE
, PSR_s
| PSR_f
| PSR_x
| PSR_c
},
488 {"SPSR_sfcx", FALSE
, PSR_s
| PSR_f
| PSR_c
| PSR_x
},
489 {"SPSR_sxfc", FALSE
, PSR_s
| PSR_x
| PSR_f
| PSR_c
},
490 {"SPSR_sxcf", FALSE
, PSR_s
| PSR_x
| PSR_c
| PSR_f
},
491 {"SPSR_scfx", FALSE
, PSR_s
| PSR_c
| PSR_f
| PSR_x
},
492 {"SPSR_scxf", FALSE
, PSR_s
| PSR_c
| PSR_x
| PSR_f
},
493 {"SPSR_xfsc", FALSE
, PSR_x
| PSR_f
| PSR_s
| PSR_c
},
494 {"SPSR_xfcs", FALSE
, PSR_x
| PSR_f
| PSR_c
| PSR_s
},
495 {"SPSR_xsfc", FALSE
, PSR_x
| PSR_s
| PSR_f
| PSR_c
},
496 {"SPSR_xscf", FALSE
, PSR_x
| PSR_s
| PSR_c
| PSR_f
},
497 {"SPSR_xcfs", FALSE
, PSR_x
| PSR_c
| PSR_f
| PSR_s
},
498 {"SPSR_xcsf", FALSE
, PSR_x
| PSR_c
| PSR_s
| PSR_f
},
499 {"SPSR_cfsx", FALSE
, PSR_c
| PSR_f
| PSR_s
| PSR_x
},
500 {"SPSR_cfxs", FALSE
, PSR_c
| PSR_f
| PSR_x
| PSR_s
},
501 {"SPSR_csfx", FALSE
, PSR_c
| PSR_s
| PSR_f
| PSR_x
},
502 {"SPSR_csxf", FALSE
, PSR_c
| PSR_s
| PSR_x
| PSR_f
},
503 {"SPSR_cxfs", FALSE
, PSR_c
| PSR_x
| PSR_f
| PSR_s
},
504 {"SPSR_cxsf", FALSE
, PSR_c
| PSR_x
| PSR_s
| PSR_f
},
511 IWMMXT_REG_WR_OR_WC
= 2,
515 enum iwmmxt_insn_type
538 VFP_REG_Dd
, VFP_REG_Dm
, VFP_REG_Dn
543 VFP_REG_Sd
, VFP_REG_Sm
, VFP_REG_Sn
548 VFP_LDSTMIA
, VFP_LDSTMDB
, VFP_LDSTMIAX
, VFP_LDSTMDBX
551 /* VFP system registers. */
558 static const struct vfp_reg vfp_regs
[] =
560 {"fpsid", 0x00000000},
561 {"FPSID", 0x00000000},
562 {"fpscr", 0x00010000},
563 {"FPSCR", 0x00010000},
564 {"fpexc", 0x00080000},
565 {"FPEXC", 0x00080000}
568 /* Structure for a hash table entry for a register. */
576 /* Some well known registers that we refer to directly elsewhere. */
581 #define wr_register(reg) ((reg ^ WR_PREFIX) >= 0 && (reg ^ WR_PREFIX) <= 15)
582 #define wc_register(reg) ((reg ^ WC_PREFIX) >= 0 && (reg ^ WC_PREFIX) <= 15)
583 #define wcg_register(reg) ((reg ^ WC_PREFIX) >= 8 && (reg ^ WC_PREFIX) <= 11)
585 /* These are the standard names. Users can add aliases with .req.
586 and delete them with .unreq. */
588 /* Integer Register Numbers. */
589 static const struct reg_entry rn_table
[] =
591 {"r0", 0, TRUE
}, {"r1", 1, TRUE
}, {"r2", 2, TRUE
}, {"r3", 3, TRUE
},
592 {"r4", 4, TRUE
}, {"r5", 5, TRUE
}, {"r6", 6, TRUE
}, {"r7", 7, TRUE
},
593 {"r8", 8, TRUE
}, {"r9", 9, TRUE
}, {"r10", 10, TRUE
}, {"r11", 11, TRUE
},
594 {"r12", 12, TRUE
}, {"r13", REG_SP
, TRUE
}, {"r14", REG_LR
, TRUE
}, {"r15", REG_PC
, TRUE
},
595 /* ATPCS Synonyms. */
596 {"a1", 0, TRUE
}, {"a2", 1, TRUE
}, {"a3", 2, TRUE
}, {"a4", 3, TRUE
},
597 {"v1", 4, TRUE
}, {"v2", 5, TRUE
}, {"v3", 6, TRUE
}, {"v4", 7, TRUE
},
598 {"v5", 8, TRUE
}, {"v6", 9, TRUE
}, {"v7", 10, TRUE
}, {"v8", 11, TRUE
},
599 /* Well-known aliases. */
600 {"wr", 7, TRUE
}, {"sb", 9, TRUE
}, {"sl", 10, TRUE
}, {"fp", 11, TRUE
},
601 {"ip", 12, TRUE
}, {"sp", REG_SP
, TRUE
}, {"lr", REG_LR
, TRUE
}, {"pc", REG_PC
, TRUE
},
605 #define WR_PREFIX 0x200
606 #define WC_PREFIX 0x400
608 static const struct reg_entry iwmmxt_table
[] =
610 /* Intel Wireless MMX technology register names. */
611 { "wr0", 0x0 | WR_PREFIX
, TRUE
}, {"wr1", 0x1 | WR_PREFIX
, TRUE
},
612 { "wr2", 0x2 | WR_PREFIX
, TRUE
}, {"wr3", 0x3 | WR_PREFIX
, TRUE
},
613 { "wr4", 0x4 | WR_PREFIX
, TRUE
}, {"wr5", 0x5 | WR_PREFIX
, TRUE
},
614 { "wr6", 0x6 | WR_PREFIX
, TRUE
}, {"wr7", 0x7 | WR_PREFIX
, TRUE
},
615 { "wr8", 0x8 | WR_PREFIX
, TRUE
}, {"wr9", 0x9 | WR_PREFIX
, TRUE
},
616 { "wr10", 0xa | WR_PREFIX
, TRUE
}, {"wr11", 0xb | WR_PREFIX
, TRUE
},
617 { "wr12", 0xc | WR_PREFIX
, TRUE
}, {"wr13", 0xd | WR_PREFIX
, TRUE
},
618 { "wr14", 0xe | WR_PREFIX
, TRUE
}, {"wr15", 0xf | WR_PREFIX
, TRUE
},
619 { "wcid", 0x0 | WC_PREFIX
, TRUE
}, {"wcon", 0x1 | WC_PREFIX
, TRUE
},
620 {"wcssf", 0x2 | WC_PREFIX
, TRUE
}, {"wcasf", 0x3 | WC_PREFIX
, TRUE
},
621 {"wcgr0", 0x8 | WC_PREFIX
, TRUE
}, {"wcgr1", 0x9 | WC_PREFIX
, TRUE
},
622 {"wcgr2", 0xa | WC_PREFIX
, TRUE
}, {"wcgr3", 0xb | WC_PREFIX
, TRUE
},
624 { "wR0", 0x0 | WR_PREFIX
, TRUE
}, {"wR1", 0x1 | WR_PREFIX
, TRUE
},
625 { "wR2", 0x2 | WR_PREFIX
, TRUE
}, {"wR3", 0x3 | WR_PREFIX
, TRUE
},
626 { "wR4", 0x4 | WR_PREFIX
, TRUE
}, {"wR5", 0x5 | WR_PREFIX
, TRUE
},
627 { "wR6", 0x6 | WR_PREFIX
, TRUE
}, {"wR7", 0x7 | WR_PREFIX
, TRUE
},
628 { "wR8", 0x8 | WR_PREFIX
, TRUE
}, {"wR9", 0x9 | WR_PREFIX
, TRUE
},
629 { "wR10", 0xa | WR_PREFIX
, TRUE
}, {"wR11", 0xb | WR_PREFIX
, TRUE
},
630 { "wR12", 0xc | WR_PREFIX
, TRUE
}, {"wR13", 0xd | WR_PREFIX
, TRUE
},
631 { "wR14", 0xe | WR_PREFIX
, TRUE
}, {"wR15", 0xf | WR_PREFIX
, TRUE
},
632 { "wCID", 0x0 | WC_PREFIX
, TRUE
}, {"wCon", 0x1 | WC_PREFIX
, TRUE
},
633 {"wCSSF", 0x2 | WC_PREFIX
, TRUE
}, {"wCASF", 0x3 | WC_PREFIX
, TRUE
},
634 {"wCGR0", 0x8 | WC_PREFIX
, TRUE
}, {"wCGR1", 0x9 | WC_PREFIX
, TRUE
},
635 {"wCGR2", 0xa | WC_PREFIX
, TRUE
}, {"wCGR3", 0xb | WC_PREFIX
, TRUE
},
639 /* Co-processor Numbers. */
640 static const struct reg_entry cp_table
[] =
642 {"p0", 0, TRUE
}, {"p1", 1, TRUE
}, {"p2", 2, TRUE
}, {"p3", 3, TRUE
},
643 {"p4", 4, TRUE
}, {"p5", 5, TRUE
}, {"p6", 6, TRUE
}, {"p7", 7, TRUE
},
644 {"p8", 8, TRUE
}, {"p9", 9, TRUE
}, {"p10", 10, TRUE
}, {"p11", 11, TRUE
},
645 {"p12", 12, TRUE
}, {"p13", 13, TRUE
}, {"p14", 14, TRUE
}, {"p15", 15, TRUE
},
649 /* Co-processor Register Numbers. */
650 static const struct reg_entry cn_table
[] =
652 {"c0", 0, TRUE
}, {"c1", 1, TRUE
}, {"c2", 2, TRUE
}, {"c3", 3, TRUE
},
653 {"c4", 4, TRUE
}, {"c5", 5, TRUE
}, {"c6", 6, TRUE
}, {"c7", 7, TRUE
},
654 {"c8", 8, TRUE
}, {"c9", 9, TRUE
}, {"c10", 10, TRUE
}, {"c11", 11, TRUE
},
655 {"c12", 12, TRUE
}, {"c13", 13, TRUE
}, {"c14", 14, TRUE
}, {"c15", 15, TRUE
},
656 /* Not really valid, but kept for back-wards compatibility. */
657 {"cr0", 0, TRUE
}, {"cr1", 1, TRUE
}, {"cr2", 2, TRUE
}, {"cr3", 3, TRUE
},
658 {"cr4", 4, TRUE
}, {"cr5", 5, TRUE
}, {"cr6", 6, TRUE
}, {"cr7", 7, TRUE
},
659 {"cr8", 8, TRUE
}, {"cr9", 9, TRUE
}, {"cr10", 10, TRUE
}, {"cr11", 11, TRUE
},
660 {"cr12", 12, TRUE
}, {"cr13", 13, TRUE
}, {"cr14", 14, TRUE
}, {"cr15", 15, TRUE
},
665 static const struct reg_entry fn_table
[] =
667 {"f0", 0, TRUE
}, {"f1", 1, TRUE
}, {"f2", 2, TRUE
}, {"f3", 3, TRUE
},
668 {"f4", 4, TRUE
}, {"f5", 5, TRUE
}, {"f6", 6, TRUE
}, {"f7", 7, TRUE
},
672 /* VFP SP Registers. */
673 static const struct reg_entry sn_table
[] =
675 {"s0", 0, TRUE
}, {"s1", 1, TRUE
}, {"s2", 2, TRUE
}, {"s3", 3, TRUE
},
676 {"s4", 4, TRUE
}, {"s5", 5, TRUE
}, {"s6", 6, TRUE
}, {"s7", 7, TRUE
},
677 {"s8", 8, TRUE
}, {"s9", 9, TRUE
}, {"s10", 10, TRUE
}, {"s11", 11, TRUE
},
678 {"s12", 12, TRUE
}, {"s13", 13, TRUE
}, {"s14", 14, TRUE
}, {"s15", 15, TRUE
},
679 {"s16", 16, TRUE
}, {"s17", 17, TRUE
}, {"s18", 18, TRUE
}, {"s19", 19, TRUE
},
680 {"s20", 20, TRUE
}, {"s21", 21, TRUE
}, {"s22", 22, TRUE
}, {"s23", 23, TRUE
},
681 {"s24", 24, TRUE
}, {"s25", 25, TRUE
}, {"s26", 26, TRUE
}, {"s27", 27, TRUE
},
682 {"s28", 28, TRUE
}, {"s29", 29, TRUE
}, {"s30", 30, TRUE
}, {"s31", 31, TRUE
},
686 /* VFP DP Registers. */
687 static const struct reg_entry dn_table
[] =
689 {"d0", 0, TRUE
}, {"d1", 1, TRUE
}, {"d2", 2, TRUE
}, {"d3", 3, TRUE
},
690 {"d4", 4, TRUE
}, {"d5", 5, TRUE
}, {"d6", 6, TRUE
}, {"d7", 7, TRUE
},
691 {"d8", 8, TRUE
}, {"d9", 9, TRUE
}, {"d10", 10, TRUE
}, {"d11", 11, TRUE
},
692 {"d12", 12, TRUE
}, {"d13", 13, TRUE
}, {"d14", 14, TRUE
}, {"d15", 15, TRUE
},
696 /* Maverick DSP coprocessor registers. */
697 static const struct reg_entry mav_mvf_table
[] =
699 {"mvf0", 0, TRUE
}, {"mvf1", 1, TRUE
}, {"mvf2", 2, TRUE
}, {"mvf3", 3, TRUE
},
700 {"mvf4", 4, TRUE
}, {"mvf5", 5, TRUE
}, {"mvf6", 6, TRUE
}, {"mvf7", 7, TRUE
},
701 {"mvf8", 8, TRUE
}, {"mvf9", 9, TRUE
}, {"mvf10", 10, TRUE
}, {"mvf11", 11, TRUE
},
702 {"mvf12", 12, TRUE
}, {"mvf13", 13, TRUE
}, {"mvf14", 14, TRUE
}, {"mvf15", 15, TRUE
},
706 static const struct reg_entry mav_mvd_table
[] =
708 {"mvd0", 0, TRUE
}, {"mvd1", 1, TRUE
}, {"mvd2", 2, TRUE
}, {"mvd3", 3, TRUE
},
709 {"mvd4", 4, TRUE
}, {"mvd5", 5, TRUE
}, {"mvd6", 6, TRUE
}, {"mvd7", 7, TRUE
},
710 {"mvd8", 8, TRUE
}, {"mvd9", 9, TRUE
}, {"mvd10", 10, TRUE
}, {"mvd11", 11, TRUE
},
711 {"mvd12", 12, TRUE
}, {"mvd13", 13, TRUE
}, {"mvd14", 14, TRUE
}, {"mvd15", 15, TRUE
},
715 static const struct reg_entry mav_mvfx_table
[] =
717 {"mvfx0", 0, TRUE
}, {"mvfx1", 1, TRUE
}, {"mvfx2", 2, TRUE
}, {"mvfx3", 3, TRUE
},
718 {"mvfx4", 4, TRUE
}, {"mvfx5", 5, TRUE
}, {"mvfx6", 6, TRUE
}, {"mvfx7", 7, TRUE
},
719 {"mvfx8", 8, TRUE
}, {"mvfx9", 9, TRUE
}, {"mvfx10", 10, TRUE
}, {"mvfx11", 11, TRUE
},
720 {"mvfx12", 12, TRUE
}, {"mvfx13", 13, TRUE
}, {"mvfx14", 14, TRUE
}, {"mvfx15", 15, TRUE
},
724 static const struct reg_entry mav_mvdx_table
[] =
726 {"mvdx0", 0, TRUE
}, {"mvdx1", 1, TRUE
}, {"mvdx2", 2, TRUE
}, {"mvdx3", 3, TRUE
},
727 {"mvdx4", 4, TRUE
}, {"mvdx5", 5, TRUE
}, {"mvdx6", 6, TRUE
}, {"mvdx7", 7, TRUE
},
728 {"mvdx8", 8, TRUE
}, {"mvdx9", 9, TRUE
}, {"mvdx10", 10, TRUE
}, {"mvdx11", 11, TRUE
},
729 {"mvdx12", 12, TRUE
}, {"mvdx13", 13, TRUE
}, {"mvdx14", 14, TRUE
}, {"mvdx15", 15, TRUE
},
733 static const struct reg_entry mav_mvax_table
[] =
735 {"mvax0", 0, TRUE
}, {"mvax1", 1, TRUE
}, {"mvax2", 2, TRUE
}, {"mvax3", 3, TRUE
},
739 static const struct reg_entry mav_dspsc_table
[] =
747 const struct reg_entry
* names
;
749 struct hash_control
* htab
;
750 const char * expected
;
753 struct reg_map all_reg_maps
[] =
755 {rn_table
, 15, NULL
, N_("ARM register expected")},
756 {cp_table
, 15, NULL
, N_("bad or missing co-processor number")},
757 {cn_table
, 15, NULL
, N_("co-processor register expected")},
758 {fn_table
, 7, NULL
, N_("FPA register expected")},
759 {sn_table
, 31, NULL
, N_("VFP single precision register expected")},
760 {dn_table
, 15, NULL
, N_("VFP double precision register expected")},
761 {mav_mvf_table
, 15, NULL
, N_("Maverick MVF register expected")},
762 {mav_mvd_table
, 15, NULL
, N_("Maverick MVD register expected")},
763 {mav_mvfx_table
, 15, NULL
, N_("Maverick MVFX register expected")},
764 {mav_mvdx_table
, 15, NULL
, N_("Maverick MVDX register expected")},
765 {mav_mvax_table
, 3, NULL
, N_("Maverick MVAX register expected")},
766 {mav_dspsc_table
, 0, NULL
, N_("Maverick DSPSC register expected")},
767 {iwmmxt_table
, 23, NULL
, N_("Intel Wireless MMX technology register expected")},
770 /* Enumeration matching entries in table above. */
774 #define REG_TYPE_FIRST REG_TYPE_RN
786 REG_TYPE_IWMMXT
= 12,
791 /* ARM instructions take 4bytes in the object file, Thumb instructions
795 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
796 #define MAV_MODE1 0x100c
798 /* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
799 #define MAV_MODE2 0x0c10
801 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
802 #define MAV_MODE3 0x100c
804 /* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
805 #define MAV_MODE4 0x0c0010
807 /* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
808 #define MAV_MODE5 0x00100c
810 /* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
811 #define MAV_MODE6 0x00100c05
815 /* Basic string to match. */
816 const char * template;
818 /* Basic instruction code. */
821 /* Offset into the template where the condition code (if any) will be.
822 If zero, then the instruction is never conditional. */
823 unsigned cond_offset
;
825 /* Which architecture variant provides this instruction. */
826 unsigned long variant
;
828 /* Function to call to parse args. */
829 void (* parms
) (char *);
832 /* Defines for various bits that we will want to toggle. */
833 #define INST_IMMEDIATE 0x02000000
834 #define OFFSET_REG 0x02000000
835 #define HWOFFSET_IMM 0x00400000
836 #define SHIFT_BY_REG 0x00000010
837 #define PRE_INDEX 0x01000000
838 #define INDEX_UP 0x00800000
839 #define WRITE_BACK 0x00200000
840 #define LDM_TYPE_2_OR_3 0x00400000
842 #define LITERAL_MASK 0xf000f000
843 #define OPCODE_MASK 0xfe1fffff
844 #define V4_STR_BIT 0x00000020
846 #define DATA_OP_SHIFT 21
848 /* Codes to distinguish the arithmetic instructions. */
859 #define OPCODE_CMP 10
860 #define OPCODE_CMN 11
861 #define OPCODE_ORR 12
862 #define OPCODE_MOV 13
863 #define OPCODE_BIC 14
864 #define OPCODE_MVN 15
866 #define T_OPCODE_MUL 0x4340
867 #define T_OPCODE_TST 0x4200
868 #define T_OPCODE_CMN 0x42c0
869 #define T_OPCODE_NEG 0x4240
870 #define T_OPCODE_MVN 0x43c0
872 #define T_OPCODE_ADD_R3 0x1800
873 #define T_OPCODE_SUB_R3 0x1a00
874 #define T_OPCODE_ADD_HI 0x4400
875 #define T_OPCODE_ADD_ST 0xb000
876 #define T_OPCODE_SUB_ST 0xb080
877 #define T_OPCODE_ADD_SP 0xa800
878 #define T_OPCODE_ADD_PC 0xa000
879 #define T_OPCODE_ADD_I8 0x3000
880 #define T_OPCODE_SUB_I8 0x3800
881 #define T_OPCODE_ADD_I3 0x1c00
882 #define T_OPCODE_SUB_I3 0x1e00
884 #define T_OPCODE_ASR_R 0x4100
885 #define T_OPCODE_LSL_R 0x4080
886 #define T_OPCODE_LSR_R 0x40c0
887 #define T_OPCODE_ASR_I 0x1000
888 #define T_OPCODE_LSL_I 0x0000
889 #define T_OPCODE_LSR_I 0x0800
891 #define T_OPCODE_MOV_I8 0x2000
892 #define T_OPCODE_CMP_I8 0x2800
893 #define T_OPCODE_CMP_LR 0x4280
894 #define T_OPCODE_MOV_HR 0x4600
895 #define T_OPCODE_CMP_HR 0x4500
897 #define T_OPCODE_LDR_PC 0x4800
898 #define T_OPCODE_LDR_SP 0x9800
899 #define T_OPCODE_STR_SP 0x9000
900 #define T_OPCODE_LDR_IW 0x6800
901 #define T_OPCODE_STR_IW 0x6000
902 #define T_OPCODE_LDR_IH 0x8800
903 #define T_OPCODE_STR_IH 0x8000
904 #define T_OPCODE_LDR_IB 0x7800
905 #define T_OPCODE_STR_IB 0x7000
906 #define T_OPCODE_LDR_RW 0x5800
907 #define T_OPCODE_STR_RW 0x5000
908 #define T_OPCODE_LDR_RH 0x5a00
909 #define T_OPCODE_STR_RH 0x5200
910 #define T_OPCODE_LDR_RB 0x5c00
911 #define T_OPCODE_STR_RB 0x5400
913 #define T_OPCODE_PUSH 0xb400
914 #define T_OPCODE_POP 0xbc00
916 #define T_OPCODE_BRANCH 0xe7fe
918 #define THUMB_SIZE 2 /* Size of thumb instruction. */
919 #define THUMB_REG_LO 0x1
920 #define THUMB_REG_HI 0x2
921 #define THUMB_REG_ANY 0x3
923 #define THUMB_H1 0x0080
924 #define THUMB_H2 0x0040
931 #define THUMB_COMPARE 1
935 #define THUMB_STORE 1
937 #define THUMB_PP_PC_LR 0x0100
939 /* These three are used for immediate shifts, do not alter. */
941 #define THUMB_HALFWORD 1
946 /* Basic string to match. */
947 const char * template;
949 /* Basic instruction code. */
954 /* Which CPU variants this exists for. */
955 unsigned long variant
;
957 /* Function to call to parse args. */
958 void (* parms
) (char *);
961 #define BAD_ARGS _("bad arguments to instruction")
962 #define BAD_PC _("r15 not allowed here")
963 #define BAD_COND _("instruction is not conditional")
964 #define ERR_NO_ACCUM _("acc0 expected")
966 static struct hash_control
* arm_ops_hsh
= NULL
;
967 static struct hash_control
* arm_tops_hsh
= NULL
;
968 static struct hash_control
* arm_cond_hsh
= NULL
;
969 static struct hash_control
* arm_shift_hsh
= NULL
;
970 static struct hash_control
* arm_psr_hsh
= NULL
;
972 /* Stuff needed to resolve the label ambiguity
982 symbolS
* last_label_seen
;
983 static int label_is_thumb_function_name
= FALSE
;
985 /* Literal Pool stuff. */
987 #define MAX_LITERAL_POOL_SIZE 1024
989 /* Literal pool structure. Held on a per-section
990 and per-sub-section basis. */
992 typedef struct literal_pool
994 expressionS literals
[MAX_LITERAL_POOL_SIZE
];
995 unsigned int next_free_entry
;
1000 struct literal_pool
* next
;
1003 /* Pointer to a linked list of literal pools. */
1004 literal_pool
* list_of_pools
= NULL
;
1006 static literal_pool
*
1007 find_literal_pool (void)
1009 literal_pool
* pool
;
1011 for (pool
= list_of_pools
; pool
!= NULL
; pool
= pool
->next
)
1013 if (pool
->section
== now_seg
1014 && pool
->sub_section
== now_subseg
)
1021 static literal_pool
*
1022 find_or_make_literal_pool (void)
1024 /* Next literal pool ID number. */
1025 static unsigned int latest_pool_num
= 1;
1026 literal_pool
* pool
;
1028 pool
= find_literal_pool ();
1032 /* Create a new pool. */
1033 pool
= xmalloc (sizeof (* pool
));
1037 pool
->next_free_entry
= 0;
1038 pool
->section
= now_seg
;
1039 pool
->sub_section
= now_subseg
;
1040 pool
->next
= list_of_pools
;
1041 pool
->symbol
= NULL
;
1043 /* Add it to the list. */
1044 list_of_pools
= pool
;
1047 /* New pools, and emptied pools, will have a NULL symbol. */
1048 if (pool
->symbol
== NULL
)
1050 pool
->symbol
= symbol_create (FAKE_LABEL_NAME
, undefined_section
,
1051 (valueT
) 0, &zero_address_frag
);
1052 pool
->id
= latest_pool_num
++;
1059 /* Add the literal in the global 'inst'
1060 structure to the relevent literal pool. */
1063 add_to_lit_pool (void)
1065 literal_pool
* pool
;
1068 pool
= find_or_make_literal_pool ();
1070 /* Check if this literal value is already in the pool. */
1071 for (entry
= 0; entry
< pool
->next_free_entry
; entry
++)
1073 if ((pool
->literals
[entry
].X_op
== inst
.reloc
.exp
.X_op
)
1074 && (inst
.reloc
.exp
.X_op
== O_constant
)
1075 && (pool
->literals
[entry
].X_add_number
1076 == inst
.reloc
.exp
.X_add_number
)
1077 && (pool
->literals
[entry
].X_unsigned
1078 == inst
.reloc
.exp
.X_unsigned
))
1081 if ((pool
->literals
[entry
].X_op
== inst
.reloc
.exp
.X_op
)
1082 && (inst
.reloc
.exp
.X_op
== O_symbol
)
1083 && (pool
->literals
[entry
].X_add_number
1084 == inst
.reloc
.exp
.X_add_number
)
1085 && (pool
->literals
[entry
].X_add_symbol
1086 == inst
.reloc
.exp
.X_add_symbol
)
1087 && (pool
->literals
[entry
].X_op_symbol
1088 == inst
.reloc
.exp
.X_op_symbol
))
1092 /* Do we need to create a new entry? */
1093 if (entry
== pool
->next_free_entry
)
1095 if (entry
>= MAX_LITERAL_POOL_SIZE
)
1097 inst
.error
= _("literal pool overflow");
1101 pool
->literals
[entry
] = inst
.reloc
.exp
;
1102 pool
->next_free_entry
+= 1;
1105 inst
.reloc
.exp
.X_op
= O_symbol
;
1106 inst
.reloc
.exp
.X_add_number
= ((int) entry
) * 4 - 8;
1107 inst
.reloc
.exp
.X_add_symbol
= pool
->symbol
;
1112 /* Can't use symbol_new here, so have to create a symbol and then at
1113 a later date assign it a value. Thats what these functions do. */
1116 symbol_locate (symbolS
* symbolP
,
1117 const char * name
, /* It is copied, the caller can modify. */
1118 segT segment
, /* Segment identifier (SEG_<something>). */
1119 valueT valu
, /* Symbol value. */
1120 fragS
* frag
) /* Associated fragment. */
1122 unsigned int name_length
;
1123 char * preserved_copy_of_name
;
1125 name_length
= strlen (name
) + 1; /* +1 for \0. */
1126 obstack_grow (¬es
, name
, name_length
);
1127 preserved_copy_of_name
= obstack_finish (¬es
);
1128 #ifdef STRIP_UNDERSCORE
1129 if (preserved_copy_of_name
[0] == '_')
1130 preserved_copy_of_name
++;
1133 #ifdef tc_canonicalize_symbol_name
1134 preserved_copy_of_name
=
1135 tc_canonicalize_symbol_name (preserved_copy_of_name
);
1138 S_SET_NAME (symbolP
, preserved_copy_of_name
);
1140 S_SET_SEGMENT (symbolP
, segment
);
1141 S_SET_VALUE (symbolP
, valu
);
1142 symbol_clear_list_pointers (symbolP
);
1144 symbol_set_frag (symbolP
, frag
);
1146 /* Link to end of symbol chain. */
1148 extern int symbol_table_frozen
;
1150 if (symbol_table_frozen
)
1154 symbol_append (symbolP
, symbol_lastP
, & symbol_rootP
, & symbol_lastP
);
1156 obj_symbol_new_hook (symbolP
);
1158 #ifdef tc_symbol_new_hook
1159 tc_symbol_new_hook (symbolP
);
1163 verify_symbol_chain (symbol_rootP
, symbol_lastP
);
1164 #endif /* DEBUG_SYMS */
1167 /* Check that an immediate is valid.
1168 If so, convert it to the right format. */
1171 validate_immediate (unsigned int val
)
1176 #define rotate_left(v, n) (v << n | v >> (32 - n))
1178 for (i
= 0; i
< 32; i
+= 2)
1179 if ((a
= rotate_left (val
, i
)) <= 0xff)
1180 return a
| (i
<< 7); /* 12-bit pack: [shift-cnt,const]. */
1185 /* Check to see if an immediate can be computed as two separate immediate
1186 values, added together. We already know that this value cannot be
1187 computed by just one ARM instruction. */
1190 validate_immediate_twopart (unsigned int val
,
1191 unsigned int * highpart
)
1196 for (i
= 0; i
< 32; i
+= 2)
1197 if (((a
= rotate_left (val
, i
)) & 0xff) != 0)
1203 * highpart
= (a
>> 8) | ((i
+ 24) << 7);
1205 else if (a
& 0xff0000)
1209 * highpart
= (a
>> 16) | ((i
+ 16) << 7);
1213 assert (a
& 0xff000000);
1214 * highpart
= (a
>> 24) | ((i
+ 8) << 7);
1217 return (a
& 0xff) | (i
<< 7);
1224 validate_offset_imm (unsigned int val
, int hwse
)
1226 if ((hwse
&& val
> 255) || val
> 4095)
1233 /* This code is to handle mapping symbols as defined in the ARM ELF spec.
1234 (This text is taken from version B-02 of the spec):
1236 4.4.7 Mapping and tagging symbols
1238 A section of an ARM ELF file can contain a mixture of ARM code,
1239 Thumb code, and data. There are inline transitions between code
1240 and data at literal pool boundaries. There can also be inline
1241 transitions between ARM code and Thumb code, for example in
1242 ARM-Thumb inter-working veneers. Linkers, machine-level
1243 debuggers, profiling tools, and disassembly tools need to map
1244 images accurately. For example, setting an ARM breakpoint on a
1245 Thumb location, or in a literal pool, can crash the program
1246 being debugged, ruining the debugging session.
1248 ARM ELF entities are mapped (see section 4.4.7.1 below) and
1249 tagged (see section 4.4.7.2 below) using local symbols (with
1250 binding STB_LOCAL). To assist consumers, mapping and tagging
1251 symbols should be collated first in the symbol table, before
1252 other symbols with binding STB_LOCAL.
1254 To allow properly collated mapping and tagging symbols to be
1255 skipped by consumers that have no interest in them, the first
1256 such symbol should have the name $m and its st_value field equal
1257 to the total number of mapping and tagging symbols (including
1258 the $m) in the symbol table.
1260 4.4.7.1 Mapping symbols
1262 $a Labels the first byte of a sequence of ARM instructions.
1263 Its type is STT_FUNC.
1265 $d Labels the first byte of a sequence of data items.
1266 Its type is STT_OBJECT.
1268 $t Labels the first byte of a sequence of Thumb instructions.
1269 Its type is STT_FUNC.
1271 This list of mapping symbols may be extended in the future.
1273 Section-relative mapping symbols
1275 Mapping symbols defined in a section define a sequence of
1276 half-open address intervals that cover the address range of the
1277 section. Each interval starts at the address defined by a
1278 mapping symbol, and continues up to, but not including, the
1279 address defined by the next (in address order) mapping symbol or
1280 the end of the section. A corollary is that there must be a
1281 mapping symbol defined at the beginning of each section.
1282 Consumers can ignore the size of a section-relative mapping
1283 symbol. Producers can set it to 0.
1285 Absolute mapping symbols
1287 Because of the need to crystallize a Thumb address with the
1288 Thumb-bit set, absolute symbol of type STT_FUNC (symbols of type
1289 STT_FUNC defined in section SHN_ABS) need to be mapped with $a
1292 The extent of a mapping symbol defined in SHN_ABS is [st_value,
1293 st_value + st_size), or [st_value, st_value + 1) if st_size = 0,
1294 where [x, y) denotes the half-open address range from x,
1295 inclusive, to y, exclusive.
1297 In the absence of a mapping symbol, a consumer can interpret a
1298 function symbol with an odd value as the Thumb code address
1299 obtained by clearing the least significant bit of the
1300 value. This interpretation is deprecated, and it may not work in
1303 Note - the Tagging symbols ($b, $f, $p $m) have been dropped from
1304 the EABI (which is still under development), so they are not
1305 implemented here. */
1307 static enum mstate mapstate
= MAP_UNDEFINED
;
1310 mapping_state (enum mstate state
)
1313 const char * symname
;
1316 if (mapstate
== state
)
1317 /* The mapping symbol has already been emitted.
1318 There is nothing else to do. */
1331 type
= BSF_FUNCTION
;
1335 type
= BSF_FUNCTION
;
1343 seg_info (now_seg
)->tc_segment_info_data
= state
;
1345 symbolP
= symbol_new (symname
, now_seg
, (valueT
) frag_now_fix (), frag_now
);
1346 symbol_table_insert (symbolP
);
1347 symbol_get_bfdsym (symbolP
)->flags
|= type
| BSF_LOCAL
;
1352 THUMB_SET_FUNC (symbolP
, 0);
1353 ARM_SET_THUMB (symbolP
, 0);
1354 ARM_SET_INTERWORK (symbolP
, support_interwork
);
1358 THUMB_SET_FUNC (symbolP
, 1);
1359 ARM_SET_THUMB (symbolP
, 1);
1360 ARM_SET_INTERWORK (symbolP
, support_interwork
);
1369 /* When we change sections we need to issue a new mapping symbol. */
1372 arm_elf_change_section (void)
1376 /* Link an unlinked unwind index table section to the .text section. */
1377 if (elf_section_type (now_seg
) == SHT_ARM_EXIDX
1378 && elf_linked_to_section (now_seg
) == NULL
)
1379 elf_linked_to_section (now_seg
) = text_section
;
1381 if (!SEG_NORMAL (now_seg
))
1384 flags
= bfd_get_section_flags (stdoutput
, now_seg
);
1386 /* We can ignore sections that only contain debug info. */
1387 if ((flags
& SEC_ALLOC
) == 0)
1390 mapstate
= seg_info (now_seg
)->tc_segment_info_data
;
1394 arm_elf_section_type (const char * str
, size_t len
)
1396 if (len
== 5 && strncmp (str
, "exidx", 5) == 0)
1397 return SHT_ARM_EXIDX
;
1402 #define mapping_state(a)
1403 #endif /* OBJ_ELF */
1405 /* arm_reg_parse () := if it looks like a register, return its token and
1406 advance the pointer. */
1409 arm_reg_parse (char ** ccp
, struct hash_control
* htab
)
1411 char * start
= * ccp
;
1414 struct reg_entry
* reg
;
1416 #ifdef REGISTER_PREFIX
1417 if (*start
!= REGISTER_PREFIX
)
1422 #ifdef OPTIONAL_REGISTER_PREFIX
1423 if (*p
== OPTIONAL_REGISTER_PREFIX
)
1427 if (!ISALPHA (*p
) || !is_name_beginner (*p
))
1431 while (ISALPHA (c
) || ISDIGIT (c
) || c
== '_')
1435 reg
= (struct reg_entry
*) hash_find (htab
, start
);
1447 /* Search for the following register name in each of the possible reg name
1448 tables. Return the classification if found, or REG_TYPE_MAX if not
1451 static enum arm_reg_type
1452 arm_reg_parse_any (char *cp
)
1456 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
1457 if (arm_reg_parse (&cp
, all_reg_maps
[i
].htab
) != FAIL
)
1458 return (enum arm_reg_type
) i
;
1460 return REG_TYPE_MAX
;
1464 opcode_select (int width
)
1471 if (! (cpu_variant
& ARM_EXT_V4T
))
1472 as_bad (_("selected processor does not support THUMB opcodes"));
1475 /* No need to force the alignment, since we will have been
1476 coming from ARM mode, which is word-aligned. */
1477 record_alignment (now_seg
, 1);
1479 mapping_state (MAP_THUMB
);
1485 if ((cpu_variant
& ARM_ALL
) == ARM_EXT_V4T
)
1486 as_bad (_("selected processor does not support ARM opcodes"));
1491 frag_align (2, 0, 0);
1493 record_alignment (now_seg
, 1);
1495 mapping_state (MAP_ARM
);
1499 as_bad (_("invalid instruction size selected (%d)"), width
);
1504 s_req (int a ATTRIBUTE_UNUSED
)
1506 as_bad (_("invalid syntax for .req directive"));
1509 /* The .unreq directive deletes an alias which was previously defined
1510 by .req. For example:
1516 s_unreq (int a ATTRIBUTE_UNUSED
)
1521 skip_whitespace (input_line_pointer
);
1522 name
= input_line_pointer
;
1524 while (*input_line_pointer
!= 0
1525 && *input_line_pointer
!= ' '
1526 && *input_line_pointer
!= '\n')
1527 ++input_line_pointer
;
1529 saved_char
= *input_line_pointer
;
1530 *input_line_pointer
= 0;
1534 enum arm_reg_type req_type
= arm_reg_parse_any (name
);
1536 if (req_type
!= REG_TYPE_MAX
)
1538 char *temp_name
= name
;
1539 int req_no
= arm_reg_parse (&temp_name
, all_reg_maps
[req_type
].htab
);
1543 struct reg_entry
*req_entry
;
1545 /* Check to see if this alias is a builtin one. */
1546 req_entry
= hash_delete (all_reg_maps
[req_type
].htab
, name
);
1549 as_bad (_("unreq: missing hash entry for \"%s\""), name
);
1550 else if (req_entry
->builtin
)
1551 /* FIXME: We are deleting a built in register alias which
1552 points to a const data structure, so we only need to
1553 free up the memory used by the key in the hash table.
1554 Unfortunately we have not recorded this value, so this
1555 is a memory leak. */
1556 /* FIXME: Should we issue a warning message ? */
1560 /* Deleting a user defined alias. We need to free the
1561 key and the value, but fortunately the key is the same
1562 as the value->name field. */
1563 free ((char *) req_entry
->name
);
1568 as_bad (_(".unreq: unrecognized symbol \"%s\""), name
);
1571 as_bad (_(".unreq: unrecognized symbol \"%s\""), name
);
1574 as_bad (_("invalid syntax for .unreq directive"));
1576 *input_line_pointer
= saved_char
;
1577 demand_empty_rest_of_line ();
1581 s_bss (int ignore ATTRIBUTE_UNUSED
)
1583 /* We don't support putting frags in the BSS segment, we fake it by
1584 marking in_bss, then looking at s_skip for clues. */
1585 subseg_set (bss_section
, 0);
1586 demand_empty_rest_of_line ();
1587 mapping_state (MAP_DATA
);
1591 s_even (int ignore ATTRIBUTE_UNUSED
)
1593 /* Never make frag if expect extra pass. */
1595 frag_align (1, 0, 0);
1597 record_alignment (now_seg
, 1);
1599 demand_empty_rest_of_line ();
1603 s_ltorg (int ignored ATTRIBUTE_UNUSED
)
1606 literal_pool
* pool
;
1609 pool
= find_literal_pool ();
1611 || pool
->symbol
== NULL
1612 || pool
->next_free_entry
== 0)
1615 mapping_state (MAP_DATA
);
1617 /* Align pool as you have word accesses.
1618 Only make a frag if we have to. */
1620 frag_align (2, 0, 0);
1622 record_alignment (now_seg
, 2);
1624 sprintf (sym_name
, "$$lit_\002%x", pool
->id
);
1626 symbol_locate (pool
->symbol
, sym_name
, now_seg
,
1627 (valueT
) frag_now_fix (), frag_now
);
1628 symbol_table_insert (pool
->symbol
);
1630 ARM_SET_THUMB (pool
->symbol
, thumb_mode
);
1632 #if defined OBJ_COFF || defined OBJ_ELF
1633 ARM_SET_INTERWORK (pool
->symbol
, support_interwork
);
1636 for (entry
= 0; entry
< pool
->next_free_entry
; entry
++)
1637 /* First output the expression in the instruction to the pool. */
1638 emit_expr (&(pool
->literals
[entry
]), 4); /* .word */
1640 /* Mark the pool as empty. */
1641 pool
->next_free_entry
= 0;
1642 pool
->symbol
= NULL
;
1645 /* Same as s_align_ptwo but align 0 => align 2. */
1648 s_align (int unused ATTRIBUTE_UNUSED
)
1652 long max_alignment
= 15;
1654 temp
= get_absolute_expression ();
1655 if (temp
> max_alignment
)
1656 as_bad (_("alignment too large: %d assumed"), temp
= max_alignment
);
1659 as_bad (_("alignment negative. 0 assumed."));
1663 if (*input_line_pointer
== ',')
1665 input_line_pointer
++;
1666 temp_fill
= get_absolute_expression ();
1674 /* Only make a frag if we HAVE to. */
1675 if (temp
&& !need_pass_2
)
1676 frag_align (temp
, (int) temp_fill
, 0);
1677 demand_empty_rest_of_line ();
1679 record_alignment (now_seg
, temp
);
1683 s_force_thumb (int ignore ATTRIBUTE_UNUSED
)
1685 /* If we are not already in thumb mode go into it, EVEN if
1686 the target processor does not support thumb instructions.
1687 This is used by gcc/config/arm/lib1funcs.asm for example
1688 to compile interworking support functions even if the
1689 target processor should not support interworking. */
1694 record_alignment (now_seg
, 1);
1697 demand_empty_rest_of_line ();
1701 s_thumb_func (int ignore ATTRIBUTE_UNUSED
)
1706 /* The following label is the name/address of the start of a Thumb function.
1707 We need to know this for the interworking support. */
1708 label_is_thumb_function_name
= TRUE
;
1710 demand_empty_rest_of_line ();
1713 /* Perform a .set directive, but also mark the alias as
1714 being a thumb function. */
1717 s_thumb_set (int equiv
)
1719 /* XXX the following is a duplicate of the code for s_set() in read.c
1720 We cannot just call that code as we need to get at the symbol that
1727 /* Especial apologies for the random logic:
1728 This just grew, and could be parsed much more simply!
1730 name
= input_line_pointer
;
1731 delim
= get_symbol_end ();
1732 end_name
= input_line_pointer
;
1737 if (*input_line_pointer
!= ',')
1740 as_bad (_("expected comma after name \"%s\""), name
);
1742 ignore_rest_of_line ();
1746 input_line_pointer
++;
1749 if (name
[0] == '.' && name
[1] == '\0')
1751 /* XXX - this should not happen to .thumb_set. */
1755 if ((symbolP
= symbol_find (name
)) == NULL
1756 && (symbolP
= md_undefined_symbol (name
)) == NULL
)
1759 /* When doing symbol listings, play games with dummy fragments living
1760 outside the normal fragment chain to record the file and line info
1762 if (listing
& LISTING_SYMBOLS
)
1764 extern struct list_info_struct
* listing_tail
;
1765 fragS
* dummy_frag
= xmalloc (sizeof (fragS
));
1767 memset (dummy_frag
, 0, sizeof (fragS
));
1768 dummy_frag
->fr_type
= rs_fill
;
1769 dummy_frag
->line
= listing_tail
;
1770 symbolP
= symbol_new (name
, undefined_section
, 0, dummy_frag
);
1771 dummy_frag
->fr_symbol
= symbolP
;
1775 symbolP
= symbol_new (name
, undefined_section
, 0, &zero_address_frag
);
1778 /* "set" symbols are local unless otherwise specified. */
1779 SF_SET_LOCAL (symbolP
);
1780 #endif /* OBJ_COFF */
1781 } /* Make a new symbol. */
1783 symbol_table_insert (symbolP
);
1788 && S_IS_DEFINED (symbolP
)
1789 && S_GET_SEGMENT (symbolP
) != reg_section
)
1790 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP
));
1792 pseudo_set (symbolP
);
1794 demand_empty_rest_of_line ();
1796 /* XXX Now we come to the Thumb specific bit of code. */
1798 THUMB_SET_FUNC (symbolP
, 1);
1799 ARM_SET_THUMB (symbolP
, 1);
1800 #if defined OBJ_ELF || defined OBJ_COFF
1801 ARM_SET_INTERWORK (symbolP
, support_interwork
);
1806 s_arm (int ignore ATTRIBUTE_UNUSED
)
1809 demand_empty_rest_of_line ();
1813 s_thumb (int ignore ATTRIBUTE_UNUSED
)
1816 demand_empty_rest_of_line ();
1820 s_code (int unused ATTRIBUTE_UNUSED
)
1824 temp
= get_absolute_expression ();
1829 opcode_select (temp
);
1833 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp
);
1838 end_of_line (char * str
)
1840 skip_whitespace (str
);
1842 if (*str
!= '\0' && !inst
.error
)
1843 inst
.error
= _("garbage following instruction");
1847 skip_past_comma (char ** str
)
1849 char * p
= * str
, c
;
1852 while ((c
= *p
) == ' ' || c
== ',')
1855 if (c
== ',' && comma
++)
1863 return comma
? SUCCESS
: FAIL
;
1866 /* Return TRUE if anything in the expression is a bignum. */
1869 walk_no_bignums (symbolS
* sp
)
1871 if (symbol_get_value_expression (sp
)->X_op
== O_big
)
1874 if (symbol_get_value_expression (sp
)->X_add_symbol
)
1876 return (walk_no_bignums (symbol_get_value_expression (sp
)->X_add_symbol
)
1877 || (symbol_get_value_expression (sp
)->X_op_symbol
1878 && walk_no_bignums (symbol_get_value_expression (sp
)->X_op_symbol
)));
1884 static int in_my_get_expression
= 0;
1887 my_get_expression (expressionS
* ep
, char ** str
)
1892 save_in
= input_line_pointer
;
1893 input_line_pointer
= *str
;
1894 in_my_get_expression
= 1;
1895 seg
= expression (ep
);
1896 in_my_get_expression
= 0;
1898 if (ep
->X_op
== O_illegal
)
1900 /* We found a bad expression in md_operand(). */
1901 *str
= input_line_pointer
;
1902 input_line_pointer
= save_in
;
1907 if (seg
!= absolute_section
1908 && seg
!= text_section
1909 && seg
!= data_section
1910 && seg
!= bss_section
1911 && seg
!= undefined_section
)
1913 inst
.error
= _("bad_segment");
1914 *str
= input_line_pointer
;
1915 input_line_pointer
= save_in
;
1920 /* Get rid of any bignums now, so that we don't generate an error for which
1921 we can't establish a line number later on. Big numbers are never valid
1922 in instructions, which is where this routine is always called. */
1923 if (ep
->X_op
== O_big
1924 || (ep
->X_add_symbol
1925 && (walk_no_bignums (ep
->X_add_symbol
)
1927 && walk_no_bignums (ep
->X_op_symbol
)))))
1929 inst
.error
= _("invalid constant");
1930 *str
= input_line_pointer
;
1931 input_line_pointer
= save_in
;
1935 *str
= input_line_pointer
;
1936 input_line_pointer
= save_in
;
1940 /* A standard register must be given at this point.
1941 SHIFT is the place to put it in inst.instruction.
1942 Restores input start point on error.
1943 Returns the reg#, or FAIL. */
1946 reg_required_here (char ** str
, int shift
)
1948 static char buff
[128]; /* XXX */
1950 char * start
= * str
;
1952 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_RN
].htab
)) != FAIL
)
1955 inst
.instruction
|= reg
<< shift
;
1959 /* Restore the start point, we may have got a reg of the wrong class. */
1962 /* In the few cases where we might be able to accept something else
1963 this error can be overridden. */
1964 sprintf (buff
, _("register expected, not '%.100s'"), start
);
1970 /* A Intel Wireless MMX technology register
1971 must be given at this point.
1972 Shift is the place to put it in inst.instruction.
1973 Restores input start point on err.
1974 Returns the reg#, or FAIL. */
1977 wreg_required_here (char ** str
,
1979 enum wreg_type reg_type
)
1981 static char buff
[128];
1983 char * start
= *str
;
1985 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_IWMMXT
].htab
)) != FAIL
)
1987 if (wr_register (reg
)
1988 && (reg_type
== IWMMXT_REG_WR
|| reg_type
== IWMMXT_REG_WR_OR_WC
))
1991 inst
.instruction
|= (reg
^ WR_PREFIX
) << shift
;
1994 else if (wc_register (reg
)
1995 && (reg_type
== IWMMXT_REG_WC
|| reg_type
== IWMMXT_REG_WR_OR_WC
))
1998 inst
.instruction
|= (reg
^ WC_PREFIX
) << shift
;
2001 else if ((wcg_register (reg
) && reg_type
== IWMMXT_REG_WCG
))
2004 inst
.instruction
|= ((reg
^ WC_PREFIX
) - 8) << shift
;
2009 /* Restore the start point, we may have got a reg of the wrong class. */
2012 /* In the few cases where we might be able to accept
2013 something else this error can be overridden. */
2014 sprintf (buff
, _("Intel Wireless MMX technology register expected, not '%.100s'"), start
);
2020 static const struct asm_psr
*
2021 arm_psr_parse (char ** ccp
)
2023 char * start
= * ccp
;
2026 const struct asm_psr
* psr
;
2030 /* Skip to the end of the next word in the input stream. */
2035 while (ISALPHA (c
) || c
== '_');
2037 /* Terminate the word. */
2040 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
2041 feature for ease of use and backwards compatibility. */
2042 if (!strncmp (start
, "cpsr", 4))
2043 strncpy (start
, "CPSR", 4);
2044 else if (!strncmp (start
, "spsr", 4))
2045 strncpy (start
, "SPSR", 4);
2047 /* Now locate the word in the psr hash table. */
2048 psr
= (const struct asm_psr
*) hash_find (arm_psr_hsh
, start
);
2050 /* Restore the input stream. */
2053 /* If we found a valid match, advance the
2054 stream pointer past the end of the word. */
2060 /* Parse the input looking for a PSR flag. */
2063 psr_required_here (char ** str
)
2065 char * start
= * str
;
2066 const struct asm_psr
* psr
;
2068 psr
= arm_psr_parse (str
);
2072 /* If this is the SPSR that is being modified, set the R bit. */
2074 inst
.instruction
|= SPSR_BIT
;
2076 /* Set the psr flags in the MSR instruction. */
2077 inst
.instruction
|= psr
->field
<< PSR_SHIFT
;
2082 /* In the few cases where we might be able to accept
2083 something else this error can be overridden. */
2084 inst
.error
= _("flag for {c}psr instruction expected");
2086 /* Restore the start point. */
2092 co_proc_number (char ** str
)
2094 int processor
, pchar
;
2097 skip_whitespace (*str
);
2100 /* The data sheet seems to imply that just a number on its own is valid
2101 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
2103 if ((processor
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CP
].htab
))
2109 if (pchar
>= '0' && pchar
<= '9')
2111 processor
= pchar
- '0';
2112 if (**str
>= '0' && **str
<= '9')
2114 processor
= processor
* 10 + *(*str
)++ - '0';
2117 inst
.error
= _("illegal co-processor number");
2124 inst
.error
= all_reg_maps
[REG_TYPE_CP
].expected
;
2129 inst
.instruction
|= processor
<< 8;
2134 cp_opc_expr (char ** str
, int where
, int length
)
2138 skip_whitespace (* str
);
2140 memset (&expr
, '\0', sizeof (expr
));
2142 if (my_get_expression (&expr
, str
))
2144 if (expr
.X_op
!= O_constant
)
2146 inst
.error
= _("bad or missing expression");
2150 if ((expr
.X_add_number
& ((1 << length
) - 1)) != expr
.X_add_number
)
2152 inst
.error
= _("immediate co-processor expression too large");
2156 inst
.instruction
|= expr
.X_add_number
<< where
;
2161 cp_reg_required_here (char ** str
, int where
)
2164 char * start
= *str
;
2166 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CN
].htab
)) != FAIL
)
2168 inst
.instruction
|= reg
<< where
;
2172 /* In the few cases where we might be able to accept something else
2173 this error can be overridden. */
2174 inst
.error
= all_reg_maps
[REG_TYPE_CN
].expected
;
2176 /* Restore the start point. */
2182 fp_reg_required_here (char ** str
, int where
)
2185 char * start
= * str
;
2187 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_FN
].htab
)) != FAIL
)
2189 inst
.instruction
|= reg
<< where
;
2193 /* In the few cases where we might be able to accept something else
2194 this error can be overridden. */
2195 inst
.error
= all_reg_maps
[REG_TYPE_FN
].expected
;
2197 /* Restore the start point. */
2203 cp_address_offset (char ** str
)
2207 skip_whitespace (* str
);
2209 if (! is_immediate_prefix (**str
))
2211 inst
.error
= _("immediate expression expected");
2217 if (my_get_expression (& inst
.reloc
.exp
, str
))
2220 if (inst
.reloc
.exp
.X_op
== O_constant
)
2222 offset
= inst
.reloc
.exp
.X_add_number
;
2226 inst
.error
= _("co-processor address must be word aligned");
2230 if (offset
> 1023 || offset
< -1023)
2232 inst
.error
= _("offset too large");
2237 inst
.instruction
|= INDEX_UP
;
2241 inst
.instruction
|= offset
>> 2;
2244 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
2250 cp_address_required_here (char ** str
, int wb_ok
)
2261 skip_whitespace (p
);
2263 if ((reg
= reg_required_here (& p
, 16)) == FAIL
)
2266 skip_whitespace (p
);
2272 skip_whitespace (p
);
2276 /* As an extension to the official ARM syntax we allow:
2278 as a short hand for:
2280 inst
.instruction
|= PRE_INDEX
| INDEX_UP
;
2285 if (skip_past_comma (& p
) == FAIL
)
2287 inst
.error
= _("comma expected after closing square bracket");
2291 skip_whitespace (p
);
2298 write_back
= WRITE_BACK
;
2302 inst
.error
= _("pc may not be used in post-increment");
2306 if (cp_address_offset (& p
) == FAIL
)
2310 pre_inc
= PRE_INDEX
| INDEX_UP
;
2316 /* [Rn], {<expr>} */
2319 skip_whitespace (p
);
2321 if (my_get_expression (& inst
.reloc
.exp
, & p
))
2324 if (inst
.reloc
.exp
.X_op
== O_constant
)
2326 option
= inst
.reloc
.exp
.X_add_number
;
2328 if (option
> 255 || option
< 0)
2330 inst
.error
= _("'option' field too large");
2334 skip_whitespace (p
);
2338 inst
.error
= _("'}' expected at end of 'option' field");
2344 inst
.instruction
|= option
;
2345 inst
.instruction
|= INDEX_UP
;
2350 inst
.error
= _("non-constant expressions for 'option' field not supported");
2356 inst
.error
= _("# or { expected after comma");
2362 /* '['Rn, #expr']'[!] */
2364 if (skip_past_comma (& p
) == FAIL
)
2366 inst
.error
= _("pre-indexed expression expected");
2370 pre_inc
= PRE_INDEX
;
2372 if (cp_address_offset (& p
) == FAIL
)
2375 skip_whitespace (p
);
2379 inst
.error
= _("missing ]");
2383 skip_whitespace (p
);
2385 if (wb_ok
&& *p
== '!')
2389 inst
.error
= _("pc may not be used with write-back");
2394 write_back
= WRITE_BACK
;
2400 if (my_get_expression (&inst
.reloc
.exp
, &p
))
2403 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
2404 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
2405 inst
.reloc
.pc_rel
= 1;
2406 inst
.instruction
|= (REG_PC
<< 16);
2407 pre_inc
= PRE_INDEX
;
2410 inst
.instruction
|= write_back
| pre_inc
;
2416 cp_byte_address_offset (char ** str
)
2420 skip_whitespace (* str
);
2422 if (! is_immediate_prefix (**str
))
2424 inst
.error
= _("immediate expression expected");
2430 if (my_get_expression (& inst
.reloc
.exp
, str
))
2433 if (inst
.reloc
.exp
.X_op
== O_constant
)
2435 offset
= inst
.reloc
.exp
.X_add_number
;
2437 if (offset
> 255 || offset
< -255)
2439 inst
.error
= _("offset too large");
2444 inst
.instruction
|= INDEX_UP
;
2448 inst
.instruction
|= offset
;
2451 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM_S2
;
2457 cp_byte_address_required_here (char ** str
)
2468 skip_whitespace (p
);
2470 if ((reg
= reg_required_here (& p
, 16)) == FAIL
)
2473 skip_whitespace (p
);
2479 if (skip_past_comma (& p
) == SUCCESS
)
2482 write_back
= WRITE_BACK
;
2486 inst
.error
= _("pc may not be used in post-increment");
2490 if (cp_byte_address_offset (& p
) == FAIL
)
2494 pre_inc
= PRE_INDEX
| INDEX_UP
;
2498 /* '['Rn, #expr']'[!] */
2500 if (skip_past_comma (& p
) == FAIL
)
2502 inst
.error
= _("pre-indexed expression expected");
2506 pre_inc
= PRE_INDEX
;
2508 if (cp_byte_address_offset (& p
) == FAIL
)
2511 skip_whitespace (p
);
2515 inst
.error
= _("missing ]");
2519 skip_whitespace (p
);
2525 inst
.error
= _("pc may not be used with write-back");
2530 write_back
= WRITE_BACK
;
2536 if (my_get_expression (&inst
.reloc
.exp
, &p
))
2539 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM_S2
;
2540 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
2541 inst
.reloc
.pc_rel
= 1;
2542 inst
.instruction
|= (REG_PC
<< 16);
2543 pre_inc
= PRE_INDEX
;
2546 inst
.instruction
|= write_back
| pre_inc
;
2554 skip_whitespace (str
);
2559 if (my_get_expression (&inst
.reloc
.exp
, &str
))
2560 inst
.reloc
.exp
.X_op
= O_illegal
;
2563 skip_whitespace (str
);
2567 inst
.reloc
.exp
.X_op
= O_illegal
;
2570 if (inst
.reloc
.exp
.X_op
!= O_constant
2571 || inst
.reloc
.exp
.X_add_number
> 255
2572 || inst
.reloc
.exp
.X_add_number
< 0)
2574 inst
.error
= _("Invalid NOP hint");
2578 /* Arcitectural NOP hints are CPSR sets with no bits selected. */
2579 inst
.instruction
&= 0xf0000000;
2580 inst
.instruction
|= 0x0320f000 + inst
.reloc
.exp
.X_add_number
;
2587 do_empty (char * str
)
2589 /* Do nothing really. */
2598 /* Only one syntax. */
2599 skip_whitespace (str
);
2601 if (reg_required_here (&str
, 12) == FAIL
)
2603 inst
.error
= BAD_ARGS
;
2607 if (skip_past_comma (&str
) == FAIL
)
2609 inst
.error
= _("comma expected after register name");
2613 skip_whitespace (str
);
2615 if ( streq (str
, "CPSR")
2616 || streq (str
, "SPSR")
2617 /* Lower case versions for backwards compatibility. */
2618 || streq (str
, "cpsr")
2619 || streq (str
, "spsr"))
2622 /* This is for backwards compatibility with older toolchains. */
2623 else if ( streq (str
, "cpsr_all")
2624 || streq (str
, "spsr_all"))
2628 inst
.error
= _("CPSR or SPSR expected");
2632 if (* str
== 's' || * str
== 'S')
2633 inst
.instruction
|= SPSR_BIT
;
2639 /* Two possible forms:
2640 "{C|S}PSR_<field>, Rm",
2641 "{C|S}PSR_f, #expression". */
2646 skip_whitespace (str
);
2648 if (psr_required_here (& str
) == FAIL
)
2651 if (skip_past_comma (& str
) == FAIL
)
2653 inst
.error
= _("comma missing after psr flags");
2657 skip_whitespace (str
);
2659 if (reg_required_here (& str
, 0) != FAIL
)
2666 if (! is_immediate_prefix (* str
))
2669 _("only a register or immediate value can follow a psr flag");
2676 if (my_get_expression (& inst
.reloc
.exp
, & str
))
2679 _("only a register or immediate value can follow a psr flag");
2683 #if 0 /* The first edition of the ARM architecture manual stated that
2684 writing anything other than the flags with an immediate operation
2685 had UNPREDICTABLE effects. This constraint was removed in the
2686 second edition of the specification. */
2687 if ((cpu_variant
& ARM_EXT_V5
) != ARM_EXT_V5
2688 && inst
.instruction
& ((PSR_c
| PSR_x
| PSR_s
) << PSR_SHIFT
))
2690 inst
.error
= _("immediate value cannot be used to set this field");
2695 inst
.instruction
|= INST_IMMEDIATE
;
2697 if (inst
.reloc
.exp
.X_add_symbol
)
2699 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
2700 inst
.reloc
.pc_rel
= 0;
2704 unsigned value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
2706 if (value
== (unsigned) FAIL
)
2708 inst
.error
= _("invalid constant");
2712 inst
.instruction
|= value
;
2719 /* Long Multiply Parser
2720 UMULL RdLo, RdHi, Rm, Rs
2721 SMULL RdLo, RdHi, Rm, Rs
2722 UMLAL RdLo, RdHi, Rm, Rs
2723 SMLAL RdLo, RdHi, Rm, Rs. */
2726 do_mull (char * str
)
2728 int rdlo
, rdhi
, rm
, rs
;
2730 /* Only one format "rdlo, rdhi, rm, rs". */
2731 skip_whitespace (str
);
2733 if ((rdlo
= reg_required_here (&str
, 12)) == FAIL
)
2735 inst
.error
= BAD_ARGS
;
2739 if (skip_past_comma (&str
) == FAIL
2740 || (rdhi
= reg_required_here (&str
, 16)) == FAIL
)
2742 inst
.error
= BAD_ARGS
;
2746 if (skip_past_comma (&str
) == FAIL
2747 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
2749 inst
.error
= BAD_ARGS
;
2753 /* rdhi, rdlo and rm must all be different. */
2754 if (rdlo
== rdhi
|| rdlo
== rm
|| rdhi
== rm
)
2755 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
2757 if (skip_past_comma (&str
) == FAIL
2758 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
2760 inst
.error
= BAD_ARGS
;
2764 if (rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
)
2766 inst
.error
= BAD_PC
;
2778 /* Only one format "rd, rm, rs". */
2779 skip_whitespace (str
);
2781 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
2783 inst
.error
= BAD_ARGS
;
2789 inst
.error
= BAD_PC
;
2793 if (skip_past_comma (&str
) == FAIL
2794 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
2796 inst
.error
= BAD_ARGS
;
2802 inst
.error
= BAD_PC
;
2807 as_tsktsk (_("rd and rm should be different in mul"));
2809 if (skip_past_comma (&str
) == FAIL
2810 || (rm
= reg_required_here (&str
, 8)) == FAIL
)
2812 inst
.error
= BAD_ARGS
;
2818 inst
.error
= BAD_PC
;
2830 /* Only one format "rd, rm, rs, rn". */
2831 skip_whitespace (str
);
2833 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
2835 inst
.error
= BAD_ARGS
;
2841 inst
.error
= BAD_PC
;
2845 if (skip_past_comma (&str
) == FAIL
2846 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
2848 inst
.error
= BAD_ARGS
;
2854 inst
.error
= BAD_PC
;
2859 as_tsktsk (_("rd and rm should be different in mla"));
2861 if (skip_past_comma (&str
) == FAIL
2862 || (rd
= reg_required_here (&str
, 8)) == FAIL
2863 || skip_past_comma (&str
) == FAIL
2864 || (rm
= reg_required_here (&str
, 12)) == FAIL
)
2866 inst
.error
= BAD_ARGS
;
2870 if (rd
== REG_PC
|| rm
== REG_PC
)
2872 inst
.error
= BAD_PC
;
2879 /* Expects *str -> the characters "acc0", possibly with leading blanks.
2880 Advances *str to the next non-alphanumeric.
2881 Returns 0, or else FAIL (in which case sets inst.error).
2883 (In a future XScale, there may be accumulators other than zero.
2884 At that time this routine and its callers can be upgraded to suit.) */
2887 accum0_required_here (char ** str
)
2889 static char buff
[128]; /* Note the address is taken. Hence, static. */
2892 int result
= 0; /* The accum number. */
2894 skip_whitespace (p
);
2896 *str
= p
; /* Advance caller's string pointer too. */
2901 *--p
= 0; /* Aap nul into input buffer at non-alnum. */
2903 if (! ( streq (*str
, "acc0") || streq (*str
, "ACC0")))
2905 sprintf (buff
, _("acc0 expected, not '%.100s'"), *str
);
2910 *p
= c
; /* Unzap. */
2911 *str
= p
; /* Caller's string pointer to after match. */
2916 ldst_extend_v4 (char ** str
)
2925 if (my_get_expression (& inst
.reloc
.exp
, str
))
2928 if (inst
.reloc
.exp
.X_op
== O_constant
)
2930 int value
= inst
.reloc
.exp
.X_add_number
;
2932 if (value
< -255 || value
> 255)
2934 inst
.error
= _("address offset too large");
2944 /* Halfword and signextension instructions have the
2945 immediate value split across bits 11..8 and bits 3..0. */
2946 inst
.instruction
|= (add
| HWOFFSET_IMM
2947 | ((value
>> 4) << 8) | (value
& 0xF));
2951 inst
.instruction
|= HWOFFSET_IMM
;
2952 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
2953 inst
.reloc
.pc_rel
= 0;
2966 if (reg_required_here (str
, 0) == FAIL
)
2969 inst
.instruction
|= add
;
2974 /* Expects **str -> after a comma. May be leading blanks.
2975 Advances *str, recognizing a load mode, and setting inst.instruction.
2976 Returns rn, or else FAIL (in which case may set inst.error
2977 and not advance str)
2979 Note: doesn't know Rd, so no err checks that require such knowledge. */
2982 ld_mode_required_here (char ** string
)
2984 char * str
= * string
;
2988 skip_whitespace (str
);
2994 skip_whitespace (str
);
2996 if ((rn
= reg_required_here (& str
, 16)) == FAIL
)
2999 skip_whitespace (str
);
3005 if (skip_past_comma (& str
) == SUCCESS
)
3007 /* [Rn],... (post inc) */
3008 if (ldst_extend_v4 (&str
) == FAIL
)
3013 skip_whitespace (str
);
3018 inst
.instruction
|= WRITE_BACK
;
3021 inst
.instruction
|= INDEX_UP
| HWOFFSET_IMM
;
3027 if (skip_past_comma (& str
) == FAIL
)
3029 inst
.error
= _("pre-indexed expression expected");
3035 if (ldst_extend_v4 (&str
) == FAIL
)
3038 skip_whitespace (str
);
3040 if (* str
++ != ']')
3042 inst
.error
= _("missing ]");
3046 skip_whitespace (str
);
3051 inst
.instruction
|= WRITE_BACK
;
3055 else if (* str
== '=') /* ldr's "r,=label" syntax */
3056 /* We should never reach here, because <text> = <expression> is
3057 caught gas/read.c read_a_source_file() as a .set operation. */
3059 else /* PC +- 8 bit immediate offset. */
3061 if (my_get_expression (& inst
.reloc
.exp
, & str
))
3064 inst
.instruction
|= HWOFFSET_IMM
; /* The I bit. */
3065 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
3066 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
3067 inst
.reloc
.pc_rel
= 1;
3068 inst
.instruction
|= (REG_PC
<< 16);
3074 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
3080 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
3081 SMLAxy{cond} Rd,Rm,Rs,Rn
3082 SMLAWy{cond} Rd,Rm,Rs,Rn
3083 Error if any register is R15. */
3086 do_smla (char * str
)
3090 skip_whitespace (str
);
3092 if ((rd
= reg_required_here (& str
, 16)) == FAIL
3093 || skip_past_comma (& str
) == FAIL
3094 || (rm
= reg_required_here (& str
, 0)) == FAIL
3095 || skip_past_comma (& str
) == FAIL
3096 || (rs
= reg_required_here (& str
, 8)) == FAIL
3097 || skip_past_comma (& str
) == FAIL
3098 || (rn
= reg_required_here (& str
, 12)) == FAIL
)
3099 inst
.error
= BAD_ARGS
;
3101 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
|| rn
== REG_PC
)
3102 inst
.error
= BAD_PC
;
3108 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
3109 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
3110 Error if any register is R15.
3111 Warning if Rdlo == Rdhi. */
3114 do_smlal (char * str
)
3116 int rdlo
, rdhi
, rm
, rs
;
3118 skip_whitespace (str
);
3120 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
3121 || skip_past_comma (& str
) == FAIL
3122 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
3123 || skip_past_comma (& str
) == FAIL
3124 || (rm
= reg_required_here (& str
, 0)) == FAIL
3125 || skip_past_comma (& str
) == FAIL
3126 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
3128 inst
.error
= BAD_ARGS
;
3132 if (rdlo
== REG_PC
|| rdhi
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
3134 inst
.error
= BAD_PC
;
3139 as_tsktsk (_("rdhi and rdlo must be different"));
3144 /* ARM V5E (El Segundo) signed-multiply (argument parse)
3145 SMULxy{cond} Rd,Rm,Rs
3146 Error if any register is R15. */
3149 do_smul (char * str
)
3153 skip_whitespace (str
);
3155 if ((rd
= reg_required_here (& str
, 16)) == FAIL
3156 || skip_past_comma (& str
) == FAIL
3157 || (rm
= reg_required_here (& str
, 0)) == FAIL
3158 || skip_past_comma (& str
) == FAIL
3159 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
3160 inst
.error
= BAD_ARGS
;
3162 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
3163 inst
.error
= BAD_PC
;
3169 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
3170 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
3171 Error if any register is R15. */
3174 do_qadd (char * str
)
3178 skip_whitespace (str
);
3180 if ((rd
= reg_required_here (& str
, 12)) == FAIL
3181 || skip_past_comma (& str
) == FAIL
3182 || (rm
= reg_required_here (& str
, 0)) == FAIL
3183 || skip_past_comma (& str
) == FAIL
3184 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
3185 inst
.error
= BAD_ARGS
;
3187 else if (rd
== REG_PC
|| rm
== REG_PC
|| rn
== REG_PC
)
3188 inst
.error
= BAD_PC
;
3194 /* ARM V5E (el Segundo)
3195 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3196 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3198 These are equivalent to the XScale instructions MAR and MRA,
3199 respectively, when coproc == 0, opcode == 0, and CRm == 0.
3201 Result unpredicatable if Rd or Rn is R15. */
3204 do_co_reg2c (char * str
)
3208 skip_whitespace (str
);
3210 if (co_proc_number (& str
) == FAIL
)
3213 inst
.error
= BAD_ARGS
;
3217 if (skip_past_comma (& str
) == FAIL
3218 || cp_opc_expr (& str
, 4, 4) == FAIL
)
3221 inst
.error
= BAD_ARGS
;
3225 if (skip_past_comma (& str
) == FAIL
3226 || (rd
= reg_required_here (& str
, 12)) == FAIL
)
3229 inst
.error
= BAD_ARGS
;
3233 if (skip_past_comma (& str
) == FAIL
3234 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
3237 inst
.error
= BAD_ARGS
;
3241 /* Unpredictable result if rd or rn is R15. */
3242 if (rd
== REG_PC
|| rn
== REG_PC
)
3244 (_("Warning: instruction unpredictable when using r15"));
3246 if (skip_past_comma (& str
) == FAIL
3247 || cp_reg_required_here (& str
, 0) == FAIL
)
3250 inst
.error
= BAD_ARGS
;
3257 /* ARM V5 count-leading-zeroes instruction (argument parse)
3258 CLZ{<cond>} <Rd>, <Rm>
3259 Condition defaults to COND_ALWAYS.
3260 Error if Rd or Rm are R15. */
3267 skip_whitespace (str
);
3269 if (((rd
= reg_required_here (& str
, 12)) == FAIL
)
3270 || (skip_past_comma (& str
) == FAIL
)
3271 || ((rm
= reg_required_here (& str
, 0)) == FAIL
))
3272 inst
.error
= BAD_ARGS
;
3274 else if (rd
== REG_PC
|| rm
== REG_PC
)
3275 inst
.error
= BAD_PC
;
3281 /* ARM V5 (argument parse)
3282 LDC2{L} <coproc>, <CRd>, <addressing mode>
3283 STC2{L} <coproc>, <CRd>, <addressing mode>
3284 Instruction is not conditional, and has 0xf in the condition field.
3285 Otherwise, it's the same as LDC/STC. */
3288 do_lstc2 (char * str
)
3290 skip_whitespace (str
);
3292 if (co_proc_number (& str
) == FAIL
)
3295 inst
.error
= BAD_ARGS
;
3297 else if (skip_past_comma (& str
) == FAIL
3298 || cp_reg_required_here (& str
, 12) == FAIL
)
3301 inst
.error
= BAD_ARGS
;
3303 else if (skip_past_comma (& str
) == FAIL
3304 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
3307 inst
.error
= BAD_ARGS
;
3313 /* ARM V5 (argument parse)
3314 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
3315 Instruction is not conditional, and has 0xf in the condition field.
3316 Otherwise, it's the same as CDP. */
3319 do_cdp2 (char * str
)
3321 skip_whitespace (str
);
3323 if (co_proc_number (& str
) == FAIL
)
3326 inst
.error
= BAD_ARGS
;
3330 if (skip_past_comma (& str
) == FAIL
3331 || cp_opc_expr (& str
, 20,4) == FAIL
)
3334 inst
.error
= BAD_ARGS
;
3338 if (skip_past_comma (& str
) == FAIL
3339 || cp_reg_required_here (& str
, 12) == FAIL
)
3342 inst
.error
= BAD_ARGS
;
3346 if (skip_past_comma (& str
) == FAIL
3347 || cp_reg_required_here (& str
, 16) == FAIL
)
3350 inst
.error
= BAD_ARGS
;
3354 if (skip_past_comma (& str
) == FAIL
3355 || cp_reg_required_here (& str
, 0) == FAIL
)
3358 inst
.error
= BAD_ARGS
;
3362 if (skip_past_comma (& str
) == SUCCESS
)
3364 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
3367 inst
.error
= BAD_ARGS
;
3375 /* ARM V5 (argument parse)
3376 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3377 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3378 Instruction is not conditional, and has 0xf in the condition field.
3379 Otherwise, it's the same as MCR/MRC. */
3382 do_co_reg2 (char * str
)
3384 skip_whitespace (str
);
3386 if (co_proc_number (& str
) == FAIL
)
3389 inst
.error
= BAD_ARGS
;
3393 if (skip_past_comma (& str
) == FAIL
3394 || cp_opc_expr (& str
, 21, 3) == FAIL
)
3397 inst
.error
= BAD_ARGS
;
3401 if (skip_past_comma (& str
) == FAIL
3402 || reg_required_here (& str
, 12) == FAIL
)
3405 inst
.error
= BAD_ARGS
;
3409 if (skip_past_comma (& str
) == FAIL
3410 || cp_reg_required_here (& str
, 16) == FAIL
)
3413 inst
.error
= BAD_ARGS
;
3417 if (skip_past_comma (& str
) == FAIL
3418 || cp_reg_required_here (& str
, 0) == FAIL
)
3421 inst
.error
= BAD_ARGS
;
3425 if (skip_past_comma (& str
) == SUCCESS
)
3427 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
3430 inst
.error
= BAD_ARGS
;
3443 skip_whitespace (str
);
3445 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
3447 inst
.error
= BAD_ARGS
;
3451 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
3453 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
3458 /* ARM v5TEJ. Jump to Jazelle code. */
3465 skip_whitespace (str
);
3467 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
3469 inst
.error
= BAD_ARGS
;
3473 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
3475 as_tsktsk (_("use of r15 in bxj is not really useful"));
3480 /* ARM V6 umaal (argument parse). */
3483 do_umaal (char * str
)
3485 int rdlo
, rdhi
, rm
, rs
;
3487 skip_whitespace (str
);
3488 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
3489 || skip_past_comma (& str
) == FAIL
3490 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
3491 || skip_past_comma (& str
) == FAIL
3492 || (rm
= reg_required_here (& str
, 0)) == FAIL
3493 || skip_past_comma (& str
) == FAIL
3494 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
3496 inst
.error
= BAD_ARGS
;
3500 if (rdlo
== REG_PC
|| rdhi
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
3502 inst
.error
= BAD_PC
;
3509 /* ARM V6 strex (argument parse). */
3512 do_strex (char * str
)
3516 /* Parse Rd, Rm,. */
3517 skip_whitespace (str
);
3518 if ((rd
= reg_required_here (& str
, 12)) == FAIL
3519 || skip_past_comma (& str
) == FAIL
3520 || (rm
= reg_required_here (& str
, 0)) == FAIL
3521 || skip_past_comma (& str
) == FAIL
)
3523 inst
.error
= BAD_ARGS
;
3526 if (rd
== REG_PC
|| rm
== REG_PC
)
3528 inst
.error
= BAD_PC
;
3533 inst
.error
= _("Rd equal to Rm or Rn yields unpredictable results");
3537 /* Skip past '['. */
3538 if ((strlen (str
) >= 1)
3539 && strncmp (str
, "[", 1) == 0)
3542 skip_whitespace (str
);
3545 if ((rn
= reg_required_here (& str
, 16)) == FAIL
)
3547 inst
.error
= BAD_ARGS
;
3550 else if (rn
== REG_PC
)
3552 inst
.error
= BAD_PC
;
3557 inst
.error
= _("Rd equal to Rm or Rn yields unpredictable results");
3560 skip_whitespace (str
);
3562 /* Skip past ']'. */
3563 if ((strlen (str
) >= 1)
3564 && strncmp (str
, "]", 1) == 0)
3570 /* KIND indicates what kind of shifts are accepted. */
3573 decode_shift (char ** str
, int kind
)
3575 const struct asm_shift_name
* shift
;
3579 skip_whitespace (* str
);
3581 for (p
= * str
; ISALPHA (* p
); p
++)
3586 inst
.error
= _("shift expression expected");
3592 shift
= (const struct asm_shift_name
*) hash_find (arm_shift_hsh
, * str
);
3597 inst
.error
= _("shift expression expected");
3601 assert (shift
->properties
->index
== shift_properties
[shift
->properties
->index
].index
);
3603 if (kind
== SHIFT_LSL_OR_ASR_IMMEDIATE
3604 && shift
->properties
->index
!= SHIFT_LSL
3605 && shift
->properties
->index
!= SHIFT_ASR
)
3607 inst
.error
= _("'LSL' or 'ASR' required");
3610 else if (kind
== SHIFT_LSL_IMMEDIATE
3611 && shift
->properties
->index
!= SHIFT_LSL
)
3613 inst
.error
= _("'LSL' required");
3616 else if (kind
== SHIFT_ASR_IMMEDIATE
3617 && shift
->properties
->index
!= SHIFT_ASR
)
3619 inst
.error
= _("'ASR' required");
3623 if (shift
->properties
->index
== SHIFT_RRX
)
3626 inst
.instruction
|= shift
->properties
->bit_field
;
3630 skip_whitespace (p
);
3632 if (kind
== NO_SHIFT_RESTRICT
&& reg_required_here (& p
, 8) != FAIL
)
3634 inst
.instruction
|= shift
->properties
->bit_field
| SHIFT_BY_REG
;
3638 else if (! is_immediate_prefix (* p
))
3640 inst
.error
= (NO_SHIFT_RESTRICT
3641 ? _("shift requires register or #expression")
3642 : _("shift requires #expression"));
3650 if (my_get_expression (& inst
.reloc
.exp
, & p
))
3653 /* Validate some simple #expressions. */
3654 if (inst
.reloc
.exp
.X_op
== O_constant
)
3656 unsigned num
= inst
.reloc
.exp
.X_add_number
;
3658 /* Reject operations greater than 32. */
3660 /* Reject a shift of 0 unless the mode allows it. */
3661 || (num
== 0 && shift
->properties
->allows_0
== 0)
3662 /* Reject a shift of 32 unless the mode allows it. */
3663 || (num
== 32 && shift
->properties
->allows_32
== 0)
3666 /* As a special case we allow a shift of zero for
3667 modes that do not support it to be recoded as an
3668 logical shift left of zero (ie nothing). We warn
3669 about this though. */
3672 as_warn (_("shift of 0 ignored."));
3673 shift
= & shift_names
[0];
3674 assert (shift
->properties
->index
== SHIFT_LSL
);
3678 inst
.error
= _("invalid immediate shift");
3683 /* Shifts of 32 are encoded as 0, for those shifts that
3688 inst
.instruction
|= (num
<< 7) | shift
->properties
->bit_field
;
3692 inst
.reloc
.type
= BFD_RELOC_ARM_SHIFT_IMM
;
3693 inst
.reloc
.pc_rel
= 0;
3694 inst
.instruction
|= shift
->properties
->bit_field
;
3702 do_sat (char ** str
, int bias
)
3707 skip_whitespace (*str
);
3709 /* Parse <Rd>, field. */
3710 if ((rd
= reg_required_here (str
, 12)) == FAIL
3711 || skip_past_comma (str
) == FAIL
)
3713 inst
.error
= BAD_ARGS
;
3718 inst
.error
= BAD_PC
;
3722 /* Parse #<immed>, field. */
3723 if (is_immediate_prefix (**str
))
3727 inst
.error
= _("immediate expression expected");
3730 if (my_get_expression (&expr
, str
))
3732 inst
.error
= _("bad expression");
3735 if (expr
.X_op
!= O_constant
)
3737 inst
.error
= _("constant expression expected");
3740 if (expr
.X_add_number
+ bias
< 0
3741 || expr
.X_add_number
+ bias
> 31)
3743 inst
.error
= _("immediate value out of range");
3746 inst
.instruction
|= (expr
.X_add_number
+ bias
) << 16;
3747 if (skip_past_comma (str
) == FAIL
)
3749 inst
.error
= BAD_ARGS
;
3753 /* Parse <Rm> field. */
3754 if ((rm
= reg_required_here (str
, 0)) == FAIL
)
3756 inst
.error
= BAD_ARGS
;
3761 inst
.error
= BAD_PC
;
3765 if (skip_past_comma (str
) == SUCCESS
)
3766 decode_shift (str
, SHIFT_LSL_OR_ASR_IMMEDIATE
);
3769 /* ARM V6 ssat (argument parse). */
3772 do_ssat (char * str
)
3774 do_sat (&str
, /*bias=*/-1);
3778 /* ARM V6 usat (argument parse). */
3781 do_usat (char * str
)
3783 do_sat (&str
, /*bias=*/0);
3788 do_sat16 (char ** str
, int bias
)
3793 skip_whitespace (*str
);
3795 /* Parse the <Rd> field. */
3796 if ((rd
= reg_required_here (str
, 12)) == FAIL
3797 || skip_past_comma (str
) == FAIL
)
3799 inst
.error
= BAD_ARGS
;
3804 inst
.error
= BAD_PC
;
3808 /* Parse #<immed>, field. */
3809 if (is_immediate_prefix (**str
))
3813 inst
.error
= _("immediate expression expected");
3816 if (my_get_expression (&expr
, str
))
3818 inst
.error
= _("bad expression");
3821 if (expr
.X_op
!= O_constant
)
3823 inst
.error
= _("constant expression expected");
3826 if (expr
.X_add_number
+ bias
< 0
3827 || expr
.X_add_number
+ bias
> 15)
3829 inst
.error
= _("immediate value out of range");
3832 inst
.instruction
|= (expr
.X_add_number
+ bias
) << 16;
3833 if (skip_past_comma (str
) == FAIL
)
3835 inst
.error
= BAD_ARGS
;
3839 /* Parse <Rm> field. */
3840 if ((rm
= reg_required_here (str
, 0)) == FAIL
)
3842 inst
.error
= BAD_ARGS
;
3847 inst
.error
= BAD_PC
;
3852 /* ARM V6 ssat16 (argument parse). */
3855 do_ssat16 (char * str
)
3857 do_sat16 (&str
, /*bias=*/-1);
3862 do_usat16 (char * str
)
3864 do_sat16 (&str
, /*bias=*/0);
3869 do_cps_mode (char ** str
)
3873 skip_whitespace (*str
);
3875 if (! is_immediate_prefix (**str
))
3877 inst
.error
= _("immediate expression expected");
3881 (*str
)++; /* Strip off the immediate signifier. */
3882 if (my_get_expression (&expr
, str
))
3884 inst
.error
= _("bad expression");
3888 if (expr
.X_op
!= O_constant
)
3890 inst
.error
= _("constant expression expected");
3894 /* The mode is a 5 bit field. Valid values are 0-31. */
3895 if (((unsigned) expr
.X_add_number
) > 31
3896 || (inst
.reloc
.exp
.X_add_number
) < 0)
3898 inst
.error
= _("invalid constant");
3902 inst
.instruction
|= expr
.X_add_number
;
3905 /* ARM V6 srs (argument parse). */
3911 skip_whitespace (str
);
3912 exclam
= strchr (str
, '!');
3920 inst
.instruction
|= WRITE_BACK
;
3926 /* ARM V6 SMMUL (argument parse). */
3929 do_smmul (char * str
)
3933 skip_whitespace (str
);
3934 if ((rd
= reg_required_here (&str
, 16)) == FAIL
3935 || skip_past_comma (&str
) == FAIL
3936 || (rm
= reg_required_here (&str
, 0)) == FAIL
3937 || skip_past_comma (&str
) == FAIL
3938 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
3940 inst
.error
= BAD_ARGS
;
3948 inst
.error
= BAD_PC
;
3955 /* ARM V6 SMLALD (argument parse). */
3958 do_smlald (char * str
)
3960 int rdlo
, rdhi
, rm
, rs
;
3962 skip_whitespace (str
);
3963 if ((rdlo
= reg_required_here (&str
, 12)) == FAIL
3964 || skip_past_comma (&str
) == FAIL
3965 || (rdhi
= reg_required_here (&str
, 16)) == FAIL
3966 || skip_past_comma (&str
) == FAIL
3967 || (rm
= reg_required_here (&str
, 0)) == FAIL
3968 || skip_past_comma (&str
) == FAIL
3969 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
3971 inst
.error
= BAD_ARGS
;
3980 inst
.error
= BAD_PC
;
3987 /* ARM V6 SMLAD (argument parse). Signed multiply accumulate dual.
3988 smlad{x}{<cond>} Rd, Rm, Rs, Rn */
3991 do_smlad (char * str
)
3995 skip_whitespace (str
);
3996 if ((rd
= reg_required_here (&str
, 16)) == FAIL
3997 || skip_past_comma (&str
) == FAIL
3998 || (rm
= reg_required_here (&str
, 0)) == FAIL
3999 || skip_past_comma (&str
) == FAIL
4000 || (rs
= reg_required_here (&str
, 8)) == FAIL
4001 || skip_past_comma (&str
) == FAIL
4002 || (rn
= reg_required_here (&str
, 12)) == FAIL
)
4004 inst
.error
= BAD_ARGS
;
4013 inst
.error
= BAD_PC
;
4020 /* Returns true if the endian-specifier indicates big-endianness. */
4023 do_endian_specifier (char * str
)
4027 skip_whitespace (str
);
4028 if (strlen (str
) < 2)
4029 inst
.error
= _("missing endian specifier");
4030 else if (strncasecmp (str
, "BE", 2) == 0)
4035 else if (strncasecmp (str
, "LE", 2) == 0)
4038 inst
.error
= _("valid endian specifiers are be or le");
4045 /* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
4046 preserving the other bits.
4048 setend <endian_specifier>, where <endian_specifier> is either
4052 do_setend (char * str
)
4054 if (do_endian_specifier (str
))
4055 inst
.instruction
|= 0x200;
4060 SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
4061 Condition defaults to COND_ALWAYS.
4062 Error if any register uses R15. */
4065 do_sxth (char * str
)
4069 int rotation_clear_mask
= 0xfffff3ff;
4070 int rotation_eight_mask
= 0x00000400;
4071 int rotation_sixteen_mask
= 0x00000800;
4072 int rotation_twenty_four_mask
= 0x00000c00;
4074 skip_whitespace (str
);
4075 if ((rd
= reg_required_here (&str
, 12)) == FAIL
4076 || skip_past_comma (&str
) == FAIL
4077 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4079 inst
.error
= BAD_ARGS
;
4083 else if (rd
== REG_PC
|| rm
== REG_PC
)
4085 inst
.error
= BAD_PC
;
4089 /* Zero out the rotation field. */
4090 inst
.instruction
&= rotation_clear_mask
;
4092 /* Check for lack of optional rotation field. */
4093 if (skip_past_comma (&str
) == FAIL
)
4099 /* Move past 'ROR'. */
4100 skip_whitespace (str
);
4101 if (strncasecmp (str
, "ROR", 3) == 0)
4105 inst
.error
= _("missing rotation field after comma");
4109 /* Get the immediate constant. */
4110 skip_whitespace (str
);
4111 if (is_immediate_prefix (* str
))
4115 inst
.error
= _("immediate expression expected");
4119 if (my_get_expression (&expr
, &str
))
4121 inst
.error
= _("bad expression");
4125 if (expr
.X_op
!= O_constant
)
4127 inst
.error
= _("constant expression expected");
4131 switch (expr
.X_add_number
)
4134 /* Rotation field has already been zeroed. */
4137 inst
.instruction
|= rotation_eight_mask
;
4141 inst
.instruction
|= rotation_sixteen_mask
;
4145 inst
.instruction
|= rotation_twenty_four_mask
;
4149 inst
.error
= _("rotation can be 8, 16, 24 or 0 when field is ommited");
4156 /* ARM V6 SXTAH extracts a 16-bit value from a register, sign
4157 extends it to 32-bits, and adds the result to a value in another
4158 register. You can specify a rotation by 0, 8, 16, or 24 bits
4159 before extracting the 16-bit value.
4160 SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
4161 Condition defaults to COND_ALWAYS.
4162 Error if any register uses R15. */
4165 do_sxtah (char * str
)
4169 int rotation_clear_mask
= 0xfffff3ff;
4170 int rotation_eight_mask
= 0x00000400;
4171 int rotation_sixteen_mask
= 0x00000800;
4172 int rotation_twenty_four_mask
= 0x00000c00;
4174 skip_whitespace (str
);
4175 if ((rd
= reg_required_here (&str
, 12)) == FAIL
4176 || skip_past_comma (&str
) == FAIL
4177 || (rn
= reg_required_here (&str
, 16)) == FAIL
4178 || skip_past_comma (&str
) == FAIL
4179 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4181 inst
.error
= BAD_ARGS
;
4185 else if (rd
== REG_PC
|| rn
== REG_PC
|| rm
== REG_PC
)
4187 inst
.error
= BAD_PC
;
4191 /* Zero out the rotation field. */
4192 inst
.instruction
&= rotation_clear_mask
;
4194 /* Check for lack of optional rotation field. */
4195 if (skip_past_comma (&str
) == FAIL
)
4201 /* Move past 'ROR'. */
4202 skip_whitespace (str
);
4203 if (strncasecmp (str
, "ROR", 3) == 0)
4207 inst
.error
= _("missing rotation field after comma");
4211 /* Get the immediate constant. */
4212 skip_whitespace (str
);
4213 if (is_immediate_prefix (* str
))
4217 inst
.error
= _("immediate expression expected");
4221 if (my_get_expression (&expr
, &str
))
4223 inst
.error
= _("bad expression");
4227 if (expr
.X_op
!= O_constant
)
4229 inst
.error
= _("constant expression expected");
4233 switch (expr
.X_add_number
)
4236 /* Rotation field has already been zeroed. */
4240 inst
.instruction
|= rotation_eight_mask
;
4244 inst
.instruction
|= rotation_sixteen_mask
;
4248 inst
.instruction
|= rotation_twenty_four_mask
;
4252 inst
.error
= _("rotation can be 8, 16, 24 or 0 when field is ommited");
4260 /* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
4261 word at the specified address and the following word
4263 Unconditionally executed.
4264 Error if Rn is R15. */
4271 skip_whitespace (str
);
4273 if ((rn
= reg_required_here (&str
, 16)) == FAIL
)
4278 inst
.error
= BAD_PC
;
4282 skip_whitespace (str
);
4286 inst
.instruction
|= WRITE_BACK
;
4292 /* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
4293 register (argument parse).
4295 Condition defaults to COND_ALWAYS.
4296 Error if Rd or Rm are R15. */
4303 skip_whitespace (str
);
4305 if ((rd
= reg_required_here (&str
, 12)) == FAIL
4306 || skip_past_comma (&str
) == FAIL
4307 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4308 inst
.error
= BAD_ARGS
;
4310 else if (rd
== REG_PC
|| rm
== REG_PC
)
4311 inst
.error
= BAD_PC
;
4317 /* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
4318 QADD16{<cond>} <Rd>, <Rn>, <Rm>
4319 Condition defaults to COND_ALWAYS.
4320 Error if Rd, Rn or Rm are R15. */
4323 do_qadd16 (char * str
)
4327 skip_whitespace (str
);
4329 if ((rd
= reg_required_here (&str
, 12)) == FAIL
4330 || skip_past_comma (&str
) == FAIL
4331 || (rn
= reg_required_here (&str
, 16)) == FAIL
4332 || skip_past_comma (&str
) == FAIL
4333 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4334 inst
.error
= BAD_ARGS
;
4336 else if (rd
== REG_PC
|| rm
== REG_PC
|| rn
== REG_PC
)
4337 inst
.error
= BAD_PC
;
4344 do_pkh_core (char * str
, int shift
)
4348 skip_whitespace (str
);
4349 if (((rd
= reg_required_here (&str
, 12)) == FAIL
)
4350 || (skip_past_comma (&str
) == FAIL
)
4351 || ((rn
= reg_required_here (&str
, 16)) == FAIL
)
4352 || (skip_past_comma (&str
) == FAIL
)
4353 || ((rm
= reg_required_here (&str
, 0)) == FAIL
))
4355 inst
.error
= BAD_ARGS
;
4359 else if (rd
== REG_PC
|| rn
== REG_PC
|| rm
== REG_PC
)
4361 inst
.error
= BAD_PC
;
4365 /* Check for optional shift immediate constant. */
4366 if (skip_past_comma (&str
) == FAIL
)
4368 if (shift
== SHIFT_ASR_IMMEDIATE
)
4370 /* If the shift specifier is ommited, turn the instruction
4371 into pkhbt rd, rm, rn. First, switch the instruction
4372 code, and clear the rn and rm fields. */
4373 inst
.instruction
&= 0xfff0f010;
4374 /* Now, re-encode the registers. */
4375 inst
.instruction
|= (rm
<< 16) | rn
;
4380 decode_shift (&str
, shift
);
4383 /* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
4384 PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
4385 Condition defaults to COND_ALWAYS.
4386 Error if Rd, Rn or Rm are R15. */
4389 do_pkhbt (char * str
)
4391 do_pkh_core (str
, SHIFT_LSL_IMMEDIATE
);
4394 /* ARM V6 PKHTB (Argument Parse). */
4397 do_pkhtb (char * str
)
4399 do_pkh_core (str
, SHIFT_ASR_IMMEDIATE
);
4402 /* ARM V6 Load Register Exclusive instruction (argument parse).
4403 LDREX{,B,D,H}{<cond>} <Rd, [<Rn>]
4404 Condition defaults to COND_ALWAYS.
4405 Error if Rd or Rn are R15.
4406 See ARMARMv6 A4.1.27: LDREX. */
4409 do_ldrex (char * str
)
4413 skip_whitespace (str
);
4416 if (((rd
= reg_required_here (&str
, 12)) == FAIL
)
4417 || (skip_past_comma (&str
) == FAIL
))
4419 inst
.error
= BAD_ARGS
;
4422 else if (rd
== REG_PC
)
4424 inst
.error
= BAD_PC
;
4427 skip_whitespace (str
);
4429 /* Skip past '['. */
4430 if ((strlen (str
) >= 1)
4431 &&strncmp (str
, "[", 1) == 0)
4433 skip_whitespace (str
);
4436 if ((rn
= reg_required_here (&str
, 16)) == FAIL
)
4438 inst
.error
= BAD_ARGS
;
4441 else if (rn
== REG_PC
)
4443 inst
.error
= BAD_PC
;
4446 skip_whitespace (str
);
4448 /* Skip past ']'. */
4449 if ((strlen (str
) >= 1)
4450 && strncmp (str
, "]", 1) == 0)
4456 /* ARM V6 change processor state instruction (argument parse)
4457 CPS, CPSIE, CSPID . */
4467 do_cps_flags (char ** str
, int thumb_p
)
4472 unsigned long arm_value
;
4473 unsigned long thumb_value
;
4475 static struct cps_flag flag_table
[] =
4484 skip_whitespace (*str
);
4486 /* Get the a, f and i flags. */
4487 while (**str
&& **str
!= ',')
4490 struct cps_flag
*q
= flag_table
+ sizeof (flag_table
)/sizeof (*p
);
4492 for (p
= flag_table
; p
< q
; ++p
)
4493 if (strncasecmp (*str
, &p
->character
, 1) == 0)
4495 inst
.instruction
|= (thumb_p
? p
->thumb_value
: p
->arm_value
);
4501 inst
.error
= _("unrecognized flag");
4508 inst
.error
= _("no 'a', 'i', or 'f' flags for 'cps'");
4512 do_cpsi (char * str
)
4514 do_cps_flags (&str
, /*thumb_p=*/0);
4516 if (skip_past_comma (&str
) == SUCCESS
)
4518 skip_whitespace (str
);
4524 /* THUMB V5 breakpoint instruction (argument parse)
4528 do_t_bkpt (char * str
)
4531 unsigned long number
;
4533 skip_whitespace (str
);
4535 /* Allow optional leading '#'. */
4536 if (is_immediate_prefix (*str
))
4539 memset (& expr
, '\0', sizeof (expr
));
4540 if (my_get_expression (& expr
, & str
)
4541 || (expr
.X_op
!= O_constant
4542 /* As a convenience we allow 'bkpt' without an operand. */
4543 && expr
.X_op
!= O_absent
))
4545 inst
.error
= _("bad expression");
4549 number
= expr
.X_add_number
;
4551 /* Check it fits an 8 bit unsigned. */
4552 if (number
!= (number
& 0xff))
4554 inst
.error
= _("immediate value out of range");
4558 inst
.instruction
|= number
;
4563 static bfd_reloc_code_real_type
4564 arm_parse_reloc (void)
4573 bfd_reloc_code_real_type reloc
;
4577 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
4578 MAP ("(got)", BFD_RELOC_ARM_GOT32
),
4579 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF
),
4580 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
4581 branch instructions generated by GCC for PLT relocs. */
4582 MAP ("(plt)", BFD_RELOC_ARM_PLT32
),
4583 MAP ("(target1)", BFD_RELOC_ARM_TARGET1
),
4584 MAP ("(sbrel)", BFD_RELOC_ARM_SBREL32
),
4585 MAP ("(target2)", BFD_RELOC_ARM_TARGET2
),
4586 { NULL
, 0, BFD_RELOC_UNUSED
}
4590 for (i
= 0, ip
= input_line_pointer
;
4591 i
< sizeof (id
) && (ISALNUM (*ip
) || ISPUNCT (*ip
));
4593 id
[i
] = TOLOWER (*ip
);
4595 for (i
= 0; reloc_map
[i
].str
; i
++)
4596 if (strncmp (id
, reloc_map
[i
].str
, reloc_map
[i
].len
) == 0)
4599 input_line_pointer
+= reloc_map
[i
].len
;
4601 return reloc_map
[i
].reloc
;
4604 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
4605 Expects inst.instruction is set for BLX(1).
4606 Note: this is cloned from do_branch, and the reloc changed to be a
4607 new one that can cope with setting one extra bit (the H bit). */
4610 do_branch25 (char * str
)
4612 if (my_get_expression (& inst
.reloc
.exp
, & str
))
4619 /* ScottB: February 5, 1998 */
4620 /* Check to see of PLT32 reloc required for the instruction. */
4622 /* arm_parse_reloc() works on input_line_pointer.
4623 We actually want to parse the operands to the branch instruction
4624 passed in 'str'. Save the input pointer and restore it later. */
4625 save_in
= input_line_pointer
;
4626 input_line_pointer
= str
;
4628 if (inst
.reloc
.exp
.X_op
== O_symbol
4630 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
4632 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
4633 inst
.reloc
.pc_rel
= 0;
4634 /* Modify str to point to after parsed operands, otherwise
4635 end_of_line() will complain about the (PLT) left in str. */
4636 str
= input_line_pointer
;
4640 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
4641 inst
.reloc
.pc_rel
= 1;
4644 input_line_pointer
= save_in
;
4647 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
4648 inst
.reloc
.pc_rel
= 1;
4649 #endif /* OBJ_ELF */
4654 /* ARM V5 branch-link-exchange instruction (argument parse)
4655 BLX <target_addr> ie BLX(1)
4656 BLX{<condition>} <Rm> ie BLX(2)
4657 Unfortunately, there are two different opcodes for this mnemonic.
4658 So, the insns[].value is not used, and the code here zaps values
4659 into inst.instruction.
4660 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
4668 skip_whitespace (mystr
);
4669 rm
= reg_required_here (& mystr
, 0);
4671 /* The above may set inst.error. Ignore his opinion. */
4676 /* Arg is a register.
4677 Use the condition code our caller put in inst.instruction.
4678 Pass ourselves off as a BX with a funny opcode. */
4679 inst
.instruction
|= 0x012fff30;
4684 /* This must be is BLX <target address>, no condition allowed. */
4685 if (inst
.instruction
!= COND_ALWAYS
)
4687 inst
.error
= BAD_COND
;
4691 inst
.instruction
= 0xfafffffe;
4693 /* Process like a B/BL, but with a different reloc.
4694 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
4699 /* ARM V5 Thumb BLX (argument parse)
4700 BLX <target_addr> which is BLX(1)
4701 BLX <Rm> which is BLX(2)
4702 Unfortunately, there are two different opcodes for this mnemonic.
4703 So, the tinsns[].value is not used, and the code here zaps values
4704 into inst.instruction. */
4707 do_t_blx (char * str
)
4712 skip_whitespace (mystr
);
4713 inst
.instruction
= 0x4780;
4715 /* Note that this call is to the ARM register recognizer. BLX(2)
4716 uses the ARM register space, not the Thumb one, so a call to
4717 thumb_reg() would be wrong. */
4718 rm
= reg_required_here (& mystr
, 3);
4723 /* It's BLX(2). The .instruction was zapped with rm & is final. */
4728 /* No ARM register. This must be BLX(1). Change the .instruction. */
4729 inst
.instruction
= 0xf7ffeffe;
4732 if (my_get_expression (& inst
.reloc
.exp
, & mystr
))
4735 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BLX
;
4736 inst
.reloc
.pc_rel
= 1;
4739 end_of_line (mystr
);
4742 /* ARM V5 breakpoint instruction (argument parse)
4743 BKPT <16 bit unsigned immediate>
4744 Instruction is not conditional.
4745 The bit pattern given in insns[] has the COND_ALWAYS condition,
4746 and it is an error if the caller tried to override that. */
4749 do_bkpt (char * str
)
4752 unsigned long number
;
4754 skip_whitespace (str
);
4756 /* Allow optional leading '#'. */
4757 if (is_immediate_prefix (* str
))
4760 memset (& expr
, '\0', sizeof (expr
));
4762 if (my_get_expression (& expr
, & str
)
4763 || (expr
.X_op
!= O_constant
4764 /* As a convenience we allow 'bkpt' without an operand. */
4765 && expr
.X_op
!= O_absent
))
4767 inst
.error
= _("bad expression");
4771 number
= expr
.X_add_number
;
4773 /* Check it fits a 16 bit unsigned. */
4774 if (number
!= (number
& 0xffff))
4776 inst
.error
= _("immediate value out of range");
4780 /* Top 12 of 16 bits to bits 19:8. */
4781 inst
.instruction
|= (number
& 0xfff0) << 4;
4783 /* Bottom 4 of 16 bits to bits 3:0. */
4784 inst
.instruction
|= number
& 0xf;
4789 /* THUMB CPS instruction (argument parse). */
4792 do_t_cps (char * str
)
4794 do_cps_flags (&str
, /*thumb_p=*/1);
4798 /* Parse and validate that a register is of the right form, this saves
4799 repeated checking of this information in many similar cases.
4800 Unlike the 32-bit case we do not insert the register into the opcode
4801 here, since the position is often unknown until the full instruction
4805 thumb_reg (char ** strp
, int hi_lo
)
4809 if ((reg
= reg_required_here (strp
, -1)) == FAIL
)
4817 inst
.error
= _("lo register required");
4825 inst
.error
= _("hi register required");
4838 thumb_mov_compare (char * str
, int move
)
4842 skip_whitespace (str
);
4844 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
4845 || skip_past_comma (&str
) == FAIL
)
4848 inst
.error
= BAD_ARGS
;
4852 if (move
!= THUMB_CPY
&& is_immediate_prefix (*str
))
4855 if (my_get_expression (&inst
.reloc
.exp
, &str
))
4858 else if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
4863 if (move
!= THUMB_CPY
&& Rs
< 8 && Rd
< 8)
4865 if (move
== THUMB_MOVE
)
4866 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
4867 since a MOV instruction produces unpredictable results. */
4868 inst
.instruction
= T_OPCODE_ADD_I3
;
4870 inst
.instruction
= T_OPCODE_CMP_LR
;
4871 inst
.instruction
|= Rd
| (Rs
<< 3);
4875 if (move
== THUMB_MOVE
)
4876 inst
.instruction
= T_OPCODE_MOV_HR
;
4877 else if (move
!= THUMB_CPY
)
4878 inst
.instruction
= T_OPCODE_CMP_HR
;
4881 inst
.instruction
|= THUMB_H1
;
4884 inst
.instruction
|= THUMB_H2
;
4886 inst
.instruction
|= (Rd
& 7) | ((Rs
& 7) << 3);
4893 inst
.error
= _("only lo regs allowed with immediate");
4897 if (move
== THUMB_MOVE
)
4898 inst
.instruction
= T_OPCODE_MOV_I8
;
4900 inst
.instruction
= T_OPCODE_CMP_I8
;
4902 inst
.instruction
|= Rd
<< 8;
4904 if (inst
.reloc
.exp
.X_op
!= O_constant
)
4905 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_IMM
;
4908 unsigned value
= inst
.reloc
.exp
.X_add_number
;
4912 inst
.error
= _("invalid immediate");
4916 inst
.instruction
|= value
;
4923 /* THUMB CPY instruction (argument parse). */
4926 do_t_cpy (char * str
)
4928 thumb_mov_compare (str
, THUMB_CPY
);
4931 /* THUMB SETEND instruction (argument parse). */
4934 do_t_setend (char * str
)
4936 if (do_endian_specifier (str
))
4937 inst
.instruction
|= 0x8;
4940 /* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
4942 static unsigned long
4943 check_iwmmxt_insn (char * str
,
4944 enum iwmmxt_insn_type insn_type
,
4948 const char * inst_error
;
4950 unsigned long number
;
4952 inst_error
= inst
.error
;
4954 inst
.error
= BAD_ARGS
;
4955 skip_whitespace (str
);
4960 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
4965 if ((wreg_required_here (&str
, 0, IWMMXT_REG_WR
)) == FAIL
)
4970 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
4971 || skip_past_comma (&str
) == FAIL
4972 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
))
4977 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
4978 || skip_past_comma (&str
) == FAIL
4979 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4980 || skip_past_comma (&str
) == FAIL
4981 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
))
4986 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
4987 || skip_past_comma (&str
) == FAIL
4988 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4989 || skip_past_comma (&str
) == FAIL
4990 || wreg_required_here (&str
, 0, IWMMXT_REG_WCG
) == FAIL
))
4995 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4996 || skip_past_comma (&str
) == FAIL
4997 || reg_required_here (&str
, 12) == FAIL
))
5002 if ((reg_required_here (&str
, 12) == FAIL
5003 || skip_past_comma (&str
) == FAIL
5004 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
))
5009 if ((wreg_required_here (&str
, 5, IWMMXT_REG_WR
) == FAIL
5010 || skip_past_comma (&str
) == FAIL
5011 || reg_required_here (&str
, 0) == FAIL
5012 || skip_past_comma (&str
) == FAIL
5013 || reg_required_here (&str
, 12) == FAIL
))
5018 if ((wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
5019 || skip_past_comma (&str
) == FAIL
5020 || reg_required_here (&str
, 12) == FAIL
5021 || skip_past_comma (&str
) == FAIL
5022 || reg_required_here (&str
, 16) == FAIL
))
5027 if ((reg_required_here (&str
, 12) == FAIL
5028 || skip_past_comma (&str
) == FAIL
5029 || reg_required_here (&str
, 16) == FAIL
5030 || skip_past_comma (&str
) == FAIL
5031 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
))
5036 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WC
) == FAIL
5037 || skip_past_comma (&str
) == FAIL
5038 || reg_required_here (&str
, 12) == FAIL
))
5043 if ((reg_required_here (&str
, 12) == FAIL
5044 || skip_past_comma (&str
) == FAIL
5045 || wreg_required_here (&str
, 16, IWMMXT_REG_WC
) == FAIL
))
5050 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5051 || skip_past_comma (&str
) == FAIL
5052 || reg_required_here (&str
, 12) == FAIL
5053 || skip_past_comma (&str
) == FAIL
))
5058 if ((reg_required_here (&str
, 12) == FAIL
5059 || skip_past_comma (&str
) == FAIL
))
5064 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
5065 || skip_past_comma (&str
) == FAIL
5066 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5067 || skip_past_comma (&str
) == FAIL
5068 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
5069 || skip_past_comma (&str
) == FAIL
))
5074 if ((reg_required_here (&str
, 12) == FAIL
5075 || skip_past_comma (&str
) == FAIL
5076 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5077 || skip_past_comma (&str
) == FAIL
))
5082 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
5083 || skip_past_comma (&str
) == FAIL
5084 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5085 || skip_past_comma (&str
) == FAIL
))
5090 if (immediate_size
== 0)
5093 inst
.error
= inst_error
;
5098 skip_whitespace (str
);
5100 /* Allow optional leading '#'. */
5101 if (is_immediate_prefix (* str
))
5104 memset (& expr
, '\0', sizeof (expr
));
5106 if (my_get_expression (& expr
, & str
) || (expr
.X_op
!= O_constant
))
5108 inst
.error
= _("bad or missing expression");
5112 number
= expr
.X_add_number
;
5114 if (number
!= (number
& immediate_size
))
5116 inst
.error
= _("immediate value out of range");
5120 inst
.error
= inst_error
;
5126 do_iwmmxt_byte_addr (char * str
)
5128 int op
= (inst
.instruction
& 0x300) >> 8;
5131 inst
.instruction
&= ~0x300;
5132 inst
.instruction
|= (op
& 1) << 22 | (op
& 2) << 7;
5134 skip_whitespace (str
);
5136 if ((reg
= wreg_required_here (&str
, 12, IWMMXT_REG_WR_OR_WC
)) == FAIL
5137 || skip_past_comma (& str
) == FAIL
5138 || cp_byte_address_required_here (&str
) == FAIL
)
5141 inst
.error
= BAD_ARGS
;
5146 if (wc_register (reg
))
5148 as_bad (_("non-word size not supported with control register"));
5149 inst
.instruction
|= 0xf0000100;
5150 inst
.instruction
&= ~0x00400000;
5155 do_iwmmxt_tandc (char * str
)
5159 reg
= check_iwmmxt_insn (str
, check_rd
, 0);
5161 if (reg
!= REG_PC
&& !inst
.error
)
5162 inst
.error
= _("only r15 allowed here");
5166 do_iwmmxt_tbcst (char * str
)
5168 check_iwmmxt_insn (str
, check_tbcst
, 0);
5172 do_iwmmxt_textrc (char * str
)
5174 unsigned long number
;
5176 if ((number
= check_iwmmxt_insn (str
, check_textrc
, 7)) == (unsigned long) FAIL
)
5179 inst
.instruction
|= number
& 0x7;
5183 do_iwmmxt_textrm (char * str
)
5185 unsigned long number
;
5187 if ((number
= check_iwmmxt_insn (str
, check_textrm
, 7)) == (unsigned long) FAIL
)
5190 inst
.instruction
|= number
& 0x7;
5194 do_iwmmxt_tinsr (char * str
)
5196 unsigned long number
;
5198 if ((number
= check_iwmmxt_insn (str
, check_tinsr
, 7)) == (unsigned long) FAIL
)
5201 inst
.instruction
|= number
& 0x7;
5205 do_iwmmxt_tmcr (char * str
)
5207 check_iwmmxt_insn (str
, check_tmcr
, 0);
5211 do_iwmmxt_tmcrr (char * str
)
5213 check_iwmmxt_insn (str
, check_tmcrr
, 0);
5217 do_iwmmxt_tmia (char * str
)
5219 check_iwmmxt_insn (str
, check_tmia
, 0);
5223 do_iwmmxt_tmovmsk (char * str
)
5225 check_iwmmxt_insn (str
, check_tmovmsk
, 0);
5229 do_iwmmxt_tmrc (char * str
)
5231 check_iwmmxt_insn (str
, check_tmrc
, 0);
5235 do_iwmmxt_tmrrc (char * str
)
5237 check_iwmmxt_insn (str
, check_tmrrc
, 0);
5241 do_iwmmxt_torc (char * str
)
5243 check_iwmmxt_insn (str
, check_rd
, 0);
5247 do_iwmmxt_waligni (char * str
)
5249 unsigned long number
;
5251 if ((number
= check_iwmmxt_insn (str
, check_waligni
, 7)) == (unsigned long) FAIL
)
5254 inst
.instruction
|= ((number
& 0x7) << 20);
5258 do_iwmmxt_wmov (char * str
)
5260 if (check_iwmmxt_insn (str
, check_wrwr
, 0) == (unsigned long) FAIL
)
5263 inst
.instruction
|= ((inst
.instruction
>> 16) & 0xf);
5267 do_iwmmxt_word_addr (char * str
)
5269 int op
= (inst
.instruction
& 0x300) >> 8;
5272 inst
.instruction
&= ~0x300;
5273 inst
.instruction
|= (op
& 1) << 22 | (op
& 2) << 7;
5275 skip_whitespace (str
);
5277 if ((reg
= wreg_required_here (&str
, 12, IWMMXT_REG_WR_OR_WC
)) == FAIL
5278 || skip_past_comma (& str
) == FAIL
5279 || cp_address_required_here (& str
, CP_WB_OK
) == FAIL
)
5282 inst
.error
= BAD_ARGS
;
5287 if (wc_register (reg
))
5289 if ((inst
.instruction
& COND_MASK
) != COND_ALWAYS
)
5290 as_bad (_("conditional execution not supported with control register"));
5292 as_bad (_("non-word size not supported with control register"));
5293 inst
.instruction
|= 0xf0000100;
5294 inst
.instruction
&= ~0x00400000;
5299 do_iwmmxt_wrwr (char * str
)
5301 check_iwmmxt_insn (str
, check_wrwr
, 0);
5305 do_iwmmxt_wrwrwcg (char * str
)
5307 check_iwmmxt_insn (str
, check_wrwrwcg
, 0);
5311 do_iwmmxt_wrwrwr (char * str
)
5313 check_iwmmxt_insn (str
, check_wrwrwr
, 0);
5317 do_iwmmxt_wshufh (char * str
)
5319 unsigned long number
;
5321 if ((number
= check_iwmmxt_insn (str
, check_wshufh
, 0xff)) == (unsigned long) FAIL
)
5324 inst
.instruction
|= ((number
& 0xf0) << 16) | (number
& 0xf);
5328 do_iwmmxt_wzero (char * str
)
5330 if (check_iwmmxt_insn (str
, check_wr
, 0) == (unsigned long) FAIL
)
5333 inst
.instruction
|= ((inst
.instruction
& 0xf) << 12) | ((inst
.instruction
& 0xf) << 16);
5336 /* Xscale multiply-accumulate (argument parse)
5339 MIAxycc acc0,Rm,Rs. */
5342 do_xsc_mia (char * str
)
5347 if (accum0_required_here (& str
) == FAIL
)
5348 inst
.error
= ERR_NO_ACCUM
;
5350 else if (skip_past_comma (& str
) == FAIL
5351 || (rm
= reg_required_here (& str
, 0)) == FAIL
)
5352 inst
.error
= BAD_ARGS
;
5354 else if (skip_past_comma (& str
) == FAIL
5355 || (rs
= reg_required_here (& str
, 12)) == FAIL
)
5356 inst
.error
= BAD_ARGS
;
5358 /* inst.instruction has now been zapped with both rm and rs. */
5359 else if (rm
== REG_PC
|| rs
== REG_PC
)
5360 inst
.error
= BAD_PC
; /* Undefined result if rm or rs is R15. */
5366 /* Xscale move-accumulator-register (argument parse)
5368 MARcc acc0,RdLo,RdHi. */
5371 do_xsc_mar (char * str
)
5375 if (accum0_required_here (& str
) == FAIL
)
5376 inst
.error
= ERR_NO_ACCUM
;
5378 else if (skip_past_comma (& str
) == FAIL
5379 || (rdlo
= reg_required_here (& str
, 12)) == FAIL
)
5380 inst
.error
= BAD_ARGS
;
5382 else if (skip_past_comma (& str
) == FAIL
5383 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
5384 inst
.error
= BAD_ARGS
;
5386 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5387 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
5388 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
5394 /* Xscale move-register-accumulator (argument parse)
5396 MRAcc RdLo,RdHi,acc0. */
5399 do_xsc_mra (char * str
)
5404 skip_whitespace (str
);
5406 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
)
5407 inst
.error
= BAD_ARGS
;
5409 else if (skip_past_comma (& str
) == FAIL
5410 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
5411 inst
.error
= BAD_ARGS
;
5413 else if (skip_past_comma (& str
) == FAIL
5414 || accum0_required_here (& str
) == FAIL
)
5415 inst
.error
= ERR_NO_ACCUM
;
5417 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5418 else if (rdlo
== rdhi
)
5419 inst
.error
= BAD_ARGS
; /* Undefined result if 2 writes to same reg. */
5421 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
5422 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
5428 ldst_extend (char ** str
)
5437 if (my_get_expression (& inst
.reloc
.exp
, str
))
5440 if (inst
.reloc
.exp
.X_op
== O_constant
)
5442 int value
= inst
.reloc
.exp
.X_add_number
;
5444 if (value
< -4095 || value
> 4095)
5446 inst
.error
= _("address offset too large");
5456 inst
.instruction
|= add
| value
;
5460 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
5461 inst
.reloc
.pc_rel
= 0;
5474 if (reg_required_here (str
, 0) == FAIL
)
5477 inst
.instruction
|= add
| OFFSET_REG
;
5478 if (skip_past_comma (str
) == SUCCESS
)
5479 return decode_shift (str
, SHIFT_IMMEDIATE
);
5485 /* ARMv5TE: Preload-Cache
5489 Syntactically, like LDR with B=1, W=0, L=1. */
5496 skip_whitespace (str
);
5500 inst
.error
= _("'[' expected after PLD mnemonic");
5505 skip_whitespace (str
);
5507 if ((rd
= reg_required_here (& str
, 16)) == FAIL
)
5510 skip_whitespace (str
);
5516 skip_whitespace (str
);
5518 /* Post-indexed addressing is not allowed with PLD. */
5519 if (skip_past_comma (&str
) == SUCCESS
)
5522 = _("post-indexed expression used in preload instruction");
5525 else if (*str
== '!') /* [Rn]! */
5527 inst
.error
= _("writeback used in preload instruction");
5531 inst
.instruction
|= INDEX_UP
| PRE_INDEX
;
5533 else /* [Rn, ...] */
5535 if (skip_past_comma (& str
) == FAIL
)
5537 inst
.error
= _("pre-indexed expression expected");
5541 if (ldst_extend (&str
) == FAIL
)
5544 skip_whitespace (str
);
5548 inst
.error
= _("missing ]");
5553 skip_whitespace (str
);
5555 if (* str
== '!') /* [Rn]! */
5557 inst
.error
= _("writeback used in preload instruction");
5561 inst
.instruction
|= PRE_INDEX
;
5567 /* ARMv5TE load-consecutive (argument parse)
5574 do_ldrd (char * str
)
5579 skip_whitespace (str
);
5581 if ((rd
= reg_required_here (& str
, 12)) == FAIL
)
5583 inst
.error
= BAD_ARGS
;
5587 if (skip_past_comma (& str
) == FAIL
5588 || (rn
= ld_mode_required_here (& str
)) == FAIL
)
5591 inst
.error
= BAD_ARGS
;
5595 /* inst.instruction has now been zapped with Rd and the addressing mode. */
5596 if (rd
& 1) /* Unpredictable result if Rd is odd. */
5598 inst
.error
= _("destination register must be even");
5604 inst
.error
= _("r14 not allowed here");
5608 if (((rd
== rn
) || (rd
+ 1 == rn
))
5609 && ((inst
.instruction
& WRITE_BACK
)
5610 || (!(inst
.instruction
& PRE_INDEX
))))
5611 as_warn (_("pre/post-indexing used when modified address register is destination"));
5613 /* For an index-register load, the index register must not overlap the
5614 destination (even if not write-back). */
5615 if ((inst
.instruction
& V4_STR_BIT
) == 0
5616 && (inst
.instruction
& HWOFFSET_IMM
) == 0)
5618 int rm
= inst
.instruction
& 0x0000000f;
5620 if (rm
== rd
|| (rm
== rd
+ 1))
5621 as_warn (_("ldrd destination registers must not overlap index register"));
5627 /* Returns the index into fp_values of a floating point number,
5628 or -1 if not in the table. */
5631 my_get_float_expression (char ** str
)
5633 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
5639 memset (words
, 0, MAX_LITTLENUMS
* sizeof (LITTLENUM_TYPE
));
5641 /* Look for a raw floating point number. */
5642 if ((save_in
= atof_ieee (*str
, 'x', words
)) != NULL
5643 && is_end_of_line
[(unsigned char) *save_in
])
5645 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
5647 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
5649 if (words
[j
] != fp_values
[i
][j
])
5653 if (j
== MAX_LITTLENUMS
)
5661 /* Try and parse a more complex expression, this will probably fail
5662 unless the code uses a floating point prefix (eg "0f"). */
5663 save_in
= input_line_pointer
;
5664 input_line_pointer
= *str
;
5665 if (expression (&exp
) == absolute_section
5666 && exp
.X_op
== O_big
5667 && exp
.X_add_number
< 0)
5669 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
5671 if (gen_to_words (words
, 5, (long) 15) == 0)
5673 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
5675 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
5677 if (words
[j
] != fp_values
[i
][j
])
5681 if (j
== MAX_LITTLENUMS
)
5683 *str
= input_line_pointer
;
5684 input_line_pointer
= save_in
;
5691 *str
= input_line_pointer
;
5692 input_line_pointer
= save_in
;
5696 /* We handle all bad expressions here, so that we can report the faulty
5697 instruction in the error message. */
5699 md_operand (expressionS
* expr
)
5701 if (in_my_get_expression
)
5703 expr
->X_op
= O_illegal
;
5704 if (inst
.error
== NULL
)
5705 inst
.error
= _("bad expression");
5709 /* Do those data_ops which can take a negative immediate constant
5710 by altering the instruction. A bit of a hack really.
5714 by inverting the second operand, and
5717 by negating the second operand. */
5720 negate_data_op (unsigned long * instruction
,
5721 unsigned long value
)
5724 unsigned long negated
, inverted
;
5726 negated
= validate_immediate (-value
);
5727 inverted
= validate_immediate (~value
);
5729 op
= (*instruction
>> DATA_OP_SHIFT
) & 0xf;
5732 /* First negates. */
5733 case OPCODE_SUB
: /* ADD <-> SUB */
5734 new_inst
= OPCODE_ADD
;
5739 new_inst
= OPCODE_SUB
;
5743 case OPCODE_CMP
: /* CMP <-> CMN */
5744 new_inst
= OPCODE_CMN
;
5749 new_inst
= OPCODE_CMP
;
5753 /* Now Inverted ops. */
5754 case OPCODE_MOV
: /* MOV <-> MVN */
5755 new_inst
= OPCODE_MVN
;
5760 new_inst
= OPCODE_MOV
;
5764 case OPCODE_AND
: /* AND <-> BIC */
5765 new_inst
= OPCODE_BIC
;
5770 new_inst
= OPCODE_AND
;
5774 case OPCODE_ADC
: /* ADC <-> SBC */
5775 new_inst
= OPCODE_SBC
;
5780 new_inst
= OPCODE_ADC
;
5784 /* We cannot do anything. */
5789 if (value
== (unsigned) FAIL
)
5792 *instruction
&= OPCODE_MASK
;
5793 *instruction
|= new_inst
<< DATA_OP_SHIFT
;
5798 data_op2 (char ** str
)
5803 skip_whitespace (* str
);
5805 if (reg_required_here (str
, 0) != FAIL
)
5807 if (skip_past_comma (str
) == SUCCESS
)
5808 /* Shift operation on register. */
5809 return decode_shift (str
, NO_SHIFT_RESTRICT
);
5815 /* Immediate expression. */
5816 if (is_immediate_prefix (**str
))
5821 if (my_get_expression (&inst
.reloc
.exp
, str
))
5824 if (inst
.reloc
.exp
.X_add_symbol
)
5826 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
5827 inst
.reloc
.pc_rel
= 0;
5831 if (skip_past_comma (str
) == SUCCESS
)
5833 /* #x, y -- ie explicit rotation by Y. */
5834 if (my_get_expression (&expr
, str
))
5837 if (expr
.X_op
!= O_constant
)
5839 inst
.error
= _("constant expression expected");
5843 /* Rotate must be a multiple of 2. */
5844 if (((unsigned) expr
.X_add_number
) > 30
5845 || (expr
.X_add_number
& 1) != 0
5846 || ((unsigned) inst
.reloc
.exp
.X_add_number
) > 255)
5848 inst
.error
= _("invalid constant");
5851 inst
.instruction
|= INST_IMMEDIATE
;
5852 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
5853 inst
.instruction
|= expr
.X_add_number
<< 7;
5857 /* Implicit rotation, select a suitable one. */
5858 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
5862 /* Can't be done. Perhaps the code reads something like
5863 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
5864 if ((value
= negate_data_op (&inst
.instruction
,
5865 inst
.reloc
.exp
.X_add_number
))
5868 inst
.error
= _("invalid constant");
5873 inst
.instruction
|= value
;
5876 inst
.instruction
|= INST_IMMEDIATE
;
5881 inst
.error
= _("register or shift expression expected");
5887 fp_op2 (char ** str
)
5889 skip_whitespace (* str
);
5891 if (fp_reg_required_here (str
, 0) != FAIL
)
5895 /* Immediate expression. */
5896 if (*((*str
)++) == '#')
5902 skip_whitespace (* str
);
5904 /* First try and match exact strings, this is to guarantee
5905 that some formats will work even for cross assembly. */
5907 for (i
= 0; fp_const
[i
]; i
++)
5909 if (strncmp (*str
, fp_const
[i
], strlen (fp_const
[i
])) == 0)
5913 *str
+= strlen (fp_const
[i
]);
5914 if (is_end_of_line
[(unsigned char) **str
])
5916 inst
.instruction
|= i
+ 8;
5923 /* Just because we didn't get a match doesn't mean that the
5924 constant isn't valid, just that it is in a format that we
5925 don't automatically recognize. Try parsing it with
5926 the standard expression routines. */
5927 if ((i
= my_get_float_expression (str
)) >= 0)
5929 inst
.instruction
|= i
+ 8;
5933 inst
.error
= _("invalid floating point immediate expression");
5937 _("floating point register or immediate expression expected");
5943 do_arit (char * str
)
5945 skip_whitespace (str
);
5947 if (reg_required_here (&str
, 12) == FAIL
5948 || skip_past_comma (&str
) == FAIL
5949 || reg_required_here (&str
, 16) == FAIL
5950 || skip_past_comma (&str
) == FAIL
5951 || data_op2 (&str
) == FAIL
)
5954 inst
.error
= BAD_ARGS
;
5964 /* This is a pseudo-op of the form "adr rd, label" to be converted
5965 into a relative address of the form "add rd, pc, #label-.-8". */
5966 skip_whitespace (str
);
5968 if (reg_required_here (&str
, 12) == FAIL
5969 || skip_past_comma (&str
) == FAIL
5970 || my_get_expression (&inst
.reloc
.exp
, &str
))
5973 inst
.error
= BAD_ARGS
;
5977 /* Frag hacking will turn this into a sub instruction if the offset turns
5978 out to be negative. */
5979 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
5981 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust. */
5983 inst
.reloc
.pc_rel
= 1;
5989 do_adrl (char * str
)
5991 /* This is a pseudo-op of the form "adrl rd, label" to be converted
5992 into a relative address of the form:
5993 add rd, pc, #low(label-.-8)"
5994 add rd, rd, #high(label-.-8)" */
5996 skip_whitespace (str
);
5998 if (reg_required_here (&str
, 12) == FAIL
5999 || skip_past_comma (&str
) == FAIL
6000 || my_get_expression (&inst
.reloc
.exp
, &str
))
6003 inst
.error
= BAD_ARGS
;
6009 /* Frag hacking will turn this into a sub instruction if the offset turns
6010 out to be negative. */
6011 inst
.reloc
.type
= BFD_RELOC_ARM_ADRL_IMMEDIATE
;
6013 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust */
6015 inst
.reloc
.pc_rel
= 1;
6016 inst
.size
= INSN_SIZE
* 2;
6022 skip_whitespace (str
);
6024 if (reg_required_here (&str
, 16) == FAIL
)
6027 inst
.error
= BAD_ARGS
;
6031 if (skip_past_comma (&str
) == FAIL
6032 || data_op2 (&str
) == FAIL
)
6035 inst
.error
= BAD_ARGS
;
6045 skip_whitespace (str
);
6047 if (reg_required_here (&str
, 12) == FAIL
)
6050 inst
.error
= BAD_ARGS
;
6054 if (skip_past_comma (&str
) == FAIL
6055 || data_op2 (&str
) == FAIL
)
6058 inst
.error
= BAD_ARGS
;
6066 do_ldst (char * str
)
6072 skip_whitespace (str
);
6074 if ((conflict_reg
= reg_required_here (&str
, 12)) == FAIL
)
6077 inst
.error
= BAD_ARGS
;
6081 if (skip_past_comma (&str
) == FAIL
)
6083 inst
.error
= _("address expected");
6093 skip_whitespace (str
);
6095 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6098 /* Conflicts can occur on stores as well as loads. */
6099 conflict_reg
= (conflict_reg
== reg
);
6101 skip_whitespace (str
);
6107 if (skip_past_comma (&str
) == SUCCESS
)
6109 /* [Rn],... (post inc) */
6110 if (ldst_extend (&str
) == FAIL
)
6113 as_warn (_("%s register same as write-back base"),
6114 ((inst
.instruction
& LOAD_BIT
)
6115 ? _("destination") : _("source")));
6120 skip_whitespace (str
);
6125 as_warn (_("%s register same as write-back base"),
6126 ((inst
.instruction
& LOAD_BIT
)
6127 ? _("destination") : _("source")));
6129 inst
.instruction
|= WRITE_BACK
;
6132 inst
.instruction
|= INDEX_UP
;
6139 if (skip_past_comma (&str
) == FAIL
)
6141 inst
.error
= _("pre-indexed expression expected");
6146 if (ldst_extend (&str
) == FAIL
)
6149 skip_whitespace (str
);
6153 inst
.error
= _("missing ]");
6157 skip_whitespace (str
);
6162 as_warn (_("%s register same as write-back base"),
6163 ((inst
.instruction
& LOAD_BIT
)
6164 ? _("destination") : _("source")));
6166 inst
.instruction
|= WRITE_BACK
;
6170 else if (*str
== '=')
6172 if ((inst
.instruction
& LOAD_BIT
) == 0)
6174 inst
.error
= _("invalid pseudo operation");
6178 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6181 skip_whitespace (str
);
6183 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6186 if (inst
.reloc
.exp
.X_op
!= O_constant
6187 && inst
.reloc
.exp
.X_op
!= O_symbol
)
6189 inst
.error
= _("constant expression expected");
6193 if (inst
.reloc
.exp
.X_op
== O_constant
)
6195 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
6199 /* This can be done with a mov instruction. */
6200 inst
.instruction
&= LITERAL_MASK
;
6201 inst
.instruction
|= (INST_IMMEDIATE
6202 | (OPCODE_MOV
<< DATA_OP_SHIFT
));
6203 inst
.instruction
|= value
& 0xfff;
6208 value
= validate_immediate (~inst
.reloc
.exp
.X_add_number
);
6212 /* This can be done with a mvn instruction. */
6213 inst
.instruction
&= LITERAL_MASK
;
6214 inst
.instruction
|= (INST_IMMEDIATE
6215 | (OPCODE_MVN
<< DATA_OP_SHIFT
));
6216 inst
.instruction
|= value
& 0xfff;
6222 /* Insert into literal pool. */
6223 if (add_to_lit_pool () == FAIL
)
6226 inst
.error
= _("literal pool insertion failed");
6230 /* Change the instruction exp to point to the pool. */
6231 inst
.reloc
.type
= BFD_RELOC_ARM_LITERAL
;
6232 inst
.reloc
.pc_rel
= 1;
6233 inst
.instruction
|= (REG_PC
<< 16);
6238 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6241 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
6243 /* PC rel adjust. */
6244 inst
.reloc
.exp
.X_add_number
-= 8;
6246 inst
.reloc
.pc_rel
= 1;
6247 inst
.instruction
|= (REG_PC
<< 16);
6251 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
6256 do_ldstt (char * str
)
6260 skip_whitespace (str
);
6262 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
6265 inst
.error
= BAD_ARGS
;
6269 if (skip_past_comma (& str
) == FAIL
)
6271 inst
.error
= _("address expected");
6281 skip_whitespace (str
);
6283 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6286 /* ldrt/strt always use post-indexed addressing, so if the base is
6287 the same as Rd, we warn. */
6288 if (conflict_reg
== reg
)
6289 as_warn (_("%s register same as write-back base"),
6290 ((inst
.instruction
& LOAD_BIT
)
6291 ? _("destination") : _("source")));
6293 skip_whitespace (str
);
6299 if (skip_past_comma (&str
) == SUCCESS
)
6301 /* [Rn],... (post inc) */
6302 if (ldst_extend (&str
) == FAIL
)
6308 skip_whitespace (str
);
6310 /* Skip a write-back '!'. */
6314 inst
.instruction
|= INDEX_UP
;
6319 inst
.error
= _("post-indexed expression expected");
6325 inst
.error
= _("post-indexed expression expected");
6332 /* Halfword and signed-byte load/store operations. */
6335 do_ldstv4 (char * str
)
6341 skip_whitespace (str
);
6343 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
6346 inst
.error
= BAD_ARGS
;
6350 if (skip_past_comma (& str
) == FAIL
)
6352 inst
.error
= _("address expected");
6362 skip_whitespace (str
);
6364 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6367 /* Conflicts can occur on stores as well as loads. */
6368 conflict_reg
= (conflict_reg
== reg
);
6370 skip_whitespace (str
);
6376 if (skip_past_comma (&str
) == SUCCESS
)
6378 /* [Rn],... (post inc) */
6379 if (ldst_extend_v4 (&str
) == FAIL
)
6382 as_warn (_("%s register same as write-back base"),
6383 ((inst
.instruction
& LOAD_BIT
)
6384 ? _("destination") : _("source")));
6389 inst
.instruction
|= HWOFFSET_IMM
;
6391 skip_whitespace (str
);
6396 as_warn (_("%s register same as write-back base"),
6397 ((inst
.instruction
& LOAD_BIT
)
6398 ? _("destination") : _("source")));
6400 inst
.instruction
|= WRITE_BACK
;
6403 inst
.instruction
|= INDEX_UP
;
6410 if (skip_past_comma (&str
) == FAIL
)
6412 inst
.error
= _("pre-indexed expression expected");
6417 if (ldst_extend_v4 (&str
) == FAIL
)
6420 skip_whitespace (str
);
6424 inst
.error
= _("missing ]");
6428 skip_whitespace (str
);
6433 as_warn (_("%s register same as write-back base"),
6434 ((inst
.instruction
& LOAD_BIT
)
6435 ? _("destination") : _("source")));
6437 inst
.instruction
|= WRITE_BACK
;
6441 else if (*str
== '=')
6443 if ((inst
.instruction
& LOAD_BIT
) == 0)
6445 inst
.error
= _("invalid pseudo operation");
6449 /* XXX Does this work correctly for half-word/byte ops? */
6450 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6453 skip_whitespace (str
);
6455 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6458 if (inst
.reloc
.exp
.X_op
!= O_constant
6459 && inst
.reloc
.exp
.X_op
!= O_symbol
)
6461 inst
.error
= _("constant expression expected");
6465 if (inst
.reloc
.exp
.X_op
== O_constant
)
6467 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
6471 /* This can be done with a mov instruction. */
6472 inst
.instruction
&= LITERAL_MASK
;
6473 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MOV
<< DATA_OP_SHIFT
);
6474 inst
.instruction
|= value
& 0xfff;
6479 value
= validate_immediate (~ inst
.reloc
.exp
.X_add_number
);
6483 /* This can be done with a mvn instruction. */
6484 inst
.instruction
&= LITERAL_MASK
;
6485 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MVN
<< DATA_OP_SHIFT
);
6486 inst
.instruction
|= value
& 0xfff;
6492 /* Insert into literal pool. */
6493 if (add_to_lit_pool () == FAIL
)
6496 inst
.error
= _("literal pool insertion failed");
6500 /* Change the instruction exp to point to the pool. */
6501 inst
.instruction
|= HWOFFSET_IMM
;
6502 inst
.reloc
.type
= BFD_RELOC_ARM_HWLITERAL
;
6503 inst
.reloc
.pc_rel
= 1;
6504 inst
.instruction
|= (REG_PC
<< 16);
6509 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6512 inst
.instruction
|= HWOFFSET_IMM
;
6513 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
6515 /* PC rel adjust. */
6516 inst
.reloc
.exp
.X_add_number
-= 8;
6518 inst
.reloc
.pc_rel
= 1;
6519 inst
.instruction
|= (REG_PC
<< 16);
6523 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
6528 reg_list (char ** strp
)
6530 char * str
= * strp
;
6534 /* We come back here if we get ranges concatenated by '+' or '|'. */
6549 skip_whitespace (str
);
6551 if ((reg
= reg_required_here (& str
, -1)) == FAIL
)
6560 inst
.error
= _("bad range in register list");
6564 for (i
= cur_reg
+ 1; i
< reg
; i
++)
6566 if (range
& (1 << i
))
6568 (_("Warning: duplicated register (r%d) in register list"),
6576 if (range
& (1 << reg
))
6577 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
6579 else if (reg
<= cur_reg
)
6580 as_tsktsk (_("Warning: register range not in ascending order"));
6585 while (skip_past_comma (&str
) != FAIL
6586 || (in_range
= 1, *str
++ == '-'));
6588 skip_whitespace (str
);
6592 inst
.error
= _("missing `}'");
6600 if (my_get_expression (&expr
, &str
))
6603 if (expr
.X_op
== O_constant
)
6605 if (expr
.X_add_number
6606 != (expr
.X_add_number
& 0x0000ffff))
6608 inst
.error
= _("invalid register mask");
6612 if ((range
& expr
.X_add_number
) != 0)
6614 int regno
= range
& expr
.X_add_number
;
6617 regno
= (1 << regno
) - 1;
6619 (_("Warning: duplicated register (r%d) in register list"),
6623 range
|= expr
.X_add_number
;
6627 if (inst
.reloc
.type
!= 0)
6629 inst
.error
= _("expression too complex");
6633 memcpy (&inst
.reloc
.exp
, &expr
, sizeof (expressionS
));
6634 inst
.reloc
.type
= BFD_RELOC_ARM_MULTI
;
6635 inst
.reloc
.pc_rel
= 0;
6639 skip_whitespace (str
);
6641 if (*str
== '|' || *str
== '+')
6647 while (another_range
);
6654 do_ldmstm (char * str
)
6659 skip_whitespace (str
);
6661 if ((base_reg
= reg_required_here (&str
, 16)) == FAIL
)
6664 if (base_reg
== REG_PC
)
6666 inst
.error
= _("r15 not allowed as base register");
6670 skip_whitespace (str
);
6674 inst
.instruction
|= WRITE_BACK
;
6678 if (skip_past_comma (&str
) == FAIL
6679 || (range
= reg_list (&str
)) == FAIL
)
6682 inst
.error
= BAD_ARGS
;
6689 inst
.instruction
|= LDM_TYPE_2_OR_3
;
6692 if (inst
.instruction
& WRITE_BACK
)
6694 /* Check for unpredictable uses of writeback. */
6695 if (inst
.instruction
& LOAD_BIT
)
6697 /* Not allowed in LDM type 2. */
6698 if ((inst
.instruction
& LDM_TYPE_2_OR_3
)
6699 && ((range
& (1 << REG_PC
)) == 0))
6700 as_warn (_("writeback of base register is UNPREDICTABLE"));
6701 /* Only allowed if base reg not in list for other types. */
6702 else if (range
& (1 << base_reg
))
6703 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
6707 /* Not allowed for type 2. */
6708 if (inst
.instruction
& LDM_TYPE_2_OR_3
)
6709 as_warn (_("writeback of base register is UNPREDICTABLE"));
6710 /* Only allowed if base reg not in list, or first in list. */
6711 else if ((range
& (1 << base_reg
))
6712 && (range
& ((1 << base_reg
) - 1)))
6713 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
6717 inst
.instruction
|= range
;
6724 skip_whitespace (str
);
6726 /* Allow optional leading '#'. */
6727 if (is_immediate_prefix (*str
))
6730 if (my_get_expression (& inst
.reloc
.exp
, & str
))
6733 inst
.reloc
.type
= BFD_RELOC_ARM_SMI
;
6734 inst
.reloc
.pc_rel
= 0;
6741 skip_whitespace (str
);
6743 /* Allow optional leading '#'. */
6744 if (is_immediate_prefix (*str
))
6747 if (my_get_expression (& inst
.reloc
.exp
, & str
))
6750 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
6751 inst
.reloc
.pc_rel
= 0;
6756 do_swap (char * str
)
6760 skip_whitespace (str
);
6762 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
6767 inst
.error
= _("r15 not allowed in swap");
6771 if (skip_past_comma (&str
) == FAIL
6772 || (reg
= reg_required_here (&str
, 0)) == FAIL
)
6775 inst
.error
= BAD_ARGS
;
6781 inst
.error
= _("r15 not allowed in swap");
6785 if (skip_past_comma (&str
) == FAIL
6788 inst
.error
= BAD_ARGS
;
6792 skip_whitespace (str
);
6794 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6799 inst
.error
= BAD_PC
;
6803 skip_whitespace (str
);
6807 inst
.error
= _("missing ]");
6815 do_branch (char * str
)
6817 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6824 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
6825 required for the instruction. */
6827 /* arm_parse_reloc () works on input_line_pointer.
6828 We actually want to parse the operands to the branch instruction
6829 passed in 'str'. Save the input pointer and restore it later. */
6830 save_in
= input_line_pointer
;
6831 input_line_pointer
= str
;
6832 if (inst
.reloc
.exp
.X_op
== O_symbol
6834 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
6836 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
6837 inst
.reloc
.pc_rel
= 0;
6838 /* Modify str to point to after parsed operands, otherwise
6839 end_of_line() will complain about the (PLT) left in str. */
6840 str
= input_line_pointer
;
6844 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
6845 inst
.reloc
.pc_rel
= 1;
6847 input_line_pointer
= save_in
;
6850 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
6851 inst
.reloc
.pc_rel
= 1;
6852 #endif /* OBJ_ELF */
6860 /* Co-processor data operation.
6861 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
6862 skip_whitespace (str
);
6864 if (co_proc_number (&str
) == FAIL
)
6867 inst
.error
= BAD_ARGS
;
6871 if (skip_past_comma (&str
) == FAIL
6872 || cp_opc_expr (&str
, 20,4) == FAIL
)
6875 inst
.error
= BAD_ARGS
;
6879 if (skip_past_comma (&str
) == FAIL
6880 || cp_reg_required_here (&str
, 12) == FAIL
)
6883 inst
.error
= BAD_ARGS
;
6887 if (skip_past_comma (&str
) == FAIL
6888 || cp_reg_required_here (&str
, 16) == FAIL
)
6891 inst
.error
= BAD_ARGS
;
6895 if (skip_past_comma (&str
) == FAIL
6896 || cp_reg_required_here (&str
, 0) == FAIL
)
6899 inst
.error
= BAD_ARGS
;
6903 if (skip_past_comma (&str
) == SUCCESS
)
6905 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
6908 inst
.error
= BAD_ARGS
;
6917 do_lstc (char * str
)
6919 /* Co-processor register load/store.
6920 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
6922 skip_whitespace (str
);
6924 if (co_proc_number (&str
) == FAIL
)
6927 inst
.error
= BAD_ARGS
;
6931 if (skip_past_comma (&str
) == FAIL
6932 || cp_reg_required_here (&str
, 12) == FAIL
)
6935 inst
.error
= BAD_ARGS
;
6939 if (skip_past_comma (&str
) == FAIL
6940 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
6943 inst
.error
= BAD_ARGS
;
6951 do_co_reg (char * str
)
6953 /* Co-processor register transfer.
6954 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
6956 skip_whitespace (str
);
6958 if (co_proc_number (&str
) == FAIL
)
6961 inst
.error
= BAD_ARGS
;
6965 if (skip_past_comma (&str
) == FAIL
6966 || cp_opc_expr (&str
, 21, 3) == FAIL
)
6969 inst
.error
= BAD_ARGS
;
6973 if (skip_past_comma (&str
) == FAIL
6974 || reg_required_here (&str
, 12) == FAIL
)
6977 inst
.error
= BAD_ARGS
;
6981 if (skip_past_comma (&str
) == FAIL
6982 || cp_reg_required_here (&str
, 16) == FAIL
)
6985 inst
.error
= BAD_ARGS
;
6989 if (skip_past_comma (&str
) == FAIL
6990 || cp_reg_required_here (&str
, 0) == FAIL
)
6993 inst
.error
= BAD_ARGS
;
6997 if (skip_past_comma (&str
) == SUCCESS
)
6999 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
7002 inst
.error
= BAD_ARGS
;
7011 do_fpa_ctrl (char * str
)
7013 /* FP control registers.
7014 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
7016 skip_whitespace (str
);
7018 if (reg_required_here (&str
, 12) == FAIL
)
7021 inst
.error
= BAD_ARGS
;
7029 do_fpa_ldst (char * str
)
7031 skip_whitespace (str
);
7033 if (fp_reg_required_here (&str
, 12) == FAIL
)
7036 inst
.error
= BAD_ARGS
;
7040 if (skip_past_comma (&str
) == FAIL
7041 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
7044 inst
.error
= BAD_ARGS
;
7052 do_fpa_ldmstm (char * str
)
7056 skip_whitespace (str
);
7058 if (fp_reg_required_here (&str
, 12) == FAIL
)
7061 inst
.error
= BAD_ARGS
;
7065 /* Get Number of registers to transfer. */
7066 if (skip_past_comma (&str
) == FAIL
7067 || my_get_expression (&inst
.reloc
.exp
, &str
))
7070 inst
.error
= _("constant expression expected");
7074 if (inst
.reloc
.exp
.X_op
!= O_constant
)
7076 inst
.error
= _("constant value required for number of registers");
7080 num_regs
= inst
.reloc
.exp
.X_add_number
;
7082 if (num_regs
< 1 || num_regs
> 4)
7084 inst
.error
= _("number of registers must be in the range [1:4]");
7091 inst
.instruction
|= CP_T_X
;
7094 inst
.instruction
|= CP_T_Y
;
7097 inst
.instruction
|= CP_T_Y
| CP_T_X
;
7105 if (inst
.instruction
& (CP_T_Pre
| CP_T_UD
)) /* ea/fd format. */
7111 /* The instruction specified "ea" or "fd", so we can only accept
7112 [Rn]{!}. The instruction does not really support stacking or
7113 unstacking, so we have to emulate these by setting appropriate
7114 bits and offsets. */
7115 if (skip_past_comma (&str
) == FAIL
7119 inst
.error
= BAD_ARGS
;
7124 skip_whitespace (str
);
7126 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
7129 skip_whitespace (str
);
7133 inst
.error
= BAD_ARGS
;
7145 _("r15 not allowed as base register with write-back");
7152 if (inst
.instruction
& CP_T_Pre
)
7154 /* Pre-decrement. */
7155 offset
= 3 * num_regs
;
7157 inst
.instruction
|= CP_T_WB
;
7161 /* Post-increment. */
7164 inst
.instruction
|= CP_T_WB
;
7165 offset
= 3 * num_regs
;
7169 /* No write-back, so convert this into a standard pre-increment
7170 instruction -- aesthetically more pleasing. */
7171 inst
.instruction
|= CP_T_Pre
| CP_T_UD
;
7176 inst
.instruction
|= offset
;
7178 else if (skip_past_comma (&str
) == FAIL
7179 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
7182 inst
.error
= BAD_ARGS
;
7190 do_fpa_dyadic (char * str
)
7192 skip_whitespace (str
);
7194 if (fp_reg_required_here (&str
, 12) == FAIL
)
7197 inst
.error
= BAD_ARGS
;
7201 if (skip_past_comma (&str
) == FAIL
7202 || fp_reg_required_here (&str
, 16) == FAIL
)
7205 inst
.error
= BAD_ARGS
;
7209 if (skip_past_comma (&str
) == FAIL
7210 || fp_op2 (&str
) == FAIL
)
7213 inst
.error
= BAD_ARGS
;
7221 do_fpa_monadic (char * str
)
7223 skip_whitespace (str
);
7225 if (fp_reg_required_here (&str
, 12) == FAIL
)
7228 inst
.error
= BAD_ARGS
;
7232 if (skip_past_comma (&str
) == FAIL
7233 || fp_op2 (&str
) == FAIL
)
7236 inst
.error
= BAD_ARGS
;
7244 do_fpa_cmp (char * str
)
7246 skip_whitespace (str
);
7248 if (fp_reg_required_here (&str
, 16) == FAIL
)
7251 inst
.error
= BAD_ARGS
;
7255 if (skip_past_comma (&str
) == FAIL
7256 || fp_op2 (&str
) == FAIL
)
7259 inst
.error
= BAD_ARGS
;
7267 do_fpa_from_reg (char * str
)
7269 skip_whitespace (str
);
7271 if (fp_reg_required_here (&str
, 16) == FAIL
)
7274 inst
.error
= BAD_ARGS
;
7278 if (skip_past_comma (&str
) == FAIL
7279 || reg_required_here (&str
, 12) == FAIL
)
7282 inst
.error
= BAD_ARGS
;
7290 do_fpa_to_reg (char * str
)
7292 skip_whitespace (str
);
7294 if (reg_required_here (&str
, 12) == FAIL
)
7297 if (skip_past_comma (&str
) == FAIL
7298 || fp_reg_required_here (&str
, 0) == FAIL
)
7301 inst
.error
= BAD_ARGS
;
7308 /* Encode a VFP SP register number. */
7311 vfp_sp_encode_reg (int reg
, enum vfp_sp_reg_pos pos
)
7316 inst
.instruction
|= ((reg
>> 1) << 12) | ((reg
& 1) << 22);
7320 inst
.instruction
|= ((reg
>> 1) << 16) | ((reg
& 1) << 7);
7324 inst
.instruction
|= ((reg
>> 1) << 0) | ((reg
& 1) << 5);
7333 vfp_sp_reg_required_here (char ** str
,
7334 enum vfp_sp_reg_pos pos
)
7337 char * start
= *str
;
7339 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_SN
].htab
)) != FAIL
)
7341 vfp_sp_encode_reg (reg
, pos
);
7345 /* In the few cases where we might be able to accept something else
7346 this error can be overridden. */
7347 inst
.error
= _(all_reg_maps
[REG_TYPE_SN
].expected
);
7349 /* Restore the start point. */
7355 vfp_dp_reg_required_here (char ** str
,
7356 enum vfp_dp_reg_pos pos
)
7359 char * start
= *str
;
7361 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_DN
].htab
)) != FAIL
)
7366 inst
.instruction
|= reg
<< 12;
7370 inst
.instruction
|= reg
<< 16;
7374 inst
.instruction
|= reg
<< 0;
7383 /* In the few cases where we might be able to accept something else
7384 this error can be overridden. */
7385 inst
.error
= _(all_reg_maps
[REG_TYPE_DN
].expected
);
7387 /* Restore the start point. */
7393 do_vfp_sp_monadic (char * str
)
7395 skip_whitespace (str
);
7397 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7400 if (skip_past_comma (&str
) == FAIL
7401 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
7404 inst
.error
= BAD_ARGS
;
7412 do_vfp_dp_monadic (char * str
)
7414 skip_whitespace (str
);
7416 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7419 if (skip_past_comma (&str
) == FAIL
7420 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7423 inst
.error
= BAD_ARGS
;
7431 do_vfp_sp_dyadic (char * str
)
7433 skip_whitespace (str
);
7435 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7438 if (skip_past_comma (&str
) == FAIL
7439 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
7440 || skip_past_comma (&str
) == FAIL
7441 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
7444 inst
.error
= BAD_ARGS
;
7452 do_vfp_dp_dyadic (char * str
)
7454 skip_whitespace (str
);
7456 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7459 if (skip_past_comma (&str
) == FAIL
7460 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
7461 || skip_past_comma (&str
) == FAIL
7462 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7465 inst
.error
= BAD_ARGS
;
7473 do_vfp_reg_from_sp (char * str
)
7475 skip_whitespace (str
);
7477 if (reg_required_here (&str
, 12) == FAIL
)
7480 if (skip_past_comma (&str
) == FAIL
7481 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
7484 inst
.error
= BAD_ARGS
;
7491 /* Parse a VFP register list. If the string is invalid return FAIL.
7492 Otherwise return the number of registers, and set PBASE to the first
7493 register. Double precision registers are matched if DP is nonzero. */
7496 vfp_parse_reg_list (char **str
, int *pbase
, int dp
)
7504 unsigned long mask
= 0;
7511 skip_whitespace (*str
);
7515 regtype
= REG_TYPE_DN
;
7520 regtype
= REG_TYPE_SN
;
7524 base_reg
= max_regs
;
7528 new_base
= arm_reg_parse (str
, all_reg_maps
[regtype
].htab
);
7529 if (new_base
== FAIL
)
7531 inst
.error
= _(all_reg_maps
[regtype
].expected
);
7535 if (new_base
< base_reg
)
7536 base_reg
= new_base
;
7538 if (mask
& (1 << new_base
))
7540 inst
.error
= _("invalid register list");
7544 if ((mask
>> new_base
) != 0 && ! warned
)
7546 as_tsktsk (_("register list not in ascending order"));
7550 mask
|= 1 << new_base
;
7553 skip_whitespace (*str
);
7555 if (**str
== '-') /* We have the start of a range expression */
7562 = arm_reg_parse (str
, all_reg_maps
[regtype
].htab
))
7565 inst
.error
= _(all_reg_maps
[regtype
].expected
);
7569 if (high_range
<= new_base
)
7571 inst
.error
= _("register range not in ascending order");
7575 for (new_base
++; new_base
<= high_range
; new_base
++)
7577 if (mask
& (1 << new_base
))
7579 inst
.error
= _("invalid register list");
7583 mask
|= 1 << new_base
;
7588 while (skip_past_comma (str
) != FAIL
);
7592 /* Sanity check -- should have raised a parse error above. */
7593 if (count
== 0 || count
> max_regs
)
7598 /* Final test -- the registers must be consecutive. */
7600 for (i
= 0; i
< count
; i
++)
7602 if ((mask
& (1u << i
)) == 0)
7604 inst
.error
= _("non-contiguous register range");
7613 do_vfp_reg2_from_sp2 (char * str
)
7617 skip_whitespace (str
);
7619 if (reg_required_here (&str
, 12) == FAIL
7620 || skip_past_comma (&str
) == FAIL
7621 || reg_required_here (&str
, 16) == FAIL
7622 || skip_past_comma (&str
) == FAIL
)
7625 inst
.error
= BAD_ARGS
;
7629 /* We require exactly two consecutive SP registers. */
7630 if (vfp_parse_reg_list (&str
, ®
, 0) != 2)
7633 inst
.error
= _("only two consecutive VFP SP registers allowed here");
7635 vfp_sp_encode_reg (reg
, VFP_REG_Sm
);
7641 do_vfp_sp_from_reg (char * str
)
7643 skip_whitespace (str
);
7645 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
7648 if (skip_past_comma (&str
) == FAIL
7649 || reg_required_here (&str
, 12) == FAIL
)
7652 inst
.error
= BAD_ARGS
;
7660 do_vfp_sp2_from_reg2 (char * str
)
7664 skip_whitespace (str
);
7666 /* We require exactly two consecutive SP registers. */
7667 if (vfp_parse_reg_list (&str
, ®
, 0) != 2)
7670 inst
.error
= _("only two consecutive VFP SP registers allowed here");
7672 vfp_sp_encode_reg (reg
, VFP_REG_Sm
);
7674 if (skip_past_comma (&str
) == FAIL
7675 || reg_required_here (&str
, 12) == FAIL
7676 || skip_past_comma (&str
) == FAIL
7677 || reg_required_here (&str
, 16) == FAIL
)
7680 inst
.error
= BAD_ARGS
;
7688 do_vfp_reg_from_dp (char * str
)
7690 skip_whitespace (str
);
7692 if (reg_required_here (&str
, 12) == FAIL
)
7695 if (skip_past_comma (&str
) == FAIL
7696 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
7699 inst
.error
= BAD_ARGS
;
7707 do_vfp_reg2_from_dp (char * str
)
7709 skip_whitespace (str
);
7711 if (reg_required_here (&str
, 12) == FAIL
)
7714 if (skip_past_comma (&str
) == FAIL
7715 || reg_required_here (&str
, 16) == FAIL
7716 || skip_past_comma (&str
) == FAIL
7717 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7720 inst
.error
= BAD_ARGS
;
7728 do_vfp_dp_from_reg (char * str
)
7730 skip_whitespace (str
);
7732 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
7735 if (skip_past_comma (&str
) == FAIL
7736 || reg_required_here (&str
, 12) == FAIL
)
7739 inst
.error
= BAD_ARGS
;
7747 do_vfp_dp_from_reg2 (char * str
)
7749 skip_whitespace (str
);
7751 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7754 if (skip_past_comma (&str
) == FAIL
7755 || reg_required_here (&str
, 12) == FAIL
7756 || skip_past_comma (&str
) == FAIL
7757 || reg_required_here (&str
, 16) == FAIL
)
7760 inst
.error
= BAD_ARGS
;
7767 static const struct vfp_reg
*
7768 vfp_psr_parse (char ** str
)
7773 const struct vfp_reg
*vreg
;
7777 /* Find the end of the current token. */
7782 while (ISALPHA (c
));
7787 for (vreg
= vfp_regs
+ 0;
7788 vreg
< vfp_regs
+ sizeof (vfp_regs
) / sizeof (struct vfp_reg
);
7791 if (streq (start
, vreg
->name
))
7804 vfp_psr_required_here (char ** str
)
7807 const struct vfp_reg
*vreg
;
7809 vreg
= vfp_psr_parse (str
);
7813 inst
.instruction
|= vreg
->regno
;
7817 inst
.error
= _("VFP system register expected");
7824 do_vfp_reg_from_ctrl (char * str
)
7826 skip_whitespace (str
);
7828 if (reg_required_here (&str
, 12) == FAIL
)
7831 if (skip_past_comma (&str
) == FAIL
7832 || vfp_psr_required_here (&str
) == FAIL
)
7835 inst
.error
= BAD_ARGS
;
7843 do_vfp_ctrl_from_reg (char * str
)
7845 skip_whitespace (str
);
7847 if (vfp_psr_required_here (&str
) == FAIL
)
7850 if (skip_past_comma (&str
) == FAIL
7851 || reg_required_here (&str
, 12) == FAIL
)
7854 inst
.error
= BAD_ARGS
;
7862 do_vfp_sp_ldst (char * str
)
7864 skip_whitespace (str
);
7866 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7869 inst
.error
= BAD_ARGS
;
7873 if (skip_past_comma (&str
) == FAIL
7874 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
7877 inst
.error
= BAD_ARGS
;
7885 do_vfp_dp_ldst (char * str
)
7887 skip_whitespace (str
);
7889 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7892 inst
.error
= BAD_ARGS
;
7896 if (skip_past_comma (&str
) == FAIL
7897 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
7900 inst
.error
= BAD_ARGS
;
7909 vfp_sp_ldstm (char * str
, enum vfp_ldstm_type ldstm_type
)
7914 skip_whitespace (str
);
7916 if (reg_required_here (&str
, 16) == FAIL
)
7919 skip_whitespace (str
);
7923 inst
.instruction
|= WRITE_BACK
;
7926 else if (ldstm_type
!= VFP_LDSTMIA
)
7928 inst
.error
= _("this addressing mode requires base-register writeback");
7932 if (skip_past_comma (&str
) == FAIL
7933 || (count
= vfp_parse_reg_list (&str
, ®
, 0)) == FAIL
)
7936 inst
.error
= BAD_ARGS
;
7939 vfp_sp_encode_reg (reg
, VFP_REG_Sd
);
7941 inst
.instruction
|= count
;
7946 vfp_dp_ldstm (char * str
, enum vfp_ldstm_type ldstm_type
)
7951 skip_whitespace (str
);
7953 if (reg_required_here (&str
, 16) == FAIL
)
7956 skip_whitespace (str
);
7960 inst
.instruction
|= WRITE_BACK
;
7963 else if (ldstm_type
!= VFP_LDSTMIA
&& ldstm_type
!= VFP_LDSTMIAX
)
7965 inst
.error
= _("this addressing mode requires base-register writeback");
7969 if (skip_past_comma (&str
) == FAIL
7970 || (count
= vfp_parse_reg_list (&str
, ®
, 1)) == FAIL
)
7973 inst
.error
= BAD_ARGS
;
7978 if (ldstm_type
== VFP_LDSTMIAX
|| ldstm_type
== VFP_LDSTMDBX
)
7981 inst
.instruction
|= (reg
<< 12) | count
;
7986 do_vfp_sp_ldstmia (char * str
)
7988 vfp_sp_ldstm (str
, VFP_LDSTMIA
);
7992 do_vfp_sp_ldstmdb (char * str
)
7994 vfp_sp_ldstm (str
, VFP_LDSTMDB
);
7998 do_vfp_dp_ldstmia (char * str
)
8000 vfp_dp_ldstm (str
, VFP_LDSTMIA
);
8004 do_vfp_dp_ldstmdb (char * str
)
8006 vfp_dp_ldstm (str
, VFP_LDSTMDB
);
8010 do_vfp_xp_ldstmia (char *str
)
8012 vfp_dp_ldstm (str
, VFP_LDSTMIAX
);
8016 do_vfp_xp_ldstmdb (char * str
)
8018 vfp_dp_ldstm (str
, VFP_LDSTMDBX
);
8022 do_vfp_sp_compare_z (char * str
)
8024 skip_whitespace (str
);
8026 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8029 inst
.error
= BAD_ARGS
;
8037 do_vfp_dp_compare_z (char * str
)
8039 skip_whitespace (str
);
8041 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8044 inst
.error
= BAD_ARGS
;
8052 do_vfp_dp_sp_cvt (char * str
)
8054 skip_whitespace (str
);
8056 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8059 if (skip_past_comma (&str
) == FAIL
8060 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
8063 inst
.error
= BAD_ARGS
;
8071 do_vfp_sp_dp_cvt (char * str
)
8073 skip_whitespace (str
);
8075 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8078 if (skip_past_comma (&str
) == FAIL
8079 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
8082 inst
.error
= BAD_ARGS
;
8089 /* Thumb specific routines. */
8091 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
8095 thumb_add_sub (char * str
, int subtract
)
8097 int Rd
, Rs
, Rn
= FAIL
;
8099 skip_whitespace (str
);
8101 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
8102 || skip_past_comma (&str
) == FAIL
)
8105 inst
.error
= BAD_ARGS
;
8109 if (is_immediate_prefix (*str
))
8113 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8118 if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8121 if (skip_past_comma (&str
) == FAIL
)
8123 /* Two operand format, shuffle the registers
8124 and pretend there are 3. */
8128 else if (is_immediate_prefix (*str
))
8131 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8134 else if ((Rn
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8138 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8139 for the latter case, EXPR contains the immediate that was found. */
8142 /* All register format. */
8143 if (Rd
> 7 || Rs
> 7 || Rn
> 7)
8147 inst
.error
= _("dest and source1 must be the same register");
8151 /* Can't do this for SUB. */
8154 inst
.error
= _("subtract valid only on lo regs");
8158 inst
.instruction
= (T_OPCODE_ADD_HI
8159 | (Rd
> 7 ? THUMB_H1
: 0)
8160 | (Rn
> 7 ? THUMB_H2
: 0));
8161 inst
.instruction
|= (Rd
& 7) | ((Rn
& 7) << 3);
8165 inst
.instruction
= subtract
? T_OPCODE_SUB_R3
: T_OPCODE_ADD_R3
;
8166 inst
.instruction
|= Rd
| (Rs
<< 3) | (Rn
<< 6);
8171 /* Immediate expression, now things start to get nasty. */
8173 /* First deal with HI regs, only very restricted cases allowed:
8174 Adjusting SP, and using PC or SP to get an address. */
8175 if ((Rd
> 7 && (Rd
!= REG_SP
|| Rs
!= REG_SP
))
8176 || (Rs
> 7 && Rs
!= REG_SP
&& Rs
!= REG_PC
))
8178 inst
.error
= _("invalid Hi register with immediate");
8182 if (inst
.reloc
.exp
.X_op
!= O_constant
)
8184 /* Value isn't known yet, all we can do is store all the fragments
8185 we know about in the instruction and let the reloc hacking
8187 inst
.instruction
= (subtract
? 0x8000 : 0) | (Rd
<< 4) | Rs
;
8188 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
8192 int offset
= inst
.reloc
.exp
.X_add_number
;
8202 /* Quick check, in case offset is MIN_INT. */
8205 inst
.error
= _("immediate value out of range");
8209 /* Note - you cannot convert a subtract of 0 into an
8210 add of 0 because the carry flag is set differently. */
8211 else if (offset
> 0)
8216 if (offset
& ~0x1fc)
8218 inst
.error
= _("invalid immediate value for stack adjust");
8221 inst
.instruction
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
8222 inst
.instruction
|= offset
>> 2;
8224 else if (Rs
== REG_PC
|| Rs
== REG_SP
)
8227 || (offset
& ~0x3fc))
8229 inst
.error
= _("invalid immediate for address calculation");
8232 inst
.instruction
= (Rs
== REG_PC
? T_OPCODE_ADD_PC
8234 inst
.instruction
|= (Rd
<< 8) | (offset
>> 2);
8240 inst
.error
= _("immediate value out of range");
8243 inst
.instruction
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
8244 inst
.instruction
|= (Rd
<< 8) | offset
;
8250 inst
.error
= _("immediate value out of range");
8253 inst
.instruction
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
8254 inst
.instruction
|= Rd
| (Rs
<< 3) | (offset
<< 6);
8263 thumb_shift (char * str
, int shift
)
8265 int Rd
, Rs
, Rn
= FAIL
;
8267 skip_whitespace (str
);
8269 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
8270 || skip_past_comma (&str
) == FAIL
)
8273 inst
.error
= BAD_ARGS
;
8277 if (is_immediate_prefix (*str
))
8279 /* Two operand immediate format, set Rs to Rd. */
8282 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8287 if ((Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8290 if (skip_past_comma (&str
) == FAIL
)
8292 /* Two operand format, shuffle the registers
8293 and pretend there are 3. */
8297 else if (is_immediate_prefix (*str
))
8300 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8303 else if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8307 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8308 for the latter case, EXPR contains the immediate that was found. */
8314 inst
.error
= _("source1 and dest must be same register");
8320 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_R
; break;
8321 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_R
; break;
8322 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_R
; break;
8325 inst
.instruction
|= Rd
| (Rn
<< 3);
8331 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_I
; break;
8332 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_I
; break;
8333 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_I
; break;
8336 if (inst
.reloc
.exp
.X_op
!= O_constant
)
8338 /* Value isn't known yet, create a dummy reloc and let reloc
8339 hacking fix it up. */
8340 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_SHIFT
;
8344 unsigned shift_value
= inst
.reloc
.exp
.X_add_number
;
8346 if (shift_value
> 32 || (shift_value
== 32 && shift
== THUMB_LSL
))
8348 inst
.error
= _("invalid immediate for shift");
8352 /* Shifts of zero are handled by converting to LSL. */
8353 if (shift_value
== 0)
8354 inst
.instruction
= T_OPCODE_LSL_I
;
8356 /* Shifts of 32 are encoded as a shift of zero. */
8357 if (shift_value
== 32)
8360 inst
.instruction
|= shift_value
<< 6;
8363 inst
.instruction
|= Rd
| (Rs
<< 3);
8370 thumb_load_store (char * str
, int load_store
, int size
)
8372 int Rd
, Rb
, Ro
= FAIL
;
8374 skip_whitespace (str
);
8376 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
8377 || skip_past_comma (&str
) == FAIL
)
8380 inst
.error
= BAD_ARGS
;
8387 if ((Rb
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8390 if (skip_past_comma (&str
) != FAIL
)
8392 if (is_immediate_prefix (*str
))
8395 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8398 else if ((Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8403 inst
.reloc
.exp
.X_op
= O_constant
;
8404 inst
.reloc
.exp
.X_add_number
= 0;
8409 inst
.error
= _("expected ']'");
8414 else if (*str
== '=')
8416 if (load_store
!= THUMB_LOAD
)
8418 inst
.error
= _("invalid pseudo operation");
8422 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
8425 skip_whitespace (str
);
8427 if (my_get_expression (& inst
.reloc
.exp
, & str
))
8432 if ( inst
.reloc
.exp
.X_op
!= O_constant
8433 && inst
.reloc
.exp
.X_op
!= O_symbol
)
8435 inst
.error
= "Constant expression expected";
8439 if (inst
.reloc
.exp
.X_op
== O_constant
8440 && ((inst
.reloc
.exp
.X_add_number
& ~0xFF) == 0))
8442 /* This can be done with a mov instruction. */
8444 inst
.instruction
= T_OPCODE_MOV_I8
| (Rd
<< 8);
8445 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
8449 /* Insert into literal pool. */
8450 if (add_to_lit_pool () == FAIL
)
8453 inst
.error
= "literal pool insertion failed";
8457 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8458 inst
.reloc
.pc_rel
= 1;
8459 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
8460 /* Adjust ARM pipeline offset to Thumb. */
8461 inst
.reloc
.exp
.X_add_number
+= 4;
8467 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8470 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
8471 inst
.reloc
.pc_rel
= 1;
8472 inst
.reloc
.exp
.X_add_number
-= 4; /* Pipeline offset. */
8473 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8478 if (Rb
== REG_PC
|| Rb
== REG_SP
)
8480 if (size
!= THUMB_WORD
)
8482 inst
.error
= _("byte or halfword not valid for base register");
8485 else if (Rb
== REG_PC
&& load_store
!= THUMB_LOAD
)
8487 inst
.error
= _("r15 based store not allowed");
8490 else if (Ro
!= FAIL
)
8492 inst
.error
= _("invalid base register for register offset");
8497 inst
.instruction
= T_OPCODE_LDR_PC
;
8498 else if (load_store
== THUMB_LOAD
)
8499 inst
.instruction
= T_OPCODE_LDR_SP
;
8501 inst
.instruction
= T_OPCODE_STR_SP
;
8503 inst
.instruction
|= Rd
<< 8;
8504 if (inst
.reloc
.exp
.X_op
== O_constant
)
8506 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
8508 if (offset
& ~0x3fc)
8510 inst
.error
= _("invalid offset");
8514 inst
.instruction
|= offset
>> 2;
8517 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8521 inst
.error
= _("invalid base register in load/store");
8524 else if (Ro
== FAIL
)
8526 /* Immediate offset. */
8527 if (size
== THUMB_WORD
)
8528 inst
.instruction
= (load_store
== THUMB_LOAD
8529 ? T_OPCODE_LDR_IW
: T_OPCODE_STR_IW
);
8530 else if (size
== THUMB_HALFWORD
)
8531 inst
.instruction
= (load_store
== THUMB_LOAD
8532 ? T_OPCODE_LDR_IH
: T_OPCODE_STR_IH
);
8534 inst
.instruction
= (load_store
== THUMB_LOAD
8535 ? T_OPCODE_LDR_IB
: T_OPCODE_STR_IB
);
8537 inst
.instruction
|= Rd
| (Rb
<< 3);
8539 if (inst
.reloc
.exp
.X_op
== O_constant
)
8541 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
8543 if (offset
& ~(0x1f << size
))
8545 inst
.error
= _("invalid offset");
8548 inst
.instruction
|= (offset
>> size
) << 6;
8551 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8555 /* Register offset. */
8556 if (size
== THUMB_WORD
)
8557 inst
.instruction
= (load_store
== THUMB_LOAD
8558 ? T_OPCODE_LDR_RW
: T_OPCODE_STR_RW
);
8559 else if (size
== THUMB_HALFWORD
)
8560 inst
.instruction
= (load_store
== THUMB_LOAD
8561 ? T_OPCODE_LDR_RH
: T_OPCODE_STR_RH
);
8563 inst
.instruction
= (load_store
== THUMB_LOAD
8564 ? T_OPCODE_LDR_RB
: T_OPCODE_STR_RB
);
8566 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
8572 /* A register must be given at this point.
8574 Shift is the place to put it in inst.instruction.
8576 Restores input start point on err.
8577 Returns the reg#, or FAIL. */
8580 mav_reg_required_here (char ** str
, int shift
, enum arm_reg_type regtype
)
8585 if ((reg
= arm_reg_parse (str
, all_reg_maps
[regtype
].htab
)) != FAIL
)
8588 inst
.instruction
|= reg
<< shift
;
8593 /* Restore the start point. */
8596 /* Try generic coprocessor name if applicable. */
8597 if (regtype
== REG_TYPE_MVF
||
8598 regtype
== REG_TYPE_MVD
||
8599 regtype
== REG_TYPE_MVFX
||
8600 regtype
== REG_TYPE_MVDX
)
8602 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CN
].htab
)) != FAIL
)
8605 inst
.instruction
|= reg
<< shift
;
8610 /* Restore the start point. */
8614 /* In the few cases where we might be able to accept something else
8615 this error can be overridden. */
8616 inst
.error
= _(all_reg_maps
[regtype
].expected
);
8621 /* Cirrus Maverick Instructions. */
8623 /* Isnsn like "foo X,Y". */
8626 do_mav_binops (char * str
,
8628 enum arm_reg_type reg0
,
8629 enum arm_reg_type reg1
)
8633 shift0
= mode
& 0xff;
8634 shift1
= (mode
>> 8) & 0xff;
8636 skip_whitespace (str
);
8638 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
8639 || skip_past_comma (&str
) == FAIL
8640 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
)
8643 inst
.error
= BAD_ARGS
;
8649 /* Isnsn like "foo X,Y,Z". */
8652 do_mav_triple (char * str
,
8654 enum arm_reg_type reg0
,
8655 enum arm_reg_type reg1
,
8656 enum arm_reg_type reg2
)
8658 int shift0
, shift1
, shift2
;
8660 shift0
= mode
& 0xff;
8661 shift1
= (mode
>> 8) & 0xff;
8662 shift2
= (mode
>> 16) & 0xff;
8664 skip_whitespace (str
);
8666 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
8667 || skip_past_comma (&str
) == FAIL
8668 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
8669 || skip_past_comma (&str
) == FAIL
8670 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
)
8673 inst
.error
= BAD_ARGS
;
8679 /* Wrapper functions. */
8682 do_mav_binops_1a (char * str
)
8684 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVF
);
8688 do_mav_binops_1b (char * str
)
8690 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVD
);
8694 do_mav_binops_1c (char * str
)
8696 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVDX
);
8700 do_mav_binops_1d (char * str
)
8702 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVF
);
8706 do_mav_binops_1e (char * str
)
8708 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVD
);
8712 do_mav_binops_1f (char * str
)
8714 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVF
);
8718 do_mav_binops_1g (char * str
)
8720 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVD
);
8724 do_mav_binops_1h (char * str
)
8726 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVFX
);
8730 do_mav_binops_1i (char * str
)
8732 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVFX
);
8736 do_mav_binops_1j (char * str
)
8738 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVDX
);
8742 do_mav_binops_1k (char * str
)
8744 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVDX
);
8748 do_mav_binops_1l (char * str
)
8750 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVF
);
8754 do_mav_binops_1m (char * str
)
8756 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVD
);
8760 do_mav_binops_1n (char * str
)
8762 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
8766 do_mav_binops_1o (char * str
)
8768 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
8772 do_mav_binops_2a (char * str
)
8774 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVF
, REG_TYPE_RN
);
8778 do_mav_binops_2b (char * str
)
8780 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVD
, REG_TYPE_RN
);
8784 do_mav_binops_2c (char * str
)
8786 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVDX
, REG_TYPE_RN
);
8790 do_mav_binops_3a (char * str
)
8792 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVFX
);
8796 do_mav_binops_3b (char * str
)
8798 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVFX
, REG_TYPE_MVAX
);
8802 do_mav_binops_3c (char * str
)
8804 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVDX
);
8808 do_mav_binops_3d (char * str
)
8810 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVDX
, REG_TYPE_MVAX
);
8814 do_mav_triple_4a (char * str
)
8816 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_RN
);
8820 do_mav_triple_4b (char * str
)
8822 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_RN
);
8826 do_mav_triple_5a (char * str
)
8828 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVF
, REG_TYPE_MVF
);
8832 do_mav_triple_5b (char * str
)
8834 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVD
, REG_TYPE_MVD
);
8838 do_mav_triple_5c (char * str
)
8840 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
8844 do_mav_triple_5d (char * str
)
8846 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
8850 do_mav_triple_5e (char * str
)
8852 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVF
, REG_TYPE_MVF
, REG_TYPE_MVF
);
8856 do_mav_triple_5f (char * str
)
8858 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVD
, REG_TYPE_MVD
, REG_TYPE_MVD
);
8862 do_mav_triple_5g (char * str
)
8864 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
8868 do_mav_triple_5h (char * str
)
8870 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
8873 /* Isnsn like "foo W,X,Y,Z".
8874 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
8877 do_mav_quad (char * str
,
8879 enum arm_reg_type reg0
,
8880 enum arm_reg_type reg1
,
8881 enum arm_reg_type reg2
,
8882 enum arm_reg_type reg3
)
8884 int shift0
, shift1
, shift2
, shift3
;
8886 shift0
= mode
& 0xff;
8887 shift1
= (mode
>> 8) & 0xff;
8888 shift2
= (mode
>> 16) & 0xff;
8889 shift3
= (mode
>> 24) & 0xff;
8891 skip_whitespace (str
);
8893 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
8894 || skip_past_comma (&str
) == FAIL
8895 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
8896 || skip_past_comma (&str
) == FAIL
8897 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
8898 || skip_past_comma (&str
) == FAIL
8899 || mav_reg_required_here (&str
, shift3
, reg3
) == FAIL
)
8902 inst
.error
= BAD_ARGS
;
8909 do_mav_quad_6a (char * str
)
8911 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
,
8916 do_mav_quad_6b (char * str
)
8918 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVAX
, REG_TYPE_MVFX
,
8922 /* cfmvsc32<cond> DSPSC,MVDX[15:0]. */
8924 do_mav_dspsc_1 (char * str
)
8926 skip_whitespace (str
);
8929 if (mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
8930 || skip_past_comma (&str
) == FAIL
8931 || mav_reg_required_here (&str
, 12, REG_TYPE_MVDX
) == FAIL
)
8934 inst
.error
= BAD_ARGS
;
8942 /* cfmv32sc<cond> MVDX[15:0],DSPSC. */
8944 do_mav_dspsc_2 (char * str
)
8946 skip_whitespace (str
);
8949 if (mav_reg_required_here (&str
, 12, REG_TYPE_MVDX
) == FAIL
8950 || skip_past_comma (&str
) == FAIL
8951 || mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
)
8954 inst
.error
= BAD_ARGS
;
8962 /* Maverick shift immediate instructions.
8963 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
8964 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
8967 do_mav_shift (char * str
,
8968 enum arm_reg_type reg0
,
8969 enum arm_reg_type reg1
)
8974 skip_whitespace (str
);
8978 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
8979 || skip_past_comma (&str
) == FAIL
8980 || mav_reg_required_here (&str
, 16, reg1
) == FAIL
8981 || skip_past_comma (&str
) == FAIL
)
8984 inst
.error
= BAD_ARGS
;
8988 /* Calculate the immediate operand.
8989 The operand is a 7bit signed number. */
8990 skip_whitespace (str
);
8995 if (!ISDIGIT (*str
) && *str
!= '-')
8997 inst
.error
= _("expecting immediate, 7bit operand");
9007 for (imm
= 0; *str
&& ISDIGIT (*str
); ++str
)
9008 imm
= imm
* 10 + *str
- '0';
9012 inst
.error
= _("immediate out of range");
9016 /* Make negative imm's into 7bit signed numbers. */
9023 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
9024 Bits 5-7 of the insn should have bits 4-6 of the immediate.
9025 Bit 4 should be 0. */
9026 imm
= (imm
& 0xf) | ((imm
& 0x70) << 1);
9028 inst
.instruction
|= imm
;
9033 do_mav_shift_1 (char * str
)
9035 do_mav_shift (str
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
9039 do_mav_shift_2 (char * str
)
9041 do_mav_shift (str
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
9045 mav_parse_offset (char ** str
, int * negative
)
9052 skip_whitespace (p
);
9065 inst
.error
= _("offset expected");
9069 for (offset
= 0; *p
&& ISDIGIT (*p
); ++p
)
9070 offset
= offset
* 10 + *p
- '0';
9074 inst
.error
= _("offset out of range");
9079 inst
.error
= _("offset not a multiple of 4");
9085 return *negative
? -offset
: offset
;
9088 /* Maverick load/store instructions.
9089 <insn><cond> CRd,[Rn,<offset>]{!}.
9090 <insn><cond> CRd,[Rn],<offset>. */
9093 do_mav_ldst (char * str
, enum arm_reg_type reg0
)
9095 int offset
, negative
;
9097 skip_whitespace (str
);
9099 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
9100 || skip_past_comma (&str
) == FAIL
9102 || reg_required_here (&str
, 16) == FAIL
)
9105 if (skip_past_comma (&str
) == SUCCESS
)
9107 /* You are here: "<offset>]{!}". */
9108 inst
.instruction
|= PRE_INDEX
;
9110 offset
= mav_parse_offset (&str
, &negative
);
9117 inst
.error
= _("missing ]");
9123 inst
.instruction
|= WRITE_BACK
;
9129 /* You are here: "], <offset>". */
9132 inst
.error
= _("missing ]");
9136 if (skip_past_comma (&str
) == FAIL
9137 || (offset
= mav_parse_offset (&str
, &negative
), inst
.error
))
9140 inst
.instruction
|= CP_T_WB
; /* Post indexed, set bit W. */
9146 inst
.instruction
|= CP_T_UD
; /* Positive, so set bit U. */
9148 inst
.instruction
|= offset
>> 2;
9154 inst
.error
= BAD_ARGS
;
9158 do_mav_ldst_1 (char * str
)
9160 do_mav_ldst (str
, REG_TYPE_MVF
);
9164 do_mav_ldst_2 (char * str
)
9166 do_mav_ldst (str
, REG_TYPE_MVD
);
9170 do_mav_ldst_3 (char * str
)
9172 do_mav_ldst (str
, REG_TYPE_MVFX
);
9176 do_mav_ldst_4 (char * str
)
9178 do_mav_ldst (str
, REG_TYPE_MVDX
);
9182 do_t_nop (char * str
)
9188 /* Handle the Format 4 instructions that do not have equivalents in other
9189 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
9193 do_t_arit (char * str
)
9197 skip_whitespace (str
);
9199 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9200 || skip_past_comma (&str
) == FAIL
9201 || (Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9203 inst
.error
= BAD_ARGS
;
9207 if (skip_past_comma (&str
) != FAIL
)
9209 /* Three operand format not allowed for TST, CMN, NEG and MVN.
9210 (It isn't allowed for CMP either, but that isn't handled by this
9212 if (inst
.instruction
== T_OPCODE_TST
9213 || inst
.instruction
== T_OPCODE_CMN
9214 || inst
.instruction
== T_OPCODE_NEG
9215 || inst
.instruction
== T_OPCODE_MVN
)
9217 inst
.error
= BAD_ARGS
;
9221 if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9226 inst
.error
= _("dest and source1 must be the same register");
9232 if (inst
.instruction
== T_OPCODE_MUL
9234 as_tsktsk (_("Rs and Rd must be different in MUL"));
9236 inst
.instruction
|= Rd
| (Rs
<< 3);
9241 do_t_add (char * str
)
9243 thumb_add_sub (str
, 0);
9247 do_t_asr (char * str
)
9249 thumb_shift (str
, THUMB_ASR
);
9253 do_t_branch9 (char * str
)
9255 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9257 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH9
;
9258 inst
.reloc
.pc_rel
= 1;
9263 do_t_branch12 (char * str
)
9265 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9267 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH12
;
9268 inst
.reloc
.pc_rel
= 1;
9272 /* Find the real, Thumb encoded start of a Thumb function. */
9275 find_real_start (symbolS
* symbolP
)
9278 const char * name
= S_GET_NAME (symbolP
);
9279 symbolS
* new_target
;
9281 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
9282 #define STUB_NAME ".real_start_of"
9287 /* Names that start with '.' are local labels, not function entry points.
9288 The compiler may generate BL instructions to these labels because it
9289 needs to perform a branch to a far away location. */
9293 real_start
= malloc (strlen (name
) + strlen (STUB_NAME
) + 1);
9294 sprintf (real_start
, "%s%s", STUB_NAME
, name
);
9296 new_target
= symbol_find (real_start
);
9298 if (new_target
== NULL
)
9300 as_warn ("Failed to find real start of function: %s\n", name
);
9301 new_target
= symbolP
;
9310 do_t_branch23 (char * str
)
9312 if (my_get_expression (& inst
.reloc
.exp
, & str
))
9315 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH23
;
9316 inst
.reloc
.pc_rel
= 1;
9319 /* If the destination of the branch is a defined symbol which does not have
9320 the THUMB_FUNC attribute, then we must be calling a function which has
9321 the (interfacearm) attribute. We look for the Thumb entry point to that
9322 function and change the branch to refer to that function instead. */
9323 if ( inst
.reloc
.exp
.X_op
== O_symbol
9324 && inst
.reloc
.exp
.X_add_symbol
!= NULL
9325 && S_IS_DEFINED (inst
.reloc
.exp
.X_add_symbol
)
9326 && ! THUMB_IS_FUNC (inst
.reloc
.exp
.X_add_symbol
))
9327 inst
.reloc
.exp
.X_add_symbol
=
9328 find_real_start (inst
.reloc
.exp
.X_add_symbol
);
9332 do_t_bx (char * str
)
9336 skip_whitespace (str
);
9338 if ((reg
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
9341 /* This sets THUMB_H2 from the top bit of reg. */
9342 inst
.instruction
|= reg
<< 3;
9344 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
9345 should cause the alignment to be checked once it is known. This is
9346 because BX PC only works if the instruction is word aligned. */
9352 do_t_compare (char * str
)
9354 thumb_mov_compare (str
, THUMB_COMPARE
);
9358 do_t_ldmstm (char * str
)
9363 skip_whitespace (str
);
9365 if ((Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9369 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
9373 if (skip_past_comma (&str
) == FAIL
9374 || (range
= reg_list (&str
)) == FAIL
)
9377 inst
.error
= BAD_ARGS
;
9381 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
9383 /* This really doesn't seem worth it. */
9384 inst
.reloc
.type
= BFD_RELOC_NONE
;
9385 inst
.error
= _("expression too complex");
9391 inst
.error
= _("only lo-regs valid in load/store multiple");
9395 inst
.instruction
|= (Rb
<< 8) | range
;
9400 do_t_ldr (char * str
)
9402 thumb_load_store (str
, THUMB_LOAD
, THUMB_WORD
);
9406 do_t_ldrb (char * str
)
9408 thumb_load_store (str
, THUMB_LOAD
, THUMB_BYTE
);
9412 do_t_ldrh (char * str
)
9414 thumb_load_store (str
, THUMB_LOAD
, THUMB_HALFWORD
);
9418 do_t_lds (char * str
)
9422 skip_whitespace (str
);
9424 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9425 || skip_past_comma (&str
) == FAIL
9427 || (Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9428 || skip_past_comma (&str
) == FAIL
9429 || (Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9433 inst
.error
= _("syntax: ldrs[b] Rd, [Rb, Ro]");
9437 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
9442 do_t_lsl (char * str
)
9444 thumb_shift (str
, THUMB_LSL
);
9448 do_t_lsr (char * str
)
9450 thumb_shift (str
, THUMB_LSR
);
9454 do_t_mov (char * str
)
9456 thumb_mov_compare (str
, THUMB_MOVE
);
9460 do_t_push_pop (char * str
)
9464 skip_whitespace (str
);
9466 if ((range
= reg_list (&str
)) == FAIL
)
9469 inst
.error
= BAD_ARGS
;
9473 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
9475 /* This really doesn't seem worth it. */
9476 inst
.reloc
.type
= BFD_RELOC_NONE
;
9477 inst
.error
= _("expression too complex");
9483 if ((inst
.instruction
== T_OPCODE_PUSH
9484 && (range
& ~0xff) == 1 << REG_LR
)
9485 || (inst
.instruction
== T_OPCODE_POP
9486 && (range
& ~0xff) == 1 << REG_PC
))
9488 inst
.instruction
|= THUMB_PP_PC_LR
;
9493 inst
.error
= _("invalid register list to push/pop instruction");
9498 inst
.instruction
|= range
;
9503 do_t_str (char * str
)
9505 thumb_load_store (str
, THUMB_STORE
, THUMB_WORD
);
9509 do_t_strb (char * str
)
9511 thumb_load_store (str
, THUMB_STORE
, THUMB_BYTE
);
9515 do_t_strh (char * str
)
9517 thumb_load_store (str
, THUMB_STORE
, THUMB_HALFWORD
);
9521 do_t_sub (char * str
)
9523 thumb_add_sub (str
, 1);
9527 do_t_swi (char * str
)
9529 skip_whitespace (str
);
9531 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9534 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
9539 do_t_adr (char * str
)
9543 /* This is a pseudo-op of the form "adr rd, label" to be converted
9544 into a relative address of the form "add rd, pc, #label-.-4". */
9545 skip_whitespace (str
);
9547 /* Store Rd in temporary location inside instruction. */
9548 if ((reg
= reg_required_here (&str
, 4)) == FAIL
9549 || (reg
> 7) /* For Thumb reg must be r0..r7. */
9550 || skip_past_comma (&str
) == FAIL
9551 || my_get_expression (&inst
.reloc
.exp
, &str
))
9554 inst
.error
= BAD_ARGS
;
9558 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
9559 inst
.reloc
.exp
.X_add_number
-= 4; /* PC relative adjust. */
9560 inst
.reloc
.pc_rel
= 1;
9561 inst
.instruction
|= REG_PC
; /* Rd is already placed into the instruction. */
9567 insert_reg (const struct reg_entry
* r
,
9568 struct hash_control
* htab
)
9570 int len
= strlen (r
->name
) + 2;
9571 char * buf
= xmalloc (len
);
9572 char * buf2
= xmalloc (len
);
9575 #ifdef REGISTER_PREFIX
9576 buf
[i
++] = REGISTER_PREFIX
;
9579 strcpy (buf
+ i
, r
->name
);
9581 for (i
= 0; buf
[i
]; i
++)
9582 buf2
[i
] = TOUPPER (buf
[i
]);
9586 hash_insert (htab
, buf
, (PTR
) r
);
9587 hash_insert (htab
, buf2
, (PTR
) r
);
9591 build_reg_hsh (struct reg_map
* map
)
9593 const struct reg_entry
*r
;
9595 if ((map
->htab
= hash_new ()) == NULL
)
9596 as_fatal (_("virtual memory exhausted"));
9598 for (r
= map
->names
; r
->name
!= NULL
; r
++)
9599 insert_reg (r
, map
->htab
);
9603 insert_reg_alias (char * str
,
9605 struct hash_control
*htab
)
9608 struct reg_entry
* new = xmalloc (sizeof (struct reg_entry
));
9609 const char * name
= xmalloc (strlen (str
) + 1);
9611 strcpy ((char *) name
, str
);
9614 new->number
= regnum
;
9615 new->builtin
= FALSE
;
9617 error
= hash_insert (htab
, name
, (PTR
) new);
9620 as_bad (_("failed to create an alias for %s, reason: %s"),
9622 free ((char *) name
);
9627 /* Look for the .req directive. This is of the form:
9629 new_register_name .req existing_register_name
9631 If we find one, or if it looks sufficiently like one that we want to
9632 handle any error here, return non-zero. Otherwise return zero. */
9635 create_register_alias (char * newname
, char * p
)
9641 skip_whitespace (q
);
9646 if (*q
&& !strncmp (q
, ".req ", 5))
9651 #ifndef IGNORE_OPCODE_CASE
9652 newname
= original_case_string
;
9654 copy_of_str
= newname
;
9657 skip_whitespace (q
);
9659 for (r
= q
; *r
!= '\0'; r
++)
9665 enum arm_reg_type new_type
, old_type
;
9670 old_type
= arm_reg_parse_any (q
);
9673 new_type
= arm_reg_parse_any (newname
);
9675 if (new_type
== REG_TYPE_MAX
)
9677 if (old_type
!= REG_TYPE_MAX
)
9679 old_regno
= arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
);
9680 insert_reg_alias (newname
, old_regno
,
9681 all_reg_maps
[old_type
].htab
);
9684 as_warn (_("register '%s' does not exist\n"), q
);
9686 else if (old_type
== REG_TYPE_MAX
)
9688 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
9693 /* Do not warn about redefinitions to the same alias. */
9694 if (new_type
!= old_type
9695 || (arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
)
9696 != arm_reg_parse (&q
, all_reg_maps
[new_type
].htab
)))
9697 as_warn (_("ignoring redefinition of register alias '%s'"),
9703 as_warn (_("ignoring incomplete .req pseuso op"));
9714 set_constant_flonums (void)
9718 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
9719 if (atof_ieee ((char *) fp_const
[i
], 'x', fp_values
[i
]) == NULL
)
9724 static const struct asm_opcode insns
[] =
9726 /* Core ARM Instructions. */
9727 {"and", 0xe0000000, 3, ARM_EXT_V1
, do_arit
},
9728 {"ands", 0xe0100000, 3, ARM_EXT_V1
, do_arit
},
9729 {"eor", 0xe0200000, 3, ARM_EXT_V1
, do_arit
},
9730 {"eors", 0xe0300000, 3, ARM_EXT_V1
, do_arit
},
9731 {"sub", 0xe0400000, 3, ARM_EXT_V1
, do_arit
},
9732 {"subs", 0xe0500000, 3, ARM_EXT_V1
, do_arit
},
9733 {"rsb", 0xe0600000, 3, ARM_EXT_V1
, do_arit
},
9734 {"rsbs", 0xe0700000, 3, ARM_EXT_V1
, do_arit
},
9735 {"add", 0xe0800000, 3, ARM_EXT_V1
, do_arit
},
9736 {"adds", 0xe0900000, 3, ARM_EXT_V1
, do_arit
},
9737 {"adc", 0xe0a00000, 3, ARM_EXT_V1
, do_arit
},
9738 {"adcs", 0xe0b00000, 3, ARM_EXT_V1
, do_arit
},
9739 {"sbc", 0xe0c00000, 3, ARM_EXT_V1
, do_arit
},
9740 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1
, do_arit
},
9741 {"rsc", 0xe0e00000, 3, ARM_EXT_V1
, do_arit
},
9742 {"rscs", 0xe0f00000, 3, ARM_EXT_V1
, do_arit
},
9743 {"orr", 0xe1800000, 3, ARM_EXT_V1
, do_arit
},
9744 {"orrs", 0xe1900000, 3, ARM_EXT_V1
, do_arit
},
9745 {"bic", 0xe1c00000, 3, ARM_EXT_V1
, do_arit
},
9746 {"bics", 0xe1d00000, 3, ARM_EXT_V1
, do_arit
},
9748 {"tst", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
9749 {"tsts", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
9750 {"tstp", 0xe110f000, 3, ARM_EXT_V1
, do_cmp
},
9751 {"teq", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
9752 {"teqs", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
9753 {"teqp", 0xe130f000, 3, ARM_EXT_V1
, do_cmp
},
9754 {"cmp", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
9755 {"cmps", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
9756 {"cmpp", 0xe150f000, 3, ARM_EXT_V1
, do_cmp
},
9757 {"cmn", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
9758 {"cmns", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
9759 {"cmnp", 0xe170f000, 3, ARM_EXT_V1
, do_cmp
},
9761 {"mov", 0xe1a00000, 3, ARM_EXT_V1
, do_mov
},
9762 {"movs", 0xe1b00000, 3, ARM_EXT_V1
, do_mov
},
9763 {"mvn", 0xe1e00000, 3, ARM_EXT_V1
, do_mov
},
9764 {"mvns", 0xe1f00000, 3, ARM_EXT_V1
, do_mov
},
9766 {"ldr", 0xe4100000, 3, ARM_EXT_V1
, do_ldst
},
9767 {"ldrb", 0xe4500000, 3, ARM_EXT_V1
, do_ldst
},
9768 {"ldrt", 0xe4300000, 3, ARM_EXT_V1
, do_ldstt
},
9769 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1
, do_ldstt
},
9770 {"str", 0xe4000000, 3, ARM_EXT_V1
, do_ldst
},
9771 {"strb", 0xe4400000, 3, ARM_EXT_V1
, do_ldst
},
9772 {"strt", 0xe4200000, 3, ARM_EXT_V1
, do_ldstt
},
9773 {"strbt", 0xe4600000, 3, ARM_EXT_V1
, do_ldstt
},
9775 {"stmia", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
9776 {"stmib", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
9777 {"stmda", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
9778 {"stmdb", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
9779 {"stmfd", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
9780 {"stmfa", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
9781 {"stmea", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
9782 {"stmed", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
9784 {"ldmia", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
9785 {"ldmib", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
9786 {"ldmda", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
9787 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
9788 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
9789 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
9790 {"ldmea", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
9791 {"ldmed", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
9793 {"swi", 0xef000000, 3, ARM_EXT_V1
, do_swi
},
9795 /* XXX This is the wrong place to do this. Think multi-arch. */
9796 {"bl", 0xeb000000, 2, ARM_EXT_V1
, do_branch
},
9797 {"b", 0xea000000, 1, ARM_EXT_V1
, do_branch
},
9799 {"bl", 0xebfffffe, 2, ARM_EXT_V1
, do_branch
},
9800 {"b", 0xeafffffe, 1, ARM_EXT_V1
, do_branch
},
9804 {"adr", 0xe28f0000, 3, ARM_EXT_V1
, do_adr
},
9805 {"adrl", 0xe28f0000, 3, ARM_EXT_V1
, do_adrl
},
9806 {"nop", 0xe1a00000, 3, ARM_EXT_V1
, do_nop
},
9808 /* ARM 2 multiplies. */
9809 {"mul", 0xe0000090, 3, ARM_EXT_V2
, do_mul
},
9810 {"muls", 0xe0100090, 3, ARM_EXT_V2
, do_mul
},
9811 {"mla", 0xe0200090, 3, ARM_EXT_V2
, do_mla
},
9812 {"mlas", 0xe0300090, 3, ARM_EXT_V2
, do_mla
},
9814 /* Generic coprocessor instructions. */
9815 {"cdp", 0xee000000, 3, ARM_EXT_V2
, do_cdp
},
9816 {"ldc", 0xec100000, 3, ARM_EXT_V2
, do_lstc
},
9817 {"ldcl", 0xec500000, 3, ARM_EXT_V2
, do_lstc
},
9818 {"stc", 0xec000000, 3, ARM_EXT_V2
, do_lstc
},
9819 {"stcl", 0xec400000, 3, ARM_EXT_V2
, do_lstc
},
9820 {"mcr", 0xee000010, 3, ARM_EXT_V2
, do_co_reg
},
9821 {"mrc", 0xee100010, 3, ARM_EXT_V2
, do_co_reg
},
9823 /* ARM 3 - swp instructions. */
9824 {"swp", 0xe1000090, 3, ARM_EXT_V2S
, do_swap
},
9825 {"swpb", 0xe1400090, 3, ARM_EXT_V2S
, do_swap
},
9827 /* ARM 6 Status register instructions. */
9828 {"mrs", 0xe10f0000, 3, ARM_EXT_V3
, do_mrs
},
9829 {"msr", 0xe120f000, 3, ARM_EXT_V3
, do_msr
},
9830 /* ScottB: our code uses 0xe128f000 for msr.
9831 NickC: but this is wrong because the bits 16 through 19 are
9832 handled by the PSR_xxx defines above. */
9834 /* ARM 7M long multiplies. */
9835 {"smull", 0xe0c00090, 5, ARM_EXT_V3M
, do_mull
},
9836 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M
, do_mull
},
9837 {"umull", 0xe0800090, 5, ARM_EXT_V3M
, do_mull
},
9838 {"umulls", 0xe0900090, 5, ARM_EXT_V3M
, do_mull
},
9839 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M
, do_mull
},
9840 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M
, do_mull
},
9841 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M
, do_mull
},
9842 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M
, do_mull
},
9844 /* ARM Architecture 4. */
9845 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4
, do_ldstv4
},
9846 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4
, do_ldstv4
},
9847 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4
, do_ldstv4
},
9848 {"strh", 0xe00000b0, 3, ARM_EXT_V4
, do_ldstv4
},
9850 /* ARM Architecture 4T. */
9851 /* Note: bx (and blx) are required on V5, even if the processor does
9852 not support Thumb. */
9853 {"bx", 0xe12fff10, 2, ARM_EXT_V4T
| ARM_EXT_V5
, do_bx
},
9855 /* ARM Architecture 5T. */
9856 /* Note: blx has 2 variants, so the .value is set dynamically.
9857 Only one of the variants has conditional execution. */
9858 {"blx", 0xe0000000, 3, ARM_EXT_V5
, do_blx
},
9859 {"clz", 0xe16f0f10, 3, ARM_EXT_V5
, do_clz
},
9860 {"bkpt", 0xe1200070, 0, ARM_EXT_V5
, do_bkpt
},
9861 {"ldc2", 0xfc100000, 0, ARM_EXT_V5
, do_lstc2
},
9862 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5
, do_lstc2
},
9863 {"stc2", 0xfc000000, 0, ARM_EXT_V5
, do_lstc2
},
9864 {"stc2l", 0xfc400000, 0, ARM_EXT_V5
, do_lstc2
},
9865 {"cdp2", 0xfe000000, 0, ARM_EXT_V5
, do_cdp2
},
9866 {"mcr2", 0xfe000010, 0, ARM_EXT_V5
, do_co_reg2
},
9867 {"mrc2", 0xfe100010, 0, ARM_EXT_V5
, do_co_reg2
},
9869 /* ARM Architecture 5TExP. */
9870 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP
, do_smla
},
9871 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP
, do_smla
},
9872 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP
, do_smla
},
9873 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP
, do_smla
},
9875 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP
, do_smla
},
9876 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP
, do_smla
},
9878 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP
, do_smlal
},
9879 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP
, do_smlal
},
9880 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP
, do_smlal
},
9881 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP
, do_smlal
},
9883 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP
, do_smul
},
9884 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP
, do_smul
},
9885 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP
, do_smul
},
9886 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP
, do_smul
},
9888 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP
, do_smul
},
9889 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP
, do_smul
},
9891 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP
, do_qadd
},
9892 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP
, do_qadd
},
9893 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP
, do_qadd
},
9894 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP
, do_qadd
},
9896 /* ARM Architecture 5TE. */
9897 {"pld", 0xf450f000, 0, ARM_EXT_V5E
, do_pld
},
9898 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E
, do_ldrd
},
9899 {"strd", 0xe00000f0, 3, ARM_EXT_V5E
, do_ldrd
},
9901 {"mcrr", 0xec400000, 4, ARM_EXT_V5E
, do_co_reg2c
},
9902 {"mrrc", 0xec500000, 4, ARM_EXT_V5E
, do_co_reg2c
},
9904 /* ARM Architecture 5TEJ. */
9905 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J
, do_bxj
},
9908 { "cps", 0xf1020000, 0, ARM_EXT_V6
, do_cps
},
9909 { "cpsie", 0xf1080000, 0, ARM_EXT_V6
, do_cpsi
},
9910 { "cpsid", 0xf10C0000, 0, ARM_EXT_V6
, do_cpsi
},
9911 { "ldrex", 0xe1900f9f, 5, ARM_EXT_V6
, do_ldrex
},
9912 { "mcrr2", 0xfc400000, 0, ARM_EXT_V6
, do_co_reg2c
},
9913 { "mrrc2", 0xfc500000, 0, ARM_EXT_V6
, do_co_reg2c
},
9914 { "pkhbt", 0xe6800010, 5, ARM_EXT_V6
, do_pkhbt
},
9915 { "pkhtb", 0xe6800050, 5, ARM_EXT_V6
, do_pkhtb
},
9916 { "qadd16", 0xe6200f10, 6, ARM_EXT_V6
, do_qadd16
},
9917 { "qadd8", 0xe6200f90, 5, ARM_EXT_V6
, do_qadd16
},
9918 { "qaddsubx", 0xe6200f30, 8, ARM_EXT_V6
, do_qadd16
},
9919 { "qsub16", 0xe6200f70, 6, ARM_EXT_V6
, do_qadd16
},
9920 { "qsub8", 0xe6200ff0, 5, ARM_EXT_V6
, do_qadd16
},
9921 { "qsubaddx", 0xe6200f50, 8, ARM_EXT_V6
, do_qadd16
},
9922 { "sadd16", 0xe6100f10, 6, ARM_EXT_V6
, do_qadd16
},
9923 { "sadd8", 0xe6100f90, 5, ARM_EXT_V6
, do_qadd16
},
9924 { "saddsubx", 0xe6100f30, 8, ARM_EXT_V6
, do_qadd16
},
9925 { "shadd16", 0xe6300f10, 7, ARM_EXT_V6
, do_qadd16
},
9926 { "shadd8", 0xe6300f90, 6, ARM_EXT_V6
, do_qadd16
},
9927 { "shaddsubx", 0xe6300f30, 9, ARM_EXT_V6
, do_qadd16
},
9928 { "shsub16", 0xe6300f70, 7, ARM_EXT_V6
, do_qadd16
},
9929 { "shsub8", 0xe6300ff0, 6, ARM_EXT_V6
, do_qadd16
},
9930 { "shsubaddx", 0xe6300f50, 9, ARM_EXT_V6
, do_qadd16
},
9931 { "ssub16", 0xe6100f70, 6, ARM_EXT_V6
, do_qadd16
},
9932 { "ssub8", 0xe6100ff0, 5, ARM_EXT_V6
, do_qadd16
},
9933 { "ssubaddx", 0xe6100f50, 8, ARM_EXT_V6
, do_qadd16
},
9934 { "uadd16", 0xe6500f10, 6, ARM_EXT_V6
, do_qadd16
},
9935 { "uadd8", 0xe6500f90, 5, ARM_EXT_V6
, do_qadd16
},
9936 { "uaddsubx", 0xe6500f30, 8, ARM_EXT_V6
, do_qadd16
},
9937 { "uhadd16", 0xe6700f10, 7, ARM_EXT_V6
, do_qadd16
},
9938 { "uhadd8", 0xe6700f90, 6, ARM_EXT_V6
, do_qadd16
},
9939 { "uhaddsubx", 0xe6700f30, 9, ARM_EXT_V6
, do_qadd16
},
9940 { "uhsub16", 0xe6700f70, 7, ARM_EXT_V6
, do_qadd16
},
9941 { "uhsub8", 0xe6700ff0, 6, ARM_EXT_V6
, do_qadd16
},
9942 { "uhsubaddx", 0xe6700f50, 9, ARM_EXT_V6
, do_qadd16
},
9943 { "uqadd16", 0xe6600f10, 7, ARM_EXT_V6
, do_qadd16
},
9944 { "uqadd8", 0xe6600f90, 6, ARM_EXT_V6
, do_qadd16
},
9945 { "uqaddsubx", 0xe6600f30, 9, ARM_EXT_V6
, do_qadd16
},
9946 { "uqsub16", 0xe6600f70, 7, ARM_EXT_V6
, do_qadd16
},
9947 { "uqsub8", 0xe6600ff0, 6, ARM_EXT_V6
, do_qadd16
},
9948 { "uqsubaddx", 0xe6600f50, 9, ARM_EXT_V6
, do_qadd16
},
9949 { "usub16", 0xe6500f70, 6, ARM_EXT_V6
, do_qadd16
},
9950 { "usub8", 0xe6500ff0, 5, ARM_EXT_V6
, do_qadd16
},
9951 { "usubaddx", 0xe6500f50, 8, ARM_EXT_V6
, do_qadd16
},
9952 { "rev", 0xe6bf0f30, 3, ARM_EXT_V6
, do_rev
},
9953 { "rev16", 0xe6bf0fb0, 5, ARM_EXT_V6
, do_rev
},
9954 { "revsh", 0xe6ff0fb0, 5, ARM_EXT_V6
, do_rev
},
9955 { "rfeia", 0xf8900a00, 0, ARM_EXT_V6
, do_rfe
},
9956 { "rfeib", 0xf9900a00, 0, ARM_EXT_V6
, do_rfe
},
9957 { "rfeda", 0xf8100a00, 0, ARM_EXT_V6
, do_rfe
},
9958 { "rfedb", 0xf9100a00, 0, ARM_EXT_V6
, do_rfe
},
9959 { "rfefd", 0xf8900a00, 0, ARM_EXT_V6
, do_rfe
},
9960 { "rfefa", 0xf9900a00, 0, ARM_EXT_V6
, do_rfe
},
9961 { "rfeea", 0xf8100a00, 0, ARM_EXT_V6
, do_rfe
},
9962 { "rfeed", 0xf9100a00, 0, ARM_EXT_V6
, do_rfe
},
9963 { "sxtah", 0xe6b00070, 5, ARM_EXT_V6
, do_sxtah
},
9964 { "sxtab16", 0xe6800070, 7, ARM_EXT_V6
, do_sxtah
},
9965 { "sxtab", 0xe6a00070, 5, ARM_EXT_V6
, do_sxtah
},
9966 { "sxth", 0xe6bf0070, 4, ARM_EXT_V6
, do_sxth
},
9967 { "sxtb16", 0xe68f0070, 6, ARM_EXT_V6
, do_sxth
},
9968 { "sxtb", 0xe6af0070, 4, ARM_EXT_V6
, do_sxth
},
9969 { "uxtah", 0xe6f00070, 5, ARM_EXT_V6
, do_sxtah
},
9970 { "uxtab16", 0xe6c00070, 7, ARM_EXT_V6
, do_sxtah
},
9971 { "uxtab", 0xe6e00070, 5, ARM_EXT_V6
, do_sxtah
},
9972 { "uxth", 0xe6ff0070, 4, ARM_EXT_V6
, do_sxth
},
9973 { "uxtb16", 0xe6cf0070, 6, ARM_EXT_V6
, do_sxth
},
9974 { "uxtb", 0xe6ef0070, 4, ARM_EXT_V6
, do_sxth
},
9975 { "sel", 0xe68000b0, 3, ARM_EXT_V6
, do_qadd16
},
9976 { "setend", 0xf1010000, 0, ARM_EXT_V6
, do_setend
},
9977 { "smlad", 0xe7000010, 5, ARM_EXT_V6
, do_smlad
},
9978 { "smladx", 0xe7000030, 6, ARM_EXT_V6
, do_smlad
},
9979 { "smlald", 0xe7400010, 6, ARM_EXT_V6
, do_smlald
},
9980 { "smlaldx", 0xe7400030, 7, ARM_EXT_V6
, do_smlald
},
9981 { "smlsd", 0xe7000050, 5, ARM_EXT_V6
, do_smlad
},
9982 { "smlsdx", 0xe7000070, 6, ARM_EXT_V6
, do_smlad
},
9983 { "smlsld", 0xe7400050, 6, ARM_EXT_V6
, do_smlald
},
9984 { "smlsldx", 0xe7400070, 7, ARM_EXT_V6
, do_smlald
},
9985 { "smmla", 0xe7500010, 5, ARM_EXT_V6
, do_smlad
},
9986 { "smmlar", 0xe7500030, 6, ARM_EXT_V6
, do_smlad
},
9987 { "smmls", 0xe75000d0, 5, ARM_EXT_V6
, do_smlad
},
9988 { "smmlsr", 0xe75000f0, 6, ARM_EXT_V6
, do_smlad
},
9989 { "smmul", 0xe750f010, 5, ARM_EXT_V6
, do_smmul
},
9990 { "smmulr", 0xe750f030, 6, ARM_EXT_V6
, do_smmul
},
9991 { "smuad", 0xe700f010, 5, ARM_EXT_V6
, do_smmul
},
9992 { "smuadx", 0xe700f030, 6, ARM_EXT_V6
, do_smmul
},
9993 { "smusd", 0xe700f050, 5, ARM_EXT_V6
, do_smmul
},
9994 { "smusdx", 0xe700f070, 6, ARM_EXT_V6
, do_smmul
},
9995 { "srsia", 0xf8cd0500, 0, ARM_EXT_V6
, do_srs
},
9996 { "srsib", 0xf9cd0500, 0, ARM_EXT_V6
, do_srs
},
9997 { "srsda", 0xf84d0500, 0, ARM_EXT_V6
, do_srs
},
9998 { "srsdb", 0xf94d0500, 0, ARM_EXT_V6
, do_srs
},
9999 { "ssat", 0xe6a00010, 4, ARM_EXT_V6
, do_ssat
},
10000 { "ssat16", 0xe6a00f30, 6, ARM_EXT_V6
, do_ssat16
},
10001 { "strex", 0xe1800f90, 5, ARM_EXT_V6
, do_strex
},
10002 { "umaal", 0xe0400090, 5, ARM_EXT_V6
, do_umaal
},
10003 { "usad8", 0xe780f010, 5, ARM_EXT_V6
, do_smmul
},
10004 { "usada8", 0xe7800010, 6, ARM_EXT_V6
, do_smlad
},
10005 { "usat", 0xe6e00010, 4, ARM_EXT_V6
, do_usat
},
10006 { "usat16", 0xe6e00f30, 6, ARM_EXT_V6
, do_usat16
},
10009 { "clrex", 0xf57ff01f, 0, ARM_EXT_V6K
, do_empty
},
10010 { "ldrexb", 0xe1d00f9f, 6, ARM_EXT_V6K
, do_ldrex
},
10011 { "ldrexd", 0xe1b00f9f, 6, ARM_EXT_V6K
, do_ldrex
},
10012 { "ldrexh", 0xe1f00f9f, 6, ARM_EXT_V6K
, do_ldrex
},
10013 { "sev", 0xe320f004, 3, ARM_EXT_V6K
, do_empty
},
10014 { "strexb", 0xe1c00f90, 6, ARM_EXT_V6K
, do_strex
},
10015 { "strexd", 0xe1a00f90, 6, ARM_EXT_V6K
, do_strex
},
10016 { "strexh", 0xe1e00f90, 6, ARM_EXT_V6K
, do_strex
},
10017 { "wfe", 0xe320f002, 3, ARM_EXT_V6K
, do_empty
},
10018 { "wfi", 0xe320f003, 3, ARM_EXT_V6K
, do_empty
},
10019 { "yield", 0xe320f001, 5, ARM_EXT_V6K
, do_empty
},
10022 { "smi", 0xe1600070, 3, ARM_EXT_V6Z
, do_smi
},
10024 /* Core FPA instruction set (V1). */
10025 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
10026 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
10027 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
10028 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
10030 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10031 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10032 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10033 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10035 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10036 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10037 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10038 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10040 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10041 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10042 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10043 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10044 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10045 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10046 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10047 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10048 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10049 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10050 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10051 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10053 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10054 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10055 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10056 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10057 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10058 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10059 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10060 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10061 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10062 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10063 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10064 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10066 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10067 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10068 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10069 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10070 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10071 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10072 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10073 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10074 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10075 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10076 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10077 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10079 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10080 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10081 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10082 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10083 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10084 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10085 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10086 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10087 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10088 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10089 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10090 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10092 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10093 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10094 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10095 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10096 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10097 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10098 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10099 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10100 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10101 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10102 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10103 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10105 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10106 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10107 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10108 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10109 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10110 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10111 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10112 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10113 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10114 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10115 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10116 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10118 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10119 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10120 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10121 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10122 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10123 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10124 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10125 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10126 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10127 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10128 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10129 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10131 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10132 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10133 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10134 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10135 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10136 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10137 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10138 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10139 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10140 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10141 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10142 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10144 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10145 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10146 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10147 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10148 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10149 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10150 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10151 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10152 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10153 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10154 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10155 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10157 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10158 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10159 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10160 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10161 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10162 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10163 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10164 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10165 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10166 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10167 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10168 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10170 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10171 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10172 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10173 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10174 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10175 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10176 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10177 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10178 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10179 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10180 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10181 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10183 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10184 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10185 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10186 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10187 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10188 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10189 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10190 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10191 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10192 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10193 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10194 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10196 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10197 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10198 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10199 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10200 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10201 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10202 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10203 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10204 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10205 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10206 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10207 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10209 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10210 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10211 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10212 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10213 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10214 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10215 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10216 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10217 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10218 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10219 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10220 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10222 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10223 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10224 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10225 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10226 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10227 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10228 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10229 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10230 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10231 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10232 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10233 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10235 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10236 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10237 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10238 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10239 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10240 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10241 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10242 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10243 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10244 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10245 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10246 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10248 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10249 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10250 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10251 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10252 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10253 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10254 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10255 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10256 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10257 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10258 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10259 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10261 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10262 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10263 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10264 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10265 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10266 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10267 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10268 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10269 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10270 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10271 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10272 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10274 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10275 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10276 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10277 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10278 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10279 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10280 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10281 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10282 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10283 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10284 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10285 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10287 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10288 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10289 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10290 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10291 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10292 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10293 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10294 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10295 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10296 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10297 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10298 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10300 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10301 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10302 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10303 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10304 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10305 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10306 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10307 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10308 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10309 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10310 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10311 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10313 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10314 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10315 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10316 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10317 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10318 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10319 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10320 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10321 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10322 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10323 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10324 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10326 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10327 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10328 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10329 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10330 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10331 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10332 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10333 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10334 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10335 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10336 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10337 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10339 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10340 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10341 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10342 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10343 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10344 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10345 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10346 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10347 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10348 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10349 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10350 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10352 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10353 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10354 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10355 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10356 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10357 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10358 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10359 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10360 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10361 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10362 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10363 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10365 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10366 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10367 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10368 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10369 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10370 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10371 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10372 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10373 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10374 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10375 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10376 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10378 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10379 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10380 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10381 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10382 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10383 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10384 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10385 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10386 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10387 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10388 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10389 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10391 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10392 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10393 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10394 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10395 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10396 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10397 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10398 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10399 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10400 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10401 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10402 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10404 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10405 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10406 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10407 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10408 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10409 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10410 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10411 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10412 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10413 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10414 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10415 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10417 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10418 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10419 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10420 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10421 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
10422 not be an optional suffix, but part of the instruction. To be
10423 compatible, we accept either. */
10424 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10425 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10427 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10428 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10429 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10430 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10431 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10432 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10433 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10434 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10435 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10436 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10437 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10438 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10440 /* The implementation of the FIX instruction is broken on some
10441 assemblers, in that it accepts a precision specifier as well as a
10442 rounding specifier, despite the fact that this is meaningless.
10443 To be more compatible, we accept it as well, though of course it
10444 does not set any bits. */
10445 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10446 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10447 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10448 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10449 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10450 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10451 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10452 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10453 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10454 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10455 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10456 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10457 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10459 /* Instructions that were new with the real FPA, call them V2. */
10460 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10461 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10462 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10463 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10464 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10465 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10467 /* VFP V1xD (single precision). */
10468 /* Moves and type conversions. */
10469 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10470 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_reg_from_sp
},
10471 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_from_reg
},
10472 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD
, do_empty
},
10473 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10474 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10475 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10476 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10477 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10478 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10479 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_reg_from_ctrl
},
10480 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_ctrl_from_reg
},
10482 /* Memory operations. */
10483 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldst
},
10484 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldst
},
10485 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
10486 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
10487 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
10488 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
10489 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
10490 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
10491 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
10492 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
10493 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
10494 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
10495 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
10496 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
10497 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
10498 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
10499 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
10500 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
10502 /* Monadic operations. */
10503 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10504 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10505 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10507 /* Dyadic operations. */
10508 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10509 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10510 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10511 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10512 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10513 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10514 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10515 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10516 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10519 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10520 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_compare_z
},
10521 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10522 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_compare_z
},
10524 /* VFP V1 (Double precision). */
10525 /* Moves and type conversions. */
10526 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10527 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
10528 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10529 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1
, do_vfp_dp_from_reg
},
10530 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1
, do_vfp_dp_from_reg
},
10531 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1
, do_vfp_reg_from_dp
},
10532 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1
, do_vfp_reg_from_dp
},
10533 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
10534 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
10535 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10536 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10537 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10538 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10540 /* Memory operations. */
10541 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1
, do_vfp_dp_ldst
},
10542 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1
, do_vfp_dp_ldst
},
10543 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
10544 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
10545 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
10546 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
10547 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
10548 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
10549 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
10550 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
10552 /* Monadic operations. */
10553 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10554 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10555 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10557 /* Dyadic operations. */
10558 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10559 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10560 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10561 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10562 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10563 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10564 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10565 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10566 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10569 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10570 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_compare_z
},
10571 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10572 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1
, do_vfp_dp_compare_z
},
10575 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2
, do_vfp_sp2_from_reg2
},
10576 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2
, do_vfp_reg2_from_sp2
},
10577 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2
, do_vfp_dp_from_reg2
},
10578 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2
, do_vfp_reg2_from_dp
},
10580 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
10581 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE
, do_xsc_mia
},
10582 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10583 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10584 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10585 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10586 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10587 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE
, do_xsc_mar
},
10588 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE
, do_xsc_mra
},
10590 /* Intel Wireless MMX technology instructions. */
10591 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
10592 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
10593 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
10594 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
10595 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
10596 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
10597 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
10598 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
10599 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
10600 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10601 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10602 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10603 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10604 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10605 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10606 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
10607 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
10608 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
10609 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmcr
},
10610 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_tmcrr
},
10611 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10612 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10613 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10614 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10615 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10616 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10617 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
10618 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
10619 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
10620 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmrc
},
10621 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_tmrrc
},
10622 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
10623 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
10624 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
10625 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10626 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10627 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10628 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10629 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10630 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10631 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10632 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10633 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10634 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10635 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10636 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10637 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_waligni
},
10638 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10639 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10640 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10641 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10642 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10643 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10644 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10645 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10646 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10647 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10648 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10649 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10650 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10651 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10652 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10653 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10654 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10655 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10656 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10657 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
10658 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
10659 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
10660 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
10661 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10662 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10663 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10664 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10665 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10666 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10667 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10668 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10669 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10670 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10671 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10672 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10673 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10674 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10675 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10676 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10677 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10678 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10679 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wmov
},
10680 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10681 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10682 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10683 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10684 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10685 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10686 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10687 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10688 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10689 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10690 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10691 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10692 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10693 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10694 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10695 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10696 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10697 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10698 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10699 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10700 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10701 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wshufh
},
10702 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10703 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10704 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10705 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10706 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10707 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10708 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10709 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10710 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10711 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10712 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10713 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10714 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10715 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10716 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10717 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10718 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10719 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10720 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
10721 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
10722 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
10723 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
10724 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10725 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10726 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10727 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10728 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10729 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10730 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10731 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10732 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10733 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10734 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10735 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10736 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10737 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10738 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10739 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10740 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10741 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10742 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10743 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10744 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10745 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10746 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10747 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10748 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10749 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10750 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10751 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10752 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wzero
},
10754 /* Cirrus Maverick instructions. */
10755 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_1
},
10756 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_2
},
10757 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_3
},
10758 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_4
},
10759 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_1
},
10760 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_2
},
10761 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_3
},
10762 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_4
},
10763 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK
, do_mav_binops_2a
},
10764 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1a
},
10765 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK
, do_mav_binops_2b
},
10766 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1b
},
10767 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK
, do_mav_binops_2b
},
10768 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1b
},
10769 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK
, do_mav_binops_2c
},
10770 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1c
},
10771 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK
, do_mav_binops_2c
},
10772 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1c
},
10773 {"cfmval32", 0xee200440, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
10774 {"cfmv32al", 0xee100440, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
10775 {"cfmvam32", 0xee200460, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
10776 {"cfmv32am", 0xee100460, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
10777 {"cfmvah32", 0xee200480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
10778 {"cfmv32ah", 0xee100480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
10779 {"cfmva32", 0xee2004a0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
10780 {"cfmv32a", 0xee1004a0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
10781 {"cfmva64", 0xee2004c0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3c
},
10782 {"cfmv64a", 0xee1004c0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3d
},
10783 {"cfmvsc32", 0xee2004e0, 8, ARM_CEXT_MAVERICK
, do_mav_dspsc_1
},
10784 {"cfmv32sc", 0xee1004e0, 8, ARM_CEXT_MAVERICK
, do_mav_dspsc_2
},
10785 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
10786 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
10787 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1f
},
10788 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1g
},
10789 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1h
},
10790 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1i
},
10791 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1j
},
10792 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1k
},
10793 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1l
},
10794 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1m
},
10795 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK
, do_mav_binops_1l
},
10796 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK
, do_mav_binops_1m
},
10797 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK
, do_mav_triple_4a
},
10798 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK
, do_mav_triple_4b
},
10799 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK
, do_mav_shift_1
},
10800 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK
, do_mav_shift_2
},
10801 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5a
},
10802 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5b
},
10803 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5c
},
10804 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5d
},
10805 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
10806 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
10807 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
10808 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
10809 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
10810 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
10811 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
10812 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
10813 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
10814 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
10815 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1n
},
10816 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1o
},
10817 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1n
},
10818 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1o
},
10819 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
10820 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
10821 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
10822 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
10823 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
10824 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
10825 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
10826 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
10827 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK
, do_mav_quad_6a
},
10828 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK
, do_mav_quad_6a
},
10829 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK
, do_mav_quad_6b
},
10830 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK
, do_mav_quad_6b
},
10833 /* Iterate over the base tables to create the instruction patterns. */
10836 build_arm_ops_hsh (void)
10840 static struct obstack insn_obstack
;
10842 obstack_begin (&insn_obstack
, 4000);
10844 for (i
= 0; i
< sizeof (insns
) / sizeof (struct asm_opcode
); i
++)
10846 const struct asm_opcode
*insn
= insns
+ i
;
10848 if (insn
->cond_offset
!= 0)
10850 /* Insn supports conditional execution. Build the varaints
10851 and insert them in the hash table. */
10852 for (j
= 0; j
< sizeof (conds
) / sizeof (struct asm_cond
); j
++)
10854 unsigned len
= strlen (insn
->template);
10855 struct asm_opcode
*new;
10858 new = obstack_alloc (&insn_obstack
, sizeof (struct asm_opcode
));
10859 /* All condition codes are two characters. */
10860 template = obstack_alloc (&insn_obstack
, len
+ 3);
10862 strncpy (template, insn
->template, insn
->cond_offset
);
10863 strcpy (template + insn
->cond_offset
, conds
[j
].template);
10864 if (len
> insn
->cond_offset
)
10865 strcpy (template + insn
->cond_offset
+ 2,
10866 insn
->template + insn
->cond_offset
);
10867 new->template = template;
10868 new->cond_offset
= 0;
10869 new->variant
= insn
->variant
;
10870 new->parms
= insn
->parms
;
10871 new->value
= (insn
->value
& ~COND_MASK
) | conds
[j
].value
;
10873 hash_insert (arm_ops_hsh
, new->template, (PTR
) new);
10876 /* Finally, insert the unconditional insn in the table directly;
10877 no need to build a copy. */
10878 hash_insert (arm_ops_hsh
, insn
->template, (PTR
) insn
);
10882 #if 0 /* Suppressed - for now. */
10883 #if defined OBJ_ELF || defined OBJ_COFF
10886 #define arm_Note Elf_External_Note
10890 unsigned char namesz
[4]; /* Size of entry's owner string. */
10891 unsigned char descsz
[4]; /* Size of the note descriptor. */
10892 unsigned char type
[4]; /* Interpretation of the descriptor. */
10893 char name
[1]; /* Start of the name+desc data. */
10897 /* The description is kept to a fix sized in order to make updating
10898 it and merging it easier. */
10899 #define ARM_NOTE_DESCRIPTION_LENGTH 8
10902 arm_add_note (const char * name
,
10903 const char * description
,
10906 arm_Note note ATTRIBUTE_UNUSED
;
10908 unsigned int name_len
;
10910 name_len
= (strlen (name
) + 1 + 3) & ~3;
10912 p
= frag_more (sizeof (note
.namesz
));
10913 md_number_to_chars (p
, (valueT
) name_len
, sizeof (note
.namesz
));
10915 p
= frag_more (sizeof (note
.descsz
));
10916 md_number_to_chars (p
, (valueT
) ARM_NOTE_DESCRIPTION_LENGTH
, sizeof (note
.descsz
));
10918 p
= frag_more (sizeof (note
.type
));
10919 md_number_to_chars (p
, (valueT
) type
, sizeof (note
.type
));
10921 p
= frag_more (name_len
);
10924 p
= frag_more (ARM_NOTE_DESCRIPTION_LENGTH
);
10925 strncpy (p
, description
, ARM_NOTE_DESCRIPTION_LENGTH
);
10926 frag_align (2, 0, 0);
10932 static const struct thumb_opcode tinsns
[] =
10934 /* Thumb v1 (ARMv4T). */
10935 {"adc", 0x4140, 2, ARM_EXT_V4T
, do_t_arit
},
10936 {"add", 0x0000, 2, ARM_EXT_V4T
, do_t_add
},
10937 {"and", 0x4000, 2, ARM_EXT_V4T
, do_t_arit
},
10938 {"asr", 0x0000, 2, ARM_EXT_V4T
, do_t_asr
},
10939 {"b", T_OPCODE_BRANCH
, 2, ARM_EXT_V4T
, do_t_branch12
},
10940 {"beq", 0xd0fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10941 {"bne", 0xd1fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10942 {"bcs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10943 {"bhs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10944 {"bcc", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10945 {"bul", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10946 {"blo", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10947 {"bmi", 0xd4fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10948 {"bpl", 0xd5fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10949 {"bvs", 0xd6fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10950 {"bvc", 0xd7fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10951 {"bhi", 0xd8fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10952 {"bls", 0xd9fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10953 {"bge", 0xdafe, 2, ARM_EXT_V4T
, do_t_branch9
},
10954 {"blt", 0xdbfe, 2, ARM_EXT_V4T
, do_t_branch9
},
10955 {"bgt", 0xdcfe, 2, ARM_EXT_V4T
, do_t_branch9
},
10956 {"ble", 0xddfe, 2, ARM_EXT_V4T
, do_t_branch9
},
10957 {"bal", 0xdefe, 2, ARM_EXT_V4T
, do_t_branch9
},
10958 {"bic", 0x4380, 2, ARM_EXT_V4T
, do_t_arit
},
10959 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T
, do_t_branch23
},
10960 {"bx", 0x4700, 2, ARM_EXT_V4T
, do_t_bx
},
10961 {"cmn", T_OPCODE_CMN
, 2, ARM_EXT_V4T
, do_t_arit
},
10962 {"cmp", 0x0000, 2, ARM_EXT_V4T
, do_t_compare
},
10963 {"eor", 0x4040, 2, ARM_EXT_V4T
, do_t_arit
},
10964 {"ldmia", 0xc800, 2, ARM_EXT_V4T
, do_t_ldmstm
},
10965 {"ldr", 0x0000, 2, ARM_EXT_V4T
, do_t_ldr
},
10966 {"ldrb", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrb
},
10967 {"ldrh", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrh
},
10968 {"ldrsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
10969 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
10970 {"ldsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
10971 {"ldsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
10972 {"lsl", 0x0000, 2, ARM_EXT_V4T
, do_t_lsl
},
10973 {"lsr", 0x0000, 2, ARM_EXT_V4T
, do_t_lsr
},
10974 {"mov", 0x0000, 2, ARM_EXT_V4T
, do_t_mov
},
10975 {"mul", T_OPCODE_MUL
, 2, ARM_EXT_V4T
, do_t_arit
},
10976 {"mvn", T_OPCODE_MVN
, 2, ARM_EXT_V4T
, do_t_arit
},
10977 {"neg", T_OPCODE_NEG
, 2, ARM_EXT_V4T
, do_t_arit
},
10978 {"orr", 0x4300, 2, ARM_EXT_V4T
, do_t_arit
},
10979 {"pop", 0xbc00, 2, ARM_EXT_V4T
, do_t_push_pop
},
10980 {"push", 0xb400, 2, ARM_EXT_V4T
, do_t_push_pop
},
10981 {"ror", 0x41c0, 2, ARM_EXT_V4T
, do_t_arit
},
10982 {"sbc", 0x4180, 2, ARM_EXT_V4T
, do_t_arit
},
10983 {"stmia", 0xc000, 2, ARM_EXT_V4T
, do_t_ldmstm
},
10984 {"str", 0x0000, 2, ARM_EXT_V4T
, do_t_str
},
10985 {"strb", 0x0000, 2, ARM_EXT_V4T
, do_t_strb
},
10986 {"strh", 0x0000, 2, ARM_EXT_V4T
, do_t_strh
},
10987 {"swi", 0xdf00, 2, ARM_EXT_V4T
, do_t_swi
},
10988 {"sub", 0x0000, 2, ARM_EXT_V4T
, do_t_sub
},
10989 {"tst", T_OPCODE_TST
, 2, ARM_EXT_V4T
, do_t_arit
},
10991 {"adr", 0x0000, 2, ARM_EXT_V4T
, do_t_adr
},
10992 {"nop", 0x46C0, 2, ARM_EXT_V4T
, do_t_nop
}, /* mov r8,r8 */
10993 /* Thumb v2 (ARMv5T). */
10994 {"blx", 0, 0, ARM_EXT_V5T
, do_t_blx
},
10995 {"bkpt", 0xbe00, 2, ARM_EXT_V5T
, do_t_bkpt
},
10998 {"cpsie", 0xb660, 2, ARM_EXT_V6
, do_t_cps
},
10999 {"cpsid", 0xb670, 2, ARM_EXT_V6
, do_t_cps
},
11000 {"cpy", 0x4600, 2, ARM_EXT_V6
, do_t_cpy
},
11001 {"rev", 0xba00, 2, ARM_EXT_V6
, do_t_arit
},
11002 {"rev16", 0xba40, 2, ARM_EXT_V6
, do_t_arit
},
11003 {"revsh", 0xbac0, 2, ARM_EXT_V6
, do_t_arit
},
11004 {"setend", 0xb650, 2, ARM_EXT_V6
, do_t_setend
},
11005 {"sxth", 0xb200, 2, ARM_EXT_V6
, do_t_arit
},
11006 {"sxtb", 0xb240, 2, ARM_EXT_V6
, do_t_arit
},
11007 {"uxth", 0xb280, 2, ARM_EXT_V6
, do_t_arit
},
11008 {"uxtb", 0xb2c0, 2, ARM_EXT_V6
, do_t_arit
},
11017 if ( (arm_ops_hsh
= hash_new ()) == NULL
11018 || (arm_tops_hsh
= hash_new ()) == NULL
11019 || (arm_cond_hsh
= hash_new ()) == NULL
11020 || (arm_shift_hsh
= hash_new ()) == NULL
11021 || (arm_psr_hsh
= hash_new ()) == NULL
)
11022 as_fatal (_("virtual memory exhausted"));
11024 build_arm_ops_hsh ();
11025 for (i
= 0; i
< sizeof (tinsns
) / sizeof (struct thumb_opcode
); i
++)
11026 hash_insert (arm_tops_hsh
, tinsns
[i
].template, (PTR
) (tinsns
+ i
));
11027 for (i
= 0; i
< sizeof (conds
) / sizeof (struct asm_cond
); i
++)
11028 hash_insert (arm_cond_hsh
, conds
[i
].template, (PTR
) (conds
+ i
));
11029 for (i
= 0; i
< sizeof (shift_names
) / sizeof (struct asm_shift_name
); i
++)
11030 hash_insert (arm_shift_hsh
, shift_names
[i
].name
, (PTR
) (shift_names
+ i
));
11031 for (i
= 0; i
< sizeof (psrs
) / sizeof (struct asm_psr
); i
++)
11032 hash_insert (arm_psr_hsh
, psrs
[i
].template, (PTR
) (psrs
+ i
));
11034 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
11035 build_reg_hsh (all_reg_maps
+ i
);
11037 set_constant_flonums ();
11039 /* Set the cpu variant based on the command-line options. We prefer
11040 -mcpu= over -march= if both are set (as for GCC); and we prefer
11041 -mfpu= over any other way of setting the floating point unit.
11042 Use of legacy options with new options are faulted. */
11043 if (legacy_cpu
!= -1)
11045 if (mcpu_cpu_opt
!= -1 || march_cpu_opt
!= -1)
11046 as_bad (_("use of old and new-style options to set CPU type"));
11048 mcpu_cpu_opt
= legacy_cpu
;
11050 else if (mcpu_cpu_opt
== -1)
11051 mcpu_cpu_opt
= march_cpu_opt
;
11053 if (legacy_fpu
!= -1)
11055 if (mfpu_opt
!= -1)
11056 as_bad (_("use of old and new-style options to set FPU type"));
11058 mfpu_opt
= legacy_fpu
;
11060 else if (mfpu_opt
== -1)
11062 #if !(defined (TE_LINUX) || defined (TE_NetBSD))
11063 /* Some environments specify a default FPU. If they don't, infer it
11064 from the processor. */
11065 if (mcpu_fpu_opt
!= -1)
11066 mfpu_opt
= mcpu_fpu_opt
;
11068 mfpu_opt
= march_fpu_opt
;
11070 mfpu_opt
= FPU_DEFAULT
;
11074 if (mfpu_opt
== -1)
11076 if (mcpu_cpu_opt
== -1)
11077 mfpu_opt
= FPU_DEFAULT
;
11078 else if (mcpu_cpu_opt
& ARM_EXT_V5
)
11079 mfpu_opt
= FPU_ARCH_VFP_V2
;
11081 mfpu_opt
= FPU_ARCH_FPA
;
11084 if (mcpu_cpu_opt
== -1)
11085 mcpu_cpu_opt
= CPU_DEFAULT
;
11087 cpu_variant
= mcpu_cpu_opt
| mfpu_opt
;
11090 unsigned int flags
= 0;
11092 #if defined OBJ_ELF
11093 flags
= meabi_flags
;
11095 switch (meabi_flags
)
11097 case EF_ARM_EABI_UNKNOWN
:
11099 #if defined OBJ_COFF || defined OBJ_ELF
11100 /* Set the flags in the private structure. */
11101 if (uses_apcs_26
) flags
|= F_APCS26
;
11102 if (support_interwork
) flags
|= F_INTERWORK
;
11103 if (uses_apcs_float
) flags
|= F_APCS_FLOAT
;
11104 if (pic_code
) flags
|= F_PIC
;
11105 if ((cpu_variant
& FPU_ANY
) == FPU_NONE
11106 || (cpu_variant
& FPU_ANY
) == FPU_ARCH_VFP
) /* VFP layout only. */
11107 flags
|= F_SOFT_FLOAT
;
11109 switch (mfloat_abi_opt
)
11111 case ARM_FLOAT_ABI_SOFT
:
11112 case ARM_FLOAT_ABI_SOFTFP
:
11113 flags
|= F_SOFT_FLOAT
;
11116 case ARM_FLOAT_ABI_HARD
:
11117 if (flags
& F_SOFT_FLOAT
)
11118 as_bad (_("hard-float conflicts with specified fpu"));
11122 /* Using VFP conventions (even if soft-float). */
11123 if (cpu_variant
& FPU_VFP_EXT_NONE
)
11124 flags
|= F_VFP_FLOAT
;
11126 #if defined OBJ_ELF
11127 if (cpu_variant
& FPU_ARCH_MAVERICK
)
11128 flags
|= EF_ARM_MAVERICK_FLOAT
;
11131 case EF_ARM_EABI_VER4
:
11132 /* No additional flags to set. */
11139 #if defined OBJ_COFF || defined OBJ_ELF
11140 bfd_set_private_flags (stdoutput
, flags
);
11142 /* We have run out flags in the COFF header to encode the
11143 status of ATPCS support, so instead we create a dummy,
11144 empty, debug section called .arm.atpcs. */
11149 sec
= bfd_make_section (stdoutput
, ".arm.atpcs");
11153 bfd_set_section_flags
11154 (stdoutput
, sec
, SEC_READONLY
| SEC_DEBUGGING
/* | SEC_HAS_CONTENTS */);
11155 bfd_set_section_size (stdoutput
, sec
, 0);
11156 bfd_set_section_contents (stdoutput
, sec
, NULL
, 0, 0);
11162 /* Record the CPU type as well. */
11163 switch (cpu_variant
& ARM_CPU_MASK
)
11166 mach
= bfd_mach_arm_2
;
11169 case ARM_3
: /* Also ARM_250. */
11170 mach
= bfd_mach_arm_2a
;
11173 case ARM_6
: /* Also ARM_7. */
11174 mach
= bfd_mach_arm_3
;
11178 mach
= bfd_mach_arm_unknown
;
11182 /* Catch special cases. */
11183 if (cpu_variant
& ARM_CEXT_IWMMXT
)
11184 mach
= bfd_mach_arm_iWMMXt
;
11185 else if (cpu_variant
& ARM_CEXT_XSCALE
)
11186 mach
= bfd_mach_arm_XScale
;
11187 else if (cpu_variant
& ARM_CEXT_MAVERICK
)
11188 mach
= bfd_mach_arm_ep9312
;
11189 else if (cpu_variant
& ARM_EXT_V5E
)
11190 mach
= bfd_mach_arm_5TE
;
11191 else if (cpu_variant
& ARM_EXT_V5
)
11193 if (cpu_variant
& ARM_EXT_V4T
)
11194 mach
= bfd_mach_arm_5T
;
11196 mach
= bfd_mach_arm_5
;
11198 else if (cpu_variant
& ARM_EXT_V4
)
11200 if (cpu_variant
& ARM_EXT_V4T
)
11201 mach
= bfd_mach_arm_4T
;
11203 mach
= bfd_mach_arm_4
;
11205 else if (cpu_variant
& ARM_EXT_V3M
)
11206 mach
= bfd_mach_arm_3M
;
11208 #if 0 /* Suppressed - for now. */
11209 #if defined (OBJ_ELF) || defined (OBJ_COFF)
11211 /* Create a .note section to fully identify this arm binary. */
11213 #define NOTE_ARCH_STRING "arch: "
11215 #if defined OBJ_COFF && ! defined NT_VERSION
11216 #define NT_VERSION 1
11221 segT current_seg
= now_seg
;
11222 subsegT current_subseg
= now_subseg
;
11223 asection
* arm_arch
;
11224 const char * arch_string
;
11226 arm_arch
= bfd_make_section_old_way (stdoutput
, ARM_NOTE_SECTION
);
11229 bfd_set_section_flags (stdoutput
, arm_arch
,
11230 SEC_DATA
| SEC_ALLOC
| SEC_LOAD
| SEC_LINK_ONCE \
11231 | SEC_HAS_CONTENTS
);
11233 bfd_set_section_flags (stdoutput
, arm_arch
,
11234 SEC_READONLY
| SEC_HAS_CONTENTS
);
11236 arm_arch
->output_section
= arm_arch
;
11237 subseg_set (arm_arch
, 0);
11242 case bfd_mach_arm_unknown
: arch_string
= "unknown"; break;
11243 case bfd_mach_arm_2
: arch_string
= "armv2"; break;
11244 case bfd_mach_arm_2a
: arch_string
= "armv2a"; break;
11245 case bfd_mach_arm_3
: arch_string
= "armv3"; break;
11246 case bfd_mach_arm_3M
: arch_string
= "armv3M"; break;
11247 case bfd_mach_arm_4
: arch_string
= "armv4"; break;
11248 case bfd_mach_arm_4T
: arch_string
= "armv4t"; break;
11249 case bfd_mach_arm_5
: arch_string
= "armv5"; break;
11250 case bfd_mach_arm_5T
: arch_string
= "armv5t"; break;
11251 case bfd_mach_arm_5TE
: arch_string
= "armv5te"; break;
11252 case bfd_mach_arm_XScale
: arch_string
= "XScale"; break;
11253 case bfd_mach_arm_ep9312
: arch_string
= "ep9312"; break;
11254 case bfd_mach_arm_iWMMXt
: arch_string
= "iWMMXt"; break;
11257 arm_add_note (NOTE_ARCH_STRING
, arch_string
, NT_ARCH
);
11259 subseg_set (current_seg
, current_subseg
);
11262 #endif /* Suppressed code. */
11264 bfd_set_arch_mach (stdoutput
, TARGET_ARCH
, mach
);
11267 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11268 for use in the a.out file, and stores them in the array pointed to by buf.
11269 This knows about the endian-ness of the target machine and does
11270 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11271 2 (short) and 4 (long) Floating numbers are put out as a series of
11272 LITTLENUMS (shorts, here at least). */
11275 md_number_to_chars (char * buf
, valueT val
, int n
)
11277 if (target_big_endian
)
11278 number_to_chars_bigendian (buf
, val
, n
);
11280 number_to_chars_littleendian (buf
, val
, n
);
11284 md_chars_to_number (char * buf
, int n
)
11287 unsigned char * where
= (unsigned char *) buf
;
11289 if (target_big_endian
)
11294 result
|= (*where
++ & 255);
11302 result
|= (where
[n
] & 255);
11309 /* Turn a string in input_line_pointer into a floating point constant
11310 of type TYPE, and store the appropriate bytes in *LITP. The number
11311 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11312 returned, or NULL on OK.
11314 Note that fp constants aren't represent in the normal way on the ARM.
11315 In big endian mode, things are as expected. However, in little endian
11316 mode fp constants are big-endian word-wise, and little-endian byte-wise
11317 within the words. For example, (double) 1.1 in big endian mode is
11318 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11319 the byte sequence 99 99 f1 3f 9a 99 99 99.
11321 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11324 md_atof (int type
, char * litP
, int * sizeP
)
11327 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
11359 return _("bad call to MD_ATOF()");
11362 t
= atof_ieee (input_line_pointer
, type
, words
);
11364 input_line_pointer
= t
;
11367 if (target_big_endian
)
11369 for (i
= 0; i
< prec
; i
++)
11371 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
11377 if (cpu_variant
& FPU_ARCH_VFP
)
11378 for (i
= prec
- 1; i
>= 0; i
--)
11380 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
11384 /* For a 4 byte float the order of elements in `words' is 1 0.
11385 For an 8 byte float the order is 1 0 3 2. */
11386 for (i
= 0; i
< prec
; i
+= 2)
11388 md_number_to_chars (litP
, (valueT
) words
[i
+ 1], 2);
11389 md_number_to_chars (litP
+ 2, (valueT
) words
[i
], 2);
11397 /* The knowledge of the PC's pipeline offset is built into the insns
11401 md_pcrel_from (fixS
* fixP
)
11404 && S_GET_SEGMENT (fixP
->fx_addsy
) == undefined_section
11405 && fixP
->fx_subsy
== NULL
)
11408 if (fixP
->fx_pcrel
&& (fixP
->fx_r_type
== BFD_RELOC_ARM_THUMB_ADD
))
11410 /* PC relative addressing on the Thumb is slightly odd
11411 as the bottom two bits of the PC are forced to zero
11412 for the calculation. */
11413 return (fixP
->fx_where
+ fixP
->fx_frag
->fr_address
) & ~3;
11417 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
11418 so we un-adjust here to compensate for the accommodation. */
11419 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
+ 8;
11421 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
11425 /* Round up a section size to the appropriate boundary. */
11428 md_section_align (segT segment ATTRIBUTE_UNUSED
,
11434 /* Round all sects to multiple of 4. */
11435 return (size
+ 3) & ~3;
11439 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
11440 Otherwise we have no need to default values of symbols. */
11443 md_undefined_symbol (char * name ATTRIBUTE_UNUSED
)
11446 if (name
[0] == '_' && name
[1] == 'G'
11447 && streq (name
, GLOBAL_OFFSET_TABLE_NAME
))
11451 if (symbol_find (name
))
11452 as_bad ("GOT already in the symbol table");
11454 GOT_symbol
= symbol_new (name
, undefined_section
,
11455 (valueT
) 0, & zero_address_frag
);
11466 md_apply_fix3 (fixS
* fixP
,
11470 offsetT value
= * valP
;
11472 unsigned int newimm
;
11473 unsigned long temp
;
11475 char * buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
11476 arm_fix_data
* arm_data
= (arm_fix_data
*) fixP
->tc_fix_data
;
11478 assert (fixP
->fx_r_type
< BFD_RELOC_UNUSED
);
11480 /* Note whether this will delete the relocation. */
11482 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
11483 doesn't work fully.) */
11484 if ((fixP
->fx_addsy
== 0 || symbol_constant_p (fixP
->fx_addsy
))
11485 && !fixP
->fx_pcrel
)
11487 if (fixP
->fx_addsy
== 0 && !fixP
->fx_pcrel
)
11491 /* If this symbol is in a different section then we need to leave it for
11492 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
11493 so we have to undo it's effects here. */
11494 if (fixP
->fx_pcrel
)
11496 if (fixP
->fx_addsy
!= NULL
11497 && S_IS_DEFINED (fixP
->fx_addsy
)
11498 && S_GET_SEGMENT (fixP
->fx_addsy
) != seg
)
11499 value
+= md_pcrel_from (fixP
);
11502 /* Remember value for emit_reloc. */
11503 fixP
->fx_addnumber
= value
;
11505 switch (fixP
->fx_r_type
)
11507 case BFD_RELOC_ARM_IMMEDIATE
:
11508 /* We claim that this fixup has been processed here,
11509 even if in fact we generate an error because we do
11510 not have a reloc for it, so tc_gen_reloc will reject it. */
11514 && ! S_IS_DEFINED (fixP
->fx_addsy
))
11516 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11517 _("undefined symbol %s used as an immediate value"),
11518 S_GET_NAME (fixP
->fx_addsy
));
11522 newimm
= validate_immediate (value
);
11523 temp
= md_chars_to_number (buf
, INSN_SIZE
);
11525 /* If the instruction will fail, see if we can fix things up by
11526 changing the opcode. */
11527 if (newimm
== (unsigned int) FAIL
11528 && (newimm
= negate_data_op (&temp
, value
)) == (unsigned int) FAIL
)
11530 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11531 _("invalid constant (%lx) after fixup"),
11532 (unsigned long) value
);
11536 newimm
|= (temp
& 0xfffff000);
11537 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
11540 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
11542 unsigned int highpart
= 0;
11543 unsigned int newinsn
= 0xe1a00000; /* nop. */
11545 newimm
= validate_immediate (value
);
11546 temp
= md_chars_to_number (buf
, INSN_SIZE
);
11548 /* If the instruction will fail, see if we can fix things up by
11549 changing the opcode. */
11550 if (newimm
== (unsigned int) FAIL
11551 && (newimm
= negate_data_op (& temp
, value
)) == (unsigned int) FAIL
)
11553 /* No ? OK - try using two ADD instructions to generate
11555 newimm
= validate_immediate_twopart (value
, & highpart
);
11557 /* Yes - then make sure that the second instruction is
11559 if (newimm
!= (unsigned int) FAIL
)
11561 /* Still No ? Try using a negated value. */
11562 else if ((newimm
= validate_immediate_twopart (- value
, & highpart
)) != (unsigned int) FAIL
)
11563 temp
= newinsn
= (temp
& OPCODE_MASK
) | OPCODE_SUB
<< DATA_OP_SHIFT
;
11564 /* Otherwise - give up. */
11567 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11568 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
11573 /* Replace the first operand in the 2nd instruction (which
11574 is the PC) with the destination register. We have
11575 already added in the PC in the first instruction and we
11576 do not want to do it again. */
11577 newinsn
&= ~ 0xf0000;
11578 newinsn
|= ((newinsn
& 0x0f000) << 4);
11581 newimm
|= (temp
& 0xfffff000);
11582 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
11584 highpart
|= (newinsn
& 0xfffff000);
11585 md_number_to_chars (buf
+ INSN_SIZE
, (valueT
) highpart
, INSN_SIZE
);
11589 case BFD_RELOC_ARM_OFFSET_IMM
:
11595 if (validate_offset_imm (value
, 0) == FAIL
)
11597 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11598 _("bad immediate value for offset (%ld)"),
11603 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11604 newval
&= 0xff7ff000;
11605 newval
|= value
| (sign
? INDEX_UP
: 0);
11606 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11609 case BFD_RELOC_ARM_OFFSET_IMM8
:
11610 case BFD_RELOC_ARM_HWLITERAL
:
11616 if (validate_offset_imm (value
, 1) == FAIL
)
11618 if (fixP
->fx_r_type
== BFD_RELOC_ARM_HWLITERAL
)
11619 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11620 _("invalid literal constant: pool needs to be closer"));
11622 as_bad (_("bad immediate value for half-word offset (%ld)"),
11627 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11628 newval
&= 0xff7ff0f0;
11629 newval
|= ((value
>> 4) << 8) | (value
& 0xf) | (sign
? INDEX_UP
: 0);
11630 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11633 case BFD_RELOC_ARM_LITERAL
:
11639 if (validate_offset_imm (value
, 0) == FAIL
)
11641 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11642 _("invalid literal constant: pool needs to be closer"));
11646 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11647 newval
&= 0xff7ff000;
11648 newval
|= value
| (sign
? INDEX_UP
: 0);
11649 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11652 case BFD_RELOC_ARM_SHIFT_IMM
:
11653 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11654 if (((unsigned long) value
) > 32
11656 && (((newval
& 0x60) == 0) || (newval
& 0x60) == 0x60)))
11658 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11659 _("shift expression is too large"));
11664 /* Shifts of zero must be done as lsl. */
11666 else if (value
== 32)
11668 newval
&= 0xfffff07f;
11669 newval
|= (value
& 0x1f) << 7;
11670 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11673 case BFD_RELOC_ARM_SMI
:
11674 if (((unsigned long) value
) > 0xffff)
11675 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11676 _("invalid smi expression"));
11677 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xfff000f0;
11678 newval
|= (value
& 0xf) | ((value
& 0xfff0) << 4);
11679 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11682 case BFD_RELOC_ARM_SWI
:
11683 if (arm_data
->thumb_mode
)
11685 if (((unsigned long) value
) > 0xff)
11686 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11687 _("invalid swi expression"));
11688 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xff00;
11690 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11694 if (((unsigned long) value
) > 0x00ffffff)
11695 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11696 _("invalid swi expression"));
11697 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff000000;
11699 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11703 case BFD_RELOC_ARM_MULTI
:
11704 if (((unsigned long) value
) > 0xffff)
11705 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11706 _("invalid expression in load/store multiple"));
11707 newval
= value
| md_chars_to_number (buf
, INSN_SIZE
);
11708 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11711 case BFD_RELOC_ARM_PCREL_BRANCH
:
11712 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11714 /* Sign-extend a 24-bit number. */
11715 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
11718 value
= fixP
->fx_offset
;
11721 /* We are going to store value (shifted right by two) in the
11722 instruction, in a 24 bit, signed field. Thus we need to check
11723 that none of the top 8 bits of the shifted value (top 7 bits of
11724 the unshifted, unsigned value) are set, or that they are all set. */
11725 if ((value
& ~ ((offsetT
) 0x1ffffff)) != 0
11726 && ((value
& ~ ((offsetT
) 0x1ffffff)) != ~ ((offsetT
) 0x1ffffff)))
11729 /* Normally we would be stuck at this point, since we cannot store
11730 the absolute address that is the destination of the branch in the
11731 24 bits of the branch instruction. If however, we happen to know
11732 that the destination of the branch is in the same section as the
11733 branch instruction itself, then we can compute the relocation for
11734 ourselves and not have to bother the linker with it.
11736 FIXME: The test for OBJ_ELF is only here because I have not
11737 worked out how to do this for OBJ_COFF. */
11738 if (fixP
->fx_addsy
!= NULL
11739 && S_IS_DEFINED (fixP
->fx_addsy
)
11740 && S_GET_SEGMENT (fixP
->fx_addsy
) == seg
)
11742 /* Get pc relative value to go into the branch. */
11745 /* Permit a backward branch provided that enough bits
11746 are set. Allow a forwards branch, provided that
11747 enough bits are clear. */
11748 if ( (value
& ~ ((offsetT
) 0x1ffffff)) == ~ ((offsetT
) 0x1ffffff)
11749 || (value
& ~ ((offsetT
) 0x1ffffff)) == 0)
11753 if (! fixP
->fx_done
)
11755 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11756 _("GAS can't handle same-section branch dest >= 0x04000000"));
11760 value
+= SEXT24 (newval
);
11762 if ( (value
& ~ ((offsetT
) 0xffffff)) != 0
11763 && ((value
& ~ ((offsetT
) 0xffffff)) != ~ ((offsetT
) 0xffffff)))
11764 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11765 _("out of range branch"));
11767 newval
= (value
& 0x00ffffff) | (newval
& 0xff000000);
11768 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11771 case BFD_RELOC_ARM_PCREL_BLX
:
11774 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11777 value
= fixP
->fx_offset
;
11779 hbit
= (value
>> 1) & 1;
11780 value
= (value
>> 2) & 0x00ffffff;
11781 value
= (value
+ (newval
& 0x00ffffff)) & 0x00ffffff;
11782 newval
= value
| (newval
& 0xfe000000) | (hbit
<< 24);
11783 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11787 case BFD_RELOC_THUMB_PCREL_BRANCH9
: /* Conditional branch. */
11788 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11790 addressT diff
= (newval
& 0xff) << 1;
11795 if ((value
& ~0xff) && ((value
& ~0xff) != ~0xff))
11796 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11797 _("branch out of range"));
11798 newval
= (newval
& 0xff00) | ((value
& 0x1ff) >> 1);
11800 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11803 case BFD_RELOC_THUMB_PCREL_BRANCH12
: /* Unconditional branch. */
11804 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11806 addressT diff
= (newval
& 0x7ff) << 1;
11811 if ((value
& ~0x7ff) && ((value
& ~0x7ff) != ~0x7ff))
11812 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11813 _("branch out of range"));
11814 newval
= (newval
& 0xf800) | ((value
& 0xfff) >> 1);
11816 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11819 case BFD_RELOC_THUMB_PCREL_BLX
:
11820 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
11825 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11826 newval2
= md_chars_to_number (buf
+ THUMB_SIZE
, THUMB_SIZE
);
11827 diff
= ((newval
& 0x7ff) << 12) | ((newval2
& 0x7ff) << 1);
11828 if (diff
& 0x400000)
11831 value
= fixP
->fx_offset
;
11835 if ((value
& ~0x3fffff) && ((value
& ~0x3fffff) != ~0x3fffff))
11836 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11837 _("branch with link out of range"));
11839 newval
= (newval
& 0xf800) | ((value
& 0x7fffff) >> 12);
11840 newval2
= (newval2
& 0xf800) | ((value
& 0xfff) >> 1);
11841 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
)
11842 /* For a BLX instruction, make sure that the relocation is rounded up
11843 to a word boundary. This follows the semantics of the instruction
11844 which specifies that bit 1 of the target address will come from bit
11845 1 of the base address. */
11846 newval2
= (newval2
+ 1) & ~ 1;
11847 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11848 md_number_to_chars (buf
+ THUMB_SIZE
, newval2
, THUMB_SIZE
);
11853 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11854 md_number_to_chars (buf
, value
, 1);
11858 value
= fixP
->fx_offset
;
11859 md_number_to_chars (buf
, value
, 1);
11865 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11866 md_number_to_chars (buf
, value
, 2);
11870 value
= fixP
->fx_offset
;
11871 md_number_to_chars (buf
, value
, 2);
11877 case BFD_RELOC_ARM_GOT32
:
11878 case BFD_RELOC_ARM_GOTOFF
:
11879 case BFD_RELOC_ARM_TARGET2
:
11880 md_number_to_chars (buf
, 0, 4);
11884 case BFD_RELOC_RVA
:
11886 case BFD_RELOC_ARM_TARGET1
:
11887 case BFD_RELOC_ARM_ROSEGREL32
:
11888 case BFD_RELOC_ARM_SBREL32
:
11889 case BFD_RELOC_32_PCREL
:
11890 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11891 md_number_to_chars (buf
, value
, 4);
11895 value
= fixP
->fx_offset
;
11896 md_number_to_chars (buf
, value
, 4);
11902 case BFD_RELOC_ARM_PREL31
:
11903 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11905 newval
= md_chars_to_number (buf
, 4) & 0x80000000;
11906 if ((value
^ (value
>> 1)) & 0x40000000)
11908 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11909 _("rel31 relocation overflow"));
11911 newval
|= value
& 0x7fffffff;
11912 md_number_to_chars (buf
, newval
, 4);
11916 case BFD_RELOC_ARM_PLT32
:
11917 /* It appears the instruction is fully prepared at this point. */
11921 case BFD_RELOC_ARM_CP_OFF_IMM
:
11923 if (value
< -1023 || value
> 1023 || (value
& 3))
11924 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11925 _("illegal value for co-processor offset"));
11928 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
11929 newval
|= (value
>> 2) | (sign
? INDEX_UP
: 0);
11930 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11933 case BFD_RELOC_ARM_CP_OFF_IMM_S2
:
11935 if (value
< -255 || value
> 255)
11936 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11937 _("Illegal value for co-processor offset"));
11940 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
11941 newval
|= value
| (sign
? INDEX_UP
: 0);
11942 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11945 case BFD_RELOC_ARM_THUMB_OFFSET
:
11946 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11947 /* Exactly what ranges, and where the offset is inserted depends
11948 on the type of instruction, we can establish this from the
11950 switch (newval
>> 12)
11952 case 4: /* PC load. */
11953 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
11954 forced to zero for these loads, so we will need to round
11955 up the offset if the instruction address is not word
11956 aligned (since the final address produced must be, and
11957 we can only describe word-aligned immediate offsets). */
11959 if ((fixP
->fx_frag
->fr_address
+ fixP
->fx_where
+ value
) & 3)
11960 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11961 _("invalid offset, target not word aligned (0x%08X)"),
11962 (unsigned int) (fixP
->fx_frag
->fr_address
11963 + fixP
->fx_where
+ value
));
11965 if ((value
+ 2) & ~0x3fe)
11966 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11967 _("invalid offset, value too big (0x%08lX)"),
11970 /* Round up, since pc will be rounded down. */
11971 newval
|= (value
+ 2) >> 2;
11974 case 9: /* SP load/store. */
11975 if (value
& ~0x3fc)
11976 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11977 _("invalid offset, value too big (0x%08lX)"),
11979 newval
|= value
>> 2;
11982 case 6: /* Word load/store. */
11984 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11985 _("invalid offset, value too big (0x%08lX)"),
11987 newval
|= value
<< 4; /* 6 - 2. */
11990 case 7: /* Byte load/store. */
11992 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11993 _("invalid offset, value too big (0x%08lX)"),
11995 newval
|= value
<< 6;
11998 case 8: /* Halfword load/store. */
12000 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12001 _("invalid offset, value too big (0x%08lX)"),
12003 newval
|= value
<< 5; /* 6 - 1. */
12007 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12008 "Unable to process relocation for thumb opcode: %lx",
12009 (unsigned long) newval
);
12012 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12015 case BFD_RELOC_ARM_THUMB_ADD
:
12016 /* This is a complicated relocation, since we use it for all of
12017 the following immediate relocations:
12021 9bit ADD/SUB SP word-aligned
12022 10bit ADD PC/SP word-aligned
12024 The type of instruction being processed is encoded in the
12031 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12033 int rd
= (newval
>> 4) & 0xf;
12034 int rs
= newval
& 0xf;
12035 int subtract
= newval
& 0x8000;
12039 if (value
& ~0x1fc)
12040 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12041 _("invalid immediate for stack address calculation"));
12042 newval
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
12043 newval
|= value
>> 2;
12045 else if (rs
== REG_PC
|| rs
== REG_SP
)
12049 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12050 _("invalid immediate for address calculation (value = 0x%08lX)"),
12051 (unsigned long) value
);
12052 newval
= (rs
== REG_PC
? T_OPCODE_ADD_PC
: T_OPCODE_ADD_SP
);
12054 newval
|= value
>> 2;
12059 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12060 _("invalid 8bit immediate"));
12061 newval
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
12062 newval
|= (rd
<< 8) | value
;
12067 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12068 _("invalid 3bit immediate"));
12069 newval
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
12070 newval
|= rd
| (rs
<< 3) | (value
<< 6);
12073 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12076 case BFD_RELOC_ARM_THUMB_IMM
:
12077 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12078 switch (newval
>> 11)
12080 case 0x04: /* 8bit immediate MOV. */
12081 case 0x05: /* 8bit immediate CMP. */
12082 if (value
< 0 || value
> 255)
12083 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12084 _("invalid immediate: %ld is too large"),
12092 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12095 case BFD_RELOC_ARM_THUMB_SHIFT
:
12096 /* 5bit shift value (0..31). */
12097 if (value
< 0 || value
> 31)
12098 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12099 _("illegal Thumb shift value: %ld"), (long) value
);
12100 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xf03f;
12101 newval
|= value
<< 6;
12102 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12105 case BFD_RELOC_VTABLE_INHERIT
:
12106 case BFD_RELOC_VTABLE_ENTRY
:
12110 case BFD_RELOC_NONE
:
12112 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12113 _("bad relocation fixup type (%d)"), fixP
->fx_r_type
);
12117 /* Translate internal representation of relocation info to BFD target
12121 tc_gen_reloc (asection
* section ATTRIBUTE_UNUSED
,
12125 bfd_reloc_code_real_type code
;
12127 reloc
= xmalloc (sizeof (arelent
));
12129 reloc
->sym_ptr_ptr
= xmalloc (sizeof (asymbol
*));
12130 *reloc
->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
12131 reloc
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
12133 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12135 if (fixp
->fx_pcrel
== 0)
12136 reloc
->addend
= fixp
->fx_offset
;
12138 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
12139 #else /* OBJ_ELF */
12140 reloc
->addend
= fixp
->fx_offset
;
12143 switch (fixp
->fx_r_type
)
12146 if (fixp
->fx_pcrel
)
12148 code
= BFD_RELOC_8_PCREL
;
12153 if (fixp
->fx_pcrel
)
12155 code
= BFD_RELOC_16_PCREL
;
12160 if (fixp
->fx_pcrel
)
12162 code
= BFD_RELOC_32_PCREL
;
12166 case BFD_RELOC_ARM_PCREL_BRANCH
:
12167 case BFD_RELOC_ARM_PCREL_BLX
:
12168 case BFD_RELOC_RVA
:
12169 case BFD_RELOC_THUMB_PCREL_BRANCH9
:
12170 case BFD_RELOC_THUMB_PCREL_BRANCH12
:
12171 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
12172 case BFD_RELOC_THUMB_PCREL_BLX
:
12173 case BFD_RELOC_VTABLE_ENTRY
:
12174 case BFD_RELOC_VTABLE_INHERIT
:
12175 code
= fixp
->fx_r_type
;
12178 case BFD_RELOC_ARM_LITERAL
:
12179 case BFD_RELOC_ARM_HWLITERAL
:
12180 /* If this is called then the a literal has
12181 been referenced across a section boundary. */
12182 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12183 _("literal referenced across section boundary"));
12187 case BFD_RELOC_ARM_GOT32
:
12188 case BFD_RELOC_ARM_GOTOFF
:
12189 case BFD_RELOC_ARM_PLT32
:
12190 case BFD_RELOC_ARM_TARGET1
:
12191 case BFD_RELOC_ARM_ROSEGREL32
:
12192 case BFD_RELOC_ARM_SBREL32
:
12193 case BFD_RELOC_ARM_PREL31
:
12194 case BFD_RELOC_ARM_TARGET2
:
12195 code
= fixp
->fx_r_type
;
12199 case BFD_RELOC_ARM_IMMEDIATE
:
12200 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12201 _("internal relocation (type: IMMEDIATE) not fixed up"));
12204 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
12205 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12206 _("ADRL used for a symbol not defined in the same file"));
12209 case BFD_RELOC_ARM_OFFSET_IMM
:
12210 if (fixp
->fx_addsy
!= NULL
12211 && !S_IS_DEFINED (fixp
->fx_addsy
)
12212 && S_IS_LOCAL (fixp
->fx_addsy
))
12214 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12215 _("undefined local label `%s'"),
12216 S_GET_NAME (fixp
->fx_addsy
));
12220 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12221 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
12228 switch (fixp
->fx_r_type
)
12230 case BFD_RELOC_ARM_OFFSET_IMM8
: type
= "OFFSET_IMM8"; break;
12231 case BFD_RELOC_ARM_SHIFT_IMM
: type
= "SHIFT_IMM"; break;
12232 case BFD_RELOC_ARM_SMI
: type
= "SMI"; break;
12233 case BFD_RELOC_ARM_SWI
: type
= "SWI"; break;
12234 case BFD_RELOC_ARM_MULTI
: type
= "MULTI"; break;
12235 case BFD_RELOC_ARM_CP_OFF_IMM
: type
= "CP_OFF_IMM"; break;
12236 case BFD_RELOC_ARM_THUMB_ADD
: type
= "THUMB_ADD"; break;
12237 case BFD_RELOC_ARM_THUMB_SHIFT
: type
= "THUMB_SHIFT"; break;
12238 case BFD_RELOC_ARM_THUMB_IMM
: type
= "THUMB_IMM"; break;
12239 case BFD_RELOC_ARM_THUMB_OFFSET
: type
= "THUMB_OFFSET"; break;
12240 default: type
= _("<unknown>"); break;
12242 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12243 _("cannot represent %s relocation in this object file format"),
12250 if ((code
== BFD_RELOC_32_PCREL
|| code
== BFD_RELOC_32
)
12252 && fixp
->fx_addsy
== GOT_symbol
)
12254 code
= BFD_RELOC_ARM_GOTPC
;
12255 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
12259 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, code
);
12261 if (reloc
->howto
== NULL
)
12263 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12264 _("cannot represent %s relocation in this object file format"),
12265 bfd_get_reloc_code_name (code
));
12269 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12270 vtable entry to be used in the relocation's section offset. */
12271 if (fixp
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
12272 reloc
->address
= fixp
->fx_offset
;
12278 md_estimate_size_before_relax (fragS
* fragP ATTRIBUTE_UNUSED
,
12279 segT segtype ATTRIBUTE_UNUSED
)
12281 as_fatal (_("md_estimate_size_before_relax\n"));
12285 /* We need to be able to fix up arbitrary expressions in some statements.
12286 This is so that we can handle symbols that are an arbitrary distance from
12287 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
12288 which returns part of an address in a form which will be valid for
12289 a data instruction. We do this by pushing the expression into a symbol
12290 in the expr_section, and creating a fix for that. */
12293 fix_new_arm (fragS
* frag
,
12301 arm_fix_data
* arm_data
;
12309 new_fix
= fix_new_exp (frag
, where
, size
, exp
, pc_rel
, reloc
);
12313 new_fix
= fix_new (frag
, where
, size
, make_expr_symbol (exp
), 0,
12318 /* Mark whether the fix is to a THUMB instruction, or an ARM
12320 arm_data
= obstack_alloc (& notes
, sizeof (arm_fix_data
));
12321 new_fix
->tc_fix_data
= (PTR
) arm_data
;
12322 arm_data
->thumb_mode
= thumb_mode
;
12326 output_inst (const char * str
)
12332 as_bad ("%s -- `%s'", inst
.error
, str
);
12336 to
= frag_more (inst
.size
);
12338 if (thumb_mode
&& (inst
.size
> THUMB_SIZE
))
12340 assert (inst
.size
== (2 * THUMB_SIZE
));
12341 md_number_to_chars (to
, inst
.instruction
>> 16, THUMB_SIZE
);
12342 md_number_to_chars (to
+ THUMB_SIZE
, inst
.instruction
, THUMB_SIZE
);
12344 else if (inst
.size
> INSN_SIZE
)
12346 assert (inst
.size
== (2 * INSN_SIZE
));
12347 md_number_to_chars (to
, inst
.instruction
, INSN_SIZE
);
12348 md_number_to_chars (to
+ INSN_SIZE
, inst
.instruction
, INSN_SIZE
);
12351 md_number_to_chars (to
, inst
.instruction
, inst
.size
);
12353 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
12354 fix_new_arm (frag_now
, to
- frag_now
->fr_literal
,
12355 inst
.size
, & inst
.reloc
.exp
, inst
.reloc
.pc_rel
,
12359 dwarf2_emit_insn (inst
.size
);
12364 md_assemble (char * str
)
12370 /* Align the instruction.
12371 This may not be the right thing to do but ... */
12376 /* Align the previous label if needed. */
12377 if (last_label_seen
!= NULL
)
12379 symbol_set_frag (last_label_seen
, frag_now
);
12380 S_SET_VALUE (last_label_seen
, (valueT
) frag_now_fix ());
12381 S_SET_SEGMENT (last_label_seen
, now_seg
);
12384 memset (&inst
, '\0', sizeof (inst
));
12385 inst
.reloc
.type
= BFD_RELOC_NONE
;
12387 skip_whitespace (str
);
12389 /* Scan up to the end of the op-code, which must end in white space or
12391 for (start
= p
= str
; *p
!= '\0'; p
++)
12397 as_bad (_("no operator -- statement `%s'\n"), str
);
12403 const struct thumb_opcode
* opcode
;
12407 opcode
= (const struct thumb_opcode
*) hash_find (arm_tops_hsh
, str
);
12412 /* Check that this instruction is supported for this CPU. */
12413 if (thumb_mode
== 1 && (opcode
->variant
& cpu_variant
) == 0)
12415 as_bad (_("selected processor does not support `%s'"), str
);
12419 mapping_state (MAP_THUMB
);
12420 inst
.instruction
= opcode
->value
;
12421 inst
.size
= opcode
->size
;
12429 const struct asm_opcode
* opcode
;
12433 opcode
= (const struct asm_opcode
*) hash_find (arm_ops_hsh
, str
);
12438 /* Check that this instruction is supported for this CPU. */
12439 if ((opcode
->variant
& cpu_variant
) == 0)
12441 as_bad (_("selected processor does not support `%s'"), str
);
12445 mapping_state (MAP_ARM
);
12446 inst
.instruction
= opcode
->value
;
12447 inst
.size
= INSN_SIZE
;
12454 /* It wasn't an instruction, but it might be a register alias of the form
12456 if (create_register_alias (str
, p
))
12459 as_bad (_("bad instruction `%s'"), start
);
12463 Invocation line includes a switch not recognized by the base assembler.
12464 See if it's a processor-specific option.
12466 This routine is somewhat complicated by the need for backwards
12467 compatibility (since older releases of gcc can't be changed).
12468 The new options try to make the interface as compatible as
12471 New options (supported) are:
12473 -mcpu=<cpu name> Assemble for selected processor
12474 -march=<architecture name> Assemble for selected architecture
12475 -mfpu=<fpu architecture> Assemble for selected FPU.
12476 -EB/-mbig-endian Big-endian
12477 -EL/-mlittle-endian Little-endian
12478 -k Generate PIC code
12479 -mthumb Start in Thumb mode
12480 -mthumb-interwork Code supports ARM/Thumb interworking
12482 For now we will also provide support for:
12484 -mapcs-32 32-bit Program counter
12485 -mapcs-26 26-bit Program counter
12486 -macps-float Floats passed in FP registers
12487 -mapcs-reentrant Reentrant code
12489 (sometime these will probably be replaced with -mapcs=<list of options>
12490 and -matpcs=<list of options>)
12492 The remaining options are only supported for back-wards compatibility.
12493 Cpu variants, the arm part is optional:
12494 -m[arm]1 Currently not supported.
12495 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
12496 -m[arm]3 Arm 3 processor
12497 -m[arm]6[xx], Arm 6 processors
12498 -m[arm]7[xx][t][[d]m] Arm 7 processors
12499 -m[arm]8[10] Arm 8 processors
12500 -m[arm]9[20][tdmi] Arm 9 processors
12501 -mstrongarm[110[0]] StrongARM processors
12502 -mxscale XScale processors
12503 -m[arm]v[2345[t[e]]] Arm architectures
12504 -mall All (except the ARM1)
12506 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
12507 -mfpe-old (No float load/store multiples)
12508 -mvfpxd VFP Single precision
12510 -mno-fpu Disable all floating point instructions
12512 The following CPU names are recognized:
12513 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
12514 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
12515 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
12516 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
12517 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
12518 arm10t arm10e, arm1020t, arm1020e, arm10200e,
12519 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
12523 const char * md_shortopts
= "m:k";
12525 #ifdef ARM_BI_ENDIAN
12526 #define OPTION_EB (OPTION_MD_BASE + 0)
12527 #define OPTION_EL (OPTION_MD_BASE + 1)
12529 #if TARGET_BYTES_BIG_ENDIAN
12530 #define OPTION_EB (OPTION_MD_BASE + 0)
12532 #define OPTION_EL (OPTION_MD_BASE + 1)
12536 struct option md_longopts
[] =
12539 {"EB", no_argument
, NULL
, OPTION_EB
},
12542 {"EL", no_argument
, NULL
, OPTION_EL
},
12544 {NULL
, no_argument
, NULL
, 0}
12547 size_t md_longopts_size
= sizeof (md_longopts
);
12549 struct arm_option_table
12551 char *option
; /* Option name to match. */
12552 char *help
; /* Help information. */
12553 int *var
; /* Variable to change. */
12554 int value
; /* What to change it to. */
12555 char *deprecated
; /* If non-null, print this message. */
12558 struct arm_option_table arm_opts
[] =
12560 {"k", N_("generate PIC code"), &pic_code
, 1, NULL
},
12561 {"mthumb", N_("assemble Thumb code"), &thumb_mode
, 1, NULL
},
12562 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
12563 &support_interwork
, 1, NULL
},
12564 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26
, 0, NULL
},
12565 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26
, 1, NULL
},
12566 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float
,
12568 {"mapcs-reentrant", N_("re-entrant code"), &pic_code
, 1, NULL
},
12569 {"matpcs", N_("code is ATPCS conformant"), &atpcs
, 1, NULL
},
12570 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian
, 1, NULL
},
12571 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian
, 1,
12574 /* These are recognized by the assembler, but have no affect on code. */
12575 {"mapcs-frame", N_("use frame pointer"), NULL
, 0, NULL
},
12576 {"mapcs-stack-check", N_("use stack size checking"), NULL
, 0, NULL
},
12578 /* DON'T add any new processors to this list -- we want the whole list
12579 to go away... Add them to the processors table instead. */
12580 {"marm1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
12581 {"m1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
12582 {"marm2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
12583 {"m2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
12584 {"marm250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
12585 {"m250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
12586 {"marm3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
12587 {"m3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
12588 {"marm6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
12589 {"m6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
12590 {"marm600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
12591 {"m600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
12592 {"marm610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
12593 {"m610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
12594 {"marm620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
12595 {"m620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
12596 {"marm7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
12597 {"m7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
12598 {"marm70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
12599 {"m70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
12600 {"marm700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
12601 {"m700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
12602 {"marm700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
12603 {"m700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
12604 {"marm710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
12605 {"m710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
12606 {"marm710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
12607 {"m710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
12608 {"marm720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
12609 {"m720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
12610 {"marm7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
12611 {"m7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
12612 {"marm7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
12613 {"m7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
12614 {"marm7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
12615 {"m7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
12616 {"marm7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
12617 {"m7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
12618 {"marm7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
12619 {"m7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
12620 {"marm7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
12621 {"m7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
12622 {"marm7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
12623 {"m7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
12624 {"marm7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
12625 {"m7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
12626 {"marm7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12627 {"m7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12628 {"marm7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12629 {"m7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12630 {"marm710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
12631 {"m710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
12632 {"marm720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
12633 {"m720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
12634 {"marm740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
12635 {"m740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
12636 {"marm8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
12637 {"m8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
12638 {"marm810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
12639 {"m810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
12640 {"marm9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
12641 {"m9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
12642 {"marm9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
12643 {"m9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
12644 {"marm920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
12645 {"m920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
12646 {"marm940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
12647 {"m940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
12648 {"mstrongarm", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=strongarm")},
12649 {"mstrongarm110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
12650 N_("use -mcpu=strongarm110")},
12651 {"mstrongarm1100", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
12652 N_("use -mcpu=strongarm1100")},
12653 {"mstrongarm1110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
12654 N_("use -mcpu=strongarm1110")},
12655 {"mxscale", NULL
, &legacy_cpu
, ARM_ARCH_XSCALE
, N_("use -mcpu=xscale")},
12656 {"miwmmxt", NULL
, &legacy_cpu
, ARM_ARCH_IWMMXT
, N_("use -mcpu=iwmmxt")},
12657 {"mall", NULL
, &legacy_cpu
, ARM_ANY
, N_("use -mcpu=all")},
12659 /* Architecture variants -- don't add any more to this list either. */
12660 {"mv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
12661 {"marmv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
12662 {"mv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
12663 {"marmv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
12664 {"mv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
12665 {"marmv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
12666 {"mv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
12667 {"marmv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
12668 {"mv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
12669 {"marmv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
12670 {"mv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
12671 {"marmv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
12672 {"mv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
12673 {"marmv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
12674 {"mv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
12675 {"marmv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
12676 {"mv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
12677 {"marmv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
12679 /* Floating point variants -- don't add any more to this list either. */
12680 {"mfpe-old", NULL
, &legacy_fpu
, FPU_ARCH_FPE
, N_("use -mfpu=fpe")},
12681 {"mfpa10", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa10")},
12682 {"mfpa11", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa11")},
12683 {"mno-fpu", NULL
, &legacy_fpu
, 0,
12684 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
12686 {NULL
, NULL
, NULL
, 0, NULL
}
12689 struct arm_cpu_option_table
12693 /* For some CPUs we assume an FPU unless the user explicitly sets
12698 /* This list should, at a minimum, contain all the cpu names
12699 recognized by GCC. */
12700 static struct arm_cpu_option_table arm_cpus
[] =
12702 {"all", ARM_ANY
, FPU_ARCH_FPA
},
12703 {"arm1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
12704 {"arm2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
12705 {"arm250", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
12706 {"arm3", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
12707 {"arm6", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12708 {"arm60", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12709 {"arm600", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12710 {"arm610", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12711 {"arm620", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12712 {"arm7", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12713 {"arm7m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
12714 {"arm7d", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12715 {"arm7dm", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
12716 {"arm7di", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12717 {"arm7dmi", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
12718 {"arm70", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12719 {"arm700", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12720 {"arm700i", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12721 {"arm710", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12722 {"arm710t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12723 {"arm720", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12724 {"arm720t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12725 {"arm740t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12726 {"arm710c", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12727 {"arm7100", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12728 {"arm7500", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12729 {"arm7500fe", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12730 {"arm7t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12731 {"arm7tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12732 {"arm7tdmi-s", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12733 {"arm8", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12734 {"arm810", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12735 {"strongarm", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12736 {"strongarm1", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12737 {"strongarm110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12738 {"strongarm1100", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12739 {"strongarm1110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12740 {"arm9", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12741 {"arm920", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12742 {"arm920t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12743 {"arm922t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12744 {"arm940t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12745 {"arm9tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12746 /* For V5 or later processors we default to using VFP; but the user
12747 should really set the FPU type explicitly. */
12748 {"arm9e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
12749 {"arm9e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12750 {"arm926ej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
12751 {"arm926ejs", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
12752 {"arm926ej-s", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
12753 {"arm946e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
12754 {"arm946e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12755 {"arm966e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
12756 {"arm966e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12757 {"arm10t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
12758 {"arm10e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12759 {"arm1020", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12760 {"arm1020t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
12761 {"arm1020e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12762 {"arm1026ejs", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12763 {"arm1026ej-s", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12764 {"arm1136js", ARM_ARCH_V6
, FPU_NONE
},
12765 {"arm1136j-s", ARM_ARCH_V6
, FPU_NONE
},
12766 {"arm1136jfs", ARM_ARCH_V6
, FPU_ARCH_VFP_V2
},
12767 {"arm1136jf-s", ARM_ARCH_V6
, FPU_ARCH_VFP_V2
},
12768 {"mpcore", ARM_ARCH_V6K
, FPU_ARCH_VFP_V2
},
12769 {"mpcorenovfp", ARM_ARCH_V6K
, FPU_NONE
},
12770 {"arm1176jz-s", ARM_ARCH_V6ZK
, FPU_NONE
},
12771 {"arm1176jzf-s", ARM_ARCH_V6ZK
, FPU_ARCH_VFP_V2
},
12772 /* ??? XSCALE is really an architecture. */
12773 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
12774 /* ??? iwmmxt is not a processor. */
12775 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP_V2
},
12776 {"i80200", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
12778 {"ep9312", ARM_ARCH_V4T
| ARM_CEXT_MAVERICK
, FPU_ARCH_MAVERICK
},
12782 struct arm_arch_option_table
12789 /* This list should, at a minimum, contain all the architecture names
12790 recognized by GCC. */
12791 static struct arm_arch_option_table arm_archs
[] =
12793 {"all", ARM_ANY
, FPU_ARCH_FPA
},
12794 {"armv1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
12795 {"armv2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
12796 {"armv2a", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
12797 {"armv2s", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
12798 {"armv3", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12799 {"armv3m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
12800 {"armv4", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12801 {"armv4xm", ARM_ARCH_V4xM
, FPU_ARCH_FPA
},
12802 {"armv4t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12803 {"armv4txm", ARM_ARCH_V4TxM
, FPU_ARCH_FPA
},
12804 {"armv5", ARM_ARCH_V5
, FPU_ARCH_VFP
},
12805 {"armv5t", ARM_ARCH_V5T
, FPU_ARCH_VFP
},
12806 {"armv5txm", ARM_ARCH_V5TxM
, FPU_ARCH_VFP
},
12807 {"armv5te", ARM_ARCH_V5TE
, FPU_ARCH_VFP
},
12808 {"armv5texp", ARM_ARCH_V5TExP
, FPU_ARCH_VFP
},
12809 {"armv5tej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP
},
12810 {"armv6", ARM_ARCH_V6
, FPU_ARCH_VFP
},
12811 {"armv6j", ARM_ARCH_V6
, FPU_ARCH_VFP
},
12812 {"armv6k", ARM_ARCH_V6K
, FPU_ARCH_VFP
},
12813 {"armv6z", ARM_ARCH_V6Z
, FPU_ARCH_VFP
},
12814 {"armv6zk", ARM_ARCH_V6ZK
, FPU_ARCH_VFP
},
12815 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP
},
12816 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP
},
12820 /* ISA extensions in the co-processor space. */
12821 struct arm_arch_extension_table
12827 static struct arm_arch_extension_table arm_extensions
[] =
12829 {"maverick", ARM_CEXT_MAVERICK
},
12830 {"xscale", ARM_CEXT_XSCALE
},
12831 {"iwmmxt", ARM_CEXT_IWMMXT
},
12835 struct arm_fpu_option_table
12841 /* This list should, at a minimum, contain all the fpu names
12842 recognized by GCC. */
12843 static struct arm_fpu_option_table arm_fpus
[] =
12845 {"softfpa", FPU_NONE
},
12846 {"fpe", FPU_ARCH_FPE
},
12847 {"fpe2", FPU_ARCH_FPE
},
12848 {"fpe3", FPU_ARCH_FPA
}, /* Third release supports LFM/SFM. */
12849 {"fpa", FPU_ARCH_FPA
},
12850 {"fpa10", FPU_ARCH_FPA
},
12851 {"fpa11", FPU_ARCH_FPA
},
12852 {"arm7500fe", FPU_ARCH_FPA
},
12853 {"softvfp", FPU_ARCH_VFP
},
12854 {"softvfp+vfp", FPU_ARCH_VFP_V2
},
12855 {"vfp", FPU_ARCH_VFP_V2
},
12856 {"vfp9", FPU_ARCH_VFP_V2
},
12857 {"vfp10", FPU_ARCH_VFP_V2
},
12858 {"vfp10-r0", FPU_ARCH_VFP_V1
},
12859 {"vfpxd", FPU_ARCH_VFP_V1xD
},
12860 {"arm1020t", FPU_ARCH_VFP_V1
},
12861 {"arm1020e", FPU_ARCH_VFP_V2
},
12862 {"arm1136jfs", FPU_ARCH_VFP_V2
},
12863 {"arm1136jf-s", FPU_ARCH_VFP_V2
},
12864 {"maverick", FPU_ARCH_MAVERICK
},
12868 struct arm_float_abi_option_table
12874 static struct arm_float_abi_option_table arm_float_abis
[] =
12876 {"hard", ARM_FLOAT_ABI_HARD
},
12877 {"softfp", ARM_FLOAT_ABI_SOFTFP
},
12878 {"soft", ARM_FLOAT_ABI_SOFT
},
12882 struct arm_eabi_option_table
12885 unsigned int value
;
12889 /* We only know how to output GNU and ver 4 (AAELF) formats. */
12890 static struct arm_eabi_option_table arm_eabis
[] =
12892 {"gnu", EF_ARM_EABI_UNKNOWN
},
12893 {"4", EF_ARM_EABI_VER4
},
12898 struct arm_long_option_table
12900 char * option
; /* Substring to match. */
12901 char * help
; /* Help information. */
12902 int (* func
) (char * subopt
); /* Function to decode sub-option. */
12903 char * deprecated
; /* If non-null, print this message. */
12907 arm_parse_extension (char * str
, int * opt_p
)
12909 while (str
!= NULL
&& *str
!= 0)
12911 struct arm_arch_extension_table
* opt
;
12917 as_bad (_("invalid architectural extension"));
12922 ext
= strchr (str
, '+');
12925 optlen
= ext
- str
;
12927 optlen
= strlen (str
);
12931 as_bad (_("missing architectural extension"));
12935 for (opt
= arm_extensions
; opt
->name
!= NULL
; opt
++)
12936 if (strncmp (opt
->name
, str
, optlen
) == 0)
12938 *opt_p
|= opt
->value
;
12942 if (opt
->name
== NULL
)
12944 as_bad (_("unknown architectural extnsion `%s'"), str
);
12955 arm_parse_cpu (char * str
)
12957 struct arm_cpu_option_table
* opt
;
12958 char * ext
= strchr (str
, '+');
12962 optlen
= ext
- str
;
12964 optlen
= strlen (str
);
12968 as_bad (_("missing cpu name `%s'"), str
);
12972 for (opt
= arm_cpus
; opt
->name
!= NULL
; opt
++)
12973 if (strncmp (opt
->name
, str
, optlen
) == 0)
12975 mcpu_cpu_opt
= opt
->value
;
12976 mcpu_fpu_opt
= opt
->default_fpu
;
12979 return arm_parse_extension (ext
, &mcpu_cpu_opt
);
12984 as_bad (_("unknown cpu `%s'"), str
);
12989 arm_parse_arch (char * str
)
12991 struct arm_arch_option_table
*opt
;
12992 char *ext
= strchr (str
, '+');
12996 optlen
= ext
- str
;
12998 optlen
= strlen (str
);
13002 as_bad (_("missing architecture name `%s'"), str
);
13007 for (opt
= arm_archs
; opt
->name
!= NULL
; opt
++)
13008 if (streq (opt
->name
, str
))
13010 march_cpu_opt
= opt
->value
;
13011 march_fpu_opt
= opt
->default_fpu
;
13014 return arm_parse_extension (ext
, &march_cpu_opt
);
13019 as_bad (_("unknown architecture `%s'\n"), str
);
13024 arm_parse_fpu (char * str
)
13026 struct arm_fpu_option_table
* opt
;
13028 for (opt
= arm_fpus
; opt
->name
!= NULL
; opt
++)
13029 if (streq (opt
->name
, str
))
13031 mfpu_opt
= opt
->value
;
13035 as_bad (_("unknown floating point format `%s'\n"), str
);
13040 arm_parse_float_abi (char * str
)
13042 struct arm_float_abi_option_table
* opt
;
13044 for (opt
= arm_float_abis
; opt
->name
!= NULL
; opt
++)
13045 if (streq (opt
->name
, str
))
13047 mfloat_abi_opt
= opt
->value
;
13051 as_bad (_("unknown floating point abi `%s'\n"), str
);
13057 arm_parse_eabi (char * str
)
13059 struct arm_eabi_option_table
*opt
;
13061 for (opt
= arm_eabis
; opt
->name
!= NULL
; opt
++)
13062 if (streq (opt
->name
, str
))
13064 meabi_flags
= opt
->value
;
13067 as_bad (_("unknown EABI `%s'\n"), str
);
13072 struct arm_long_option_table arm_long_opts
[] =
13074 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13075 arm_parse_cpu
, NULL
},
13076 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13077 arm_parse_arch
, NULL
},
13078 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13079 arm_parse_fpu
, NULL
},
13080 {"mfloat-abi=", N_("<abi>\t assemble for floating point ABI <abi>"),
13081 arm_parse_float_abi
, NULL
},
13083 {"meabi=", N_("<ver>\t assemble for eabi version <ver>"),
13084 arm_parse_eabi
, NULL
},
13086 {NULL
, NULL
, 0, NULL
}
13090 md_parse_option (int c
, char * arg
)
13092 struct arm_option_table
*opt
;
13093 struct arm_long_option_table
*lopt
;
13099 target_big_endian
= 1;
13105 target_big_endian
= 0;
13110 /* Listing option. Just ignore these, we don't support additional
13115 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
13117 if (c
== opt
->option
[0]
13118 && ((arg
== NULL
&& opt
->option
[1] == 0)
13119 || streq (arg
, opt
->option
+ 1)))
13121 #if WARN_DEPRECATED
13122 /* If the option is deprecated, tell the user. */
13123 if (opt
->deprecated
!= NULL
)
13124 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
,
13125 arg
? arg
: "", _(opt
->deprecated
));
13128 if (opt
->var
!= NULL
)
13129 *opt
->var
= opt
->value
;
13135 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
13137 /* These options are expected to have an argument. */
13138 if (c
== lopt
->option
[0]
13140 && strncmp (arg
, lopt
->option
+ 1,
13141 strlen (lopt
->option
+ 1)) == 0)
13143 #if WARN_DEPRECATED
13144 /* If the option is deprecated, tell the user. */
13145 if (lopt
->deprecated
!= NULL
)
13146 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
, arg
,
13147 _(lopt
->deprecated
));
13150 /* Call the sup-option parser. */
13151 return lopt
->func (arg
+ strlen (lopt
->option
) - 1);
13162 md_show_usage (FILE * fp
)
13164 struct arm_option_table
*opt
;
13165 struct arm_long_option_table
*lopt
;
13167 fprintf (fp
, _(" ARM-specific assembler options:\n"));
13169 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
13170 if (opt
->help
!= NULL
)
13171 fprintf (fp
, " -%-23s%s\n", opt
->option
, _(opt
->help
));
13173 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
13174 if (lopt
->help
!= NULL
)
13175 fprintf (fp
, " -%s%s\n", lopt
->option
, _(lopt
->help
));
13179 -EB assemble code for a big-endian cpu\n"));
13184 -EL assemble code for a little-endian cpu\n"));
13188 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13191 cons_fix_new_arm (fragS
* frag
,
13196 bfd_reloc_code_real_type type
;
13200 FIXME: @@ Should look at CPU word size. */
13204 type
= BFD_RELOC_8
;
13207 type
= BFD_RELOC_16
;
13211 type
= BFD_RELOC_32
;
13214 type
= BFD_RELOC_64
;
13218 fix_new_exp (frag
, where
, (int) size
, exp
, pcrel
, type
);
13221 /* A good place to do this, although this was probably not intended
13222 for this kind of use. We need to dump the literal pool before
13223 references are made to a null symbol pointer. */
13228 literal_pool
* pool
;
13230 for (pool
= list_of_pools
; pool
; pool
= pool
->next
)
13232 /* Put it at the end of the relevent section. */
13233 subseg_set (pool
->section
, pool
->sub_section
);
13235 arm_elf_change_section ();
13242 arm_start_line_hook (void)
13244 last_label_seen
= NULL
;
13248 arm_frob_label (symbolS
* sym
)
13250 last_label_seen
= sym
;
13252 ARM_SET_THUMB (sym
, thumb_mode
);
13254 #if defined OBJ_COFF || defined OBJ_ELF
13255 ARM_SET_INTERWORK (sym
, support_interwork
);
13258 /* Note - do not allow local symbols (.Lxxx) to be labeled
13259 as Thumb functions. This is because these labels, whilst
13260 they exist inside Thumb code, are not the entry points for
13261 possible ARM->Thumb calls. Also, these labels can be used
13262 as part of a computed goto or switch statement. eg gcc
13263 can generate code that looks like this:
13265 ldr r2, [pc, .Laaa]
13275 The first instruction loads the address of the jump table.
13276 The second instruction converts a table index into a byte offset.
13277 The third instruction gets the jump address out of the table.
13278 The fourth instruction performs the jump.
13280 If the address stored at .Laaa is that of a symbol which has the
13281 Thumb_Func bit set, then the linker will arrange for this address
13282 to have the bottom bit set, which in turn would mean that the
13283 address computation performed by the third instruction would end
13284 up with the bottom bit set. Since the ARM is capable of unaligned
13285 word loads, the instruction would then load the incorrect address
13286 out of the jump table, and chaos would ensue. */
13287 if (label_is_thumb_function_name
13288 && (S_GET_NAME (sym
)[0] != '.' || S_GET_NAME (sym
)[1] != 'L')
13289 && (bfd_get_section_flags (stdoutput
, now_seg
) & SEC_CODE
) != 0)
13291 /* When the address of a Thumb function is taken the bottom
13292 bit of that address should be set. This will allow
13293 interworking between Arm and Thumb functions to work
13296 THUMB_SET_FUNC (sym
, 1);
13298 label_is_thumb_function_name
= FALSE
;
13302 /* Adjust the symbol table. This marks Thumb symbols as distinct from
13306 arm_adjust_symtab (void)
13311 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
13313 if (ARM_IS_THUMB (sym
))
13315 if (THUMB_IS_FUNC (sym
))
13317 /* Mark the symbol as a Thumb function. */
13318 if ( S_GET_STORAGE_CLASS (sym
) == C_STAT
13319 || S_GET_STORAGE_CLASS (sym
) == C_LABEL
) /* This can happen! */
13320 S_SET_STORAGE_CLASS (sym
, C_THUMBSTATFUNC
);
13322 else if (S_GET_STORAGE_CLASS (sym
) == C_EXT
)
13323 S_SET_STORAGE_CLASS (sym
, C_THUMBEXTFUNC
);
13325 as_bad (_("%s: unexpected function type: %d"),
13326 S_GET_NAME (sym
), S_GET_STORAGE_CLASS (sym
));
13328 else switch (S_GET_STORAGE_CLASS (sym
))
13331 S_SET_STORAGE_CLASS (sym
, C_THUMBEXT
);
13334 S_SET_STORAGE_CLASS (sym
, C_THUMBSTAT
);
13337 S_SET_STORAGE_CLASS (sym
, C_THUMBLABEL
);
13345 if (ARM_IS_INTERWORK (sym
))
13346 coffsymbol (symbol_get_bfdsym (sym
))->native
->u
.syment
.n_flags
= 0xFF;
13353 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
13355 if (ARM_IS_THUMB (sym
))
13357 elf_symbol_type
* elf_sym
;
13359 elf_sym
= elf_symbol (symbol_get_bfdsym (sym
));
13360 bind
= ELF_ST_BIND (elf_sym
);
13362 /* If it's a .thumb_func, declare it as so,
13363 otherwise tag label as .code 16. */
13364 if (THUMB_IS_FUNC (sym
))
13365 elf_sym
->internal_elf_sym
.st_info
=
13366 ELF_ST_INFO (bind
, STT_ARM_TFUNC
);
13368 elf_sym
->internal_elf_sym
.st_info
=
13369 ELF_ST_INFO (bind
, STT_ARM_16BIT
);
13376 arm_data_in_code (void)
13378 if (thumb_mode
&& ! strncmp (input_line_pointer
+ 1, "data:", 5))
13380 *input_line_pointer
= '/';
13381 input_line_pointer
+= 5;
13382 *input_line_pointer
= 0;
13390 arm_canonicalize_symbol_name (char * name
)
13394 if (thumb_mode
&& (len
= strlen (name
)) > 5
13395 && streq (name
+ len
- 5, "/data"))
13396 *(name
+ len
- 5) = 0;
13401 #if defined OBJ_COFF || defined OBJ_ELF
13403 arm_validate_fix (fixS
* fixP
)
13405 /* If the destination of the branch is a defined symbol which does not have
13406 the THUMB_FUNC attribute, then we must be calling a function which has
13407 the (interfacearm) attribute. We look for the Thumb entry point to that
13408 function and change the branch to refer to that function instead. */
13409 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
13410 && fixP
->fx_addsy
!= NULL
13411 && S_IS_DEFINED (fixP
->fx_addsy
)
13412 && ! THUMB_IS_FUNC (fixP
->fx_addsy
))
13414 fixP
->fx_addsy
= find_real_start (fixP
->fx_addsy
);
13420 arm_force_relocation (struct fix
* fixp
)
13422 #if defined (OBJ_COFF) && defined (TE_PE)
13423 if (fixp
->fx_r_type
== BFD_RELOC_RVA
)
13427 if (fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
13428 || fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
13429 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
13430 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
)
13434 /* Resolve these relocations even if the symbol is extern or weak. */
13435 if (fixp
->fx_r_type
== BFD_RELOC_ARM_IMMEDIATE
13436 || fixp
->fx_r_type
== BFD_RELOC_ARM_OFFSET_IMM
13437 || fixp
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
13440 return generic_force_reloc (fixp
);
13444 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
13445 local labels from being added to the output symbol table when they
13446 are used with the ADRL pseudo op. The ADRL relocation should always
13447 be resolved before the binbary is emitted, so it is safe to say that
13448 it is adjustable. */
13451 arm_fix_adjustable (fixS
* fixP
)
13453 if (fixP
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
13460 /* Relocations against Thumb function names must be left unadjusted,
13461 so that the linker can use this information to correctly set the
13462 bottom bit of their addresses. The MIPS version of this function
13463 also prevents relocations that are mips-16 specific, but I do not
13464 know why it does this.
13467 There is one other problem that ought to be addressed here, but
13468 which currently is not: Taking the address of a label (rather
13469 than a function) and then later jumping to that address. Such
13470 addresses also ought to have their bottom bit set (assuming that
13471 they reside in Thumb code), but at the moment they will not. */
13474 arm_fix_adjustable (fixS
* fixP
)
13476 if (fixP
->fx_addsy
== NULL
)
13479 if (THUMB_IS_FUNC (fixP
->fx_addsy
)
13480 && fixP
->fx_subsy
== NULL
)
13483 /* We need the symbol name for the VTABLE entries. */
13484 if ( fixP
->fx_r_type
== BFD_RELOC_VTABLE_INHERIT
13485 || fixP
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
13488 /* Don't allow symbols to be discarded on GOT related relocs. */
13489 if (fixP
->fx_r_type
== BFD_RELOC_ARM_PLT32
13490 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOT32
13491 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOTOFF
13492 || fixP
->fx_r_type
== BFD_RELOC_ARM_TARGET2
)
13499 elf32_arm_target_format (void)
13502 return (target_big_endian
13503 ? "elf32-bigarm-symbian"
13504 : "elf32-littlearm-symbian");
13506 if (target_big_endian
)
13507 return "elf32-bigarm";
13509 return "elf32-littlearm";
13514 armelf_frob_symbol (symbolS
* symp
,
13517 elf_frob_symbol (symp
, puntp
);
13521 s_arm_elf_cons (int nbytes
)
13525 #ifdef md_flush_pending_output
13526 md_flush_pending_output ();
13529 if (is_it_end_of_statement ())
13531 demand_empty_rest_of_line ();
13535 #ifdef md_cons_align
13536 md_cons_align (nbytes
);
13539 mapping_state (MAP_DATA
);
13542 bfd_reloc_code_real_type reloc
;
13544 expression (& exp
);
13546 if (exp
.X_op
== O_symbol
13547 && * input_line_pointer
== '('
13548 && (reloc
= arm_parse_reloc ()) != BFD_RELOC_UNUSED
)
13550 reloc_howto_type
*howto
= bfd_reloc_type_lookup (stdoutput
, reloc
);
13551 int size
= bfd_get_reloc_size (howto
);
13554 as_bad ("%s relocations do not fit in %d bytes",
13555 howto
->name
, nbytes
);
13558 char *p
= frag_more ((int) nbytes
);
13559 int offset
= nbytes
- size
;
13561 fix_new_exp (frag_now
, p
- frag_now
->fr_literal
+ offset
, size
,
13566 emit_expr (&exp
, (unsigned int) nbytes
);
13568 while (*input_line_pointer
++ == ',');
13570 /* Put terminator back into stream. */
13571 input_line_pointer
--;
13572 demand_empty_rest_of_line ();
13576 /* Parse a .rel31 directive. */
13579 s_arm_rel31 (int ignored ATTRIBUTE_UNUSED
)
13585 SKIP_WHITESPACE ();
13588 if (*input_line_pointer
== '1')
13589 highbit
= 0x80000000;
13590 else if (*input_line_pointer
!= '0')
13591 as_bad (_("expected 0 or 1"));
13593 input_line_pointer
++;
13594 SKIP_WHITESPACE ();
13595 if (*input_line_pointer
!= ',')
13596 as_bad (_("missing comma"));
13597 input_line_pointer
++;
13599 #ifdef md_flush_pending_output
13600 md_flush_pending_output ();
13603 #ifdef md_cons_align
13607 mapping_state (MAP_DATA
);
13612 md_number_to_chars (p
, highbit
, 4);
13613 fix_new_arm (frag_now
, p
- frag_now
->fr_literal
, 4, &exp
, 1,
13614 BFD_RELOC_ARM_PREL31
);
13616 demand_empty_rest_of_line ();
13619 /* Code to deal with unwinding tables. */
13621 static void add_unwind_adjustsp (offsetT
);
13623 /* Switch to section NAME and create section if necessary. It's
13624 rather ugly that we have to manipulate input_line_pointer but I
13625 don't see any other way to accomplish the same thing without
13626 changing obj-elf.c (which may be the Right Thing, in the end).
13627 Copied from tc-ia64.c. */
13630 set_section (char *name
)
13632 char *saved_input_line_pointer
;
13634 saved_input_line_pointer
= input_line_pointer
;
13635 input_line_pointer
= name
;
13636 obj_elf_section (0);
13637 input_line_pointer
= saved_input_line_pointer
;
13640 /* Cenerate and deferred unwind frame offset. */
13643 flush_pending_unwind (void)
13647 offset
= unwind
.pending_offset
;
13648 unwind
.pending_offset
= 0;
13650 add_unwind_adjustsp (offset
);
13653 /* Add an opcode to this list for this function. Two-byte opcodes should
13654 be passed as op[0] << 8 | op[1]. The list of opcodes is built in reverse
13658 add_unwind_opcode (valueT op
, int length
)
13660 /* Add any deferred stack adjustment. */
13661 if (unwind
.pending_offset
)
13662 flush_pending_unwind ();
13664 unwind
.sp_restored
= 0;
13666 if (unwind
.opcode_count
+ length
> unwind
.opcode_alloc
)
13668 unwind
.opcode_alloc
+= ARM_OPCODE_CHUNK_SIZE
;
13669 if (unwind
.opcodes
)
13670 unwind
.opcodes
= xrealloc (unwind
.opcodes
,
13671 unwind
.opcode_alloc
);
13673 unwind
.opcodes
= xmalloc (unwind
.opcode_alloc
);
13678 unwind
.opcodes
[unwind
.opcode_count
] = op
& 0xff;
13680 unwind
.opcode_count
++;
13684 /* Add unwind opcodes to adjust the stack pointer. */
13687 add_unwind_adjustsp (offsetT offset
)
13691 if (offset
> 0x200)
13693 /* We need at most 5 bytes to hold a 32-bit value in a uleb128. */
13698 /* Long form: 0xb2, uleb128. */
13699 /* This might not fit in a word so add the individual bytes,
13700 remembering the list is built in reverse order. */
13701 o
= (valueT
) ((offset
- 0x204) >> 2);
13703 add_unwind_opcode (0, 1);
13705 /* Calculate the uleb128 encoding of the offset. */
13709 bytes
[n
] = o
& 0x7f;
13715 /* Add the insn. */
13717 add_unwind_opcode (bytes
[n
- 1], 1);
13718 add_unwind_opcode (0xb2, 1);
13720 else if (offset
> 0x100)
13722 /* Two short opcodes. */
13723 add_unwind_opcode (0x3f, 1);
13724 op
= (offset
- 0x104) >> 2;
13725 add_unwind_opcode (op
, 1);
13727 else if (offset
> 0)
13729 /* Short opcode. */
13730 op
= (offset
- 4) >> 2;
13731 add_unwind_opcode (op
, 1);
13733 else if (offset
< 0)
13736 while (offset
> 0x100)
13738 add_unwind_opcode (0x7f, 1);
13741 op
= ((offset
- 4) >> 2) | 0x40;
13742 add_unwind_opcode (op
, 1);
13746 /* Finish the list of unwind opcodes for this function. */
13748 finish_unwind_opcodes (void)
13752 if (unwind
.fp_used
)
13754 /* Adjust sp as neccessary. */
13755 unwind
.pending_offset
+= unwind
.fp_offset
- unwind
.frame_size
;
13756 flush_pending_unwind ();
13758 /* After restoring sp from the frame pointer. */
13759 op
= 0x90 | unwind
.fp_reg
;
13760 add_unwind_opcode (op
, 1);
13763 flush_pending_unwind ();
13767 /* Start an exception table entry. If idx is nonzero this is an index table
13771 start_unwind_section (const segT text_seg
, int idx
)
13773 const char * text_name
;
13774 const char * prefix
;
13775 const char * prefix_once
;
13779 size_t sec_name_len
;
13783 prefix
= ELF_STRING_ARM_unwind
;
13784 prefix_once
= ELF_STRING_ARM_unwind_once
;
13788 prefix
= ELF_STRING_ARM_unwind_info
;
13789 prefix_once
= ELF_STRING_ARM_unwind_info_once
;
13792 text_name
= segment_name (text_seg
);
13793 if (streq (text_name
, ".text"))
13796 if (strncmp (text_name
, ".gnu.linkonce.t.",
13797 strlen (".gnu.linkonce.t.")) == 0)
13799 prefix
= prefix_once
;
13800 text_name
+= strlen (".gnu.linkonce.t.");
13803 prefix_len
= strlen (prefix
);
13804 text_len
= strlen (text_name
);
13805 sec_name_len
= prefix_len
+ text_len
;
13806 sec_name
= alloca (sec_name_len
+ 1);
13807 memcpy (sec_name
, prefix
, prefix_len
);
13808 memcpy (sec_name
+ prefix_len
, text_name
, text_len
);
13809 sec_name
[prefix_len
+ text_len
] = '\0';
13811 /* Handle COMDAT group. */
13812 if (prefix
!= prefix_once
&& (text_seg
->flags
& SEC_LINK_ONCE
) != 0)
13815 size_t len
, group_name_len
;
13816 const char *group_name
= elf_group_name (text_seg
);
13818 if (group_name
== NULL
)
13820 as_bad ("Group section `%s' has no group signature",
13821 segment_name (text_seg
));
13822 ignore_rest_of_line ();
13825 /* We have to construct a fake section directive. */
13826 group_name_len
= strlen (group_name
);
13832 len
= (sec_name_len
13833 + prefix_len
/* ,"aG",%sectiontype, */
13834 + group_name_len
/* ,group_name */
13835 + 7); /* ,comdat */
13837 section
= alloca (len
+ 1);
13838 memcpy (section
, sec_name
, sec_name_len
);
13840 memcpy (section
+ sec_name_len
, ",\"aG\",%exidx,", 13);
13842 memcpy (section
+ sec_name_len
, ",\"aG\",%progbits,", 16);
13843 memcpy (section
+ sec_name_len
+ prefix_len
, group_name
, group_name_len
);
13844 memcpy (section
+ len
- 7, ",comdat", 7);
13845 section
[len
] = '\0';
13846 set_section (section
);
13850 set_section (sec_name
);
13851 bfd_set_section_flags (stdoutput
, now_seg
,
13852 SEC_LOAD
| SEC_ALLOC
| SEC_READONLY
);
13855 /* Set the setion link for index tables. */
13857 elf_linked_to_section (now_seg
) = text_seg
;
13861 /* Start an unwind table entry. HAVE_DATA is nonzero if we have additional
13862 personality routine data. Returns zero, or the index table value for
13863 and inline entry. */
13866 create_unwind_entry (int have_data
)
13870 unsigned char *ptr
;
13871 /* The current word of data. */
13873 /* The number of bytes left in this word. */
13876 finish_unwind_opcodes ();
13878 /* Remember the current text section. */
13879 unwind
.saved_seg
= now_seg
;
13880 unwind
.saved_subseg
= now_subseg
;
13882 start_unwind_section (now_seg
, 0);
13884 if (unwind
.personality_routine
== NULL
)
13886 if (unwind
.personality_index
== -2)
13889 as_bad (_("handerdata in cantunwind frame"));
13890 return 1; /* EXIDX_CANTUNWIND. */
13893 /* Use a default personality routine if none is specified. */
13894 if (unwind
.personality_index
== -1)
13896 if (unwind
.opcode_count
> 3)
13897 unwind
.personality_index
= 1;
13899 unwind
.personality_index
= 0;
13902 /* Space for the personality routine entry. */
13903 if (unwind
.personality_index
== 0)
13905 if (unwind
.opcode_count
> 3)
13906 as_bad (_("too many unwind opcodes for personality routine 0"));
13910 /* All the data is inline in the index table. */
13913 while (unwind
.opcode_count
> 0)
13915 unwind
.opcode_count
--;
13916 data
= (data
<< 8) | unwind
.opcodes
[unwind
.opcode_count
];
13920 /* Pad with "finish" opcodes. */
13922 data
= (data
<< 8) | 0xb0;
13929 /* We get two opcodes "free" in the first word. */
13930 size
= unwind
.opcode_count
- 2;
13933 /* An extra byte is required for the opcode count. */
13934 size
= unwind
.opcode_count
+ 1;
13936 size
= (size
+ 3) >> 2;
13938 as_bad (_("too many unwind opcodes"));
13940 frag_align (2, 0, 0);
13941 record_alignment (now_seg
, 2);
13942 unwind
.table_entry
= expr_build_dot ();
13944 /* Allocate the table entry. */
13945 ptr
= frag_more ((size
<< 2) + 4);
13946 where
= frag_now_fix () - ((size
<< 2) + 4);
13948 switch (unwind
.personality_index
)
13951 /* ??? Should this be a PLT generating relocation? */
13952 /* Custom personality routine. */
13953 fix_new (frag_now
, where
, 4, unwind
.personality_routine
, 0, 1,
13954 BFD_RELOC_ARM_PREL31
);
13958 /* Set the first byte to the number of additional words. */
13963 /* ABI defined personality routines. */
13964 /* TODO: Emit R_ARM_NONE to the personality routine. */
13966 /* Three opcodes bytes are packed into the first word. */
13973 /* The size and first two opcode bytes go in the first word. */
13974 data
= ((0x80 + unwind
.personality_index
) << 8) | size
;
13979 /* Should never happen. */
13983 /* Pack the opcodes into words (MSB first), reversing the list at the same
13985 while (unwind
.opcode_count
> 0)
13989 md_number_to_chars (ptr
, data
, 4);
13994 unwind
.opcode_count
--;
13996 data
= (data
<< 8) | unwind
.opcodes
[unwind
.opcode_count
];
13999 /* Finish off the last word. */
14002 /* Pad with "finish" opcodes. */
14004 data
= (data
<< 8) | 0xb0;
14006 md_number_to_chars (ptr
, data
, 4);
14011 /* Add an empty descriptor if there is no user-specified data. */
14012 ptr
= frag_more (4);
14013 md_number_to_chars (ptr
, 0, 4);
14020 /* Parse an unwind_fnstart directive. Simply records the current location. */
14023 s_arm_unwind_fnstart (int ignored ATTRIBUTE_UNUSED
)
14025 demand_empty_rest_of_line ();
14026 /* Mark the start of the function. */
14027 unwind
.proc_start
= expr_build_dot ();
14029 /* Reset the rest of the unwind info. */
14030 unwind
.opcode_count
= 0;
14031 unwind
.table_entry
= NULL
;
14032 unwind
.personality_routine
= NULL
;
14033 unwind
.personality_index
= -1;
14034 unwind
.frame_size
= 0;
14035 unwind
.fp_offset
= 0;
14036 unwind
.fp_reg
= 13;
14037 unwind
.fp_used
= 0;
14038 unwind
.sp_restored
= 0;
14042 /* Parse a handlerdata directive. Creates the exception handling table entry
14043 for the function. */
14046 s_arm_unwind_handlerdata (int ignored ATTRIBUTE_UNUSED
)
14048 demand_empty_rest_of_line ();
14049 if (unwind
.table_entry
)
14050 as_bad (_("dupicate .handlerdata directive"));
14052 create_unwind_entry (1);
14055 /* Parse an unwind_fnend directive. Generates the index table entry. */
14058 s_arm_unwind_fnend (int ignored ATTRIBUTE_UNUSED
)
14061 unsigned char *ptr
;
14064 demand_empty_rest_of_line ();
14066 /* Add eh table entry. */
14067 if (unwind
.table_entry
== NULL
)
14068 val
= create_unwind_entry (0);
14072 /* Add index table entry. This is two words. */
14073 start_unwind_section (unwind
.saved_seg
, 1);
14074 frag_align (2, 0, 0);
14075 record_alignment (now_seg
, 2);
14077 ptr
= frag_more (8);
14078 where
= frag_now_fix () - 8;
14080 /* Self relative offset of the function start. */
14081 fix_new (frag_now
, where
, 4, unwind
.proc_start
, 0, 1,
14082 BFD_RELOC_ARM_PREL31
);
14085 /* Inline exception table entry. */
14086 md_number_to_chars (ptr
+ 4, val
, 4);
14088 /* Self relative offset of the table entry. */
14089 fix_new (frag_now
, where
+ 4, 4, unwind
.table_entry
, 0, 1,
14090 BFD_RELOC_ARM_PREL31
);
14092 /* Restore the original section. */
14093 subseg_set (unwind
.saved_seg
, unwind
.saved_subseg
);
14097 /* Parse an unwind_cantunwind directive. */
14100 s_arm_unwind_cantunwind (int ignored ATTRIBUTE_UNUSED
)
14102 demand_empty_rest_of_line ();
14103 if (unwind
.personality_routine
|| unwind
.personality_index
!= -1)
14104 as_bad (_("personality routine specified for cantunwind frame"));
14106 unwind
.personality_index
= -2;
14110 /* Parse a personalityindex directive. */
14113 s_arm_unwind_personalityindex (int ignored ATTRIBUTE_UNUSED
)
14117 if (unwind
.personality_routine
|| unwind
.personality_index
!= -1)
14118 as_bad (_("duplicate .personalityindex directive"));
14120 SKIP_WHITESPACE ();
14124 if (exp
.X_op
!= O_constant
14125 || exp
.X_add_number
< 0 || exp
.X_add_number
> 15)
14127 as_bad (_("bad personality routine number"));
14128 ignore_rest_of_line ();
14132 unwind
.personality_index
= exp
.X_add_number
;
14134 demand_empty_rest_of_line ();
14138 /* Parse a personality directive. */
14141 s_arm_unwind_personality (int ignored ATTRIBUTE_UNUSED
)
14145 if (unwind
.personality_routine
|| unwind
.personality_index
!= -1)
14146 as_bad (_("duplicate .personality directive"));
14148 SKIP_WHITESPACE ();
14149 name
= input_line_pointer
;
14150 c
= get_symbol_end ();
14151 p
= input_line_pointer
;
14152 unwind
.personality_routine
= symbol_find_or_make (name
);
14154 SKIP_WHITESPACE ();
14155 demand_empty_rest_of_line ();
14159 /* Parse a directive saving core registers. */
14162 s_arm_unwind_save_core (void)
14168 SKIP_WHITESPACE ();
14169 range
= reg_list (&input_line_pointer
);
14172 as_bad (_("expected register list"));
14173 ignore_rest_of_line ();
14177 demand_empty_rest_of_line ();
14179 /* Turn .unwind_movsp ip followed by .unwind_save {..., ip, ...}
14180 into .unwind_save {..., sp...}. We aren't bothered about the value of
14181 ip because it is clobbered by calls. */
14182 if (unwind
.sp_restored
&& unwind
.fp_reg
== 12
14183 && (range
& 0x3000) == 0x1000)
14185 unwind
.opcode_count
--;
14186 unwind
.sp_restored
= 0;
14187 range
= (range
| 0x2000) & ~0x1000;
14188 unwind
.pending_offset
= 0;
14191 /* See if we can use the short opcodes. These pop a block of upto 8
14192 registers starting with r4, plus maybe r14. */
14193 for (n
= 0; n
< 8; n
++)
14195 /* Break at the first non-saved register. */
14196 if ((range
& (1 << (n
+ 4))) == 0)
14199 /* See if there are any other bits set. */
14200 if (n
== 0 || (range
& (0xfff0 << n
) & 0xbff0) != 0)
14202 /* Use the long form. */
14203 op
= 0x8000 | ((range
>> 4) & 0xfff);
14204 add_unwind_opcode (op
, 2);
14208 /* Use the short form. */
14209 if (range
& 0x4000)
14210 op
= 0xa8; /* Pop r14. */
14212 op
= 0xa0; /* Do not pop r14. */
14214 add_unwind_opcode (op
, 1);
14220 op
= 0xb100 | (range
& 0xf);
14221 add_unwind_opcode (op
, 2);
14224 /* Record the number of bytes pushed. */
14225 for (n
= 0; n
< 16; n
++)
14227 if (range
& (1 << n
))
14228 unwind
.frame_size
+= 4;
14233 /* Parse a directive saving FPA registers. */
14236 s_arm_unwind_save_fpa (int reg
)
14242 /* Get Number of registers to transfer. */
14243 if (skip_past_comma (&input_line_pointer
) != FAIL
)
14246 exp
.X_op
= O_illegal
;
14248 if (exp
.X_op
!= O_constant
)
14250 as_bad (_("expected , <constant>"));
14251 ignore_rest_of_line ();
14255 num_regs
= exp
.X_add_number
;
14257 if (num_regs
< 1 || num_regs
> 4)
14259 as_bad (_("number of registers must be in the range [1:4]"));
14260 ignore_rest_of_line ();
14264 demand_empty_rest_of_line ();
14269 op
= 0xb4 | (num_regs
- 1);
14270 add_unwind_opcode (op
, 1);
14275 op
= 0xc800 | (reg
<< 4) | (num_regs
- 1);
14276 add_unwind_opcode (op
, 2);
14278 unwind
.frame_size
+= num_regs
* 12;
14282 /* Parse a directive saving VFP registers. */
14285 s_arm_unwind_save_vfp (void)
14291 count
= vfp_parse_reg_list (&input_line_pointer
, ®
, 1);
14294 as_bad (_("expected register list"));
14295 ignore_rest_of_line ();
14299 demand_empty_rest_of_line ();
14304 op
= 0xb8 | (count
- 1);
14305 add_unwind_opcode (op
, 1);
14310 op
= 0xb300 | (reg
<< 4) | (count
- 1);
14311 add_unwind_opcode (op
, 2);
14313 unwind
.frame_size
+= count
* 8 + 4;
14317 /* Parse a directive saving iWMMXt registers. */
14320 s_arm_unwind_save_wmmx (void)
14329 if (*input_line_pointer
== '{')
14330 input_line_pointer
++;
14336 reg
= arm_reg_parse (&input_line_pointer
,
14337 all_reg_maps
[REG_TYPE_IWMMXT
].htab
);
14339 if (wr_register (reg
))
14341 i
= reg
& ~WR_PREFIX
;
14343 as_tsktsk (_("register list not in ascending order"));
14346 else if (wcg_register (reg
))
14348 i
= (reg
& ~WC_PREFIX
) - 8;
14350 as_tsktsk (_("register list not in ascending order"));
14351 wcg_mask
|= 1 << i
;
14355 as_bad (_("expected wr or wcgr"));
14359 SKIP_WHITESPACE ();
14360 if (*input_line_pointer
== '-')
14362 hi_reg
= arm_reg_parse (&input_line_pointer
,
14363 all_reg_maps
[REG_TYPE_IWMMXT
].htab
);
14364 if (wr_register (reg
) && wr_register (hi_reg
))
14366 for (; reg
< hi_reg
; reg
++)
14367 wr_mask
|= 1 << (reg
& ~WR_PREFIX
);
14369 else if (wcg_register (reg
) && wcg_register (hi_reg
))
14371 for (; reg
< hi_reg
; reg
++)
14372 wcg_mask
|= 1 << ((reg
& ~WC_PREFIX
) - 8);
14376 as_bad (_("bad register range"));
14381 while (skip_past_comma (&input_line_pointer
) != FAIL
);
14383 SKIP_WHITESPACE ();
14384 if (*input_line_pointer
== '}')
14385 input_line_pointer
++;
14387 demand_empty_rest_of_line ();
14389 if (wr_mask
&& wcg_mask
)
14391 as_bad (_("inconsistent register types"));
14395 /* Generate any deferred opcodes becuuse we're going to be looking at
14397 flush_pending_unwind ();
14401 for (i
= 0; i
< 16; i
++)
14403 if (wcg_mask
& (1 << i
))
14404 unwind
.frame_size
+= 4;
14406 op
= 0xc700 | wcg_mask
;
14407 add_unwind_opcode (op
, 2);
14411 for (i
= 0; i
< 16; i
++)
14413 if (wr_mask
& (1 << i
))
14414 unwind
.frame_size
+= 8;
14416 /* Attempt to combine with a previous opcode. We do this because gcc
14417 likes to output separate unwind directives for a single block of
14419 if (unwind
.opcode_count
> 0)
14421 i
= unwind
.opcodes
[unwind
.opcode_count
- 1];
14422 if ((i
& 0xf8) == 0xc0)
14425 /* Only merge if the blocks are contiguous. */
14428 if ((wr_mask
& 0xfe00) == (1 << 9))
14430 wr_mask
|= ((1 << (i
+ 11)) - 1) & 0xfc00;
14431 unwind
.opcode_count
--;
14434 else if (i
== 6 && unwind
.opcode_count
>= 2)
14436 i
= unwind
.opcodes
[unwind
.opcode_count
- 2];
14440 op
= 0xffff << (reg
- 1);
14442 || ((wr_mask
& op
) == (1u << (reg
- 1))))
14444 op
= (1 << (reg
+ i
+ 1)) - 1;
14445 op
&= ~((1 << reg
) - 1);
14447 unwind
.opcode_count
-= 2;
14454 /* We want to generate opcodes in the order the registers have been
14455 saved, ie. descending order. */
14456 for (reg
= 15; reg
>= -1; reg
--)
14458 /* Save registers in blocks. */
14460 || !(wr_mask
& (1 << reg
)))
14462 /* We found an unsaved reg. Generate opcodes to save the
14463 preceeding block. */
14469 op
= 0xc0 | (hi_reg
- 10);
14470 add_unwind_opcode (op
, 1);
14475 op
= 0xc600 | ((reg
+ 1) << 4) | ((hi_reg
- reg
) - 1);
14476 add_unwind_opcode (op
, 2);
14485 ignore_rest_of_line ();
14489 /* Parse an unwind_save directive. */
14492 s_arm_unwind_save (int ignored ATTRIBUTE_UNUSED
)
14497 /* Figure out what sort of save we have. */
14498 SKIP_WHITESPACE ();
14499 saved_ptr
= input_line_pointer
;
14501 reg
= arm_reg_parse (&input_line_pointer
, all_reg_maps
[REG_TYPE_FN
].htab
);
14504 s_arm_unwind_save_fpa (reg
);
14508 if (*input_line_pointer
== '{')
14509 input_line_pointer
++;
14511 SKIP_WHITESPACE ();
14513 reg
= arm_reg_parse (&input_line_pointer
, all_reg_maps
[REG_TYPE_RN
].htab
);
14516 input_line_pointer
= saved_ptr
;
14517 s_arm_unwind_save_core ();
14521 reg
= arm_reg_parse (&input_line_pointer
, all_reg_maps
[REG_TYPE_DN
].htab
);
14524 input_line_pointer
= saved_ptr
;
14525 s_arm_unwind_save_vfp ();
14529 reg
= arm_reg_parse (&input_line_pointer
,
14530 all_reg_maps
[REG_TYPE_IWMMXT
].htab
);
14533 input_line_pointer
= saved_ptr
;
14534 s_arm_unwind_save_wmmx ();
14538 /* TODO: Maverick registers. */
14539 as_bad (_("unrecognised register"));
14543 /* Parse an unwind_movsp directive. */
14546 s_arm_unwind_movsp (int ignored ATTRIBUTE_UNUSED
)
14551 SKIP_WHITESPACE ();
14552 reg
= reg_required_here (&input_line_pointer
, -1);
14555 as_bad (_("ARM register expected"));
14556 ignore_rest_of_line ();
14560 if (reg
== 13 || reg
== 15)
14562 as_bad (_("r%d not permitted in .unwind_movsp directive"), reg
);
14563 ignore_rest_of_line ();
14567 if (unwind
.fp_reg
!= 13)
14568 as_bad (_("unexpected .unwind_movsp directive"));
14570 /* Generate opcode to restore the value. */
14572 add_unwind_opcode (op
, 1);
14574 /* Record the information for later. */
14575 unwind
.fp_reg
= reg
;
14576 unwind
.fp_offset
= unwind
.frame_size
;
14577 unwind
.sp_restored
= 1;
14578 demand_empty_rest_of_line ();
14582 /* Parse #<number>. */
14585 require_hashconst (int * val
)
14589 SKIP_WHITESPACE ();
14590 if (*input_line_pointer
== '#')
14592 input_line_pointer
++;
14596 exp
.X_op
= O_illegal
;
14598 if (exp
.X_op
!= O_constant
)
14600 as_bad (_("expected #constant"));
14601 ignore_rest_of_line ();
14604 *val
= exp
.X_add_number
;
14608 /* Parse an unwind_pad directive. */
14611 s_arm_unwind_pad (int ignored ATTRIBUTE_UNUSED
)
14615 if (require_hashconst (&offset
) == FAIL
)
14620 as_bad (_("stack increment must be multiple of 4"));
14621 ignore_rest_of_line ();
14625 /* Don't generate any opcodes, just record the details for later. */
14626 unwind
.frame_size
+= offset
;
14627 unwind
.pending_offset
+= offset
;
14629 demand_empty_rest_of_line ();
14632 /* Parse an unwind_setfp directive. */
14635 s_arm_unwind_setfp (int ignored ATTRIBUTE_UNUSED
)
14641 fp_reg
= reg_required_here (&input_line_pointer
, -1);
14642 if (skip_past_comma (&input_line_pointer
) == FAIL
)
14645 sp_reg
= reg_required_here (&input_line_pointer
, -1);
14647 if (fp_reg
== FAIL
|| sp_reg
== FAIL
)
14649 as_bad (_("expected <reg>, <reg>"));
14650 ignore_rest_of_line ();
14654 /* Optonal constant. */
14655 if (skip_past_comma (&input_line_pointer
) != FAIL
)
14657 if (require_hashconst (&offset
) == FAIL
)
14663 demand_empty_rest_of_line ();
14665 if (sp_reg
!= 13 && sp_reg
!= unwind
.fp_reg
)
14667 as_bad (_("register must be either sp or set by a previous"
14668 "unwind_movsp directive"));
14672 /* Don't generate any opcodes, just record the information for later. */
14673 unwind
.fp_reg
= fp_reg
;
14674 unwind
.fp_used
= 1;
14676 unwind
.fp_offset
= unwind
.frame_size
- offset
;
14678 unwind
.fp_offset
-= offset
;
14681 /* Parse an unwind_raw directive. */
14684 s_arm_unwind_raw (int ignored ATTRIBUTE_UNUSED
)
14687 /* This is an arbitary limit. */
14688 unsigned char op
[16];
14691 SKIP_WHITESPACE ();
14693 if (exp
.X_op
== O_constant
14694 && skip_past_comma (&input_line_pointer
) != FAIL
)
14696 unwind
.frame_size
+= exp
.X_add_number
;
14700 exp
.X_op
= O_illegal
;
14702 if (exp
.X_op
!= O_constant
)
14704 as_bad (_("expected <offset>, <opcode>"));
14705 ignore_rest_of_line ();
14711 /* Parse the opcode. */
14716 as_bad (_("unwind opcode too long"));
14717 ignore_rest_of_line ();
14719 if (exp
.X_op
!= O_constant
|| exp
.X_add_number
& ~0xff)
14721 as_bad (_("invalid unwind opcode"));
14722 ignore_rest_of_line ();
14725 op
[count
++] = exp
.X_add_number
;
14727 /* Parse the next byte. */
14728 if (skip_past_comma (&input_line_pointer
) == FAIL
)
14734 /* Add the opcode bytes in reverse order. */
14736 add_unwind_opcode (op
[count
], 1);
14738 demand_empty_rest_of_line ();
14741 #endif /* OBJ_ELF */
14743 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
14744 of an rs_align_code fragment. */
14747 arm_handle_align (fragS
* fragP
)
14749 static char const arm_noop
[4] = { 0x00, 0x00, 0xa0, 0xe1 };
14750 static char const thumb_noop
[2] = { 0xc0, 0x46 };
14751 static char const arm_bigend_noop
[4] = { 0xe1, 0xa0, 0x00, 0x00 };
14752 static char const thumb_bigend_noop
[2] = { 0x46, 0xc0 };
14754 int bytes
, fix
, noop_size
;
14758 if (fragP
->fr_type
!= rs_align_code
)
14761 bytes
= fragP
->fr_next
->fr_address
- fragP
->fr_address
- fragP
->fr_fix
;
14762 p
= fragP
->fr_literal
+ fragP
->fr_fix
;
14765 if (bytes
> MAX_MEM_FOR_RS_ALIGN_CODE
)
14766 bytes
&= MAX_MEM_FOR_RS_ALIGN_CODE
;
14768 if (fragP
->tc_frag_data
)
14770 if (target_big_endian
)
14771 noop
= thumb_bigend_noop
;
14774 noop_size
= sizeof (thumb_noop
);
14778 if (target_big_endian
)
14779 noop
= arm_bigend_noop
;
14782 noop_size
= sizeof (arm_noop
);
14785 if (bytes
& (noop_size
- 1))
14787 fix
= bytes
& (noop_size
- 1);
14788 memset (p
, 0, fix
);
14793 while (bytes
>= noop_size
)
14795 memcpy (p
, noop
, noop_size
);
14797 bytes
-= noop_size
;
14801 fragP
->fr_fix
+= fix
;
14802 fragP
->fr_var
= noop_size
;
14805 /* Called from md_do_align. Used to create an alignment
14806 frag in a code section. */
14809 arm_frag_align_code (int n
, int max
)
14813 /* We assume that there will never be a requirement
14814 to support alignments greater than 32 bytes. */
14815 if (max
> MAX_MEM_FOR_RS_ALIGN_CODE
)
14816 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
14818 p
= frag_var (rs_align_code
,
14819 MAX_MEM_FOR_RS_ALIGN_CODE
,
14821 (relax_substateT
) max
,
14828 /* Perform target specific initialisation of a frag. */
14831 arm_init_frag (fragS
* fragP
)
14833 /* Record whether this frag is in an ARM or a THUMB area. */
14834 fragP
->tc_frag_data
= thumb_mode
;
14839 /* Convert REGNAME to a DWARF-2 register number. */
14842 tc_arm_regname_to_dw2regnum (const char *regname
)
14846 for (i
= 0; rn_table
[i
].name
; i
++)
14847 if (streq (regname
, rn_table
[i
].name
))
14848 return rn_table
[i
].number
;
14853 /* Initialize the DWARF-2 unwind information for this procedure. */
14856 tc_arm_frame_initial_instructions (void)
14858 cfi_add_CFA_def_cfa (REG_SP
, 0);
14862 /* This table describes all the machine specific pseudo-ops the assembler
14863 has to support. The fields are:
14864 pseudo-op name without dot
14865 function to call to execute this pseudo-op
14866 Integer arg to pass to the function. */
14868 const pseudo_typeS md_pseudo_table
[] =
14870 /* Never called because '.req' does not start a line. */
14871 { "req", s_req
, 0 },
14872 { "unreq", s_unreq
, 0 },
14873 { "bss", s_bss
, 0 },
14874 { "align", s_align
, 0 },
14875 { "arm", s_arm
, 0 },
14876 { "thumb", s_thumb
, 0 },
14877 { "code", s_code
, 0 },
14878 { "force_thumb", s_force_thumb
, 0 },
14879 { "thumb_func", s_thumb_func
, 0 },
14880 { "thumb_set", s_thumb_set
, 0 },
14881 { "even", s_even
, 0 },
14882 { "ltorg", s_ltorg
, 0 },
14883 { "pool", s_ltorg
, 0 },
14885 { "word", s_arm_elf_cons
, 4 },
14886 { "long", s_arm_elf_cons
, 4 },
14887 { "rel31", s_arm_rel31
, 0 },
14888 { "fnstart", s_arm_unwind_fnstart
, 0 },
14889 { "fnend", s_arm_unwind_fnend
, 0 },
14890 { "cantunwind", s_arm_unwind_cantunwind
, 0 },
14891 { "personality", s_arm_unwind_personality
, 0 },
14892 { "personalityindex", s_arm_unwind_personalityindex
, 0 },
14893 { "handlerdata", s_arm_unwind_handlerdata
, 0 },
14894 { "save", s_arm_unwind_save
, 0 },
14895 { "movsp", s_arm_unwind_movsp
, 0 },
14896 { "pad", s_arm_unwind_pad
, 0 },
14897 { "setfp", s_arm_unwind_setfp
, 0 },
14898 { "unwind_raw", s_arm_unwind_raw
, 0 },
14900 { "word", cons
, 4},
14902 { "extend", float_cons
, 'x' },
14903 { "ldouble", float_cons
, 'x' },
14904 { "packed", float_cons
, 'p' },